From 1ea00124f77df1753b3d881810bbed181bbc6fc6 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 5 Sep 2012 13:39:25 +0200 Subject: Windows: Implement automatic mouse capture in QPA. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Qt expects the mouse to be captured on any button press until release. Remove flags to store capture, use WinAPI GetCapture() instead. Remove setMouseGrabEnabled_sys(), streamline code. Replacement for the reverted change 6b5bbc531b30d8ece25425e39843c6ae1af1d045 for QTBUG-25977. Task-number: QTBUG-27132 Task-number: QTBUG-27039 Task-number: QTBUG-25977 Task-number: QTBUG-26962 Change-Id: If86428eabfadcafd16da10f134a419f833185272 Reviewed-by: Qt Doc Bot Reviewed-by: Miikka Heikkinen Reviewed-by: Jørgen Lind --- .../platforms/windows/qwindowsmousehandler.cpp | 19 ++++++++++- src/plugins/platforms/windows/qwindowswindow.cpp | 39 +++++++++++----------- src/plugins/platforms/windows/qwindowswindow.h | 6 ++-- 3 files changed, 41 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index f1e3d70d96..50980100cb 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -175,9 +175,26 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, return true; } compressMouseMove(&msg); + QWindowsWindow *platformWindow = static_cast(window->handle()); + // Qt expects the platform plugin to capture the mouse on + // any button press until release. + if (!platformWindow->hasMouseCapture() + && (msg.message == WM_LBUTTONDOWN || msg.message == WM_MBUTTONDOWN + || msg.message == WM_RBUTTONDOWN)) { + platformWindow->setMouseGrabEnabled(true); + platformWindow->setFlag(QWindowsWindow::AutoMouseCapture); + if (QWindowsContext::verboseEvents) + qDebug() << "Automatic mouse capture " << window; + } else if (platformWindow->hasMouseCapture() + && platformWindow->testFlag(QWindowsWindow::AutoMouseCapture) + && (msg.message == WM_LBUTTONUP || msg.message == WM_MBUTTONUP + || msg.message == WM_RBUTTONUP)) { + platformWindow->setMouseGrabEnabled(false); + if (QWindowsContext::verboseEvents) + qDebug() << "Releasing automatic mouse capture " << window; + } // Eat mouse move after size grip drag. if (msg.message == WM_MOUSEMOVE) { - QWindowsWindow *platformWindow = static_cast(window->handle()); if (platformWindow->testFlag(QWindowsWindow::SizeGripOperation)) { MSG mouseMsg; while (PeekMessage(&mouseMsg, platformWindow->handle(), WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) ; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index b43032dc1a..d58d10b4d5 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -696,7 +696,6 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) : m_hdc(0), m_windowState(Qt::WindowNoState), m_opacity(1.0), - m_mouseGrab(false), m_cursor(QWindowsScreen::screenOf(aWindow)->windowsCursor()->standardWindowCursor()), m_dropTarget(0), m_savedStyle(0), @@ -738,6 +737,8 @@ void QWindowsWindow::destroyWindow() if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows) qDebug() << __FUNCTION__ << this << window() << m_data.hwnd; if (m_data.hwnd) { // Stop event dispatching before Window is destroyed. + if (hasMouseCapture()) + setMouseGrabEnabled(false); unregisterDropSite(); QWindowsContext::instance()->removeWindow(m_data.hwnd); #ifdef QT_OPENGL_ES_2 @@ -811,6 +812,8 @@ void QWindowsWindow::setVisible(bool visible) QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); } else { + if (hasMouseCapture()) + setMouseGrabEnabled(false); hide_sys(); QWindowSystemInterface::handleExposeEvent(window(), QRegion()); } @@ -1495,29 +1498,27 @@ bool QWindowsWindow::setKeyboardGrabEnabled(bool grab) bool QWindowsWindow::setMouseGrabEnabled(bool grab) { - bool result = false; + if (QWindowsContext::verboseWindows) + qDebug() << __FUNCTION__ << window() << grab; if (!m_data.hwnd) { qWarning("%s: No handle", __FUNCTION__); - return result; + return false; } - if (QWindowsContext::verboseWindows) - qDebug() << __FUNCTION__ << window() << grab; - - if (m_mouseGrab != grab) { - m_mouseGrab = grab; - if (isVisible()) - setMouseGrabEnabled_sys(grab); + if (!isVisible() && grab) { + qWarning("%s: Not setting mouse grab for invisible window %s", + __FUNCTION__, qPrintable(window()->objectName())); + return false; } - return grab; -} - -void QWindowsWindow::setMouseGrabEnabled_sys(bool grab) -{ - if (grab) { - SetCapture(m_data.hwnd); - } else { - ReleaseCapture(); + // release grab or an explicit grab overriding autocapture: Clear flag. + clearFlag(QWindowsWindow::AutoMouseCapture); + if (hasMouseCapture() != grab) { + if (grab) { + SetCapture(m_data.hwnd); + } else { + ReleaseCapture(); + } } + return grab; } static inline DWORD cornerToWinOrientation(Qt::Corner corner) diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 35790e2739..2bcca8710f 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -126,7 +126,8 @@ public: SizeGripOperation = 0x100, FrameStrutEventsEnabled = 0x200, SynchronousGeometryChangeEvent = 0x400, - WithinSetStyle = 0x800 + WithinSetStyle = 0x800, + AutoMouseCapture = 0x1000 //! Automatic mouse capture on button press. }; struct WindowData @@ -179,6 +180,7 @@ public: virtual bool setKeyboardGrabEnabled(bool grab); virtual bool setMouseGrabEnabled(bool grab); + inline bool hasMouseCapture() const { return GetCapture() == m_data.hwnd; } virtual bool startSystemResize(const QPoint &pos, Qt::Corner corner); @@ -249,7 +251,6 @@ private: inline bool isFullScreen_sys() const; inline void setWindowState_sys(Qt::WindowState newState); inline void setParent_sys(const QPlatformWindow *parent) const; - inline void setMouseGrabEnabled_sys(bool grab); void destroyWindow(); void registerDropSite(); void unregisterDropSite(); @@ -261,7 +262,6 @@ private: HDC m_hdc; Qt::WindowState m_windowState; qreal m_opacity; - bool m_mouseGrab; QWindowsWindowCursor m_cursor; QWindowsOleDropTarget *m_dropTarget; unsigned m_savedStyle; -- cgit v1.2.3