From e8dcb6e6fe47f44fea2081b7fc39a5add8644ab8 Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Tue, 5 Jul 2022 17:58:04 +0800 Subject: [PATCH] add api to set title bar and chrome button color TODO: 1. Special handling for the close button 2. Move QuickChromePalette class to own files 3. More testing Signed-off-by: Yuhang Zhao <2546789017@qq.com> --- examples/quick-blur/MainWindow.qml | 7 +- examples/widget-blur/widget.cpp | 7 +- include/FramelessHelper/Core/ChromePalette | 1 + include/FramelessHelper/Core/chromepalette.h | 105 ++++++ .../Core/private/chromepalette_p.h | 88 +++++ .../Core/private/sysapiloader_p.h | 4 +- .../Quick/framelesshelperquick_global.h | 14 + .../private/quickstandardsystembutton_p.h | 36 +- .../Quick/private/quickstandardtitlebar_p.h | 11 +- .../Widgets/private/standardsystembutton_p.h | 17 +- .../Widgets/private/standardtitlebar_p.h | 16 +- .../Widgets/standardsystembutton.h | 20 +- .../Widgets/standardtitlebar.h | 9 +- src/core/CMakeLists.txt | 3 + src/core/chromepalette.cpp | 350 ++++++++++++++++++ src/core/chromepalette.h | 1 + src/core/chromepalette_p.h | 1 + src/core/sysapiloader.cpp | 16 +- src/core/utils_win.cpp | 16 - src/quick/framelessquickmodule.cpp | 7 + src/quick/framelessquickutils.cpp | 13 +- src/quick/quickstandardsystembutton.cpp | 164 +++++--- src/quick/quickstandardtitlebar.cpp | 105 +++--- src/widgets/standardsystembutton.cpp | 105 +++--- src/widgets/standardtitlebar.cpp | 158 ++++---- 25 files changed, 968 insertions(+), 306 deletions(-) create mode 100644 include/FramelessHelper/Core/ChromePalette create mode 100644 include/FramelessHelper/Core/chromepalette.h create mode 100644 include/FramelessHelper/Core/private/chromepalette_p.h create mode 100644 src/core/chromepalette.cpp create mode 100644 src/core/chromepalette.h create mode 100644 src/core/chromepalette_p.h diff --git a/examples/quick-blur/MainWindow.qml b/examples/quick-blur/MainWindow.qml index 66eaccf..326f753 100644 --- a/examples/quick-blur/MainWindow.qml +++ b/examples/quick-blur/MainWindow.qml @@ -76,8 +76,11 @@ FramelessWindow { left: parent.left right: parent.right } - useAlternativeBackground: true titleLabelAlignment: Qt.AlignCenter - color: window.color + chromePalette { + titleBarActiveBackgroundColor: "transparent" + titleBarInactiveBackgroundColor: "transparent" + titleBarActiveForegroundColor: "black" + } } } diff --git a/examples/widget-blur/widget.cpp b/examples/widget-blur/widget.cpp index d47486d..c214075 100644 --- a/examples/widget-blur/widget.cpp +++ b/examples/widget-blur/widget.cpp @@ -35,6 +35,7 @@ #include #include #include +#include FRAMELESSHELPER_USE_NAMESPACE @@ -80,9 +81,11 @@ void Widget::initialize() setWindowTitle(tr("FramelessHelper demo application - Qt Widgets (Blur behind window)")); resize(800, 600); m_titleBar.reset(new StandardTitleBar(this)); - m_titleBar->setUseAlternativeBackground(true); - m_titleBar->setStyleSheet(FRAMELESSHELPER_STRING_LITERAL("background-color: transparent;")); m_titleBar->setTitleLabelAlignment(Qt::AlignCenter); + ChromePalette *pal = m_titleBar->chromePalette(); + pal->setTitleBarActiveBackgroundColor(kDefaultTransparentColor); + pal->setTitleBarInactiveBackgroundColor(kDefaultTransparentColor); + pal->setTitleBarActiveForegroundColor(kDefaultBlackColor); m_clockLabel.reset(new QLabel(this)); m_clockLabel->setFrameShape(QFrame::NoFrame); QFont clockFont = font(); diff --git a/include/FramelessHelper/Core/ChromePalette b/include/FramelessHelper/Core/ChromePalette new file mode 100644 index 0000000..de6bfff --- /dev/null +++ b/include/FramelessHelper/Core/ChromePalette @@ -0,0 +1 @@ +#include diff --git a/include/FramelessHelper/Core/chromepalette.h b/include/FramelessHelper/Core/chromepalette.h new file mode 100644 index 0000000..fcc64d4 --- /dev/null +++ b/include/FramelessHelper/Core/chromepalette.h @@ -0,0 +1,105 @@ +/* + * MIT License + * + * Copyright (C) 2022 by wangwenx190 (Yuhang Zhao) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once + +#include "framelesshelpercore_global.h" +#include + +FRAMELESSHELPER_BEGIN_NAMESPACE + +class ChromePalettePrivate; + +class FRAMELESSHELPER_CORE_API ChromePalette : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(ChromePalette) + Q_DISABLE_COPY_MOVE(ChromePalette) + + Q_PROPERTY(QColor titleBarActiveBackgroundColor READ titleBarActiveBackgroundColor + WRITE setTitleBarActiveBackgroundColor RESET resetTitleBarActiveBackgroundColor + NOTIFY titleBarActiveBackgroundColorChanged FINAL) + Q_PROPERTY(QColor titleBarInactiveBackgroundColor READ titleBarInactiveBackgroundColor + WRITE setTitleBarInactiveBackgroundColor RESET resetTitleBarInactiveBackgroundColor + NOTIFY titleBarInactiveBackgroundColorChanged FINAL) + Q_PROPERTY(QColor titleBarActiveForegroundColor READ titleBarActiveForegroundColor + WRITE setTitleBarActiveForegroundColor RESET resetTitleBarActiveForegroundColor + NOTIFY titleBarActiveForegroundColorChanged FINAL) + Q_PROPERTY(QColor titleBarInactiveForegroundColor READ titleBarInactiveForegroundColor + WRITE setTitleBarInactiveForegroundColor RESET resetTitleBarInactiveForegroundColor + NOTIFY titleBarInactiveForegroundColorChanged FINAL) + Q_PROPERTY(QColor chromeButtonNormalColor READ chromeButtonNormalColor + WRITE setChromeButtonNormalColor RESET resetChromeButtonNormalColor + NOTIFY chromeButtonNormalColorChanged FINAL) + Q_PROPERTY(QColor chromeButtonHoverColor READ chromeButtonHoverColor + WRITE setChromeButtonHoverColor RESET resetChromeButtonHoverColor + NOTIFY chromeButtonHoverColorChanged FINAL) + Q_PROPERTY(QColor chromeButtonPressColor READ chromeButtonPressColor + WRITE setChromeButtonPressColor RESET resetChromeButtonPressColor + NOTIFY chromeButtonPressColorChanged FINAL) + +public: + explicit ChromePalette(QObject *parent = nullptr); + ~ChromePalette() override; + + Q_NODISCARD QColor titleBarActiveBackgroundColor() const; + Q_NODISCARD QColor titleBarInactiveBackgroundColor() const; + Q_NODISCARD QColor titleBarActiveForegroundColor() const; + Q_NODISCARD QColor titleBarInactiveForegroundColor() const; + Q_NODISCARD QColor chromeButtonNormalColor() const; + Q_NODISCARD QColor chromeButtonHoverColor() const; + Q_NODISCARD QColor chromeButtonPressColor() const; + +public Q_SLOTS: + void setTitleBarActiveBackgroundColor(const QColor &value); + void resetTitleBarActiveBackgroundColor(); + void setTitleBarInactiveBackgroundColor(const QColor &value); + void resetTitleBarInactiveBackgroundColor(); + void setTitleBarActiveForegroundColor(const QColor &value); + void resetTitleBarActiveForegroundColor(); + void setTitleBarInactiveForegroundColor(const QColor &value); + void resetTitleBarInactiveForegroundColor(); + void setChromeButtonNormalColor(const QColor &value); + void resetChromeButtonNormalColor(); + void setChromeButtonHoverColor(const QColor &value); + void resetChromeButtonHoverColor(); + void setChromeButtonPressColor(const QColor &value); + void resetChromeButtonPressColor(); + +Q_SIGNALS: + void titleBarActiveBackgroundColorChanged(); + void titleBarInactiveBackgroundColorChanged(); + void titleBarActiveForegroundColorChanged(); + void titleBarInactiveForegroundColorChanged(); + void chromeButtonNormalColorChanged(); + void chromeButtonHoverColorChanged(); + void chromeButtonPressColorChanged(); + void titleBarColorChanged(); + void chromeButtonColorChanged(); + +private: + QScopedPointer d_ptr; +}; + +FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Core/private/chromepalette_p.h b/include/FramelessHelper/Core/private/chromepalette_p.h new file mode 100644 index 0000000..a9c8394 --- /dev/null +++ b/include/FramelessHelper/Core/private/chromepalette_p.h @@ -0,0 +1,88 @@ +/* + * MIT License + * + * Copyright (C) 2022 by wangwenx190 (Yuhang Zhao) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once + +#include "framelesshelpercore_global.h" +#include +#include + +FRAMELESSHELPER_BEGIN_NAMESPACE + +class ChromePalette; + +class FRAMELESSHELPER_CORE_API ChromePalettePrivate : public QObject +{ + Q_OBJECT + Q_DECLARE_PUBLIC(ChromePalette) + Q_DISABLE_COPY_MOVE(ChromePalettePrivate) + +public: + enum class MaskFlag + { + TitleBarActiveBackgroundColor = 0x00000001, + TitleBarInactiveBackgroundColor = 0x00000002, + TitleBarActiveForegroundColor = 0x00000004, + TitleBarInactiveForegroundColor = 0x00000008, + ChromeButtonNormalColor = 0x00000010, + ChromeButtonHoverColor = 0x00000020, + ChromeButtonPressColor = 0x00000040 + }; + Q_ENUM(MaskFlag) + Q_DECLARE_FLAGS(Mask, MaskFlag) + Q_FLAG(Mask) + + explicit ChromePalettePrivate(ChromePalette *q); + ~ChromePalettePrivate() override; + + Q_NODISCARD static ChromePalettePrivate *get(ChromePalette *q); + Q_NODISCARD static const ChromePalettePrivate *get(const ChromePalette *q); + +public Q_SLOTS: + void refresh(); + +private: + QPointer q_ptr = nullptr; + Mask mask = {}; + // System-defined ones: + QColor titleBarActiveBackgroundColor_sys = {}; + QColor titleBarInactiveBackgroundColor_sys = {}; + QColor titleBarActiveForegroundColor_sys = {}; + QColor titleBarInactiveForegroundColor_sys = {}; + QColor chromeButtonNormalColor_sys = {}; + QColor chromeButtonHoverColor_sys = {}; + QColor chromeButtonPressColor_sys = {}; + // User-defined ones: + QColor titleBarActiveBackgroundColor = {}; + QColor titleBarInactiveBackgroundColor = {}; + QColor titleBarActiveForegroundColor = {}; + QColor titleBarInactiveForegroundColor = {}; + QColor chromeButtonNormalColor = {}; + QColor chromeButtonHoverColor = {}; + QColor chromeButtonPressColor = {}; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(ChromePalettePrivate::Mask) + +FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Core/private/sysapiloader_p.h b/include/FramelessHelper/Core/private/sysapiloader_p.h index 114741e..a1f5f39 100644 --- a/include/FramelessHelper/Core/private/sysapiloader_p.h +++ b/include/FramelessHelper/Core/private/sysapiloader_p.h @@ -55,8 +55,8 @@ public: } private: - QMutex m_mutex; - QHash m_apiCache = {}; + static inline QMutex m_mutex; + static inline QHash> m_functionCache = {}; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Quick/framelesshelperquick_global.h b/include/FramelessHelper/Quick/framelesshelperquick_global.h index d1ef98f..d6b7841 100644 --- a/include/FramelessHelper/Quick/framelesshelperquick_global.h +++ b/include/FramelessHelper/Quick/framelesshelperquick_global.h @@ -25,6 +25,7 @@ #pragma once #include +#include #if __has_include() # include #else @@ -190,4 +191,17 @@ private: #endif }; +class FRAMELESSHELPER_QUICK_API QuickChromePalette : public ChromePalette +{ + Q_OBJECT +#ifdef QML_ANONYMOUS + QML_ANONYMOUS +#endif + Q_DISABLE_COPY_MOVE(QuickChromePalette) + +public: + explicit QuickChromePalette(QObject *parent = nullptr); + ~QuickChromePalette() override; +}; + FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Quick/private/quickstandardsystembutton_p.h b/include/FramelessHelper/Quick/private/quickstandardsystembutton_p.h index 7b21b66..b57e364 100644 --- a/include/FramelessHelper/Quick/private/quickstandardsystembutton_p.h +++ b/include/FramelessHelper/Quick/private/quickstandardsystembutton_p.h @@ -42,29 +42,55 @@ class FRAMELESSHELPER_QUICK_API QuickStandardSystemButton : public QQuickButton QML_NAMED_ELEMENT(StandardSystemButton) #endif Q_DISABLE_COPY_MOVE(QuickStandardSystemButton) + Q_PROPERTY(QuickGlobal::SystemButtonType buttonType READ buttonType WRITE setButtonType NOTIFY buttonTypeChanged FINAL) + Q_PROPERTY(QString code READ code WRITE setCode NOTIFY codeChanged FINAL) + Q_PROPERTY(QColor hoverColor READ hoverColor WRITE setHoverColor NOTIFY hoverColorChanged FINAL) + Q_PROPERTY(QColor pressColor READ pressColor WRITE setPressColor NOTIFY pressColorChanged FINAL) + Q_PROPERTY(QColor normalColor READ normalColor WRITE setNormalColor NOTIFY normalColorChanged FINAL) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL) public: explicit QuickStandardSystemButton(QQuickItem *parent = nullptr); explicit QuickStandardSystemButton(const QuickGlobal::SystemButtonType type, QQuickItem *parent = nullptr); ~QuickStandardSystemButton() override; + Q_NODISCARD QuickGlobal::SystemButtonType buttonType() const; + Q_NODISCARD QString code() const; + Q_NODISCARD QColor color() const; + Q_NODISCARD QColor normalColor() const; + Q_NODISCARD QColor hoverColor() const; + Q_NODISCARD QColor pressColor() const; + public Q_SLOTS: void updateForeground(); void updateBackground(); void setButtonType(const QuickGlobal::SystemButtonType type); - -protected: - void itemChange(const ItemChange change, const ItemChangeData &value) override; + void setCode(const QString &value); + void setColor(const QColor &value); + void setNormalColor(const QColor &value); + void setHoverColor(const QColor &value); + void setPressColor(const QColor &value); private: void initialize(); +Q_SIGNALS: + void buttonTypeChanged(); + void codeChanged(); + void colorChanged(); + void normalColorChanged(); + void hoverColorChanged(); + void pressColorChanged(); + private: QScopedPointer m_contentItem; QScopedPointer m_backgroundItem; QuickGlobal::SystemButtonType m_buttonType = QuickGlobal::SystemButtonType::Unknown; - QMetaObject::Connection m_windowActiveConnection = {}; - bool m_settingIconCode = false; + QString m_code = {}; + QColor m_color = {}; + QColor m_normalColor = {}; + QColor m_hoverColor = {}; + QColor m_pressColor = {}; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Quick/private/quickstandardtitlebar_p.h b/include/FramelessHelper/Quick/private/quickstandardtitlebar_p.h index 4ce62ed..db71205 100644 --- a/include/FramelessHelper/Quick/private/quickstandardtitlebar_p.h +++ b/include/FramelessHelper/Quick/private/quickstandardtitlebar_p.h @@ -50,8 +50,8 @@ class FRAMELESSHELPER_QUICK_API QuickStandardTitleBar : public QQuickRectangle Q_PROPERTY(QuickStandardSystemButton* maximizeButton READ maximizeButton CONSTANT FINAL) Q_PROPERTY(QuickStandardSystemButton* closeButton READ closeButton CONSTANT FINAL) Q_PROPERTY(bool extended READ isExtended WRITE setExtended NOTIFY extendedChanged FINAL) - Q_PROPERTY(bool useAlternativeBackground READ isUsingAlternativeBackground WRITE setUseAlternativeBackground NOTIFY useAlternativeBackgroundChanged FINAL) Q_PROPERTY(bool hideWhenClose READ isHideWhenClose WRITE setHideWhenClose NOTIFY hideWhenCloseChanged FINAL) + Q_PROPERTY(QuickChromePalette* chromePalette READ chromePalette CONSTANT FINAL) public: explicit QuickStandardTitleBar(QQuickItem *parent = nullptr); @@ -68,12 +68,11 @@ public: Q_NODISCARD bool isExtended() const; void setExtended(const bool value); - Q_NODISCARD bool isUsingAlternativeBackground() const; - void setUseAlternativeBackground(const bool value); - Q_NODISCARD bool isHideWhenClose() const; void setHideWhenClose(const bool value); + Q_NODISCARD QuickChromePalette *chromePalette() const; + protected: void itemChange(const ItemChange change, const ItemChangeData &value) override; Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override; @@ -82,6 +81,7 @@ private Q_SLOTS: void updateMaximizeButton(); void updateTitleLabelText(); void updateTitleBarColor(); + void updateChromeButtonColor(); void clickMinimizeButton(); void clickMaximizeButton(); void clickCloseButton(); @@ -90,7 +90,6 @@ private Q_SLOTS: Q_SIGNALS: void titleLabelAlignmentChanged(); void extendedChanged(); - void useAlternativeBackgroundChanged(); void hideWhenCloseChanged(); private: @@ -108,8 +107,8 @@ private: QMetaObject::Connection m_windowActiveChangeConnection = {}; QMetaObject::Connection m_windowTitleChangeConnection = {}; bool m_extended = false; - bool m_useAlternativeBackground = false; bool m_hideWhenClose = false; + QScopedPointer m_chromePalette; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/private/standardsystembutton_p.h b/include/FramelessHelper/Widgets/private/standardsystembutton_p.h index f0d472f..cfd5522 100644 --- a/include/FramelessHelper/Widgets/private/standardsystembutton_p.h +++ b/include/FramelessHelper/Widgets/private/standardsystembutton_p.h @@ -50,8 +50,8 @@ public: Q_NODISCARD static StandardSystemButtonPrivate *get(StandardSystemButton *pub); Q_NODISCARD static const StandardSystemButtonPrivate *get(const StandardSystemButton *pub); - Q_NODISCARD QString getIconCode() const; - void setIconCode(const QString &value); + Q_NODISCARD QString getCode() const; + void setCode(const QString &value); Q_NODISCARD Global::SystemButtonType getButtonType() const; void setButtonType(const Global::SystemButtonType type); @@ -62,15 +62,15 @@ public: Q_NODISCARD bool isPressed() const; Q_NODISCARD QColor getHoverColor() const; Q_NODISCARD QColor getPressColor() const; - Q_NODISCARD QColor getIconColor() const; + Q_NODISCARD QColor getNormalColor() const; + Q_NODISCARD QColor getColor() const; void setHovered(const bool value); void setPressed(const bool value); void setHoverColor(const QColor &value); void setPressColor(const QColor &value); - void setIconColor(const QColor &value); - - void updateBackgroundColor(); + void setNormalColor(const QColor &value); + void setColor(const QColor &value); void enterEventHandler(QT_ENTER_EVENT_TYPE *event); void leaveEventHandler(QEvent *event); @@ -82,10 +82,11 @@ private: private: QPointer q_ptr = nullptr; Global::SystemButtonType m_buttonType = Global::SystemButtonType::Unknown; - QString m_iconCode = {}; + QString m_code = {}; QColor m_hoverColor = {}; QColor m_pressColor = {}; - QColor m_iconColor = {}; + QColor m_normalColor = {}; + QColor m_color = {}; bool m_hovered = false; bool m_pressed = false; }; diff --git a/include/FramelessHelper/Widgets/private/standardtitlebar_p.h b/include/FramelessHelper/Widgets/private/standardtitlebar_p.h index 4571410..d408983 100644 --- a/include/FramelessHelper/Widgets/private/standardtitlebar_p.h +++ b/include/FramelessHelper/Widgets/private/standardtitlebar_p.h @@ -31,12 +31,14 @@ QT_BEGIN_NAMESPACE class QLabel; class QSpacerItem; +class QPaintEvent; QT_END_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE class StandardTitleBar; class StandardSystemButton; +class ChromePalette; class FRAMELESSHELPER_WIDGETS_API StandardTitleBarPrivate : public QObject { @@ -57,15 +59,17 @@ public: Q_NODISCARD bool isExtended() const; void setExtended(const bool value); - Q_NODISCARD bool isUsingAlternativeBackground() const; - void setUseAlternativeBackground(const bool value); - Q_NODISCARD bool isHideWhenClose() const; void setHideWhenClose(const bool value); + Q_NODISCARD ChromePalette *chromePalette() const; + + void paintTitleBar(QPaintEvent *event); + public Q_SLOTS: void updateMaximizeButton(); - void updateTitleBarStyleSheet(); + void updateTitleBarColor(); + void updateChromeButtonColor(); void retranslateUi(); protected: @@ -75,7 +79,7 @@ private: void initialize(); private: - StandardTitleBar *q_ptr = nullptr; + QPointer q_ptr = nullptr; QScopedPointer m_windowTitleLabel; QScopedPointer m_minimizeButton; QScopedPointer m_maximizeButton; @@ -85,8 +89,8 @@ private: Qt::Alignment m_labelAlignment = {}; QSpacerItem *m_labelLeftStretch = nullptr; QSpacerItem *m_labelRightStretch = nullptr; - bool m_useAlternativeBackground = false; bool m_hideWhenClose = false; + QScopedPointer m_chromePalette; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/standardsystembutton.h b/include/FramelessHelper/Widgets/standardsystembutton.h index e7b1661..c9cc4e1 100644 --- a/include/FramelessHelper/Widgets/standardsystembutton.h +++ b/include/FramelessHelper/Widgets/standardsystembutton.h @@ -37,12 +37,13 @@ class FRAMELESSHELPER_WIDGETS_API StandardSystemButton : public QAbstractButton Q_DECLARE_PRIVATE(StandardSystemButton) Q_DISABLE_COPY_MOVE(StandardSystemButton) Q_PROPERTY(Global::SystemButtonType buttonType READ buttonType WRITE setButtonType NOTIFY buttonTypeChanged FINAL) - Q_PROPERTY(QString iconCode READ iconCode WRITE setIconCode NOTIFY iconCodeChanged FINAL) + Q_PROPERTY(QString code READ code WRITE setCode NOTIFY codeChanged FINAL) Q_PROPERTY(bool hovered READ isHovered WRITE setHovered NOTIFY hoveredChanged FINAL) Q_PROPERTY(bool pressed READ isPressed WRITE setPressed NOTIFY pressedChanged FINAL) Q_PROPERTY(QColor hoverColor READ hoverColor WRITE setHoverColor NOTIFY hoverColorChanged FINAL) Q_PROPERTY(QColor pressColor READ pressColor WRITE setPressColor NOTIFY pressColorChanged FINAL) - Q_PROPERTY(QColor iconColor READ iconColor WRITE setIconColor NOTIFY iconColorChanged FINAL) + Q_PROPERTY(QColor normalColor READ normalColor WRITE setNormalColor NOTIFY normalColorChanged FINAL) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL) public: explicit StandardSystemButton(QWidget *parent = nullptr); @@ -51,21 +52,23 @@ public: Q_NODISCARD QSize sizeHint() const override; Q_NODISCARD Global::SystemButtonType buttonType(); - Q_NODISCARD QString iconCode() const; + Q_NODISCARD QString code() const; Q_NODISCARD bool isHovered() const; Q_NODISCARD bool isPressed() const; Q_NODISCARD QColor hoverColor() const; Q_NODISCARD QColor pressColor() const; - Q_NODISCARD QColor iconColor() const; + Q_NODISCARD QColor normalColor() const; + Q_NODISCARD QColor color() const; public Q_SLOTS: void setButtonType(const Global::SystemButtonType value); - void setIconCode(const QString &code); + void setCode(const QString &code); void setHovered(const bool value); void setPressed(const bool value); void setHoverColor(const QColor &value); void setPressColor(const QColor &value); - void setIconColor(const QColor &value); + void setNormalColor(const QColor &value); + void setColor(const QColor &value); protected: void enterEvent(QT_ENTER_EVENT_TYPE *event) override; @@ -74,12 +77,13 @@ protected: Q_SIGNALS: void buttonTypeChanged(); - void iconCodeChanged(); + void codeChanged(); void hoveredChanged(); void pressedChanged(); void hoverColorChanged(); void pressColorChanged(); - void iconColorChanged(); + void normalColorChanged(); + void colorChanged(); private: QScopedPointer d_ptr; diff --git a/include/FramelessHelper/Widgets/standardtitlebar.h b/include/FramelessHelper/Widgets/standardtitlebar.h index b8e8ff4..6bd3b4b 100644 --- a/include/FramelessHelper/Widgets/standardtitlebar.h +++ b/include/FramelessHelper/Widgets/standardtitlebar.h @@ -25,6 +25,7 @@ #pragma once #include "framelesshelperwidgets_global.h" +#include #include #include @@ -44,8 +45,8 @@ class FRAMELESSHELPER_WIDGETS_API StandardTitleBar : public QWidget Q_PROPERTY(StandardSystemButton* maximizeButton READ maximizeButton CONSTANT FINAL) Q_PROPERTY(StandardSystemButton* closeButton READ closeButton CONSTANT FINAL) Q_PROPERTY(bool extended READ isExtended WRITE setExtended NOTIFY extendedChanged FINAL) - Q_PROPERTY(bool useAlternativeBackground READ isUsingAlternativeBackground WRITE setUseAlternativeBackground NOTIFY useAlternativeBackgroundChanged FINAL) Q_PROPERTY(bool hideWhenClose READ isHideWhenClose WRITE setHideWhenClose NOTIFY hideWhenCloseChanged FINAL) + Q_PROPERTY(ChromePalette* chromePalette READ chromePalette CONSTANT FINAL) public: explicit StandardTitleBar(QWidget *parent = nullptr); @@ -62,19 +63,17 @@ public: Q_NODISCARD bool isExtended() const; void setExtended(const bool value); - Q_NODISCARD bool isUsingAlternativeBackground() const; - void setUseAlternativeBackground(const bool value); - Q_NODISCARD bool isHideWhenClose() const; void setHideWhenClose(const bool value); + Q_NODISCARD ChromePalette *chromePalette() const; + protected: void paintEvent(QPaintEvent *event) override; Q_SIGNALS: void extendedChanged(); void titleLabelAlignmentChanged(); - void useAlternativeBackgroundChanged(); void hideWhenCloseChanged(); private: diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 65b9cc1..f42ae9e 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -42,15 +42,18 @@ set(SOURCES ${INCLUDE_PREFIX}/framelesshelper_qt.h ${INCLUDE_PREFIX}/framelessmanager.h ${INCLUDE_PREFIX}/utils.h + ${INCLUDE_PREFIX}/chromepalette.h ${INCLUDE_PREFIX}/private/framelessmanager_p.h ${INCLUDE_PREFIX}/private/framelessconfig_p.h ${INCLUDE_PREFIX}/private/sysapiloader_p.h + ${INCLUDE_PREFIX}/private/chromepalette_p.h framelesshelpercore.qrc utils.cpp framelesshelper_qt.cpp framelessmanager.cpp framelessconfig.cpp sysapiloader.cpp + chromepalette.cpp ) if(WIN32) diff --git a/src/core/chromepalette.cpp b/src/core/chromepalette.cpp new file mode 100644 index 0000000..1d17a61 --- /dev/null +++ b/src/core/chromepalette.cpp @@ -0,0 +1,350 @@ +/* + * MIT License + * + * Copyright (C) 2022 by wangwenx190 (Yuhang Zhao) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "chromepalette.h" +#include "chromepalette_p.h" +#include "framelessmanager.h" +#include "utils.h" + +FRAMELESSHELPER_BEGIN_NAMESPACE + +using namespace Global; + +ChromePalettePrivate::ChromePalettePrivate(ChromePalette *q) : QObject(q) +{ + Q_ASSERT(q); + if (!q) { + return; + } + q_ptr = q; + connect(FramelessManager::instance(), + &FramelessManager::systemThemeChanged, this, &ChromePalettePrivate::refresh); + refresh(); +} + +ChromePalettePrivate::~ChromePalettePrivate() = default; + +ChromePalettePrivate *ChromePalettePrivate::get(ChromePalette *q) +{ + Q_ASSERT(q); + if (!q) { + return nullptr; + } + return q->d_func(); +} + +const ChromePalettePrivate *ChromePalettePrivate::get(const ChromePalette *q) +{ + Q_ASSERT(q); + if (!q) { + return nullptr; + } + return q->d_func(); +} + +void ChromePalettePrivate::refresh() +{ + const bool colorized = Utils::isTitleBarColorized(); + const bool dark = Utils::shouldAppsUseDarkMode(); + titleBarActiveBackgroundColor_sys = [colorized, dark]() -> QColor { + if (colorized) { +#ifdef Q_OS_WINDOWS + return Utils::getDwmColorizationColor(); +#elif defined(Q_OS_LINUX) + return Utils::getWmThemeColor(); +#elif defined(Q_OS_MACOS) + return Utils::getControlsAccentColor(); +#else + return {}; +#endif + } else { + return (dark ? kDefaultBlackColor : kDefaultWhiteColor); + } + }(); + titleBarInactiveBackgroundColor_sys = (dark ? kDefaultSystemDarkColor : kDefaultWhiteColor); + // ### TODO: Use dark/light color if background color is light/dark. + titleBarActiveForegroundColor_sys = ((dark || colorized) ? kDefaultWhiteColor : kDefaultBlackColor); + titleBarInactiveForegroundColor_sys = kDefaultDarkGrayColor; + chromeButtonNormalColor_sys = kDefaultTransparentColor; + chromeButtonHoverColor_sys = + Utils::calculateSystemButtonBackgroundColor(SystemButtonType::Minimize, ButtonState::Hovered); + chromeButtonPressColor_sys = + Utils::calculateSystemButtonBackgroundColor(SystemButtonType::Minimize, ButtonState::Pressed); + Q_Q(ChromePalette); + Q_EMIT q->titleBarActiveBackgroundColorChanged(); + Q_EMIT q->titleBarInactiveBackgroundColorChanged(); + Q_EMIT q->titleBarActiveForegroundColorChanged(); + Q_EMIT q->titleBarInactiveForegroundColorChanged(); + Q_EMIT q->chromeButtonNormalColorChanged(); + Q_EMIT q->chromeButtonHoverColorChanged(); + Q_EMIT q->chromeButtonPressColorChanged(); + Q_EMIT q->titleBarColorChanged(); + Q_EMIT q->chromeButtonColorChanged(); +} + +ChromePalette::ChromePalette(QObject *parent) : QObject(parent), d_ptr(new ChromePalettePrivate(this)) +{ +} + +ChromePalette::~ChromePalette() = default; + +QColor ChromePalette::titleBarActiveBackgroundColor() const +{ + Q_D(const ChromePalette); + if (d->mask & ChromePalettePrivate::MaskFlag::TitleBarActiveBackgroundColor) { + return d->titleBarActiveBackgroundColor; + } + return d->titleBarActiveBackgroundColor_sys; +} + +QColor ChromePalette::titleBarInactiveBackgroundColor() const +{ + Q_D(const ChromePalette); + if (d->mask & ChromePalettePrivate::MaskFlag::TitleBarInactiveBackgroundColor) { + return d->titleBarInactiveBackgroundColor; + } + return d->titleBarInactiveBackgroundColor_sys; +} + +QColor ChromePalette::titleBarActiveForegroundColor() const +{ + Q_D(const ChromePalette); + if (d->mask & ChromePalettePrivate::MaskFlag::TitleBarActiveForegroundColor) { + return d->titleBarActiveForegroundColor; + } + return d->titleBarActiveForegroundColor_sys; +} + +QColor ChromePalette::titleBarInactiveForegroundColor() const +{ + Q_D(const ChromePalette); + if (d->mask & ChromePalettePrivate::MaskFlag::TitleBarInactiveForegroundColor) { + return d->titleBarInactiveForegroundColor; + } + return d->titleBarInactiveForegroundColor_sys; +} + +QColor ChromePalette::chromeButtonNormalColor() const +{ + Q_D(const ChromePalette); + if (d->mask & ChromePalettePrivate::MaskFlag::ChromeButtonNormalColor) { + return d->chromeButtonNormalColor; + } + return d->chromeButtonNormalColor_sys; +} + +QColor ChromePalette::chromeButtonHoverColor() const +{ + Q_D(const ChromePalette); + if (d->mask & ChromePalettePrivate::MaskFlag::ChromeButtonHoverColor) { + return d->chromeButtonHoverColor; + } + return d->chromeButtonHoverColor_sys; +} + +QColor ChromePalette::chromeButtonPressColor() const +{ + Q_D(const ChromePalette); + if (d->mask & ChromePalettePrivate::MaskFlag::ChromeButtonPressColor) { + return d->chromeButtonPressColor; + } + return d->chromeButtonPressColor_sys; +} + +void ChromePalette::setTitleBarActiveBackgroundColor(const QColor &value) +{ + Q_ASSERT(value.isValid()); + if (!value.isValid()) { + return; + } + Q_D(ChromePalette); + if (d->titleBarActiveBackgroundColor == value) { + return; + } + d->titleBarActiveBackgroundColor = value; + d->mask |= ChromePalettePrivate::MaskFlag::TitleBarActiveBackgroundColor; + Q_EMIT titleBarActiveBackgroundColorChanged(); + Q_EMIT titleBarColorChanged(); +} + +void ChromePalette::resetTitleBarActiveBackgroundColor() +{ + Q_D(ChromePalette); + d->titleBarActiveBackgroundColor = {}; + d->mask &= ~ChromePalettePrivate::Mask(ChromePalettePrivate::MaskFlag::TitleBarActiveBackgroundColor); + Q_EMIT titleBarActiveBackgroundColorChanged(); + Q_EMIT titleBarColorChanged(); +} + +void ChromePalette::setTitleBarInactiveBackgroundColor(const QColor &value) +{ + Q_ASSERT(value.isValid()); + if (!value.isValid()) { + return; + } + Q_D(ChromePalette); + if (d->titleBarInactiveBackgroundColor == value) { + return; + } + d->titleBarInactiveBackgroundColor = value; + d->mask |= ChromePalettePrivate::MaskFlag::TitleBarInactiveBackgroundColor; + Q_EMIT titleBarInactiveBackgroundColorChanged(); + Q_EMIT titleBarColorChanged(); +} + +void ChromePalette::resetTitleBarInactiveBackgroundColor() +{ + Q_D(ChromePalette); + d->titleBarInactiveBackgroundColor = {}; + d->mask &= ~ChromePalettePrivate::Mask(ChromePalettePrivate::MaskFlag::TitleBarInactiveBackgroundColor); + Q_EMIT titleBarInactiveBackgroundColorChanged(); + Q_EMIT titleBarColorChanged(); +} + +void ChromePalette::setTitleBarActiveForegroundColor(const QColor &value) +{ + Q_ASSERT(value.isValid()); + if (!value.isValid()) { + return; + } + Q_D(ChromePalette); + if (d->titleBarActiveForegroundColor == value) { + return; + } + d->titleBarActiveForegroundColor = value; + d->mask |= ChromePalettePrivate::MaskFlag::TitleBarActiveForegroundColor; + Q_EMIT titleBarActiveForegroundColorChanged(); + Q_EMIT titleBarColorChanged(); +} + +void ChromePalette::resetTitleBarActiveForegroundColor() +{ + Q_D(ChromePalette); + d->titleBarActiveForegroundColor = {}; + d->mask &= ~ChromePalettePrivate::Mask(ChromePalettePrivate::MaskFlag::TitleBarActiveForegroundColor); + Q_EMIT titleBarActiveForegroundColorChanged(); + Q_EMIT titleBarColorChanged(); +} + +void ChromePalette::setTitleBarInactiveForegroundColor(const QColor &value) +{ + Q_ASSERT(value.isValid()); + if (!value.isValid()) { + return; + } + Q_D(ChromePalette); + if (d->titleBarInactiveForegroundColor == value) { + return; + } + d->titleBarInactiveForegroundColor = value; + d->mask |= ChromePalettePrivate::MaskFlag::TitleBarInactiveForegroundColor; + Q_EMIT titleBarInactiveForegroundColorChanged(); + Q_EMIT titleBarColorChanged(); +} + +void ChromePalette::resetTitleBarInactiveForegroundColor() +{ + Q_D(ChromePalette); + d->titleBarInactiveForegroundColor = {}; + d->mask &= ~ChromePalettePrivate::Mask(ChromePalettePrivate::MaskFlag::TitleBarInactiveForegroundColor); + Q_EMIT titleBarInactiveForegroundColorChanged(); + Q_EMIT titleBarColorChanged(); +} + +void ChromePalette::setChromeButtonNormalColor(const QColor &value) +{ + Q_ASSERT(value.isValid()); + if (!value.isValid()) { + return; + } + Q_D(ChromePalette); + if (d->chromeButtonNormalColor == value) { + return; + } + d->chromeButtonNormalColor = value; + d->mask |= ChromePalettePrivate::MaskFlag::ChromeButtonNormalColor; + Q_EMIT chromeButtonNormalColorChanged(); + Q_EMIT chromeButtonColorChanged(); +} + +void ChromePalette::resetChromeButtonNormalColor() +{ + Q_D(ChromePalette); + d->chromeButtonNormalColor = {}; + d->mask &= ~ChromePalettePrivate::Mask(ChromePalettePrivate::MaskFlag::ChromeButtonNormalColor); + Q_EMIT chromeButtonNormalColorChanged(); + Q_EMIT chromeButtonColorChanged(); +} + +void ChromePalette::setChromeButtonHoverColor(const QColor &value) +{ + Q_ASSERT(value.isValid()); + if (!value.isValid()) { + return; + } + Q_D(ChromePalette); + if (d->chromeButtonHoverColor == value) { + return; + } + d->chromeButtonHoverColor = value; + d->mask |= ChromePalettePrivate::MaskFlag::ChromeButtonHoverColor; + Q_EMIT chromeButtonHoverColorChanged(); + Q_EMIT chromeButtonColorChanged(); +} + +void ChromePalette::resetChromeButtonHoverColor() +{ + Q_D(ChromePalette); + d->chromeButtonHoverColor = {}; + d->mask &= ~ChromePalettePrivate::Mask(ChromePalettePrivate::MaskFlag::ChromeButtonHoverColor); + Q_EMIT chromeButtonHoverColorChanged(); + Q_EMIT chromeButtonColorChanged(); +} + +void ChromePalette::setChromeButtonPressColor(const QColor &value) +{ + Q_ASSERT(value.isValid()); + if (!value.isValid()) { + return; + } + Q_D(ChromePalette); + if (d->chromeButtonPressColor == value) { + return; + } + d->chromeButtonPressColor = value; + d->mask |= ChromePalettePrivate::MaskFlag::ChromeButtonPressColor; + Q_EMIT chromeButtonPressColorChanged(); + Q_EMIT chromeButtonColorChanged(); +} + +void ChromePalette::resetChromeButtonPressColor() +{ + Q_D(ChromePalette); + d->chromeButtonPressColor = {}; + d->mask &= ~ChromePalettePrivate::Mask(ChromePalettePrivate::MaskFlag::ChromeButtonPressColor); + Q_EMIT chromeButtonPressColorChanged(); + Q_EMIT chromeButtonColorChanged(); +} + +FRAMELESSHELPER_END_NAMESPACE diff --git a/src/core/chromepalette.h b/src/core/chromepalette.h new file mode 100644 index 0000000..68f6ff7 --- /dev/null +++ b/src/core/chromepalette.h @@ -0,0 +1 @@ +#include "../../include/FramelessHelper/Core/chromepalette.h" diff --git a/src/core/chromepalette_p.h b/src/core/chromepalette_p.h new file mode 100644 index 0000000..4202da2 --- /dev/null +++ b/src/core/chromepalette_p.h @@ -0,0 +1 @@ +#include "../../include/FramelessHelper/Core/private/chromepalette_p.h" diff --git a/src/core/sysapiloader.cpp b/src/core/sysapiloader.cpp index 468d8c8..d21a82f 100644 --- a/src/core/sysapiloader.cpp +++ b/src/core/sysapiloader.cpp @@ -67,15 +67,16 @@ bool SysApiLoader::isAvailable(const QString &library, const QString &function) return false; } QMutexLocker locker(&m_mutex); - if (m_apiCache.contains(function)) { - return true; + if (m_functionCache.contains(function)) { + return m_functionCache.value(function).has_value(); } - QFunctionPointer symbol = SysApiLoader::resolve(library, function); + const QFunctionPointer symbol = SysApiLoader::resolve(library, function); if (symbol) { - m_apiCache.insert(function, symbol); + m_functionCache.insert(function, symbol); qDebug() << "Successfully loaded" << function << "from" << library; return true; } + m_functionCache.insert(function, std::nullopt); qWarning() << "Failed to load" << function << "from" << library; return false; } @@ -87,8 +88,11 @@ QFunctionPointer SysApiLoader::get(const QString &function) return nullptr; } QMutexLocker locker(&m_mutex); - if (m_apiCache.contains(function)) { - return m_apiCache.value(function); + if (m_functionCache.contains(function)) { + const std::optional symbol = m_functionCache.value(function); + if (symbol.has_value()) { + return symbol.value(); + } } return nullptr; } diff --git a/src/core/utils_win.cpp b/src/core/utils_win.cpp index 6a10bc9..72ee83c 100644 --- a/src/core/utils_win.cpp +++ b/src/core/utils_win.cpp @@ -444,7 +444,6 @@ bool Utils::isDwmCompositionEnabled() return (ok && (value != 0)); }; if (!API_DWM_AVAILABLE(DwmIsCompositionEnabled)) { - qWarning() << "Failed to resolve DwmIsCompositionEnabled() from DWMAPI.DLL."; return resultFromRegistry(); } BOOL enabled = FALSE; @@ -481,7 +480,6 @@ void Utils::updateWindowFrameMargins(const WId windowId, const bool reset) return; } if (!API_DWM_AVAILABLE(DwmExtendFrameIntoClientArea)) { - qWarning() << "Failed to resolve DwmExtendFrameIntoClientArea() from DWMAPI.DLL."; return; } const MARGINS margins = [reset]() -> MARGINS { @@ -563,7 +561,6 @@ QColor Utils::getDwmColorizationColor() return (ok ? QColor::fromRgba(value) : kDefaultDarkGrayColor); }; if (!API_DWM_AVAILABLE(DwmGetColorizationColor)) { - qWarning() << "Failed to resolve DwmGetColorizationColor() from DWMAPI.DLL."; return resultFromRegistry(); } DWORD color = 0; @@ -716,19 +713,15 @@ void Utils::syncWmPaintWithDwm() return; } if (!API_WINMM_AVAILABLE(timeGetDevCaps)) { - qWarning() << "Failed to resolve timeGetDevCaps() from WINMM.DLL."; return; } if (!API_WINMM_AVAILABLE(timeBeginPeriod)) { - qWarning() << "Failed to resolve timeBeginPeriod() from WINMM.DLL."; return; } if (!API_WINMM_AVAILABLE(timeEndPeriod)) { - qWarning() << "Failed to resolve timeEndPeriod() from WINMM.DLL."; return; } if (!API_DWM_AVAILABLE(DwmGetCompositionTimingInfo)) { - qWarning() << "Failed to resolve DwmGetCompositionTimingInfo() from DWMAPI.DLL."; return; } // Dirty hack to workaround the resize flicker caused by DWM. @@ -960,7 +953,6 @@ quint32 Utils::getFrameBorderThickness(const WId windowId, const bool scaled) return 0; } if (!API_DWM_AVAILABLE(DwmGetWindowAttribute)) { - qWarning() << "Failed to resolve DwmGetWindowAttribute() from DWMAPI.DLL."; return 0; } const UINT dpi = getWindowDpi(windowId, true); @@ -1010,7 +1002,6 @@ void Utils::updateWindowFrameBorderColor(const WId windowId, const bool dark) return; } if (!API_DWM_AVAILABLE(DwmSetWindowAttribute)) { - qWarning() << "Failed to resolve DwmSetWindowAttribute() from DWMAPI.DLL."; return; } const auto hwnd = reinterpret_cast(windowId); @@ -1362,7 +1353,6 @@ void Utils::updateGlobalWin32ControlsTheme(const WId windowId, const bool dark) return; } if (!API_THEME_AVAILABLE(SetWindowTheme)) { - qWarning() << "Failed to resolve SetWindowTheme() from UXTHEME.DLL."; return; } const auto hwnd = reinterpret_cast(windowId); @@ -1411,7 +1401,6 @@ void Utils::forceSquareCornersForWindow(const WId windowId, const bool force) return; } if (!API_DWM_AVAILABLE(DwmSetWindowAttribute)) { - qWarning() << "Failed to resolve DwmSetWindowAttribute() from DWMAPI.DLL."; return; } const auto hwnd = reinterpret_cast(windowId); @@ -1432,15 +1421,12 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode, static const bool isWin8OrGreater = isWindowsVersionOrGreater(WindowsVersion::_8); if (isWin8OrGreater) { if (!API_USER_AVAILABLE(SetWindowCompositionAttribute)) { - qWarning() << "Failed to resolve SetWindowCompositionAttribute() from USER32.DLL."; return false; } if (!API_DWM_AVAILABLE(DwmSetWindowAttribute)) { - qWarning() << "Failed to resolve DwmSetWindowAttribute() from DWMAPI.DLL."; return false; } if (!API_DWM_AVAILABLE(DwmExtendFrameIntoClientArea)) { - qWarning() << "Failed to resolve DwmExtendFrameIntoClientArea() from DWMAPI.DLL."; return false; } const auto pSetWindowCompositionAttribute = @@ -1607,8 +1593,6 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode, return true; } qWarning() << __getSystemErrorMessage(kDwmEnableBlurBehindWindow, hr); - } else { - qWarning() << "Failed to resolve DwmEnableBlurBehindWindow() from DWMAPI.DLL."; } } return false; diff --git a/src/quick/framelessquickmodule.cpp b/src/quick/framelessquickmodule.cpp index 64bef46..c1378d9 100644 --- a/src/quick/framelessquickmodule.cpp +++ b/src/quick/framelessquickmodule.cpp @@ -69,6 +69,7 @@ void FramelessHelper::Quick::registerTypes(QQmlEngine *engine) Q_UNUSED(scriptEngine); return new FramelessQuickUtils; }); + qmlRegisterAnonymousType(QUICK_URI_SHORT); qmlRegisterRevision(QUICK_URI_FULL); qmlRegisterRevision(QUICK_URI_FULL); qmlRegisterRevision(QUICK_URI_FULL); @@ -88,4 +89,10 @@ void FramelessHelper::Quick::registerTypes(QQmlEngine *engine) qmlRegisterModule(QUICK_URI_FULL); } +QuickChromePalette::QuickChromePalette(QObject *parent) : ChromePalette(parent) +{ +} + +QuickChromePalette::~QuickChromePalette() = default; + FRAMELESSHELPER_END_NAMESPACE diff --git a/src/quick/framelessquickutils.cpp b/src/quick/framelessquickutils.cpp index ef2d90a..38a72cd 100644 --- a/src/quick/framelessquickutils.cpp +++ b/src/quick/framelessquickutils.cpp @@ -74,12 +74,12 @@ QColor FramelessQuickUtils::systemAccentColor() const { #ifdef Q_OS_WINDOWS return Utils::getDwmColorizationColor(); -#endif -#ifdef Q_OS_LINUX +#elif defined(Q_OS_LINUX) return Utils::getWmThemeColor(); -#endif -#ifdef Q_OS_MACOS +#elif defined(Q_OS_MACOS) return Utils::getControlsAccentColor(); +#else + return {}; #endif } @@ -121,8 +121,9 @@ QColor FramelessQuickUtils::defaultSystemCloseButtonBackgroundColor() const QColor FramelessQuickUtils::getSystemButtonBackgroundColor(const QuickGlobal::SystemButtonType button, const QuickGlobal::ButtonState state) { - return Utils::calculateSystemButtonBackgroundColor(FRAMELESSHELPER_ENUM_QUICK_TO_CORE(SystemButtonType, button), - FRAMELESSHELPER_ENUM_QUICK_TO_CORE(ButtonState, state)); + return Utils::calculateSystemButtonBackgroundColor( + FRAMELESSHELPER_ENUM_QUICK_TO_CORE(SystemButtonType, button), + FRAMELESSHELPER_ENUM_QUICK_TO_CORE(ButtonState, state)); } FRAMELESSHELPER_END_NAMESPACE diff --git a/src/quick/quickstandardsystembutton.cpp b/src/quick/quickstandardsystembutton.cpp index 4a9308e..e57119b 100644 --- a/src/quick/quickstandardsystembutton.cpp +++ b/src/quick/quickstandardsystembutton.cpp @@ -26,7 +26,6 @@ #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #include #include -#include #include #include #include @@ -49,6 +48,36 @@ QuickStandardSystemButton::QuickStandardSystemButton(const QuickGlobal::SystemBu QuickStandardSystemButton::~QuickStandardSystemButton() = default; +QuickGlobal::SystemButtonType QuickStandardSystemButton::buttonType() const +{ + return m_buttonType; +} + +QString QuickStandardSystemButton::code() const +{ + return m_code; +} + +QColor QuickStandardSystemButton::color() const +{ + return m_color; +} + +QColor QuickStandardSystemButton::normalColor() const +{ + return m_normalColor; +} + +QColor QuickStandardSystemButton::hoverColor() const +{ + return m_hoverColor; +} + +QColor QuickStandardSystemButton::pressColor() const +{ + return m_pressColor; +} + void QuickStandardSystemButton::setButtonType(const QuickGlobal::SystemButtonType type) { Q_ASSERT(type != QuickGlobal::SystemButtonType::Unknown); @@ -59,50 +88,103 @@ void QuickStandardSystemButton::setButtonType(const QuickGlobal::SystemButtonTyp return; } m_buttonType = type; - m_settingIconCode = true; + setCode(Utils::getSystemButtonIconCode( + FRAMELESSHELPER_ENUM_QUICK_TO_CORE(SystemButtonType, m_buttonType))); + Q_EMIT buttonTypeChanged(); +} + +void QuickStandardSystemButton::setCode(const QString &value) +{ + Q_ASSERT(!value.isEmpty()); + if (value.isEmpty()) { + return; + } + if (m_code == value) { + return; + } + m_code = value; + m_contentItem->setText(m_code); + Q_EMIT codeChanged(); +} + +void QuickStandardSystemButton::setColor(const QColor &value) +{ + Q_ASSERT(value.isValid()); + if (!value.isValid()) { + return; + } + if (m_color == value) { + return; + } + m_color = value; updateForeground(); - m_settingIconCode = false; + Q_EMIT colorChanged(); +} + +void QuickStandardSystemButton::setNormalColor(const QColor &value) +{ + Q_ASSERT(value.isValid()); + if (!value.isValid()) { + return; + } + if (m_normalColor == value) { + return; + } + m_normalColor = value; + updateBackground(); + Q_EMIT normalColorChanged(); +} + +void QuickStandardSystemButton::setHoverColor(const QColor &value) +{ + Q_ASSERT(value.isValid()); + if (!value.isValid()) { + return; + } + if (m_hoverColor == value) { + return; + } + m_hoverColor = value; + updateBackground(); + Q_EMIT hoverColorChanged(); +} + +void QuickStandardSystemButton::setPressColor(const QColor &value) +{ + Q_ASSERT(value.isValid()); + if (!value.isValid()) { + return; + } + if (m_pressColor == value) { + return; + } + m_pressColor = value; + updateBackground(); + Q_EMIT pressColorChanged(); } void QuickStandardSystemButton::updateForeground() { - if (m_buttonType == QuickGlobal::SystemButtonType::Unknown) { - return; - } - if (m_settingIconCode) { - const QString iconCode = Utils::getSystemButtonIconCode( - FRAMELESSHELPER_ENUM_QUICK_TO_CORE(SystemButtonType, m_buttonType)); - if (m_contentItem->text() != iconCode) { - m_contentItem->setText(iconCode); - } - } - const QColor iconColor = [this]() -> QColor { - const bool active = [this]() -> bool { - const QQuickWindow * const w = window(); - return (w ? w->isActive() : false); - }(); - if (!active) { - return kDefaultDarkGrayColor; - } - if (Utils::isTitleBarColorized()) { - return kDefaultWhiteColor; - } - return kDefaultBlackColor; - }(); - if (m_contentItem->color() != iconColor) { - m_contentItem->setColor(iconColor); - } + m_contentItem->setColor(m_color.isValid() ? m_color : kDefaultBlackColor); } void QuickStandardSystemButton::updateBackground() { const bool hover = isHovered(); const bool press = isPressed(); - m_backgroundItem->setColor(Utils::calculateSystemButtonBackgroundColor( - FRAMELESSHELPER_ENUM_QUICK_TO_CORE(SystemButtonType, m_buttonType), - (press ? ButtonState::Pressed : ButtonState::Hovered))); - m_backgroundItem->setVisible(hover || press); - qobject_cast(qmlAttachedPropertiesObject(this))->setVisible(hover); + m_backgroundItem->setColor([this, hover, press]() -> QColor { + if (press && m_pressColor.isValid()) { + return m_pressColor; + } + if (hover && m_hoverColor.isValid()) { + return m_hoverColor; + } + if (m_normalColor.isValid()) { + return m_normalColor; + } + return kDefaultTransparentColor; + }()); + qobject_cast(qmlAttachedPropertiesObject(this))->setVisible(hover || press); } void QuickStandardSystemButton::initialize() @@ -123,7 +205,6 @@ void QuickStandardSystemButton::initialize() border->setWidth(0.0); border->setColor(kDefaultTransparentColor); connect(this, &QuickStandardSystemButton::hoveredChanged, this, &QuickStandardSystemButton::updateBackground); - connect(this, &QuickStandardSystemButton::hoveredChanged, this, &QuickStandardSystemButton::updateForeground); connect(this, &QuickStandardSystemButton::pressedChanged, this, &QuickStandardSystemButton::updateBackground); updateBackground(); @@ -133,18 +214,5 @@ void QuickStandardSystemButton::initialize() setBackground(m_backgroundItem.data()); } -void QuickStandardSystemButton::itemChange(const ItemChange change, const ItemChangeData &value) -{ - QQuickButton::itemChange(change, value); - if ((change == ItemSceneChange) && value.window) { - if (m_windowActiveConnection) { - disconnect(m_windowActiveConnection); - m_windowActiveConnection = {}; - } - m_windowActiveConnection = connect(value.window, &QQuickWindow::activeChanged, - this, &QuickStandardSystemButton::updateForeground); - } -} - FRAMELESSHELPER_END_NAMESPACE #endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) diff --git a/src/quick/quickstandardtitlebar.cpp b/src/quick/quickstandardtitlebar.cpp index 1ca2b2e..8e4e5e3 100644 --- a/src/quick/quickstandardtitlebar.cpp +++ b/src/quick/quickstandardtitlebar.cpp @@ -26,8 +26,6 @@ #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #include "quickstandardsystembutton_p.h" #include "framelessquickwindow_p.h" -#include -#include #include #include #include @@ -129,20 +127,6 @@ void QuickStandardTitleBar::setExtended(const bool value) Q_EMIT extendedChanged(); } -bool QuickStandardTitleBar::isUsingAlternativeBackground() const -{ - return m_useAlternativeBackground; -} - -void QuickStandardTitleBar::setUseAlternativeBackground(const bool value) -{ - if (m_useAlternativeBackground == value) { - return; - } - m_useAlternativeBackground = value; - Q_EMIT useAlternativeBackgroundChanged(); -} - bool QuickStandardTitleBar::isHideWhenClose() const { return m_hideWhenClose; @@ -157,6 +141,11 @@ void QuickStandardTitleBar::setHideWhenClose(const bool value) Q_EMIT hideWhenCloseChanged(); } +QuickChromePalette *QuickStandardTitleBar::chromePalette() const +{ + return m_chromePalette.data(); +} + void QuickStandardTitleBar::updateMaximizeButton() { const QQuickWindow * const w = window(); @@ -184,45 +173,43 @@ void QuickStandardTitleBar::updateTitleBarColor() return; } const bool active = w->isActive(); - const bool dark = Utils::shouldAppsUseDarkMode(); - const bool colorizedTitleBar = Utils::isTitleBarColorized(); - QColor backgroundColor = {}; - QColor foregroundColor = {}; - if (active) { - if (colorizedTitleBar) { -#ifdef Q_OS_WINDOWS - backgroundColor = Utils::getDwmColorizationColor(); -#endif -#ifdef Q_OS_LINUX - backgroundColor = Utils::getWmThemeColor(); -#endif -#ifdef Q_OS_MACOS - backgroundColor = Utils::getControlsAccentColor(); -#endif - foregroundColor = kDefaultWhiteColor; - } else { - if (dark) { - backgroundColor = kDefaultBlackColor; - foregroundColor = kDefaultWhiteColor; - } else { - backgroundColor = kDefaultWhiteColor; - foregroundColor = kDefaultBlackColor; - } - } - } else { - if (dark) { - backgroundColor = kDefaultSystemDarkColor; - } else { - backgroundColor = kDefaultWhiteColor; - } - foregroundColor = kDefaultDarkGrayColor; - } - if (!m_useAlternativeBackground) { - setColor(backgroundColor); - } + const QColor backgroundColor = (active ? + m_chromePalette->titleBarActiveBackgroundColor() : + m_chromePalette->titleBarInactiveBackgroundColor()); + const QColor foregroundColor = (active ? + m_chromePalette->titleBarActiveForegroundColor() : + m_chromePalette->titleBarInactiveForegroundColor()); + setColor(backgroundColor); m_windowTitleLabel->setColor(foregroundColor); } +void QuickStandardTitleBar::updateChromeButtonColor() +{ + const QQuickWindow * const w = window(); + if (!w) { + return; + } + const bool active = w->isActive(); + const QColor color = (active ? + m_chromePalette->titleBarActiveForegroundColor() : + m_chromePalette->titleBarInactiveForegroundColor()); + const QColor normal = m_chromePalette->chromeButtonNormalColor(); + const QColor hover = m_chromePalette->chromeButtonHoverColor(); + const QColor press = m_chromePalette->chromeButtonPressColor(); + m_minimizeButton->setColor(color); + m_minimizeButton->setNormalColor(normal); + m_minimizeButton->setHoverColor(hover); + m_minimizeButton->setPressColor(press); + m_maximizeButton->setColor(color); + m_maximizeButton->setNormalColor(normal); + m_maximizeButton->setHoverColor(hover); + m_maximizeButton->setPressColor(press); + m_closeButton->setColor(color); + m_closeButton->setNormalColor(normal); + m_closeButton->setHoverColor(hover); + m_closeButton->setPressColor(press); +} + void QuickStandardTitleBar::clickMinimizeButton() { QQuickWindow * const w = window(); @@ -278,6 +265,12 @@ void QuickStandardTitleBar::retranslateUi() void QuickStandardTitleBar::initialize() { + m_chromePalette.reset(new QuickChromePalette(this)); + connect(m_chromePalette.data(), &ChromePalette::titleBarColorChanged, + this, &QuickStandardTitleBar::updateTitleBarColor); + connect(m_chromePalette.data(), &ChromePalette::chromeButtonColorChanged, + this, &QuickStandardTitleBar::updateChromeButtonColor); + QQuickPen * const b = border(); b->setWidth(0.0); b->setColor(kDefaultTransparentColor); @@ -300,8 +293,6 @@ void QuickStandardTitleBar::initialize() m_closeButton.reset(new QuickStandardSystemButton(QuickGlobal::SystemButtonType::Close, m_systemButtonsRow.data())); connect(m_closeButton.data(), &QuickStandardSystemButton::clicked, this, &QuickStandardTitleBar::clickCloseButton); - connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged, this, &QuickStandardTitleBar::updateTitleBarColor); - setTitleLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter); retranslateUi(); updateAll(); @@ -324,7 +315,10 @@ void QuickStandardTitleBar::itemChange(const ItemChange change, const ItemChange m_windowTitleChangeConnection = {}; } m_windowStateChangeConnection = connect(value.window, &QQuickWindow::visibilityChanged, this, &QuickStandardTitleBar::updateMaximizeButton); - m_windowActiveChangeConnection = connect(value.window, &QQuickWindow::activeChanged, this, &QuickStandardTitleBar::updateTitleBarColor); + m_windowActiveChangeConnection = connect(value.window, &QQuickWindow::activeChanged, this, [this](){ + updateTitleBarColor(); + updateChromeButtonColor(); + }); m_windowTitleChangeConnection = connect(value.window, &QQuickWindow::windowTitleChanged, this, &QuickStandardTitleBar::updateTitleLabelText); updateAll(); value.window->installEventFilter(this); @@ -344,6 +338,7 @@ void QuickStandardTitleBar::updateAll() updateMaximizeButton(); updateTitleLabelText(); updateTitleBarColor(); + updateChromeButtonColor(); } FRAMELESSHELPER_END_NAMESPACE diff --git a/src/widgets/standardsystembutton.cpp b/src/widgets/standardsystembutton.cpp index f0381c4..0398965 100644 --- a/src/widgets/standardsystembutton.cpp +++ b/src/widgets/standardsystembutton.cpp @@ -26,7 +26,6 @@ #include "standardsystembutton_p.h" #include #include -#include #include #include @@ -66,24 +65,24 @@ const StandardSystemButtonPrivate *StandardSystemButtonPrivate::get(const Standa return pub->d_func(); } -QString StandardSystemButtonPrivate::getIconCode() const +QString StandardSystemButtonPrivate::getCode() const { - return m_iconCode; + return m_code; } -void StandardSystemButtonPrivate::setIconCode(const QString &value) +void StandardSystemButtonPrivate::setCode(const QString &value) { Q_ASSERT(!value.isEmpty()); if (value.isEmpty()) { return; } - if (m_iconCode == value) { + if (m_code == value) { return; } - m_iconCode = value; + m_code = value; Q_Q(StandardSystemButton); q->update(); - Q_EMIT q->iconCodeChanged(); + Q_EMIT q->codeChanged(); } SystemButtonType StandardSystemButtonPrivate::getButtonType() const @@ -101,8 +100,7 @@ void StandardSystemButtonPrivate::setButtonType(const SystemButtonType type) return; } m_buttonType = type; - setIconCode(Utils::getSystemButtonIconCode(m_buttonType)); - updateBackgroundColor(); + setCode(Utils::getSystemButtonIconCode(m_buttonType)); Q_Q(StandardSystemButton); q->update(); } @@ -132,9 +130,14 @@ QColor StandardSystemButtonPrivate::getPressColor() const return m_pressColor; } -QColor StandardSystemButtonPrivate::getIconColor() const +QColor StandardSystemButtonPrivate::getNormalColor() const { - return m_iconColor; + return m_normalColor; +} + +QColor StandardSystemButtonPrivate::getColor() const +{ + return m_color; } void StandardSystemButtonPrivate::setHovered(const bool value) @@ -214,28 +217,34 @@ void StandardSystemButtonPrivate::setPressColor(const QColor &value) Q_EMIT q->pressColorChanged(); } -void StandardSystemButtonPrivate::setIconColor(const QColor &value) +void StandardSystemButtonPrivate::setNormalColor(const QColor &value) { Q_ASSERT(value.isValid()); if (!value.isValid()) { return; } - if (m_iconColor == value) { + if (m_normalColor == value) { return; } - m_iconColor = value; + m_normalColor = value; Q_Q(StandardSystemButton); q->update(); - Q_EMIT q->iconColorChanged(); + Q_EMIT q->normalColorChanged(); } -void StandardSystemButtonPrivate::updateBackgroundColor() +void StandardSystemButtonPrivate::setColor(const QColor &value) { - if (m_buttonType == SystemButtonType::Unknown) { + Q_ASSERT(value.isValid()); + if (!value.isValid()) { return; } - setHoverColor(Utils::calculateSystemButtonBackgroundColor(m_buttonType, ButtonState::Hovered)); - setPressColor(Utils::calculateSystemButtonBackgroundColor(m_buttonType, ButtonState::Pressed)); + if (m_color == value) { + return; + } + m_color = value; + Q_Q(StandardSystemButton); + q->update(); + Q_EMIT q->colorChanged(); } void StandardSystemButtonPrivate::enterEventHandler(QT_ENTER_EVENT_TYPE *event) @@ -271,34 +280,22 @@ void StandardSystemButtonPrivate::paintEventHandler(QPaintEvent *event) // The pressed state has higher priority than the hovered state. if (m_pressed && m_pressColor.isValid()) { return m_pressColor; - } else if (m_hovered && m_hoverColor.isValid()) { + } + if (m_hovered && m_hoverColor.isValid()) { return m_hoverColor; } + if (m_normalColor.isValid()) { + return m_normalColor; + } return {}; }(); if (backgroundColor.isValid()) { painter.fillRect(g_buttonRect, backgroundColor); } - if (!m_iconCode.isEmpty()) { - const QColor iconColor = [this, q]() -> QColor { - if (m_iconColor.isValid()) { - return m_iconColor; - } - const bool active = [q]() -> bool { - const QWidget * const window = q->window(); - return (window ? window->isActiveWindow() : false); - }(); - if (!active) { - return kDefaultDarkGrayColor; - } - if (Utils::isTitleBarColorized()) { - return kDefaultWhiteColor; - } - return kDefaultBlackColor; - }(); - painter.setPen(iconColor); + if (!m_code.isEmpty() && m_color.isValid()) { + painter.setPen(m_color); painter.setFont(FramelessManagerPrivate::getIconFont()); - painter.drawText(g_buttonRect, Qt::AlignCenter, m_iconCode); + painter.drawText(g_buttonRect, Qt::AlignCenter, m_code); } painter.restore(); } @@ -312,8 +309,6 @@ void StandardSystemButtonPrivate::initialize() q->setIconSize(kDefaultSystemButtonIconSize); connect(q, &StandardSystemButton::pressed, this, [this](){ setPressed(true); }); connect(q, &StandardSystemButton::released, this, [this](){ setPressed(false); }); - connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged, - this, [this](){ updateBackgroundColor(); }); } StandardSystemButton::StandardSystemButton(QWidget *parent) : QAbstractButton(parent), d_ptr(new StandardSystemButtonPrivate(this)) @@ -339,10 +334,10 @@ SystemButtonType StandardSystemButton::buttonType() return d->getButtonType(); } -QString StandardSystemButton::iconCode() const +QString StandardSystemButton::code() const { Q_D(const StandardSystemButton); - return d->getIconCode(); + return d->getCode(); } void StandardSystemButton::setButtonType(const SystemButtonType value) @@ -351,10 +346,10 @@ void StandardSystemButton::setButtonType(const SystemButtonType value) d->setButtonType(value); } -void StandardSystemButton::setIconCode(const QString &code) +void StandardSystemButton::setCode(const QString &code) { Q_D(StandardSystemButton); - d->setIconCode(code); + d->setCode(code); } bool StandardSystemButton::isHovered() const @@ -399,10 +394,16 @@ QColor StandardSystemButton::pressColor() const return d->getPressColor(); } -QColor StandardSystemButton::iconColor() const +QColor StandardSystemButton::normalColor() const { Q_D(const StandardSystemButton); - return d->getIconColor(); + return d->getNormalColor(); +} + +QColor StandardSystemButton::color() const +{ + Q_D(const StandardSystemButton); + return d->getColor(); } void StandardSystemButton::setPressColor(const QColor &value) @@ -411,10 +412,16 @@ void StandardSystemButton::setPressColor(const QColor &value) d->setPressColor(value); } -void StandardSystemButton::setIconColor(const QColor &value) +void StandardSystemButton::setNormalColor(const QColor &value) { Q_D(StandardSystemButton); - d->setIconColor(value); + d->setNormalColor(value); +} + +void StandardSystemButton::setColor(const QColor &value) +{ + Q_D(StandardSystemButton); + d->setColor(value); } void StandardSystemButton::enterEvent(QT_ENTER_EVENT_TYPE *event) diff --git a/src/widgets/standardtitlebar.cpp b/src/widgets/standardtitlebar.cpp index ce09a87..e85d22b 100644 --- a/src/widgets/standardtitlebar.cpp +++ b/src/widgets/standardtitlebar.cpp @@ -26,20 +26,17 @@ #include "standardtitlebar_p.h" #include "standardsystembutton.h" #include -#include #include #include -#include #include -#include -#include +#include FRAMELESSHELPER_BEGIN_NAMESPACE using namespace Global; -FRAMELESSHELPER_STRING_CONSTANT2(StyleSheetColorTemplate, "color: %1;") -FRAMELESSHELPER_STRING_CONSTANT2(StyleSheetBackgroundColorTemplate, "background-color: %1;") +FRAMELESSHELPER_STRING_CONSTANT2(StyleSheetColorTemplate, "color: rgba(%1, %2, %3, %4);") +FRAMELESSHELPER_STRING_CONSTANT2(StyleSheetBackgroundColorTemplate, "background-color: rgba(%1, %2, %3, %4);") StandardTitleBarPrivate::StandardTitleBarPrivate(StandardTitleBar *q) : QObject(q) { @@ -123,21 +120,6 @@ void StandardTitleBarPrivate::setExtended(const bool value) Q_EMIT q->extendedChanged(); } -bool StandardTitleBarPrivate::isUsingAlternativeBackground() const -{ - return m_useAlternativeBackground; -} - -void StandardTitleBarPrivate::setUseAlternativeBackground(const bool value) -{ - if (m_useAlternativeBackground == value) { - return; - } - m_useAlternativeBackground = value; - Q_Q(StandardTitleBar); - Q_EMIT q->useAlternativeBackgroundChanged(); -} - bool StandardTitleBarPrivate::isHideWhenClose() const { return m_hideWhenClose; @@ -153,6 +135,25 @@ void StandardTitleBarPrivate::setHideWhenClose(const bool value) Q_EMIT q->hideWhenCloseChanged(); } +ChromePalette *StandardTitleBarPrivate::chromePalette() const +{ + return m_chromePalette.data(); +} + +void StandardTitleBarPrivate::paintTitleBar(QPaintEvent *event) +{ + Q_UNUSED(event); + Q_Q(StandardTitleBar); + // This block of code ensures that our widget can still apply the stylesheet correctly. + // Enabling the "Qt::WA_StyledBackground" attribute can also achieve the same + // effect, but since it's documented as only for internal uses, we use the + // public way to do that instead. + QStyleOption option; + option.initFrom(q); + QStylePainter painter(q); + painter.drawPrimitive(QStyle::PE_Widget, option); +} + void StandardTitleBarPrivate::updateMaximizeButton() { const bool max = m_window->isMaximized(); @@ -160,44 +161,45 @@ void StandardTitleBarPrivate::updateMaximizeButton() m_maximizeButton->setToolTip(max ? tr("Restore") : tr("Maximize")); } -void StandardTitleBarPrivate::updateTitleBarStyleSheet() +void StandardTitleBarPrivate::updateTitleBarColor() { const bool active = m_window->isActiveWindow(); - const bool dark = Utils::shouldAppsUseDarkMode(); - const bool colorizedTitleBar = Utils::isTitleBarColorized(); - const QColor titleBarBackgroundColor = [active, colorizedTitleBar, dark]() -> QColor { - if (active) { - if (colorizedTitleBar) { -#ifdef Q_OS_WINDOWS - return Utils::getDwmColorizationColor(); -#endif -#ifdef Q_OS_LINUX - return Utils::getWmThemeColor(); -#endif -#ifdef Q_OS_MACOS - return Utils::getControlsAccentColor(); -#endif - } else { - if (dark) { - return kDefaultBlackColor; - } else { - return kDefaultWhiteColor; - } - } - } else { - if (dark) { - return kDefaultSystemDarkColor; - } else { - return kDefaultWhiteColor; - } - } - }(); - const QColor windowTitleLabelTextColor = (active ? ((dark || colorizedTitleBar) ? kDefaultWhiteColor : kDefaultBlackColor) : kDefaultDarkGrayColor); - m_windowTitleLabel->setStyleSheet(kStyleSheetColorTemplate.arg(windowTitleLabelTextColor.name())); - if (!m_useAlternativeBackground) { - Q_Q(StandardTitleBar); - q->setStyleSheet(kStyleSheetBackgroundColorTemplate.arg(titleBarBackgroundColor.name())); - } + const QColor backgroundColor = (active ? + m_chromePalette->titleBarActiveBackgroundColor() : + m_chromePalette->titleBarInactiveBackgroundColor()); + const QColor foregroundColor = (active ? + m_chromePalette->titleBarActiveForegroundColor() : + m_chromePalette->titleBarInactiveForegroundColor()); + m_windowTitleLabel->setStyleSheet(kStyleSheetColorTemplate.arg( + QString::number(foregroundColor.red()), QString::number(foregroundColor.green()), + QString::number(foregroundColor.blue()), QString::number(foregroundColor.alpha()))); + Q_Q(StandardTitleBar); + q->setStyleSheet(kStyleSheetBackgroundColorTemplate.arg( + QString::number(backgroundColor.red()), QString::number(backgroundColor.green()), + QString::number(backgroundColor.blue()), QString::number(backgroundColor.alpha()))); +} + +void StandardTitleBarPrivate::updateChromeButtonColor() +{ + const bool active = m_window->isActiveWindow(); + const QColor color = (active ? + m_chromePalette->titleBarActiveForegroundColor() : + m_chromePalette->titleBarInactiveForegroundColor()); + const QColor normal = m_chromePalette->chromeButtonNormalColor(); + const QColor hover = m_chromePalette->chromeButtonHoverColor(); + const QColor press = m_chromePalette->chromeButtonPressColor(); + m_minimizeButton->setColor(color); + m_minimizeButton->setNormalColor(normal); + m_minimizeButton->setHoverColor(hover); + m_minimizeButton->setPressColor(press); + m_maximizeButton->setColor(color); + m_maximizeButton->setNormalColor(normal); + m_maximizeButton->setHoverColor(hover); + m_maximizeButton->setPressColor(press); + m_closeButton->setColor(color); + m_closeButton->setNormalColor(normal); + m_closeButton->setHoverColor(hover); + m_closeButton->setPressColor(press); } void StandardTitleBarPrivate::retranslateUi() @@ -226,7 +228,8 @@ bool StandardTitleBarPrivate::eventFilter(QObject *object, QEvent *event) updateMaximizeButton(); break; case QEvent::ActivationChange: - updateTitleBarStyleSheet(); + updateTitleBarColor(); + updateChromeButtonColor(); break; case QEvent::LanguageChange: retranslateUi(); @@ -241,6 +244,11 @@ void StandardTitleBarPrivate::initialize() { Q_Q(StandardTitleBar); m_window = (q->nativeParentWidget() ? q->nativeParentWidget() : q->window()); + m_chromePalette.reset(new ChromePalette(this)); + connect(m_chromePalette.data(), &ChromePalette::titleBarColorChanged, + this, &StandardTitleBarPrivate::updateTitleBarColor); + connect(m_chromePalette.data(), &ChromePalette::chromeButtonColorChanged, + this, &StandardTitleBarPrivate::updateChromeButtonColor); q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); q->setFixedHeight(kDefaultTitleBarHeight); m_windowTitleLabel.reset(new QLabel(q)); @@ -299,9 +307,8 @@ void StandardTitleBarPrivate::initialize() q->setLayout(titleBarLayout); setTitleLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter); retranslateUi(); - updateTitleBarStyleSheet(); - connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged, - this, &StandardTitleBarPrivate::updateTitleBarStyleSheet); + updateTitleBarColor(); + updateChromeButtonColor(); m_window->installEventFilter(this); } @@ -360,18 +367,6 @@ void StandardTitleBar::setExtended(const bool value) d->setExtended(value); } -bool StandardTitleBar::isUsingAlternativeBackground() const -{ - Q_D(const StandardTitleBar); - return d->isUsingAlternativeBackground(); -} - -void StandardTitleBar::setUseAlternativeBackground(const bool value) -{ - Q_D(StandardTitleBar); - d->setUseAlternativeBackground(value); -} - bool StandardTitleBar::isHideWhenClose() const { Q_D(const StandardTitleBar); @@ -384,17 +379,16 @@ void StandardTitleBar::setHideWhenClose(const bool value) d->setHideWhenClose(value); } +ChromePalette *StandardTitleBar::chromePalette() const +{ + Q_D(const StandardTitleBar); + return d->chromePalette(); +} + void StandardTitleBar::paintEvent(QPaintEvent *event) { - Q_UNUSED(event); - // This block of code ensures that our widget can still apply the stylesheet correctly. - // Enabling the "Qt::WA_StyledBackground" attribute can also achieve the same - // effect, but since it's documented as only for internal uses, we use the - // public way to do that instead. - QStyleOption option; - option.initFrom(this); - QPainter painter(this); - style()->drawPrimitive(QStyle::PE_Widget, &option, &painter, this); + Q_D(StandardTitleBar); + d->paintTitleBar(event); } FRAMELESSHELPER_END_NAMESPACE