From f1ec81b543fe1d5090acff298e24faf10a7bac63 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 19 Sep 2017 13:18:49 +0200 Subject: Windows QPA: Detect screen by mouse position when dragging a window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When dragging a window by its border, detect the screen by mouse position to prevent it from oscillating between screens when it resizes. Task-number: QTBUG-62971 Change-Id: I0a4a584ef8ff3bb7288d1abec4de51fb4091dccd Reviewed-by: Oliver Wolff Reviewed-by: Thorbjørn Lund Martsum --- src/plugins/platforms/windows/qtwindowsglobal.h | 6 ++++ src/plugins/platforms/windows/qwindowscontext.cpp | 7 +++++ src/plugins/platforms/windows/qwindowswindow.cpp | 34 +++++++++++++++-------- src/plugins/platforms/windows/qwindowswindow.h | 3 ++ 4 files changed, 39 insertions(+), 11 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h index b2152e7ed4..d2e1309280 100644 --- a/src/plugins/platforms/windows/qtwindowsglobal.h +++ b/src/plugins/platforms/windows/qtwindowsglobal.h @@ -101,6 +101,8 @@ enum WindowsEventType // Simplify event types FocusOutEvent = WindowEventFlag + 18, WhatsThisEvent = WindowEventFlag + 19, DpiChangedEvent = WindowEventFlag + 21, + EnterSizeMoveEvent = WindowEventFlag + 22, + ExitSizeMoveEvent = WindowEventFlag + 23, MouseEvent = MouseEventFlag + 1, MouseWheelEvent = MouseEventFlag + 2, CursorEvent = MouseEventFlag + 3, @@ -274,6 +276,10 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI return QtWindows::DeviceChangeEvent; case WM_DPICHANGED: return QtWindows::DpiChangedEvent; + case WM_ENTERSIZEMOVE: + return QtWindows::EnterSizeMoveEvent; + case WM_EXITSIZEMOVE: + return QtWindows::ExitSizeMoveEvent; default: break; } diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index e6e6ee8b1a..f108be96e7 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -1055,6 +1055,13 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); #endif break; + case QtWindows::EnterSizeMoveEvent: + platformWindow->setFlag(QWindowsWindow::ResizeMoveActive); + return true; + case QtWindows::ExitSizeMoveEvent: + platformWindow->clearFlag(QWindowsWindow::ResizeMoveActive); + platformWindow->checkForScreenChanged(); + return true; case QtWindows::ScrollEvent: #if QT_CONFIG(sessionmanager) return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result); diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 050829e6f5..d97ebb7545 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1527,6 +1527,26 @@ void QWindowsWindow::handleResized(int wParam) } } +void QWindowsWindow::checkForScreenChanged() +{ + if (parent()) + return; + + QPlatformScreen *currentScreen = screen(); + const auto &screenManager = QWindowsContext::instance()->screenManager(); + // QTBUG-62971: When dragging a window by its border, detect by mouse position + // to prevent it from oscillating between screens when it resizes + const QWindowsScreen *newScreen = testFlag(ResizeMoveActive) + ? screenManager.screenAtDp(QWindowsCursor::mousePosition()) + : screenManager.screenForHwnd(m_data.hwnd); + if (newScreen != nullptr && newScreen != currentScreen) { + qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__ + << ' ' << window() << " \"" << currentScreen->name() + << "\"->\"" << newScreen->name() << '"'; + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); + } +} + void QWindowsWindow::handleGeometryChange() { const QRect previousGeometry = m_data.geometry; @@ -1541,17 +1561,9 @@ void QWindowsWindow::handleGeometryChange() && !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) { fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true); } - if (!parent() && previousGeometry.topLeft() != m_data.geometry.topLeft()) { - QPlatformScreen *currentScreen = screen(); - const QWindowsScreen *newScreen = - QWindowsContext::instance()->screenManager().screenForHwnd(m_data.hwnd); - if (newScreen != nullptr && newScreen != currentScreen) { - qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__ - << ' ' << window() << " \"" << currentScreen->name() - << "\"->\"" << newScreen->name() << '"'; - QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); - } - } + + checkForScreenChanged(); + if (testFlag(SynchronousGeometryChangeEvent)) QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index aa8ce7e73a..2b447751ba 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -208,6 +208,7 @@ public: Compositing = 0x200000, HasBorderInFullScreen = 0x400000, WithinDpiChanged = 0x800000, + ResizeMoveActive = 0x2000000 }; QWindowsWindow(QWindow *window, const QWindowsWindowData &data); @@ -313,6 +314,8 @@ public: void alertWindow(int durationMs = 0); void stopAlertWindow(); + void checkForScreenChanged(); + static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes); void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch); static void setHasBorderInFullScreenStatic(QWindow *window, bool border); -- cgit v1.2.3