From c49b971983ad0b8a4be09680b32612316de8a69d Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Mon, 28 Mar 2022 18:03:59 +0800 Subject: [PATCH] internal refactoring Signed-off-by: Yuhang Zhao <2546789017@qq.com> --- examples/mainwindow/main.cpp | 2 + examples/mainwindow/mainwindow.cpp | 2 +- examples/quick/main.cpp | 2 + examples/quick/qml/MainWindow.qml | 8 +- examples/widget/main.cpp | 2 + .../Core/framelesshelpercore_global.h | 22 ++- .../Quick/framelessquickwindow.h | 7 +- .../Widgets/framelessmainwindow.h | 10 +- .../FramelessHelper/Widgets/framelesswidget.h | 10 +- .../Widgets/framelesswidgetshelper.h | 5 +- src/core/framelesswindowsmanager.cpp | 19 +- src/core/utils_win.cpp | 6 +- src/quick/framelesshelper_quick.cpp | 42 ++-- src/quick/framelessquickwindow.cpp | 183 ++++++++++++++---- src/quick/framelessquickwindow_p.h | 14 +- src/widgets/framelessmainwindow.cpp | 40 +--- src/widgets/framelesswidget.cpp | 40 +--- src/widgets/framelesswidgetshelper.cpp | 71 +++++-- 18 files changed, 301 insertions(+), 184 deletions(-) diff --git a/examples/mainwindow/main.cpp b/examples/mainwindow/main.cpp index efd75ac..361f5bd 100644 --- a/examples/mainwindow/main.cpp +++ b/examples/mainwindow/main.cpp @@ -42,6 +42,8 @@ int main(int argc, char *argv[]) QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round); #endif + FramelessHelperEarlyInitialize(); + QApplication application(argc, argv); MainWindow mainWindow; diff --git a/examples/mainwindow/mainwindow.cpp b/examples/mainwindow/mainwindow.cpp index 0924a69..79a353c 100644 --- a/examples/mainwindow/mainwindow.cpp +++ b/examples/mainwindow/mainwindow.cpp @@ -87,7 +87,7 @@ void MainWindow::setupUi() setHitTestVisible(titleBar->closeButton); connect(titleBar->minimizeButton, &QPushButton::clicked, this, &MainWindow::showMinimized); - connect(titleBar->maximizeButton, &QPushButton::clicked, this, &MainWindow::toggleMaximized); + connect(titleBar->maximizeButton, &QPushButton::clicked, this, &MainWindow::toggleMaximize); connect(titleBar->closeButton, &QPushButton::clicked, this, &MainWindow::close); connect(this, &MainWindow::windowIconChanged, titleBar->iconButton, &QPushButton::setIcon); connect(this, &MainWindow::windowTitleChanged, titleBar->titleLabel, &QLabel::setText); diff --git a/examples/quick/main.cpp b/examples/quick/main.cpp index 9afb11c..e6c7501 100644 --- a/examples/quick/main.cpp +++ b/examples/quick/main.cpp @@ -45,6 +45,8 @@ int main(int argc, char *argv[]) QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round); #endif + FramelessHelperEarlyInitialize(); + QGuiApplication application(argc, argv); #ifdef Q_OS_WINDOWS diff --git a/examples/quick/qml/MainWindow.qml b/examples/quick/qml/MainWindow.qml index bc34d91..2ad38d1 100644 --- a/examples/quick/qml/MainWindow.qml +++ b/examples/quick/qml/MainWindow.qml @@ -55,8 +55,6 @@ FramelessWindow { StandardTitleBar { id: titleBar anchors { - top: parent.top - topMargin: 1 left: parent.left right: parent.right } @@ -76,7 +74,13 @@ FramelessWindow { onClicked: window.close() } Component.onCompleted: { + // Make our homemade title bar snap to the window top frame border. + window.snapToTopBorder(titleBar, FramelessHelper.Top, FramelessHelper.Bottom); + // Make our homemade title bar draggable, and on Windows, open the system menu + // when the user right clicks on the title bar area. window.setTitleBarItem(titleBar); + // Make our homemade system buttons visible to hit test. + // The call to "setHitTestVisible()" is necessary, don't forget to do it. window.setHitTestVisible(minimizeButton); window.setHitTestVisible(maximizeButton); window.setHitTestVisible(closeButton); diff --git a/examples/widget/main.cpp b/examples/widget/main.cpp index fb24c0b..1afa095 100644 --- a/examples/widget/main.cpp +++ b/examples/widget/main.cpp @@ -42,6 +42,8 @@ int main(int argc, char *argv[]) QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round); #endif + FramelessHelperEarlyInitialize(); + QApplication application(argc, argv); Widget widget; diff --git a/include/FramelessHelper/Core/framelesshelpercore_global.h b/include/FramelessHelper/Core/framelesshelpercore_global.h index 25d3858..95b4774 100644 --- a/include/FramelessHelper/Core/framelesshelpercore_global.h +++ b/include/FramelessHelper/Core/framelesshelpercore_global.h @@ -116,6 +116,8 @@ using NATIVE_EVENT_RESULT_TYPE = long; FRAMELESSHELPER_BEGIN_NAMESPACE +FRAMELESSHELPER_CORE_API void FramelessHelperEarlyInitialize(); + namespace Global { @@ -207,6 +209,18 @@ enum class DwmColorizationArea : int }; Q_ENUM_NS(DwmColorizationArea) +enum class Anchor : int +{ + Top = 0, + Bottom = 1, + Left = 2, + Right = 3, + HorizontalCenter = 4, + VerticalCenter = 5, + Center = 6 +}; +Q_ENUM_NS(Anchor) + using GetWindowFlagsCallback = std::function; using SetWindowFlagsCallback = std::function; @@ -281,10 +295,10 @@ struct SystemParameters { return (windowId && getWindowFlags && setWindowFlags && getWindowSize && setWindowSize && getWindowPosition && setWindowPosition - && isWindowFixedSize && setWindowFixedSize && getWindowState - && setWindowState && getWindowHandle && windowToScreen && screenToWindow - && isInsideSystemButtons && isInsideTitleBarDraggableArea - && getWindowDevicePixelRatio); + && getWindowScreen && isWindowFixedSize && setWindowFixedSize + && getWindowState && setWindowState && getWindowHandle + && windowToScreen && screenToWindow && isInsideSystemButtons + && isInsideTitleBarDraggableArea && getWindowDevicePixelRatio); } }; diff --git a/include/FramelessHelper/Quick/framelessquickwindow.h b/include/FramelessHelper/Quick/framelessquickwindow.h index 6212b6b..933e8a2 100644 --- a/include/FramelessHelper/Quick/framelessquickwindow.h +++ b/include/FramelessHelper/Quick/framelessquickwindow.h @@ -74,12 +74,7 @@ public Q_SLOTS: void setHitTestVisible(QQuickItem *item); void moveToDesktopCenter(); void bringToFront(); - -protected: - void showEvent(QShowEvent *event) override; - void mousePressEvent(QMouseEvent *event) override; - void mouseReleaseEvent(QMouseEvent *event) override; - void mouseDoubleClickEvent(QMouseEvent *event) override; + void snapToTopBorder(QQuickItem *item, const Global::Anchor itemAnchor, const Global::Anchor topBorderAnchor); Q_SIGNALS: void hiddenChanged(); diff --git a/include/FramelessHelper/Widgets/framelessmainwindow.h b/include/FramelessHelper/Widgets/framelessmainwindow.h index d35a591..0db8276 100644 --- a/include/FramelessHelper/Widgets/framelessmainwindow.h +++ b/include/FramelessHelper/Widgets/framelessmainwindow.h @@ -56,7 +56,7 @@ public: public Q_SLOTS: void setHitTestVisible(QWidget *widget); - void toggleMaximized(); + void toggleMaximize(); void toggleFullScreen(); void moveToDesktopCenter(); void bringToFront(); @@ -64,14 +64,6 @@ public Q_SLOTS: void startSystemMove2(); void startSystemResize2(const Qt::Edges edges); -protected: - void showEvent(QShowEvent *event) override; - void changeEvent(QEvent *event) override; - void paintEvent(QPaintEvent *event) override; - void mousePressEvent(QMouseEvent *event) override; - void mouseReleaseEvent(QMouseEvent *event) override; - void mouseDoubleClickEvent(QMouseEvent *event) override; - Q_SIGNALS: void hiddenChanged(); void normalChanged(); diff --git a/include/FramelessHelper/Widgets/framelesswidget.h b/include/FramelessHelper/Widgets/framelesswidget.h index 731467f..2b7e8a7 100644 --- a/include/FramelessHelper/Widgets/framelesswidget.h +++ b/include/FramelessHelper/Widgets/framelesswidget.h @@ -60,7 +60,7 @@ public: public Q_SLOTS: void setHitTestVisible(QWidget *widget); - void toggleMaximized(); + void toggleMaximize(); void toggleFullScreen(); void moveToDesktopCenter(); void bringToFront(); @@ -68,14 +68,6 @@ public Q_SLOTS: void startSystemMove2(); void startSystemResize2(const Qt::Edges edges); -protected: - void showEvent(QShowEvent *event) override; - void changeEvent(QEvent *event) override; - void paintEvent(QPaintEvent *event) override; - void mousePressEvent(QMouseEvent *event) override; - void mouseReleaseEvent(QMouseEvent *event) override; - void mouseDoubleClickEvent(QMouseEvent *event) override; - Q_SIGNALS: void hiddenChanged(); void normalChanged(); diff --git a/include/FramelessHelper/Widgets/framelesswidgetshelper.h b/include/FramelessHelper/Widgets/framelesswidgetshelper.h index 104c2b8..b26664e 100644 --- a/include/FramelessHelper/Widgets/framelesswidgetshelper.h +++ b/include/FramelessHelper/Widgets/framelesswidgetshelper.h @@ -68,7 +68,7 @@ public: public Q_SLOTS: void setHitTestVisible(QWidget *widget); - void toggleMaximized(); + void toggleMaximize(); void toggleFullScreen(); void moveToDesktopCenter(); void bringToFront(); @@ -76,6 +76,9 @@ public Q_SLOTS: void startSystemMove2(); void startSystemResize2(const Qt::Edges edges); +protected: + Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override; + private: void initialize(); void createSystemTitleBar(); diff --git a/src/core/framelesswindowsmanager.cpp b/src/core/framelesswindowsmanager.cpp index 2a63ab5..39a6720 100644 --- a/src/core/framelesswindowsmanager.cpp +++ b/src/core/framelesswindowsmanager.cpp @@ -51,11 +51,6 @@ Q_GLOBAL_STATIC(FramelessWindowsManager, g_manager) FramelessWindowsManager::FramelessWindowsManager(QObject *parent) : QObject(parent) { - if (!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings)) { - QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); - } - qRegisterMetaType(); - qRegisterMetaType(); } FramelessWindowsManager::~FramelessWindowsManager() = default; @@ -136,4 +131,18 @@ void FramelessWindowsManager::addWindow(const UserSettings &settings, const Syst #endif } +void FramelessHelperEarlyInitialize() +{ + static bool inited = false; + if (inited) { + return; + } + inited = true; + if (!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings)) { + QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + } + qRegisterMetaType(); + qRegisterMetaType(); +} + FRAMELESSHELPER_END_NAMESPACE diff --git a/src/core/utils_win.cpp b/src/core/utils_win.cpp index b141800..02013f0 100644 --- a/src/core/utils_win.cpp +++ b/src/core/utils_win.cpp @@ -731,10 +731,10 @@ quint32 Utils::getPrimaryScreenDpi(const bool horizontal) if (SUCCEEDED(pD2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, IID_PPV_ARGS(&d2dFactory)))) { if (SUCCEEDED(d2dFactory->ReloadSystemMetrics())) { FLOAT dpiX = 0.0, dpiY = 0.0; -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED d2dFactory->GetDesktopDpi(&dpiX, &dpiY); -QT_WARNING_POP + QT_WARNING_POP return (horizontal ? quint32(qRound(dpiX)) : quint32(qRound(dpiY))); } } diff --git a/src/quick/framelesshelper_quick.cpp b/src/quick/framelesshelper_quick.cpp index 00533ee..daa8566 100644 --- a/src/quick/framelesshelper_quick.cpp +++ b/src/quick/framelesshelper_quick.cpp @@ -30,7 +30,15 @@ #ifndef QML_URL_EXPAND # define QML_URL_EXPAND(fileName) \ - QUrl(QStringLiteral("qrc:///org.wangwenx190.FramelessHelper/qml/%1.qml").arg(fileName)) + QUrl(QStringLiteral("qrc:///org.wangwenx190.FramelessHelper/qml/%1.qml").arg(QStringLiteral(fileName))) +#endif + +#ifndef QUICK_URI_SHORT +# define QUICK_URI_SHORT FRAMELESSHELPER_QUICK_URI, 1 +#endif + +#ifndef QUICK_URI_EXPAND +# define QUICK_URI_EXPAND(name) QUICK_URI_SHORT, 0, name #endif // The "Q_INIT_RESOURCE()" macro can't be used inside a namespace, @@ -49,23 +57,31 @@ void FramelessHelper::Quick::registerTypes(QQmlEngine *engine) if (!engine) { return; } + static bool inited = false; + if (inited) { + return; + } + inited = true; engine->addImageProvider(QStringLiteral("framelesshelper"), new FramelessHelperImageProvider); - qmlRegisterSingletonType(FRAMELESSHELPER_QUICK_URI, 1, 0, "FramelessUtils", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * { - Q_UNUSED(engine); - Q_UNUSED(scriptEngine); - return new FramelessQuickUtils; - }); - qmlRegisterType(FRAMELESSHELPER_QUICK_URI, 1, 0, "FramelessWindow"); + qmlRegisterUncreatableMetaObject(Global::staticMetaObject, QUICK_URI_EXPAND("FramelessHelper"), + QStringLiteral("The FramelessHelper namespace is not creatable, you can only use it to access its enums.")); + qmlRegisterSingletonType(QUICK_URI_EXPAND("FramelessUtils"), + [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * { + Q_UNUSED(engine); + Q_UNUSED(scriptEngine); + return new FramelessQuickUtils; + }); #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) - qmlRegisterAnonymousType(FRAMELESSHELPER_QUICK_URI, 1); + qmlRegisterAnonymousType(QUICK_URI_SHORT); #else - qmlRegisterAnonymousType(FRAMELESSHELPER_QUICK_URI, 1); + qmlRegisterAnonymousType(QUICK_URI_SHORT); #endif + qmlRegisterType(QUICK_URI_EXPAND("FramelessWindow")); initResource(); - qmlRegisterType(QML_URL_EXPAND(QStringLiteral("MinimizeButton")), FRAMELESSHELPER_QUICK_URI, 1, 0, "MinimizeButton"); - qmlRegisterType(QML_URL_EXPAND(QStringLiteral("MaximizeButton")), FRAMELESSHELPER_QUICK_URI, 1, 0, "MaximizeButton"); - qmlRegisterType(QML_URL_EXPAND(QStringLiteral("CloseButton")), FRAMELESSHELPER_QUICK_URI, 1, 0, "CloseButton"); - qmlRegisterType(QML_URL_EXPAND(QStringLiteral("StandardTitleBar")), FRAMELESSHELPER_QUICK_URI, 1, 0, "StandardTitleBar"); + qmlRegisterType(QML_URL_EXPAND("MinimizeButton"), QUICK_URI_EXPAND("MinimizeButton")); + qmlRegisterType(QML_URL_EXPAND("MaximizeButton"), QUICK_URI_EXPAND("MaximizeButton")); + qmlRegisterType(QML_URL_EXPAND("CloseButton"), QUICK_URI_EXPAND("CloseButton")); + qmlRegisterType(QML_URL_EXPAND("StandardTitleBar"), QUICK_URI_EXPAND("StandardTitleBar")); } FRAMELESSHELPER_END_NAMESPACE diff --git a/src/quick/framelessquickwindow.cpp b/src/quick/framelessquickwindow.cpp index 4839273..1becd6a 100644 --- a/src/quick/framelessquickwindow.cpp +++ b/src/quick/framelessquickwindow.cpp @@ -109,6 +109,36 @@ QColor FramelessQuickWindowPrivate::getFrameBorderColor() const #endif } +QQuickAnchorLine FramelessQuickWindowPrivate::getTopBorderTop() const +{ + return QQuickAnchorLine(m_topBorderRectangle.data(), QQuickAnchors::TopAnchor); +} + +QQuickAnchorLine FramelessQuickWindowPrivate::getTopBorderBottom() const +{ + return QQuickAnchorLine(m_topBorderRectangle.data(), QQuickAnchors::BottomAnchor); +} + +QQuickAnchorLine FramelessQuickWindowPrivate::getTopBorderLeft() const +{ + return QQuickAnchorLine(m_topBorderRectangle.data(), QQuickAnchors::LeftAnchor); +} + +QQuickAnchorLine FramelessQuickWindowPrivate::getTopBorderRight() const +{ + return QQuickAnchorLine(m_topBorderRectangle.data(), QQuickAnchors::RightAnchor); +} + +QQuickAnchorLine FramelessQuickWindowPrivate::getTopBorderHorizontalCenter() const +{ + return QQuickAnchorLine(m_topBorderRectangle.data(), QQuickAnchors::HCenterAnchor); +} + +QQuickAnchorLine FramelessQuickWindowPrivate::getTopBorderVerticalCenter() const +{ + return QQuickAnchorLine(m_topBorderRectangle.data(), QQuickAnchors::VCenterAnchor); +} + void FramelessQuickWindowPrivate::setTitleBarItem(QQuickItem *item) { Q_ASSERT(item); @@ -178,6 +208,96 @@ void FramelessQuickWindowPrivate::bringToFront() q->requestActivate(); } +void FramelessQuickWindowPrivate::snapToTopBorder(QQuickItem *item, const Anchor itemAnchor, const Anchor topBorderAnchor) +{ + Q_ASSERT(item); + if (!item) { + return; + } + const QQuickAnchorLine targetAnchorLine = [this, topBorderAnchor]() -> QQuickAnchorLine { + switch (topBorderAnchor) { + case Anchor::Top: + return getTopBorderTop(); + case Anchor::Bottom: + return getTopBorderBottom(); + case Anchor::Left: + return getTopBorderLeft(); + case Anchor::Right: + return getTopBorderRight(); + case Anchor::HorizontalCenter: + return getTopBorderHorizontalCenter(); + case Anchor::VerticalCenter: + return getTopBorderVerticalCenter(); + default: + break; + } + return {}; + }(); + const QQuickItemPrivate * const itemPrivate = QQuickItemPrivate::get(item); + QQuickAnchors * const anchors = itemPrivate->anchors(); + switch (itemAnchor) { + case Anchor::Top: + anchors->setTop(targetAnchorLine); + break; + case Anchor::Bottom: + anchors->setBottom(targetAnchorLine); + break; + case Anchor::Left: + anchors->setLeft(targetAnchorLine); + break; + case Anchor::Right: + anchors->setRight(targetAnchorLine); + break; + case Anchor::HorizontalCenter: + anchors->setHorizontalCenter(targetAnchorLine); + break; + case Anchor::VerticalCenter: + anchors->setVerticalCenter(targetAnchorLine); + break; + case Anchor::Center: + anchors->setCenterIn(m_topBorderRectangle.data()); + break; + } +} + +bool FramelessQuickWindowPrivate::eventFilter(QObject *object, QEvent *event) +{ + Q_ASSERT(object); + Q_ASSERT(event); + if (!object || !event) { + return false; + } + if (!object->isWindowType()) { + return QObject::eventFilter(object, event); + } + Q_Q(FramelessQuickWindow); + const auto window = qobject_cast(object); + if (window != q) { + return QObject::eventFilter(object, event); + } + switch (event->type()) { + case QEvent::Show: { + const auto showEvent = static_cast(event); + showEventHandler(showEvent); + } break; + case QEvent::MouseButtonPress: { + const auto mouseEvent = static_cast(event); + mousePressEventHandler(mouseEvent); + } break; + case QEvent::MouseButtonRelease: { + const auto mouseEvent = static_cast(event); + mouseReleaseEventHandler(mouseEvent); + } break; + case QEvent::MouseButtonDblClick: { + const auto mouseEvent = static_cast(event); + mouseDoubleClickEventHandler(mouseEvent); + } break; + default: + break; + } + return QObject::eventFilter(object, event); +} + void FramelessQuickWindowPrivate::showMinimized2() { #ifdef Q_OS_WINDOWS @@ -288,10 +408,18 @@ void FramelessQuickWindowPrivate::initialize() m_params.getWindowDevicePixelRatio = [q]() -> qreal { return q->effectiveDevicePixelRatio(); }; FramelessWindowsManager * const manager = FramelessWindowsManager::instance(); manager->addWindow(m_settings, m_params); + q->installEventFilter(this); QQuickItem * const rootItem = q->contentItem(); const QQuickItemPrivate * const rootItemPrivate = QQuickItemPrivate::get(rootItem); m_topBorderRectangle.reset(new QQuickRectangle(rootItem)); - const bool frameBorderVisible = shouldDrawFrameBorder(); + const bool frameBorderVisible = [this]() -> bool { +#ifdef Q_OS_WINDOWS + return (Utils::isWindowFrameBorderVisible() && !Utils::isWin11OrGreater() + && !(m_settings.options & Option::DontDrawTopWindowFrameBorder)); +#else + return false; +#endif + }(); if (frameBorderVisible) { updateTopBorderHeight(); updateTopBorderColor(); @@ -337,7 +465,7 @@ QRect FramelessQuickWindowPrivate::mapItemGeometryToScene(const QQuickItem * con return QRectF(originPoint, size).toRect(); } -bool FramelessQuickWindowPrivate::isInSystemButtons(const QPoint &pos, Global::SystemButtonType *button) const +bool FramelessQuickWindowPrivate::isInSystemButtons(const QPoint &pos, SystemButtonType *button) const { Q_ASSERT(button); if (!button) { @@ -387,22 +515,14 @@ bool FramelessQuickWindowPrivate::isInTitleBarDraggableArea(const QPoint &pos) c return region.contains(pos); } -bool FramelessQuickWindowPrivate::shouldDrawFrameBorder() const -{ -#ifdef Q_OS_WINDOWS - return (Utils::isWindowFrameBorderVisible() && !Utils::isWin11OrGreater() - && isNormal() && !(m_settings.options & Option::DontDrawTopWindowFrameBorder)); -#else - return false; -#endif -} - bool FramelessQuickWindowPrivate::shouldIgnoreMouseEvents(const QPoint &pos) const { Q_Q(const FramelessQuickWindow); - return (isNormal() && ((pos.x() < kDefaultResizeBorderThickness) - || (pos.x() >= (q->width() - kDefaultResizeBorderThickness)) - || (pos.y() < kDefaultResizeBorderThickness))); + return (isNormal() + && ((pos.y() < kDefaultResizeBorderThickness) + || (Utils::isWindowFrameBorderVisible() + ? false : ((pos.x() < kDefaultResizeBorderThickness) + || (pos.x() >= (q->width() - kDefaultResizeBorderThickness)))))); } void FramelessQuickWindowPrivate::showEventHandler(QShowEvent *event) @@ -610,32 +730,14 @@ void FramelessQuickWindow::bringToFront() d->bringToFront(); } -void FramelessQuickWindow::showEvent(QShowEvent *event) +void FramelessQuickWindow::snapToTopBorder(QQuickItem *item, const Anchor itemAnchor, const Anchor topBorderAnchor) { - QQuickWindow::showEvent(event); + Q_ASSERT(item); + if (!item) { + return; + } Q_D(FramelessQuickWindow); - d->showEventHandler(event); -} - -void FramelessQuickWindow::mousePressEvent(QMouseEvent *event) -{ - QQuickWindow::mousePressEvent(event); - Q_D(FramelessQuickWindow); - d->mousePressEventHandler(event); -} - -void FramelessQuickWindow::mouseReleaseEvent(QMouseEvent *event) -{ - QQuickWindow::mouseReleaseEvent(event); - Q_D(FramelessQuickWindow); - d->mouseReleaseEventHandler(event); -} - -void FramelessQuickWindow::mouseDoubleClickEvent(QMouseEvent *event) -{ - QQuickWindow::mouseDoubleClickEvent(event); - Q_D(FramelessQuickWindow); - d->mouseDoubleClickEventHandler(event); + d->snapToTopBorder(item, itemAnchor, topBorderAnchor); } void FramelessQuickWindow::showMinimized2() @@ -670,6 +772,9 @@ void FramelessQuickWindow::startSystemMove2() void FramelessQuickWindow::startSystemResize2(const Qt::Edges edges) { + if (edges == Qt::Edges{}) { + return; + } Q_D(FramelessQuickWindow); d->startSystemResize2(edges); } diff --git a/src/quick/framelessquickwindow_p.h b/src/quick/framelessquickwindow_p.h index 58dac76..5c12c21 100644 --- a/src/quick/framelessquickwindow_p.h +++ b/src/quick/framelessquickwindow_p.h @@ -27,11 +27,10 @@ #include "framelesshelperquick_global.h" #include #include +#include QT_BEGIN_NAMESPACE -class QQuickItem; class QQuickRectangle; -class QQuickAnchors; QT_END_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE @@ -56,6 +55,12 @@ public: Q_INVOKABLE Q_NODISCARD bool isFixedSize() const; Q_INVOKABLE Q_NODISCARD QColor getFrameBorderColor() const; + Q_INVOKABLE Q_NODISCARD QQuickAnchorLine getTopBorderTop() const; + Q_INVOKABLE Q_NODISCARD QQuickAnchorLine getTopBorderBottom() const; + Q_INVOKABLE Q_NODISCARD QQuickAnchorLine getTopBorderLeft() const; + Q_INVOKABLE Q_NODISCARD QQuickAnchorLine getTopBorderRight() const; + Q_INVOKABLE Q_NODISCARD QQuickAnchorLine getTopBorderHorizontalCenter() const; + Q_INVOKABLE Q_NODISCARD QQuickAnchorLine getTopBorderVerticalCenter() const; Q_INVOKABLE void showEventHandler(QShowEvent *event); Q_INVOKABLE void mousePressEventHandler(QMouseEvent *event); @@ -74,13 +79,16 @@ public Q_SLOTS: void moveToDesktopCenter(); void setFixedSize(const bool value, const bool force = false); void bringToFront(); + void snapToTopBorder(QQuickItem *item, const Global::Anchor itemAnchor, const Global::Anchor topBorderAnchor); + +protected: + Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override; private: void initialize(); Q_NODISCARD QRect mapItemGeometryToScene(const QQuickItem * const item) const; Q_NODISCARD bool isInSystemButtons(const QPoint &pos, Global::SystemButtonType *button) const; Q_NODISCARD bool isInTitleBarDraggableArea(const QPoint &pos) const; - Q_NODISCARD bool shouldDrawFrameBorder() const; Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const; private Q_SLOTS: diff --git a/src/widgets/framelessmainwindow.cpp b/src/widgets/framelessmainwindow.cpp index f42f158..02e90ab 100644 --- a/src/widgets/framelessmainwindow.cpp +++ b/src/widgets/framelessmainwindow.cpp @@ -71,9 +71,9 @@ void FramelessMainWindow::setHitTestVisible(QWidget *widget) m_helper->setHitTestVisible(widget); } -void FramelessMainWindow::toggleMaximized() +void FramelessMainWindow::toggleMaximize() { - m_helper->toggleMaximized(); + m_helper->toggleMaximize(); } void FramelessMainWindow::toggleFullScreen() @@ -106,40 +106,4 @@ void FramelessMainWindow::startSystemResize2(const Qt::Edges edges) m_helper->startSystemResize2(edges); } -void FramelessMainWindow::showEvent(QShowEvent *event) -{ - QMainWindow::showEvent(event); - m_helper->showEventHandler(event); -} - -void FramelessMainWindow::changeEvent(QEvent *event) -{ - QMainWindow::changeEvent(event); - m_helper->changeEventHandler(event); -} - -void FramelessMainWindow::paintEvent(QPaintEvent *event) -{ - QMainWindow::paintEvent(event); - m_helper->paintEventHandler(event); -} - -void FramelessMainWindow::mousePressEvent(QMouseEvent *event) -{ - QMainWindow::mousePressEvent(event); - m_helper->mousePressEventHandler(event); -} - -void FramelessMainWindow::mouseReleaseEvent(QMouseEvent *event) -{ - QMainWindow::mouseReleaseEvent(event); - m_helper->mouseReleaseEventHandler(event); -} - -void FramelessMainWindow::mouseDoubleClickEvent(QMouseEvent *event) -{ - QMainWindow::mouseDoubleClickEvent(event); - m_helper->mouseDoubleClickEventHandler(event); -} - FRAMELESSHELPER_END_NAMESPACE diff --git a/src/widgets/framelesswidget.cpp b/src/widgets/framelesswidget.cpp index f937c37..9926433 100644 --- a/src/widgets/framelesswidget.cpp +++ b/src/widgets/framelesswidget.cpp @@ -81,9 +81,9 @@ void FramelessWidget::setHitTestVisible(QWidget *widget) m_helper->setHitTestVisible(widget); } -void FramelessWidget::toggleMaximized() +void FramelessWidget::toggleMaximize() { - m_helper->toggleMaximized(); + m_helper->toggleMaximize(); } void FramelessWidget::toggleFullScreen() @@ -116,40 +116,4 @@ void FramelessWidget::startSystemResize2(const Qt::Edges edges) m_helper->startSystemResize2(edges); } -void FramelessWidget::showEvent(QShowEvent *event) -{ - QWidget::showEvent(event); - m_helper->showEventHandler(event); -} - -void FramelessWidget::changeEvent(QEvent *event) -{ - QWidget::changeEvent(event); - m_helper->changeEventHandler(event); -} - -void FramelessWidget::paintEvent(QPaintEvent *event) -{ - QWidget::paintEvent(event); - m_helper->paintEventHandler(event); -} - -void FramelessWidget::mousePressEvent(QMouseEvent *event) -{ - QWidget::mousePressEvent(event); - m_helper->mousePressEventHandler(event); -} - -void FramelessWidget::mouseReleaseEvent(QMouseEvent *event) -{ - QWidget::mouseReleaseEvent(event); - m_helper->mouseReleaseEventHandler(event); -} - -void FramelessWidget::mouseDoubleClickEvent(QMouseEvent *event) -{ - QWidget::mouseDoubleClickEvent(event); - m_helper->mouseDoubleClickEventHandler(event); -} - FRAMELESSHELPER_END_NAMESPACE diff --git a/src/widgets/framelesswidgetshelper.cpp b/src/widgets/framelesswidgetshelper.cpp index 9da5fd4..631db02 100644 --- a/src/widgets/framelesswidgetshelper.cpp +++ b/src/widgets/framelesswidgetshelper.cpp @@ -335,7 +335,7 @@ void FramelessWidgetsHelper::mouseDoubleClickEventHandler(QMouseEvent *event) if (!isInTitleBarDraggableArea(scenePos)) { return; } - toggleMaximized(); + toggleMaximize(); } void FramelessWidgetsHelper::initialize() @@ -393,12 +393,16 @@ void FramelessWidgetsHelper::initialize() " Enabling this option will mess up with your main window's layout."; } } + if (m_settings.options & Option::DisableResizing) { + setFixedSize(true, true); + } if (m_settings.options & Option::BeCompatibleWithQtFramelessWindowHint) { Utils::tryToBeCompatibleWithQtFramelessWindowHint(windowId, m_params.getWindowFlags, m_params.setWindowFlags, true); } FramelessWindowsManager * const manager = FramelessWindowsManager::instance(); manager->addWindow(m_settings, m_params); + q->installEventFilter(this); connect(manager, &FramelessWindowsManager::systemThemeChanged, this, [this](){ if (m_settings.options & Option::UseStandardWindowLayout) { updateSystemTitleBarStyleSheet(); @@ -414,16 +418,10 @@ void FramelessWidgetsHelper::initialize() }); setupInitialUi(); if (m_settings.options & Option::UseStandardWindowLayout) { - Q_ASSERT(m_systemMinimizeButton); - Q_ASSERT(m_systemMaximizeButton); - Q_ASSERT(m_systemCloseButton); m_settings.minimizeButton = m_systemMinimizeButton; m_settings.maximizeButton = m_systemMaximizeButton; m_settings.closeButton = m_systemCloseButton; } - if (m_settings.options & Option::DisableResizing) { - setFixedSize(true, true); - } } void FramelessWidgetsHelper::createSystemTitleBar() @@ -450,7 +448,7 @@ void FramelessWidgetsHelper::createSystemTitleBar() m_systemMaximizeButton->setFixedSize(kDefaultSystemButtonSize); m_systemMaximizeButton->setIconSize(kDefaultSystemButtonIconSize); m_systemMaximizeButton->setToolTip(tr("Maximize")); - connect(m_systemMaximizeButton, &QPushButton::clicked, this, &FramelessWidgetsHelper::toggleMaximized); + connect(m_systemMaximizeButton, &QPushButton::clicked, this, &FramelessWidgetsHelper::toggleMaximize); m_systemCloseButton = new QPushButton(m_systemTitleBarWidget); m_systemCloseButton->setFixedSize(kDefaultSystemButtonSize); m_systemCloseButton->setIconSize(kDefaultSystemButtonIconSize); @@ -510,7 +508,7 @@ QRect FramelessWidgetsHelper::mapWidgetGeometryToScene(const QWidget * const wid return QRect(originPoint, size); } -bool FramelessWidgetsHelper::isInSystemButtons(const QPoint &pos, Global::SystemButtonType *button) const +bool FramelessWidgetsHelper::isInSystemButtons(const QPoint &pos, SystemButtonType *button) const { Q_ASSERT(button); if (!button) { @@ -581,9 +579,11 @@ bool FramelessWidgetsHelper::shouldDrawFrameBorder() const bool FramelessWidgetsHelper::shouldIgnoreMouseEvents(const QPoint &pos) const { - return (isNormal() && ((pos.x() < kDefaultResizeBorderThickness) - || (pos.x() >= (q->width() - kDefaultResizeBorderThickness)) - || (pos.y() < kDefaultResizeBorderThickness))); + return (isNormal() + && ((pos.y() < kDefaultResizeBorderThickness) + || (Utils::isWindowFrameBorderVisible() + ? false : ((pos.x() < kDefaultResizeBorderThickness) + || (pos.x() >= (q->width() - kDefaultResizeBorderThickness)))))); } void FramelessWidgetsHelper::updateContentsMargins() @@ -644,7 +644,7 @@ void FramelessWidgetsHelper::updateSystemButtonsIcon() m_systemCloseButton->setIcon(qvariant_cast(Utils::getSystemButtonIconResource(SystemButtonType::Close, theme, resource))); } -void FramelessWidgetsHelper::toggleMaximized() +void FramelessWidgetsHelper::toggleMaximize() { if (isFixedSize()) { return; @@ -716,4 +716,49 @@ void FramelessWidgetsHelper::startSystemResize2(const Qt::Edges edges) #endif } +bool FramelessWidgetsHelper::eventFilter(QObject *object, QEvent *event) +{ + Q_ASSERT(object); + Q_ASSERT(event); + if (!object || !event) { + return false; + } + if (!object->isWidgetType()) { + return QObject::eventFilter(object, event); + } + const auto widget = qobject_cast(object); + if (widget != q) { + return QObject::eventFilter(object, event); + } + switch (event->type()) { + case QEvent::Show: { + const auto showEvent = static_cast(event); + showEventHandler(showEvent); + } break; + case QEvent::Paint: { + const auto paintEvent = static_cast(event); + paintEventHandler(paintEvent); + } break; + case QEvent::MouseButtonPress: { + const auto mouseEvent = static_cast(event); + mousePressEventHandler(mouseEvent); + } break; + case QEvent::MouseButtonRelease: { + const auto mouseEvent = static_cast(event); + mouseReleaseEventHandler(mouseEvent); + } break; + case QEvent::MouseButtonDblClick: { + const auto mouseEvent = static_cast(event); + mouseDoubleClickEventHandler(mouseEvent); + } break; + case QEvent::ActivationChange: + case QEvent::WindowStateChange: { + changeEventHandler(event); + } break; + default: + break; + } + return QObject::eventFilter(object, event); +} + FRAMELESSHELPER_END_NAMESPACE