WinRT: Fix multi-touch on PC

The pointer ID was incorrectly interpreted as a device ID, which caused
creating a new QTouchDevice for each touch update and potential crashes
in QtQuick. The handling has now been simplified and aligned with Windows
Phone, treating all touch events as if they originate from the same
device. Given that the native device has no ID, it is not
possible to track the native device between events anyway (even the
pointer values change).

Task-number: QTBUG-38745
Change-Id: I24b6c00b765dcb49cd653638afafc04fdd80f774
Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@digia.com>
This commit is contained in:
Andrew Knight 2014-05-05 08:41:22 +03:00 committed by The Qt Project
parent 9ae89313e4
commit 3f885939c0
2 changed files with 30 additions and 58 deletions

View File

@ -425,17 +425,8 @@ QWinRTScreen::QWinRTScreen(ICoreWindow *window)
#endif
, m_cursor(new QWinRTCursor(window))
, m_orientation(Qt::PrimaryOrientation)
, m_touchDevice(Q_NULLPTR)
{
#ifdef Q_OS_WINPHONE // On phone, there can be only one touch device
QTouchDevice *touchDevice = new QTouchDevice;
touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure);
touchDevice->setType(QTouchDevice::TouchScreen);
touchDevice->setName(QStringLiteral("WinPhoneTouchScreen"));
Pointer pointer = { Pointer::TouchScreen, touchDevice };
m_pointers.insert(0, pointer);
QWindowSystemInterface::registerTouchDevice(touchDevice);
#endif
Rect rect;
window->get_Bounds(&rect);
m_geometry = QRect(0, 0, rect.Width, rect.Height);
@ -762,47 +753,25 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
if (FAILED(pointerPoint->get_Properties(&properties)))
return E_INVALIDARG;
#ifdef Q_OS_WINPHONE
quint32 pointerId = 0;
Pointer pointer = m_pointers.value(pointerId);
PointerDeviceType pointerDeviceType;
#if defined(Q_OS_WINPHONE) && _MSC_VER <= 1700
pointerDeviceType = PointerDeviceType_Touch;
#else
Pointer pointer = { Pointer::Unknown, 0 };
quint32 pointerId;
pointerPoint->get_PointerId(&pointerId);
if (m_pointers.contains(pointerId)) {
pointer = m_pointers.value(pointerId);
} else { // We have not yet enumerated this device. Do so now...
IPointerDevice *device;
if (SUCCEEDED(pointerPoint->get_PointerDevice(&device))) {
PointerDeviceType type;
device->get_PointerDeviceType(&type);
switch (type) {
case PointerDeviceType_Touch:
pointer.type = Pointer::TouchScreen;
pointer.device = new QTouchDevice;
pointer.device->setName(QStringLiteral("WinRT TouchScreen ") + QString::number(pointerId));
// TODO: We may want to probe the device usage flags for more accurate values for these next two
pointer.device->setType(QTouchDevice::TouchScreen);
pointer.device->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure);
QWindowSystemInterface::registerTouchDevice(pointer.device);
break;
case PointerDeviceType_Pen:
pointer.type = Pointer::Tablet;
break;
case PointerDeviceType_Mouse:
pointer.type = Pointer::Mouse;
break;
ComPtr<IPointerDevice> pointerDevice;
HRESULT hr = pointerPoint->get_PointerDevice(&pointerDevice);
if (FAILED(hr)) {
qErrnoWarning(hr, "Failed to get pointer device.");
return S_OK;
}
m_pointers.insert(pointerId, pointer);
device->Release();
}
hr = pointerDevice->get_PointerDeviceType(&pointerDeviceType);
if (FAILED(hr)) {
qErrnoWarning(hr, "Failed to get pointer device type.");
return S_OK;
}
#endif
switch (pointer.type) {
case Pointer::Mouse: {
switch (pointerDeviceType) {
case PointerDeviceType_Mouse: {
qint32 delta;
properties->get_MouseWheelDelta(&delta);
if (delta) {
@ -839,7 +808,15 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
break;
}
case Pointer::TouchScreen: {
case PointerDeviceType_Touch: {
if (!m_touchDevice) {
m_touchDevice = new QTouchDevice;
m_touchDevice->setName(QStringLiteral("WinRTTouchScreen"));
m_touchDevice->setType(QTouchDevice::TouchScreen);
m_touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure | QTouchDevice::NormalizedPosition);
QWindowSystemInterface::registerTouchDevice(m_touchDevice);
}
quint32 id;
pointerPoint->get_PointerId(&id);
@ -867,7 +844,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
it.value().normalPosition = QPointF(pos.x()/m_geometry.width(), pos.y()/m_geometry.height());
it.value().pressure = pressure;
QWindowSystemInterface::handleTouchEvent(topWindow(), pointer.device, m_touchPoints.values(), mods);
QWindowSystemInterface::handleTouchEvent(topWindow(), m_touchDevice, m_touchPoints.values(), mods);
// Remove released points, station others
for (QHash<quint32, QWindowSystemInterface::TouchPoint>::iterator i = m_touchPoints.begin(); i != m_touchPoints.end();) {
@ -879,7 +856,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
break;
}
case Pointer::Tablet: {
case PointerDeviceType_Pen: {
quint32 id;
pointerPoint->get_PointerId(&id);
@ -902,7 +879,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
float rotation;
properties->get_Twist(&rotation);
QWindowSystemInterface::handleTabletEvent(topWindow(), isPressed, pos, pos, pointerId,
QWindowSystemInterface::handleTabletEvent(topWindow(), isPressed, pos, pos, 0,
pointerType, pressure, xTilt, yTilt,
0, rotation, 0, id, mods);

View File

@ -101,12 +101,6 @@ class QWinRTPageFlipper;
class QWinRTCursor;
class QWinRTInputContext;
struct Pointer {
enum Type { Unknown, Mouse, TouchScreen, Tablet };
Type type;
QTouchDevice *device;
};
class QWinRTScreen : public QPlatformScreen
{
public:
@ -165,6 +159,7 @@ private:
ABI::Windows::UI::Core::ICoreWindow *m_coreWindow;
ABI::Windows::UI::ViewManagement::IApplicationViewStatics *m_applicationView;
ABI::Windows::ApplicationModel::Core::ICoreApplication *m_application;
QRect m_geometry;
QImage::Format m_format;
QSurfaceFormat m_surfaceFormat;
@ -183,7 +178,7 @@ private:
#ifndef Q_OS_WINPHONE
QHash<quint32, QPair<Qt::Key, QString> > m_activeKeys;
#endif
QHash<quint32, Pointer> m_pointers;
QTouchDevice *m_touchDevice;
QHash<quint32, QWindowSystemInterface::TouchPoint> m_touchPoints;
};