From b672851f515ca6caa812bbfaa6ca3a27b9dff093 Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Mon, 16 Nov 2020 17:05:39 +0800 Subject: [PATCH] Win32: Remove the dependency of the widgets and quick module This commit totally removed the dependency of the widgets and quick modules for the Windows platform. Now the library itself only depends on the core and gui modules. Currently no bug can be found. But there are some side effects: one is we can't set a palette for a widget due to we can't access QWidget specific functions so if you want to enable blur effect, you will have to do this by yourself. Another one is you now have to pass the window handle to WinNativeEventFilter instead of the pointer of a QObject. Before this patch, I'm using QWidget::winId() to get the window handle, now we have get rid of the widgets dependency so I can't get the window handle now, you have to pass it explicitly. And it leads to huge refactoring of the whole repository. But I think it's worth doing. If anyone knows how to get the window handle without introducing new dependencies, please tell me. It will help me a lot. To remove the quick dependency, the FramelessQuickHelper class is moved out of the library now. If your project needs it, please copy the files to your project and include them directly. Signed-off-by: Yuhang Zhao <2546789017@qq.com> --- README.md | 28 ++-- README_win32.md | 14 +- examples/QMainWindow/main.cpp | 18 ++- examples/QWidget/main.cpp | 16 ++- examples/Quick/Quick.pro | 3 +- examples/Win32Demo/widget.cpp | 18 ++- examples/common.pri | 11 +- framelesshelper.cpp | 54 ++++---- framelessquickhelper.cpp | 92 ++++++------- framelessquickhelper.h | 13 +- framelesswindowsmanager.cpp | 236 +++++++--------------------------- framelesswindowsmanager.h | 57 ++++---- lib.pro | 10 +- winnativeeventfilter.cpp | 146 ++++++--------------- winnativeeventfilter.h | 15 +-- 15 files changed, 260 insertions(+), 471 deletions(-) diff --git a/README.md b/README.md index a925f67..3d3a423 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,12 @@ If you are using part of or all the code from this repository in your own projec int main(int argc, char *argv[]) { QWidget widget; // Do this before the widget is shown. - FramelessWindowsManager::addWindow(&widget); +#ifdef Q_OS_WIN + const auto id = reinterpret_cast(widget.winId()); +#else + const auto id = static_cast(&widget); +#endif + FramelessWindowsManager::addWindow(id); widget.show(); } ``` @@ -65,29 +70,34 @@ Please refer to [the QWidget example](/examples/QWidget/main.cpp) for more detai ```cpp // Only **TOP LEVEL** QWidgets and QWindows are supported. QMainWindow *mainWindow = new QMainWindow; +#ifdef Q_OS_WIN +const auto id = reinterpret_cast(mainWindow->winId()); +#else +const auto id = static_cast(mainWindow); +#endif // Disable resizing of the given window. Resizing is enabled by default. -FramelessWindowsManager::setResizable(mainWindow, false); +FramelessWindowsManager::setResizable(id, false); // All the following values should not be DPI-aware, just use the // original numbers, assuming the scale factor is 1.0, don't scale // them yourself, this code will do the scaling according to DPI // internally and automatically. // Maximum window size -FramelessWindowsManager::setMaximumSize(mainWindow, {1280, 720}); +FramelessWindowsManager::setMaximumSize(id, {1280, 720}); // Minimum window size -FramelessWindowsManager::setMinimumSize(mainWindow, {800, 540}); +FramelessWindowsManager::setMinimumSize(id, {800, 540}); // How to set ignore areas: // The geometry of something you already know, in window coordinates -FramelessWindowsManager::addIgnoreArea(mainWindow, {100, 0, 30, 30}); +FramelessWindowsManager::addIgnoreArea(id, {100, 0, 30, 30}); // The geometry of a widget, in window coordinates. // It won't update automatically when the geometry of that widget has // changed, so if you want to add a widget, which is in a layout and // it's geometry will possibly change, to the ignore list, try the // next method (addIgnoreObject) instead. -FramelessWindowsManager::addIgnoreArea(mainWindow, pushButton_close.geometry()); +FramelessWindowsManager::addIgnoreArea(id, pushButton_close.geometry()); // The **POINTER** of a QWidget or QQuickItem -FramelessWindowsManager::addIgnoreObject(mainWindow, ui->pushButton_minimize); +FramelessWindowsManager::addIgnoreObject(id, ui->pushButton_minimize); // Move a QWidget or QWindow to the center of its current desktop. -FramelessWindowsManager::moveWindowToDesktopCenter(mainWindow); +FramelessWindowsManager::moveWindowToDesktopCenter(id); ``` ## Supported Platforms @@ -108,7 +118,7 @@ A not too old version of Linux and macOS, 32 bit & 64 bit. | Component | Requirement | Additional Information | | --- | --- | --- | -| Qt | >= 5.6 | Only the `gui` module is required explicitly, but to make full use of this repository, you'd better install the `widgets` and `quick` modules as well | +| Qt | >= 5.6 | Only the `core` and `gui` modules are required | | Compiler | >= C++11 | MSVC, MinGW, Clang-CL, Intel-CL or cross compile from Linux/macOS are all supported | ### UNIX diff --git a/README_win32.md b/README_win32.md index aac7b02..f35280c 100644 --- a/README_win32.md +++ b/README_win32.md @@ -32,7 +32,7 @@ ```cpp QWidget widget; // Do this before the widget is shown. -WinNativeEventFilter::addFramelessWindow(&widget); +WinNativeEventFilter::addFramelessWindow(reinterpret_cast(widget.winId())); widget.show(); ``` @@ -41,6 +41,8 @@ Please refer to [the QWidget example](/examples/QWidget/main.cpp) for more detai ### Ignore areas and etc ```cpp +// Get the window handle (HWND) first. +const auto handle = reinterpret_cast(widget.winId()); WinNativeEventFilter::WINDOWDATA data = {}; // All the following values should not be DPI-aware, just use the // original numbers, assuming the scale factor is 1.0, don't scale @@ -62,18 +64,18 @@ data.ignoreAreas.append(pushButton_close.geometry()); // The **POINTER** of a QWidget or QQuickItem data.ignoreObjects.append(ui->pushButton_minimize); // Pass data as the second parameter -WinNativeEventFilter::addFramelessWindow(&widget, &data); +WinNativeEventFilter::addFramelessWindow(handle, &data); // Or -WinNativeEventFilter::setWindowData(&widget, &data); +WinNativeEventFilter::setWindowData(handle, &data); // Or modify the window data of a specific window directly: -const auto data = WinNativeEventFilter::getWindowData(&widget); +const auto data = WinNativeEventFilter::getWindowData(handle); if (data) { data->borderWidth = 5; data->borderHeight = 5; data->titleBarHeight = 30; } // The frameless window is resizable by default. -WinNativeEventFilter::setWindowResizable(reinterpret_cast(mainWindow->winId()), false); +WinNativeEventFilter::setWindowResizable(handle, false); ``` ## Supported Platforms @@ -86,7 +88,7 @@ The code itself should be able to work on Windows Vista in theory, but Qt5 has d | Component | Requirement | Additional Information | | --- | --- | --- | -| Qt | >= 5.6 | Only the `gui` module is required explicitly, but to make full use of this repository, you'd better install the `widgets` and `quick` modules as well | +| Qt | >= 5.6 | Only the `core` and `gui` modules are required | | Compiler | >= C++11 | MSVC, MinGW, Clang-CL, Intel-CL or cross compile from Linux are all supported | ## Known Bugs diff --git a/examples/QMainWindow/main.cpp b/examples/QMainWindow/main.cpp index 362d5b3..3355aa0 100644 --- a/examples/QMainWindow/main.cpp +++ b/examples/QMainWindow/main.cpp @@ -103,17 +103,21 @@ int main(int argc, char *argv[]) mainWindow->setWindowIcon(icon); mainWindow->setWindowTitle(QObject::tr("Hello, World!")); - FramelessWindowsManager::addWindow(mainWindow); +#ifdef Q_OS_WIN + const auto id = reinterpret_cast(mainWindow->winId()); +#else + const auto id = static_cast(mainWindow); +#endif - FramelessWindowsManager::addIgnoreObject(mainWindow, titleBarWidget.minimizeButton); - FramelessWindowsManager::addIgnoreObject(mainWindow, titleBarWidget.maximizeButton); - FramelessWindowsManager::addIgnoreObject(mainWindow, titleBarWidget.closeButton); - FramelessWindowsManager::addIgnoreObject(mainWindow, appMainWindow.menubar); + FramelessWindowsManager::addWindow(id); + + FramelessWindowsManager::addIgnoreObject(id, titleBarWidget.minimizeButton); + FramelessWindowsManager::addIgnoreObject(id, titleBarWidget.maximizeButton); + FramelessWindowsManager::addIgnoreObject(id, titleBarWidget.closeButton); + FramelessWindowsManager::addIgnoreObject(id, appMainWindow.menubar); mainWindow->resize(800, 600); - //FramelessWindowsManager::moveWindowToDesktopCenter(mainWindow); - mainWindow->show(); return QApplication::exec(); diff --git a/examples/QWidget/main.cpp b/examples/QWidget/main.cpp index d59cfa0..7c24f08 100644 --- a/examples/QWidget/main.cpp +++ b/examples/QWidget/main.cpp @@ -94,16 +94,20 @@ int main(int argc, char *argv[]) widget.setLayout(mainLayout); widget.setWindowTitle(QObject::tr("Hello, World!")); - FramelessWindowsManager::addWindow(&widget); +#ifdef Q_OS_WIN + const auto id = reinterpret_cast(widget.winId()); +#else + const auto id = static_cast(&widget); +#endif - FramelessWindowsManager::addIgnoreObject(&widget, minimizeButton); - FramelessWindowsManager::addIgnoreObject(&widget, maximizeButton); - FramelessWindowsManager::addIgnoreObject(&widget, closeButton); + FramelessWindowsManager::addWindow(id); + + FramelessWindowsManager::addIgnoreObject(id, minimizeButton); + FramelessWindowsManager::addIgnoreObject(id, maximizeButton); + FramelessWindowsManager::addIgnoreObject(id, closeButton); widget.resize(800, 600); - //FramelessWindowsManager::moveWindowToDesktopCenter(&widget); - widget.show(); return QApplication::exec(); diff --git a/examples/Quick/Quick.pro b/examples/Quick/Quick.pro index c7a4817..d8ed467 100644 --- a/examples/Quick/Quick.pro +++ b/examples/Quick/Quick.pro @@ -1,6 +1,7 @@ TARGET = Quick TEMPLATE = app QT += quick -SOURCES += main.cpp +HEADERS += ../../framelessquickhelper.h +SOURCES += ../../framelessquickhelper.cpp main.cpp RESOURCES += qml.qrc include($$PWD/../common.pri) diff --git a/examples/Win32Demo/widget.cpp b/examples/Win32Demo/widget.cpp index a3ff285..5c4e635 100644 --- a/examples/Win32Demo/widget.cpp +++ b/examples/Win32Demo/widget.cpp @@ -138,6 +138,7 @@ const QLatin1String g_sCloseButtonImageLight(":/images/button_close_white.svg"); Widget::Widget(QWidget *parent) : QWidget(parent) { + createWinId(); // Internal function initializeWindow(); } @@ -373,7 +374,7 @@ bool Widget::eventFilter(QObject *object, QEvent *event) break; } case QEvent::WinIdChange: - WinNativeEventFilter::addFramelessWindow(this); + WinNativeEventFilter::addFramelessWindow(rawHandle()); break; case QEvent::WindowActivate: case QEvent::WindowDeactivate: @@ -400,9 +401,7 @@ bool Widget::nativeEvent(const QByteArray &eventType, void *message, long *resul switch (msg->message) { case WM_NCRBUTTONUP: { if (msg->wParam == HTCAPTION) { - const int x = GET_X_LPARAM(msg->lParam); - const int y = GET_Y_LPARAM(msg->lParam); - if (WinNativeEventFilter::displaySystemMenu(msg->hwnd, false, x, y)) { + if (WinNativeEventFilter::displaySystemMenu(msg->hwnd)) { *result = 0; return true; } @@ -581,6 +580,15 @@ void Widget::setupConnections() QColorDialog::ShowAlphaChannel); } } + // Qt will paint a solid white background to the window, + // it will cover the blurred effect, so we need to + // make the background become totally transparent. Achieve + // this by setting a palette to the window. + QPalette palette = {}; + if (enable) { + palette.setColor(QPalette::Window, Qt::transparent); + } + setPalette(palette); WinNativeEventFilter::setBlurEffectEnabled(rawHandle(), enable, color); updateWindow(); if (useAcrylicEffect && enable && WinNativeEventFilter::isTransparencyEffectEnabled()) { @@ -621,7 +629,7 @@ void Widget::initializeFramelessFunctions() { WinNativeEventFilter::WINDOWDATA data = {}; data.ignoreObjects << iconButton << minimizeButton << maximizeButton << closeButton; - WinNativeEventFilter::addFramelessWindow(this, &data); + WinNativeEventFilter::addFramelessWindow(rawHandle(), &data); installEventFilter(this); } diff --git a/examples/common.pri b/examples/common.pri index 1319968..2c5fda7 100644 --- a/examples/common.pri +++ b/examples/common.pri @@ -14,10 +14,9 @@ win32 { RC_FILE = $$PWD/windows.rc OTHER_FILES += $$PWD/windows.manifest } -CONFIG(debug, debug|release) { - LIBS += -L$$OUT_PWD/../../debug - win32: LIBS += -lFramelessHelperd - else: unix: LIBS += -lFramelessHelper_debug -} else: CONFIG(release, debug|release) { - LIBS += -L$$OUT_PWD/../../release -lFramelessHelper +win32 { + CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../debug -lFramelessHelperd + else: CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../release -lFramelessHelper +} else: unix { + LIBS += -L$$OUT_PWD/../../bin -lFramelessHelper } diff --git a/framelesshelper.cpp b/framelesshelper.cpp index c94703e..b85bbfc 100644 --- a/framelesshelper.cpp +++ b/framelesshelper.cpp @@ -407,29 +407,31 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) if (!obj) { continue; } -#ifdef QT_WIDGETS_LIB - const auto widget = qobject_cast(obj); - if (widget) { -#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) - const QPointF pos = widget->mapToGlobal(QPointF{0, 0}); -#else - const QPoint pos = widget->mapToGlobal(QPoint{0, 0}); -#endif - if (QRectF(pos.x(), pos.y(), widget->width(), widget->height()).contains(mousePos)) { - return true; - } + const bool isWidget = obj->inherits("QWidget"); + const bool isQuickItem = obj->inherits("QQuickItem"); + if (!isWidget && !isQuickItem) { + qWarning() << obj << "is not a QWidget or QQuickItem!"; + continue; } -#endif -#ifdef QT_QUICK_LIB - const auto quickItem = qobject_cast(obj); - if (quickItem) { - const QPointF pos = quickItem->mapToGlobal({0, 0}); - if (QRectF(pos.x(), pos.y(), quickItem->width(), quickItem->height()) - .contains(mousePos)) { - return true; + const auto mapOriginPointToWindow = [](const QObject *obj) -> QPointF { + Q_ASSERT(obj); + QPointF point = {obj->property("x").toReal(), obj->property("y").toReal()}; + for (QObject *parent = obj->parent(); parent; parent = parent->parent()) { + point += {parent->property("x").toReal(), + parent->property("y").toReal()}; } + return point; + }; + const QPointF originPoint = mapOriginPointToWindow(obj); + const qreal width = obj->property("width").toReal(); + const qreal height = obj->property("height").toReal(); + if (QRectF(originPoint.x(), + originPoint.y(), + width, + height) + .contains(mousePos)) { + return true; } -#endif } return false; }; @@ -441,13 +443,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) const auto isInIgnoreObjects = [this, &isInSpecificObjects](const QPointF &point, QObject *window) -> bool { Q_ASSERT(window); -#if defined(QT_WIDGETS_LIB) || defined(QT_QUICK_LIB) return isInSpecificObjects(point, getIgnoreObjects(window)); -#else - Q_UNUSED(point) - Q_UNUSED(window) - return false; -#endif }; const auto isInDraggableAreas = [this, &isInSpecificAreas](const QPointF &point, QObject *window) -> bool { @@ -458,14 +454,8 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) const auto isInDraggableObjects = [this, &isInSpecificObjects](const QPointF &point, QObject *window) -> bool { Q_ASSERT(window); -#if defined(QT_WIDGETS_LIB) || defined(QT_QUICK_LIB) const auto objs = getDraggableObjects(window); return (objs.isEmpty() ? true : isInSpecificObjects(point, objs)); -#else - Q_UNUSED(point) - Q_UNUSED(window) - return true; -#endif }; const auto isResizePermitted = [&isInIgnoreAreas, &isInIgnoreObjects](const QPointF &globalPoint, const QPointF &point, diff --git a/framelessquickhelper.cpp b/framelessquickhelper.cpp index 54cbed6..8c38008 100644 --- a/framelessquickhelper.cpp +++ b/framelessquickhelper.cpp @@ -31,15 +31,34 @@ #include #endif -#ifdef Q_OS_WINDOWS namespace { +#ifdef Q_OS_WINDOWS const char g_sPreserveWindowFrame[] = "WNEF_FORCE_PRESERVE_WINDOW_FRAME"; const char g_sDontExtendFrame[] = "WNEF_DO_NOT_EXTEND_FRAME"; const char g_sForceUseAcrylicEffect[] = "WNEF_FORCE_ACRYLIC_ON_WIN10"; +#endif + +FramelessWindowsManager::WindowId getWindowId(QObject *object) +{ + Q_ASSERT(object); + if (!object->isWindowType()) { + qWarning() << object << "is not a window!"; + return nullptr; + } + const auto window = qobject_cast(object); + if (!window) { + qWarning() << "Failed to convert" << object << "to QWindow!"; + return nullptr; + } +#ifdef Q_OS_WINDOWS + return reinterpret_cast(window->winId()); +#else + return static_cast(window); +#endif +} } // namespace -#endif FramelessQuickHelper::FramelessQuickHelper(QQuickItem *parent) : QQuickItem(parent) { @@ -50,56 +69,56 @@ FramelessQuickHelper::FramelessQuickHelper(QQuickItem *parent) : QQuickItem(pare int FramelessQuickHelper::borderWidth() const { - return FramelessWindowsManager::getBorderWidth(window()); + return FramelessWindowsManager::getBorderWidth(getWindowId(window())); } void FramelessQuickHelper::setBorderWidth(const int val) { - FramelessWindowsManager::setBorderWidth(window(), val); + FramelessWindowsManager::setBorderWidth(getWindowId(window()), val); Q_EMIT borderWidthChanged(val); } int FramelessQuickHelper::borderHeight() const { - return FramelessWindowsManager::getBorderHeight(window()); + return FramelessWindowsManager::getBorderHeight(getWindowId(window())); } void FramelessQuickHelper::setBorderHeight(const int val) { - FramelessWindowsManager::setBorderHeight(window(), val); + FramelessWindowsManager::setBorderHeight(getWindowId(window()), val); Q_EMIT borderHeightChanged(val); } int FramelessQuickHelper::titleBarHeight() const { - return FramelessWindowsManager::getTitleBarHeight(window()); + return FramelessWindowsManager::getTitleBarHeight(getWindowId(window())); } void FramelessQuickHelper::setTitleBarHeight(const int val) { - FramelessWindowsManager::setTitleBarHeight(window(), val); + FramelessWindowsManager::setTitleBarHeight(getWindowId(window()), val); Q_EMIT titleBarHeightChanged(val); } bool FramelessQuickHelper::resizable() const { - return FramelessWindowsManager::getResizable(window()); + return FramelessWindowsManager::getResizable(getWindowId(window())); } void FramelessQuickHelper::setResizable(const bool val) { - FramelessWindowsManager::setResizable(window(), val); + FramelessWindowsManager::setResizable(getWindowId(window()), val); Q_EMIT resizableChanged(val); } bool FramelessQuickHelper::titleBarEnabled() const { - return FramelessWindowsManager::getTitleBarEnabled(window()); + return FramelessWindowsManager::getTitleBarEnabled(getWindowId(window())); } void FramelessQuickHelper::setTitleBarEnabled(const bool val) { - FramelessWindowsManager::setTitleBarEnabled(window(), val); + FramelessWindowsManager::setTitleBarEnabled(getWindowId(window()), val); Q_EMIT titleBarEnabledChanged(val); } @@ -136,7 +155,7 @@ bool FramelessQuickHelper::highContrastModeEnabled() const bool FramelessQuickHelper::darkFrameEnabled() const { - return WinNativeEventFilter::isDarkFrameEnabled(rawHandle()); + return WinNativeEventFilter::isDarkFrameEnabled(rawWindowHandle()); } bool FramelessQuickHelper::transparencyEffectEnabled() const @@ -147,71 +166,56 @@ bool FramelessQuickHelper::transparencyEffectEnabled() const QSize FramelessQuickHelper::minimumSize() const { - return FramelessWindowsManager::getMinimumSize(window()); + return FramelessWindowsManager::getMinimumSize(getWindowId(window())); } void FramelessQuickHelper::setMinimumSize(const QSize &val) { - FramelessWindowsManager::setMinimumSize(window(), val); + FramelessWindowsManager::setMinimumSize(getWindowId(window()), val); Q_EMIT minimumSizeChanged(val); } QSize FramelessQuickHelper::maximumSize() const { - return FramelessWindowsManager::getMaximumSize(window()); + return FramelessWindowsManager::getMaximumSize(getWindowId(window())); } void FramelessQuickHelper::setMaximumSize(const QSize &val) { - FramelessWindowsManager::setMaximumSize(window(), val); + FramelessWindowsManager::setMaximumSize(getWindowId(window()), val); Q_EMIT maximumSizeChanged(val); } void FramelessQuickHelper::removeWindowFrame(const bool center) { - FramelessWindowsManager::addWindow(window(), center); + FramelessWindowsManager::addWindow(getWindowId(window()), center); } -QSize FramelessQuickHelper::desktopSize() const +void FramelessQuickHelper::moveWindowToDesktopCenter() { - return FramelessWindowsManager::getDesktopSize(window()); -} - -QRect FramelessQuickHelper::desktopAvailableGeometry() const -{ - return FramelessWindowsManager::getDesktopAvailableGeometry(window()); -} - -QSize FramelessQuickHelper::desktopAvailableSize() const -{ - return FramelessWindowsManager::getDesktopAvailableSize(window()); -} - -void FramelessQuickHelper::moveWindowToDesktopCenter(const bool realCenter) -{ - FramelessWindowsManager::moveWindowToDesktopCenter(window(), realCenter); + FramelessWindowsManager::moveWindowToDesktopCenter(getWindowId(window())); } void FramelessQuickHelper::addIgnoreArea(const QRect &val) { - FramelessWindowsManager::addIgnoreArea(window(), val); + FramelessWindowsManager::addIgnoreArea(getWindowId(window()), val); } void FramelessQuickHelper::addDraggableArea(const QRect &val) { - FramelessWindowsManager::addDraggableArea(window(), val); + FramelessWindowsManager::addDraggableArea(getWindowId(window()), val); } void FramelessQuickHelper::addIgnoreObject(QQuickItem *val) { Q_ASSERT(val); - FramelessWindowsManager::addIgnoreObject(window(), val); + FramelessWindowsManager::addIgnoreObject(getWindowId(window()), val); } void FramelessQuickHelper::addDraggableObject(QQuickItem *val) { Q_ASSERT(val); - FramelessWindowsManager::addDraggableObject(window(), val); + FramelessWindowsManager::addDraggableObject(getWindowId(window()), val); } #ifdef Q_OS_WINDOWS @@ -227,9 +231,9 @@ void FramelessQuickHelper::timerEvent(QTimerEvent *event) Q_EMIT transparencyEffectEnabledChanged(transparencyEffectEnabled()); } -void *FramelessQuickHelper::rawHandle() const +void *FramelessQuickHelper::rawWindowHandle() const { - QWindow *win = window(); + const QWindow *win = window(); if (win) { return reinterpret_cast(win->winId()); } @@ -247,9 +251,9 @@ void FramelessQuickHelper::setWindowFrameVisible(const bool value) } } -void FramelessQuickHelper::displaySystemMenu(const int x, const int y, const bool isRtl) +void FramelessQuickHelper::displaySystemMenu(const QPointF &pos) { - WinNativeEventFilter::displaySystemMenu(rawHandle(), isRtl, x, y); + WinNativeEventFilter::displaySystemMenu(rawWindowHandle(), pos); } void FramelessQuickHelper::setBlurEffectEnabled(const bool enabled, @@ -261,6 +265,6 @@ void FramelessQuickHelper::setBlurEffectEnabled(const bool enabled, } else { qunsetenv(g_sForceUseAcrylicEffect); } - WinNativeEventFilter::setBlurEffectEnabled(rawHandle(), enabled, gradientColor); + WinNativeEventFilter::setBlurEffectEnabled(rawWindowHandle(), enabled, gradientColor); } #endif diff --git a/framelessquickhelper.h b/framelessquickhelper.h index d8576eb..d3b6567 100644 --- a/framelessquickhelper.h +++ b/framelessquickhelper.h @@ -24,7 +24,6 @@ #pragma once -#include "framelesshelper_global.h" #include #if (defined(Q_OS_WIN) || defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINRT)) \ @@ -42,7 +41,7 @@ Q_DISABLE_MOVE(Class) #endif -class FRAMELESSHELPER_EXPORT FramelessQuickHelper : public QQuickItem +class FramelessQuickHelper : public QQuickItem { Q_OBJECT Q_DISABLE_COPY_MOVE(FramelessQuickHelper) @@ -110,11 +109,7 @@ public: public Q_SLOTS: void removeWindowFrame(const bool center = false); - void moveWindowToDesktopCenter(const bool realCenter = true); - - QSize desktopSize() const; - QRect desktopAvailableGeometry() const; - QSize desktopAvailableSize() const; + void moveWindowToDesktopCenter(); void addIgnoreArea(const QRect &val); void addDraggableArea(const QRect &val); @@ -124,7 +119,7 @@ public Q_SLOTS: #ifdef Q_OS_WINDOWS void setWindowFrameVisible(const bool value = true); - void displaySystemMenu(const int x, const int y, const bool isRtl = false); + void displaySystemMenu(const QPointF &pos = {}); void setBlurEffectEnabled(const bool enabled = true, const bool forceAcrylic = false, const QColor &gradientColor = Qt::white); @@ -135,7 +130,7 @@ protected: void timerEvent(QTimerEvent *event) override; private: - void *rawHandle() const; + void *rawWindowHandle() const; #endif Q_SIGNALS: diff --git a/framelesswindowsmanager.cpp b/framelesswindowsmanager.cpp index 3f47746..b1270d9 100644 --- a/framelesswindowsmanager.cpp +++ b/framelesswindowsmanager.cpp @@ -24,16 +24,9 @@ #include "framelesswindowsmanager.h" +#ifndef Q_OS_WINDOWS #include -#include #include -#ifdef QT_WIDGETS_LIB -#include -#endif - -#if (defined(Q_OS_WIN) || defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINRT)) \ - && !defined(Q_OS_WINDOWS) -#define Q_OS_WINDOWS #endif #ifdef Q_OS_WINDOWS @@ -42,70 +35,30 @@ #include "framelesshelper.h" #endif +#ifndef Q_OS_WINDOWS namespace { -void reportError() +QWindow *toWindow(QObject *object) { - qFatal("Only top level QWidgets and QWindows are accepted."); + Q_ASSERT(object); + return object->isWindowType() ? qobject_cast(object) : nullptr; } -QScreen *getCurrentScreenFromWindow(QObject *window) -{ - Q_ASSERT(window); - if (window->isWindowType()) { - return qobject_cast(window)->screen(); - } -#ifdef QT_WIDGETS_LIB - else if (window->isWidgetType()) { -#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) - return qobject_cast(window)->screen(); -#else - QWindow *win = qobject_cast(window)->windowHandle(); - return win ? win->screen() : nullptr; -#endif - } -#endif - else { - reportError(); - } - return nullptr; -} - -#ifdef Q_OS_WINDOWS -void *getRawHandleFromWindow(QObject *window) -{ - Q_ASSERT(window); - if (window->isWindowType()) { - return reinterpret_cast(qobject_cast(window)->winId()); - } -#ifdef QT_WIDGETS_LIB - else if (window->isWidgetType()) { - return reinterpret_cast(qobject_cast(window)->winId()); - } -#endif - else { - reportError(); - } - return nullptr; -} -#endif - -#ifndef Q_OS_WINDOWS using FLWM_CORE_DATA = struct _FLWM_CORE_DATA { FramelessHelper framelessHelper; }; -#endif } // namespace +#endif #ifndef Q_OS_WINDOWS Q_GLOBAL_STATIC(FLWM_CORE_DATA, coreData) #endif -FramelessWindowsManager::FramelessWindowsManager() {} +FramelessWindowsManager::FramelessWindowsManager() = default; -void FramelessWindowsManager::addWindow(QObject *window, const bool center) +void FramelessWindowsManager::addWindow(WindowId window, const bool center) { Q_ASSERT(window); #ifdef Q_OS_WINDOWS @@ -118,86 +71,17 @@ void FramelessWindowsManager::addWindow(QObject *window, const bool center) } } -void FramelessWindowsManager::moveWindowToDesktopCenter(QObject *window, const bool realCenter) +void FramelessWindowsManager::moveWindowToDesktopCenter(WindowId window) { Q_ASSERT(window); - if (realCenter) { #ifdef Q_OS_WINDOWS - WinNativeEventFilter::moveWindowToDesktopCenter(getRawHandleFromWindow(window)); + WinNativeEventFilter::moveWindowToDesktopCenter(window); #else - FramelessHelper::moveWindowToDesktopCenter(window); + FramelessHelper::moveWindowToDesktopCenter(window); #endif - } else { - QSize windowSize = {}, screenSize = {}; - QRect screenGeometry = {}; - if (window->isWindowType()) { - const auto win = qobject_cast(window); - if (win) { - windowSize = win->size(); - screenSize = getDesktopAvailableSize(win); - screenGeometry = getDesktopAvailableGeometry(win); - } - } -#ifdef QT_WIDGETS_LIB - else if (window->isWidgetType()) { - const auto widget = qobject_cast(window); - if (widget && widget->isTopLevel()) { - windowSize = widget->size(); - screenSize = getDesktopAvailableSize(widget); - screenGeometry = getDesktopAvailableGeometry(widget); - } - } -#endif - else { - reportError(); - } - const int newX = qRound(static_cast(screenSize.width() - windowSize.width()) / 2.0); - const int newY = qRound(static_cast(screenSize.height() - windowSize.height()) / 2.0); - const int x = newX + screenGeometry.x(); - const int y = newY + screenGeometry.y(); - if (window->isWindowType()) { - const auto win = qobject_cast(window); - if (win) { - win->setX(x); - win->setY(y); - } - } -#ifdef QT_WIDGETS_LIB - else if (window->isWidgetType()) { - const auto widget = qobject_cast(window); - if (widget && widget->isTopLevel()) { - widget->move(x, y); - } - } -#endif - else { - reportError(); - } - } } -QSize FramelessWindowsManager::getDesktopSize(QObject *window) -{ - const QScreen *screen = window ? getCurrentScreenFromWindow(window) - : QGuiApplication::primaryScreen(); - return screen ? screen->size() : QSize(); -} - -QRect FramelessWindowsManager::getDesktopAvailableGeometry(QObject *window) -{ - const QScreen *screen = window ? getCurrentScreenFromWindow(window) - : QGuiApplication::primaryScreen(); - return screen ? screen->availableGeometry() : QRect(); -} - -QSize FramelessWindowsManager::getDesktopAvailableSize(QObject *window) -{ - const QScreen *screen = window ? getCurrentScreenFromWindow(window) - : QGuiApplication::primaryScreen(); - return screen ? screen->availableSize() : QSize(); -} - -void FramelessWindowsManager::addIgnoreArea(QObject *window, const QRect &area) +void FramelessWindowsManager::addIgnoreArea(WindowId window, const QRect &area) { Q_ASSERT(window); #ifdef Q_OS_WINDOWS @@ -210,7 +94,7 @@ void FramelessWindowsManager::addIgnoreArea(QObject *window, const QRect &area) #endif } -void FramelessWindowsManager::addDraggableArea(QObject *window, const QRect &area) +void FramelessWindowsManager::addDraggableArea(WindowId window, const QRect &area) { Q_ASSERT(window); #ifdef Q_OS_WINDOWS @@ -223,7 +107,7 @@ void FramelessWindowsManager::addDraggableArea(QObject *window, const QRect &are #endif } -void FramelessWindowsManager::addIgnoreObject(QObject *window, QObject *object) +void FramelessWindowsManager::addIgnoreObject(WindowId window, QObject *object) { Q_ASSERT(window); #ifdef Q_OS_WINDOWS @@ -236,7 +120,7 @@ void FramelessWindowsManager::addIgnoreObject(QObject *window, QObject *object) #endif } -void FramelessWindowsManager::addDraggableObject(QObject *window, QObject *object) +void FramelessWindowsManager::addDraggableObject(WindowId window, QObject *object) { Q_ASSERT(window); #ifdef Q_OS_WINDOWS @@ -249,11 +133,11 @@ void FramelessWindowsManager::addDraggableObject(QObject *window, QObject *objec #endif } -int FramelessWindowsManager::getBorderWidth(QObject *window) +int FramelessWindowsManager::getBorderWidth(WindowId window) { #ifdef Q_OS_WINDOWS Q_ASSERT(window); - return WinNativeEventFilter::getSystemMetric(getRawHandleFromWindow(window), + return WinNativeEventFilter::getSystemMetric(window, WinNativeEventFilter::SystemMetric::BorderWidth); #else Q_UNUSED(window) @@ -261,7 +145,7 @@ int FramelessWindowsManager::getBorderWidth(QObject *window) #endif } -void FramelessWindowsManager::setBorderWidth(QObject *window, const int value) +void FramelessWindowsManager::setBorderWidth(WindowId window, const int value) { #ifdef Q_OS_WINDOWS Q_ASSERT(window); @@ -275,11 +159,11 @@ void FramelessWindowsManager::setBorderWidth(QObject *window, const int value) #endif } -int FramelessWindowsManager::getBorderHeight(QObject *window) +int FramelessWindowsManager::getBorderHeight(WindowId window) { #ifdef Q_OS_WINDOWS Q_ASSERT(window); - return WinNativeEventFilter::getSystemMetric(getRawHandleFromWindow(window), + return WinNativeEventFilter::getSystemMetric(window, WinNativeEventFilter::SystemMetric::BorderHeight); #else Q_UNUSED(window) @@ -287,7 +171,7 @@ int FramelessWindowsManager::getBorderHeight(QObject *window) #endif } -void FramelessWindowsManager::setBorderHeight(QObject *window, const int value) +void FramelessWindowsManager::setBorderHeight(WindowId window, const int value) { #ifdef Q_OS_WINDOWS Q_ASSERT(window); @@ -301,11 +185,11 @@ void FramelessWindowsManager::setBorderHeight(QObject *window, const int value) #endif } -int FramelessWindowsManager::getTitleBarHeight(QObject *window) +int FramelessWindowsManager::getTitleBarHeight(WindowId window) { #ifdef Q_OS_WINDOWS Q_ASSERT(window); - return WinNativeEventFilter::getSystemMetric(getRawHandleFromWindow(window), + return WinNativeEventFilter::getSystemMetric(window, WinNativeEventFilter::SystemMetric::TitleBarHeight); #else Q_UNUSED(window) @@ -313,7 +197,7 @@ int FramelessWindowsManager::getTitleBarHeight(QObject *window) #endif } -void FramelessWindowsManager::setTitleBarHeight(QObject *window, const int value) +void FramelessWindowsManager::setTitleBarHeight(WindowId window, const int value) { #ifdef Q_OS_WINDOWS Q_ASSERT(window); @@ -327,7 +211,7 @@ void FramelessWindowsManager::setTitleBarHeight(QObject *window, const int value #endif } -bool FramelessWindowsManager::getResizable(QObject *window) +bool FramelessWindowsManager::getResizable(WindowId window) { Q_ASSERT(window); #ifdef Q_OS_WINDOWS @@ -338,39 +222,29 @@ bool FramelessWindowsManager::getResizable(QObject *window) #endif } -void FramelessWindowsManager::setResizable(QObject *window, const bool value) +void FramelessWindowsManager::setResizable(WindowId window, const bool value) { Q_ASSERT(window); #ifdef Q_OS_WINDOWS - WinNativeEventFilter::setWindowResizable(getRawHandleFromWindow(window), value); + WinNativeEventFilter::setWindowResizable(window, value); #else coreData()->framelessHelper.setResizable(window, value); #endif } -QSize FramelessWindowsManager::getMinimumSize(QObject *window) +QSize FramelessWindowsManager::getMinimumSize(WindowId window) { Q_ASSERT(window); #ifdef Q_OS_WINDOWS const auto data = WinNativeEventFilter::getWindowData(window); return data ? data->minimumSize : QSize(); #else - if (window->isWindowType()) { - return qobject_cast(window)->minimumSize(); - } -#ifdef QT_WIDGETS_LIB - else if (window->isWidgetType()) { - return qobject_cast(window)->minimumSize(); - } -#endif - else { - reportError(); - } - return {}; + const auto win = toWindow(window); + return win ? win->minimumSize() : QSize(); #endif } -void FramelessWindowsManager::setMinimumSize(QObject *window, const QSize &value) +void FramelessWindowsManager::setMinimumSize(WindowId window, const QSize &value) { Q_ASSERT(window); #ifdef Q_OS_WINDOWS @@ -379,43 +253,26 @@ void FramelessWindowsManager::setMinimumSize(QObject *window, const QSize &value data->minimumSize = value; } #else - if (window->isWindowType()) { - qobject_cast(window)->setMinimumSize(value); - } -#ifdef QT_WIDGETS_LIB - else if (window->isWidgetType()) { - qobject_cast(window)->setMinimumSize(value); - } -#endif - else { - reportError(); + const auto win = toWindow(window); + if (win) { + win->setMinimumSize(value); } #endif } -QSize FramelessWindowsManager::getMaximumSize(QObject *window) +QSize FramelessWindowsManager::getMaximumSize(WindowId window) { Q_ASSERT(window); #ifdef Q_OS_WINDOWS const auto data = WinNativeEventFilter::getWindowData(window); return data ? data->maximumSize : QSize(); #else - if (window->isWindowType()) { - return qobject_cast(window)->maximumSize(); - } -#ifdef QT_WIDGETS_LIB - else if (window->isWidgetType()) { - return qobject_cast(window)->maximumSize(); - } -#endif - else { - reportError(); - } - return {}; + const auto win = toWindow(window); + return win ? win->maximumSize() : QSize(); #endif } -void FramelessWindowsManager::setMaximumSize(QObject *window, const QSize &value) +void FramelessWindowsManager::setMaximumSize(WindowId window, const QSize &value) { Q_ASSERT(window); #ifdef Q_OS_WINDOWS @@ -424,21 +281,14 @@ void FramelessWindowsManager::setMaximumSize(QObject *window, const QSize &value data->maximumSize = value; } #else - if (window->isWindowType()) { - qobject_cast(window)->setMaximumSize(value); - } -#ifdef QT_WIDGETS_LIB - else if (window->isWidgetType()) { - qobject_cast(window)->setMaximumSize(value); - } -#endif - else { - reportError(); + const auto win = toWindow(window); + if (win) { + win->setMaximumSize(value); } #endif } -bool FramelessWindowsManager::getTitleBarEnabled(QObject *window) +bool FramelessWindowsManager::getTitleBarEnabled(WindowId window) { Q_ASSERT(window); #ifdef Q_OS_WINDOWS @@ -449,7 +299,7 @@ bool FramelessWindowsManager::getTitleBarEnabled(QObject *window) #endif } -void FramelessWindowsManager::setTitleBarEnabled(QObject *window, const bool value) +void FramelessWindowsManager::setTitleBarEnabled(WindowId window, const bool value) { Q_ASSERT(window); #ifdef Q_OS_WINDOWS diff --git a/framelesswindowsmanager.h b/framelesswindowsmanager.h index 83a4d02..39fcf17 100644 --- a/framelesswindowsmanager.h +++ b/framelesswindowsmanager.h @@ -27,6 +27,11 @@ #include "framelesshelper_global.h" #include +#if (defined(Q_OS_WIN) || defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINRT)) \ + && !defined(Q_OS_WINDOWS) +#define Q_OS_WINDOWS +#endif + QT_BEGIN_NAMESPACE QT_FORWARD_DECLARE_CLASS(QObject) QT_END_NAMESPACE @@ -46,41 +51,45 @@ class FRAMELESSHELPER_EXPORT FramelessWindowsManager Q_DISABLE_COPY_MOVE(FramelessWindowsManager) public: + using WindowId = +#ifdef Q_OS_WINDOWS + void * +#else + QObject * +#endif + ; + explicit FramelessWindowsManager(); ~FramelessWindowsManager() = default; - static void addWindow(QObject *window, const bool center = false); + static void addWindow(WindowId window, const bool center = false); - static void moveWindowToDesktopCenter(QObject *window, const bool realCenter = true); + static void moveWindowToDesktopCenter(WindowId window); - static QSize getDesktopSize(QObject *window = nullptr); - static QRect getDesktopAvailableGeometry(QObject *window = nullptr); - static QSize getDesktopAvailableSize(QObject *window = nullptr); + static void addIgnoreArea(WindowId window, const QRect &area); + static void addDraggableArea(WindowId window, const QRect &area); - static void addIgnoreArea(QObject *window, const QRect &area); - static void addDraggableArea(QObject *window, const QRect &area); + static void addIgnoreObject(WindowId window, QObject *object); + static void addDraggableObject(WindowId window, QObject *object); - static void addIgnoreObject(QObject *window, QObject *object); - static void addDraggableObject(QObject *window, QObject *object); + static int getBorderWidth(WindowId window); + static void setBorderWidth(WindowId window, const int value); - static int getBorderWidth(QObject *window); - static void setBorderWidth(QObject *window, const int value); + static int getBorderHeight(WindowId window); + static void setBorderHeight(WindowId window, const int value); - static int getBorderHeight(QObject *window); - static void setBorderHeight(QObject *window, const int value); + static int getTitleBarHeight(WindowId window); + static void setTitleBarHeight(WindowId window, const int value); - static int getTitleBarHeight(QObject *window); - static void setTitleBarHeight(QObject *window, const int value); + static bool getResizable(WindowId window); + static void setResizable(WindowId window, const bool value = true); - static bool getResizable(QObject *window); - static void setResizable(QObject *window, const bool value = true); + static QSize getMinimumSize(WindowId window); + static void setMinimumSize(WindowId window, const QSize &value); - static QSize getMinimumSize(QObject *window); - static void setMinimumSize(QObject *window, const QSize &value); + static QSize getMaximumSize(WindowId window); + static void setMaximumSize(WindowId window, const QSize &value); - static QSize getMaximumSize(QObject *window); - static void setMaximumSize(QObject *window, const QSize &value); - - static bool getTitleBarEnabled(QObject *window); - static void setTitleBarEnabled(QObject *window, const bool value = true); + static bool getTitleBarEnabled(WindowId window); + static void setTitleBarEnabled(WindowId window, const bool value = true); }; diff --git a/lib.pro b/lib.pro index d2dd0db..662a21c 100644 --- a/lib.pro +++ b/lib.pro @@ -3,8 +3,10 @@ TEMPLATE = lib win32: DLLDESTDIR = $$OUT_PWD/bin else: unix: DESTDIR = $$OUT_PWD/bin QT += gui-private -qtHaveModule(widgets): QT += widgets -qtHaveModule(quick): QT += quick +unix { + qtHaveModule(widgets): QT += widgets + qtHaveModule(quick): QT += quick +} CONFIG += c++17 strict_c++ utf8_source warn_on DEFINES += \ QT_NO_CAST_FROM_ASCII \ @@ -14,10 +16,6 @@ HEADERS += \ framelesshelper_global.h \ framelesswindowsmanager.h SOURCES += framelesswindowsmanager.cpp -qtHaveModule(quick) { - HEADERS += framelessquickhelper.h - SOURCES += framelessquickhelper.cpp -} win32 { DEFINES += WIN32_LEAN_AND_MEAN _CRT_SECURE_NO_WARNINGS CONFIG += LINK_TO_SYSTEM_DLL diff --git a/winnativeeventfilter.cpp b/winnativeeventfilter.cpp index 7ec4252..58e09a9 100644 --- a/winnativeeventfilter.cpp +++ b/winnativeeventfilter.cpp @@ -46,12 +46,6 @@ #else #include #endif -#ifdef QT_QUICK_LIB -#include -#endif -#ifdef QT_WIDGETS_LIB -#include -#endif #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) #include #else @@ -1115,25 +1109,6 @@ void qCoreAppFixup() } } -HWND getHWNDFromQObject(QObject *object) -{ - Q_ASSERT(object); - WId wid = 0; - if (object->isWindowType()) { - wid = qobject_cast(object)->winId(); - } -#ifdef QT_WIDGETS_LIB - else if (object->isWidgetType()) { - wid = qobject_cast(object)->winId(); - } -#endif - else { - qFatal( - "Can't acquire the window handle: only top level QWidgets and QWindows are accepted."); - } - return reinterpret_cast(wid); -} - void updateQtFrame_internal(const HWND handle, const bool resetToDefault = false) { Q_ASSERT(handle); @@ -1149,21 +1124,17 @@ void updateQtFrame_internal(const HWND handle, const bool resetToDefault = false } } -bool displaySystemMenu_internal(const HWND handle, const bool isRtl, const LPARAM lParam) +bool displaySystemMenu_internal(const HWND handle, const LPARAM lParam) { Q_ASSERT(handle); if (WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) { - const POINT globalMouse{GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; - POINT localMouse = globalMouse; + POINT localMouse = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; WNEF_EXECUTE_WINAPI(ScreenToClient, handle, &localMouse) const int tbh = WinNativeEventFilter::getSystemMetric( handle, WinNativeEventFilter::SystemMetric::TitleBarHeight, true); const bool isTitleBar = localMouse.y <= tbh; if (isTitleBar && !IsFullScreen(handle)) { - return WinNativeEventFilter::displaySystemMenu(handle, - isRtl, - globalMouse.x, - globalMouse.y); + return WinNativeEventFilter::displaySystemMenu(handle); } } return false; @@ -1256,18 +1227,6 @@ void WinNativeEventFilter::addFramelessWindow(void *window, } } -void WinNativeEventFilter::addFramelessWindow(QObject *window, - const WINDOWDATA *data, - const bool center, - const int x, - const int y, - const int width, - const int height) -{ - Q_ASSERT(window); - addFramelessWindow(getHWNDFromQObject(window), data, center, x, y, width, height); -} - void WinNativeEventFilter::removeFramelessWindow(void *window) { Q_ASSERT(window); @@ -1282,12 +1241,6 @@ void WinNativeEventFilter::removeFramelessWindow(void *window) updateWindow(window, true, false); } -void WinNativeEventFilter::removeFramelessWindow(QObject *window) -{ - Q_ASSERT(window); - removeFramelessWindow(getHWNDFromQObject(window)); -} - #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, @@ -1775,6 +1728,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, *result = HTTRANSPARENT; return true; } + const auto isInSpecificAreas = [](const QPointF &mousePos, const QList &areas, const qreal dpr) -> bool { if (areas.isEmpty()) { @@ -1794,7 +1748,6 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, } return false; }; -#if defined(QT_WIDGETS_LIB) || defined(QT_QUICK_LIB) const auto isInSpecificObjects = [](const QPointF &mousePos, const QList &objects, const qreal dpr) -> bool { @@ -1805,40 +1758,34 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, if (!object) { continue; } -#ifdef QT_WIDGETS_LIB - const auto widget = qobject_cast(object); - if (widget) { -#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) - const QPointF pos = widget->mapToGlobal(QPointF{0, 0}); -#else - const QPoint pos = widget->mapToGlobal(QPoint{0, 0}); -#endif - if (QRectF(pos.x() * dpr, - pos.y() * dpr, - widget->width() * dpr, - widget->height() * dpr) - .contains(mousePos)) { - return true; - } + const bool isWidget = object->inherits("QWidget"); + const bool isQuickItem = object->inherits("QQuickItem"); + if (!isWidget && !isQuickItem) { + qWarning() << object << "is not a QWidget or QQuickItem!"; + continue; } -#endif -#ifdef QT_QUICK_LIB - const auto quickItem = qobject_cast(object); - if (quickItem) { - const QPointF pos = quickItem->mapToGlobal(QPointF{0, 0}); - if (QRectF(pos.x() * dpr, - pos.y() * dpr, - quickItem->width() * dpr, - quickItem->height() * dpr) - .contains(mousePos)) { - return true; + const auto mapOriginPointToWindow = [](const QObject *obj) -> QPointF { + Q_ASSERT(obj); + QPointF point = {obj->property("x").toReal(), obj->property("y").toReal()}; + for (QObject *parent = obj->parent(); parent; parent = parent->parent()) { + point += {parent->property("x").toReal(), + parent->property("y").toReal()}; } + return point; + }; + const QPointF originPoint = mapOriginPointToWindow(object); + const qreal width = object->property("width").toReal(); + const qreal height = object->property("height").toReal(); + if (QRectF(originPoint.x() * dpr, + originPoint.y() * dpr, + width * dpr, + height * dpr) + .contains(mousePos)) { + return true; } -#endif } return false; }; -#endif const qreal dpr = GetDevicePixelRatioForWindow(msg->hwnd); const QPointF globalMouse = QCursor::pos() * dpr; POINT winLocalMouse = {qRound(globalMouse.x()), qRound(globalMouse.y())}; @@ -1852,7 +1799,6 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, data->draggableAreas, dpr) : true; -#if defined(QT_WIDGETS_LIB) || defined(QT_QUICK_LIB) const bool isInIgnoreObjects = isInSpecificObjects(globalMouse, data->ignoreObjects, dpr); @@ -1862,14 +1808,6 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, data->draggableObjects, dpr) : true; -#else - // Don't block resizing if both of the Qt Widgets module and Qt - // Quick module are not compiled in, although there's not much - // significance of using this code in this case. - const bool isInIgnoreObjects = false; - const bool isInDraggableObjects = true; - const bool customDragObjects = false; -#endif const bool customDrag = customDragAreas || customDragObjects; const bool isResizePermitted = !isInIgnoreAreas && !isInIgnoreObjects; const int bh = getSystemMetric(msg->hwnd, SystemMetric::BorderHeight, true); @@ -2074,7 +2012,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, // (SHIFT + F10 or the context menu key), lParam will be -1. const LPARAM lParam = (msg->lParam == -1) ? WNEF_EXECUTE_WINAPI_RETURN(GetMessagePos, 0) : msg->lParam; - if (displaySystemMenu_internal(msg->hwnd, false, lParam)) { + if (displaySystemMenu_internal(msg->hwnd, lParam)) { // The WM_CONTEXTMENU message has no return value so there's // no need to modify *result. return true; @@ -2110,12 +2048,6 @@ void WinNativeEventFilter::setWindowData(void *window, const WINDOWDATA *data) } } -void WinNativeEventFilter::setWindowData(QObject *window, const WINDOWDATA *data) -{ - Q_ASSERT(window); - setWindowData(getHWNDFromQObject(window), data); -} - WinNativeEventFilter::WINDOWDATA *WinNativeEventFilter::getWindowData(void *window) { Q_ASSERT(window); @@ -2128,12 +2060,6 @@ WinNativeEventFilter::WINDOWDATA *WinNativeEventFilter::getWindowData(void *wind return nullptr; } -WinNativeEventFilter::WINDOWDATA *WinNativeEventFilter::getWindowData(QObject *window) -{ - Q_ASSERT(window); - return getWindowData(getHWNDFromQObject(window)); -} - void WinNativeEventFilter::setBorderWidth(const int bw) { coreData()->m_borderWidth = bw; @@ -2338,10 +2264,7 @@ void WinNativeEventFilter::updateQtFrame(QWindow *window, const int titleBarHeig } } -bool WinNativeEventFilter::displaySystemMenu(void *handle, - const bool isRtl, - const int x, - const int y) +bool WinNativeEventFilter::displaySystemMenu(void *handle, const QPointF &pos) { Q_ASSERT(handle); const auto hwnd = reinterpret_cast(handle); @@ -2377,15 +2300,20 @@ bool WinNativeEventFilter::displaySystemMenu(void *handle, WNEF_EXECUTE_WINAPI(SetMenuItemInfoW, hMenu, SC_RESTORE, FALSE, &mii) } } + const QPointF mousePos = pos.isNull() + ? QCursor::pos() * GetDevicePixelRatioForWindow(hwnd) + : pos; const LPARAM cmd = WNEF_EXECUTE_WINAPI_RETURN(TrackPopupMenu, 0, hMenu, (TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_TOPALIGN - | (isRtl ? TPM_RIGHTALIGN - : TPM_LEFTALIGN)), - x, - y, + | (QGuiApplication::layoutDirection() + == Qt::RightToLeft + ? TPM_RIGHTALIGN + : TPM_LEFTALIGN)), + qRound(mousePos.x()), + qRound(mousePos.y()), 0, hwnd, nullptr); diff --git a/winnativeeventfilter.h b/winnativeeventfilter.h index f95c1ff..55ed9b6 100644 --- a/winnativeeventfilter.h +++ b/winnativeeventfilter.h @@ -79,26 +79,16 @@ public: const int y = -1, const int width = -1, const int height = -1); - static void addFramelessWindow(QObject *window, - const WINDOWDATA *data = nullptr, - const bool center = false, - const int x = -1, - const int y = -1, - const int width = -1, - const int height = -1); static void removeFramelessWindow(void *window /* HWND */); - static void removeFramelessWindow(QObject *window); // Set borderWidth, borderHeight or titleBarHeight to a negative value to // restore default behavior. // Note that it can only affect one specific window. // If you want to change these values globally, use setBorderWidth instead. static void setWindowData(void *window /* HWND */, const WINDOWDATA *data); - static void setWindowData(QObject *window, const WINDOWDATA *data); // You can modify the given window's data directly, it's the same with using // setWindowData. static WINDOWDATA *getWindowData(void *window /* HWND */); - static WINDOWDATA *getWindowData(QObject *window); // Change settings globally, not a specific window. // These values will be scaled automatically according to DPI, don't scale @@ -135,10 +125,7 @@ public: static void updateQtFrame(QWindow *window, const int titleBarHeight); // Display the system context menu. - static bool displaySystemMenu(void *handle /* HWND */, - const bool isRtl, - const int x, - const int y); + static bool displaySystemMenu(void *handle /* HWND */, const QPointF &pos = {}); // Enable or disable the blur effect for a specific window. // On Win10 it's the Acrylic effect.