quick: adapt macos updates

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2023-01-15 14:11:52 +08:00
parent d25666b0e6
commit 5e7ddb1864
9 changed files with 116 additions and 55 deletions

View File

@ -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();
}

View File

@ -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();
}

View File

@ -28,6 +28,7 @@
#include <QtGui/qguiapplication.h>
#include <QtQml/qqmlapplicationengine.h>
#include <QtQml/qqmlcontext.h>
#include <QtQuick/qquickwindow.h>
#include <framelessquickmodule.h>
#include <framelessconfig_p.h>
@ -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<QQmlApplicationEngine>();
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());

View File

@ -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);

View File

@ -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 = {};

View File

@ -49,7 +49,7 @@ public:
{
int width = 0;
int height = 0;
int baseline = 0;
int ascent = 0;
};
explicit StandardTitleBarPrivate(StandardTitleBar *q);

View File

@ -29,6 +29,7 @@
#include <QtGui/qwindow.h>
#include <QtGui/qscreen.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qfontmetrics.h>
#ifndef FRAMELESSHELPER_CORE_NO_PRIVATE
# include <QtGui/private/qhighdpiscaling_p.h>
#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

View File

@ -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<QQuickToolTipAttached *>(qmlAttachedPropertiesObject<QQuickToolTip>(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<QQuickToolTipAttached *>(qmlAttachedPropertiesObject<QQuickToolTip>(m_minimizeButton))->setText(tr("Minimize"));
qobject_cast<QQuickToolTipAttached *>(qmlAttachedPropertiesObject<QQuickToolTip>(m_maximizeButton))->setText([this]() -> QString {
if (const QQuickWindow * const w = window()) {
@ -352,6 +361,7 @@ void QuickStandardTitleBar::retranslateUi()
return tr("Maximize");
}());
qobject_cast<QQuickToolTipAttached *>(qmlAttachedPropertiesObject<QQuickToolTip>(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();
}

View File

@ -26,6 +26,7 @@
#include "standardtitlebar_p.h"
#include "standardsystembutton.h"
#include "framelesswidgetshelper.h"
#include "utils.h"
#include <QtCore/qcoreevent.h>
#include <QtCore/qtimer.h>
#include <QtGui/qpainter.h>
@ -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