From 2b5df245d6cdbfb3150ee815debccf655af8f19f Mon Sep 17 00:00:00 2001 From: Andreas Holzammer Date: Tue, 20 Jan 2015 13:17:36 +0100 Subject: Implement Multitouch handling for WinCE Implemented handling of GID_DirectManipulation for WinCE. Derive touch information out of gesture event directmanipulation. Task-number: QTBUG-31216 Change-Id: I74e90f32d2384fc3550b47af0b72edf0292dea8f Reviewed-by: Friedemann Kleint --- .../platforms/windows/qtwindows_additional.h | 4 + src/plugins/platforms/windows/qtwindowsglobal.h | 3 + src/plugins/platforms/windows/qwindowscontext.cpp | 2 + .../platforms/windows/qwindowsmousehandler.cpp | 86 +++++++++++++++++++++- .../platforms/windows/qwindowsmousehandler.h | 4 + src/plugins/platforms/windows/qwindowswindow.cpp | 4 + 6 files changed, 100 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/windows/qtwindows_additional.h b/src/plugins/platforms/windows/qtwindows_additional.h index 9451b9ce55..4e77350132 100644 --- a/src/plugins/platforms/windows/qtwindows_additional.h +++ b/src/plugins/platforms/windows/qtwindows_additional.h @@ -166,4 +166,8 @@ typedef TOUCHINPUT const * PCTOUCHINPUT; #endif // if defined(Q_CC_MINGW) || !defined(TOUCHEVENTF_MOVE) +#ifndef WM_GESTURE +# define WM_GESTURE 0x0119 +#endif + #endif // QTWINDOWS_ADDITIONAL_H diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h index 90e6d6ab9d..083d82ed8c 100644 --- a/src/plugins/platforms/windows/qtwindowsglobal.h +++ b/src/plugins/platforms/windows/qtwindowsglobal.h @@ -109,6 +109,7 @@ enum WindowsEventType // Simplify event types DisplayChangedEvent = 437, SettingChangedEvent = DisplayChangedEvent + 1, ContextMenu = 123, + GestureEvent = 124, UnknownEvent = 542 }; @@ -247,6 +248,8 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI case WM_APPCOMMAND: return QtWindows::AppCommandEvent; #endif + case WM_GESTURE: + return QtWindows::GestureEvent; default: break; } diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 2dab4f699f..1cc596ca8d 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -905,6 +905,8 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return QWindowsInputContext::instance()->endComposition(hwnd); case QtWindows::InputMethodRequest: return QWindowsInputContext::instance()->handleIME_Request(wParam, lParam, result); + case QtWindows::GestureEvent: + return d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result); case QtWindows::InputMethodOpenCandidateWindowEvent: case QtWindows::InputMethodCloseCandidateWindowEvent: // TODO: Release/regrab mouse if a popup has mouse grab. diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index acb692579b..0fa34041d6 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -422,11 +422,12 @@ bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND, } // from bool QApplicationPrivate::translateTouchEvent() -bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, +bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType, MSG msg, LRESULT *) { #ifndef Q_OS_WINCE + Q_UNUSED(hwnd); typedef QWindowSystemInterface::TouchPoint QTouchPoint; typedef QList QTouchPointList; @@ -495,8 +496,87 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, m_touchDevice, touchPoints); return true; -#else - return false; +#else //Q_OS_WINCE + GESTUREINFO gi; + memset(&gi, 0, sizeof(GESTUREINFO)); + gi.cbSize = sizeof(GESTUREINFO); + + if (!GetGestureInfo((HGESTUREINFO)msg.lParam, &gi)) + return false; + + const QPoint position = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); + + if (gi.dwID != GID_DIRECTMANIPULATION) + return true; + static QPoint lastTouchPos; + const QRect screenGeometry = window->screen()->geometry(); + QWindowSystemInterface::TouchPoint touchPoint; + static QWindowSystemInterface::TouchPoint touchPoint2; + touchPoint.id = 0;//gi.dwInstanceID; + touchPoint.pressure = 1.0; + + if (gi.dwFlags & GF_BEGIN) + touchPoint.state = Qt::TouchPointPressed; + else if (gi.dwFlags & GF_END) + touchPoint.state = Qt::TouchPointReleased; + else if (gi.dwFlags == 0) + touchPoint.state = Qt::TouchPointMoved; + else + return true; + touchPoint2.pressure = 1.0; + touchPoint2.id = 1; + const QPoint winEventPosition = position; + const int deltaX = GID_DIRECTMANIPULATION_DELTA_X(gi.ullArguments); + const int deltaY = GID_DIRECTMANIPULATION_DELTA_Y(gi.ullArguments); + //Touch points are taken from the whole screen so map the position to the screen + const QPoint globalPosition = QWindowsGeometryHint::mapToGlobal(hwnd, winEventPosition); + const QPoint globalPosition2 = QWindowsGeometryHint::mapToGlobal(hwnd, QPoint(position.x() + deltaX, position.y() + deltaY)); + + touchPoint.normalPosition = + QPointF( (qreal)globalPosition.x() / screenGeometry.width(), (qreal)globalPosition.y() / screenGeometry.height() ); + + touchPoint.area.moveCenter(globalPosition); + + QList pointList; + pointList.append(touchPoint); + if (deltaX != 0 && deltaY != 0) { + touchPoint2.state = m_had2ndTouchPoint ? Qt::TouchPointMoved : Qt::TouchPointPressed; + m_had2ndTouchPoint = true; + touchPoint2.normalPosition = + QPointF( (qreal)globalPosition2.x() / screenGeometry.width(), (qreal)globalPosition2.y() / screenGeometry.height() ); + + touchPoint2.area.moveCenter(globalPosition2); + lastTouchPos = globalPosition2; + pointList.append(touchPoint2); + } else if (m_had2ndTouchPoint) { + touchPoint2.normalPosition = + QPointF( (qreal)lastTouchPos.x() / screenGeometry.width(), (qreal)lastTouchPos.y() / screenGeometry.height() ); + + touchPoint2.area.moveCenter(lastTouchPos); + touchPoint2.state = Qt::TouchPointReleased; + pointList.append(touchPoint2); + m_had2ndTouchPoint = false; + } + + if (!m_touchDevice) { + m_touchDevice = new QTouchDevice; + // TODO: Device used to be hardcoded to screen in previous code. + m_touchDevice->setType(QTouchDevice::TouchScreen); + m_touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition); + QWindowSystemInterface::registerTouchDevice(m_touchDevice); + } + + QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, pointList); + // handle window focusing in/out + if (window != m_windowUnderMouse) { + if (m_windowUnderMouse) + QWindowSystemInterface::handleLeaveEvent(m_windowUnderMouse); + if (window) + QWindowSystemInterface::handleEnterEvent(window); + m_windowUnderMouse = window; + } + + return true; #endif } diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h index 6491de93b5..60fe26b2b9 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.h +++ b/src/plugins/platforms/windows/qwindowsmousehandler.h @@ -79,6 +79,10 @@ private: QTouchDevice *m_touchDevice; bool m_leftButtonDown; QWindow *m_previousCaptureWindow; +#ifdef Q_OS_WINCE +//This is required to send a touch up if we don't get a second touch position any more + bool m_had2ndTouchPoint; +#endif }; Qt::MouseButtons QWindowsMouseHandler::keyStateToMouseButtons(int wParam) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index fbb61a1aff..2e5308f157 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -639,6 +639,10 @@ QWindowsWindowData context->frameX, context->frameY, context->frameWidth, context->frameHeight, parentHandle, NULL, appinst, NULL); +#ifdef Q_OS_WINCE + if (DisableGestures(result.hwnd, TGF_GID_ALL, TGF_SCOPE_WINDOW)) + EnableGestures(result.hwnd, TGF_GID_DIRECTMANIPULATION, TGF_SCOPE_WINDOW); +#endif qCDebug(lcQpaWindows).nospace() << "CreateWindowEx: returns " << w << ' ' << result.hwnd << " obtained geometry: " << context->obtainedGeometry << context->margins; -- cgit v1.2.3