diff options
Diffstat (limited to 'src/plugins/platforms/windows/qwindowsmousehandler.cpp')
-rw-r--r-- | src/plugins/platforms/windows/qwindowsmousehandler.cpp | 79 |
1 files changed, 48 insertions, 31 deletions
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 2f624c3e16..2f2d5d2c59 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -130,7 +130,8 @@ QWindowsMouseHandler::QWindowsMouseHandler() : m_windowUnderMouse(0), m_trackedWindow(0), m_touchDevice(0), - m_leftButtonDown(false) + m_leftButtonDown(false), + m_previousCaptureWindow(0) { } @@ -212,6 +213,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, if (QWindowsContext::verboseEvents) qDebug() << "Automatic mouse capture for missing buttondown event" << window; } + m_previousCaptureWindow = window; return true; } else if (m_leftButtonDown && !actualLeftDown) { m_leftButtonDown = false; @@ -253,12 +255,13 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, } } + const bool hasCapture = platformWindow->hasMouseCapture(); + const bool currentNotCapturing = hasCapture && currentWindowUnderMouse != window; #ifndef Q_OS_WINCE // Enter new window: track to generate leave event. - // If there is an active capture, we must track the actual capture window instead of window - // under cursor or leaves will trigger constantly, so always track the window we got - // native mouse event for. - if (window != m_trackedWindow) { + // If there is an active capture, only track if the current window is capturing, + // so we don't get extra leave when cursor leaves the application. + if (window != m_trackedWindow && !currentNotCapturing) { TRACKMOUSEEVENT tme; tme.cbSize = sizeof(TRACKMOUSEEVENT); tme.dwFlags = TME_LEAVE; @@ -270,39 +273,53 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, } #endif // !Q_OS_WINCE - // Qt expects enter/leave events for windows even when some window is capturing mouse input, - // except for automatic capture when mouse button is pressed - in that case enter/leave - // should be sent only after the last button is released. - // We need to track m_windowUnderMouse separately from m_trackedWindow, as - // Windows mouse tracking will not trigger WM_MOUSELEAVE for leaving window when - // mouse capture is set. - if (!platformWindow->hasMouseCapture() - || !platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)) { - if (m_windowUnderMouse != currentWindowUnderMouse) { - if (m_windowUnderMouse) { - if (QWindowsContext::verboseEvents) - qDebug() << "Synthetic leave for " << m_windowUnderMouse; - QWindowSystemInterface::handleLeaveEvent(m_windowUnderMouse); - // Clear tracking if we are no longer over application, - // since we have already sent the leave. - if (!currentWindowUnderMouse) - m_trackedWindow = 0; - } - - if (currentWindowUnderMouse) { - if (QWindowsContext::verboseEvents) - qDebug() << "Entering " << currentWindowUnderMouse; - QWindowsWindow::baseWindowOf(currentWindowUnderMouse)->applyCursor(); - QWindowSystemInterface::handleEnterEvent(currentWindowUnderMouse, - currentWindowUnderMouse->mapFromGlobal(globalPosition), - globalPosition); + // No enter or leave events are sent as long as there is an autocapturing window. + if (!hasCapture || !platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)) { + // Leave is needed if: + // 1) There is no capture and we move from a window to another window. + // Note: Leaving the application entirely is handled in WM_MOUSELEAVE case. + // 2) There is capture and we move out of the capturing window. + // 3) There is a new capture and we were over another window. + if ((m_windowUnderMouse && m_windowUnderMouse != currentWindowUnderMouse + && (!hasCapture || window == m_windowUnderMouse)) + || (hasCapture && m_previousCaptureWindow != window && m_windowUnderMouse + && m_windowUnderMouse != window)) { + if (QWindowsContext::verboseEvents) + qDebug() << "Synthetic leave for " << m_windowUnderMouse; + QWindowSystemInterface::handleLeaveEvent(m_windowUnderMouse); + if (currentNotCapturing) { + // Clear tracking if capturing and current window is not the capturing window + // to avoid leave when mouse actually leaves the application. + m_trackedWindow = 0; + // We are not officially in any window, but we need to set some cursor to clear + // whatever cursor the left window had, so apply the cursor of the capture window. + QWindowsWindow::baseWindowOf(window)->applyCursor(); } } + // Enter is needed if: + // 1) There is no capture and we move to a new window. + // 2) There is capture and we move into the capturing window. + // 3) The capture just ended and we are over non-capturing window. + if ((currentWindowUnderMouse && m_windowUnderMouse != currentWindowUnderMouse + && (!hasCapture || currentWindowUnderMouse == window)) + || (m_previousCaptureWindow && window != m_previousCaptureWindow && currentWindowUnderMouse + && currentWindowUnderMouse != m_previousCaptureWindow)) { + if (QWindowsContext::verboseEvents) + qDebug() << "Entering " << currentWindowUnderMouse; + QWindowsWindow::baseWindowOf(currentWindowUnderMouse)->applyCursor(); + QWindowSystemInterface::handleEnterEvent(currentWindowUnderMouse, + currentWindowUnderMouse->mapFromGlobal(globalPosition), + globalPosition); + } + // We need to track m_windowUnderMouse separately from m_trackedWindow, as + // Windows mouse tracking will not trigger WM_MOUSELEAVE for leaving window when + // mouse capture is set. m_windowUnderMouse = currentWindowUnderMouse; } QWindowSystemInterface::handleMouseEvent(window, winEventPosition, globalPosition, buttons, QWindowsKeyMapper::queryKeyboardModifiers()); + m_previousCaptureWindow = hasCapture ? window : 0; return true; } |