Fix invalid mouse press and release events on window maximize
authorMiikka Heikkinen <miikka.heikkinen@digia.com>
Tue, 6 Nov 2012 11:56:18 +0000 (13:56 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Wed, 7 Nov 2012 07:44:25 +0000 (08:44 +0100)
In Windows, if the window is maximized with a doubleclick on the title
bar or resized with a doubleclick on the bottom or top frame border,
there comes no WM_LBUTTONDOWN or WM_LBUTTONDBLCLK event for the second
click, but there comes at least one WM_MOUSEMOVE with left button down
and eventual WM_LBUTTONUP.
Since QWindowSystemInterface::handleMouseEvent() can't differentiate
between actual button down event and a move event with button held
down, the move resulted in a button down event being sent to the widget
that was under cursor after resize.

Fixed by ignoring any events with left button down for which we didn't
get the initial native button down event. Since entering an application
with mouse button already held down is not generating mouse events
anyway until the button is released, this should be safe.

Task-number: QTBUG-27845
Change-Id: Ibc7abf8a127c401801e1b654a2829582f43a1ae8
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
src/plugins/platforms/windows/qwindowsmousehandler.cpp
src/plugins/platforms/windows/qwindowsmousehandler.h

index 2d60c87..2a8fd4c 100644 (file)
@@ -129,7 +129,8 @@ static inline void compressMouseMove(MSG *msg)
 QWindowsMouseHandler::QWindowsMouseHandler() :
     m_windowUnderMouse(0),
     m_trackedWindow(0),
-    m_touchDevice(0)
+    m_touchDevice(0),
+    m_leftButtonDown(false)
 {
 }
 
@@ -164,7 +165,6 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
         return false; // Allow further event processing (dragging of windows).
     }
 
-
     *result = 0;
     if (msg.message == WM_MOUSELEAVE) {
         if (QWindowsContext::verboseEvents)
@@ -185,6 +185,34 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
     }
 
     QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
+
+    // If the window was recently resized via mouse doubleclick on the frame or title bar,
+    // we don't get WM_LBUTTONDOWN or WM_LBUTTONDBLCLK for the second click,
+    // but we will get at least one WM_MOUSEMOVE with left button down and the WM_LBUTTONUP,
+    // which will result undesired mouse press and release events.
+    // To avoid those, we ignore any events with left button down if we didn't
+    // get the original WM_LBUTTONDOWN/WM_LBUTTONDBLCLK.
+    if (msg.message == WM_LBUTTONDOWN || msg.message == WM_LBUTTONDBLCLK) {
+        m_leftButtonDown = true;
+    } else {
+        const bool actualLeftDown = keyStateToMouseButtons((int)msg.wParam) & Qt::LeftButton;
+        if (!m_leftButtonDown && actualLeftDown) {
+            // Autocapture the mouse for current window to and ignore further events until release.
+            // Capture is necessary so we don't get WM_MOUSELEAVEs to confuse matters.
+            // This autocapture is released normally when button is released.
+            if (!platformWindow->hasMouseCapture()) {
+                QWindowsWindow::baseWindowOf(window)->applyCursor();
+                platformWindow->setMouseGrabEnabled(true);
+                platformWindow->setFlag(QWindowsWindow::AutoMouseCapture);
+                if (QWindowsContext::verboseEvents)
+                    qDebug() << "Automatic mouse capture for missing buttondown event" << window;
+            }
+            return true;
+        } else if (m_leftButtonDown && !actualLeftDown) {
+            m_leftButtonDown = false;
+        }
+    }
+
     const QPoint globalPosition = QWindowsGeometryHint::mapToGlobal(hwnd, winEventPosition);
     QWindow *currentWindowUnderMouse = platformWindow->hasMouseCapture() ?
         QWindowsScreen::windowAt(globalPosition) : window;
index 1b19b34..e43d20e 100644 (file)
@@ -81,6 +81,7 @@ private:
     QPointer<QWindow> m_trackedWindow;
     QHash<DWORD, int> m_touchInputIDToTouchPointID;
     QTouchDevice *m_touchDevice;
+    bool m_leftButtonDown;
 };
 
 Qt::MouseButtons QWindowsMouseHandler::keyStateToMouseButtons(int wParam)