summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp20
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp483
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.h6
3 files changed, 165 insertions, 344 deletions
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 2b96fb3a5e..41655dbd57 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -334,12 +334,8 @@ bool QWindowsContext::initTouch(unsigned integrationOptions)
if (!touchDevice)
return false;
- if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) {
- QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
- } else {
- if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch))
- touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation);
- }
+ if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch))
+ touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation);
QWindowSystemInterface::registerTouchDevice(touchDevice);
@@ -376,7 +372,6 @@ bool QWindowsContext::initPointer(unsigned integrationOptions)
if (!QWindowsContext::user32dll.supportsPointerApi())
return false;
- QWindowsContext::user32dll.enableMouseInPointer(TRUE);
d->m_systemInfo |= QWindowsContext::SI_SupportsPointer;
return true;
}
@@ -1218,9 +1213,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::ExposeEvent:
return platformWindow->handleWmPaint(hwnd, message, wParam, lParam);
case QtWindows::NonClientMouseEvent:
- if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
+ if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
+ return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
+ else
return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
- break;
case QtWindows::NonClientPointerEvent:
if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result);
@@ -1246,10 +1242,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
window = window->parent();
if (!window)
return false;
- if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
- return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result);
- else
+ if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer)
return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(window, hwnd, et, msg, result);
+ else
+ return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result);
}
break;
case QtWindows::TouchEvent:
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index 203d803a1b..f1960f1585 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -50,9 +50,6 @@
#include "qwindowswindow.h"
#include "qwindowsintegration.h"
#include "qwindowsscreen.h"
-#if QT_CONFIG(draganddrop)
-# include "qwindowsdrag.h"
-#endif
#include <QtGui/qguiapplication.h>
#include <QtGui/qscreen.h>
@@ -78,111 +75,9 @@ enum {
QT_PT_TOUCHPAD = 5, // MinGW is missing PT_TOUCHPAD
};
-struct PointerTouchEventInfo {
- QPointer<QWindow> window;
- QList<QWindowSystemInterface::TouchPoint> points;
- Qt::KeyboardModifiers modifiers;
-};
-
-struct PointerTabletEventInfo {
- QPointer<QWindow> window;
- QPointF local;
- QPointF global;
- int device;
- int pointerType;
- Qt::MouseButtons buttons;
- qreal pressure;
- int xTilt;
- int yTilt;
- qreal tangentialPressure;
- qreal rotation;
- int z;
- qint64 uid;
- Qt::KeyboardModifiers modifiers;
-};
-
-static QQueue<PointerTouchEventInfo> touchEventQueue;
-static QQueue<PointerTabletEventInfo> tabletEventQueue;
-
-static void enqueueTouchEvent(QWindow *window,
- const QList<QWindowSystemInterface::TouchPoint> &points,
- Qt::KeyboardModifiers modifiers)
-{
- PointerTouchEventInfo eventInfo;
- eventInfo.window = window;
- eventInfo.points = points;
- eventInfo.modifiers = modifiers;
- touchEventQueue.enqueue(eventInfo);
-}
-
-static void enqueueTabletEvent(QWindow *window, const QPointF &local, const QPointF &global,
- int device, int pointerType, Qt::MouseButtons buttons, qreal pressure,
- int xTilt, int yTilt, qreal tangentialPressure, qreal rotation,
- int z, qint64 uid, Qt::KeyboardModifiers modifiers)
-{
- PointerTabletEventInfo eventInfo;
- eventInfo.window = window;
- eventInfo.local = local;
- eventInfo.global = global;
- eventInfo.device = device;
- eventInfo.pointerType = pointerType;
- eventInfo.buttons = buttons;
- eventInfo.pressure = pressure;
- eventInfo.xTilt = xTilt;
- eventInfo.yTilt = yTilt;
- eventInfo.tangentialPressure = tangentialPressure;
- eventInfo.rotation = rotation;
- eventInfo.z = z;
- eventInfo.uid = uid;
- eventInfo.modifiers = modifiers;
- tabletEventQueue.enqueue(eventInfo);
-}
-
-static void flushTouchEvents(QTouchDevice *touchDevice)
-{
- while (!touchEventQueue.isEmpty()) {
- PointerTouchEventInfo eventInfo = touchEventQueue.dequeue();
- if (eventInfo.window) {
- QWindowSystemInterface::handleTouchEvent(eventInfo.window,
- touchDevice,
- eventInfo.points,
- eventInfo.modifiers);
- }
- }
-}
-
-static void flushTabletEvents()
-{
- while (!tabletEventQueue.isEmpty()) {
- PointerTabletEventInfo eventInfo = tabletEventQueue.dequeue();
- if (eventInfo.window) {
- QWindowSystemInterface::handleTabletEvent(eventInfo.window,
- eventInfo.local,
- eventInfo.global,
- eventInfo.device,
- eventInfo.pointerType,
- eventInfo.buttons,
- eventInfo.pressure,
- eventInfo.xTilt,
- eventInfo.yTilt,
- eventInfo.tangentialPressure,
- eventInfo.rotation,
- eventInfo.z,
- eventInfo.uid,
- eventInfo.modifiers);
- }
- }
-}
-
bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
{
*result = 0;
-
- // If we are inside the move/resize modal loop, let DefWindowProc() handle it (but process NC button release).
- QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
- if (msg.message != WM_NCPOINTERUP && platformWindow->testFlag(QWindowsWindow::ResizeMoveActive))
- return false;
-
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
POINTER_INPUT_TYPE pointerType;
@@ -191,30 +86,12 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
return false;
}
- m_lastPointerType = pointerType;
-
- // Handle non-client pen/touch as generic mouse events for compatibility with QDockWindow.
- if ((pointerType == QT_PT_TOUCH || pointerType == QT_PT_PEN) && (et & QtWindows::NonClientEventFlag)) {
- POINTER_INFO pointerInfo;
- if (!QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo)) {
- qWarning() << "GetPointerInfo() failed:" << qt_error_string();
- return false;
- }
- if (pointerInfo.pointerFlags & (POINTER_FLAG_UP | POINTER_FLAG_DOWN))
- return translateMouseTouchPadEvent(window, hwnd, et, msg, &pointerInfo);
- return false;
- }
-
switch (pointerType) {
case QT_PT_POINTER:
case QT_PT_MOUSE:
case QT_PT_TOUCHPAD: {
- POINTER_INFO pointerInfo;
- if (!QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo)) {
- qWarning() << "GetPointerInfo() failed:" << qt_error_string();
- return false;
- }
- return translateMouseTouchPadEvent(window, hwnd, et, msg, &pointerInfo);
+ // Let Mouse/TouchPad be handled using legacy messages.
+ return false;
}
case QT_PT_TOUCH: {
quint32 pointerCount = 0;
@@ -290,76 +167,71 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
return false;
}
-static void getMouseEventInfo(UINT message, POINTER_BUTTON_CHANGE_TYPE changeType, QEvent::Type *eventType, Qt::MouseButton *mouseButton)
-{
- static const QHash<POINTER_BUTTON_CHANGE_TYPE, Qt::MouseButton> buttonMapping {
- {POINTER_CHANGE_FIRSTBUTTON_DOWN, Qt::LeftButton},
- {POINTER_CHANGE_FIRSTBUTTON_UP, Qt::LeftButton},
- {POINTER_CHANGE_SECONDBUTTON_DOWN, Qt::RightButton},
- {POINTER_CHANGE_SECONDBUTTON_UP, Qt::RightButton},
- {POINTER_CHANGE_THIRDBUTTON_DOWN, Qt::MiddleButton},
- {POINTER_CHANGE_THIRDBUTTON_UP, Qt::MiddleButton},
- {POINTER_CHANGE_FOURTHBUTTON_DOWN, Qt::XButton1},
- {POINTER_CHANGE_FOURTHBUTTON_UP, Qt::XButton1},
- {POINTER_CHANGE_FIFTHBUTTON_DOWN, Qt::XButton2},
- {POINTER_CHANGE_FIFTHBUTTON_UP, Qt::XButton2},
- };
-
- static const POINTER_BUTTON_CHANGE_TYPE downChanges[] = {
- POINTER_CHANGE_FIRSTBUTTON_DOWN,
- POINTER_CHANGE_SECONDBUTTON_DOWN,
- POINTER_CHANGE_THIRDBUTTON_DOWN,
- POINTER_CHANGE_FOURTHBUTTON_DOWN,
- POINTER_CHANGE_FIFTHBUTTON_DOWN,
- };
-
- static const POINTER_BUTTON_CHANGE_TYPE upChanges[] = {
- POINTER_CHANGE_FIRSTBUTTON_UP,
- POINTER_CHANGE_SECONDBUTTON_UP,
- POINTER_CHANGE_THIRDBUTTON_UP,
- POINTER_CHANGE_FOURTHBUTTON_UP,
- POINTER_CHANGE_FIFTHBUTTON_UP,
- };
-
- if (!eventType || !mouseButton)
- return;
-
- const bool nonClient = message == WM_NCPOINTERUPDATE ||
- message == WM_NCPOINTERDOWN ||
- message == WM_NCPOINTERUP;
-
- if (std::find(std::begin(downChanges),
- std::end(downChanges), changeType) < std::end(downChanges)) {
- *eventType = nonClient ? QEvent::NonClientAreaMouseButtonPress :
- QEvent::MouseButtonPress;
- } else if (std::find(std::begin(upChanges),
- std::end(upChanges), changeType) < std::end(upChanges)) {
- *eventType = nonClient ? QEvent::NonClientAreaMouseButtonRelease :
- QEvent::MouseButtonRelease;
- } else if (message == WM_POINTERWHEEL || message == WM_POINTERHWHEEL) {
- *eventType = QEvent::Wheel;
- } else {
- *eventType = nonClient ? QEvent::NonClientAreaMouseMove :
- QEvent::MouseMove;
- }
+namespace {
+struct MouseEvent {
+ QEvent::Type type;
+ Qt::MouseButton button;
+};
+} // namespace
- *mouseButton = buttonMapping.value(changeType, Qt::NoButton);
+static inline Qt::MouseButton extraButton(WPARAM wParam) // for WM_XBUTTON...
+{
+ return GET_XBUTTON_WPARAM(wParam) == XBUTTON1 ? Qt::BackButton : Qt::ForwardButton;
}
-static Qt::MouseButtons mouseButtonsFromPointerFlags(POINTER_FLAGS pointerFlags)
+static inline MouseEvent eventFromMsg(const MSG &msg)
{
- Qt::MouseButtons result = Qt::NoButton;
- if (pointerFlags & POINTER_FLAG_FIRSTBUTTON)
- result |= Qt::LeftButton;
- if (pointerFlags & POINTER_FLAG_SECONDBUTTON)
- result |= Qt::RightButton;
- if (pointerFlags & POINTER_FLAG_THIRDBUTTON)
- result |= Qt::MiddleButton;
- if (pointerFlags & POINTER_FLAG_FOURTHBUTTON)
- result |= Qt::XButton1;
- if (pointerFlags & POINTER_FLAG_FIFTHBUTTON)
- result |= Qt::XButton2;
- return result;
+ switch (msg.message) {
+ case WM_MOUSEMOVE:
+ return {QEvent::MouseMove, Qt::NoButton};
+ case WM_LBUTTONDOWN:
+ return {QEvent::MouseButtonPress, Qt::LeftButton};
+ case WM_LBUTTONUP:
+ return {QEvent::MouseButtonRelease, Qt::LeftButton};
+ case WM_LBUTTONDBLCLK: // Qt QPA does not handle double clicks, send as press
+ return {QEvent::MouseButtonPress, Qt::LeftButton};
+ case WM_MBUTTONDOWN:
+ return {QEvent::MouseButtonPress, Qt::MidButton};
+ case WM_MBUTTONUP:
+ return {QEvent::MouseButtonRelease, Qt::MidButton};
+ case WM_MBUTTONDBLCLK:
+ return {QEvent::MouseButtonPress, Qt::MidButton};
+ case WM_RBUTTONDOWN:
+ return {QEvent::MouseButtonPress, Qt::RightButton};
+ case WM_RBUTTONUP:
+ return {QEvent::MouseButtonRelease, Qt::RightButton};
+ case WM_RBUTTONDBLCLK:
+ return {QEvent::MouseButtonPress, Qt::RightButton};
+ case WM_XBUTTONDOWN:
+ return {QEvent::MouseButtonPress, extraButton(msg.wParam)};
+ case WM_XBUTTONUP:
+ return {QEvent::MouseButtonRelease, extraButton(msg.wParam)};
+ case WM_XBUTTONDBLCLK:
+ return {QEvent::MouseButtonPress, extraButton(msg.wParam)};
+ case WM_NCMOUSEMOVE:
+ return {QEvent::NonClientAreaMouseMove, Qt::NoButton};
+ case WM_NCLBUTTONDOWN:
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton};
+ case WM_NCLBUTTONUP:
+ return {QEvent::NonClientAreaMouseButtonRelease, Qt::LeftButton};
+ case WM_NCLBUTTONDBLCLK:
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton};
+ case WM_NCMBUTTONDOWN:
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton};
+ case WM_NCMBUTTONUP:
+ return {QEvent::NonClientAreaMouseButtonRelease, Qt::MidButton};
+ case WM_NCMBUTTONDBLCLK:
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton};
+ case WM_NCRBUTTONDOWN:
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton};
+ case WM_NCRBUTTONUP:
+ return {QEvent::NonClientAreaMouseButtonRelease, Qt::RightButton};
+ case WM_NCRBUTTONDBLCLK:
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton};
+ default: // WM_MOUSELEAVE
+ break;
+ }
+ return {QEvent::None, Qt::NoButton};
}
static Qt::MouseButtons mouseButtonsFromKeyState(WPARAM keyState)
@@ -419,15 +291,6 @@ static bool isValidWheelReceiver(QWindow *candidate)
return false;
}
-static bool isMenuWindow(QWindow *window)
-{
- if (window)
- if (QObject *fo = window->focusObject())
- if (fo->inherits("QMenu"))
- return true;
- return false;
-}
-
static QTouchDevice *createTouchDevice()
{
const int digitizers = GetSystemMetrics(SM_DIGITIZER);
@@ -553,71 +416,6 @@ void QWindowsPointerHandler::handleEnterLeave(QWindow *window,
m_previousCaptureWindow = hasCapture ? window : nullptr;
}
-bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND hwnd,
- QtWindows::WindowsEventType et,
- MSG msg, PVOID vPointerInfo)
-{
- POINTER_INFO *pointerInfo = static_cast<POINTER_INFO *>(vPointerInfo);
- const QPoint globalPos = QPoint(pointerInfo->ptPixelLocation.x, pointerInfo->ptPixelLocation.y);
- const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
- const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
- const Qt::MouseButtons mouseButtons = mouseButtonsFromPointerFlags(pointerInfo->pointerFlags);
- QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
-
- switch (msg.message) {
- case WM_NCPOINTERDOWN:
- case WM_NCPOINTERUP:
- case WM_NCPOINTERUPDATE:
- case WM_POINTERDOWN:
- case WM_POINTERUP:
- case WM_POINTERUPDATE: {
-
- QEvent::Type eventType;
- Qt::MouseButton button;
- getMouseEventInfo(msg.message, pointerInfo->ButtonChangeType, &eventType, &button);
-
- if (et & QtWindows::NonClientEventFlag) {
- QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType,
- keyModifiers, Qt::MouseEventNotSynthesized);
- return false; // To allow window dragging, etc.
- } else {
-
- handleCaptureRelease(window, currentWindowUnderPointer, hwnd, eventType, mouseButtons);
- handleEnterLeave(window, currentWindowUnderPointer, globalPos);
-
- QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType,
- keyModifiers, Qt::MouseEventNotSynthesized);
-
- // The initial down click over the QSizeGrip area, which posts a resize WM_SYSCOMMAND
- // has go to through DefWindowProc() for resizing to work, so we return false here,
- // unless the click was on a menu, as it would mess with menu processing.
- return msg.message != WM_POINTERDOWN || isMenuWindow(window);
- }
- }
- case WM_POINTERHWHEEL:
- case WM_POINTERWHEEL: {
-
- if (!isValidWheelReceiver(window))
- return true;
-
- int delta = GET_WHEEL_DELTA_WPARAM(msg.wParam);
-
- // Qt horizontal wheel rotation orientation is opposite to the one in WM_POINTERHWHEEL
- if (msg.message == WM_POINTERHWHEEL)
- delta = -delta;
-
- const QPoint angleDelta = (msg.message == WM_POINTERHWHEEL || (keyModifiers & Qt::AltModifier)) ?
- QPoint(delta, 0) : QPoint(0, delta);
-
- QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers);
- return true;
- }
- case WM_POINTERLEAVE:
- return true;
- }
- return false;
-}
-
bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
QtWindows::WindowsEventType et,
MSG msg, PVOID vTouchInfo, quint32 count)
@@ -653,15 +451,14 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
QList<QWindowSystemInterface::TouchPoint> touchPoints;
- bool primaryPointer = false;
- bool pressRelease = false;
-
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaEvents).noquote().nospace() << showbase
<< __FUNCTION__
<< " message=" << hex << msg.message
<< " count=" << dec << count;
+ Qt::TouchPointStates allStates = 0;
+
for (quint32 i = 0; i < count; ++i) {
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaEvents).noquote().nospace() << showbase
@@ -670,7 +467,13 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
<< " flags=" << hex << touchInfo[i].pointerInfo.pointerFlags;
QWindowSystemInterface::TouchPoint touchPoint;
- touchPoint.id = touchInfo[i].pointerInfo.pointerId;
+ const quint32 pointerId = touchInfo[i].pointerInfo.pointerId;
+ int id = m_touchInputIDToTouchPointID.value(pointerId, -1);
+ if (id == -1) {
+ id = m_touchInputIDToTouchPointID.size();
+ m_touchInputIDToTouchPointID.insert(pointerId, id);
+ }
+ touchPoint.id = id;
touchPoint.pressure = (touchInfo[i].touchMask & TOUCH_MASK_PRESSURE) ?
touchInfo[i].pressure / 1024.0 : 1.0;
if (m_lastTouchPositions.contains(touchPoint.id))
@@ -691,32 +494,27 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_DOWN) {
touchPoint.state = Qt::TouchPointPressed;
m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition);
- pressRelease = true;
} else if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_UP) {
touchPoint.state = Qt::TouchPointReleased;
m_lastTouchPositions.remove(touchPoint.id);
- pressRelease = true;
} else {
touchPoint.state = stationaryTouchPoint ? Qt::TouchPointStationary : Qt::TouchPointMoved;
m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition);
}
- if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY)
- primaryPointer = true;
+ allStates |= touchPoint.state;
touchPoints.append(touchPoint);
// Avoid getting repeated messages for this frame if there are multiple pointerIds
QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
}
- if (primaryPointer && !pressRelease) {
- // Postpone event delivery to avoid hanging inside DoDragDrop().
- // Only the primary pointer will generate mouse messages.
- enqueueTouchEvent(window, touchPoints, QWindowsKeyMapper::queryKeyboardModifiers());
- } else {
- flushTouchEvents(m_touchDevice);
- QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints,
- QWindowsKeyMapper::queryKeyboardModifiers());
- }
+
+ // all touch points released, forget the ids we've seen.
+ if (allStates == Qt::TouchPointReleased)
+ m_touchInputIDToTouchPointID.clear();
+
+ QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints,
+ QWindowsKeyMapper::queryKeyboardModifiers());
return false; // Allow mouse messages to be generated.
}
@@ -807,10 +605,9 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
}
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
- // Postpone event delivery to avoid hanging inside DoDragDrop().
- enqueueTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons,
- pressure, xTilt, yTilt, tangentialPressure, rotation, z,
- pointerId, keyModifiers);
+ QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons,
+ pressure, xTilt, yTilt, tangentialPressure, rotation, z,
+ pointerId, keyModifiers);
return false; // Allow mouse messages to be generated.
}
}
@@ -835,18 +632,46 @@ static inline bool isMouseEventSynthesizedFromPenOrTouch()
return ((::GetMessageExtraInfo() & SIGNATURE_MASK) == MI_WP_SIGNATURE);
}
-// Process old-style mouse messages here.
-bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
+bool QWindowsPointerHandler::translateMouseWheelEvent(QWindow *window,
+ QWindow *currentWindowUnderPointer,
+ MSG msg,
+ QPoint globalPos,
+ Qt::KeyboardModifiers keyModifiers)
{
- // Generate enqueued events.
- flushTouchEvents(m_touchDevice);
- flushTabletEvents();
+ QWindow *receiver = currentWindowUnderPointer;
+ if (!isValidWheelReceiver(receiver))
+ receiver = window;
+ if (!isValidWheelReceiver(receiver))
+ return true;
+
+ int delta = GET_WHEEL_DELTA_WPARAM(msg.wParam);
+ // Qt horizontal wheel rotation orientation is opposite to the one in WM_MOUSEHWHEEL
+ if (msg.message == WM_MOUSEHWHEEL)
+ delta = -delta;
+
+ const QPoint angleDelta = (msg.message == WM_MOUSEHWHEEL || (keyModifiers & Qt::AltModifier)) ?
+ QPoint(delta, 0) : QPoint(0, delta);
+
+ QPoint localPos = QWindowsGeometryHint::mapFromGlobal(receiver, globalPos);
+
+ QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers);
+ return true;
+}
+
+// Process legacy mouse messages here.
+bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
+ HWND hwnd,
+ QtWindows::WindowsEventType et,
+ MSG msg,
+ LRESULT *result)
+{
*result = 0;
const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
QPoint localPos;
QPoint globalPos;
+
if ((et == QtWindows::MouseWheelEvent) || (et & QtWindows::NonClientEventFlag)) {
globalPos = eventPos;
localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, eventPos);
@@ -857,46 +682,39 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
+ QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
- // Handle "press and hold for right-clicking".
- // We have to synthesize it here as it only comes from Windows as a fake RMB.
- // MS docs say we could use bit 7 from extraInfo to distinguish pen from touch,
- // but on the Surface it is set for both. So we use the last pointer type.
- if (isMouseEventSynthesizedFromPenOrTouch()) {
- if ((msg.message == WM_RBUTTONDOWN || msg.message == WM_RBUTTONUP)
- && (((m_lastPointerType == QT_PT_PEN)
- && QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents))
- || ((m_lastPointerType == QT_PT_TOUCH)
- && QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)))) {
- QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, Qt::RightButton,
- (msg.message == WM_RBUTTONDOWN) ? QEvent::MouseButtonPress
- : QEvent::MouseButtonRelease,
- keyModifiers, Qt::MouseEventSynthesizedBySystem);
- }
- // Messages synthesized from touch/pen are only used for flushing queues and press&hold.
- return false;
+ if (et == QtWindows::MouseWheelEvent)
+ return translateMouseWheelEvent(window, currentWindowUnderPointer, msg, globalPos, keyModifiers);
+
+ // Windows sends a mouse move with no buttons pressed to signal "Enter"
+ // when a window is shown over the cursor. Discard the event and only use
+ // it for generating QEvent::Enter to be consistent with other platforms -
+ // X11 and macOS.
+ bool discardEvent = false;
+ if (msg.message == WM_MOUSEMOVE) {
+ static QPoint lastMouseMovePos;
+ if (msg.wParam == 0 && (m_windowUnderPointer.isNull() || globalPos == lastMouseMovePos))
+ discardEvent = true;
+ lastMouseMovePos = globalPos;
}
- if (et == QtWindows::MouseWheelEvent) {
-
- if (!isValidWheelReceiver(window))
- return true;
-
- int delta = GET_WHEEL_DELTA_WPARAM(msg.wParam);
-
- // Qt horizontal wheel rotation orientation is opposite to the one in WM_MOUSEHWHEEL
- if (msg.message == WM_MOUSEHWHEEL)
- delta = -delta;
+ Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
+ if (isMouseEventSynthesizedFromPenOrTouch()) {
+ if (QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)
+ return false;
+ source = Qt::MouseEventSynthesizedBySystem;
+ }
- const QPoint angleDelta = (msg.message == WM_MOUSEHWHEEL || (keyModifiers & Qt::AltModifier)) ?
- QPoint(delta, 0) : QPoint(0, delta);
+ const MouseEvent mouseEvent = eventFromMsg(msg);
- QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers);
- return true;
+ if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) {
+ QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons,
+ mouseEvent.button, mouseEvent.type, keyModifiers, source);
+ return false; // Allow further event processing
}
if (msg.message == WM_MOUSELEAVE) {
-
if (window == m_currentWindow) {
QWindow *leaveTarget = m_windowUnderPointer ? m_windowUnderPointer : m_currentWindow;
qCDebug(lcQpaEvents) << "Leaving window " << leaveTarget;
@@ -904,14 +722,21 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW
m_windowUnderPointer = nullptr;
m_currentWindow = nullptr;
}
+ return true;
+ }
- } else if (msg.message == WM_MOUSEMOVE) {
+ handleCaptureRelease(window, currentWindowUnderPointer, hwnd, mouseEvent.type, mouseButtons);
+ handleEnterLeave(window, currentWindowUnderPointer, globalPos);
- QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
- handleCaptureRelease(window, currentWindowUnderPointer, hwnd, QEvent::MouseMove, mouseButtons);
- handleEnterLeave(window, currentWindowUnderPointer, globalPos);
+ if (!discardEvent && mouseEvent.type != QEvent::None) {
+ QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons,
+ mouseEvent.button, mouseEvent.type, keyModifiers, source);
}
- return false;
+
+ // QTBUG-48117, force synchronous handling for the extra buttons so that WM_APPCOMMAND
+ // is sent for unhandled WM_XBUTTONDOWN.
+ return (msg.message != WM_XBUTTONUP && msg.message != WM_XBUTTONDOWN && msg.message != WM_XBUTTONDBLCLK)
+ || QWindowSystemInterface::flushWindowSystemEvents();
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h
index ec3179e821..aebef062bc 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.h
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -66,19 +66,19 @@ public:
void clearWindowUnderMouse() { m_windowUnderPointer = nullptr; }
private:
- bool translateMouseTouchPadEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPointerInfo);
bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count);
bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo);
+ bool translateMouseWheelEvent(QWindow *window, QWindow *currentWindowUnderPointer, MSG msg, QPoint globalPos, Qt::KeyboardModifiers keyModifiers);
void handleCaptureRelease(QWindow *window, QWindow *currentWindowUnderPointer, HWND hwnd, QEvent::Type eventType, Qt::MouseButtons mouseButtons);
void handleEnterLeave(QWindow *window, QWindow *currentWindowUnderPointer, QPoint globalPos);
QTouchDevice *m_touchDevice = nullptr;
QHash<int, QPointF> m_lastTouchPositions;
+ QHash<DWORD, int> m_touchInputIDToTouchPointID;
QPointer<QWindow> m_windowUnderPointer;
QPointer<QWindow> m_currentWindow;
QWindow *m_previousCaptureWindow = nullptr;
bool m_needsEnterOnPointerUpdate = false;
- DWORD m_lastPointerType = 0;
};
QT_END_NAMESPACE