diff --git a/examples/dialog/dialog.cpp b/examples/dialog/dialog.cpp index b08abaf7..f4b8258d 100644 --- a/examples/dialog/dialog.cpp +++ b/examples/dialog/dialog.cpp @@ -97,12 +97,11 @@ void Dialog::setupUi() connect(moreButton, &QPushButton::toggled, extension, &QWidget::setVisible); - QVBoxLayout *extensionLayout = new QVBoxLayout; + QVBoxLayout *extensionLayout = new QVBoxLayout(extension); extensionLayout->setContentsMargins(0, 0, 0, 0); extensionLayout->addWidget(wholeWordsCheckBox); extensionLayout->addWidget(backwardCheckBox); extensionLayout->addWidget(searchSelectionCheckBox); - extension->setLayout(extensionLayout); QHBoxLayout *topLeftLayout = new QHBoxLayout; topLeftLayout->addWidget(label); @@ -120,14 +119,12 @@ void Dialog::setupUi() controlsLayout->addWidget(extension, 1, 0, 1, 2); controlsLayout->setRowStretch(2, 1); - QVBoxLayout *mainLayout = new QVBoxLayout; + QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSizeConstraint(QLayout::SetFixedSize); mainLayout->addWidget(titleBar); mainLayout->addLayout(controlsLayout); - setLayout(mainLayout); - extension->hide(); FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this); diff --git a/examples/openglwidget/mainwindow.cpp b/examples/openglwidget/mainwindow.cpp index 87a13654..1679bdf3 100644 --- a/examples/openglwidget/mainwindow.cpp +++ b/examples/openglwidget/mainwindow.cpp @@ -73,7 +73,6 @@ void MainWindow::initialize() mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->addWidget(m_titleBar); mainLayout->addWidget(m_glWidget); - setLayout(mainLayout); FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this); helper->setTitleBarWidget(m_titleBar); diff --git a/examples/widget/widget.cpp b/examples/widget/widget.cpp index c44b5116..826d9ca8 100644 --- a/examples/widget/widget.cpp +++ b/examples/widget/widget.cpp @@ -102,7 +102,6 @@ void Widget::initialize() mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->addWidget(m_titleBar); mainLayout->addLayout(contentLayout); - setLayout(mainLayout); updateStyleSheet(); m_cancelShortcut = new QShortcut(this); diff --git a/include/FramelessHelper/Widgets/private/framelessdialog_p.h b/include/FramelessHelper/Widgets/private/framelessdialog_p.h index c36a06d0..66b0a964 100644 --- a/include/FramelessHelper/Widgets/private/framelessdialog_p.h +++ b/include/FramelessHelper/Widgets/private/framelessdialog_p.h @@ -44,14 +44,8 @@ class FRAMELESSHELPER_WIDGETS_API FramelessDialogPrivate : public QObject Q_NODISCARD static FramelessDialogPrivate *get(FramelessDialog *pub); Q_NODISCARD static const FramelessDialogPrivate *get(const FramelessDialog *pub); - Q_NODISCARD WidgetsSharedHelper *widgetsSharedHelper() const; - -private: - void initialize(); - -private: FramelessDialog *q_ptr = nullptr; - WidgetsSharedHelper *m_sharedHelper = nullptr; + WidgetsSharedHelper *sharedHelper = nullptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/private/framelessmainwindow_p.h b/include/FramelessHelper/Widgets/private/framelessmainwindow_p.h index fecf9e3b..f15ca176 100644 --- a/include/FramelessHelper/Widgets/private/framelessmainwindow_p.h +++ b/include/FramelessHelper/Widgets/private/framelessmainwindow_p.h @@ -44,21 +44,9 @@ class FRAMELESSHELPER_WIDGETS_API FramelessMainWindowPrivate : public QObject Q_NODISCARD static FramelessMainWindowPrivate *get(FramelessMainWindow *pub); Q_NODISCARD static const FramelessMainWindowPrivate *get(const FramelessMainWindow *pub); - Q_NODISCARD bool isNormal() const; - Q_NODISCARD bool isZoomed() const; - - void toggleMaximized(); - void toggleFullScreen(); - - Q_NODISCARD WidgetsSharedHelper *widgetsSharedHelper() const; - -private: - void initialize(); - -private: FramelessMainWindow *q_ptr = nullptr; - Qt::WindowState m_savedWindowState = Qt::WindowNoState; - WidgetsSharedHelper *m_sharedHelper = nullptr; + Qt::WindowState savedWindowState = Qt::WindowNoState; + WidgetsSharedHelper *sharedHelper = nullptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/private/framelesswidget_p.h b/include/FramelessHelper/Widgets/private/framelesswidget_p.h index 347172b4..4146011e 100644 --- a/include/FramelessHelper/Widgets/private/framelesswidget_p.h +++ b/include/FramelessHelper/Widgets/private/framelesswidget_p.h @@ -44,21 +44,9 @@ class FRAMELESSHELPER_WIDGETS_API FramelessWidgetPrivate : public QObject Q_NODISCARD static FramelessWidgetPrivate *get(FramelessWidget *pub); Q_NODISCARD static const FramelessWidgetPrivate *get(const FramelessWidget *pub); - Q_NODISCARD bool isNormal() const; - Q_NODISCARD bool isZoomed() const; - - void toggleMaximized(); - void toggleFullScreen(); - - Q_NODISCARD WidgetsSharedHelper *widgetsSharedHelper() const; - -private: - void initialize(); - -private: FramelessWidget *q_ptr = nullptr; - Qt::WindowState m_savedWindowState = Qt::WindowNoState; - WidgetsSharedHelper *m_sharedHelper = nullptr; + Qt::WindowState savedWindowState = Qt::WindowNoState; + WidgetsSharedHelper *sharedHelper = nullptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h b/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h index 74c3f410..2f81b497 100644 --- a/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h +++ b/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h @@ -49,53 +49,25 @@ class FRAMELESSHELPER_WIDGETS_API FramelessWidgetsHelperPrivate : public QObject Q_NODISCARD static FramelessWidgetsHelperPrivate *get(FramelessWidgetsHelper *pub); Q_NODISCARD static const FramelessWidgetsHelperPrivate *get(const FramelessWidgetsHelper *pub); - Q_NODISCARD bool isContentExtendedIntoTitleBar() const; - void extendsContentIntoTitleBar(const bool value); - - Q_NODISCARD QWidget *getTitleBarWidget() const; - void setTitleBarWidget(QWidget *widget); - void attach(); void detach(); - void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType); - void setHitTestVisible(QWidget *widget, const bool visible = true); - void setHitTestVisible(const QRect &rect, const bool visible = true); - void setHitTestVisible(QObject *object, const bool visible = true); - void showSystemMenu(const QPoint &pos); - void windowStartSystemMove2(const QPoint &pos); - void windowStartSystemResize2(const Qt::Edges edges, const QPoint &pos); - - void moveWindowToDesktopCenter(); - void bringWindowToFront(); - - Q_NODISCARD bool isWindowFixedSize() const; - void setWindowFixedSize(const bool value); void emitSignalForAllInstances(const char *signal); - Q_NODISCARD bool isBlurBehindWindowEnabled() const; - void setBlurBehindWindowEnabled(const bool enable, const QColor &color); - void setProperty(const char *name, const QVariant &value); Q_NODISCARD QVariant getProperty(const char *name, const QVariant &defaultValue = {}); - Q_NODISCARD QWidget *window() const; - Q_NODISCARD MicaMaterial *getMicaMaterialIfAny() const; Q_NODISCARD WindowBorderPainter *getWindowBorderIfAny() const; Q_NODISCARD static WidgetsSharedHelper *findOrCreateSharedHelper(QWidget *window); Q_NODISCARD static FramelessWidgetsHelper *findOrCreateFramelessHelper(QObject *object); - Q_NODISCARD bool isReady() const; - void waitForReady(); - void repaintAllChildren(const quint32 delay = 0) const; Q_NODISCARD quint32 readyWaitTime() const; void setReadyWaitTime(const quint32 time); -private: Q_NODISCARD QRect mapWidgetGeometryToScene(const QWidget * const widget) const; Q_NODISCARD bool isInSystemButtons(const QPoint &pos, Global::SystemButtonType *button) const; Q_NODISCARD bool isInTitleBarDraggableArea(const QPoint &pos) const; @@ -105,15 +77,13 @@ class FRAMELESSHELPER_WIDGETS_API FramelessWidgetsHelperPrivate : public QObject Q_NODISCARD const FramelessWidgetsHelperData *getWindowData() const; Q_NODISCARD FramelessWidgetsHelperData *getWindowDataMutable() const; -private: FramelessWidgetsHelper *q_ptr = nullptr; - QColor m_savedWindowBackgroundColor = {}; - bool m_blurBehindWindowEnabled = false; - QPointer m_window = nullptr; - bool m_destroying = false; - bool m_qpaReady = false; - QSizePolicy m_savedSizePolicy = {}; - quint32 m_qpaWaitTime = 0; + QColor savedWindowBackgroundColor = {}; + bool blurBehindWindowEnabled = false; + QPointer window = nullptr; + bool qpaReady = false; + QSizePolicy savedSizePolicy = {}; + quint32 qpaWaitTime = 0; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/private/standardsystembutton_p.h b/include/FramelessHelper/Widgets/private/standardsystembutton_p.h index f09996ad..91742d96 100644 --- a/include/FramelessHelper/Widgets/private/standardsystembutton_p.h +++ b/include/FramelessHelper/Widgets/private/standardsystembutton_p.h @@ -27,11 +27,6 @@ #include #include -QT_BEGIN_NAMESPACE -class QEnterEvent; -class QPaintEvent; -QT_END_NAMESPACE - FRAMELESSHELPER_BEGIN_NAMESPACE class StandardSystemButton; @@ -49,46 +44,18 @@ class FRAMELESSHELPER_WIDGETS_API StandardSystemButtonPrivate : public QObject Q_NODISCARD static StandardSystemButtonPrivate *get(StandardSystemButton *pub); Q_NODISCARD static const StandardSystemButtonPrivate *get(const StandardSystemButton *pub); - Q_NODISCARD QString getGlyph() const; - void setGlyph(const QString &value); - - Q_NODISCARD Global::SystemButtonType getButtonType() const; - void setButtonType(const Global::SystemButtonType type); - - Q_NODISCARD QSize getRecommendedButtonSize() const; - - Q_NODISCARD QColor getHoverColor() const; - Q_NODISCARD QColor getPressColor() const; - Q_NODISCARD QColor getNormalColor() const; - Q_NODISCARD QColor getActiveForegroundColor() const; - Q_NODISCARD QColor getInactiveForegroundColor() const; - Q_NODISCARD bool isActive() const; - Q_NODISCARD int glyphSize() const; - - void setHoverColor(const QColor &value); - void setPressColor(const QColor &value); - void setNormalColor(const QColor &value); - void setActiveForegroundColor(const QColor &value); - void setInactiveForegroundColor(const QColor &value); - void setActive(const bool value); - void setGlyphSize(const int value); - - void paintEventHandler(QPaintEvent *event); - -private: - void initialize(); + Q_NODISCARD static QSize getRecommendedButtonSize(); -private: StandardSystemButton *q_ptr = nullptr; - Global::SystemButtonType m_buttonType = Global::SystemButtonType::Unknown; - QString m_glyph = {}; - QColor m_hoverColor = {}; - QColor m_pressColor = {}; - QColor m_normalColor = {}; - QColor m_activeForegroundColor = {}; - QColor m_inactiveForegroundColor = {}; - bool m_active = false; - std::optional m_glyphSize = std::nullopt; + Global::SystemButtonType buttonType = Global::SystemButtonType::Unknown; + QString glyph = {}; + QColor hoverColor = {}; + QColor pressColor = {}; + QColor normalColor = {}; + QColor activeForegroundColor = {}; + QColor inactiveForegroundColor = {}; + bool active = false; + std::optional glyphSize = std::nullopt; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/private/standardtitlebar_p.h b/include/FramelessHelper/Widgets/private/standardtitlebar_p.h index 8bffd0e8..b1fd794b 100644 --- a/include/FramelessHelper/Widgets/private/standardtitlebar_p.h +++ b/include/FramelessHelper/Widgets/private/standardtitlebar_p.h @@ -29,7 +29,6 @@ #include QT_BEGIN_NAMESPACE -class QPaintEvent; class QMouseEvent; QT_END_NAMESPACE @@ -59,33 +58,6 @@ class FRAMELESSHELPER_WIDGETS_API StandardTitleBarPrivate : public QObject Q_NODISCARD static StandardTitleBarPrivate *get(StandardTitleBar *pub); Q_NODISCARD static const StandardTitleBarPrivate *get(const StandardTitleBar *pub); - Q_NODISCARD Qt::Alignment titleLabelAlignment() const; - void setTitleLabelAlignment(const Qt::Alignment value); - - Q_NODISCARD bool isExtended() const; - void setExtended(const bool value); - - Q_NODISCARD bool isHideWhenClose() const; - void setHideWhenClose(const bool value); - - Q_NODISCARD ChromePalette *chromePalette() const; - - void paintTitleBar(QPaintEvent *event); - - Q_NODISCARD bool titleLabelVisible() const; - void setTitleLabelVisible(const bool value); - - Q_NODISCARD QSize windowIconSize() const; - void setWindowIconSize(const QSize &value); - - Q_NODISCARD bool windowIconVisible() const; - void setWindowIconVisible(const bool value); - - Q_NODISCARD QFont titleFont() const; - void setTitleFont(const QFont &value); - - Q_NODISCARD bool mouseEventHandler(QMouseEvent *event); - Q_NODISCARD QRect windowIconRect() const; Q_NODISCARD bool windowIconVisible_real() const; Q_NODISCARD bool isInTitleBarIconArea(const QPoint &pos) const; @@ -93,35 +65,34 @@ class FRAMELESSHELPER_WIDGETS_API StandardTitleBarPrivate : public QObject Q_NODISCARD QFont defaultFont() const; Q_NODISCARD FontMetrics titleLabelSize() const; -public Q_SLOTS: - void updateMaximizeButton(); - void updateTitleBarColor(); - void updateChromeButtonColor(); - void retranslateUi(); + Q_SLOT void updateMaximizeButton(); + Q_SLOT void updateTitleBarColor(); + Q_SLOT void updateChromeButtonColor(); + Q_SLOT void retranslateUi(); -protected: - Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override; + Q_NODISCARD bool mouseEventHandler(QMouseEvent *event); -private: void initialize(); -private: StandardTitleBar *q_ptr = nullptr; #ifndef Q_OS_MACOS - StandardSystemButton *m_minimizeButton = nullptr; - StandardSystemButton *m_maximizeButton = nullptr; - StandardSystemButton *m_closeButton = nullptr; + StandardSystemButton *minimizeButton = nullptr; + StandardSystemButton *maximizeButton = nullptr; + StandardSystemButton *closeButton = nullptr; #endif // Q_OS_MACOS - QPointer m_window = nullptr; - bool m_extended = false; - Qt::Alignment m_labelAlignment = {}; - bool m_hideWhenClose = false; - ChromePalette *m_chromePalette = nullptr; - bool m_titleLabelVisible = true; - std::optional m_windowIconSize = std::nullopt; - bool m_windowIconVisible = false; - std::optional m_titleFont = std::nullopt; - bool m_closeTriggered = false; + QPointer window = nullptr; + bool extended = false; + Qt::Alignment labelAlignment = {}; + bool hideWhenClose = false; + ChromePalette *chromePalette = nullptr; + bool titleLabelVisible = true; + std::optional windowIconSize = std::nullopt; + bool windowIconVisible = false; + std::optional titleFont = std::nullopt; + bool closeTriggered = false; + +protected: + bool eventFilter(QObject *object, QEvent *event) override; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/standardsystembutton.h b/include/FramelessHelper/Widgets/standardsystembutton.h index fc3412a8..16cf3695 100644 --- a/include/FramelessHelper/Widgets/standardsystembutton.h +++ b/include/FramelessHelper/Widgets/standardsystembutton.h @@ -52,7 +52,7 @@ class FRAMELESSHELPER_WIDGETS_API StandardSystemButton : public QPushButton ~StandardSystemButton() override; Q_NODISCARD QSize sizeHint() const override; - Q_NODISCARD Global::SystemButtonType buttonType(); + Q_NODISCARD Global::SystemButtonType buttonType() const; Q_NODISCARD QString glyph() const; Q_NODISCARD QColor hoverColor() const; Q_NODISCARD QColor pressColor() const; diff --git a/src/core/framelesshelper_win.cpp b/src/core/framelesshelper_win.cpp index 4d98db9f..ffcb138e 100644 --- a/src/core/framelesshelper_win.cpp +++ b/src/core/framelesshelper_win.cpp @@ -988,6 +988,9 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me #endif case WM_NCMOUSEHOVER: case WM_NCMOUSELEAVE: { + // For future code readers: + // The following code is not workaround anything, it's just try to emulate the original + // behavior of a native Win32 window. const WindowPart previousWindowPart = getHittedWindowPart(data.hitTestResult.first.value_or(HTNOWHERE)); const bool isXButtonMessage = ((uMsg >= WM_NCXBUTTONDOWN) && (uMsg <= WM_NCXBUTTONDBLCLK)); const WindowPart nowWindowPart = getHittedWindowPart(isXButtonMessage ? GET_NCHITTEST_WPARAM(wParam) : wParam); diff --git a/src/quick/framelessquickhelper.cpp b/src/quick/framelessquickhelper.cpp index a0772025..2f4fa61c 100644 --- a/src/quick/framelessquickhelper.cpp +++ b/src/quick/framelessquickhelper.cpp @@ -237,7 +237,8 @@ void FramelessQuickHelperPrivate::setProperty(const char *name, const QVariant & Q_ASSERT(name); Q_ASSERT(*name != '\0'); Q_ASSERT(value.isValid()); - if (!name || (*name == '\0') || !value.isValid()) { + Q_ASSERT(!value.isNull()); + if (!name || (*name == '\0') || !value.isValid() || value.isNull()) { return; } Q_Q(FramelessQuickHelper); @@ -261,7 +262,7 @@ QVariant FramelessQuickHelperPrivate::getProperty(const char *name, const QVaria return {}; } const QVariant value = window->property(name); - return (value.isValid() ? value : defaultValue); + return ((value.isValid() && !value.isNull()) ? value : defaultValue); } QuickMicaMaterial *FramelessQuickHelperPrivate::findOrCreateMicaMaterial() const diff --git a/src/widgets/framelessdialog.cpp b/src/widgets/framelessdialog.cpp index 49ba0c03..a6a634d9 100644 --- a/src/widgets/framelessdialog.cpp +++ b/src/widgets/framelessdialog.cpp @@ -26,7 +26,6 @@ #include "framelessdialog_p.h" #include "framelesswidgetshelper.h" #include "widgetssharedhelper_p.h" -#include #include FRAMELESSHELPER_BEGIN_NAMESPACE @@ -54,7 +53,6 @@ FramelessDialogPrivate::FramelessDialogPrivate(FramelessDialog *q) : QObject(q) return; } q_ptr = q; - initialize(); } FramelessDialogPrivate::~FramelessDialogPrivate() = default; @@ -77,22 +75,13 @@ const FramelessDialogPrivate *FramelessDialogPrivate::get(const FramelessDialog return pub->d_func(); } -void FramelessDialogPrivate::initialize() -{ - Q_Q(FramelessDialog); - FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar(); - m_sharedHelper = new WidgetsSharedHelper(this); - m_sharedHelper->setup(q); -} - -WidgetsSharedHelper *FramelessDialogPrivate::widgetsSharedHelper() const -{ - return m_sharedHelper; -} - FramelessDialog::FramelessDialog(QWidget *parent) : QDialog(parent), d_ptr(new FramelessDialogPrivate(this)) { + FramelessWidgetsHelper::get(this)->extendsContentIntoTitleBar(); + Q_D(FramelessDialog); + d->sharedHelper = new WidgetsSharedHelper(d); + d->sharedHelper->setup(this); } FramelessDialog::~FramelessDialog() = default; diff --git a/src/widgets/framelessmainwindow.cpp b/src/widgets/framelessmainwindow.cpp index 41c309f5..5131a764 100644 --- a/src/widgets/framelessmainwindow.cpp +++ b/src/widgets/framelessmainwindow.cpp @@ -54,7 +54,6 @@ FramelessMainWindowPrivate::FramelessMainWindowPrivate(FramelessMainWindow *q) : return; } q_ptr = q; - initialize(); } FramelessMainWindowPrivate::~FramelessMainWindowPrivate() = default; @@ -77,81 +76,45 @@ const FramelessMainWindowPrivate *FramelessMainWindowPrivate::get(const Frameles return pub->d_func(); } -void FramelessMainWindowPrivate::initialize() -{ - Q_Q(FramelessMainWindow); - FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar(); - m_sharedHelper = new WidgetsSharedHelper(this); - m_sharedHelper->setup(q); -} - -bool FramelessMainWindowPrivate::isNormal() const -{ - Q_Q(const FramelessMainWindow); - return (Utils::windowStatesToWindowState(q->windowState()) == Qt::WindowNoState); -} - -bool FramelessMainWindowPrivate::isZoomed() const -{ - Q_Q(const FramelessMainWindow); - return (q->isMaximized() || q->isFullScreen()); -} - -void FramelessMainWindowPrivate::toggleMaximized() -{ - Q_Q(FramelessMainWindow); - if (q->isMaximized()) { - q->showNormal(); - } else { - q->showMaximized(); - } -} - -void FramelessMainWindowPrivate::toggleFullScreen() -{ - Q_Q(FramelessMainWindow); - if (q->isFullScreen()) { - q->setWindowState(m_savedWindowState); - } else { - m_savedWindowState = Utils::windowStatesToWindowState(q->windowState()); - q->showFullScreen(); - } -} - -WidgetsSharedHelper *FramelessMainWindowPrivate::widgetsSharedHelper() const -{ - return m_sharedHelper; -} - FramelessMainWindow::FramelessMainWindow(QWidget *parent, const Qt::WindowFlags flags) : QMainWindow(parent, flags), d_ptr(new FramelessMainWindowPrivate(this)) { + FramelessWidgetsHelper::get(this)->extendsContentIntoTitleBar(); + Q_D(FramelessMainWindow); + d->sharedHelper = new WidgetsSharedHelper(d); + d->sharedHelper->setup(this); } FramelessMainWindow::~FramelessMainWindow() = default; bool FramelessMainWindow::isNormal() const { - Q_D(const FramelessMainWindow); - return d->isNormal(); + return (Utils::windowStatesToWindowState(windowState()) == Qt::WindowNoState); } bool FramelessMainWindow::isZoomed() const { - Q_D(const FramelessMainWindow); - return d->isZoomed(); + return (isMaximized() || isFullScreen()); } void FramelessMainWindow::toggleMaximized() { - Q_D(FramelessMainWindow); - d->toggleMaximized(); + if (isMaximized()) { + showNormal(); + } else { + showMaximized(); + } } void FramelessMainWindow::toggleFullScreen() { Q_D(FramelessMainWindow); - d->toggleFullScreen(); + if (isFullScreen()) { + setWindowState(d->savedWindowState); + } else { + d->savedWindowState = Utils::windowStatesToWindowState(windowState()); + showFullScreen(); + } } FRAMELESSHELPER_END_NAMESPACE diff --git a/src/widgets/framelesswidget.cpp b/src/widgets/framelesswidget.cpp index 7ce4feb9..72e40a26 100644 --- a/src/widgets/framelesswidget.cpp +++ b/src/widgets/framelesswidget.cpp @@ -54,7 +54,6 @@ FramelessWidgetPrivate::FramelessWidgetPrivate(FramelessWidget *q) : QObject(q) return; } q_ptr = q; - initialize(); } FramelessWidgetPrivate::~FramelessWidgetPrivate() = default; @@ -77,81 +76,45 @@ const FramelessWidgetPrivate *FramelessWidgetPrivate::get(const FramelessWidget return pub->d_func(); } -void FramelessWidgetPrivate::initialize() -{ - Q_Q(FramelessWidget); - FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar(); - m_sharedHelper = new WidgetsSharedHelper(this); - m_sharedHelper->setup(q); -} - -bool FramelessWidgetPrivate::isNormal() const -{ - Q_Q(const FramelessWidget); - return (Utils::windowStatesToWindowState(q->windowState()) == Qt::WindowNoState); -} - -bool FramelessWidgetPrivate::isZoomed() const -{ - Q_Q(const FramelessWidget); - return (q->isMaximized() || q->isFullScreen()); -} - -void FramelessWidgetPrivate::toggleMaximized() -{ - Q_Q(FramelessWidget); - if (q->isMaximized()) { - q->showNormal(); - } else { - q->showMaximized(); - } -} - -void FramelessWidgetPrivate::toggleFullScreen() -{ - Q_Q(FramelessWidget); - if (q->isFullScreen()) { - q->setWindowState(m_savedWindowState); - } else { - m_savedWindowState = Utils::windowStatesToWindowState(q->windowState()); - q->showFullScreen(); - } -} - -WidgetsSharedHelper *FramelessWidgetPrivate::widgetsSharedHelper() const -{ - return m_sharedHelper; -} - FramelessWidget::FramelessWidget(QWidget *parent) : QWidget(parent, Qt::Window), d_ptr(new FramelessWidgetPrivate(this)) { + FramelessWidgetsHelper::get(this)->extendsContentIntoTitleBar(); + Q_D(FramelessWidget); + d->sharedHelper = new WidgetsSharedHelper(d); + d->sharedHelper->setup(this); } FramelessWidget::~FramelessWidget() = default; bool FramelessWidget::isNormal() const { - Q_D(const FramelessWidget); - return d->isNormal(); + return (Utils::windowStatesToWindowState(windowState()) == Qt::WindowNoState); } bool FramelessWidget::isZoomed() const { - Q_D(const FramelessWidget); - return d->isZoomed(); + return (isMaximized() || isFullScreen()); } void FramelessWidget::toggleMaximized() { - Q_D(FramelessWidget); - d->toggleMaximized(); + if (isMaximized()) { + showNormal(); + } else { + showMaximized(); + } } void FramelessWidget::toggleFullScreen() { Q_D(FramelessWidget); - d->toggleFullScreen(); + if (isFullScreen()) { + setWindowState(d->savedWindowState); + } else { + d->savedWindowState = Utils::windowStatesToWindowState(windowState()); + showFullScreen(); + } } FRAMELESSHELPER_END_NAMESPACE diff --git a/src/widgets/framelesswidgetshelper.cpp b/src/widgets/framelesswidgetshelper.cpp index b1896d26..eb914314 100644 --- a/src/widgets/framelesswidgetshelper.cpp +++ b/src/widgets/framelesswidgetshelper.cpp @@ -169,11 +169,7 @@ FramelessWidgetsHelperPrivate::FramelessWidgetsHelperPrivate(FramelessWidgetsHel q_ptr = q; } -FramelessWidgetsHelperPrivate::~FramelessWidgetsHelperPrivate() -{ - m_destroying = true; - extendsContentIntoTitleBar(false); -} +FramelessWidgetsHelperPrivate::~FramelessWidgetsHelperPrivate() = default; FramelessWidgetsHelperPrivate *FramelessWidgetsHelperPrivate::get(FramelessWidgetsHelper *pub) { @@ -193,37 +189,6 @@ const FramelessWidgetsHelperPrivate *FramelessWidgetsHelperPrivate::get(const Fr return pub->d_func(); } -bool FramelessWidgetsHelperPrivate::isWindowFixedSize() const -{ - if (!m_window) { - return false; - } - return isWidgetFixedSize(m_window); -} - -void FramelessWidgetsHelperPrivate::setWindowFixedSize(const bool value) -{ - if (!m_window) { - return; - } - if (isWindowFixedSize() == value) { - return; - } - if (value) { - m_savedSizePolicy = m_window->sizePolicy(); - m_window->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - m_window->setFixedSize(m_window->size()); - } else { - m_window->setSizePolicy(m_savedSizePolicy); - m_window->setMinimumSize(kDefaultWindowSize); - m_window->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); - } -#ifdef Q_OS_WINDOWS - std::ignore = Utils::setAeroSnappingEnabled(m_window->winId(), !value); -#endif - emitSignalForAllInstances("windowFixedSizeChanged"); -} - void FramelessWidgetsHelperPrivate::emitSignalForAllInstances(const char *signal) { Q_ASSERT(signal); @@ -231,10 +196,10 @@ void FramelessWidgetsHelperPrivate::emitSignalForAllInstances(const char *signal if (!signal || (*signal == '\0')) { return; } - if (!m_window) { + if (!window) { return; } - const auto instances = m_window->findChildren(); + const auto instances = window->findChildren(); if (instances.isEmpty()) { return; } @@ -243,57 +208,20 @@ void FramelessWidgetsHelperPrivate::emitSignalForAllInstances(const char *signal } } -bool FramelessWidgetsHelperPrivate::isBlurBehindWindowEnabled() const -{ - return m_blurBehindWindowEnabled; -} - -void FramelessWidgetsHelperPrivate::setBlurBehindWindowEnabled(const bool enable, const QColor &color) -{ - if (!m_window) { - return; - } - if (m_blurBehindWindowEnabled == enable) { - return; - } - if (Utils::isBlurBehindWindowSupported()) { - QPalette palette = m_window->palette(); - if (enable) { - m_savedWindowBackgroundColor = palette.color(QPalette::Window); - } - palette.setColor(QPalette::Window, (enable ? kDefaultTransparentColor : m_savedWindowBackgroundColor)); - m_window->setPalette(palette); - if (Utils::setBlurBehindWindowEnabled(m_window->winId(), - (enable ? BlurMode::Default : BlurMode::Disable), color)) { - m_blurBehindWindowEnabled = enable; - emitSignalForAllInstances("blurBehindWindowEnabledChanged"); - } else { - WARNING << "Failed to enable/disable blur behind window."; - } - } else { - if (WidgetsSharedHelper * const helper = findOrCreateSharedHelper(m_window)) { - m_blurBehindWindowEnabled = enable; - helper->setMicaEnabled(m_blurBehindWindowEnabled); - emitSignalForAllInstances("blurBehindWindowEnabledChanged"); - } else { - DEBUG << "Blur behind window is not supported on current platform."; - } - } -} - void FramelessWidgetsHelperPrivate::setProperty(const char *name, const QVariant &value) { Q_ASSERT(name); Q_ASSERT(*name != '\0'); Q_ASSERT(value.isValid()); - if (!name || (*name == '\0') || !value.isValid()) { + Q_ASSERT(!value.isNull()); + if (!name || (*name == '\0') || !value.isValid() || value.isNull()) { return; } - Q_ASSERT(m_window); - if (!m_window) { + Q_ASSERT(window); + if (!window) { return; } - m_window->setProperty(name, value); + window->setProperty(name, value); } QVariant FramelessWidgetsHelperPrivate::getProperty(const char *name, const QVariant &defaultValue) @@ -303,25 +231,20 @@ QVariant FramelessWidgetsHelperPrivate::getProperty(const char *name, const QVar if (!name || (*name == '\0')) { return {}; } - Q_ASSERT(m_window); - if (!m_window) { + Q_ASSERT(window); + if (!window) { return {}; } - const QVariant value = m_window->property(name); - return (value.isValid() ? value : defaultValue); -} - -QWidget *FramelessWidgetsHelperPrivate::window() const -{ - return m_window; + const QVariant value = window->property(name); + return ((value.isValid() && !value.isNull()) ? value : defaultValue); } MicaMaterial *FramelessWidgetsHelperPrivate::getMicaMaterialIfAny() const { - if (!m_window) { + if (!window) { return nullptr; } - if (const WidgetsSharedHelper * const helper = findOrCreateSharedHelper(m_window)) { + if (const WidgetsSharedHelper * const helper = findOrCreateSharedHelper(window)) { return helper->rawMicaMaterial(); } return nullptr; @@ -329,10 +252,10 @@ MicaMaterial *FramelessWidgetsHelperPrivate::getMicaMaterialIfAny() const WindowBorderPainter *FramelessWidgetsHelperPrivate::getWindowBorderIfAny() const { - if (!m_window) { + if (!window) { return nullptr; } - if (const WidgetsSharedHelper * const helper = findOrCreateSharedHelper(m_window)) { + if (const WidgetsSharedHelper * const helper = findOrCreateSharedHelper(window)) { return helper->rawWindowBorder(); } return nullptr; @@ -346,17 +269,17 @@ WidgetsSharedHelper *FramelessWidgetsHelperPrivate::findOrCreateSharedHelper(QWi } if (const auto widget = qobject_cast(window)) { if (const auto widgetPriv = FramelessWidgetPrivate::get(widget)) { - return widgetPriv->widgetsSharedHelper(); + return widgetPriv->sharedHelper; } } if (const auto mainWindow = qobject_cast(window)) { if (const auto mainWindowPriv = FramelessMainWindowPrivate::get(mainWindow)) { - return mainWindowPriv->widgetsSharedHelper(); + return mainWindowPriv->sharedHelper; } } if (const auto dialog = qobject_cast(window)) { if (const auto dialogPriv = FramelessDialogPrivate::get(dialog)) { - return dialogPriv->widgetsSharedHelper(); + return dialogPriv->sharedHelper; } } QWidget * const topLevelWindow = window->window(); @@ -391,38 +314,14 @@ FramelessWidgetsHelper *FramelessWidgetsHelperPrivate::findOrCreateFramelessHelp return instance; } -bool FramelessWidgetsHelperPrivate::isReady() const -{ - return m_qpaReady; -} - -void FramelessWidgetsHelperPrivate::waitForReady() -{ - if (m_qpaReady) { - return; - } -#if 1 - QEventLoop loop; - Q_Q(FramelessWidgetsHelper); - const QMetaObject::Connection connection = connect( - q, &FramelessWidgetsHelper::ready, &loop, &QEventLoop::quit); - loop.exec(); - disconnect(connection); -#else - while (!m_qpaReady) { - QCoreApplication::processEvents(); - } -#endif -} - void FramelessWidgetsHelperPrivate::repaintAllChildren(const quint32 delay) const { - if (!m_window) { + if (!window) { return; } const auto update = [this]() -> void { - forceWidgetRepaint(m_window); - const QList widgets = m_window->findChildren(); + forceWidgetRepaint(window); + const QList widgets = window->findChildren(); if (widgets.isEmpty()) { return; } @@ -439,102 +338,28 @@ void FramelessWidgetsHelperPrivate::repaintAllChildren(const quint32 delay) cons quint32 FramelessWidgetsHelperPrivate::readyWaitTime() const { - return m_qpaWaitTime; + return qpaWaitTime; } void FramelessWidgetsHelperPrivate::setReadyWaitTime(const quint32 time) { - if (m_qpaWaitTime == time) { - return; - } - m_qpaWaitTime = time; -} - -bool FramelessWidgetsHelperPrivate::isContentExtendedIntoTitleBar() const -{ - const FramelessWidgetsHelperData *data = getWindowData(); - return (data ? data->ready : false); -} - -void FramelessWidgetsHelperPrivate::setTitleBarWidget(QWidget *widget) -{ - Q_ASSERT(widget); - if (!widget) { - return; - } - FramelessWidgetsHelperData *data = getWindowDataMutable(); - if (!data || (data->titleBarWidget == widget)) { - return; - } - data->titleBarWidget = widget; - emitSignalForAllInstances("titleBarWidgetChanged"); -} - -QWidget *FramelessWidgetsHelperPrivate::getTitleBarWidget() const -{ - const FramelessWidgetsHelperData *data = getWindowData(); - return (data ? data->titleBarWidget : nullptr); -} - -void FramelessWidgetsHelperPrivate::setHitTestVisible(QWidget *widget, const bool visible) -{ - Q_ASSERT(widget); - if (!widget) { - return; - } - FramelessWidgetsHelperData *data = getWindowDataMutable(); - if (!data) { + if (qpaWaitTime == time) { return; } - if (visible) { - data->hitTestVisibleWidgets.append(widget); - } else { - data->hitTestVisibleWidgets.removeAll(widget); - } -} - -void FramelessWidgetsHelperPrivate::setHitTestVisible(const QRect &rect, const bool visible) -{ - Q_ASSERT(rect.isValid()); - if (!rect.isValid()) { - return; - } - FramelessWidgetsHelperData *data = getWindowDataMutable(); - if (!data) { - return; - } - if (visible) { - data->hitTestVisibleRects.append(rect); - } else { - data->hitTestVisibleRects.removeAll(rect); - } -} - -void FramelessWidgetsHelperPrivate::setHitTestVisible(QObject *object, const bool visible) -{ - Q_ASSERT(object); - if (!object) { - return; - } - const auto widget = qobject_cast(object); - Q_ASSERT(widget); - if (!widget) { - return; - } - setHitTestVisible(widget, visible); + qpaWaitTime = time; } void FramelessWidgetsHelperPrivate::attach() { - QWidget * const window = findTopLevelWindow(); - Q_ASSERT(window); - if (!window) { + QWidget * const tlw = findTopLevelWindow(); + Q_ASSERT(tlw); + if (!tlw) { return; } - if (m_window == window) { + if (window == tlw) { return; } - m_window = window; + window = tlw; if (!window->testAttribute(Qt::WA_DontCreateNativeAncestors)) { window->setAttribute(Qt::WA_DontCreateNativeAncestors); @@ -548,39 +373,41 @@ void FramelessWidgetsHelperPrivate::attach() return; } + Q_Q(FramelessWidgetsHelper); + SystemParameters params = {}; - params.getWindowId = [window]() -> WId { return window->winId(); }; - params.getWindowFlags = [window]() -> Qt::WindowFlags { return window->windowFlags(); }; - params.setWindowFlags = [window](const Qt::WindowFlags flags) -> void { window->setWindowFlags(flags); }; - params.getWindowSize = [window]() -> QSize { return window->size(); }; - params.setWindowSize = [window](const QSize &size) -> void { window->resize(size); }; - params.getWindowPosition = [window]() -> QPoint { return window->pos(); }; - params.setWindowPosition = [window](const QPoint &pos) -> void { window->move(pos); }; - params.getWindowScreen = [window]() -> QScreen * { + params.getWindowId = [this]() -> WId { return window->winId(); }; + params.getWindowFlags = [this]() -> Qt::WindowFlags { return window->windowFlags(); }; + params.setWindowFlags = [this](const Qt::WindowFlags flags) -> void { window->setWindowFlags(flags); }; + params.getWindowSize = [this]() -> QSize { return window->size(); }; + params.setWindowSize = [this](const QSize &size) -> void { window->resize(size); }; + params.getWindowPosition = [this]() -> QPoint { return window->pos(); }; + params.setWindowPosition = [this](const QPoint &pos) -> void { window->move(pos); }; + params.getWindowScreen = [this]() -> QScreen * { #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) return window->screen(); #else return window->windowHandle()->screen(); #endif }; - params.isWindowFixedSize = [this]() -> bool { return isWindowFixedSize(); }; - params.setWindowFixedSize = [this](const bool value) -> void { setWindowFixedSize(value); }; - params.getWindowState = [window]() -> Qt::WindowState { return Utils::windowStatesToWindowState(window->windowState()); }; - params.setWindowState = [window](const Qt::WindowState state) -> void { window->setWindowState(state); }; - params.getWindowHandle = [window]() -> QWindow * { return window->windowHandle(); }; - params.windowToScreen = [window](const QPoint &pos) -> QPoint { return window->mapToGlobal(pos); }; - params.screenToWindow = [window](const QPoint &pos) -> QPoint { return window->mapFromGlobal(pos); }; + params.isWindowFixedSize = [q]() -> bool { return q->isWindowFixedSize(); }; + params.setWindowFixedSize = [q](const bool value) -> void { q->setWindowFixedSize(value); }; + params.getWindowState = [this]() -> Qt::WindowState { return Utils::windowStatesToWindowState(window->windowState()); }; + params.setWindowState = [this](const Qt::WindowState state) -> void { window->setWindowState(state); }; + params.getWindowHandle = [this]() -> QWindow * { return window->windowHandle(); }; + params.windowToScreen = [this](const QPoint &pos) -> QPoint { return window->mapToGlobal(pos); }; + params.screenToWindow = [this](const QPoint &pos) -> QPoint { return window->mapFromGlobal(pos); }; params.isInsideSystemButtons = [this](const QPoint &pos, SystemButtonType *button) -> bool { return isInSystemButtons(pos, button); }; params.isInsideTitleBarDraggableArea = [this](const QPoint &pos) -> bool { return isInTitleBarDraggableArea(pos); }; - params.getWindowDevicePixelRatio = [window]() -> qreal { return window->devicePixelRatioF(); }; + params.getWindowDevicePixelRatio = [this]() -> qreal { return window->devicePixelRatioF(); }; params.setSystemButtonState = [this](const SystemButtonType button, const ButtonState state) -> void { setSystemButtonState(button, state); }; params.shouldIgnoreMouseEvents = [this](const QPoint &pos) -> bool { return shouldIgnoreMouseEvents(pos); }; - params.showSystemMenu = [this](const QPoint &pos) -> void { showSystemMenu(pos); }; + params.showSystemMenu = [q](const QPoint &pos) -> void { q->showSystemMenu(pos); }; params.setProperty = [this](const char *name, const QVariant &value) -> void { setProperty(name, value); }; params.getProperty = [this](const char *name, const QVariant &defaultValue) -> QVariant { return getProperty(name, defaultValue); }; - params.setCursor = [window](const QCursor &cursor) -> void { window->setCursor(cursor); }; - params.unsetCursor = [window]() -> void { window->unsetCursor(); }; - params.getWidgetHandle = [window]() -> QObject * { return window; }; + params.setCursor = [this](const QCursor &cursor) -> void { window->setCursor(cursor); }; + params.unsetCursor = [this]() -> void { window->unsetCursor(); }; + params.getWidgetHandle = [this]() -> QObject * { return window; }; params.forceChildrenRepaint = [this](const int delay) -> void { repaintAllChildren(delay); }; params.resetQtGrabbedControl = []() -> void { qt_button_down = nullptr; }; @@ -594,13 +421,13 @@ void FramelessWidgetsHelperPrivate::attach() // we reach here, and all the modifications from the Qt side will be lost // due to QPA will reset the position and size of the window during it's // initialization process. - QTimer::singleShot(m_qpaWaitTime, this, [this](){ - m_qpaReady = true; + QTimer::singleShot(qpaWaitTime, this, [this, q](){ + qpaReady = true; if (FramelessConfig::instance()->isSet(Option::CenterWindowBeforeShow)) { - moveWindowToDesktopCenter(); + q->moveWindowToDesktopCenter(); } if (FramelessConfig::instance()->isSet(Option::EnableBlurBehindWindow)) { - setBlurBehindWindowEnabled(true, {}); + q->setBlurBehindWindowEnabled(true); } emitSignalForAllInstances("windowChanged"); emitSignalForAllInstances("ready"); @@ -609,35 +436,20 @@ void FramelessWidgetsHelperPrivate::attach() void FramelessWidgetsHelperPrivate::detach() { - if (!m_window) { + if (!window) { return; } - const WId windowId = m_window->winId(); + const WId windowId = window->winId(); const auto it = g_framelessWidgetsHelperData()->constFind(windowId); if (it == g_framelessWidgetsHelperData()->constEnd()) { return; } g_framelessWidgetsHelperData()->erase(it); FramelessManager::instance()->removeWindow(windowId); - m_window = nullptr; + window = nullptr; emitSignalForAllInstances("windowChanged"); } -void FramelessWidgetsHelperPrivate::extendsContentIntoTitleBar(const bool value) -{ - if (isContentExtendedIntoTitleBar() == value) { - return; - } - if (value) { - attach(); - } else { - detach(); - } - if (!m_destroying) { - emitSignalForAllInstances("extendsContentIntoTitleBarChanged"); - } -} - QWidget *FramelessWidgetsHelperPrivate::findTopLevelWindow() const { Q_Q(const FramelessWidgetsHelper); @@ -653,11 +465,11 @@ QWidget *FramelessWidgetsHelperPrivate::findTopLevelWindow() const const FramelessWidgetsHelperData *FramelessWidgetsHelperPrivate::getWindowData() const { - //Q_ASSERT(m_window); - if (!m_window) { + //Q_ASSERT(window); + if (!window) { return nullptr; } - const WId windowId = m_window->winId(); + const WId windowId = window->winId(); auto it = g_framelessWidgetsHelperData()->find(windowId); if (it == g_framelessWidgetsHelperData()->end()) { it = g_framelessWidgetsHelperData()->insert(windowId, {}); @@ -667,11 +479,11 @@ const FramelessWidgetsHelperData *FramelessWidgetsHelperPrivate::getWindowData() FramelessWidgetsHelperData *FramelessWidgetsHelperPrivate::getWindowDataMutable() const { - //Q_ASSERT(m_window); - if (!m_window) { + //Q_ASSERT(window); + if (!window) { return nullptr; } - const WId windowId = m_window->winId(); + const WId windowId = window->winId(); auto it = g_framelessWidgetsHelperData()->find(windowId); if (it == g_framelessWidgetsHelperData()->end()) { it = g_framelessWidgetsHelperData()->insert(windowId, {}); @@ -685,10 +497,10 @@ QRect FramelessWidgetsHelperPrivate::mapWidgetGeometryToScene(const QWidget * co if (!widget) { return {}; } - if (!m_window) { + if (!window) { return {}; } - const QPoint originPoint = widget->mapTo(m_window, QPoint(0, 0)); + const QPoint originPoint = widget->mapTo(window, QPoint(0, 0)); const QSize size = widget->size(); return QRect(originPoint, size); } @@ -751,12 +563,12 @@ bool FramelessWidgetsHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos) // The title bar is hidden or disabled for some reason, treat it as there's no title bar. return false; } - if (!m_window) { + if (!window) { // The FramelessWidgetsHelper object has not been attached to a specific window yet, // so we assume there's no title bar. return false; } - const QRect windowRect = {QPoint(0, 0), m_window->size()}; + const QRect windowRect = {QPoint(0, 0), window->size()}; const QRect titleBarRect = mapWidgetGeometryToScene(data->titleBarWidget); if (!titleBarRect.intersects(windowRect)) { // The title bar is totally outside of the window for some reason, @@ -793,7 +605,7 @@ bool FramelessWidgetsHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos) bool FramelessWidgetsHelperPrivate::shouldIgnoreMouseEvents(const QPoint &pos) const { - if (!m_window) { + if (!window) { return false; } const auto withinFrameBorder = [this, &pos]() -> bool { @@ -806,9 +618,9 @@ bool FramelessWidgetsHelperPrivate::shouldIgnoreMouseEvents(const QPoint &pos) c } #endif return ((pos.x() < kDefaultResizeBorderThickness) - || (pos.x() >= (m_window->width() - kDefaultResizeBorderThickness))); + || (pos.x() >= (window->width() - kDefaultResizeBorderThickness))); }(); - return ((Utils::windowStatesToWindowState(m_window->windowState()) == Qt::WindowNoState) && withinFrameBorder); + return ((Utils::windowStatesToWindowState(window->windowState()) == Qt::WindowNoState) && withinFrameBorder); } void FramelessWidgetsHelperPrivate::setSystemButtonState(const SystemButtonType button, const ButtonState state) @@ -817,42 +629,45 @@ void FramelessWidgetsHelperPrivate::setSystemButtonState(const SystemButtonType Q_UNUSED(state); } -void FramelessWidgetsHelperPrivate::moveWindowToDesktopCenter() +void FramelessWidgetsHelper::moveWindowToDesktopCenter() { - if (!m_window) { + Q_D(FramelessWidgetsHelper); + if (!d->window) { return; } - Utils::moveWindowToDesktopCenter(&getWindowData()->params, true); + Utils::moveWindowToDesktopCenter(&d->getWindowData()->params, true); } -void FramelessWidgetsHelperPrivate::bringWindowToFront() +void FramelessWidgetsHelper::bringWindowToFront() { - if (!m_window) { + Q_D(FramelessWidgetsHelper); + if (!d->window) { return; } #ifdef Q_OS_WINDOWS - std::ignore = Utils::bringWindowToFront(m_window->winId()); + std::ignore = Utils::bringWindowToFront(d->window->winId()); #else - if (m_window->isHidden()) { - m_window->show(); + if (d->window->isHidden()) { + d->window->show(); } - if (m_window->isMinimized()) { - m_window->setWindowState(m_window->windowState() & ~Qt::WindowMinimized); + if (d->window->isMinimized()) { + d->window->setWindowState(d->window->windowState() & ~Qt::WindowMinimized); } - m_window->raise(); - m_window->activateWindow(); + d->window->raise(); + d->window->activateWindow(); #endif } -void FramelessWidgetsHelperPrivate::showSystemMenu(const QPoint &pos) +void FramelessWidgetsHelper::showSystemMenu(const QPoint &pos) { - if (!m_window) { + Q_D(FramelessWidgetsHelper); + if (!d->window) { return; } - const WId windowId = m_window->winId(); - const QPoint nativePos = Utils::toNativeGlobalPosition(m_window->windowHandle(), pos); + const WId windowId = d->window->winId(); + const QPoint nativePos = Utils::toNativeGlobalPosition(d->window->windowHandle(), pos); #ifdef Q_OS_WINDOWS - std::ignore = Utils::showSystemMenu(windowId, nativePos, false, &getWindowData()->params); + std::ignore = Utils::showSystemMenu(windowId, nativePos, false, &d->getWindowData()->params); #elif defined(Q_OS_LINUX) Utils::openSystemMenu(windowId, nativePos); #else @@ -861,33 +676,36 @@ void FramelessWidgetsHelperPrivate::showSystemMenu(const QPoint &pos) #endif } -void FramelessWidgetsHelperPrivate::windowStartSystemMove2(const QPoint &pos) +void FramelessWidgetsHelper::windowStartSystemMove2(const QPoint &pos) { - if (!m_window) { + Q_D(FramelessWidgetsHelper); + if (!d->window) { return; } - std::ignore = Utils::startSystemMove(m_window->windowHandle(), pos); + std::ignore = Utils::startSystemMove(d->window->windowHandle(), pos); } -void FramelessWidgetsHelperPrivate::windowStartSystemResize2(const Qt::Edges edges, const QPoint &pos) +void FramelessWidgetsHelper::windowStartSystemResize2(const Qt::Edges edges, const QPoint &pos) { - if (!m_window) { + Q_D(FramelessWidgetsHelper); + if (!d->window) { return; } if (edges == Qt::Edges{}) { return; } - std::ignore = Utils::startSystemResize(m_window->windowHandle(), edges, pos); + std::ignore = Utils::startSystemResize(d->window->windowHandle(), edges, pos); } -void FramelessWidgetsHelperPrivate::setSystemButton(QWidget *widget, const SystemButtonType buttonType) +void FramelessWidgetsHelper::setSystemButton(QWidget *widget, const SystemButtonType buttonType) { Q_ASSERT(widget); Q_ASSERT(buttonType != SystemButtonType::Unknown); if (!widget || (buttonType == SystemButtonType::Unknown)) { return; } - FramelessWidgetsHelperData *data = getWindowDataMutable(); + Q_D(FramelessWidgetsHelper); + FramelessWidgetsHelperData *data = d->getWindowDataMutable(); if (!data) { return; } @@ -929,64 +747,125 @@ FramelessWidgetsHelper *FramelessWidgetsHelper::get(QObject *object) return FramelessWidgetsHelperPrivate::findOrCreateFramelessHelper(object); } -QWidget *FramelessWidgetsHelper::titleBarWidget() const +QWidget *FramelessWidgetsHelper::window() const { Q_D(const FramelessWidgetsHelper); - return d->getTitleBarWidget(); + return d->window; } -bool FramelessWidgetsHelper::isWindowFixedSize() const +MicaMaterial *FramelessWidgetsHelper::micaMaterial() const { Q_D(const FramelessWidgetsHelper); - return d->isWindowFixedSize(); + return d->getMicaMaterialIfAny(); } -bool FramelessWidgetsHelper::isBlurBehindWindowEnabled() const +WindowBorderPainter *FramelessWidgetsHelper::windowBorder() const { Q_D(const FramelessWidgetsHelper); - return d->isBlurBehindWindowEnabled(); + return d->getWindowBorderIfAny(); } -QWidget *FramelessWidgetsHelper::window() const +bool FramelessWidgetsHelper::isWindowFixedSize() const { Q_D(const FramelessWidgetsHelper); - return d->window(); + if (!d->window) { + return false; + } + return isWidgetFixedSize(d->window); } -bool FramelessWidgetsHelper::isContentExtendedIntoTitleBar() const +void FramelessWidgetsHelper::setWindowFixedSize(const bool value) { - Q_D(const FramelessWidgetsHelper); - return d->isContentExtendedIntoTitleBar(); + Q_D(FramelessWidgetsHelper); + if (!d->window) { + return; + } + if (isWindowFixedSize() == value) { + return; + } + if (value) { + d->savedSizePolicy = d->window->sizePolicy(); + d->window->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + d->window->setFixedSize(d->window->size()); + } else { + d->window->setSizePolicy(d->savedSizePolicy); + d->window->setMinimumSize(kDefaultWindowSize); + d->window->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); + } +#ifdef Q_OS_WINDOWS + std::ignore = Utils::setAeroSnappingEnabled(d->window->winId(), !value); +#endif + d->emitSignalForAllInstances("windowFixedSizeChanged"); } -MicaMaterial *FramelessWidgetsHelper::micaMaterial() const +bool FramelessWidgetsHelper::isBlurBehindWindowEnabled() const { Q_D(const FramelessWidgetsHelper); - return d->getMicaMaterialIfAny(); + return d->blurBehindWindowEnabled; } -WindowBorderPainter *FramelessWidgetsHelper::windowBorder() const +void FramelessWidgetsHelper::setBlurBehindWindowEnabled(const bool enable) { - Q_D(const FramelessWidgetsHelper); - return d->getWindowBorderIfAny(); + Q_D(FramelessWidgetsHelper); + if (!d->window) { + return; + } + if (d->blurBehindWindowEnabled == enable) { + return; + } + if (Utils::isBlurBehindWindowSupported()) { + QPalette palette = d->window->palette(); + if (enable) { + d->savedWindowBackgroundColor = palette.color(QPalette::Window); + } + palette.setColor(QPalette::Window, (enable ? kDefaultTransparentColor : d->savedWindowBackgroundColor)); + d->window->setPalette(palette); + if (Utils::setBlurBehindWindowEnabled(d->window->winId(), (enable ? BlurMode::Default : BlurMode::Disable), {})) { + d->blurBehindWindowEnabled = enable; + d->emitSignalForAllInstances("blurBehindWindowEnabledChanged"); + } else { + WARNING << "Failed to enable/disable blur behind window."; + } + } else { + if (WidgetsSharedHelper * const helper = d->findOrCreateSharedHelper(d->window)) { + d->blurBehindWindowEnabled = enable; + helper->setMicaEnabled(d->blurBehindWindowEnabled); + d->emitSignalForAllInstances("blurBehindWindowEnabledChanged"); + } else { + DEBUG << "Blur behind window is not supported on current platform."; + } + } } bool FramelessWidgetsHelper::isReady() const { Q_D(const FramelessWidgetsHelper); - return d->isReady(); + return d->qpaReady; } void FramelessWidgetsHelper::waitForReady() { Q_D(FramelessWidgetsHelper); - d->waitForReady(); + if (d->qpaReady) { + return; + } +#if 1 + QEventLoop loop{}; + const QMetaObject::Connection connection = connect(this, &FramelessWidgetsHelper::ready, &loop, &QEventLoop::quit); + loop.exec(); + disconnect(connection); +#else + while (!d->qpaReady) { + QCoreApplication::processEvents(); + } +#endif } -void FramelessWidgetsHelper::extendsContentIntoTitleBar(const bool value) +bool FramelessWidgetsHelper::isContentExtendedIntoTitleBar() const { - Q_D(FramelessWidgetsHelper); - d->extendsContentIntoTitleBar(value); + Q_D(const FramelessWidgetsHelper); + const FramelessWidgetsHelperData *data = d->getWindowData(); + return (data ? data->ready : false); } void FramelessWidgetsHelper::setTitleBarWidget(QWidget *widget) @@ -996,18 +875,19 @@ void FramelessWidgetsHelper::setTitleBarWidget(QWidget *widget) return; } Q_D(FramelessWidgetsHelper); - d->setTitleBarWidget(widget); + FramelessWidgetsHelperData *data = d->getWindowDataMutable(); + if (!data || (data->titleBarWidget == widget)) { + return; + } + data->titleBarWidget = widget; + d->emitSignalForAllInstances("titleBarWidgetChanged"); } -void FramelessWidgetsHelper::setSystemButton(QWidget *widget, const SystemButtonType buttonType) +QWidget *FramelessWidgetsHelper::titleBarWidget() const { - Q_ASSERT(widget); - Q_ASSERT(buttonType != SystemButtonType::Unknown); - if (!widget || (buttonType == SystemButtonType::Unknown)) { - return; - } - Q_D(FramelessWidgetsHelper); - d->setSystemButton(widget, buttonType); + Q_D(const FramelessWidgetsHelper); + const FramelessWidgetsHelperData *data = d->getWindowData(); + return (data ? data->titleBarWidget : nullptr); } void FramelessWidgetsHelper::setHitTestVisible(QWidget *widget, const bool visible) @@ -1017,7 +897,15 @@ void FramelessWidgetsHelper::setHitTestVisible(QWidget *widget, const bool visib return; } Q_D(FramelessWidgetsHelper); - d->setHitTestVisible(widget, visible); + FramelessWidgetsHelperData *data = d->getWindowDataMutable(); + if (!data) { + return; + } + if (visible) { + data->hitTestVisibleWidgets.append(widget); + } else { + data->hitTestVisibleWidgets.removeAll(widget); + } } void FramelessWidgetsHelper::setHitTestVisible(const QRect &rect, const bool visible) @@ -1027,7 +915,15 @@ void FramelessWidgetsHelper::setHitTestVisible(const QRect &rect, const bool vis return; } Q_D(FramelessWidgetsHelper); - d->setHitTestVisible(rect, visible); + FramelessWidgetsHelperData *data = d->getWindowDataMutable(); + if (!data) { + return; + } + if (visible) { + data->hitTestVisibleRects.append(rect); + } else { + data->hitTestVisibleRects.removeAll(rect); + } } void FramelessWidgetsHelper::setHitTestVisible(QObject *object, const bool visible) @@ -1036,53 +932,26 @@ void FramelessWidgetsHelper::setHitTestVisible(QObject *object, const bool visib if (!object) { return; } - Q_D(FramelessWidgetsHelper); - d->setHitTestVisible(object, visible); -} - -void FramelessWidgetsHelper::showSystemMenu(const QPoint &pos) -{ - Q_D(FramelessWidgetsHelper); - d->showSystemMenu(pos); -} - -void FramelessWidgetsHelper::windowStartSystemMove2(const QPoint &pos) -{ - Q_D(FramelessWidgetsHelper); - d->windowStartSystemMove2(pos); -} - -void FramelessWidgetsHelper::windowStartSystemResize2(const Qt::Edges edges, const QPoint &pos) -{ - if (edges == Qt::Edges{}) { + const auto widget = qobject_cast(object); + Q_ASSERT(widget); + if (!widget) { return; } - Q_D(FramelessWidgetsHelper); - d->windowStartSystemResize2(edges, pos); -} - -void FramelessWidgetsHelper::moveWindowToDesktopCenter() -{ - Q_D(FramelessWidgetsHelper); - d->moveWindowToDesktopCenter(); -} - -void FramelessWidgetsHelper::bringWindowToFront() -{ - Q_D(FramelessWidgetsHelper); - d->bringWindowToFront(); -} - -void FramelessWidgetsHelper::setWindowFixedSize(const bool value) -{ - Q_D(FramelessWidgetsHelper); - d->setWindowFixedSize(value); + setHitTestVisible(widget, visible); } -void FramelessWidgetsHelper::setBlurBehindWindowEnabled(const bool value) +void FramelessWidgetsHelper::extendsContentIntoTitleBar(const bool value) { + if (isContentExtendedIntoTitleBar() == value) { + return; + } Q_D(FramelessWidgetsHelper); - d->setBlurBehindWindowEnabled(value, {}); + if (value) { + d->attach(); + } else { + d->detach(); + } + d->emitSignalForAllInstances("extendsContentIntoTitleBarChanged"); } FRAMELESSHELPER_END_NAMESPACE diff --git a/src/widgets/standardsystembutton.cpp b/src/widgets/standardsystembutton.cpp index 95e0141d..a7d4991f 100644 --- a/src/widgets/standardsystembutton.cpp +++ b/src/widgets/standardsystembutton.cpp @@ -56,7 +56,6 @@ StandardSystemButtonPrivate::StandardSystemButtonPrivate(StandardSystemButton *q return; } q_ptr = q; - initialize(); } StandardSystemButtonPrivate::~StandardSystemButtonPrivate() = default; @@ -79,173 +78,206 @@ const StandardSystemButtonPrivate *StandardSystemButtonPrivate::get(const Standa return pub->d_func(); } -QString StandardSystemButtonPrivate::getGlyph() const +QSize StandardSystemButtonPrivate::getRecommendedButtonSize() { - return m_glyph; + return kDefaultSystemButtonSize; +} + +StandardSystemButton::StandardSystemButton(QWidget *parent) + : QPushButton(parent), d_ptr(new StandardSystemButtonPrivate(this)) +{ + FramelessManagerPrivate::initializeIconFont(); + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + setFixedSize(StandardSystemButtonPrivate::getRecommendedButtonSize()); + setIconSize(kDefaultSystemButtonIconSize); + setMouseTracking(true); + setAttribute(Qt::WA_Hover); +} + +StandardSystemButton::StandardSystemButton(const SystemButtonType type, QWidget *parent) + : StandardSystemButton(parent) +{ + setButtonType(type); +} + +StandardSystemButton::~StandardSystemButton() = default; + +QSize StandardSystemButton::sizeHint() const +{ + return StandardSystemButtonPrivate::getRecommendedButtonSize(); +} + +QString StandardSystemButton::glyph() const +{ + Q_D(const StandardSystemButton); + return d->glyph; } -void StandardSystemButtonPrivate::setGlyph(const QString &value) +void StandardSystemButton::setGlyph(const QString &value) { Q_ASSERT(!value.isEmpty()); if (value.isEmpty()) { return; } - if (m_glyph == value) { + Q_D(StandardSystemButton); + if (d->glyph == value) { return; } - m_glyph = value; - Q_Q(StandardSystemButton); - q->update(); - Q_EMIT q->glyphChanged(); + d->glyph = value; + update(); + Q_EMIT glyphChanged(); } -SystemButtonType StandardSystemButtonPrivate::getButtonType() const +SystemButtonType StandardSystemButton::buttonType() const { - return m_buttonType; + Q_D(const StandardSystemButton); + return d->buttonType; } -void StandardSystemButtonPrivate::setButtonType(const SystemButtonType type) +void StandardSystemButton::setButtonType(const SystemButtonType type) { Q_ASSERT(type != SystemButtonType::Unknown); if (type == SystemButtonType::Unknown) { return; } - if (m_buttonType == type) { + Q_D(StandardSystemButton); + if (d->buttonType == type) { return; } - m_buttonType = type; - setGlyph(Utils::getSystemButtonGlyph(m_buttonType)); - Q_Q(StandardSystemButton); - q->update(); + d->buttonType = type; + setGlyph(Utils::getSystemButtonGlyph(d->buttonType)); + update(); } -QSize StandardSystemButtonPrivate::getRecommendedButtonSize() const -{ - return kDefaultSystemButtonSize; -} - -QColor StandardSystemButtonPrivate::getHoverColor() const +QColor StandardSystemButton::hoverColor() const { - return m_hoverColor; + Q_D(const StandardSystemButton); + return d->hoverColor; } -QColor StandardSystemButtonPrivate::getPressColor() const +QColor StandardSystemButton::pressColor() const { - return m_pressColor; + Q_D(const StandardSystemButton); + return d->pressColor; } -QColor StandardSystemButtonPrivate::getNormalColor() const +QColor StandardSystemButton::normalColor() const { - return m_normalColor; + Q_D(const StandardSystemButton); + return d->normalColor; } -QColor StandardSystemButtonPrivate::getActiveForegroundColor() const +QColor StandardSystemButton::activeForegroundColor() const { - return m_activeForegroundColor; + Q_D(const StandardSystemButton); + return d->activeForegroundColor; } -QColor StandardSystemButtonPrivate::getInactiveForegroundColor() const +QColor StandardSystemButton::inactiveForegroundColor() const { - return m_inactiveForegroundColor; + Q_D(const StandardSystemButton); + return d->inactiveForegroundColor; } -bool StandardSystemButtonPrivate::isActive() const +bool StandardSystemButton::isActive() const { - return m_active; + Q_D(const StandardSystemButton); + return d->active; } -int StandardSystemButtonPrivate::glyphSize() const +int StandardSystemButton::glyphSize() const { - return m_glyphSize.value_or(FramelessManagerPrivate::getIconFont().pointSize()); + Q_D(const StandardSystemButton); + return d->glyphSize.value_or(FramelessManagerPrivate::getIconFont().pointSize()); } -void StandardSystemButtonPrivate::setHoverColor(const QColor &value) +void StandardSystemButton::setHoverColor(const QColor &value) { Q_ASSERT(value.isValid()); if (!value.isValid()) { return; } - if (m_hoverColor == value) { + Q_D(StandardSystemButton); + if (d->hoverColor == value) { return; } - m_hoverColor = value; - Q_Q(StandardSystemButton); - q->update(); - Q_EMIT q->hoverColorChanged(); + d->hoverColor = value; + update(); + Q_EMIT hoverColorChanged(); } -void StandardSystemButtonPrivate::setPressColor(const QColor &value) +void StandardSystemButton::setPressColor(const QColor &value) { Q_ASSERT(value.isValid()); if (!value.isValid()) { return; } - if (m_pressColor == value) { + Q_D(StandardSystemButton); + if (d->pressColor == value) { return; } - m_pressColor = value; - Q_Q(StandardSystemButton); - q->update(); - Q_EMIT q->pressColorChanged(); + d->pressColor = value; + update(); + Q_EMIT pressColorChanged(); } -void StandardSystemButtonPrivate::setNormalColor(const QColor &value) +void StandardSystemButton::setNormalColor(const QColor &value) { Q_ASSERT(value.isValid()); if (!value.isValid()) { return; } - if (m_normalColor == value) { + Q_D(StandardSystemButton); + if (d->normalColor == value) { return; } - m_normalColor = value; - Q_Q(StandardSystemButton); - q->update(); - Q_EMIT q->normalColorChanged(); + d->normalColor = value; + update(); + Q_EMIT normalColorChanged(); } -void StandardSystemButtonPrivate::setActiveForegroundColor(const QColor &value) +void StandardSystemButton::setActiveForegroundColor(const QColor &value) { Q_ASSERT(value.isValid()); if (!value.isValid()) { return; } - if (m_activeForegroundColor == value) { + Q_D(StandardSystemButton); + if (d->activeForegroundColor == value) { return; } - m_activeForegroundColor = value; - Q_Q(StandardSystemButton); - q->update(); - Q_EMIT q->activeForegroundColorChanged(); + d->activeForegroundColor = value; + update(); + Q_EMIT activeForegroundColorChanged(); } -void StandardSystemButtonPrivate::setInactiveForegroundColor(const QColor &value) +void StandardSystemButton::setInactiveForegroundColor(const QColor &value) { Q_ASSERT(value.isValid()); if (!value.isValid()) { return; } - if (m_inactiveForegroundColor == value) { + Q_D(StandardSystemButton); + if (d->inactiveForegroundColor == value) { return; } - m_inactiveForegroundColor = value; - Q_Q(StandardSystemButton); - q->update(); - Q_EMIT q->inactiveForegroundColorChanged(); + d->inactiveForegroundColor = value; + update(); + Q_EMIT inactiveForegroundColorChanged(); } -void StandardSystemButtonPrivate::setActive(const bool value) +void StandardSystemButton::setActive(const bool value) { - if (m_active == value) { + Q_D(StandardSystemButton); + if (d->active == value) { return; } - m_active = value; - Q_Q(StandardSystemButton); - q->update(); - Q_EMIT q->activeChanged(); + d->active = value; + update(); + Q_EMIT activeChanged(); } -void StandardSystemButtonPrivate::setGlyphSize(const int value) +void StandardSystemButton::setGlyphSize(const int value) { Q_ASSERT(value > 0); if (value <= 0) { @@ -254,205 +286,61 @@ void StandardSystemButtonPrivate::setGlyphSize(const int value) if (glyphSize() == value) { return; } - m_glyphSize = value; - Q_Q(StandardSystemButton); - q->update(); - Q_EMIT q->glyphSizeChanged(); + Q_D(StandardSystemButton); + d->glyphSize = value; + update(); + Q_EMIT glyphSizeChanged(); } -void StandardSystemButtonPrivate::paintEventHandler(QPaintEvent *event) +void StandardSystemButton::paintEvent(QPaintEvent *event) { Q_ASSERT(event); if (!event) { return; } - Q_Q(StandardSystemButton); - QPainter painter(q); + Q_D(StandardSystemButton); + QPainter painter(this); painter.save(); painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); - const auto backgroundColor = [this, q]() -> QColor { + const auto backgroundColor = [this, d]() -> QColor { // The pressed state has higher priority than the hovered state. - if (q->isDown() && m_pressColor.isValid()) { - return m_pressColor; + if (isDown() && d->pressColor.isValid()) { + return d->pressColor; } - if (q->underMouse() && m_hoverColor.isValid()) { - return m_hoverColor; + if (underMouse() && d->hoverColor.isValid()) { + return d->hoverColor; } - if (m_normalColor.isValid()) { - return m_normalColor; + if (d->normalColor.isValid()) { + return d->normalColor; } return {}; }(); - const QRect buttonRect = {QPoint(0, 0), q->size()}; + const QRect buttonRect = {QPoint(0, 0), size()}; if (backgroundColor.isValid()) { painter.fillRect(buttonRect, backgroundColor); } - if (!m_glyph.isEmpty()) { - painter.setPen([this, q]() -> QColor { - if (!q->underMouse() && !m_active && m_inactiveForegroundColor.isValid()) { - return m_inactiveForegroundColor; + if (!d->glyph.isEmpty()) { + painter.setPen([this, d]() -> QColor { + if (!underMouse() && !d->active && d->inactiveForegroundColor.isValid()) { + return d->inactiveForegroundColor; } - if (m_activeForegroundColor.isValid()) { - return m_activeForegroundColor; + if (d->activeForegroundColor.isValid()) { + return d->activeForegroundColor; } return kDefaultBlackColor; }()); - painter.setFont([this]() -> QFont { + painter.setFont([d]() -> QFont { QFont font = FramelessManagerPrivate::getIconFont(); - if (m_glyphSize.has_value()) { - font.setPointSize(m_glyphSize.value()); + if (d->glyphSize.has_value()) { + font.setPointSize(d->glyphSize.value()); } return font; }()); - painter.drawText(buttonRect, Qt::AlignCenter, m_glyph); + painter.drawText(buttonRect, Qt::AlignCenter, d->glyph); } painter.restore(); event->accept(); } -void StandardSystemButtonPrivate::initialize() -{ - FramelessManagerPrivate::initializeIconFont(); - Q_Q(StandardSystemButton); - q->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - q->setFixedSize(getRecommendedButtonSize()); - q->setIconSize(kDefaultSystemButtonIconSize); - q->setMouseTracking(true); - q->setAttribute(Qt::WA_Hover); -} - -StandardSystemButton::StandardSystemButton(QWidget *parent) - : QPushButton(parent), d_ptr(new StandardSystemButtonPrivate(this)) -{ -} - -StandardSystemButton::StandardSystemButton(const SystemButtonType type, QWidget *parent) - : StandardSystemButton(parent) -{ - setButtonType(type); -} - -StandardSystemButton::~StandardSystemButton() = default; - -QSize StandardSystemButton::sizeHint() const -{ - Q_D(const StandardSystemButton); - return d->getRecommendedButtonSize(); -} - -SystemButtonType StandardSystemButton::buttonType() -{ - Q_D(const StandardSystemButton); - return d->getButtonType(); -} - -QString StandardSystemButton::glyph() const -{ - Q_D(const StandardSystemButton); - return d->getGlyph(); -} - -void StandardSystemButton::setButtonType(const SystemButtonType value) -{ - Q_D(StandardSystemButton); - d->setButtonType(value); -} - -void StandardSystemButton::setGlyph(const QString &glyph) -{ - Q_D(StandardSystemButton); - d->setGlyph(glyph); -} - -QColor StandardSystemButton::hoverColor() const -{ - Q_D(const StandardSystemButton); - return d->getHoverColor(); -} - -void StandardSystemButton::setHoverColor(const QColor &value) -{ - Q_D(StandardSystemButton); - d->setHoverColor(value); -} - -QColor StandardSystemButton::pressColor() const -{ - Q_D(const StandardSystemButton); - return d->getPressColor(); -} - -QColor StandardSystemButton::normalColor() const -{ - Q_D(const StandardSystemButton); - return d->getNormalColor(); -} - -QColor StandardSystemButton::activeForegroundColor() const -{ - Q_D(const StandardSystemButton); - return d->getActiveForegroundColor(); -} - -QColor StandardSystemButton::inactiveForegroundColor() const -{ - Q_D(const StandardSystemButton); - return d->getInactiveForegroundColor(); -} - -bool StandardSystemButton::isActive() const -{ - Q_D(const StandardSystemButton); - return d->isActive(); -} - -int StandardSystemButton::glyphSize() const -{ - Q_D(const StandardSystemButton); - return d->glyphSize(); -} - -void StandardSystemButton::setPressColor(const QColor &value) -{ - Q_D(StandardSystemButton); - d->setPressColor(value); -} - -void StandardSystemButton::setNormalColor(const QColor &value) -{ - Q_D(StandardSystemButton); - d->setNormalColor(value); -} - -void StandardSystemButton::setActiveForegroundColor(const QColor &value) -{ - Q_D(StandardSystemButton); - d->setActiveForegroundColor(value); -} - -void StandardSystemButton::setInactiveForegroundColor(const QColor &value) -{ - Q_D(StandardSystemButton); - d->setInactiveForegroundColor(value); -} - -void StandardSystemButton::setActive(const bool value) -{ - Q_D(StandardSystemButton); - d->setActive(value); -} - -void StandardSystemButton::setGlyphSize(const int value) -{ - Q_D(StandardSystemButton); - d->setGlyphSize(value); -} - -void StandardSystemButton::paintEvent(QPaintEvent *event) -{ - Q_D(StandardSystemButton); - d->paintEventHandler(event); -} - FRAMELESSHELPER_END_NAMESPACE diff --git a/src/widgets/standardtitlebar.cpp b/src/widgets/standardtitlebar.cpp index 17222def..e11c75aa 100644 --- a/src/widgets/standardtitlebar.cpp +++ b/src/widgets/standardtitlebar.cpp @@ -83,58 +83,6 @@ const StandardTitleBarPrivate *StandardTitleBarPrivate::get(const StandardTitleB return pub->d_func(); } -Qt::Alignment StandardTitleBarPrivate::titleLabelAlignment() const -{ - return m_labelAlignment; -} - -void StandardTitleBarPrivate::setTitleLabelAlignment(const Qt::Alignment value) -{ - if (m_labelAlignment == value) { - return; - } - m_labelAlignment = value; - Q_Q(StandardTitleBar); - q->update(); - Q_EMIT q->titleLabelAlignmentChanged(); -} - -bool StandardTitleBarPrivate::isExtended() const -{ - return m_extended; -} - -void StandardTitleBarPrivate::setExtended(const bool value) -{ - if (m_extended == value) { - return; - } - m_extended = value; - Q_Q(StandardTitleBar); - q->setFixedHeight(m_extended ? kDefaultExtendedTitleBarHeight : kDefaultTitleBarHeight); - Q_EMIT q->extendedChanged(); -} - -bool StandardTitleBarPrivate::isHideWhenClose() const -{ - return m_hideWhenClose; -} - -void StandardTitleBarPrivate::setHideWhenClose(const bool value) -{ - if (m_hideWhenClose == value) { - return; - } - m_hideWhenClose = value; - Q_Q(StandardTitleBar); - Q_EMIT q->hideWhenCloseChanged(); -} - -ChromePalette *StandardTitleBarPrivate::chromePalette() const -{ - return m_chromePalette; -} - QFont StandardTitleBarPrivate::defaultFont() const { Q_Q(const StandardTitleBar); @@ -145,14 +93,14 @@ QFont StandardTitleBarPrivate::defaultFont() const StandardTitleBarPrivate::FontMetrics StandardTitleBarPrivate::titleLabelSize() const { - if (!m_window) { + if (!window) { return {}; } - const QString text = m_window->windowTitle(); + const QString text = window->windowTitle(); if (text.isEmpty()) { return {}; } - const QFont font = m_titleFont.value_or(defaultFont()); + const QFont font = titleFont.value_or(defaultFont()); const QFontMetrics fontMetrics(font); return { /* .width */ Utils::horizontalAdvance(fontMetrics, text), @@ -161,143 +109,6 @@ StandardTitleBarPrivate::FontMetrics StandardTitleBarPrivate::titleLabelSize() c }; } -void StandardTitleBarPrivate::paintTitleBar(QPaintEvent *event) -{ - Q_ASSERT(event); - if (!event) { - return; - } - Q_Q(StandardTitleBar); - if (!m_window || !m_chromePalette) { - return; - } - const bool active = m_window->isActiveWindow(); - const QColor backgroundColor = (active ? - m_chromePalette->titleBarActiveBackgroundColor() : - m_chromePalette->titleBarInactiveBackgroundColor()); - const QColor foregroundColor = (active ? - m_chromePalette->titleBarActiveForegroundColor() : - m_chromePalette->titleBarInactiveForegroundColor()); - QPainter painter(q); - painter.save(); - painter.setRenderHints(QPainter::Antialiasing | - QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); - painter.fillRect(QRect(QPoint(0, 0), q->size()), backgroundColor); - if (m_titleLabelVisible) { - const QString text = m_window->windowTitle(); - if (!text.isEmpty()) { - painter.setPen(foregroundColor); - painter.setFont(m_titleFont.value_or(defaultFont())); - const auto pos = [this, q]() -> QPoint { - const FontMetrics labelSize = titleLabelSize(); - const int titleBarWidth = q->width(); - int x = 0; - if (m_labelAlignment & Qt::AlignLeft) { - x = (windowIconRect().right() + kDefaultTitleBarContentsMargin); - } else if (m_labelAlignment & Qt::AlignRight) { - x = (titleBarWidth - kDefaultTitleBarContentsMargin - labelSize.width); -#ifndef Q_OS_MACOS - x -= (titleBarWidth - m_minimizeButton->x()); -#endif // Q_OS_MACOS - } else if (m_labelAlignment & Qt::AlignHCenter) { - x = std::round(qreal(titleBarWidth - labelSize.width) / qreal(2)); - } else { - WARNING << "The alignment for the title label is not set!"; - } - const int y = std::round((qreal(q->height() - labelSize.height) / qreal(2)) + qreal(labelSize.ascent)); - return {x, y}; - }(); - painter.drawText(pos, text); - } - } - if (m_windowIconVisible) { - const QIcon icon = m_window->windowIcon(); - if (!icon.isNull()) { - icon.paint(&painter, windowIconRect()); - } - } - painter.restore(); - event->accept(); -} - -bool StandardTitleBarPrivate::titleLabelVisible() const -{ - return m_titleLabelVisible; -} - -void StandardTitleBarPrivate::setTitleLabelVisible(const bool value) -{ - if (m_titleLabelVisible == value) { - return; - } - m_titleLabelVisible = value; - Q_Q(StandardTitleBar); - q->update(); - Q_EMIT q->titleLabelVisibleChanged(); -} - -QSize StandardTitleBarPrivate::windowIconSize() const -{ - return m_windowIconSize.value_or(kDefaultWindowIconSize); -} - -void StandardTitleBarPrivate::setWindowIconSize(const QSize &value) -{ - Q_ASSERT(!value.isEmpty()); - if (value.isEmpty()) { - return; - } - if (windowIconSize() == value) { - return; - } - m_windowIconSize = value; - Q_Q(StandardTitleBar); - q->update(); - Q_EMIT q->windowIconSizeChanged(); -} - -bool StandardTitleBarPrivate::windowIconVisible() const -{ - return m_windowIconVisible; -} - -void StandardTitleBarPrivate::setWindowIconVisible(const bool value) -{ - if (m_windowIconVisible == value) { - return; - } - m_windowIconVisible = value; - Q_Q(StandardTitleBar); - q->update(); - Q_EMIT q->windowIconVisibleChanged(); -#ifndef Q_OS_MACOS - // Ideally we should use FramelessWidgetsHelper::get(this) everywhere, but sadly when - // we call it here, it may be too early that FramelessWidgetsHelper has not attached - // to the top level widget yet, and thus it will trigger an assert error (the assert - // should not be suppressed, because it usually indicates there's something really - // wrong). So here we have to use the top level widget directly, as a special case. - // NOTE: In your own code, you should always use FramelessWidgetsHelper::get(this) - // if possible. - FramelessWidgetsHelper::get(m_window)->setHitTestVisible(windowIconRect(), windowIconVisible_real()); -#endif // Q_OS_MACOS -} - -QFont StandardTitleBarPrivate::titleFont() const -{ - return m_titleFont.value_or(QFont()); -} - -void StandardTitleBarPrivate::setTitleFont(const QFont &value) -{ - if (titleFont() == value) { - return; - } - m_titleFont = value; - Q_Q(StandardTitleBar); - q->update(); - Q_EMIT q->titleFontChanged(); -} - bool StandardTitleBarPrivate::mouseEventHandler(QMouseEvent *event) { #ifdef Q_OS_MACOS @@ -319,7 +130,7 @@ bool StandardTitleBarPrivate::mouseEventHandler(QMouseEvent *event) switch (event->type()) { case QEvent::MouseButtonRelease: // We need a valid top level widget here. - if (m_window && interestArea) { + if (window && interestArea) { // Sadly the mouse release events are always triggered before the // mouse double click events, and if we intercept the mouse release // events here, we'll never get the double click events afterwards, @@ -339,16 +150,16 @@ bool StandardTitleBarPrivate::mouseEventHandler(QMouseEvent *event) // The close event is already triggered, don't try to show the // system menu anymore, otherwise it will prevent our window // from closing. - if (m_closeTriggered) { + if (closeTriggered) { return; } // Please refer to the comments in StandardTitleBarPrivate::setWindowIconVisible(). - FramelessWidgetsHelper::get(m_window)->showSystemMenu([button, q, &scenePos, this]() -> QPoint { + FramelessWidgetsHelper::get(window)->showSystemMenu([button, q, &scenePos, this]() -> QPoint { QPoint pos = scenePos; if (button == Qt::LeftButton) { pos = {0, q->height()}; } - return m_window->mapToGlobal(pos); + return window->mapToGlobal(pos); }()); }); // Don't eat this event, we have not handled it yet. @@ -356,9 +167,9 @@ bool StandardTitleBarPrivate::mouseEventHandler(QMouseEvent *event) break; case QEvent::MouseButtonDblClick: // We need a valid top level widget here. - if (m_window && (button == Qt::LeftButton) && interestArea) { - m_closeTriggered = true; - m_window->close(); + if (window && (button == Qt::LeftButton) && interestArea) { + closeTriggered = true; + window->close(); // Eat this event, we have handled it here. event->accept(); return true; @@ -377,21 +188,21 @@ QRect StandardTitleBarPrivate::windowIconRect() const if (!windowIconVisible_real()) { return {}; } - const QSize size = windowIconSize(); + const QSize size = q->windowIconSize(); #ifdef Q_OS_MACOS const auto x = [this, q, &size]() -> int { - if (m_labelAlignment & Qt::AlignLeft) { + if (labelAlignment & Qt::AlignLeft) { return (kMacOSChromeButtonAreaWidth + kDefaultTitleBarContentsMargin); } const int titleBarWidth = q->width(); const int labelWidth = titleLabelSize().width; - if (m_labelAlignment & Qt::AlignRight) { + if (labelAlignment & Qt::AlignRight) { // We need two spacer here, one is on the right edge of the title bar, // the other one is between the window icon and the window label. return (titleBarWidth - kDefaultTitleBarContentsMargin - labelWidth - kDefaultTitleBarContentsMargin - size.width()); } - if (m_labelAlignment & Qt::AlignHCenter) { + if (labelAlignment & Qt::AlignHCenter) { const int centeredX = std::round(qreal(titleBarWidth - labelWidth) / qreal(2)); return (centeredX - kDefaultTitleBarContentsMargin - size.width()); } @@ -407,7 +218,7 @@ QRect StandardTitleBarPrivate::windowIconRect() const bool StandardTitleBarPrivate::windowIconVisible_real() const { - return (m_windowIconVisible && !m_window->windowIcon().isNull()); + return (windowIconVisible && !window->windowIcon().isNull()); } bool StandardTitleBarPrivate::isInTitleBarIconArea(const QPoint &pos) const @@ -421,9 +232,9 @@ bool StandardTitleBarPrivate::isInTitleBarIconArea(const QPoint &pos) const void StandardTitleBarPrivate::updateMaximizeButton() { #ifndef Q_OS_MACOS - const bool max = m_window->isMaximized(); - m_maximizeButton->setButtonType(max ? SystemButtonType::Restore : SystemButtonType::Maximize); - m_maximizeButton->setToolTip(max ? tr("Restore") : tr("Maximize")); + const bool max = window->isMaximized(); + maximizeButton->setButtonType(max ? SystemButtonType::Restore : SystemButtonType::Maximize); + maximizeButton->setToolTip(max ? tr("Restore") : tr("Maximize")); #endif // Q_OS_MACOS } @@ -436,39 +247,39 @@ void StandardTitleBarPrivate::updateTitleBarColor() void StandardTitleBarPrivate::updateChromeButtonColor() { #ifndef Q_OS_MACOS - const bool active = m_window->isActiveWindow(); - const QColor activeForeground = m_chromePalette->titleBarActiveForegroundColor(); - const QColor inactiveForeground = m_chromePalette->titleBarInactiveForegroundColor(); - const QColor normal = m_chromePalette->chromeButtonNormalColor(); - const QColor hover = m_chromePalette->chromeButtonHoverColor(); - const QColor press = m_chromePalette->chromeButtonPressColor(); - m_minimizeButton->setActiveForegroundColor(activeForeground); - m_minimizeButton->setInactiveForegroundColor(inactiveForeground); - m_minimizeButton->setNormalColor(normal); - m_minimizeButton->setHoverColor(hover); - m_minimizeButton->setPressColor(press); - m_minimizeButton->setActive(active); - m_maximizeButton->setActiveForegroundColor(activeForeground); - m_maximizeButton->setInactiveForegroundColor(inactiveForeground); - m_maximizeButton->setNormalColor(normal); - m_maximizeButton->setHoverColor(hover); - m_maximizeButton->setPressColor(press); - m_maximizeButton->setActive(active); - m_closeButton->setActiveForegroundColor(activeForeground); - m_closeButton->setInactiveForegroundColor(inactiveForeground); - m_closeButton->setNormalColor(m_chromePalette->closeButtonNormalColor()); - m_closeButton->setHoverColor(m_chromePalette->closeButtonHoverColor()); - m_closeButton->setPressColor(m_chromePalette->closeButtonPressColor()); - m_closeButton->setActive(active); + const bool active = window->isActiveWindow(); + const QColor activeForeground = chromePalette->titleBarActiveForegroundColor(); + const QColor inactiveForeground = chromePalette->titleBarInactiveForegroundColor(); + const QColor normal = chromePalette->chromeButtonNormalColor(); + const QColor hover = chromePalette->chromeButtonHoverColor(); + const QColor press = chromePalette->chromeButtonPressColor(); + minimizeButton->setActiveForegroundColor(activeForeground); + minimizeButton->setInactiveForegroundColor(inactiveForeground); + minimizeButton->setNormalColor(normal); + minimizeButton->setHoverColor(hover); + minimizeButton->setPressColor(press); + minimizeButton->setActive(active); + maximizeButton->setActiveForegroundColor(activeForeground); + maximizeButton->setInactiveForegroundColor(inactiveForeground); + maximizeButton->setNormalColor(normal); + maximizeButton->setHoverColor(hover); + maximizeButton->setPressColor(press); + maximizeButton->setActive(active); + closeButton->setActiveForegroundColor(activeForeground); + closeButton->setInactiveForegroundColor(inactiveForeground); + closeButton->setNormalColor(chromePalette->closeButtonNormalColor()); + closeButton->setHoverColor(chromePalette->closeButtonHoverColor()); + closeButton->setPressColor(chromePalette->closeButtonPressColor()); + closeButton->setActive(active); #endif // Q_OS_MACOS } void StandardTitleBarPrivate::retranslateUi() { #ifndef Q_OS_MACOS - m_minimizeButton->setToolTip(tr("Minimize")); - m_maximizeButton->setToolTip(m_window->isMaximized() ? tr("Restore") : tr("Maximize")); - m_closeButton->setToolTip(tr("Close")); + minimizeButton->setToolTip(tr("Minimize")); + maximizeButton->setToolTip(window->isMaximized() ? tr("Restore") : tr("Maximize")); + closeButton->setToolTip(tr("Close")); #endif // Q_OS_MACOS } @@ -483,17 +294,17 @@ bool StandardTitleBarPrivate::eventFilter(QObject *object, QEvent *event) return QObject::eventFilter(object, event); } const auto widget = qobject_cast(object); - if (!widget->isWindow() || (widget != m_window)) { + if (!widget->isWindow() || (widget != window)) { return QObject::eventFilter(object, event); } switch (event->type()) { case QEvent::WindowStateChange: updateMaximizeButton(); break; - case QEvent::ActivationChange: + case QEvent::ActivationChange: { updateTitleBarColor(); updateChromeButtonColor(); - break; + } break; case QEvent::LanguageChange: retranslateUi(); break; @@ -506,19 +317,19 @@ bool StandardTitleBarPrivate::eventFilter(QObject *object, QEvent *event) void StandardTitleBarPrivate::initialize() { Q_Q(StandardTitleBar); - m_window = q->window(); - m_chromePalette = new ChromePalette(this); - connect(m_chromePalette, &ChromePalette::titleBarColorChanged, + window = q->window(); + chromePalette = new ChromePalette(this); + connect(chromePalette, &ChromePalette::titleBarColorChanged, this, &StandardTitleBarPrivate::updateTitleBarColor); - connect(m_chromePalette, &ChromePalette::chromeButtonColorChanged, + connect(chromePalette, &ChromePalette::chromeButtonColorChanged, this, &StandardTitleBarPrivate::updateChromeButtonColor); q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); q->setFixedHeight(kDefaultTitleBarHeight); - connect(m_window, &QWidget::windowIconChanged, this, [q](const QIcon &icon){ + connect(window, &QWidget::windowIconChanged, this, [q](const QIcon &icon){ Q_UNUSED(icon); q->update(); }); - connect(m_window, &QWidget::windowTitleChanged, this, [q](const QString &title){ + connect(window, &QWidget::windowTitleChanged, this, [q](const QString &title){ Q_UNUSED(title); q->update(); }); @@ -526,26 +337,25 @@ void StandardTitleBarPrivate::initialize() const auto titleBarLayout = new QHBoxLayout(q); titleBarLayout->setSpacing(0); titleBarLayout->setContentsMargins(0, 0, 0, 0); - q->setLayout(titleBarLayout); - setTitleLabelAlignment(Qt::AlignCenter); + q->setTitleLabelAlignment(Qt::AlignCenter); #else // !Q_OS_MACOS - m_minimizeButton = new StandardSystemButton(SystemButtonType::Minimize, q); - connect(m_minimizeButton, &StandardSystemButton::clicked, m_window, &QWidget::showMinimized); - m_maximizeButton = new StandardSystemButton(SystemButtonType::Maximize, q); + minimizeButton = new StandardSystemButton(SystemButtonType::Minimize, q); + connect(minimizeButton, &StandardSystemButton::clicked, window, &QWidget::showMinimized); + maximizeButton = new StandardSystemButton(SystemButtonType::Maximize, q); updateMaximizeButton(); - connect(m_maximizeButton, &StandardSystemButton::clicked, this, [this](){ - if (m_window->isMaximized()) { - m_window->showNormal(); + connect(maximizeButton, &StandardSystemButton::clicked, this, [this](){ + if (window->isMaximized()) { + window->showNormal(); } else { - m_window->showMaximized(); + window->showMaximized(); } }); - m_closeButton = new StandardSystemButton(SystemButtonType::Close, q); - connect(m_closeButton, &StandardSystemButton::clicked, this, [this](){ - if (m_hideWhenClose) { - m_window->hide(); + closeButton = new StandardSystemButton(SystemButtonType::Close, q); + connect(closeButton, &StandardSystemButton::clicked, this, [this](){ + if (hideWhenClose) { + window->hide(); } else { - m_window->close(); + window->close(); } }); // According to the title bar design guidance, the system buttons should always be @@ -554,9 +364,9 @@ void StandardTitleBarPrivate::initialize() const auto systemButtonsInnerLayout = new QHBoxLayout; systemButtonsInnerLayout->setSpacing(0); systemButtonsInnerLayout->setContentsMargins(0, 0, 0, 0); - systemButtonsInnerLayout->addWidget(m_minimizeButton); - systemButtonsInnerLayout->addWidget(m_maximizeButton); - systemButtonsInnerLayout->addWidget(m_closeButton); + systemButtonsInnerLayout->addWidget(minimizeButton); + systemButtonsInnerLayout->addWidget(maximizeButton); + systemButtonsInnerLayout->addWidget(closeButton); const auto systemButtonsOuterLayout = new QVBoxLayout; systemButtonsOuterLayout->setSpacing(0); systemButtonsOuterLayout->setContentsMargins(0, 0, 0, 0); @@ -567,13 +377,12 @@ void StandardTitleBarPrivate::initialize() titleBarLayout->setContentsMargins(0, 0, 0, 0); titleBarLayout->addStretch(); titleBarLayout->addLayout(systemButtonsOuterLayout); - q->setLayout(titleBarLayout); - setTitleLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter); + q->setTitleLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter); #endif // Q_OS_MACOS retranslateUi(); updateTitleBarColor(); updateChromeButtonColor(); - m_window->installEventFilter(this); + window->installEventFilter(this); } StandardTitleBar::StandardTitleBar(QWidget *parent) @@ -583,134 +392,235 @@ StandardTitleBar::StandardTitleBar(QWidget *parent) StandardTitleBar::~StandardTitleBar() = default; -Qt::Alignment StandardTitleBar::titleLabelAlignment() const +#ifndef Q_OS_MACOS +StandardSystemButton *StandardTitleBar::minimizeButton() const { Q_D(const StandardTitleBar); - return d->titleLabelAlignment(); + return d->minimizeButton; } -void StandardTitleBar::setTitleLabelAlignment(const Qt::Alignment value) +StandardSystemButton *StandardTitleBar::maximizeButton() const { - Q_D(StandardTitleBar); - d->setTitleLabelAlignment(value); + Q_D(const StandardTitleBar); + return d->maximizeButton; } -#ifndef Q_OS_MACOS -StandardSystemButton *StandardTitleBar::minimizeButton() const +StandardSystemButton *StandardTitleBar::closeButton() const { Q_D(const StandardTitleBar); - return d->m_minimizeButton; + return d->closeButton; } +#endif // Q_OS_MACOS -StandardSystemButton *StandardTitleBar::maximizeButton() const +void StandardTitleBar::mouseReleaseEvent(QMouseEvent *event) { - Q_D(const StandardTitleBar); - return d->m_maximizeButton; + QWidget::mouseReleaseEvent(event); + Q_D(StandardTitleBar); + std::ignore = d->mouseEventHandler(event); } -StandardSystemButton *StandardTitleBar::closeButton() const +void StandardTitleBar::mouseDoubleClickEvent(QMouseEvent *event) +{ + QWidget::mouseDoubleClickEvent(event); + Q_D(StandardTitleBar); + std::ignore = d->mouseEventHandler(event); +} + +Qt::Alignment StandardTitleBar::titleLabelAlignment() const { Q_D(const StandardTitleBar); - return d->m_closeButton; + return d->labelAlignment; +} + +void StandardTitleBar::setTitleLabelAlignment(const Qt::Alignment value) +{ + Q_D(StandardTitleBar); + if (d->labelAlignment == value) { + return; + } + d->labelAlignment = value; + update(); + Q_EMIT titleLabelAlignmentChanged(); } -#endif // Q_OS_MACOS bool StandardTitleBar::isExtended() const { Q_D(const StandardTitleBar); - return d->isExtended(); + return d->extended; } void StandardTitleBar::setExtended(const bool value) { Q_D(StandardTitleBar); - d->setExtended(value); + if (d->extended == value) { + return; + } + d->extended = value; + setFixedHeight(d->extended ? kDefaultExtendedTitleBarHeight : kDefaultTitleBarHeight); + Q_EMIT extendedChanged(); } bool StandardTitleBar::isHideWhenClose() const { Q_D(const StandardTitleBar); - return d->isHideWhenClose(); + return d->hideWhenClose; } void StandardTitleBar::setHideWhenClose(const bool value) { Q_D(StandardTitleBar); - d->setHideWhenClose(value); + if (d->hideWhenClose == value) { + return; + } + d->hideWhenClose = value; + Q_EMIT hideWhenCloseChanged(); } ChromePalette *StandardTitleBar::chromePalette() const { Q_D(const StandardTitleBar); - return d->chromePalette(); + return d->chromePalette; +} + +void StandardTitleBar::paintEvent(QPaintEvent *event) +{ + Q_ASSERT(event); + if (!event) { + return; + } + Q_D(StandardTitleBar); + if (!d->window) { + return; + } + const bool active = d->window->isActiveWindow(); + const QColor backgroundColor = (active ? + d->chromePalette->titleBarActiveBackgroundColor() : + d->chromePalette->titleBarInactiveBackgroundColor()); + const QColor foregroundColor = (active ? + d->chromePalette->titleBarActiveForegroundColor() : + d->chromePalette->titleBarInactiveForegroundColor()); + QPainter painter(this); + painter.save(); + painter.setRenderHints(QPainter::Antialiasing | + QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); + painter.fillRect(QRect(QPoint(0, 0), size()), backgroundColor); + if (d->titleLabelVisible) { + const QString text = d->window->windowTitle(); + if (!text.isEmpty()) { + painter.setPen(foregroundColor); + painter.setFont(d->titleFont.value_or(d->defaultFont())); + const auto pos = [this, d]() -> QPoint { + const StandardTitleBarPrivate::FontMetrics labelSize = d->titleLabelSize(); + const int titleBarWidth = width(); + int x = 0; + if (d->labelAlignment & Qt::AlignLeft) { + x = (d->windowIconRect().right() + kDefaultTitleBarContentsMargin); + } else if (d->labelAlignment & Qt::AlignRight) { + x = (titleBarWidth - kDefaultTitleBarContentsMargin - labelSize.width); +#ifndef Q_OS_MACOS + x -= (titleBarWidth - d->minimizeButton->x()); +#endif // Q_OS_MACOS + } else if (d->labelAlignment & Qt::AlignHCenter) { + x = std::round(qreal(titleBarWidth - labelSize.width) / qreal(2)); + } else { + WARNING << "The alignment for the title label is not set!"; + } + const int y = std::round((qreal(height() - labelSize.height) / qreal(2)) + qreal(labelSize.ascent)); + return {x, y}; + }(); + painter.drawText(pos, text); + } + } + if (d->windowIconVisible) { + const QIcon icon = d->window->windowIcon(); + if (!icon.isNull()) { + icon.paint(&painter, d->windowIconRect()); + } + } + painter.restore(); + event->accept(); } bool StandardTitleBar::titleLabelVisible() const { Q_D(const StandardTitleBar); - return d->titleLabelVisible(); + return d->titleLabelVisible; } void StandardTitleBar::setTitleLabelVisible(const bool value) { Q_D(StandardTitleBar); - d->setTitleLabelVisible(value); + if (d->titleLabelVisible == value) { + return; + } + d->titleLabelVisible = value; + update(); + Q_EMIT titleLabelVisibleChanged(); } QSize StandardTitleBar::windowIconSize() const { Q_D(const StandardTitleBar); - return d->windowIconSize(); + return d->windowIconSize.value_or(kDefaultWindowIconSize); } void StandardTitleBar::setWindowIconSize(const QSize &value) { + Q_ASSERT(!value.isEmpty()); + if (value.isEmpty()) { + return; + } + if (windowIconSize() == value) { + return; + } Q_D(StandardTitleBar); - d->setWindowIconSize(value); + d->windowIconSize = value; + update(); + Q_EMIT windowIconSizeChanged(); } bool StandardTitleBar::windowIconVisible() const { Q_D(const StandardTitleBar); - return d->windowIconVisible(); + return d->windowIconVisible; } void StandardTitleBar::setWindowIconVisible(const bool value) { Q_D(StandardTitleBar); - d->setWindowIconVisible(value); + if (d->windowIconVisible == value) { + return; + } + d->windowIconVisible = value; + update(); + Q_EMIT windowIconVisibleChanged(); +#ifndef Q_OS_MACOS + // Ideally we should use FramelessWidgetsHelper::get(this) everywhere, but sadly when + // we call it here, it may be too early that FramelessWidgetsHelper has not attached + // to the top level widget yet, and thus it will trigger an assert error (the assert + // should not be suppressed, because it usually indicates there's something really + // wrong). So here we have to use the top level widget directly, as a special case. + // NOTE: In your own code, you should always use FramelessWidgetsHelper::get(this) + // if possible. + FramelessWidgetsHelper::get(d->window)->setHitTestVisible(d->windowIconRect(), d->windowIconVisible_real()); +#endif // Q_OS_MACOS } QFont StandardTitleBar::titleFont() const { Q_D(const StandardTitleBar); - return d->titleFont(); + return d->titleFont.value_or(QFont()); } void StandardTitleBar::setTitleFont(const QFont &value) { + if (titleFont() == value) { + return; + } Q_D(StandardTitleBar); - d->setTitleFont(value); -} - -void StandardTitleBar::paintEvent(QPaintEvent *event) -{ - Q_D(StandardTitleBar); - d->paintTitleBar(event); -} - -void StandardTitleBar::mouseReleaseEvent(QMouseEvent *event) -{ - QWidget::mouseReleaseEvent(event); - Q_D(StandardTitleBar); - std::ignore = d->mouseEventHandler(event); -} - -void StandardTitleBar::mouseDoubleClickEvent(QMouseEvent *event) -{ - QWidget::mouseDoubleClickEvent(event); - Q_D(StandardTitleBar); - std::ignore = d->mouseEventHandler(event); + d->titleFont = value; + update(); + Q_EMIT titleFontChanged(); } FRAMELESSHELPER_END_NAMESPACE