From e9a8b026f51d77ccb014c9e8011b081d4100aad4 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 27 Nov 2012 10:11:30 +0100 Subject: Fix touch event handling for Windows Filtering touch events depending on Qt::WA_AcceptTouchEvents is not trivial. I thought about doing so in QWidgetWindow::handleTouchEvent but the target widget (not window), which has to be checked, has to be obtained using the primary touch event's position etc. Thus that is not part of this commit and will be done in a followup. Change-Id: I876ee72acd7fdfbe46da61c6eb3c5891ea319cd8 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowscontext.cpp | 6 +++-- src/plugins/platforms/windows/qwindowscontext.h | 2 ++ .../platforms/windows/qwindowsmousehandler.cpp | 30 +++++++++++++--------- .../platforms/windows/qwindowsmousehandler.h | 1 + src/plugins/platforms/windows/qwindowswindow.cpp | 4 +++ 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index aaa5573899..28269e8653 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -171,7 +171,8 @@ QWindowsUser32DLL::QWindowsUser32DLL() : setLayeredWindowAttributes(0), updateLayeredWindow(0), updateLayeredWindowIndirect(0), isHungAppWindow(0), - registerTouchWindow(0), getTouchInputInfo(0), closeTouchInputHandle(0) + registerTouchWindow(0), unregisterTouchWindow(0), + getTouchInputInfo(0), closeTouchInputHandle(0) { } @@ -192,9 +193,10 @@ bool QWindowsUser32DLL::initTouch() { QSystemLibrary library(QStringLiteral("user32")); registerTouchWindow = (RegisterTouchWindow)(library.resolve("RegisterTouchWindow")); + unregisterTouchWindow = (UnregisterTouchWindow)(library.resolve("UnregisterTouchWindow")); getTouchInputInfo = (GetTouchInputInfo)(library.resolve("GetTouchInputInfo")); closeTouchInputHandle = (CloseTouchInputHandle)(library.resolve("CloseTouchInputHandle")); - return registerTouchWindow && getTouchInputInfo && getTouchInputInfo; + return registerTouchWindow && unregisterTouchWindow && getTouchInputInfo && getTouchInputInfo; } /*! diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 21a846ef97..13e63d19be 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -71,6 +71,7 @@ struct QWindowsUser32DLL inline bool initTouch(); typedef BOOL (WINAPI *RegisterTouchWindow)(HWND, ULONG); + typedef BOOL (WINAPI *UnregisterTouchWindow)(HWND); typedef BOOL (WINAPI *GetTouchInputInfo)(HANDLE, UINT, PVOID, int); typedef BOOL (WINAPI *CloseTouchInputHandle)(HANDLE); typedef BOOL (WINAPI *SetLayeredWindowAttributes)(HWND, COLORREF, BYTE, DWORD); @@ -90,6 +91,7 @@ struct QWindowsUser32DLL // Touch functions from Windows 7 onwards (also for use with Q_CC_MSVC). RegisterTouchWindow registerTouchWindow; + UnregisterTouchWindow unregisterTouchWindow; GetTouchInputInfo getTouchInputInfo; CloseTouchInputHandle closeTouchInputHandle; }; diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index d202da1d31..357def57c8 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -395,34 +395,40 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, QWindowsContext::user32dll.getTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT)); for (int i = 0; i < winTouchPointCount; ++i) { const TOUCHINPUT &winTouchInput = winTouchInputs[i]; + int id = m_touchInputIDToTouchPointID.value(winTouchInput.dwID, -1); + if (id == -1) { + id = m_touchInputIDToTouchPointID.size(); + m_touchInputIDToTouchPointID.insert(winTouchInput.dwID, id); + } QTouchPoint touchPoint; touchPoint.pressure = 1.0; - touchPoint.id = m_touchInputIDToTouchPointID.value(winTouchInput.dwID, -1); - if (touchPoint.id == -1) { - touchPoint.id = m_touchInputIDToTouchPointID.size(); - m_touchInputIDToTouchPointID.insert(winTouchInput.dwID, touchPoint.id); - } + touchPoint.id = id; + if (m_lastTouchPositions.contains(id)) + touchPoint.normalPosition = m_lastTouchPositions.value(id); QPointF screenPos = QPointF(qreal(winTouchInput.x) / qreal(100.), qreal(winTouchInput.y) / qreal(100.)); if (winTouchInput.dwMask & TOUCHINPUTMASKF_CONTACTAREA) touchPoint.area.setSize(QSizeF(qreal(winTouchInput.cxContact) / qreal(100.), qreal(winTouchInput.cyContact) / qreal(100.))); touchPoint.area.moveCenter(screenPos); + QPointF normalPosition = QPointF(screenPos.x() / screenGeometry.width(), + screenPos.y() / screenGeometry.height()); + const bool stationaryTouchPoint = (normalPosition == touchPoint.normalPosition); + touchPoint.normalPosition = normalPosition; if (winTouchInput.dwFlags & TOUCHEVENTF_DOWN) { touchPoint.state = Qt::TouchPointPressed; + m_lastTouchPositions.insert(id, touchPoint.normalPosition); } else if (winTouchInput.dwFlags & TOUCHEVENTF_UP) { touchPoint.state = Qt::TouchPointReleased; + m_lastTouchPositions.remove(id); } else { - // TODO: Previous code checked" - // screenPos == touchPoint.normalPosition -> Qt::TouchPointStationary, but - // but touchPoint.normalPosition was never initialized? - touchPoint.state = touchPoint.state; + touchPoint.state = (stationaryTouchPoint + ? Qt::TouchPointStationary + : Qt::TouchPointMoved); + m_lastTouchPositions.insert(id, touchPoint.normalPosition); } - touchPoint.normalPosition = QPointF(screenPos.x() / screenGeometry.width(), - screenPos.y() / screenGeometry.height()); - allStates |= touchPoint.state; touchPoints.append(touchPoint); diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h index 965deb4e0f..c652f869f1 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.h +++ b/src/plugins/platforms/windows/qwindowsmousehandler.h @@ -80,6 +80,7 @@ private: QPointer m_windowUnderMouse; QPointer m_trackedWindow; QHash m_touchInputIDToTouchPointID; + QHash m_lastTouchPositions; QTouchDevice *m_touchDevice; bool m_leftButtonDown; QWindow *m_previousCaptureWindow; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 123607cd79..1f6253438f 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -728,11 +728,15 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) : break; } } + if (QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch) + QWindowsContext::user32dll.registerTouchWindow(m_data.hwnd, 0); setWindowState(aWindow->windowState()); } QWindowsWindow::~QWindowsWindow() { + if (QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch) + QWindowsContext::user32dll.unregisterTouchWindow(m_data.hwnd); destroyWindow(); destroyIcon(); } -- cgit v1.2.3