summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows
diff options
context:
space:
mode:
authorRomain Pokrzywka <romain.pokrzywka@bluescape.com>2018-08-22 11:31:34 -0500
committerRomain Pokrzywka <romain.pokrzywka@gmail.com>2018-08-30 04:47:04 +0000
commitd02f888417c144963c929512f5cb3a0178af9fb4 (patch)
treeded4a5d3c5e8b31922b66f9e22670d41fd1aebfa /src/plugins/platforms/windows
parent81e298a51d08c510457b4a26b37c0d4aac5eba65 (diff)
Windows QPA: Fix duplicate Pointer Touch events and missing TouchCancel
translateTouchEvent needs to filter events based on the message type passed in msg, as Windows sends more than just down/up/update events, it also sends enter/leave for each touch and occasionally a few more. One of them is WM_POINTERCAPTURECHANGED which indicates a general loss of touch input, which needs to be translated to a touch cancel event. Ignore WM_POINTERENTER/WM_POINTERLEAVE events as they result in sending duplicate Qt::TouchPointPressed/Qt::TouchPointReleased events otherwise. Also avoid sending duplicate events for each additional touchpoint: Windows already bundles all available touchpoints for a touch event when calling GetPointerFrameTouchInfo, so we get all points at once, but we'll still receive other events for each additional touchpoint, resulting in reading the same bundled data again for each one and sending duplicate events to QWindowSystemInterface. Use SkipPointerFrameMessages() to avoid receiving the additional events for the frame we just processed. Finally, add raw event logging when the platform verbose level is >1. Change-Id: I55d840285f642a00f6ffcda4a3efd7ae3985310b Reviewed-by: Andre de la Rocha <andre.rocha@qt.io>
Diffstat (limited to 'src/plugins/platforms/windows')
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h1
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h2
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp25
4 files changed, 31 insertions, 1 deletions
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index ef22a4451a..985f13bdc5 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -71,6 +71,7 @@
# define WM_POINTERENTER 0x0249
# define WM_POINTERLEAVE 0x024A
# define WM_POINTERACTIVATE 0x024B
+# define WM_POINTERCAPTURECHANGED 0x024C
# define WM_POINTERWHEEL 0x024E
# define WM_POINTERHWHEEL 0x024F
#endif // WM_POINTERUPDATE
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 0df6264bcb..aa85b2edbe 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -201,6 +201,7 @@ void QWindowsUser32DLL::init()
getPointerTouchInfo = (GetPointerTouchInfo)library.resolve("GetPointerTouchInfo");
getPointerFrameTouchInfo = (GetPointerFrameTouchInfo)library.resolve("GetPointerFrameTouchInfo");
getPointerPenInfo = (GetPointerPenInfo)library.resolve("GetPointerPenInfo");
+ skipPointerFrameMessages = (SkipPointerFrameMessages)library.resolve("SkipPointerFrameMessages");
}
if (QOperatingSystemVersion::current()
@@ -214,7 +215,8 @@ void QWindowsUser32DLL::init()
bool QWindowsUser32DLL::supportsPointerApi()
{
return enableMouseInPointer && getPointerType && getPointerInfo && getPointerDeviceRects
- && getPointerTouchInfo && getPointerFrameTouchInfo && getPointerPenInfo;
+ && getPointerTouchInfo && getPointerFrameTouchInfo && getPointerPenInfo
+ && skipPointerFrameMessages;
}
void QWindowsShcoreDLL::init()
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index 33bd42a669..8102e0bf19 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -93,6 +93,7 @@ struct QWindowsUser32DLL
typedef BOOL (WINAPI *GetPointerTouchInfo)(UINT32, PVOID);
typedef BOOL (WINAPI *GetPointerFrameTouchInfo)(UINT32, UINT32 *, PVOID);
typedef BOOL (WINAPI *GetPointerPenInfo)(UINT32, PVOID);
+ typedef BOOL (WINAPI *SkipPointerFrameMessages)(UINT32);
typedef BOOL (WINAPI *SetProcessDPIAware)();
typedef BOOL (WINAPI *AddClipboardFormatListener)(HWND);
typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
@@ -110,6 +111,7 @@ struct QWindowsUser32DLL
GetPointerTouchInfo getPointerTouchInfo = nullptr;
GetPointerFrameTouchInfo getPointerFrameTouchInfo = nullptr;
GetPointerPenInfo getPointerPenInfo = nullptr;
+ SkipPointerFrameMessages skipPointerFrameMessages = nullptr;
// Windows Vista onwards
SetProcessDPIAware setProcessDPIAware = nullptr;
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index abd4d56da0..af9048828f 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -354,6 +354,17 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
if (count < 1)
return false;
+ if (msg.message == WM_POINTERCAPTURECHANGED) {
+ QWindowSystemInterface::handleTouchCancelEvent(window, m_touchDevice,
+ QWindowsKeyMapper::queryKeyboardModifiers());
+ m_lastTouchPositions.clear();
+ return true;
+ }
+
+ // Only handle down/up/update, ignore others like WM_POINTERENTER, WM_POINTERLEAVE, etc.
+ if (msg.message > WM_POINTERUP)
+ return false;
+
const QScreen *screen = window->screen();
if (!screen)
screen = QGuiApplication::primaryScreen();
@@ -366,7 +377,18 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
QList<QWindowSystemInterface::TouchPoint> touchPoints;
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaEvents).noquote().nospace() << showbase
+ << __FUNCTION__
+ << " message=" << hex << msg.message
+ << " count=" << dec << count;
+
for (quint32 i = 0; i < count; ++i) {
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaEvents).noquote().nospace() << showbase
+ << " TouchPoint id=" << touchInfo[i].pointerInfo.pointerId
+ << " frame=" << touchInfo[i].pointerInfo.frameId
+ << " flags=" << hex << touchInfo[i].pointerInfo.pointerFlags;
QWindowSystemInterface::TouchPoint touchPoint;
touchPoint.id = touchInfo[i].pointerInfo.pointerId;
@@ -398,6 +420,9 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition);
}
touchPoints.append(touchPoint);
+
+ // Avoid getting repeated messages for this frame if there are multiple pointerIds
+ QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
}
QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints,