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 <Friedemann.Kleint@theqtcompany.com>
This commit is contained in:
Andreas Holzammer 2015-01-20 13:17:36 +01:00 committed by Björn Breitmeyer
parent 416c099205
commit 2b5df245d6
6 changed files with 100 additions and 3 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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.

View File

@ -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<QWindowSystemInterface::TouchPoint> 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<QWindowSystemInterface::TouchPoint> 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
}

View File

@ -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)

View File

@ -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;