diff --git a/CMakeLists.txt b/CMakeLists.txt index 00498be..6871693 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.5) project(FramelessHelper LANGUAGES CXX) diff --git a/framelesshelper.cpp b/framelesshelper.cpp index 7985c97..9c78152 100644 --- a/framelesshelper.cpp +++ b/framelesshelper.cpp @@ -26,6 +26,7 @@ #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) #include "utilities.h" +#include "framelesswindowsmanager.h" #include #include #include @@ -33,65 +34,26 @@ FramelessHelper::FramelessHelper(QObject *parent) : QObject(parent) {} -int FramelessHelper::getBorderWidth() const -{ - return m_borderWidth; -} - -void FramelessHelper::setBorderWidth(const int val) -{ - m_borderWidth = val; -} - -int FramelessHelper::getBorderHeight() const -{ - return m_borderHeight; -} - -void FramelessHelper::setBorderHeight(const int val) -{ - m_borderHeight = val; -} - -int FramelessHelper::getTitleBarHeight() const -{ - return m_titleBarHeight; -} - -void FramelessHelper::setTitleBarHeight(const int val) -{ - m_titleBarHeight = val; -} - -bool FramelessHelper::getResizable(const QWindow *window) const -{ - Q_ASSERT(window); - if (!window) { - return false; - } - return !m_fixedSize.value(window); -} - -void FramelessHelper::setResizable(const QWindow *window, const bool val) -{ - Q_ASSERT(window); - if (!window) { - return; - } - m_fixedSize.insert(window, !val); -} - void FramelessHelper::removeWindowFrame(QWindow *window) { Q_ASSERT(window); if (!window) { return; } - // TODO: check whether these flags are correct for Linux and macOS. - window->setFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint - | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint); - // MouseTracking is always enabled for QWindow. + window->setFlags(window->flags() | Qt::FramelessWindowHint); window->installEventFilter(this); + window->setProperty(_flh_global::_flh_framelessEnabled_flag, true); +} + +void FramelessHelper::bringBackWindowFrame(QWindow *window) +{ + Q_ASSERT(window); + if (!window) { + return; + } + window->removeEventFilter(this); + window->setFlags(window->flags() & ~Qt::FramelessWindowHint); + window->setProperty(_flh_global::_flh_framelessEnabled_flag, false); } bool FramelessHelper::eventFilter(QObject *object, QEvent *event) @@ -104,11 +66,13 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) if (!object->isWindowType()) { return false; } - // QWindow will always be a top level window. It can't - // be anyone's child window. const auto currentWindow = qobject_cast(object); + const int m_borderWidth = FramelessWindowsManager::getBorderWidth(currentWindow); + const int m_borderHeight = FramelessWindowsManager::getBorderHeight(currentWindow); + const int m_titleBarHeight = FramelessWindowsManager::getTitleBarHeight(currentWindow); + const bool m_resizable = FramelessWindowsManager::getResizable(currentWindow); const auto getWindowEdges = - [this](const QPointF &point, const int ww, const int wh) -> Qt::Edges { + [m_borderWidth, m_borderHeight](const QPointF &point, const int ww, const int wh) -> Qt::Edges { if (point.y() <= m_borderHeight) { if (point.x() <= m_borderWidth) { return Qt::Edge::TopEdge | Qt::Edge::LeftEdge; @@ -152,7 +116,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) } return Qt::CursorShape::ArrowCursor; }; - const auto isInTitlebarArea = [this](const QPointF &point, const QWindow *window) -> bool { + const auto isInTitlebarArea = [m_titleBarHeight](const QPointF &point, const QWindow *window) -> bool { Q_ASSERT(window); if (!window) { return false; @@ -160,7 +124,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) return (point.y() <= m_titleBarHeight) && !Utilities::isHitTestVisibleInChrome(window); }; const auto moveOrResize = - [this, &getWindowEdges, &isInTitlebarArea](const QPointF &point, QWindow *window) { + [m_resizable, &getWindowEdges, &isInTitlebarArea](const QPointF &point, QWindow *window) { Q_ASSERT(window); if (!window) { return; @@ -175,7 +139,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) } } else { if ((window->windowState() == Qt::WindowState::WindowNoState) - && !Utilities::isHitTestVisibleInChrome(window) && getResizable(window)) { + && !Utilities::isHitTestVisibleInChrome(window) && m_resizable) { if (!window->startSystemResize(edges)) { // ### FIXME: TO BE IMPLEMENTED! qWarning() << "Current OS doesn't support QWindow::startSystemResize()."; @@ -221,8 +185,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) } break; case QEvent::MouseMove: { const auto mouseEvent = static_cast(event); - if ((currentWindow->windowState() == Qt::WindowState::WindowNoState) - && getResizable(currentWindow)) { + if ((currentWindow->windowState() == Qt::WindowState::WindowNoState) && m_resizable) { currentWindow->setCursor( getCursorShape(getWindowEdges(getMousePos(mouseEvent, false), currentWindow->width(), diff --git a/framelesshelper.h b/framelesshelper.h index ecb6145..98c28c2 100644 --- a/framelesshelper.h +++ b/framelesshelper.h @@ -27,8 +27,7 @@ #include "framelesshelper_global.h" #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) -#include -#include +#include QT_BEGIN_NAMESPACE QT_FORWARD_DECLARE_CLASS(QWindow) @@ -44,27 +43,9 @@ public: ~FramelessHelper() override = default; void removeWindowFrame(QWindow *window); - - int getBorderWidth() const; - void setBorderWidth(const int val); - - int getBorderHeight() const; - void setBorderHeight(const int val); - - int getTitleBarHeight() const; - void setTitleBarHeight(const int val); - - bool getResizable(const QWindow *window) const; - void setResizable(const QWindow *window, const bool val); + void bringBackWindowFrame(QWindow *window); protected: bool eventFilter(QObject *object, QEvent *event) override; - -private: - // ### FIXME: The default border width and height on Windows is 8 pixels if - // the scale factor is 1.0. Don't know how to acquire these values on UNIX - // platforms through native API. - int m_borderWidth = 8, m_borderHeight = 8, m_titleBarHeight = 30; - QHash m_fixedSize = {}; }; #endif diff --git a/framelesshelper_global.h b/framelesshelper_global.h index 0bb78fd..5e79de4 100644 --- a/framelesshelper_global.h +++ b/framelesshelper_global.h @@ -67,6 +67,6 @@ namespace _flh_global { [[maybe_unused]] const char _flh_useNativeTitleBar_flag[] = "_FRAMELESSHELPER_USE_NATIVE_TITLE_BAR"; [[maybe_unused]] const char _flh_preserveNativeFrame_flag[] = "_FRAMELESSHELPER_PRESERVE_NATIVE_WINDOW_FRAME"; [[maybe_unused]] const char _flh_forcePreserveNativeFrame_flag[] = "_FRAMELESSHELPER_FORCE_PRESERVE_NATIVE_WINDOW_FRAME"; -[[maybe_unused]] const char _flh_nativeParent_flag[] = "_FRAMELESSHELPER_NATIVE_PARENT"; +[[maybe_unused]] const char _flh_windowFixedSize_flag[] = "_FRAMELESSHELPER_WINDOW_FIXED_SIZE"; } diff --git a/framelesshelper_win32.cpp b/framelesshelper_win32.cpp index 15eb181..16bb5c1 100644 --- a/framelesshelper_win32.cpp +++ b/framelesshelper_win32.cpp @@ -116,10 +116,10 @@ static inline void installHelper(QWindow *window, const bool enable) if (!window) { return; } - window->setProperty(_flh_global::_flh_framelessEnabled_flag, enable); Utilities::updateQtFrameMargins(window, enable); Utilities::updateFrameMargins(window, !enable); Utilities::triggerFrameChange(window); + window->setProperty(_flh_global::_flh_framelessEnabled_flag, enable); } FramelessHelperWin::FramelessHelperWin() = default; @@ -134,19 +134,13 @@ FramelessHelperWin::~FramelessHelperWin() void FramelessHelperWin::addFramelessWindow(QWindow *window) { Q_ASSERT(window); + if (!window) { + return; + } setup(); installHelper(window, true); } -bool FramelessHelperWin::isWindowFrameless(const QWindow *window) -{ - Q_ASSERT(window); - if (!window) { - return false; - } - return window->property(_flh_global::_flh_framelessEnabled_flag).toBool(); -} - void FramelessHelperWin::removeFramelessWindow(QWindow *window) { Q_ASSERT(window); @@ -639,30 +633,3 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me } return false; } - -void FramelessHelperWin::setBorderWidth(QWindow *window, const int bw) -{ - Q_ASSERT(window); - if (!window) { - return; - } - window->setProperty(_flh_global::_flh_borderWidth_flag, bw); -} - -void FramelessHelperWin::setBorderHeight(QWindow *window, const int bh) -{ - Q_ASSERT(window); - if (!window) { - return; - } - window->setProperty(_flh_global::_flh_borderHeight_flag, bh); -} - -void FramelessHelperWin::setTitleBarHeight(QWindow *window, const int tbh) -{ - Q_ASSERT(window); - if (!window) { - return; - } - window->setProperty(_flh_global::_flh_titleBarHeight_flag, tbh); -} diff --git a/framelesshelper_win32.h b/framelesshelper_win32.h index 57e4411..540373e 100644 --- a/framelesshelper_win32.h +++ b/framelesshelper_win32.h @@ -41,13 +41,8 @@ public: ~FramelessHelperWin() override; static void addFramelessWindow(QWindow *window); - static bool isWindowFrameless(const QWindow *window); static void removeFramelessWindow(QWindow *window); - static void setBorderWidth(QWindow *window, const int bw); - static void setBorderHeight(QWindow *window, const int bh); - static void setTitleBarHeight(QWindow *window, const int tbh); - #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override; #else diff --git a/framelessquickhelper.cpp b/framelessquickhelper.cpp index b49f1a8..bf3c238 100644 --- a/framelessquickhelper.cpp +++ b/framelessquickhelper.cpp @@ -97,6 +97,16 @@ void FramelessQuickHelper::removeWindowFrame() FramelessWindowsManager::addWindow(window()); } +void FramelessQuickHelper::bringBackWindowFrame() +{ + FramelessWindowsManager::removeWindow(window()); +} + +bool FramelessQuickHelper::isWindowFrameless() const +{ + return FramelessWindowsManager::isWindowFrameless(window()); +} + void FramelessQuickHelper::setHitTestVisibleInChrome(QQuickItem *item, const bool visible) { Q_ASSERT(item); diff --git a/framelessquickhelper.h b/framelessquickhelper.h index a5b4c04..6245fe7 100644 --- a/framelessquickhelper.h +++ b/framelessquickhelper.h @@ -60,6 +60,8 @@ public: public Q_SLOTS: void removeWindowFrame(); + void bringBackWindowFrame(); + bool isWindowFrameless() const; void setHitTestVisibleInChrome(QQuickItem *item, const bool visible); Q_SIGNALS: diff --git a/framelesswindowsmanager.cpp b/framelesswindowsmanager.cpp index 3b9987d..ac8c77a 100644 --- a/framelesswindowsmanager.cpp +++ b/framelesswindowsmanager.cpp @@ -35,13 +35,11 @@ #endif #ifdef FRAMELESSHELPER_USE_UNIX_VERSION -Q_GLOBAL_STATIC(FramelessHelper, framelessHelper) +Q_GLOBAL_STATIC(FramelessHelper, framelessHelperUnix) #endif Q_DECLARE_METATYPE(const QObject *) -FramelessWindowsManager::FramelessWindowsManager() = default; - void FramelessWindowsManager::addWindow(QWindow *window) { Q_ASSERT(window); @@ -49,7 +47,7 @@ void FramelessWindowsManager::addWindow(QWindow *window) return; } #ifdef FRAMELESSHELPER_USE_UNIX_VERSION - framelessHelper()->removeWindowFrame(window); + framelessHelperUnix()->removeWindowFrame(window); #else FramelessHelperWin::addFramelessWindow(window); // Work-around a Win32 multi-monitor bug. @@ -60,7 +58,7 @@ void FramelessWindowsManager::addWindow(QWindow *window) #endif } -void FramelessWindowsManager::setHitTestVisibleInChrome(QWindow *window, QObject *object, const bool value) +void FramelessWindowsManager::setHitTestVisibleInChrome(QWindow *window, const QObject *object, const bool value) { Q_ASSERT(window); Q_ASSERT(object); @@ -71,97 +69,86 @@ void FramelessWindowsManager::setHitTestVisibleInChrome(QWindow *window, QObject qWarning() << object << "is not a QWidget or QQuickItem."; return; } - const QObject *nativeParent = Utilities::getNativeParent(object); - Q_ASSERT(nativeParent); - if (!nativeParent) { - return; + auto objList = qvariant_cast(window->property(_flh_global::_flh_hitTestVisibleInChrome_flag)); + if (value) { + if (objList.isEmpty() || !objList.contains(object)) { + objList.append(const_cast(object)); + } + } else { + if (!objList.isEmpty() && objList.contains(object)) { + objList.removeAll(object); + } } - window->setProperty(_flh_global::_flh_nativeParent_flag, QVariant::fromValue(nativeParent)); - object->setProperty(_flh_global::_flh_hitTestVisibleInChrome_flag, value); + window->setProperty(_flh_global::_flh_hitTestVisibleInChrome_flag, QVariant::fromValue(objList)); } int FramelessWindowsManager::getBorderWidth(const QWindow *window) { -#ifdef FRAMELESSHELPER_USE_UNIX_VERSION - Q_UNUSED(window); - return framelessHelper()->getBorderWidth(); -#else Q_ASSERT(window); if (!window) { - return 0; + return 8; } +#ifdef FRAMELESSHELPER_USE_UNIX_VERSION + const int value = window->property(_flh_global::_flh_borderWidth_flag).toInt(); + return value <= 0 ? 8 : value; +#else return Utilities::getSystemMetric(window, Utilities::SystemMetric::BorderWidth, false); #endif } void FramelessWindowsManager::setBorderWidth(QWindow *window, const int value) { -#ifdef FRAMELESSHELPER_USE_UNIX_VERSION - Q_UNUSED(window); - framelessHelper()->setBorderWidth(value); -#else Q_ASSERT(window); - if (!window) { + if (!window || (value <= 0)) { return; } - FramelessHelperWin::setBorderWidth(window, value); -#endif + window->setProperty(_flh_global::_flh_borderWidth_flag, value); } int FramelessWindowsManager::getBorderHeight(const QWindow *window) { -#ifdef FRAMELESSHELPER_USE_UNIX_VERSION - Q_UNUSED(window); - return framelessHelper()->getBorderHeight(); -#else Q_ASSERT(window); if (!window) { - return 0; + return 8; } +#ifdef FRAMELESSHELPER_USE_UNIX_VERSION + const int value = window->property(_flh_global::_flh_borderHeight_flag).toInt(); + return value <= 0 ? 8 : value; +#else return Utilities::getSystemMetric(window, Utilities::SystemMetric::BorderHeight, false); #endif } void FramelessWindowsManager::setBorderHeight(QWindow *window, const int value) { -#ifdef FRAMELESSHELPER_USE_UNIX_VERSION - Q_UNUSED(window); - framelessHelper()->setBorderHeight(value); -#else Q_ASSERT(window); - if (!window) { + if (!window || (value <= 0)) { return; } - FramelessHelperWin::setBorderHeight(window, value); -#endif + window->setProperty(_flh_global::_flh_borderHeight_flag, value); } int FramelessWindowsManager::getTitleBarHeight(const QWindow *window) { -#ifdef FRAMELESSHELPER_USE_UNIX_VERSION - Q_UNUSED(window); - return framelessHelper()->getTitleBarHeight(); -#else Q_ASSERT(window); if (!window) { - return 0; + return 30; } +#ifdef FRAMELESSHELPER_USE_UNIX_VERSION + const int value = window->property(_flh_global::_flh_titleBarHeight_flag).toInt(); + return value <= 0 ? 30 : value; +#else return Utilities::getSystemMetric(window, Utilities::SystemMetric::TitleBarHeight, false); #endif } void FramelessWindowsManager::setTitleBarHeight(QWindow *window, const int value) { -#ifdef FRAMELESSHELPER_USE_UNIX_VERSION - Q_UNUSED(window); - framelessHelper()->setTitleBarHeight(value); -#else Q_ASSERT(window); - if (!window) { + if (!window || (value <= 0)) { return; } - FramelessHelperWin::setTitleBarHeight(window, value); -#endif + window->setProperty(_flh_global::_flh_titleBarHeight_flag, value); } bool FramelessWindowsManager::getResizable(const QWindow *window) @@ -171,7 +158,7 @@ bool FramelessWindowsManager::getResizable(const QWindow *window) return false; } #ifdef FRAMELESSHELPER_USE_UNIX_VERSION - return framelessHelper()->getResizable(window); + return !window->property(_flh_global::_flh_windowFixedSize_flag).toBool(); #else return !Utilities::isWindowFixedSize(window); #endif @@ -184,8 +171,30 @@ void FramelessWindowsManager::setResizable(QWindow *window, const bool value) return; } #ifdef FRAMELESSHELPER_USE_UNIX_VERSION - framelessHelper()->setResizable(window, value); + window->setProperty(_flh_global::_flh_windowFixedSize_flag, !value); #else window->setFlag(Qt::MSWindowsFixedSizeDialogHint, !value); #endif } + +void FramelessWindowsManager::removeWindow(QWindow *window) +{ + Q_ASSERT(window); + if (!window) { + return; + } +#ifdef FRAMELESSHELPER_USE_UNIX_VERSION + framelessHelperUnix()->bringBackWindowFrame(window); +#else + FramelessHelperWin::removeFramelessWindow(window); +#endif +} + +bool FramelessWindowsManager::isWindowFrameless(const QWindow *window) +{ + Q_ASSERT(window); + if (!window) { + return false; + } + return window->property(_flh_global::_flh_framelessEnabled_flag).toBool(); +} diff --git a/framelesswindowsmanager.h b/framelesswindowsmanager.h index b8483c8..7607e15 100644 --- a/framelesswindowsmanager.h +++ b/framelesswindowsmanager.h @@ -25,34 +25,25 @@ #pragma once #include "framelesshelper_global.h" -#include QT_BEGIN_NAMESPACE QT_FORWARD_DECLARE_CLASS(QObject) QT_FORWARD_DECLARE_CLASS(QWindow) QT_END_NAMESPACE -class FRAMELESSHELPER_API FramelessWindowsManager -{ - Q_DISABLE_COPY_MOVE(FramelessWindowsManager) +namespace FramelessWindowsManager { -public: - explicit FramelessWindowsManager(); - ~FramelessWindowsManager() = default; +FRAMELESSHELPER_API void addWindow(QWindow *window); +FRAMELESSHELPER_API void removeWindow(QWindow *window); +FRAMELESSHELPER_API bool isWindowFrameless(const QWindow *window); +FRAMELESSHELPER_API void setHitTestVisibleInChrome(QWindow *window, const QObject *object, const bool value = true); +FRAMELESSHELPER_API int getBorderWidth(const QWindow *window); +FRAMELESSHELPER_API void setBorderWidth(QWindow *window, const int value); +FRAMELESSHELPER_API int getBorderHeight(const QWindow *window); +FRAMELESSHELPER_API void setBorderHeight(QWindow *window, const int value); +FRAMELESSHELPER_API int getTitleBarHeight(const QWindow *window); +FRAMELESSHELPER_API void setTitleBarHeight(QWindow *window, const int value); +FRAMELESSHELPER_API bool getResizable(const QWindow *window); +FRAMELESSHELPER_API void setResizable(QWindow *window, const bool value = true); - static void addWindow(QWindow *window); - - static void setHitTestVisibleInChrome(QWindow *window, QObject *object, const bool value = true); - - static int getBorderWidth(const QWindow *window); - static void setBorderWidth(QWindow *window, const int value); - - static int getBorderHeight(const QWindow *window); - static void setBorderHeight(QWindow *window, const int value); - - static int getTitleBarHeight(const QWindow *window); - static void setTitleBarHeight(QWindow *window, const int value); - - static bool getResizable(const QWindow *window); - static void setResizable(QWindow *window, const bool value = true); -}; +} diff --git a/utilities.cpp b/utilities.cpp index 64b47a2..87e19fb 100644 --- a/utilities.cpp +++ b/utilities.cpp @@ -73,10 +73,9 @@ bool Utilities::isWindowFixedSize(const QWindow *window) QPointF Utilities::getGlobalMousePosition(const QWindow *window) { if (window) { - return (QCursor::pos(window->screen()) * window->devicePixelRatio()); + return QPointF(QCursor::pos(window->screen()) * window->devicePixelRatio()); } else { - const qreal dpr = 1.0; // TODO - return (QCursor::pos() * dpr); + return QPointF(QCursor::pos() * qGuiApp->devicePixelRatio()); } } @@ -86,8 +85,7 @@ bool Utilities::isHitTestVisibleInChrome(const QWindow *window) if (!window) { return false; } - const auto target = qvariant_cast(window->property(_flh_global::_flh_nativeParent_flag)); - const QObjectList objs = target ? target->findChildren() : window->findChildren(); + const auto objs = qvariant_cast(window->property(_flh_global::_flh_hitTestVisibleInChrome_flag)); if (objs.isEmpty()) { return false; } @@ -95,7 +93,7 @@ bool Utilities::isHitTestVisibleInChrome(const QWindow *window) if (!obj || !(obj->isWidgetType() || obj->inherits("QQuickItem"))) { continue; } - if (!obj->property(_flh_global::_flh_hitTestVisibleInChrome_flag).toBool() || !obj->property("visible").toBool()) { + if (!obj->property("visible").toBool()) { continue; } const QPointF originPoint = mapOriginPointToWindow(obj); @@ -110,27 +108,6 @@ bool Utilities::isHitTestVisibleInChrome(const QWindow *window) return false; } -QObject *Utilities::getNativeParent(const QObject *object) -{ - Q_ASSERT(object); - if (!object) { - return nullptr; - } - if (!object->isWidgetType() && !object->inherits("QQuickItem")) { - qWarning() << object << "is not a QWidget or a QQuickItem."; - return nullptr; - } - QObject *parent = object->parent(); - while (parent) { - QObject *p = parent->parent(); - if (!p || p->isWindowType()) { - return parent; - } - parent = p; - } - return parent; -} - QPointF Utilities::mapOriginPointToWindow(const QObject *object) { Q_ASSERT(object); diff --git a/utilities.h b/utilities.h index a89543b..81a0c78 100644 --- a/utilities.h +++ b/utilities.h @@ -39,24 +39,14 @@ enum class SystemMetric // Common FRAMELESSHELPER_API int getSystemMetric(const QWindow *window, const SystemMetric metric, const bool dpiAware, const bool forceSystemValue = false); - FRAMELESSHELPER_API bool isLightThemeEnabled(); FRAMELESSHELPER_API bool isDarkThemeEnabled(); - FRAMELESSHELPER_API QWindow *findWindow(const WId winId); - FRAMELESSHELPER_API bool shouldUseNativeTitleBar(); - FRAMELESSHELPER_API bool isWindowFixedSize(const QWindow *window); - FRAMELESSHELPER_API QPointF getGlobalMousePosition(const QWindow *window); - FRAMELESSHELPER_API bool isHitTestVisibleInChrome(const QWindow *window); - FRAMELESSHELPER_API QColor getNativeWindowFrameColor(const bool isActive = true); - -FRAMELESSHELPER_API QObject *getNativeParent(const QObject *object); - FRAMELESSHELPER_API QPointF mapOriginPointToWindow(const QObject *object); #ifdef Q_OS_WINDOWS @@ -66,20 +56,15 @@ FRAMELESSHELPER_API bool isWin8OrGreater(); FRAMELESSHELPER_API bool isWin8Point1OrGreater(); FRAMELESSHELPER_API bool isWin10OrGreater(); FRAMELESSHELPER_API bool isWin10OrGreater(const int subVer); - FRAMELESSHELPER_API bool isDwmBlurAvailable(); - FRAMELESSHELPER_API bool isColorizationEnabled(); FRAMELESSHELPER_API QColor getColorizationColor(); - FRAMELESSHELPER_API void triggerFrameChange(const QWindow *window); FRAMELESSHELPER_API void updateFrameMargins(const QWindow *window, const bool reset); FRAMELESSHELPER_API void updateQtFrameMargins(QWindow *window, const bool enable); - FRAMELESSHELPER_API quint32 getWindowDpi(const QWindow *window); FRAMELESSHELPER_API QMargins getWindowNativeFrameMargins(const QWindow *window); - -FRAMELESSHELPER_API void displaySystemMenu(const QWindow *window, const QPoint &pos = {}); +FRAMELESSHELPER_API void displaySystemMenu(const QWindow *window, const QPointF &pos = {}); #endif } diff --git a/utilities_win32.cpp b/utilities_win32.cpp index aae902c..a7c51f0 100644 --- a/utilities_win32.cpp +++ b/utilities_win32.cpp @@ -284,6 +284,11 @@ void Utilities::triggerFrameChange(const QWindow *window) void Utilities::updateFrameMargins(const QWindow *window, const bool reset) { + // DwmExtendFrameIntoClientArea() will always fail if DWM Composition is disabled. + // No need to try in this case. + if (!isDwmBlurAvailable()) { + return; + } Q_ASSERT(window); if (!window) { return; @@ -456,7 +461,7 @@ bool Utilities::isWin10OrGreater(const int subVer) #endif } -void Utilities::displaySystemMenu(const QWindow *window, const QPoint &pos) +void Utilities::displaySystemMenu(const QWindow *window, const QPointF &pos) { Q_ASSERT(window); if (!window) { @@ -511,11 +516,12 @@ void Utilities::displaySystemMenu(const QWindow *window, const QPoint &pos) SetMenuItemInfoW(hMenu, SC_MINIMIZE, FALSE, &mii); } const bool isRtl = QGuiApplication::isRightToLeft(); - const QPoint point = pos.isNull() ? QCursor::pos(window->screen()) : window->mapToGlobal(pos); + const qreal dpr = window->devicePixelRatio(); + const QPointF point = pos.isNull() ? QPointF(QCursor::pos(window->screen()) * dpr) : QPointF(window->mapToGlobal(pos) * dpr); const LPARAM cmd = TrackPopupMenu(hMenu, (TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_TOPALIGN | (isRtl ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), - point.x(), point.y(), 0, hwnd, nullptr); + qRound(point.x()), qRound(point.y()), 0, hwnd, nullptr); if (cmd) { PostMessageW(hwnd, WM_SYSCOMMAND, cmd, 0); }