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:
parent
9ae89313e4
commit
3f885939c0
@ -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;
|
||||
ComPtr<IPointerDevice> pointerDevice;
|
||||
HRESULT hr = pointerPoint->get_PointerDevice(&pointerDevice);
|
||||
if (FAILED(hr)) {
|
||||
qErrnoWarning(hr, "Failed to get pointer device.");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
case PointerDeviceType_Pen:
|
||||
pointer.type = Pointer::Tablet;
|
||||
break;
|
||||
|
||||
case PointerDeviceType_Mouse:
|
||||
pointer.type = Pointer::Mouse;
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user