finish the chrome palette implementation

And with some other minor tweaks that improve user experience.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-07-06 14:24:41 +08:00
parent e8dcb6e6fe
commit 464e2af515
18 changed files with 339 additions and 107 deletions

View File

@ -68,10 +68,29 @@ void MainWindow::closeEvent(QCloseEvent *event)
void MainWindow::initialize()
{
m_titleBar.reset(new StandardTitleBar(this));
m_titleBar->setTitleLabelAlignment(Qt::AlignCenter);
m_mainWindow.reset(new Ui::MainWindow);
m_mainWindow->setupUi(this);
QMenuBar * const mb = menuBar();
mb->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
mb->setStyleSheet(FRAMELESSHELPER_STRING_LITERAL(R"(
QMenuBar {
background-color: transparent;
}
QMenuBar::item {
background: transparent;
}
QMenuBar::item:selected {
background: #a8a8a8;
}
QMenuBar::item:pressed {
background: #888888;
}
)"));
const auto titleBarLayout = static_cast<QHBoxLayout *>(m_titleBar->layout());
titleBarLayout->insertWidget(0, mb);

View File

@ -58,6 +58,15 @@ class FRAMELESSHELPER_CORE_API ChromePalette : public QObject
Q_PROPERTY(QColor chromeButtonPressColor READ chromeButtonPressColor
WRITE setChromeButtonPressColor RESET resetChromeButtonPressColor
NOTIFY chromeButtonPressColorChanged FINAL)
Q_PROPERTY(QColor closeButtonNormalColor READ closeButtonNormalColor
WRITE setCloseButtonNormalColor RESET resetCloseButtonNormalColor
NOTIFY closeButtonNormalColorChanged FINAL)
Q_PROPERTY(QColor closeButtonHoverColor READ closeButtonHoverColor
WRITE setCloseButtonHoverColor RESET resetCloseButtonHoverColor
NOTIFY closeButtonHoverColorChanged FINAL)
Q_PROPERTY(QColor closeButtonPressColor READ closeButtonPressColor
WRITE setCloseButtonPressColor RESET resetCloseButtonPressColor
NOTIFY closeButtonPressColorChanged FINAL)
public:
explicit ChromePalette(QObject *parent = nullptr);
@ -70,6 +79,9 @@ public:
Q_NODISCARD QColor chromeButtonNormalColor() const;
Q_NODISCARD QColor chromeButtonHoverColor() const;
Q_NODISCARD QColor chromeButtonPressColor() const;
Q_NODISCARD QColor closeButtonNormalColor() const;
Q_NODISCARD QColor closeButtonHoverColor() const;
Q_NODISCARD QColor closeButtonPressColor() const;
public Q_SLOTS:
void setTitleBarActiveBackgroundColor(const QColor &value);
@ -86,6 +98,12 @@ public Q_SLOTS:
void resetChromeButtonHoverColor();
void setChromeButtonPressColor(const QColor &value);
void resetChromeButtonPressColor();
void setCloseButtonNormalColor(const QColor &value);
void resetCloseButtonNormalColor();
void setCloseButtonHoverColor(const QColor &value);
void resetCloseButtonHoverColor();
void setCloseButtonPressColor(const QColor &value);
void resetCloseButtonPressColor();
Q_SIGNALS:
void titleBarActiveBackgroundColorChanged();
@ -95,6 +113,9 @@ Q_SIGNALS:
void chromeButtonNormalColorChanged();
void chromeButtonHoverColorChanged();
void chromeButtonPressColorChanged();
void closeButtonNormalColorChanged();
void closeButtonHoverColorChanged();
void closeButtonPressColorChanged();
void titleBarColorChanged();
void chromeButtonColorChanged();

View File

@ -188,12 +188,12 @@ using MONITOR_DPI_TYPE = enum MONITOR_DPI_TYPE
using _DWMWINDOWATTRIBUTE = enum _DWMWINDOWATTRIBUTE
{
_DWMWA_USE_HOSTBACKDROPBRUSH = 17,
_DWMWA_USE_HOSTBACKDROPBRUSH = 17, // [set] BOOL, Allows the use of host backdrop brushes for the window.
_DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19, // Undocumented
_DWMWA_USE_IMMERSIVE_DARK_MODE = 20,
_DWMWA_WINDOW_CORNER_PREFERENCE = 33,
_DWMWA_VISIBLE_FRAME_BORDER_THICKNESS = 37,
_DWMWA_SYSTEMBACKDROP_TYPE = 38,
_DWMWA_USE_IMMERSIVE_DARK_MODE = 20, // [set] BOOL, Allows a window to either use the accent color, or dark, according to the user Color Mode preferences.
_DWMWA_WINDOW_CORNER_PREFERENCE = 33, // [set] WINDOW_CORNER_PREFERENCE, Controls the policy that rounds top-level window corners
_DWMWA_VISIBLE_FRAME_BORDER_THICKNESS = 37, // [get] UINT, width of the visible border around a thick frame window
_DWMWA_SYSTEMBACKDROP_TYPE = 38, // [get, set] SYSTEMBACKDROP_TYPE, Controls the system-drawn backdrop material of a window, including behind the non-client area.
_DWMWA_MICA_EFFECT = 1029 // Undocumented
};
@ -254,10 +254,10 @@ using ACCENT_STATE = enum ACCENT_STATE
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3,
ACCENT_ENABLE_BLURBEHIND = 3, // Traditional DWM blur
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, // RS4 1803
ACCENT_USE_HOST_BACKDROP = 5, // RS5 1809
ACCENT_INVALID_STATE = 6
ACCENT_INVALID_STATE = 6 // Using this value will remove the window background
};
using ACCENT_POLICY = struct ACCENT_POLICY

View File

@ -47,7 +47,10 @@ public:
TitleBarInactiveForegroundColor = 0x00000008,
ChromeButtonNormalColor = 0x00000010,
ChromeButtonHoverColor = 0x00000020,
ChromeButtonPressColor = 0x00000040
ChromeButtonPressColor = 0x00000040,
CloseButtonNormalColor = 0x00000080,
CloseButtonHoverColor = 0x00000100,
CloseButtonPressColor = 0x00000200
};
Q_ENUM(MaskFlag)
Q_DECLARE_FLAGS(Mask, MaskFlag)
@ -73,6 +76,9 @@ private:
QColor chromeButtonNormalColor_sys = {};
QColor chromeButtonHoverColor_sys = {};
QColor chromeButtonPressColor_sys = {};
QColor closeButtonNormalColor_sys = {};
QColor closeButtonHoverColor_sys = {};
QColor closeButtonPressColor_sys = {};
// User-defined ones:
QColor titleBarActiveBackgroundColor = {};
QColor titleBarInactiveBackgroundColor = {};
@ -81,6 +87,9 @@ private:
QColor chromeButtonNormalColor = {};
QColor chromeButtonHoverColor = {};
QColor chromeButtonPressColor = {};
QColor closeButtonNormalColor = {};
QColor closeButtonHoverColor = {};
QColor closeButtonPressColor = {};
};
Q_DECLARE_OPERATORS_FOR_FLAGS(ChromePalettePrivate::Mask)

