diff --git a/include/FramelessHelper/Quick/private/quickstandardclosebutton_p.h b/include/FramelessHelper/Quick/private/quickstandardclosebutton_p.h index 017aef19..fa1c2a4e 100644 --- a/include/FramelessHelper/Quick/private/quickstandardclosebutton_p.h +++ b/include/FramelessHelper/Quick/private/quickstandardclosebutton_p.h @@ -47,17 +47,22 @@ class FRAMELESSHELPER_QUICK_API QuickStandardCloseButton : public QQuickButton explicit QuickStandardCloseButton(QQuickItem *parent = nullptr); ~QuickStandardCloseButton() override; -private Q_SLOTS: +public Q_SLOTS: void updateForeground(); void updateBackground(); + void setInactive(const bool value); private: void initialize(); + void checkInactive(); private: QScopedPointer m_contentItem; QScopedPointer m_image; QScopedPointer m_backgroundItem; + bool m_forceLightTheme = false; + bool m_shouldCheck = false; + bool m_checkFlag = false; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Quick/private/quickstandardmaximizebutton_p.h b/include/FramelessHelper/Quick/private/quickstandardmaximizebutton_p.h index e2824f84..e72fca10 100644 --- a/include/FramelessHelper/Quick/private/quickstandardmaximizebutton_p.h +++ b/include/FramelessHelper/Quick/private/quickstandardmaximizebutton_p.h @@ -51,21 +51,26 @@ class FRAMELESSHELPER_QUICK_API QuickStandardMaximizeButton : public QQuickButto Q_NODISCARD bool isMaximized() const; void setMaximized(const bool max); -private Q_SLOTS: +public Q_SLOTS: void updateForeground(); void updateBackground(); + void setInactive(const bool value); Q_SIGNALS: void maximizedChanged(); private: void initialize(); + void checkInactive(); private: bool m_max = false; QScopedPointer m_contentItem; QScopedPointer m_image; QScopedPointer m_backgroundItem; + bool m_forceLightTheme = false; + bool m_shouldCheck = false; + bool m_checkFlag = false; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Quick/private/quickstandardminimizebutton_p.h b/include/FramelessHelper/Quick/private/quickstandardminimizebutton_p.h index 761744da..d2e9355b 100644 --- a/include/FramelessHelper/Quick/private/quickstandardminimizebutton_p.h +++ b/include/FramelessHelper/Quick/private/quickstandardminimizebutton_p.h @@ -47,17 +47,22 @@ class FRAMELESSHELPER_QUICK_API QuickStandardMinimizeButton : public QQuickButto explicit QuickStandardMinimizeButton(QQuickItem *parent = nullptr); ~QuickStandardMinimizeButton() override; -private Q_SLOTS: +public Q_SLOTS: void updateForeground(); void updateBackground(); + void setInactive(const bool value); private: void initialize(); + void checkInactive(); private: QScopedPointer m_contentItem; QScopedPointer m_image; QScopedPointer m_backgroundItem; + bool m_forceLightTheme = false; + bool m_shouldCheck = false; + bool m_checkFlag = false; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/private/standardsystembutton_p.h b/include/FramelessHelper/Widgets/private/standardsystembutton_p.h index 971c187d..9ddb6e71 100644 --- a/include/FramelessHelper/Widgets/private/standardsystembutton_p.h +++ b/include/FramelessHelper/Widgets/private/standardsystembutton_p.h @@ -75,8 +75,11 @@ class FRAMELESSHELPER_WIDGETS_API StandardSystemButtonPrivate : public QObject void leaveEventHandler(QEvent *event); void paintEventHandler(QPaintEvent *event); + void setInactive(const bool value); + private: void initialize(); + void checkInactive(); private: StandardSystemButton *q_ptr = nullptr; @@ -88,6 +91,9 @@ class FRAMELESSHELPER_WIDGETS_API StandardSystemButtonPrivate : public QObject QColor m_pressColor = {}; bool m_hovered = false; bool m_pressed = false; + bool m_forceLightTheme = false; + bool m_shouldCheck = false; + bool m_checkFlag = false; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/src/quick/quickstandardclosebutton.cpp b/src/quick/quickstandardclosebutton.cpp index 0ecbe65b..60b8bfe7 100644 --- a/src/quick/quickstandardclosebutton.cpp +++ b/src/quick/quickstandardclosebutton.cpp @@ -52,7 +52,7 @@ QuickStandardCloseButton::~QuickStandardCloseButton() = default; void QuickStandardCloseButton::updateForeground() { - const bool dark = (Utils::shouldAppsUseDarkMode() || Utils::isTitleBarColorized()); + const bool dark = ((Utils::shouldAppsUseDarkMode() || Utils::isTitleBarColorized()) && !m_forceLightTheme); const auto url = QUrl((dark || isHovered() || isPressed()) ? kDarkUrl : kLightUrl); initResource(); m_image->setSource(url); @@ -65,9 +65,31 @@ void QuickStandardCloseButton::updateBackground() const bool press = isPressed(); m_backgroundItem->setColor(Utils::calculateSystemButtonBackgroundColor(button, (press ? ButtonState::Pressed : ButtonState::Hovered))); m_backgroundItem->setVisible(hover || press); + checkInactive(); qobject_cast(qmlAttachedPropertiesObject(this))->setVisible(hover); } +void QuickStandardCloseButton::setInactive(const bool value) +{ + const bool force = (value && Utils::isTitleBarColorized() && !Utils::shouldAppsUseDarkMode()); + if (m_forceLightTheme == force) { + return; + } + m_forceLightTheme = force; + m_shouldCheck = m_forceLightTheme; + updateForeground(); +} + +void QuickStandardCloseButton::checkInactive() +{ + if (!m_shouldCheck) { + return; + } + m_forceLightTheme = m_checkFlag; + m_checkFlag = !m_checkFlag; + updateForeground(); +} + void QuickStandardCloseButton::initialize() { setImplicitWidth(kDefaultSystemButtonSize.width()); diff --git a/src/quick/quickstandardmaximizebutton.cpp b/src/quick/quickstandardmaximizebutton.cpp index c788a765..7d30e6e9 100644 --- a/src/quick/quickstandardmaximizebutton.cpp +++ b/src/quick/quickstandardmaximizebutton.cpp @@ -68,7 +68,7 @@ void QuickStandardMaximizeButton::setMaximized(const bool max) void QuickStandardMaximizeButton::updateForeground() { - const bool dark = (Utils::shouldAppsUseDarkMode() || Utils::isTitleBarColorized()); + const bool dark = ((Utils::shouldAppsUseDarkMode() || Utils::isTitleBarColorized()) && !m_forceLightTheme); const auto url = QUrl(dark ? (m_max ? kDarkRestoreUrl : kDarkMaxUrl) : (m_max ? kLightRestoreUrl : kLightMaxUrl)); initResource(); m_image->setSource(url); @@ -81,9 +81,31 @@ void QuickStandardMaximizeButton::updateBackground() const bool press = isPressed(); m_backgroundItem->setColor(Utils::calculateSystemButtonBackgroundColor(button, (press ? ButtonState::Pressed : ButtonState::Hovered))); m_backgroundItem->setVisible(hover || press); + checkInactive(); qobject_cast(qmlAttachedPropertiesObject(this))->setVisible(hover); } +void QuickStandardMaximizeButton::setInactive(const bool value) +{ + const bool force = (value && Utils::isTitleBarColorized() && !Utils::shouldAppsUseDarkMode()); + if (m_forceLightTheme == force) { + return; + } + m_forceLightTheme = force; + m_shouldCheck = m_forceLightTheme; + updateForeground(); +} + +void QuickStandardMaximizeButton::checkInactive() +{ + if (!m_shouldCheck) { + return; + } + m_forceLightTheme = m_checkFlag; + m_checkFlag = !m_checkFlag; + updateForeground(); +} + void QuickStandardMaximizeButton::initialize() { setImplicitWidth(kDefaultSystemButtonSize.width()); diff --git a/src/quick/quickstandardminimizebutton.cpp b/src/quick/quickstandardminimizebutton.cpp index b0e3a402..982d8b16 100644 --- a/src/quick/quickstandardminimizebutton.cpp +++ b/src/quick/quickstandardminimizebutton.cpp @@ -52,7 +52,7 @@ QuickStandardMinimizeButton::~QuickStandardMinimizeButton() = default; void QuickStandardMinimizeButton::updateForeground() { - const bool dark = (Utils::shouldAppsUseDarkMode() || Utils::isTitleBarColorized()); + const bool dark = ((Utils::shouldAppsUseDarkMode() || Utils::isTitleBarColorized()) && !m_forceLightTheme); const auto url = QUrl(dark ? kDarkUrl : kLightUrl); initResource(); m_image->setSource(url); @@ -65,9 +65,31 @@ void QuickStandardMinimizeButton::updateBackground() const bool press = isPressed(); m_backgroundItem->setColor(Utils::calculateSystemButtonBackgroundColor(button, (press ? ButtonState::Pressed : ButtonState::Hovered))); m_backgroundItem->setVisible(hover || press); + checkInactive(); qobject_cast(qmlAttachedPropertiesObject(this))->setVisible(hover); } +void QuickStandardMinimizeButton::setInactive(const bool value) +{ + const bool force = (value && Utils::isTitleBarColorized() && !Utils::shouldAppsUseDarkMode()); + if (m_forceLightTheme == force) { + return; + } + m_forceLightTheme = force; + m_shouldCheck = m_forceLightTheme; + updateForeground(); +} + +void QuickStandardMinimizeButton::checkInactive() +{ + if (!m_shouldCheck) { + return; + } + m_forceLightTheme = m_checkFlag; + m_checkFlag = !m_checkFlag; + updateForeground(); +} + void QuickStandardMinimizeButton::initialize() { setImplicitWidth(kDefaultSystemButtonSize.width()); diff --git a/src/quick/quickstandardtitlebar.cpp b/src/quick/quickstandardtitlebar.cpp index aab84337..7cabce26 100644 --- a/src/quick/quickstandardtitlebar.cpp +++ b/src/quick/quickstandardtitlebar.cpp @@ -155,9 +155,10 @@ void QuickStandardTitleBar::updateTitleBarColor() if (!w) { return; } + const bool active = w->isActive(); QColor backgroundColor = {}; QColor foregroundColor = {}; - if (w->isActive()) { + if (active) { if (Utils::isTitleBarColorized()) { #ifdef Q_OS_WINDOWS backgroundColor = Utils::getDwmColorizationColor(); @@ -188,6 +189,9 @@ void QuickStandardTitleBar::updateTitleBarColor() } setColor(backgroundColor); m_windowTitleLabel->setColor(foregroundColor); + m_minimizeButton->setInactive(!active); + m_maximizeButton->setInactive(!active); + m_closeButton->setInactive(!active); } void QuickStandardTitleBar::clickMinimizeButton() diff --git a/src/widgets/standardsystembutton.cpp b/src/widgets/standardsystembutton.cpp index 12897b71..f2883e44 100644 --- a/src/widgets/standardsystembutton.cpp +++ b/src/widgets/standardsystembutton.cpp @@ -73,7 +73,10 @@ void StandardSystemButtonPrivate::refreshButtonTheme(const bool force) if (m_buttonType == SystemButtonType::Unknown) { return; } - const SystemTheme systemTheme = []() -> SystemTheme { + const SystemTheme systemTheme = [this]() -> SystemTheme { + if (m_forceLightTheme) { + return SystemTheme::Light; + } #ifdef Q_OS_WINDOWS if (Utils::isTitleBarColorized()) { return SystemTheme::Dark; @@ -204,7 +207,16 @@ void StandardSystemButtonPrivate::setHovered(const bool value) if (m_hovered) { const QString toolTip = q->toolTip(); if (!toolTip.isEmpty() && !QToolTip::isVisible()) { - QToolTip::showText(q->mapToGlobal(QPoint(0, -(qRound(qreal(q->height()) * 1.3)))), toolTip, q, q->geometry()); + const int yPos = [q]() -> int { + const auto h = qreal(q->height()); + if (const QWidget * const window = q->window()) { + if (Utils::windowStatesToWindowState(window->windowState()) == Qt::WindowMaximized) { + return int(qRound(h * 0.5)); + } + } + return -int(qRound(h * 1.3)); + }(); + QToolTip::showText(q->mapToGlobal(QPoint(-2, yPos)), toolTip, q, q->geometry()); } } else { if (QToolTip::isVisible()) { @@ -299,17 +311,40 @@ void StandardSystemButtonPrivate::paintEventHandler(QPaintEvent *event) painter.fillRect(g_buttonRect, color); } if (!m_icon.isNull()) { - painter.drawPixmap(g_buttonIconX, - g_buttonIconY, - ((m_buttonType == SystemButtonType::Close) - && (m_buttonTheme == SystemTheme::Light) && m_hovered - && !m_reversedIcon.isNull()) - ? m_reversedIcon - : m_icon); + painter.drawPixmap(g_buttonIconX, g_buttonIconY, [this]() -> QPixmap { + if (m_reversedIcon.isNull()) { + return m_icon; + } + if (m_hovered && m_forceLightTheme) { + return m_reversedIcon; + } + return m_icon; + }()); } painter.restore(); } +void StandardSystemButtonPrivate::setInactive(const bool value) +{ + const bool force = (value && Utils::isTitleBarColorized() && !Utils::shouldAppsUseDarkMode()); + if (m_forceLightTheme == force) { + return; + } + m_forceLightTheme = force; + m_shouldCheck = m_forceLightTheme; + refreshButtonTheme(true); +} + +void StandardSystemButtonPrivate::checkInactive() +{ + if (!m_shouldCheck) { + return; + } + m_forceLightTheme = m_checkFlag; + m_checkFlag = !m_checkFlag; + refreshButtonTheme(true); +} + void StandardSystemButtonPrivate::initialize() { Q_Q(StandardSystemButton); diff --git a/src/widgets/standardtitlebar.cpp b/src/widgets/standardtitlebar.cpp index cbb0d8eb..809f6a37 100644 --- a/src/widgets/standardtitlebar.cpp +++ b/src/widgets/standardtitlebar.cpp @@ -25,6 +25,7 @@ #include "standardtitlebar.h" #include "standardtitlebar_p.h" #include "standardsystembutton.h" +#include "standardsystembutton_p.h" #include #include #include @@ -84,13 +85,13 @@ void StandardTitleBarPrivate::setTitleLabelAlignment(const Qt::Alignment value) m_labelAlignment = value; bool needsInvalidate = false; if (m_labelAlignment & Qt::AlignLeft) { - m_labelLeftStretch->changeSize(0, 0); + m_labelLeftStretch->changeSize(kDefaultTitleBarContentsMargin, 0, QSizePolicy::Fixed); m_labelRightStretch->changeSize(0, 0, QSizePolicy::Expanding); needsInvalidate = true; } if (m_labelAlignment & Qt::AlignRight) { m_labelLeftStretch->changeSize(0, 0, QSizePolicy::Expanding); - m_labelRightStretch->changeSize(0, 0); + m_labelRightStretch->changeSize(kDefaultTitleBarContentsMargin, 0, QSizePolicy::Fixed); needsInvalidate = true; } if (m_labelAlignment & Qt::AlignHCenter) { @@ -100,6 +101,8 @@ void StandardTitleBarPrivate::setTitleLabelAlignment(const Qt::Alignment value) } Q_Q(StandardTitleBar); if (needsInvalidate) { + // Tell the layout manager that we have changed the layout item's size + // manually to let it refresh the layout immediately. q->layout()->invalidate(); } Q_EMIT q->titleLabelAlignmentChanged(); @@ -162,6 +165,9 @@ void StandardTitleBarPrivate::updateTitleBarStyleSheet() }(); const QColor windowTitleLabelTextColor = (active ? ((dark || colorizedTitleBar) ? kDefaultWhiteColor : kDefaultBlackColor) : kDefaultDarkGrayColor); m_windowTitleLabel->setStyleSheet(kStyleSheetColorTemplate.arg(windowTitleLabelTextColor.name())); + StandardSystemButtonPrivate::get(m_minimizeButton.data())->setInactive(!active); + StandardSystemButtonPrivate::get(m_maximizeButton.data())->setInactive(!active); + StandardSystemButtonPrivate::get(m_closeButton.data())->setInactive(!active); Q_Q(StandardTitleBar); q->setStyleSheet(kStyleSheetBackgroundColorTemplate.arg(titleBarBackgroundColor.name())); q->update(); @@ -253,9 +259,8 @@ void StandardTitleBarPrivate::initialize() systemButtonsOuterLayout->addLayout(systemButtonsInnerLayout); systemButtonsOuterLayout->addStretch(); const auto titleBarLayout = new QHBoxLayout(q); - titleBarLayout->setContentsMargins(0, 0, 0, 0); titleBarLayout->setSpacing(0); - titleBarLayout->addSpacerItem(new QSpacerItem(kDefaultTitleBarContentsMargin, 0, QSizePolicy::Fixed, QSizePolicy::Fixed)); + titleBarLayout->setContentsMargins(0, 0, 0, 0); titleBarLayout->addLayout(titleLabelLayout); titleBarLayout->addLayout(systemButtonsOuterLayout); q->setLayout(titleBarLayout);