From 8ba59441fc62c567b1e8dadce5f6e044caa67e49 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 16 Oct 2020 11:26:54 +0200 Subject: Windows QPA/WmPointer: Register tablet devices of pointer handler Task-number: QTBUG-46412 Change-Id: Ib9b5fd6056a5474ce46c7bde53be7a12c1494611 Reviewed-by: Oliver Wolff Reviewed-by: Shawn Rutledge --- .../platforms/windows/qwindowspointerhandler.cpp | 68 +++++++++++++++++----- .../platforms/windows/qwindowspointerhandler.h | 9 +++ 2 files changed, 64 insertions(+), 13 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index 095aea2b95..41f17f5c3b 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -45,6 +45,9 @@ #endif #include "qwindowspointerhandler.h" +#if QT_CONFIG(tabletevent) +# include "qwindowstabletsupport.h" +#endif #include "qwindowskeymapper.h" #include "qwindowscontext.h" #include "qwindowswindow.h" @@ -552,6 +555,17 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, return false; // Allow mouse messages to be generated. } +#if QT_CONFIG(tabletevent) +QWindowsPointerHandler::QPointingDevicePtr QWindowsPointerHandler::findTabletDevice(QPointingDevice::PointerType pointerType) const +{ + for (const auto &d : m_tabletDevices) { + if (d->pointerType() == pointerType) + return d; + } + return {}; +} +#endif + bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo) { @@ -565,28 +579,31 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect)) return false; - const auto sourceDevice = (qint64)penInfo->pointerInfo.sourceDevice; + const auto systemId = (qint64)penInfo->pointerInfo.sourceDevice; const QPoint globalPos = QPoint(penInfo->pointerInfo.ptPixelLocation.x, penInfo->pointerInfo.ptPixelLocation.y); const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos); const QPointF hiResGlobalPos = QPointF(dRect.left + qreal(penInfo->pointerInfo.ptHimetricLocation.x - pRect.left) / (pRect.right - pRect.left) * (dRect.right - dRect.left), dRect.top + qreal(penInfo->pointerInfo.ptHimetricLocation.y - pRect.top) / (pRect.bottom - pRect.top) * (dRect.bottom - dRect.top)); - const qreal pressure = (penInfo->penMask & PEN_MASK_PRESSURE) ? qreal(penInfo->pressure) / 1024.0 : 0.5; - const qreal rotation = (penInfo->penMask & PEN_MASK_ROTATION) ? qreal(penInfo->rotation) : 0.0; + const bool hasPressure = (penInfo->penMask & PEN_MASK_PRESSURE) != 0; + const bool hasRotation = (penInfo->penMask & PEN_MASK_ROTATION) != 0; + const qreal pressure = hasPressure ? qreal(penInfo->pressure) / 1024.0 : 0.5; + const qreal rotation = hasRotation ? qreal(penInfo->rotation) : 0.0; const qreal tangentialPressure = 0.0; - const int xTilt = (penInfo->penMask & PEN_MASK_TILT_X) ? penInfo->tiltX : 0; - const int yTilt = (penInfo->penMask & PEN_MASK_TILT_Y) ? penInfo->tiltY : 0; + const bool hasTiltX = (penInfo->penMask & PEN_MASK_TILT_X) != 0; + const bool hasTiltY = (penInfo->penMask & PEN_MASK_TILT_Y) != 0; + const int xTilt = hasTiltX ? penInfo->tiltX : 0; + const int yTilt = hasTiltY ? penInfo->tiltY : 0; const int z = 0; if (QWindowsContext::verbose > 1) qCDebug(lcQpaEvents).noquote().nospace() << Qt::showbase - << __FUNCTION__ << " sourceDevice=" << sourceDevice + << __FUNCTION__ << " systemId=" << systemId << " globalPos=" << globalPos << " localPos=" << localPos << " hiResGlobalPos=" << hiResGlobalPos << " message=" << Qt::hex << msg.message << " flags=" << Qt::hex << penInfo->pointerInfo.pointerFlags; - const QInputDevice::DeviceType device = QInputDevice::DeviceType::Stylus; QPointingDevice::PointerType type; // Since it may be the middle button, so if the checks fail then it should // be set to Middle if it was used. @@ -604,9 +621,33 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin mouseButtons = Qt::RightButton; // Either left or right, not both } + auto device = findTabletDevice(type); + if (device.isNull()) { + QInputDevice::Capabilities caps(QInputDevice::Capability::Position + | QInputDevice::Capability::MouseEmulation + | QInputDevice::Capability::Hover); + if (hasPressure) + caps |= QInputDevice::Capability::Pressure; + if (hasRotation) + caps |= QInputDevice::Capability::Rotation; + if (hasTiltX) + caps |= QInputDevice::Capability::XTilt; + if (hasTiltY) + caps |= QInputDevice::Capability::YTilt; + const qint64 uniqueId = systemId | (qint64(type) << 32L); + device.reset(new QPointingDevice(QStringLiteral("wmpointer"), + systemId, QInputDevice::DeviceType::Stylus, + type, caps, 1, 3, QString(), + QPointingDeviceUniqueId::fromNumericId(uniqueId))); + QWindowSystemInterface::registerInputDevice(device.data()); + m_tabletDevices.append(device); + } + + const auto uniqueId = device->uniqueId().numericId(); + switch (msg.message) { case WM_POINTERENTER: { - QWindowSystemInterface::handleTabletEnterProximityEvent(int(device), int(type), sourceDevice); + QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(window, device.data(), true); m_windowUnderPointer = window; // The local coordinates may fall outside the window. // Wait until the next update to send the enter event. @@ -619,12 +660,12 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin m_windowUnderPointer = nullptr; m_currentWindow = nullptr; } - QWindowSystemInterface::handleTabletLeaveProximityEvent(int(device), int(type), sourceDevice); + QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(window, device.data(), false); break; case WM_POINTERDOWN: case WM_POINTERUP: case WM_POINTERUPDATE: { - QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(sourceDevice).target; // Pass to window that grabbed it. + QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(uniqueId).target; // Pass to window that grabbed it. if (!target && m_windowUnderPointer) target = m_windowUnderPointer; if (!target) @@ -644,9 +685,10 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin } const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); - QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, int(device), int(type), mouseButtons, - pressure, xTilt, yTilt, tangentialPressure, rotation, z, - sourceDevice, keyModifiers); + QWindowSystemInterface::handleTabletEvent(target, device.data(), + localPos, hiResGlobalPos, mouseButtons, + pressure, xTilt, yTilt, tangentialPressure, + rotation, z, keyModifiers); return false; // Allow mouse messages to be generated. } } diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h index 3b204c675b..d0f0b816d3 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.h +++ b/src/plugins/platforms/windows/qwindowspointerhandler.h @@ -45,6 +45,7 @@ #include #include +#include #include #include @@ -57,6 +58,8 @@ class QWindowsPointerHandler { Q_DISABLE_COPY_MOVE(QWindowsPointerHandler) public: + using QPointingDevicePtr = QSharedPointer; + QWindowsPointerHandler() = default; ~QWindowsPointerHandler(); bool translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result); @@ -76,8 +79,14 @@ private: bool translateMouseWheelEvent(QWindow *window, QWindow *currentWindowUnderPointer, MSG msg, QPoint globalPos, Qt::KeyboardModifiers keyModifiers); void handleCaptureRelease(QWindow *window, QWindow *currentWindowUnderPointer, HWND hwnd, QEvent::Type eventType, Qt::MouseButtons mouseButtons); void handleEnterLeave(QWindow *window, QWindow *currentWindowUnderPointer, QPoint globalPos); +#if QT_CONFIG(tabletevent) + QPointingDevicePtr findTabletDevice(QPointingDevice::PointerType pointerType) const; +#endif QPointingDevice *m_touchDevice = nullptr; +#if QT_CONFIG(tabletevent) + QList m_tabletDevices; +#endif QHash m_lastTouchPositions; QHash m_touchInputIDToTouchPointID; QPointer m_windowUnderPointer; -- cgit v1.2.3