2018-02-27 18:06:05 +01:00
|
|
|
/*
|
|
|
|
* Strawberry Music Player
|
|
|
|
* This file was part of Clementine.
|
|
|
|
* Copyright 2010, David Sansome <me@davidsansome.com>
|
2021-03-20 21:14:47 +01:00
|
|
|
* Copyright 2019-2021, Jonas Kvinge <jonas@jkvinge.net>
|
2018-02-27 18:06:05 +01:00
|
|
|
*
|
|
|
|
* Strawberry is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* Strawberry is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
2018-08-09 18:39:44 +02:00
|
|
|
*
|
2018-02-27 18:06:05 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2021-06-20 19:04:08 +02:00
|
|
|
#include <chrono>
|
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QtGlobal>
|
2018-02-27 18:06:05 +01:00
|
|
|
#include <QApplication>
|
2019-07-09 19:49:15 +02:00
|
|
|
#include <QGuiApplication>
|
|
|
|
#include <QWindow>
|
|
|
|
#include <QScreen>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QWidget>
|
2020-02-09 02:29:35 +01:00
|
|
|
#include <QList>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QVariant>
|
|
|
|
#include <QString>
|
|
|
|
#include <QImage>
|
|
|
|
#include <QPixmap>
|
2018-02-27 18:06:05 +01:00
|
|
|
#include <QBitmap>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QLabel>
|
2018-02-27 18:06:05 +01:00
|
|
|
#include <QPainter>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QPainterPath>
|
|
|
|
#include <QPalette>
|
|
|
|
#include <QColor>
|
|
|
|
#include <QBrush>
|
|
|
|
#include <QCursor>
|
|
|
|
#include <QPen>
|
|
|
|
#include <QRect>
|
|
|
|
#include <QPoint>
|
|
|
|
#include <QFont>
|
2018-02-27 18:06:05 +01:00
|
|
|
#include <QTimer>
|
|
|
|
#include <QTimeLine>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QTransform>
|
|
|
|
#include <QLayout>
|
|
|
|
#include <QBoxLayout>
|
|
|
|
#include <QLinearGradient>
|
|
|
|
#include <QSettings>
|
|
|
|
#include <QFlags>
|
|
|
|
#include <QtEvents>
|
2021-08-14 16:40:37 +02:00
|
|
|
|
|
|
|
#ifdef HAVE_X11EXTRAS
|
|
|
|
# include <QX11Info>
|
|
|
|
#elif defined(HAVE_X11) && defined(HAVE_QPA_QPLATFORMNATIVEINTERFACE_H)
|
2020-11-29 07:41:30 +01:00
|
|
|
# include <qpa/qplatformnativeinterface.h>
|
2018-02-27 18:06:05 +01:00
|
|
|
#endif
|
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
#include "osdpretty.h"
|
|
|
|
#include "ui_osdpretty.h"
|
|
|
|
|
2018-09-15 13:07:51 +02:00
|
|
|
#ifdef Q_OS_WIN
|
2021-07-11 09:49:38 +02:00
|
|
|
# include <windows.h>
|
2018-02-27 18:06:05 +01:00
|
|
|
#endif
|
|
|
|
|
2021-05-12 20:08:06 +02:00
|
|
|
#include "core/utilities.h"
|
|
|
|
|
2021-06-20 19:04:08 +02:00
|
|
|
using namespace std::chrono_literals;
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
const char *OSDPretty::kSettingsGroup = "OSDPretty";
|
|
|
|
|
|
|
|
const int OSDPretty::kDropShadowSize = 13;
|
|
|
|
const int OSDPretty::kBorderRadius = 10;
|
|
|
|
const int OSDPretty::kMaxIconSize = 100;
|
|
|
|
|
|
|
|
const int OSDPretty::kSnapProximity = 20;
|
|
|
|
|
|
|
|
const QRgb OSDPretty::kPresetBlue = qRgb(102, 150, 227);
|
2018-09-20 17:44:31 +02:00
|
|
|
const QRgb OSDPretty::kPresetRed = qRgb(202, 22, 16);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
|
|
|
|
OSDPretty::OSDPretty(Mode mode, QWidget *parent)
|
|
|
|
: QWidget(parent),
|
|
|
|
ui_(new Ui_OSDPretty),
|
|
|
|
mode_(mode),
|
|
|
|
background_color_(kPresetBlue),
|
|
|
|
background_opacity_(0.85),
|
2019-07-09 19:49:15 +02:00
|
|
|
popup_screen_(nullptr),
|
2018-02-27 18:06:05 +01:00
|
|
|
disable_duration_(false),
|
|
|
|
timeout_(new QTimer(this)),
|
|
|
|
fading_enabled_(false),
|
|
|
|
fader_(new QTimeLine(300, this)),
|
2019-02-10 21:25:36 +01:00
|
|
|
toggle_mode_(false) {
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
Qt::WindowFlags flags = Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint;
|
|
|
|
|
|
|
|
setWindowFlags(flags);
|
|
|
|
setAttribute(Qt::WA_TranslucentBackground, true);
|
|
|
|
setAttribute(Qt::WA_X11NetWmWindowTypeNotification, true);
|
|
|
|
setAttribute(Qt::WA_ShowWithoutActivating, true);
|
|
|
|
ui_->setupUi(this);
|
|
|
|
|
2019-09-30 20:32:34 +02:00
|
|
|
#ifdef Q_OS_WIN
|
2019-07-09 19:49:15 +02:00
|
|
|
// Don't show the window in the taskbar. Qt::ToolTip does this too, but it adds an extra ugly shadow.
|
2018-05-04 20:28:44 +02:00
|
|
|
int ex_style = GetWindowLong((HWND) winId(), GWL_EXSTYLE);
|
2018-02-27 18:06:05 +01:00
|
|
|
ex_style |= WS_EX_NOACTIVATE;
|
2018-05-04 20:28:44 +02:00
|
|
|
SetWindowLong((HWND) winId(), GWL_EXSTYLE, ex_style);
|
2018-02-27 18:06:05 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Mode settings
|
|
|
|
switch (mode_) {
|
|
|
|
case Mode_Popup:
|
|
|
|
setCursor(QCursor(Qt::ArrowCursor));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Mode_Draggable:
|
|
|
|
setCursor(QCursor(Qt::OpenHandCursor));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Timeout
|
|
|
|
timeout_->setSingleShot(true);
|
2021-06-20 19:04:08 +02:00
|
|
|
timeout_->setInterval(5s);
|
2021-01-26 16:48:04 +01:00
|
|
|
QObject::connect(timeout_, &QTimer::timeout, this, &OSDPretty::hide);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
ui_->icon->setMaximumSize(kMaxIconSize, kMaxIconSize);
|
|
|
|
|
|
|
|
// Fader
|
2021-01-26 16:48:04 +01:00
|
|
|
QObject::connect(fader_, &QTimeLine::valueChanged, this, &OSDPretty::FaderValueChanged);
|
|
|
|
QObject::connect(fader_, &QTimeLine::finished, this, &OSDPretty::FaderFinished);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
// Load the show edges and corners
|
2018-08-29 22:17:23 +02:00
|
|
|
QImage shadow_edge(":/pictures/osd_shadow_edge.png");
|
|
|
|
QImage shadow_corner(":/pictures/osd_shadow_corner.png");
|
2018-02-27 18:06:05 +01:00
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
QTransform rotation = QTransform().rotate(90 * i);
|
|
|
|
shadow_edge_[i] = QPixmap::fromImage(shadow_edge.transformed(rotation));
|
|
|
|
shadow_corner_[i] = QPixmap::fromImage(shadow_corner.transformed(rotation));
|
|
|
|
}
|
2018-08-29 22:17:23 +02:00
|
|
|
background_ = QPixmap(":/pictures/osd_background.png");
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
// Set the margins to allow for the drop shadow
|
2020-07-17 01:32:07 +02:00
|
|
|
QBoxLayout *l = qobject_cast<QBoxLayout*>(layout());
|
2020-07-19 04:09:34 +02:00
|
|
|
QMargins margin = l->contentsMargins();
|
2020-07-18 04:15:19 +02:00
|
|
|
margin.setTop(margin.top() + kDropShadowSize);
|
|
|
|
margin.setBottom(margin.bottom() + kDropShadowSize);
|
|
|
|
margin.setLeft(margin.left() + kDropShadowSize);
|
|
|
|
margin.setRight(margin.right() + kDropShadowSize);
|
|
|
|
l->setContentsMargins(margin);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2021-01-26 16:48:04 +01:00
|
|
|
QObject::connect(qApp, &QApplication::screenAdded, this, &OSDPretty::ScreenAdded);
|
|
|
|
QObject::connect(qApp, &QApplication::screenRemoved, this, &OSDPretty::ScreenRemoved);
|
2019-07-09 19:49:15 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
OSDPretty::~OSDPretty() {
|
|
|
|
delete ui_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OSDPretty::showEvent(QShowEvent *e) {
|
|
|
|
|
|
|
|
screens_.clear();
|
2021-09-10 01:46:13 +02:00
|
|
|
for(QScreen *screen : QGuiApplication::screens()) {
|
2019-07-09 19:49:15 +02:00
|
|
|
screens_.insert(screen->name(), screen);
|
|
|
|
}
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
// Get current screen resolution
|
2020-04-06 22:01:44 +02:00
|
|
|
QScreen *screen = current_screen();
|
|
|
|
if (screen) {
|
|
|
|
QRect resolution = screen->availableGeometry();
|
|
|
|
// Leave 200 px for icon
|
|
|
|
ui_->summary->setMaximumWidth(resolution.width() - 200);
|
|
|
|
ui_->message->setMaximumWidth(resolution.width() - 200);
|
|
|
|
// Set maximum size for the OSD, a little margin here too
|
|
|
|
setMaximumSize(resolution.width() - 100, resolution.height() - 100);
|
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2019-07-09 19:49:15 +02:00
|
|
|
setWindowOpacity(fading_enabled_ ? 0.0 : 1.0);
|
|
|
|
|
|
|
|
QWidget::showEvent(e);
|
|
|
|
|
|
|
|
Load();
|
|
|
|
Reposition();
|
|
|
|
|
|
|
|
if (fading_enabled_) {
|
|
|
|
fader_->setDirection(QTimeLine::Forward);
|
|
|
|
fader_->start(); // Timeout will be started in FaderFinished
|
|
|
|
}
|
|
|
|
else if (mode_ == Mode_Popup) {
|
2021-08-23 21:21:08 +02:00
|
|
|
if (!disable_duration()) {
|
2019-07-09 19:49:15 +02:00
|
|
|
timeout_->start();
|
2021-08-23 21:21:08 +02:00
|
|
|
}
|
2019-07-09 19:49:15 +02:00
|
|
|
// Ensures it is above when showing the preview
|
|
|
|
raise();
|
|
|
|
}
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2019-07-09 19:49:15 +02:00
|
|
|
void OSDPretty::ScreenAdded(QScreen *screen) {
|
|
|
|
|
|
|
|
screens_.insert(screen->name(), screen);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void OSDPretty::ScreenRemoved(QScreen *screen) {
|
|
|
|
|
|
|
|
if (screens_.contains(screen->name())) screens_.remove(screen->name());
|
|
|
|
if (screen == popup_screen_) popup_screen_ = current_screen();
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OSDPretty::IsTransparencyAvailable() {
|
2020-11-29 07:41:30 +01:00
|
|
|
|
2021-08-14 16:40:37 +02:00
|
|
|
#ifdef HAVE_X11EXTRAS
|
|
|
|
return QX11Info::isCompositingManagerRunning();
|
|
|
|
#elif defined(HAVE_X11) && defined(HAVE_QPA_QPLATFORMNATIVEINTERFACE_H)
|
2020-11-29 07:41:30 +01:00
|
|
|
if (qApp) {
|
2021-09-10 01:46:13 +02:00
|
|
|
QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
|
2021-07-11 09:49:38 +02:00
|
|
|
QScreen *screen = popup_screen_ == nullptr ? QGuiApplication::primaryScreen() : popup_screen_;
|
2021-05-12 20:08:06 +02:00
|
|
|
if (native && screen) {
|
|
|
|
return native->nativeResourceForScreen(QByteArray("compositingEnabled"), screen);
|
2020-11-29 07:41:30 +01:00
|
|
|
}
|
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
#endif
|
2020-11-29 07:41:30 +01:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
return true;
|
2020-11-29 07:41:30 +01:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void OSDPretty::Load() {
|
|
|
|
|
|
|
|
QSettings s;
|
|
|
|
s.beginGroup(kSettingsGroup);
|
|
|
|
foreground_color_ = QColor(s.value("foreground_color", 0).toInt());
|
|
|
|
background_color_ = QColor(s.value("background_color", kPresetBlue).toInt());
|
2021-03-21 18:53:02 +01:00
|
|
|
background_opacity_ = s.value("background_opacity", 0.85).toFloat();
|
2018-02-27 18:06:05 +01:00
|
|
|
font_.fromString(s.value("font", "Verdana,9,-1,5,50,0,0,0,0,0").toString());
|
|
|
|
disable_duration_ = s.value("disable_duration", false).toBool();
|
2021-04-13 17:26:54 +02:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
fading_enabled_ = s.value("fading", true).toBool();
|
|
|
|
#else
|
|
|
|
fading_enabled_ = s.value("fading", false).toBool();
|
|
|
|
#endif
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2019-09-30 20:32:34 +02:00
|
|
|
if (s.contains("popup_screen")) {
|
|
|
|
popup_screen_name_ = s.value("popup_screen").toString();
|
|
|
|
if (screens_.contains(popup_screen_name_)) {
|
|
|
|
popup_screen_ = screens_[popup_screen_name_];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
popup_screen_ = current_screen();
|
|
|
|
if (current_screen()) popup_screen_name_ = current_screen()->name();
|
|
|
|
else popup_screen_name_.clear();
|
|
|
|
}
|
|
|
|
}
|
2019-07-09 20:28:43 +02:00
|
|
|
else {
|
|
|
|
popup_screen_ = current_screen();
|
|
|
|
if (current_screen()) popup_screen_name_ = current_screen()->name();
|
|
|
|
}
|
2019-09-30 20:32:34 +02:00
|
|
|
|
|
|
|
if (s.contains("popup_pos")) {
|
|
|
|
popup_pos_ = s.value("popup_pos").toPoint();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (popup_screen_) {
|
|
|
|
QRect geometry = popup_screen_->availableGeometry();
|
|
|
|
popup_pos_.setX(geometry.width() - width());
|
|
|
|
popup_pos_.setY(0);
|
2019-07-09 20:28:43 +02:00
|
|
|
}
|
|
|
|
else {
|
2019-09-30 20:32:34 +02:00
|
|
|
popup_pos_.setX(0);
|
|
|
|
popup_pos_.setY(0);
|
2019-07-09 20:28:43 +02:00
|
|
|
}
|
|
|
|
}
|
2019-07-09 19:49:15 +02:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
set_font(font());
|
|
|
|
set_foreground_color(foreground_color());
|
|
|
|
|
2019-09-30 20:32:34 +02:00
|
|
|
s.endGroup();
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void OSDPretty::ReloadSettings() {
|
|
|
|
Load();
|
|
|
|
if (isVisible()) update();
|
|
|
|
}
|
|
|
|
|
|
|
|
QRect OSDPretty::BoxBorder() const {
|
|
|
|
return rect().adjusted(kDropShadowSize, kDropShadowSize, -kDropShadowSize, -kDropShadowSize);
|
|
|
|
}
|
|
|
|
|
2021-06-13 20:55:37 +02:00
|
|
|
void OSDPretty::paintEvent(QPaintEvent*) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
QPainter p(this);
|
|
|
|
p.setRenderHint(QPainter::Antialiasing);
|
|
|
|
|
|
|
|
QRect box(BoxBorder());
|
|
|
|
|
|
|
|
// Shadow corners
|
|
|
|
const int kShadowCornerSize = kDropShadowSize + kBorderRadius;
|
|
|
|
p.drawPixmap(0, 0, shadow_corner_[0]);
|
|
|
|
p.drawPixmap(width() - kShadowCornerSize, 0, shadow_corner_[1]);
|
|
|
|
p.drawPixmap(width() - kShadowCornerSize, height() - kShadowCornerSize, shadow_corner_[2]);
|
|
|
|
p.drawPixmap(0, height() - kShadowCornerSize, shadow_corner_[3]);
|
|
|
|
|
|
|
|
// Shadow edges
|
|
|
|
p.drawTiledPixmap(kShadowCornerSize, 0, width() - kShadowCornerSize*2, kDropShadowSize, shadow_edge_[0]);
|
|
|
|
p.drawTiledPixmap(width() - kDropShadowSize, kShadowCornerSize, kDropShadowSize, height() - kShadowCornerSize*2, shadow_edge_[1]);
|
|
|
|
p.drawTiledPixmap(kShadowCornerSize, height() - kDropShadowSize, width() - kShadowCornerSize*2, kDropShadowSize, shadow_edge_[2]);
|
|
|
|
p.drawTiledPixmap(0, kShadowCornerSize, kDropShadowSize, height() - kShadowCornerSize*2, shadow_edge_[3]);
|
|
|
|
|
|
|
|
// Box background
|
|
|
|
p.setBrush(background_color_);
|
|
|
|
p.setPen(QPen());
|
|
|
|
p.setOpacity(background_opacity_);
|
|
|
|
p.drawRoundedRect(box, kBorderRadius, kBorderRadius);
|
|
|
|
|
|
|
|
// Background pattern
|
|
|
|
QPainterPath background_path;
|
|
|
|
background_path.addRoundedRect(box, kBorderRadius, kBorderRadius);
|
|
|
|
p.setClipPath(background_path);
|
|
|
|
p.setOpacity(1.0);
|
|
|
|
p.drawPixmap(box.right() - background_.width(), box.bottom() - background_.height(), background_);
|
|
|
|
p.setClipping(false);
|
|
|
|
|
|
|
|
// Gradient overlay
|
|
|
|
QLinearGradient gradient(0, 0, 0, height());
|
|
|
|
gradient.setColorAt(0, QColor(255, 255, 255, 130));
|
|
|
|
gradient.setColorAt(1, QColor(255, 255, 255, 50));
|
|
|
|
p.setBrush(gradient);
|
|
|
|
p.drawRoundedRect(box, kBorderRadius, kBorderRadius);
|
|
|
|
|
|
|
|
// Box border
|
|
|
|
p.setBrush(QBrush());
|
2021-06-13 20:56:14 +02:00
|
|
|
p.setPen(QPen(background_color_.darker(150), 3));
|
2018-02-27 18:06:05 +01:00
|
|
|
p.drawRoundedRect(box, kBorderRadius, kBorderRadius);
|
2019-07-09 19:49:15 +02:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2021-06-12 20:53:23 +02:00
|
|
|
void OSDPretty::SetMessage(const QString &summary, const QString &message, const QImage &image) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
if (!image.isNull()) {
|
|
|
|
QImage scaled_image = image.scaled(kMaxIconSize, kMaxIconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
|
|
|
ui_->icon->setPixmap(QPixmap::fromImage(scaled_image));
|
|
|
|
ui_->icon->show();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ui_->icon->hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
ui_->summary->setText(summary);
|
|
|
|
ui_->message->setText(message);
|
|
|
|
|
|
|
|
if (isVisible()) Reposition();
|
2019-07-09 19:49:15 +02:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set the desired message and then show the OSD
|
|
|
|
void OSDPretty::ShowMessage(const QString &summary, const QString &message, const QImage &image) {
|
|
|
|
|
|
|
|
SetMessage(summary, message, image);
|
|
|
|
|
|
|
|
if (isVisible() && mode_ == Mode_Popup) {
|
|
|
|
// The OSD is already visible, toggle or restart the timer
|
|
|
|
if (toggle_mode()) {
|
|
|
|
set_toggle_mode(false);
|
|
|
|
// If timeout is disabled, timer hadn't been started
|
2021-08-23 21:21:08 +02:00
|
|
|
if (!disable_duration()) {
|
2018-02-27 18:06:05 +01:00
|
|
|
timeout_->stop();
|
2021-08-23 21:21:08 +02:00
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
hide();
|
|
|
|
}
|
|
|
|
else {
|
2021-08-23 21:21:08 +02:00
|
|
|
if (!disable_duration()) {
|
2021-07-11 09:49:38 +02:00
|
|
|
timeout_->start(); // Restart the timer
|
2021-08-23 21:21:08 +02:00
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2021-08-23 21:21:08 +02:00
|
|
|
if (toggle_mode()) {
|
2018-02-27 18:06:05 +01:00
|
|
|
set_toggle_mode(false);
|
2021-08-23 21:21:08 +02:00
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
// The OSD is not visible, show it
|
|
|
|
show();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void OSDPretty::setVisible(bool visible) {
|
|
|
|
|
|
|
|
if (!visible && fading_enabled_ && fader_->direction() == QTimeLine::Forward) {
|
|
|
|
fader_->setDirection(QTimeLine::Backward);
|
|
|
|
fader_->start();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
QWidget::setVisible(visible);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void OSDPretty::FaderFinished() {
|
|
|
|
|
2021-08-23 21:21:08 +02:00
|
|
|
if (fader_->direction() == QTimeLine::Backward) {
|
2018-02-27 18:06:05 +01:00
|
|
|
hide();
|
2021-08-23 21:21:08 +02:00
|
|
|
}
|
|
|
|
else if (mode_ == Mode_Popup && !disable_duration()) {
|
2018-02-27 18:06:05 +01:00
|
|
|
timeout_->start();
|
2021-08-23 21:21:08 +02:00
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-01-26 16:48:04 +01:00
|
|
|
void OSDPretty::FaderValueChanged(const qreal value) {
|
2018-02-27 18:06:05 +01:00
|
|
|
setWindowOpacity(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OSDPretty::Reposition() {
|
|
|
|
|
|
|
|
// Make the OSD the proper size
|
|
|
|
layout()->activate();
|
|
|
|
resize(sizeHint());
|
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
// Work out where to place the OSD. -1 for x or y means "on the right or bottom edge".
|
2019-07-09 19:49:15 +02:00
|
|
|
if (popup_screen_) {
|
2019-09-30 20:32:34 +02:00
|
|
|
|
2019-07-09 19:49:15 +02:00
|
|
|
QRect geometry = popup_screen_->availableGeometry();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2019-07-09 19:49:15 +02:00
|
|
|
int x = popup_pos_.x() < 0 ? geometry.right() - width() : geometry.left() + popup_pos_.x();
|
|
|
|
int y = popup_pos_.y() < 0 ? geometry.bottom() - height() : geometry.top() + popup_pos_.y();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2019-09-30 20:32:34 +02:00
|
|
|
#ifndef Q_OS_WIN
|
|
|
|
x = qBound(0, x, geometry.right() - width());
|
|
|
|
y = qBound(0, y, geometry.bottom() - height());
|
|
|
|
#endif
|
|
|
|
move(x, y);
|
2019-07-09 19:49:15 +02:00
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
// Create a mask for the actual area of the OSD
|
|
|
|
QBitmap mask(size());
|
|
|
|
mask.clear();
|
|
|
|
|
|
|
|
QPainter p(&mask);
|
|
|
|
p.setBrush(Qt::color1);
|
|
|
|
p.drawRoundedRect(BoxBorder().adjusted(-1, -1, 0, 0), kBorderRadius, kBorderRadius);
|
|
|
|
p.end();
|
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
// If there's no compositing window manager running then we have to set an XShape mask.
|
2018-02-27 18:06:05 +01:00
|
|
|
if (IsTransparencyAvailable())
|
|
|
|
clearMask();
|
|
|
|
else {
|
|
|
|
setMask(mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
// On windows, enable blurbehind on the masked area
|
2021-05-12 20:08:06 +02:00
|
|
|
#ifdef Q_OS_WIN
|
2021-09-13 20:49:33 +02:00
|
|
|
Utilities::enableBlurBehindWindow(windowHandle(), QRegion(mask));
|
2018-02-27 18:06:05 +01:00
|
|
|
#endif
|
2020-11-29 07:41:30 +01:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2020-09-05 19:20:43 +02:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
|
|
void OSDPretty::enterEvent(QEnterEvent*) {
|
|
|
|
#else
|
|
|
|
void OSDPretty::enterEvent(QEvent*) {
|
|
|
|
#endif
|
2021-08-23 21:21:08 +02:00
|
|
|
if (mode_ == Mode_Popup) {
|
2018-02-27 18:06:05 +01:00
|
|
|
setWindowOpacity(0.25);
|
2021-08-23 21:21:08 +02:00
|
|
|
}
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2020-09-05 19:20:43 +02:00
|
|
|
void OSDPretty::leaveEvent(QEvent*) {
|
2018-02-27 18:06:05 +01:00
|
|
|
setWindowOpacity(1.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OSDPretty::mousePressEvent(QMouseEvent *e) {
|
|
|
|
|
2021-08-23 21:21:08 +02:00
|
|
|
if (mode_ == Mode_Popup) {
|
2018-02-27 18:06:05 +01:00
|
|
|
hide();
|
2021-08-23 21:21:08 +02:00
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
else {
|
|
|
|
original_window_pos_ = pos();
|
2020-07-18 04:15:19 +02:00
|
|
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
|
|
|
drag_start_pos_ = e->globalPosition().toPoint();
|
|
|
|
#else
|
2018-02-27 18:06:05 +01:00
|
|
|
drag_start_pos_ = e->globalPos();
|
2020-07-18 04:15:19 +02:00
|
|
|
#endif
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void OSDPretty::mouseMoveEvent(QMouseEvent *e) {
|
|
|
|
|
|
|
|
if (mode_ == Mode_Draggable) {
|
2020-07-18 04:15:19 +02:00
|
|
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
|
|
|
QPoint delta = e->globalPosition().toPoint() - drag_start_pos_;
|
|
|
|
#else
|
2018-02-27 18:06:05 +01:00
|
|
|
QPoint delta = e->globalPos() - drag_start_pos_;
|
2020-07-18 04:15:19 +02:00
|
|
|
#endif
|
2018-02-27 18:06:05 +01:00
|
|
|
QPoint new_pos = original_window_pos_ + delta;
|
|
|
|
|
|
|
|
// Keep it to the bounds of the desktop
|
2020-07-18 04:15:19 +02:00
|
|
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
|
|
|
QScreen *screen = current_screen(e->globalPosition().toPoint());
|
|
|
|
#else
|
2020-04-06 23:01:50 +02:00
|
|
|
QScreen *screen = current_screen(e->globalPos());
|
2020-07-18 04:15:19 +02:00
|
|
|
#endif
|
2019-07-09 19:49:15 +02:00
|
|
|
if (!screen) return;
|
|
|
|
|
|
|
|
QRect geometry = screen->availableGeometry();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
new_pos.setX(qBound(geometry.left(), new_pos.x(), geometry.right() - width()));
|
|
|
|
new_pos.setY(qBound(geometry.top(), new_pos.y(), geometry.bottom() - height()));
|
|
|
|
|
|
|
|
// Snap to center
|
|
|
|
int snap_x = geometry.center().x() - width() / 2;
|
|
|
|
if (new_pos.x() > snap_x - kSnapProximity && new_pos.x() < snap_x + kSnapProximity) {
|
|
|
|
new_pos.setX(snap_x);
|
|
|
|
}
|
|
|
|
|
|
|
|
move(new_pos);
|
|
|
|
|
2019-07-09 19:49:15 +02:00
|
|
|
popup_screen_ = screen;
|
|
|
|
popup_screen_name_ = screen->name();
|
2019-09-30 20:32:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void OSDPretty::mouseReleaseEvent(QMouseEvent *) {
|
|
|
|
|
2020-04-06 22:01:44 +02:00
|
|
|
if (current_screen() && mode_ == Mode_Draggable) {
|
2019-09-30 20:32:34 +02:00
|
|
|
popup_screen_ = current_screen();
|
|
|
|
popup_screen_name_ = current_screen()->name();
|
2018-02-27 18:06:05 +01:00
|
|
|
popup_pos_ = current_pos();
|
2020-06-05 23:46:07 +02:00
|
|
|
emit PositionChanged();
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-06-22 14:17:24 +02:00
|
|
|
QScreen *OSDPretty::current_screen(const QPoint pos) const {
|
2020-04-06 22:01:44 +02:00
|
|
|
|
|
|
|
QScreen *screen(nullptr);
|
2019-07-09 19:49:15 +02:00
|
|
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
2020-04-06 22:01:44 +02:00
|
|
|
screen = QGuiApplication::screenAt(pos);
|
2019-07-09 19:49:15 +02:00
|
|
|
#else
|
2020-07-06 20:32:17 +02:00
|
|
|
Q_UNUSED(pos)
|
2020-04-06 22:01:44 +02:00
|
|
|
if (window() && window()->windowHandle()) screen = window()->windowHandle()->screen();
|
2019-07-09 19:49:15 +02:00
|
|
|
#endif
|
2020-04-06 22:01:44 +02:00
|
|
|
if (!screen) screen = QGuiApplication::primaryScreen();
|
|
|
|
|
|
|
|
return screen;
|
|
|
|
|
2019-07-09 19:49:15 +02:00
|
|
|
}
|
|
|
|
|
2020-04-06 22:01:44 +02:00
|
|
|
QScreen *OSDPretty::current_screen() const { return current_screen(pos()); }
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
QPoint OSDPretty::current_pos() const {
|
|
|
|
|
2019-07-09 19:49:15 +02:00
|
|
|
if (current_screen()) {
|
|
|
|
QRect geometry = current_screen()->availableGeometry();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2019-07-09 19:49:15 +02:00
|
|
|
int x = pos().x() >= geometry.right() - width() ? -1 : pos().x() - geometry.left();
|
|
|
|
int y = pos().y() >= geometry.bottom() - height() ? -1 : pos().y() - geometry.top();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2019-07-09 19:49:15 +02:00
|
|
|
return QPoint(x, y);
|
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2019-07-09 19:49:15 +02:00
|
|
|
return QPoint(0, 0);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-06-12 20:53:23 +02:00
|
|
|
void OSDPretty::set_background_color(const QRgb color) {
|
2018-02-27 18:06:05 +01:00
|
|
|
background_color_ = color;
|
|
|
|
if (isVisible()) update();
|
|
|
|
}
|
|
|
|
|
2021-06-12 20:53:23 +02:00
|
|
|
void OSDPretty::set_background_opacity(const qreal opacity) {
|
2018-02-27 18:06:05 +01:00
|
|
|
background_opacity_ = opacity;
|
|
|
|
if (isVisible()) update();
|
|
|
|
}
|
|
|
|
|
2021-06-12 20:53:23 +02:00
|
|
|
void OSDPretty::set_foreground_color(const QRgb color) {
|
2019-07-09 19:49:15 +02:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
foreground_color_ = QColor(color);
|
|
|
|
|
|
|
|
QPalette p;
|
|
|
|
p.setColor(QPalette::WindowText, foreground_color_);
|
|
|
|
|
|
|
|
ui_->summary->setPalette(p);
|
|
|
|
ui_->message->setPalette(p);
|
2019-07-09 19:49:15 +02:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2021-06-12 20:53:23 +02:00
|
|
|
void OSDPretty::set_popup_duration(const int msec) {
|
2018-02-27 18:06:05 +01:00
|
|
|
timeout_->setInterval(msec);
|
|
|
|
}
|
|
|
|
|
2021-06-20 19:04:08 +02:00
|
|
|
void OSDPretty::set_font(const QFont &font) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
font_ = font;
|
|
|
|
|
|
|
|
// Update the UI
|
|
|
|
ui_->summary->setFont(font);
|
|
|
|
ui_->message->setFont(font);
|
|
|
|
// Now adjust OSD size so everything fits
|
|
|
|
ui_->verticalLayout->activate();
|
|
|
|
resize(sizeHint());
|
|
|
|
// Update the position after font change
|
|
|
|
Reposition();
|
|
|
|
|
|
|
|
}
|