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>
This commit is contained in:
parent
81e298a51d
commit
d02f888417
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user