View File

@ -0,0 +1 @@
#include <quickchromepalette.h>

View File

@ -25,7 +25,6 @@
#pragma once
#include <framelesshelpercore_global.h>
#include <chromepalette.h>
#if __has_include(<QtQml/qqmlregistration.h>)
# include <QtQml/qqmlregistration.h>
#else
@ -191,17 +190,4 @@ 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

View File

@ -26,6 +26,7 @@
#include "framelesshelperquick_global.h"
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
#include "quickchromepalette.h"
#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQuickTemplates2/private/qquicklabel_p.h>

View File

@ -0,0 +1,48 @@
/*
* 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 "framelesshelperquick_global.h"
#include <QtQml/qqml.h>
#include <chromepalette.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
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
QML_DECLARE_TYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(QuickChromePalette))

View File

@ -29,8 +29,6 @@
#include <QtCore/qpointer.h>
QT_BEGIN_NAMESPACE
class QLabel;
class QSpacerItem;
class QPaintEvent;
QT_END_NAMESPACE
@ -80,15 +78,12 @@ private:
private:
QPointer<StandardTitleBar> q_ptr = nullptr;
QScopedPointer<QLabel> m_windowTitleLabel;
QScopedPointer<StandardSystemButton> m_minimizeButton;
QScopedPointer<StandardSystemButton> m_maximizeButton;
QScopedPointer<StandardSystemButton> m_closeButton;
QPointer<QWidget> m_window = nullptr;
bool m_extended = false;
Qt::Alignment m_labelAlignment = {};
QSpacerItem *m_labelLeftStretch = nullptr;
QSpacerItem *m_labelRightStretch = nullptr;
bool m_hideWhenClose = false;
QScopedPointer<ChromePalette> m_chromePalette;
};

View File

@ -27,7 +27,6 @@
#include "framelesshelperwidgets_global.h"
#include <chromepalette.h>
#include <QtWidgets/qwidget.h>
#include <QtWidgets/qlabel.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -40,7 +39,6 @@ class FRAMELESSHELPER_WIDGETS_API StandardTitleBar : public QWidget
Q_DECLARE_PRIVATE(StandardTitleBar)
Q_DISABLE_COPY_MOVE(StandardTitleBar)
Q_PROPERTY(Qt::Alignment titleLabelAlignment READ titleLabelAlignment WRITE setTitleLabelAlignment NOTIFY titleLabelAlignmentChanged FINAL)
Q_PROPERTY(QLabel* titleLabel READ titleLabel CONSTANT FINAL)
Q_PROPERTY(StandardSystemButton* minimizeButton READ minimizeButton CONSTANT FINAL)
Q_PROPERTY(StandardSystemButton* maximizeButton READ maximizeButton CONSTANT FINAL)
Q_PROPERTY(StandardSystemButton* closeButton READ closeButton CONSTANT FINAL)
@ -55,7 +53,6 @@ public:
Q_NODISCARD Qt::Alignment titleLabelAlignment() const;
void setTitleLabelAlignment(const Qt::Alignment value);
Q_NODISCARD QLabel *titleLabel() const;
Q_NODISCARD StandardSystemButton *minimizeButton() const;
Q_NODISCARD StandardSystemButton *maximizeButton() const;
Q_NODISCARD StandardSystemButton *closeButton() const;

View File

@ -83,14 +83,31 @@ void ChromePalettePrivate::refresh()
}
}();
titleBarInactiveBackgroundColor_sys = (dark ? kDefaultSystemDarkColor : kDefaultWhiteColor);
// ### TODO: Use dark/light color if background color is light/dark.
titleBarActiveForegroundColor_sys = ((dark || colorized) ? kDefaultWhiteColor : kDefaultBlackColor);
titleBarActiveForegroundColor_sys = [this, dark, colorized]() -> QColor {
if (dark || colorized) {
// Calculate the most appropriate foreground color, based on the
// current background color.
const qreal grayF = (
(0.299 * titleBarActiveBackgroundColor_sys.redF()) +
(0.587 * titleBarActiveBackgroundColor_sys.greenF()) +
(0.114 * titleBarActiveBackgroundColor_sys.blueF()));
if (grayF <= 0.5) {
return kDefaultWhiteColor;
}
}
return kDefaultBlackColor;
}();
titleBarInactiveForegroundColor_sys = kDefaultDarkGrayColor;
chromeButtonNormalColor_sys = kDefaultTransparentColor;
chromeButtonHoverColor_sys =
Utils::calculateSystemButtonBackgroundColor(SystemButtonType::Minimize, ButtonState::Hovered);
chromeButtonPressColor_sys =
Utils::calculateSystemButtonBackgroundColor(SystemButtonType::Minimize, ButtonState::Pressed);
closeButtonNormalColor_sys = kDefaultTransparentColor;
closeButtonHoverColor_sys =
Utils::calculateSystemButtonBackgroundColor(SystemButtonType::Close, ButtonState::Hovered);
closeButtonPressColor_sys =
Utils::calculateSystemButtonBackgroundColor(SystemButtonType::Close, ButtonState::Pressed);
Q_Q(ChromePalette);
Q_EMIT q->titleBarActiveBackgroundColorChanged();
Q_EMIT q->titleBarInactiveBackgroundColorChanged();
@ -99,11 +116,15 @@ void ChromePalettePrivate::refresh()
Q_EMIT q->chromeButtonNormalColorChanged();
Q_EMIT q->chromeButtonHoverColorChanged();
Q_EMIT q->chromeButtonPressColorChanged();
Q_EMIT q->closeButtonNormalColorChanged();
Q_EMIT q->closeButtonHoverColorChanged();
Q_EMIT q->closeButtonPressColorChanged();
Q_EMIT q->titleBarColorChanged();
Q_EMIT q->chromeButtonColorChanged();
}
ChromePalette::ChromePalette(QObject *parent) : QObject(parent), d_ptr(new ChromePalettePrivate(this))
ChromePalette::ChromePalette(QObject *parent) :
QObject(parent), d_ptr(new ChromePalettePrivate(this))
{
}
@ -172,6 +193,33 @@ QColor ChromePalette::chromeButtonPressColor() const
return d->chromeButtonPressColor_sys;
}
QColor ChromePalette::closeButtonNormalColor() const
{
Q_D(const ChromePalette);
if (d->mask & ChromePalettePrivate::MaskFlag::CloseButtonNormalColor) {
return d->closeButtonNormalColor;
}
return d->closeButtonNormalColor_sys;
}
QColor ChromePalette::closeButtonHoverColor() const
{
Q_D(const ChromePalette);
if (d->mask & ChromePalettePrivate::MaskFlag::CloseButtonHoverColor) {
return d->closeButtonHoverColor;
}
return d->closeButtonHoverColor_sys;
}
QColor ChromePalette::closeButtonPressColor() const
{
Q_D(const ChromePalette);
if (d->mask & ChromePalettePrivate::MaskFlag::CloseButtonPressColor) {
return d->closeButtonPressColor;
}
return d->closeButtonPressColor_sys;
}
void ChromePalette::setTitleBarActiveBackgroundColor(const QColor &value)
{
Q_ASSERT(value.isValid());
@ -347,4 +395,79 @@ void ChromePalette::resetChromeButtonPressColor()
Q_EMIT chromeButtonColorChanged();
}
void ChromePalette::setCloseButtonNormalColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
Q_D(ChromePalette);
if (d->closeButtonNormalColor == value) {
return;
}
d->closeButtonNormalColor = value;
d->mask |= ChromePalettePrivate::MaskFlag::CloseButtonNormalColor;
Q_EMIT closeButtonNormalColorChanged();
Q_EMIT chromeButtonColorChanged();
}
void ChromePalette::resetCloseButtonNormalColor()
{
Q_D(ChromePalette);
d->closeButtonNormalColor = {};
d->mask &= ~ChromePalettePrivate::Mask(ChromePalettePrivate::MaskFlag::CloseButtonNormalColor);
Q_EMIT closeButtonNormalColorChanged();
Q_EMIT chromeButtonColorChanged();
}
void ChromePalette::setCloseButtonHoverColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
Q_D(ChromePalette);
if (d->closeButtonHoverColor == value) {
return;
}
d->closeButtonHoverColor = value;
d->mask |= ChromePalettePrivate::MaskFlag::CloseButtonHoverColor;
Q_EMIT closeButtonHoverColorChanged();
Q_EMIT chromeButtonColorChanged();
}
void ChromePalette::resetCloseButtonHoverColor()
{
Q_D(ChromePalette);
d->closeButtonHoverColor = {};
d->mask &= ~ChromePalettePrivate::Mask(ChromePalettePrivate::MaskFlag::CloseButtonHoverColor);
Q_EMIT closeButtonHoverColorChanged();
Q_EMIT chromeButtonColorChanged();
}
void ChromePalette::setCloseButtonPressColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
Q_D(ChromePalette);
if (d->closeButtonPressColor == value) {
return;
}
d->closeButtonPressColor = value;
d->mask |= ChromePalettePrivate::MaskFlag::CloseButtonPressColor;
Q_EMIT closeButtonPressColorChanged();
Q_EMIT chromeButtonColorChanged();
}
void ChromePalette::resetCloseButtonPressColor()
{
Q_D(ChromePalette);
d->closeButtonPressColor = {};
d->mask &= ~ChromePalettePrivate::Mask(ChromePalettePrivate::MaskFlag::CloseButtonPressColor);
Q_EMIT closeButtonPressColorChanged();
Q_EMIT chromeButtonColorChanged();
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -1324,9 +1324,13 @@ void Utils::tryToEnableHighestDpiAwarenessLevel()
return;
}
}
if (SetProcessDPIAware() == FALSE) {
// Some really old MinGW SDK may lack this function, we workaround this
// issue by always load it dynamically at runtime.
if (API_USER_AVAILABLE(SetProcessDPIAware)) {
if (API_CALL_FUNCTION(SetProcessDPIAware) == FALSE) {
qWarning() << getSystemErrorMessage(kSetProcessDPIAware);
}
}
}
SystemTheme Utils::getSystemTheme()

View File

@ -35,6 +35,7 @@ set(SOURCES
${INCLUDE_PREFIX}/framelessquickmodule.h
${INCLUDE_PREFIX}/framelessquickhelper.h
${INCLUDE_PREFIX}/framelessquickutils.h
${INCLUDE_PREFIX}/quickchromepalette.h
${INCLUDE_PREFIX}/private/quickstandardsystembutton_p.h
${INCLUDE_PREFIX}/private/quickstandardtitlebar_p.h
${INCLUDE_PREFIX}/private/framelessquickhelper_p.h
@ -46,6 +47,7 @@ set(SOURCES
framelessquickmodule.cpp
framelessquickwindow.cpp
framelessquickhelper.cpp
quickchromepalette.cpp
)
if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC)

View File

@ -25,6 +25,7 @@
#include "framelessquickmodule.h"
#include "framelessquickhelper.h"
#include "framelessquickutils.h"
#include "quickchromepalette.h"
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
# include "quickstandardsystembutton_p.h"
# include "quickstandardtitlebar_p.h"
@ -89,10 +90,4 @@ void FramelessHelper::Quick::registerTypes(QQmlEngine *engine)
qmlRegisterModule(QUICK_URI_FULL);
}
QuickChromePalette::QuickChromePalette(QObject *parent) : ChromePalette(parent)
{
}
QuickChromePalette::~QuickChromePalette() = default;
FRAMELESSHELPER_END_NAMESPACE

View File

@ -0,0 +1,35 @@
/*
* 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 "quickchromepalette.h"
FRAMELESSHELPER_BEGIN_NAMESPACE
QuickChromePalette::QuickChromePalette(QObject *parent) : ChromePalette(parent)
{
}
QuickChromePalette::~QuickChromePalette() = default;
FRAMELESSHELPER_END_NAMESPACE

View File

@ -0,0 +1 @@
#include "../../include/FramelessHelper/Quick/quickchromepalette.h"

View File

@ -205,9 +205,10 @@ void QuickStandardTitleBar::updateChromeButtonColor()
m_maximizeButton->setHoverColor(hover);
m_maximizeButton->setPressColor(press);
m_closeButton->setColor(color);
m_closeButton->setNormalColor(normal);
m_closeButton->setHoverColor(hover);
m_closeButton->setPressColor(press);
// The close button is special.
m_closeButton->setNormalColor(m_chromePalette->closeButtonNormalColor());
m_closeButton->setHoverColor(m_chromePalette->closeButtonHoverColor());
m_closeButton->setPressColor(m_chromePalette->closeButtonPressColor());
}
void QuickStandardTitleBar::clickMinimizeButton()

View File

@ -26,7 +26,6 @@
#include "standardtitlebar_p.h"
#include "standardsystembutton.h"
#include <QtCore/qcoreevent.h>
#include <QtWidgets/qlabel.h>
#include <QtWidgets/qboxlayout.h>
#include <QtWidgets/qstyleoption.h>
#include <QtWidgets/qstylepainter.h>
@ -35,9 +34,6 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
using namespace Global;
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)
{
Q_ASSERT(q);
@ -79,28 +75,8 @@ void StandardTitleBarPrivate::setTitleLabelAlignment(const Qt::Alignment value)
return;
}
m_labelAlignment = value;
bool needsInvalidate = false;
if (m_labelAlignment & Qt::AlignLeft) {
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(kDefaultTitleBarContentsMargin, 0, QSizePolicy::Fixed);
needsInvalidate = true;
}
if (m_labelAlignment & Qt::AlignHCenter) {
m_labelLeftStretch->changeSize(0, 0, QSizePolicy::Expanding);
m_labelRightStretch->changeSize(0, 0, QSizePolicy::Expanding);
needsInvalidate = true;
}
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->update();
Q_EMIT q->titleLabelAlignmentChanged();
}
@ -144,6 +120,7 @@ void StandardTitleBarPrivate::paintTitleBar(QPaintEvent *event)
{
Q_UNUSED(event);
Q_Q(StandardTitleBar);
#if 0
// 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
@ -152,6 +129,51 @@ void StandardTitleBarPrivate::paintTitleBar(QPaintEvent *event)
option.initFrom(q);
QStylePainter painter(q);
painter.drawPrimitive(QStyle::PE_Widget, option);
#else
if (!m_window || m_chromePalette.isNull()) {
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);
const QString text = m_window->windowTitle();
if (!text.isEmpty()) {
const QFont font = [q]() -> QFont {
QFont f = q->font();
f.setPointSize(kDefaultTitleBarFontPointSize);
return f;
}();
painter.setPen(foregroundColor);
painter.setFont(font);
const QRect rect = [this, q]() -> QRect {
const int w = q->width();
int leftMargin = 0;
int rightMargin = 0;
if (m_labelAlignment & Qt::AlignLeft) {
leftMargin = kDefaultTitleBarContentsMargin;
}
if (m_labelAlignment & Qt::AlignRight) {
rightMargin = (w - m_minimizeButton->x() + kDefaultTitleBarContentsMargin);
}
const int x = leftMargin;
const int y = 0;
const int width = (w - leftMargin - rightMargin);
const int height = q->height();
return {QPoint(x, y), QSize(width, height)};
}();
painter.drawText(rect, m_labelAlignment, text);
}
painter.restore();
#endif
}
void StandardTitleBarPrivate::updateMaximizeButton()
@ -163,20 +185,8 @@ void StandardTitleBarPrivate::updateMaximizeButton()
void StandardTitleBarPrivate::updateTitleBarColor()
{
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());
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())));
q->update();
}
void StandardTitleBarPrivate::updateChromeButtonColor()
@ -197,9 +207,10 @@ void StandardTitleBarPrivate::updateChromeButtonColor()
m_maximizeButton->setHoverColor(hover);
m_maximizeButton->setPressColor(press);
m_closeButton->setColor(color);
m_closeButton->setNormalColor(normal);
m_closeButton->setHoverColor(hover);
m_closeButton->setPressColor(press);
// The close button is special.
m_closeButton->setNormalColor(m_chromePalette->closeButtonNormalColor());
m_closeButton->setHoverColor(m_chromePalette->closeButtonHoverColor());
m_closeButton->setPressColor(m_chromePalette->closeButtonPressColor());
}
void StandardTitleBarPrivate::retranslateUi()
@ -251,13 +262,10 @@ void StandardTitleBarPrivate::initialize()
this, &StandardTitleBarPrivate::updateChromeButtonColor);
q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
q->setFixedHeight(kDefaultTitleBarHeight);
m_windowTitleLabel.reset(new QLabel(q));
m_windowTitleLabel->setFrameShape(QFrame::NoFrame);
QFont windowTitleFont = q->font();
windowTitleFont.setPointSize(kDefaultTitleBarFontPointSize);
m_windowTitleLabel->setFont(windowTitleFont);
m_windowTitleLabel->setText(m_window->windowTitle());
connect(m_window, &QWidget::windowTitleChanged, m_windowTitleLabel.data(), &QLabel::setText);
connect(m_window, &QWidget::windowTitleChanged, this, [q](const QString &title){
Q_UNUSED(title);
q->update();
});
m_minimizeButton.reset(new StandardSystemButton(SystemButtonType::Minimize, q));
connect(m_minimizeButton.data(), &StandardSystemButton::clicked, m_window, &QWidget::showMinimized);
m_maximizeButton.reset(new StandardSystemButton(SystemButtonType::Maximize, q));
@ -277,14 +285,6 @@ void StandardTitleBarPrivate::initialize()
m_window->close();
}
});
m_labelLeftStretch = new QSpacerItem(0, 0);
m_labelRightStretch = new QSpacerItem(0, 0);
const auto titleLabelLayout = new QHBoxLayout;
titleLabelLayout->setSpacing(0);
titleLabelLayout->setContentsMargins(0, 0, 0, 0);
titleLabelLayout->addSpacerItem(m_labelLeftStretch);
titleLabelLayout->addWidget(m_windowTitleLabel.data());
titleLabelLayout->addSpacerItem(m_labelRightStretch);
// According to the title bar design guidance, the system buttons should always be
// placed on the top-right corner of the window, so we need the following additional
// layouts to ensure this.
@ -302,7 +302,7 @@ void StandardTitleBarPrivate::initialize()
const auto titleBarLayout = new QHBoxLayout(q);
titleBarLayout->setSpacing(0);
titleBarLayout->setContentsMargins(0, 0, 0, 0);
titleBarLayout->addLayout(titleLabelLayout);
titleBarLayout->addStretch();
titleBarLayout->addLayout(systemButtonsOuterLayout);
q->setLayout(titleBarLayout);
setTitleLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter);
@ -331,12 +331,6 @@ void StandardTitleBar::setTitleLabelAlignment(const Qt::Alignment value)
d->setTitleLabelAlignment(value);
}
QLabel *StandardTitleBar::titleLabel() const
{
Q_D(const StandardTitleBar);
return d->m_windowTitleLabel.data();
}
StandardSystemButton *StandardTitleBar::minimizeButton() const
{
Q_D(const StandardTitleBar);