From 5e7ddb186485472ff8b78466f081064ae887d486 Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Sun, 15 Jan 2023 14:11:52 +0800 Subject: [PATCH] quick: adapt macos updates Signed-off-by: Yuhang Zhao <2546789017@qq.com> --- examples/quick/ApplicationWindow.qml | 12 ++- examples/quick/Window.qml | 12 ++- examples/quick/main.cpp | 12 +++ include/FramelessHelper/Core/utils.h | 1 + .../Quick/private/quickstandardtitlebar_p.h | 8 +- .../Widgets/private/standardtitlebar_p.h | 2 +- src/core/utils.cpp | 10 ++ src/quick/quickstandardtitlebar.cpp | 101 +++++++++++------- src/widgets/standardtitlebar.cpp | 13 +-- 9 files changed, 116 insertions(+), 55 deletions(-) diff --git a/examples/quick/ApplicationWindow.qml b/examples/quick/ApplicationWindow.qml index 3d9675b..b377085 100644 --- a/examples/quick/ApplicationWindow.qml +++ b/examples/quick/ApplicationWindow.qml @@ -50,11 +50,13 @@ FramelessApplicationWindow { // Let FramelessHelper know what's our homemade title bar, otherwise // our window won't be draggable. FramelessHelper.titleBarItem = titleBar; - // Make our own items visible to the hit test and on Windows, enable - // the snap layout feature (available since Windows 11). - FramelessHelper.setSystemButton(titleBar.minimizeButton, FramelessHelperConstants.Minimize); - FramelessHelper.setSystemButton(titleBar.maximizeButton, FramelessHelperConstants.Maximize); - FramelessHelper.setSystemButton(titleBar.closeButton, FramelessHelperConstants.Close); + if (!$isMacOSHost) { + // Make our own items visible to the hit test and on Windows, enable + // the snap layout feature (available since Windows 11). + FramelessHelper.setSystemButton(titleBar.minimizeButton, FramelessHelperConstants.Minimize); + FramelessHelper.setSystemButton(titleBar.maximizeButton, FramelessHelperConstants.Maximize); + FramelessHelper.setSystemButton(titleBar.closeButton, FramelessHelperConstants.Close); + } if (!Settings.restoreGeometry(window)) { FramelessHelper.moveWindowToDesktopCenter(); } diff --git a/examples/quick/Window.qml b/examples/quick/Window.qml index d6667c8..6de5995 100644 --- a/examples/quick/Window.qml +++ b/examples/quick/Window.qml @@ -50,11 +50,13 @@ FramelessWindow { // Let FramelessHelper know what's our homemade title bar, otherwise // our window won't be draggable. FramelessHelper.titleBarItem = titleBar; - // Make our own items visible to the hit test and on Windows, enable - // the snap layout feature (available since Windows 11). - FramelessHelper.setSystemButton(titleBar.minimizeButton, FramelessHelperConstants.Minimize); - FramelessHelper.setSystemButton(titleBar.maximizeButton, FramelessHelperConstants.Maximize); - FramelessHelper.setSystemButton(titleBar.closeButton, FramelessHelperConstants.Close); + if (!$isMacOSHost) { + // Make our own items visible to the hit test and on Windows, enable + // the snap layout feature (available since Windows 11). + FramelessHelper.setSystemButton(titleBar.minimizeButton, FramelessHelperConstants.Minimize); + FramelessHelper.setSystemButton(titleBar.maximizeButton, FramelessHelperConstants.Maximize); + FramelessHelper.setSystemButton(titleBar.closeButton, FramelessHelperConstants.Close); + } if (!Settings.restoreGeometry(window)) { FramelessHelper.moveWindowToDesktopCenter(); } diff --git a/examples/quick/main.cpp b/examples/quick/main.cpp index a37215a..d59584d 100644 --- a/examples/quick/main.cpp +++ b/examples/quick/main.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -40,6 +41,14 @@ FRAMELESSHELPER_USE_NAMESPACE +static constexpr const bool IS_MACOS_HOST = +#ifdef Q_OS_MACOS + true +#else // !Q_OS_MACOS + false +#endif // Q_OS_MACOS + ; + int main(int argc, char *argv[]) { std::setlocale(LC_ALL, "en_US.UTF-8"); @@ -96,6 +105,9 @@ int main(int argc, char *argv[]) const auto engine = std::make_unique(); + engine->rootContext()->setContextProperty( + FRAMELESSHELPER_STRING_LITERAL("$isMacOSHost"), QVariant(IS_MACOS_HOST)); + #if (((QT_VERSION < QT_VERSION_CHECK(6, 2, 0)) || defined(QUICK_USE_QMAKE)) && !QMLTC_ENABLED) // Don't forget to register our own custom QML types! FramelessHelper::Quick::registerTypes(engine.get()); diff --git a/include/FramelessHelper/Core/utils.h b/include/FramelessHelper/Core/utils.h index d79b723..2afe93c 100644 --- a/include/FramelessHelper/Core/utils.h +++ b/include/FramelessHelper/Core/utils.h @@ -80,6 +80,7 @@ FRAMELESSHELPER_CORE_API void registerThemeChangeNotification(); [[nodiscard]] FRAMELESSHELPER_CORE_API QPoint fromNativePixels(const QWindow *window, const QPoint &point); [[nodiscard]] FRAMELESSHELPER_CORE_API QSize fromNativePixels(const QWindow *window, const QSize &size); [[nodiscard]] FRAMELESSHELPER_CORE_API QRect fromNativePixels(const QWindow *window, const QRect &rect); +[[nodiscard]] FRAMELESSHELPER_CORE_API int horizontalAdvance(const QFontMetrics &fm, const QString &str); #ifdef Q_OS_WINDOWS [[nodiscard]] FRAMELESSHELPER_CORE_API bool isWindowsVersionOrGreater(const Global::WindowsVersion version); diff --git a/include/FramelessHelper/Quick/private/quickstandardtitlebar_p.h b/include/FramelessHelper/Quick/private/quickstandardtitlebar_p.h index 2716a04..074c40e 100644 --- a/include/FramelessHelper/Quick/private/quickstandardtitlebar_p.h +++ b/include/FramelessHelper/Quick/private/quickstandardtitlebar_p.h @@ -46,13 +46,15 @@ class FRAMELESSHELPER_QUICK_API QuickStandardTitleBar : public QQuickRectangle Q_OBJECT #ifdef QML_NAMED_ELEMENT QML_NAMED_ELEMENT(StandardTitleBar) -#endif +#endif // QML_NAMED_ELEMENT Q_DISABLE_COPY_MOVE(QuickStandardTitleBar) Q_PROPERTY(Qt::Alignment titleLabelAlignment READ titleLabelAlignment WRITE setTitleLabelAlignment NOTIFY titleLabelAlignmentChanged FINAL) Q_PROPERTY(QQuickLabel* titleLabel READ titleLabel CONSTANT FINAL) +#ifndef Q_OS_MACOS Q_PROPERTY(QuickStandardSystemButton* minimizeButton READ minimizeButton CONSTANT FINAL) Q_PROPERTY(QuickStandardSystemButton* maximizeButton READ maximizeButton CONSTANT FINAL) Q_PROPERTY(QuickStandardSystemButton* closeButton READ closeButton CONSTANT FINAL) +#endif // Q_OS_MACOS Q_PROPERTY(bool extended READ isExtended WRITE setExtended NOTIFY extendedChanged FINAL) Q_PROPERTY(bool hideWhenClose READ isHideWhenClose WRITE setHideWhenClose NOTIFY hideWhenCloseChanged FINAL) Q_PROPERTY(QuickChromePalette* chromePalette READ chromePalette CONSTANT FINAL) @@ -68,9 +70,11 @@ public: void setTitleLabelAlignment(const Qt::Alignment value); Q_NODISCARD QQuickLabel *titleLabel() const; +#ifndef Q_OS_MACOS Q_NODISCARD QuickStandardSystemButton *minimizeButton() const; Q_NODISCARD QuickStandardSystemButton *maximizeButton() const; Q_NODISCARD QuickStandardSystemButton *closeButton() const; +#endif // Q_OS_MACOS Q_NODISCARD bool isExtended() const; void setExtended(const bool value); @@ -126,10 +130,12 @@ private: Qt::Alignment m_labelAlignment = {}; QuickImageItem *m_windowIcon = nullptr; QQuickLabel *m_windowTitleLabel = nullptr; +#ifndef Q_OS_MACOS QQuickRow *m_systemButtonsRow = nullptr; QuickStandardSystemButton *m_minimizeButton = nullptr; QuickStandardSystemButton *m_maximizeButton = nullptr; QuickStandardSystemButton *m_closeButton = nullptr; +#endif // Q_OS_MACOS QMetaObject::Connection m_windowStateChangeConnection = {}; QMetaObject::Connection m_windowActiveChangeConnection = {}; QMetaObject::Connection m_windowTitleChangeConnection = {}; diff --git a/include/FramelessHelper/Widgets/private/standardtitlebar_p.h b/include/FramelessHelper/Widgets/private/standardtitlebar_p.h index b9e88cb..f9dce4c 100644 --- a/include/FramelessHelper/Widgets/private/standardtitlebar_p.h +++ b/include/FramelessHelper/Widgets/private/standardtitlebar_p.h @@ -49,7 +49,7 @@ public: { int width = 0; int height = 0; - int baseline = 0; + int ascent = 0; }; explicit StandardTitleBarPrivate(StandardTitleBar *q); diff --git a/src/core/utils.cpp b/src/core/utils.cpp index 2bf844e..8bc99a8 100644 --- a/src/core/utils.cpp +++ b/src/core/utils.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #ifndef FRAMELESSHELPER_CORE_NO_PRIVATE # include #endif // FRAMELESSHELPER_CORE_NO_PRIVATE @@ -439,4 +440,13 @@ QRect Utils::fromNativePixels(const QWindow *window, const QRect &rect) #endif // FRAMELESSHELPER_CORE_NO_PRIVATE } +int Utils::horizontalAdvance(const QFontMetrics &fm, const QString &str) +{ +#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) + return fm.horizontalAdvance(str); +#else // (QT_VERSION < QT_VERSION_CHECK(5, 11, 0)) + return fm.width(); +#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) +} + FRAMELESSHELPER_END_NAMESPACE diff --git a/src/quick/quickstandardtitlebar.cpp b/src/quick/quickstandardtitlebar.cpp index c762a32..1b6063c 100644 --- a/src/quick/quickstandardtitlebar.cpp +++ b/src/quick/quickstandardtitlebar.cpp @@ -75,22 +75,18 @@ void QuickStandardTitleBar::setTitleLabelAlignment(const Qt::Alignment value) } m_labelAlignment = value; QQuickAnchors * const labelAnchors = QQuickItemPrivate::get(m_windowTitleLabel)->anchors(); - //labelAnchors->setMargins(0); labelAnchors->resetFill(); labelAnchors->resetCenterIn(); + labelAnchors->resetHorizontalCenter(); + labelAnchors->resetVerticalCenter(); labelAnchors->resetTop(); labelAnchors->resetBottom(); labelAnchors->resetLeft(); labelAnchors->resetRight(); + labelAnchors->setMargins(0); + m_windowTitleLabel->setVAlign(QQuickLabel::AlignVCenter); const QQuickItemPrivate * const titleBarPriv = QQuickItemPrivate::get(this); - if (m_labelAlignment & Qt::AlignTop) { - labelAnchors->setTop(titleBarPriv->top()); - labelAnchors->setTopMargin(kDefaultTitleBarContentsMargin); - } - if (m_labelAlignment & Qt::AlignBottom) { - labelAnchors->setBottom(titleBarPriv->bottom()); - labelAnchors->setBottomMargin(kDefaultTitleBarContentsMargin); - } + labelAnchors->setVerticalCenter(titleBarPriv->verticalCenter()); if (m_labelAlignment & Qt::AlignLeft) { if (m_windowIcon->isVisible()) { labelAnchors->setLeft(QQuickItemPrivate::get(m_windowIcon)->right()); @@ -98,20 +94,22 @@ void QuickStandardTitleBar::setTitleLabelAlignment(const Qt::Alignment value) labelAnchors->setLeft(titleBarPriv->left()); } labelAnchors->setLeftMargin(kDefaultTitleBarContentsMargin); - } - if (m_labelAlignment & Qt::AlignRight) { + m_windowTitleLabel->setHAlign(QQuickLabel::AlignLeft); + } else if (m_labelAlignment & Qt::AlignRight) { +#ifdef Q_OS_MACOS + labelAnchors->setRight(titleBarPriv->right()); +#else // !Q_OS_MACOS labelAnchors->setRight(QQuickItemPrivate::get(m_systemButtonsRow)->left()); +#endif // Q_OS_MACOS labelAnchors->setRightMargin(kDefaultTitleBarContentsMargin); - } - if (m_labelAlignment & Qt::AlignVCenter) { - //labelAnchors->setTopMargin(0); - //labelAnchors->setBottomMargin(0); - labelAnchors->setVerticalCenter(titleBarPriv->verticalCenter()); - } - if (m_labelAlignment & Qt::AlignHCenter) { - //labelAnchors->setLeftMargin(0); - //labelAnchors->setRightMargin(0); + m_windowTitleLabel->setHAlign(QQuickLabel::AlignRight); + } else if (m_labelAlignment & Qt::AlignHCenter) { labelAnchors->setHorizontalCenter(titleBarPriv->horizontalCenter()); + m_windowTitleLabel->setHAlign(QQuickLabel::AlignHCenter); + } else { + WARNING << "The alignment for the title label is not set!"; + labelAnchors->setLeft(titleBarPriv->left()); + m_windowTitleLabel->setHAlign(QQuickLabel::AlignLeft); } Q_EMIT titleLabelAlignmentChanged(); } @@ -121,6 +119,7 @@ QQuickLabel *QuickStandardTitleBar::titleLabel() const return m_windowTitleLabel; } +#ifndef Q_OS_MACOS QuickStandardSystemButton *QuickStandardTitleBar::minimizeButton() const { return m_minimizeButton; @@ -135,6 +134,7 @@ QuickStandardSystemButton *QuickStandardTitleBar::closeButton() const { return m_closeButton; } +#endif // Q_OS_MACOS bool QuickStandardTitleBar::isExtended() const { @@ -207,13 +207,17 @@ void QuickStandardTitleBar::setWindowIconVisible(const bool value) return; } m_windowIcon->setVisible(value); - QQuickAnchors *labelAnchors = QQuickItemPrivate::get(m_windowTitleLabel)->anchors(); - if (value) { - labelAnchors->setLeft(QQuickItemPrivate::get(m_windowIcon)->right()); - } else { - labelAnchors->setLeft(QQuickItemPrivate::get(this)->left()); +#ifndef Q_OS_MACOS + if (m_labelAlignment & Qt::AlignLeft) { + QQuickAnchors * const labelAnchors = QQuickItemPrivate::get(m_windowTitleLabel)->anchors(); + if (value) { + labelAnchors->setLeft(QQuickItemPrivate::get(m_windowIcon)->right()); + } else { + labelAnchors->setLeft(QQuickItemPrivate::get(this)->left()); + } } FramelessQuickHelper::get(this)->setHitTestVisible_rect(windowIconRect(), windowIconVisible_real()); +#endif // Q_OS_MACOS } QVariant QuickStandardTitleBar::windowIcon() const @@ -235,6 +239,7 @@ void QuickStandardTitleBar::setWindowIcon(const QVariant &value) void QuickStandardTitleBar::updateMaximizeButton() { +#ifndef Q_OS_MACOS const QQuickWindow * const w = window(); if (!w) { return; @@ -242,6 +247,7 @@ void QuickStandardTitleBar::updateMaximizeButton() const bool max = (w->visibility() == QQuickWindow::Maximized); m_maximizeButton->setButtonType(max ? QuickGlobal::SystemButtonType::Restore : QuickGlobal::SystemButtonType::Maximize); qobject_cast(qmlAttachedPropertiesObject(m_maximizeButton))->setText(max ? tr("Restore") : tr("Maximize")); +#endif // Q_OS_MACOS } void QuickStandardTitleBar::updateTitleLabelText() @@ -272,6 +278,7 @@ void QuickStandardTitleBar::updateTitleBarColor() void QuickStandardTitleBar::updateChromeButtonColor() { +#ifndef Q_OS_MACOS const QQuickWindow * const w = window(); if (!w) { return; @@ -299,6 +306,7 @@ void QuickStandardTitleBar::updateChromeButtonColor() m_closeButton->setHoverColor(m_chromePalette->closeButtonHoverColor()); m_closeButton->setPressColor(m_chromePalette->closeButtonPressColor()); m_closeButton->updateColor(); +#endif // Q_OS_MACOS } void QuickStandardTitleBar::clickMinimizeButton() @@ -342,6 +350,7 @@ void QuickStandardTitleBar::clickCloseButton() void QuickStandardTitleBar::retranslateUi() { +#ifndef Q_OS_MACOS qobject_cast(qmlAttachedPropertiesObject(m_minimizeButton))->setText(tr("Minimize")); qobject_cast(qmlAttachedPropertiesObject(m_maximizeButton))->setText([this]() -> QString { if (const QQuickWindow * const w = window()) { @@ -352,6 +361,7 @@ void QuickStandardTitleBar::retranslateUi() return tr("Maximize"); }()); qobject_cast(qmlAttachedPropertiesObject(m_closeButton))->setText(tr("Close")); +#endif // Q_OS_MACOS } void QuickStandardTitleBar::updateWindowIcon() @@ -369,6 +379,10 @@ void QuickStandardTitleBar::updateWindowIcon() bool QuickStandardTitleBar::mouseEventHandler(QMouseEvent *event) { +#ifdef Q_OS_MACOS + Q_UNUSED(event); + return false; +#else // !Q_OS_MACOS Q_ASSERT(event); if (!event) { return false; @@ -430,6 +444,7 @@ bool QuickStandardTitleBar::mouseEventHandler(QMouseEvent *event) break; } return false; +#endif // Q_OS_MACOS } QRect QuickStandardTitleBar::windowIconRect() const @@ -476,23 +491,30 @@ void QuickStandardTitleBar::initialize() b->setColor(kDefaultTransparentColor); setHeight(kDefaultTitleBarHeight); - const QQuickItemPrivate * const thisPriv = QQuickItemPrivate::get(this); - - m_windowIcon = new QuickImageItem(this); - QQuickAnchors * const iconAnchors = QQuickItemPrivate::get(m_windowIcon)->anchors(); - iconAnchors->setLeft(thisPriv->left()); - iconAnchors->setLeftMargin(kDefaultTitleBarContentsMargin); - iconAnchors->setVerticalCenter(thisPriv->verticalCenter()); - connect(m_windowIcon, &QuickImageItem::visibleChanged, this, &QuickStandardTitleBar::windowIconVisibleChanged); - connect(m_windowIcon, &QuickImageItem::sourceChanged, this, &QuickStandardTitleBar::windowIconChanged); - connect(m_windowIcon, &QuickImageItem::widthChanged, this, &QuickStandardTitleBar::windowIconSizeChanged); - connect(m_windowIcon, &QuickImageItem::heightChanged, this, &QuickStandardTitleBar::windowIconSizeChanged); - m_windowTitleLabel = new QQuickLabel(this); QFont f = m_windowTitleLabel->font(); f.setPointSize(kDefaultTitleBarFontPointSize); m_windowTitleLabel->setFont(f); + const QQuickItemPrivate * const thisPriv = QQuickItemPrivate::get(this); + + m_windowIcon = new QuickImageItem(this); + QQuickAnchors * const iconAnchors = QQuickItemPrivate::get(m_windowIcon)->anchors(); + iconAnchors->setVerticalCenter(thisPriv->verticalCenter()); +#ifdef Q_OS_MACOS + const QQuickItemPrivate * const labelPriv = QQuickItemPrivate::get(m_windowTitleLabel); + iconAnchors->setRight(labelPriv->left()); + iconAnchors->setRightMargin(kDefaultTitleBarContentsMargin); +#else // !Q_OS_MACOS + iconAnchors->setLeft(thisPriv->left()); + iconAnchors->setLeftMargin(kDefaultTitleBarContentsMargin); +#endif // Q_OS_MACOS + connect(m_windowIcon, &QuickImageItem::visibleChanged, this, &QuickStandardTitleBar::windowIconVisibleChanged); + connect(m_windowIcon, &QuickImageItem::sourceChanged, this, &QuickStandardTitleBar::windowIconChanged); + connect(m_windowIcon, &QuickImageItem::widthChanged, this, &QuickStandardTitleBar::windowIconSizeChanged); + connect(m_windowIcon, &QuickImageItem::heightChanged, this, &QuickStandardTitleBar::windowIconSizeChanged); + +#ifndef Q_OS_MACOS m_systemButtonsRow = new QQuickRow(this); QQuickAnchors * const rowAnchors = QQuickItemPrivate::get(m_systemButtonsRow)->anchors(); rowAnchors->setTop(thisPriv->top()); @@ -503,10 +525,15 @@ void QuickStandardTitleBar::initialize() connect(m_maximizeButton, &QuickStandardSystemButton::clicked, this, &QuickStandardTitleBar::clickMaximizeButton); m_closeButton = new QuickStandardSystemButton(QuickGlobal::SystemButtonType::Close, m_systemButtonsRow); connect(m_closeButton, &QuickStandardSystemButton::clicked, this, &QuickStandardTitleBar::clickCloseButton); +#endif // Q_OS_MACOS setWindowIconSize(kDefaultWindowIconSize); setWindowIconVisible(false); +#ifdef Q_OS_MACOS + setTitleLabelAlignment(Qt::AlignCenter); +#else // !Q_OS_MACOS setTitleLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter); +#endif // Q_OS_MACOS retranslateUi(); updateAll(); } diff --git a/src/widgets/standardtitlebar.cpp b/src/widgets/standardtitlebar.cpp index 0a74651..7940786 100644 --- a/src/widgets/standardtitlebar.cpp +++ b/src/widgets/standardtitlebar.cpp @@ -26,6 +26,7 @@ #include "standardtitlebar_p.h" #include "standardsystembutton.h" #include "framelesswidgetshelper.h" +#include "utils.h" #include #include #include @@ -153,9 +154,9 @@ StandardTitleBarPrivate::FontMetrics StandardTitleBarPrivate::titleLabelSize() c const QFont font = m_titleFont.value_or(defaultFont()); const QFontMetrics fontMetrics(font); return { - fontMetrics.horizontalAdvance(text), - fontMetrics.height(), - fontMetrics.ascent() + /* .width */ Utils::horizontalAdvance(fontMetrics, text), + /* .height */ fontMetrics.height(), + /* .ascent */ fontMetrics.ascent() }; } @@ -200,9 +201,9 @@ void StandardTitleBarPrivate::paintTitleBar(QPaintEvent *event) } else if (m_labelAlignment & Qt::AlignHCenter) { x = std::round(qreal(titleBarWidth - labelSize.width) / qreal(2)); } else { - WARNING << "You didn't set an alignment for the title label!"; + WARNING << "The alignment for the title label is not set!"; } - const int y = std::round((qreal(q->height() - labelSize.height) / qreal(2)) + qreal(labelSize.baseline)); + const int y = std::round((qreal(q->height() - labelSize.height) / qreal(2)) + qreal(labelSize.ascent)); return {x, y}; }(); painter.drawText(pos, text); @@ -389,7 +390,7 @@ QRect StandardTitleBarPrivate::windowIconRect() const const int centeredX = std::round(qreal(titleBarWidth - labelWidth) / qreal(2)); return (centeredX - kDefaultTitleBarContentsMargin - size.width()); } - WARNING << "You didn't set an alignment for the title label!"; + WARNING << "The alignment for the title label is not set!"; return 0; }(); #else // !Q_OS_MACOS