From f85e70c569f4aa979004889d20de8acec9a790bf Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 8 Mar 2021 15:56:07 +0100 Subject: xcb: use QXcbScrollingDevice for a touchpad When using XQuartz on macOS, the virtual pointer device is detected as a touchpad, not a mouse; but QXcbConnection::xi2HandleScrollEvent() expects the device to be an instance of QXcbScrollingDevice for storage of some state. A touchpad that has the scrolling capability must be that type, not a plain QPointingDevice. Fixes: QTBUG-91402 Pick-to: 6.1 Change-Id: I1b82766d4a3f87f656e56c0d8904def26fb0979a Reviewed-by: Liang Qi --- src/plugins/platforms/xcb/qxcbconnection.h | 3 ++- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 33 +++++++++++++++++------- 2 files changed, 26 insertions(+), 10 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 1e402a37de..8938d28939 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -79,6 +79,7 @@ class QXcbWindow; class QXcbDrag; class QXcbKeyboard; class QXcbScrollingDevice; +class QXcbScrollingDevicePrivate; class QXcbClipboard; class QXcbWMSupport; class QXcbNativeInterface; @@ -284,7 +285,7 @@ private: QSizeF size; // device size in mm bool providesTouchOrientation = false; }; - TouchDeviceData *populateTouchDevices(void *info); + TouchDeviceData *populateTouchDevices(void *info, QXcbScrollingDevicePrivate *scrollingDeviceP); TouchDeviceData *touchDeviceForId(int id); void xi2HandleEvent(xcb_ge_event_t *event); void xi2HandleHierarchyEvent(void *event); diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 5c455cf296..1f45f6dc80 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -291,12 +291,12 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting, auto *sci = reinterpret_cast(classinfo); if (sci->scroll_type == XCB_INPUT_SCROLL_TYPE_VERTICAL) { auto dev = scrollingDevice(); - dev->orientations |= Qt::Vertical; + dev->orientations.setFlag(Qt::Vertical); dev->verticalIndex = sci->number; dev->verticalIncrement = fixed3232ToReal(sci->increment); } else if (sci->scroll_type == XCB_INPUT_SCROLL_TYPE_HORIZONTAL) { auto dev = scrollingDevice(); - dev->orientations |= Qt::Horizontal; + dev->orientations.setFlag(Qt::Horizontal); dev->horizontalIndex = sci->number; dev->horizontalIncrement = fixed3232ToReal(sci->increment); } @@ -412,7 +412,7 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting, } if (!isTablet) { - TouchDeviceData *dev = populateTouchDevices(deviceInfo); + TouchDeviceData *dev = populateTouchDevices(deviceInfo, scrollingDeviceP); if (dev && lcQpaXInputDevices().isDebugEnabled()) { if (dev->qtTouchDevice->type() == QInputDevice::DeviceType::TouchScreen) qCDebug(lcQpaXInputDevices, " it's a touchscreen with type %d capabilities 0x%X max touch points %d", @@ -521,7 +521,7 @@ QXcbConnection::TouchDeviceData *QXcbConnection::touchDeviceForId(int id) return dev; } -QXcbConnection::TouchDeviceData *QXcbConnection::populateTouchDevices(void *info) +QXcbConnection::TouchDeviceData *QXcbConnection::populateTouchDevices(void *info, QXcbScrollingDevicePrivate *scrollingDeviceP) { auto *deviceInfo = reinterpret_cast(info); QPointingDevice::Capabilities caps; @@ -582,6 +582,8 @@ QXcbConnection::TouchDeviceData *QXcbConnection::populateTouchDevices(void *info } else if (valuatorAtom == QXcbAtom::AbsY) { caps |= QInputDevice::Capability::Position; dev.size.setHeight((fixed3232ToReal(vci->max) - fixed3232ToReal(vci->min)) * 1000.0 / vciResolution); + } else if (valuatorAtom == QXcbAtom::RelVertWheel || valuatorAtom == QXcbAtom::RelHorizWheel) { + caps |= QInputDevice::Capability::Scroll; } break; } @@ -601,11 +603,24 @@ QXcbConnection::TouchDeviceData *QXcbConnection::populateTouchDevices(void *info if (type == QInputDevice::DeviceType::TouchScreen || type == QInputDevice::DeviceType::TouchPad) { QInputDevice *master = const_cast(QInputDevicePrivate::fromId(deviceInfo->attachment)); Q_ASSERT(master); - dev.qtTouchDevice = new QPointingDevice(QString::fromUtf8(xcb_input_xi_device_info_name(deviceInfo), - xcb_input_xi_device_info_name_length(deviceInfo)), - deviceInfo->deviceid, - type, QPointingDevice::PointerType::Finger, caps, maxTouchPoints, 0, - master->seatName(), QPointingDeviceUniqueId(), master); + if (scrollingDeviceP) { + // valuators were already discovered in QXcbConnection::xi2SetupSlavePointerDevice, so just finish initialization + scrollingDeviceP->deviceType = type; + scrollingDeviceP->pointerType = QPointingDevice::PointerType::Finger; + scrollingDeviceP->capabilities |= caps; + scrollingDeviceP->maximumTouchPoints = maxTouchPoints; + scrollingDeviceP->buttonCount = 3; + scrollingDeviceP->seatName = master->seatName(); + dev.qtTouchDevice = new QXcbScrollingDevice(*scrollingDeviceP, master); + if (Q_UNLIKELY(!caps.testFlag(QInputDevice::Capability::Scroll))) + qCDebug(lcQpaXInputDevices) << "unexpectedly missing RelVert/HorizWheel atoms for touchpad with scroll capability" << dev.qtTouchDevice; + } else { + dev.qtTouchDevice = new QPointingDevice(QString::fromUtf8(xcb_input_xi_device_info_name(deviceInfo), + xcb_input_xi_device_info_name_length(deviceInfo)), + deviceInfo->deviceid, + type, QPointingDevice::PointerType::Finger, caps, maxTouchPoints, 0, + master->seatName(), QPointingDeviceUniqueId(), master); + } if (caps != 0) QWindowSystemInterface::registerInputDevice(dev.qtTouchDevice); m_touchDevices[deviceInfo->deviceid] = dev; -- cgit v1.2.3