From 6ff58ef7b77d704b7b2f2ac439198c9ce07d5422 Mon Sep 17 00:00:00 2001 From: somenewacc <62895232+somenewacc@users.noreply.github.com> Date: Tue, 20 Apr 2021 18:38:11 +0300 Subject: [PATCH 1/6] Fix resize on another screen, closes #14 --- .../Kernels/NativeWindowHelper.cpp | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/FramelessHelper/Kernels/NativeWindowHelper.cpp b/FramelessHelper/Kernels/NativeWindowHelper.cpp index 0c2cefa..d54e9dd 100644 --- a/FramelessHelper/Kernels/NativeWindowHelper.cpp +++ b/FramelessHelper/Kernels/NativeWindowHelper.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -249,8 +250,33 @@ int NativeWindowHelperPrivate::hitTest(int x, int y) const { Q_CHECK_PTR(window); - x = x / window->devicePixelRatio(); - y = y / window->devicePixelRatio(); + int ratio = window->devicePixelRatio(); + + QList screens = QGuiApplication::screens(); + + auto screen_geometry = screens[0]->geometry(); + if (QGuiApplication::screenAt(QPoint(x, y)) != screens[0]) + { + for (int i = 1; i < screens.length(); i++) + { + auto geometry_tmp = screens[i]->geometry(); + + int delta_x = geometry_tmp.right() - geometry_tmp.left(); + int delta_y = geometry_tmp.bottom() - geometry_tmp.top(); + + if (x >= geometry_tmp.left() + && x <= (geometry_tmp.left() + delta_x * ratio) + && y >= geometry_tmp.top() + && y <= (geometry_tmp.top() + delta_y * ratio) + ){ + screen_geometry = geometry_tmp; + break; + } + } + } + + x = x - screen_geometry.left(); + y = y - screen_geometry.top(); enum RegionMask { Client = 0x0000, @@ -279,10 +305,10 @@ int NativeWindowHelperPrivate::hitTest(int x, int y) const bottom = GetSystemMetrics(SM_CYFRAME); auto result = - (Top * (y < (wfg.top() + top))) | - (Left * (x < (wfg.left() + left))) | - (Right * (x > (wfg.right() - right))) | - (Bottom * (y > (wfg.bottom() - bottom))); + (Top * (y < ((wfg.top() - screen_geometry.top()) * ratio + top))) | + (Left * (x < ((wfg.left() - screen_geometry.left()) * ratio + left))) | + (Right * (x > ((wfg.right() - screen_geometry.left()) * ratio - right))) | + (Bottom * (y > ((wfg.bottom() - screen_geometry.top()) * ratio - bottom))); bool wResizable = window->minimumWidth() < window->maximumWidth(); bool hResizable = window->minimumHeight() < window->maximumHeight(); From ea0a317e021c8225bf1c1c7add54535639d0677e Mon Sep 17 00:00:00 2001 From: somenewacc <62895232+somenewacc@users.noreply.github.com> Date: Tue, 20 Apr 2021 21:07:01 +0300 Subject: [PATCH 2/6] Fix pos to make buttons clickable --- FramelessHelper/Kernels/NativeWindowHelper.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/FramelessHelper/Kernels/NativeWindowHelper.cpp b/FramelessHelper/Kernels/NativeWindowHelper.cpp index d54e9dd..ea837a3 100644 --- a/FramelessHelper/Kernels/NativeWindowHelper.cpp +++ b/FramelessHelper/Kernels/NativeWindowHelper.cpp @@ -275,6 +275,9 @@ int NativeWindowHelperPrivate::hitTest(int x, int y) const } } + int x_prev = x; + int y_prev = y; + x = x - screen_geometry.left(); y = y - screen_geometry.top(); @@ -324,7 +327,7 @@ int NativeWindowHelperPrivate::hitTest(int x, int y) const case Left : return wResizable ? HTLEFT : HTCLIENT; } - auto pos = window->mapFromGlobal(QPoint(x, y)); + auto pos = window->mapFromGlobal(QPoint(x_prev * ratio, y_prev * ratio)); return ((nullptr != tester) && !tester->hitTest(pos)) ? HTCLIENT : HTCAPTION; } From c723c1c7d0757b6cca13078c7a6e80550d4df4ee Mon Sep 17 00:00:00 2001 From: somenewacc <62895232+somenewacc@users.noreply.github.com> Date: Wed, 21 Apr 2021 14:19:04 +0300 Subject: [PATCH 3/6] Resize window on screenChanged signal --- FramelessHelper/Kernels/NativeWindowHelper.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/FramelessHelper/Kernels/NativeWindowHelper.cpp b/FramelessHelper/Kernels/NativeWindowHelper.cpp index ea837a3..2a6246d 100644 --- a/FramelessHelper/Kernels/NativeWindowHelper.cpp +++ b/FramelessHelper/Kernels/NativeWindowHelper.cpp @@ -44,6 +44,11 @@ NativeWindowHelper::NativeWindowHelper(QWindow *window, NativeWindowTester *test d->updateWindowStyle(); } } + + QObject::connect(d->window, &QWindow::screenChanged, d->window, [=](QScreen *screen){ + Q_UNUSED(screen); + d->window->resize(d->window->size()); + }); } NativeWindowHelper::NativeWindowHelper(QWindow *window) From c2147c31607ac2ec675a901c6dd31648652e701d Mon Sep 17 00:00:00 2001 From: somenewacc <62895232+somenewacc@users.noreply.github.com> Date: Mon, 28 Jun 2021 00:32:36 +0300 Subject: [PATCH 4/6] Code clean up, use map from global position for HitTest --- .../Kernels/NativeWindowHelper.cpp | 55 ++++--------------- 1 file changed, 12 insertions(+), 43 deletions(-) diff --git a/FramelessHelper/Kernels/NativeWindowHelper.cpp b/FramelessHelper/Kernels/NativeWindowHelper.cpp index 2a6246d..876c2dd 100644 --- a/FramelessHelper/Kernels/NativeWindowHelper.cpp +++ b/FramelessHelper/Kernels/NativeWindowHelper.cpp @@ -44,11 +44,6 @@ NativeWindowHelper::NativeWindowHelper(QWindow *window, NativeWindowTester *test d->updateWindowStyle(); } } - - QObject::connect(d->window, &QWindow::screenChanged, d->window, [=](QScreen *screen){ - Q_UNUSED(screen); - d->window->resize(d->window->size()); - }); } NativeWindowHelper::NativeWindowHelper(QWindow *window) @@ -86,9 +81,11 @@ bool NativeWindowHelper::nativeEventFilter(void *msg, long *result) WPARAM wParam = lpMsg->wParam; LPARAM lParam = lpMsg->lParam; + QPoint pos = QCursor::pos(); + if (WM_NCHITTEST == lpMsg->message) { - *result = d->hitTest(GET_X_LPARAM(lParam), - GET_Y_LPARAM(lParam)); + *result = d->hitTest(pos.x(), + pos.y()); return true; } else if (WM_NCACTIVATE == lpMsg->message) { if (!QtWin::isCompositionEnabled()) { @@ -255,36 +252,7 @@ int NativeWindowHelperPrivate::hitTest(int x, int y) const { Q_CHECK_PTR(window); - int ratio = window->devicePixelRatio(); - - QList screens = QGuiApplication::screens(); - - auto screen_geometry = screens[0]->geometry(); - if (QGuiApplication::screenAt(QPoint(x, y)) != screens[0]) - { - for (int i = 1; i < screens.length(); i++) - { - auto geometry_tmp = screens[i]->geometry(); - - int delta_x = geometry_tmp.right() - geometry_tmp.left(); - int delta_y = geometry_tmp.bottom() - geometry_tmp.top(); - - if (x >= geometry_tmp.left() - && x <= (geometry_tmp.left() + delta_x * ratio) - && y >= geometry_tmp.top() - && y <= (geometry_tmp.top() + delta_y * ratio) - ){ - screen_geometry = geometry_tmp; - break; - } - } - } - - int x_prev = x; - int y_prev = y; - - x = x - screen_geometry.left(); - y = y - screen_geometry.top(); + QPoint pos_global = QPoint(x, y); enum RegionMask { Client = 0x0000, @@ -294,7 +262,6 @@ int NativeWindowHelperPrivate::hitTest(int x, int y) const Bottom = 0x1000, }; - auto wfg = window->frameGeometry(); QMargins draggableMargins = this->draggableMargins(); @@ -312,11 +279,14 @@ int NativeWindowHelperPrivate::hitTest(int x, int y) const if (bottom <= 0) bottom = GetSystemMetrics(SM_CYFRAME); + auto pos = window->mapFromGlobal(pos_global); + auto wfg = window->geometry(); + auto result = - (Top * (y < ((wfg.top() - screen_geometry.top()) * ratio + top))) | - (Left * (x < ((wfg.left() - screen_geometry.left()) * ratio + left))) | - (Right * (x > ((wfg.right() - screen_geometry.left()) * ratio - right))) | - (Bottom * (y > ((wfg.bottom() - screen_geometry.top()) * ratio - bottom))); + (Left * (pos.x() <= left) ) | + (Right * (pos.x() + right >= wfg.width())) | + (Top * (pos.y() <= top) ) | + (Bottom * (pos.y() + bottom >= wfg.height())); bool wResizable = window->minimumWidth() < window->maximumWidth(); bool hResizable = window->minimumHeight() < window->maximumHeight(); @@ -332,7 +302,6 @@ int NativeWindowHelperPrivate::hitTest(int x, int y) const case Left : return wResizable ? HTLEFT : HTCLIENT; } - auto pos = window->mapFromGlobal(QPoint(x_prev * ratio, y_prev * ratio)); return ((nullptr != tester) && !tester->hitTest(pos)) ? HTCLIENT : HTCAPTION; } From 6497a9f9fc1d82d97c494e25e69b6822fb3f73a3 Mon Sep 17 00:00:00 2001 From: somenewacc <62895232+somenewacc@users.noreply.github.com> Date: Mon, 28 Feb 2022 15:53:13 +0300 Subject: [PATCH 5/6] Fixes: - fix window size when maximized (remove 1 pixel from top and left) - g rect with scaleFactor - add case for WM_MOVE to update window on move - remove NativeWindowHelperPrivate::availableGeometry() (Fix for blank window now it's returns only window->screen()->availableGeometry()) - hitTest: scaledTitleBarHeight now doesn't use scaleFactor - add excludeItems.contains(child->parentWidget()) check in hitTest (fixes problem with buttons in toolbar) --- FramelessHelper/FramelessHelper.cpp | 6 ++-- .../Kernels/NativeWindowHelper.cpp | 34 ++++++++++++------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/FramelessHelper/FramelessHelper.cpp b/FramelessHelper/FramelessHelper.cpp index ffdb17a..0ee69df 100644 --- a/FramelessHelper/FramelessHelper.cpp +++ b/FramelessHelper/FramelessHelper.cpp @@ -219,7 +219,8 @@ QMargins FramelessHelperPrivate::maximizedMargins() const bool FramelessHelperPrivate::hitTest(const QPoint &pos) const { - int scaledTitleBarHeight = titleBarHeight * helper->scaleFactor(); + // Works fine with any scale without scaleFactor so far + int scaledTitleBarHeight = titleBarHeight /*/ helper->scaleFactor()*/; if (!window) return false; @@ -251,7 +252,8 @@ bool FramelessHelperPrivate::hitTest(const QPoint &pos) const if (includeItems.contains(child)) { break; - } else if (excludeItems.contains(child)) { + } else if (excludeItems.contains(child) || excludeItems.contains(child->parentWidget())) { + // child->parentWidget() fixed issue with toolbar, not sure about side effects return false; } else if (window == child) { break; diff --git a/FramelessHelper/Kernels/NativeWindowHelper.cpp b/FramelessHelper/Kernels/NativeWindowHelper.cpp index 876c2dd..dec21f8 100644 --- a/FramelessHelper/Kernels/NativeWindowHelper.cpp +++ b/FramelessHelper/Kernels/NativeWindowHelper.cpp @@ -98,10 +98,12 @@ bool NativeWindowHelper::nativeEventFilter(void *msg, long *result) NCCALCSIZE_PARAMS ¶ms = *reinterpret_cast(lParam); QRect g = d->availableGeometry(); + g.setWidth(g.width() * d->scaleFactor); + g.setHeight(g.height() * d->scaleFactor); QMargins m = d->maximizedMargins(); - params.rgrc[0].top = g.top() - m.top(); - params.rgrc[0].left = g.left() - m.left(); + params.rgrc[0].top = g.top() - m.top() - 1; + params.rgrc[0].left = g.left() - m.left() - 1; params.rgrc[0].right = g.right() + m.right() + 1; params.rgrc[0].bottom = g.bottom() + m.bottom() + 1; } @@ -113,6 +115,8 @@ bool NativeWindowHelper::nativeEventFilter(void *msg, long *result) LPMINMAXINFO lpMinMaxInfo = reinterpret_cast(lParam); QRect g = d->availableGeometry(); + g.setWidth(g.width() * d->scaleFactor); + g.setHeight(g.height() * d->scaleFactor); QMargins m = d->maximizedMargins(); lpMinMaxInfo->ptMaxPosition.x = - m.left(); @@ -156,6 +160,18 @@ bool NativeWindowHelper::nativeEventFilter(void *msg, long *result) rect->right - rect->left, rect->bottom - rect->top, SWP_NOZORDER | SWP_NOACTIVATE); + } else if (WM_MOVE == lpMsg->message) { + // Update window pos on move + auto hWnd = reinterpret_cast(d->window->winId()); + RECT rcClient; + GetWindowRect(hWnd, &rcClient); + SetWindowPos(hWnd, + NULL, + rcClient.left, + rcClient.top, + rcClient.right - rcClient.left, + rcClient.bottom - rcClient.top, + SWP_FRAMECHANGED); } return false; @@ -332,15 +348,7 @@ QMargins NativeWindowHelperPrivate::maximizedMargins() const QRect NativeWindowHelperPrivate::availableGeometry() const { - MONITORINFO mi{0}; - mi.cbSize = sizeof(MONITORINFO); - - auto hWnd = reinterpret_cast(window->winId()); - auto hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST); - if (!hMonitor || !GetMonitorInfoW(hMonitor, &mi)) { - Q_ASSERT(NULL != hMonitor); - return window->screen()->availableGeometry(); - } - - return QRect(mi.rcWork.left, mi.rcWork.top, mi.rcWork.right - mi.rcWork.left, mi.rcWork.bottom - mi.rcWork.top); + // These changes made because MonitorFromWindow doesn't work properly + // on second monitor. (Blank window on maximize after minimize) + return window->screen()->availableGeometry(); } From 83465695f1268d6c053345015d975dc64ca5f98a Mon Sep 17 00:00:00 2001 From: somenewacc <62895232+somenewacc@users.noreply.github.com> Date: Mon, 28 Feb 2022 16:05:50 +0300 Subject: [PATCH 6/6] Fix: - remove g.set*(g.*() * d->scaleFactor) for window on screen with scale --- FramelessHelper/Kernels/NativeWindowHelper.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/FramelessHelper/Kernels/NativeWindowHelper.cpp b/FramelessHelper/Kernels/NativeWindowHelper.cpp index dec21f8..afa7e76 100644 --- a/FramelessHelper/Kernels/NativeWindowHelper.cpp +++ b/FramelessHelper/Kernels/NativeWindowHelper.cpp @@ -98,8 +98,6 @@ bool NativeWindowHelper::nativeEventFilter(void *msg, long *result) NCCALCSIZE_PARAMS ¶ms = *reinterpret_cast(lParam); QRect g = d->availableGeometry(); - g.setWidth(g.width() * d->scaleFactor); - g.setHeight(g.height() * d->scaleFactor); QMargins m = d->maximizedMargins(); params.rgrc[0].top = g.top() - m.top() - 1; @@ -115,8 +113,6 @@ bool NativeWindowHelper::nativeEventFilter(void *msg, long *result) LPMINMAXINFO lpMinMaxInfo = reinterpret_cast(lParam); QRect g = d->availableGeometry(); - g.setWidth(g.width() * d->scaleFactor); - g.setHeight(g.height() * d->scaleFactor); QMargins m = d->maximizedMargins(); lpMinMaxInfo->ptMaxPosition.x = - m.left();