xcb: report wheel events from the correct device instance
Until now, all wheel events came from one "core pointer". It's useful in Qt Quick to tell the devices apart, because some support smooth scrolling and some don't. Also remove the QHash storing legacy ScrollingDevice structs, and use a subclass of QPointingDevicePrivate instead. Task-number: QTBUG-46412 Task-number: QTBUG-72167 Task-number: QTBUG-69433 Change-Id: Ie6a3d8dd494f981e8706b9a66a1021dfb51baec4 Reviewed-by: Liang Qi <liang.qi@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
50e1976437
commit
ac210c73e4
@ -354,6 +354,25 @@ const QPointingDevice *QPointingDevicePrivate::queryTabletDevice(QInputDevice::D
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
Finds the device instance identified by its \a systemId.
|
||||||
|
Returns the device found, or \c nullptr if none was found.
|
||||||
|
*/
|
||||||
|
const QPointingDevice *QPointingDevicePrivate::pointingDeviceById(qint64 systemId)
|
||||||
|
{
|
||||||
|
const auto &devices = QInputDevice::devices();
|
||||||
|
for (const QInputDevice *dev : devices) {
|
||||||
|
if (dev->type() >= QPointingDevice::DeviceType::Keyboard)
|
||||||
|
continue;
|
||||||
|
const QPointingDevice *pdev = static_cast<const QPointingDevice *>(dev);
|
||||||
|
const auto devPriv = QPointingDevicePrivate::get(pdev);
|
||||||
|
if (devPriv->systemId == systemId)
|
||||||
|
return pdev;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
First, ensure that the \a cancelEvent's QTouchEvent::points() list contains
|
First, ensure that the \a cancelEvent's QTouchEvent::points() list contains
|
||||||
|
@ -132,6 +132,8 @@ public:
|
|||||||
QPointingDevice::PointerType pointerType,
|
QPointingDevice::PointerType pointerType,
|
||||||
QPointingDeviceUniqueId uniqueId,
|
QPointingDeviceUniqueId uniqueId,
|
||||||
qint64 systemId = 0);
|
qint64 systemId = 0);
|
||||||
|
|
||||||
|
static const QPointingDevice *pointingDeviceById(qint64 systemId);
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -26,6 +26,7 @@ qt_internal_add_module(XcbQpa
|
|||||||
qxcbimage.cpp qxcbimage.h
|
qxcbimage.cpp qxcbimage.h
|
||||||
qxcbintegration.cpp qxcbintegration.h
|
qxcbintegration.cpp qxcbintegration.h
|
||||||
qxcbkeyboard.cpp qxcbkeyboard.h
|
qxcbkeyboard.cpp qxcbkeyboard.h
|
||||||
|
qxcbscrollingdevice.cpp qxcbscrollingdevice_p.h
|
||||||
qxcbmime.cpp qxcbmime.h
|
qxcbmime.cpp qxcbmime.h
|
||||||
qxcbnativeinterface.cpp qxcbnativeinterface.h
|
qxcbnativeinterface.cpp qxcbnativeinterface.h
|
||||||
qxcbobject.h
|
qxcbobject.h
|
||||||
|
@ -78,6 +78,7 @@ class QXcbScreen;
|
|||||||
class QXcbWindow;
|
class QXcbWindow;
|
||||||
class QXcbDrag;
|
class QXcbDrag;
|
||||||
class QXcbKeyboard;
|
class QXcbKeyboard;
|
||||||
|
class QXcbScrollingDevicePrivate;
|
||||||
class QXcbClipboard;
|
class QXcbClipboard;
|
||||||
class QXcbWMSupport;
|
class QXcbWMSupport;
|
||||||
class QXcbNativeInterface;
|
class QXcbNativeInterface;
|
||||||
@ -264,7 +265,7 @@ private:
|
|||||||
|
|
||||||
void xi2SetupSlavePointerDevice(void *info, bool removeExisting = true, QPointingDevice *master = nullptr);
|
void xi2SetupSlavePointerDevice(void *info, bool removeExisting = true, QPointingDevice *master = nullptr);
|
||||||
void xi2SetupDevices();
|
void xi2SetupDevices();
|
||||||
// TODO get rid of this: store a smaller struct in QPointingDevicePrivate::extra
|
// TODO get rid of this: store minimal necessary info in a subclass of QPointingDevicePrivate
|
||||||
struct TouchDeviceData {
|
struct TouchDeviceData {
|
||||||
QPointingDevice *qtTouchDevice = nullptr;
|
QPointingDevice *qtTouchDevice = nullptr;
|
||||||
QHash<int, QWindowSystemInterface::TouchPoint> touchPoints;
|
QHash<int, QWindowSystemInterface::TouchPoint> touchPoints;
|
||||||
@ -290,7 +291,7 @@ private:
|
|||||||
void xi2HandleDeviceChangedEvent(void *event);
|
void xi2HandleDeviceChangedEvent(void *event);
|
||||||
void xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow);
|
void xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow);
|
||||||
#if QT_CONFIG(tabletevent)
|
#if QT_CONFIG(tabletevent)
|
||||||
// TODO get rid of this: store a smaller struct in QPointingDevicePrivate::extra
|
// TODO get rid of this: store minimal necessary info in a subclass of QXcbScrollingDevice (some tablets can scroll)
|
||||||
struct TabletData {
|
struct TabletData {
|
||||||
int deviceId = 0;
|
int deviceId = 0;
|
||||||
QString name;
|
QString name;
|
||||||
@ -314,21 +315,9 @@ private:
|
|||||||
QList<TabletData> m_tabletData;
|
QList<TabletData> m_tabletData;
|
||||||
TabletData *tabletDataForDevice(int id);
|
TabletData *tabletDataForDevice(int id);
|
||||||
#endif // QT_CONFIG(tabletevent)
|
#endif // QT_CONFIG(tabletevent)
|
||||||
// TODO get rid of this: store a smaller struct in QPointingDevicePrivate::extra
|
void xi2HandleScrollEvent(void *event, const QPointingDevice *scrollingDevice);
|
||||||
struct ScrollingDevice {
|
void xi2UpdateScrollingDevice(QXcbScrollingDevicePrivate *scrollingDevice);
|
||||||
int deviceId = 0;
|
QXcbScrollingDevicePrivate *scrollingDeviceForId(int id);
|
||||||
int verticalIndex = 0;
|
|
||||||
int horizontalIndex = 0;
|
|
||||||
double verticalIncrement = 0;
|
|
||||||
double horizontalIncrement = 0;
|
|
||||||
Qt::Orientations orientations;
|
|
||||||
Qt::Orientations legacyOrientations;
|
|
||||||
QPointF lastScrollPosition;
|
|
||||||
};
|
|
||||||
QHash<int, ScrollingDevice> m_scrollingDevices;
|
|
||||||
void xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice);
|
|
||||||
void xi2UpdateScrollingDevice(ScrollingDevice &scrollingDevice);
|
|
||||||
ScrollingDevice *scrollingDeviceForId(int id);
|
|
||||||
|
|
||||||
static bool xi2GetValuatorValueIfSet(const void *event, int valuatorNum, double *value);
|
static bool xi2GetValuatorValueIfSet(const void *event, int valuatorNum, double *value);
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#include "qxcbconnection.h"
|
#include "qxcbconnection.h"
|
||||||
#include "qxcbkeyboard.h"
|
#include "qxcbkeyboard.h"
|
||||||
|
#include "qxcbscrollingdevice_p.h"
|
||||||
#include "qxcbscreen.h"
|
#include "qxcbscreen.h"
|
||||||
#include "qxcbwindow.h"
|
#include "qxcbwindow.h"
|
||||||
#include "QtCore/qmetaobject.h"
|
#include "QtCore/qmetaobject.h"
|
||||||
@ -243,15 +244,24 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
m_scrollingDevices.remove(deviceInfo->deviceid);
|
|
||||||
m_touchDevices.remove(deviceInfo->deviceid);
|
m_touchDevices.remove(deviceInfo->deviceid);
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(lcQpaXInputDevices) << "input device " << xcb_input_xi_device_info_name(deviceInfo) << "ID" << deviceInfo->deviceid;
|
const QByteArray nameRaw = QByteArray(xcb_input_xi_device_info_name(deviceInfo),
|
||||||
|
xcb_input_xi_device_info_name_length(deviceInfo));
|
||||||
|
const QString name = QString::fromUtf8(nameRaw);
|
||||||
|
qCDebug(lcQpaXInputDevices) << "input device " << name << "ID" << deviceInfo->deviceid;
|
||||||
#if QT_CONFIG(tabletevent)
|
#if QT_CONFIG(tabletevent)
|
||||||
TabletData tabletData;
|
TabletData tabletData;
|
||||||
#endif
|
#endif
|
||||||
ScrollingDevice scrollingDevice;
|
QXcbScrollingDevicePrivate *scrollingDeviceP = nullptr;
|
||||||
|
auto scrollingDevice = [&]() {
|
||||||
|
if (!scrollingDeviceP)
|
||||||
|
scrollingDeviceP = new QXcbScrollingDevicePrivate(name, deviceInfo->deviceid,
|
||||||
|
QInputDevice::Capability::Scroll);
|
||||||
|
return scrollingDeviceP;
|
||||||
|
};
|
||||||
|
|
||||||
int buttonCount = 32;
|
int buttonCount = 32;
|
||||||
auto classes_it = xcb_input_xi_device_info_classes_iterator(deviceInfo);
|
auto classes_it = xcb_input_xi_device_info_classes_iterator(deviceInfo);
|
||||||
for (; classes_it.rem; xcb_input_device_class_next(&classes_it)) {
|
for (; classes_it.rem; xcb_input_device_class_next(&classes_it)) {
|
||||||
@ -271,21 +281,23 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
|
|||||||
}
|
}
|
||||||
#endif // QT_CONFIG(tabletevent)
|
#endif // QT_CONFIG(tabletevent)
|
||||||
if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
|
if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
|
||||||
scrollingDevice.lastScrollPosition.setX(fixed3232ToReal(vci->value));
|
scrollingDevice()->lastScrollPosition.setX(fixed3232ToReal(vci->value));
|
||||||
else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
|
else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
|
||||||
scrollingDevice.lastScrollPosition.setY(fixed3232ToReal(vci->value));
|
scrollingDevice()->lastScrollPosition.setY(fixed3232ToReal(vci->value));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XCB_INPUT_DEVICE_CLASS_TYPE_SCROLL: {
|
case XCB_INPUT_DEVICE_CLASS_TYPE_SCROLL: {
|
||||||
auto *sci = reinterpret_cast<xcb_input_scroll_class_t *>(classinfo);
|
auto *sci = reinterpret_cast<xcb_input_scroll_class_t *>(classinfo);
|
||||||
if (sci->scroll_type == XCB_INPUT_SCROLL_TYPE_VERTICAL) {
|
if (sci->scroll_type == XCB_INPUT_SCROLL_TYPE_VERTICAL) {
|
||||||
scrollingDevice.orientations |= Qt::Vertical;
|
auto dev = scrollingDevice();
|
||||||
scrollingDevice.verticalIndex = sci->number;
|
dev->orientations |= Qt::Vertical;
|
||||||
scrollingDevice.verticalIncrement = fixed3232ToReal(sci->increment);
|
dev->verticalIndex = sci->number;
|
||||||
|
dev->verticalIncrement = fixed3232ToReal(sci->increment);
|
||||||
} else if (sci->scroll_type == XCB_INPUT_SCROLL_TYPE_HORIZONTAL) {
|
} else if (sci->scroll_type == XCB_INPUT_SCROLL_TYPE_HORIZONTAL) {
|
||||||
scrollingDevice.orientations |= Qt::Horizontal;
|
auto dev = scrollingDevice();
|
||||||
scrollingDevice.horizontalIndex = sci->number;
|
dev->orientations |= Qt::Horizontal;
|
||||||
scrollingDevice.horizontalIncrement = fixed3232ToReal(sci->increment);
|
dev->horizontalIndex = sci->number;
|
||||||
|
dev->horizontalIncrement = fixed3232ToReal(sci->increment);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -300,13 +312,13 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
|
|||||||
// button 4 and the wrong one on button 5. So we just check that they are not labelled with unrelated buttons.
|
// button 4 and the wrong one on button 5. So we just check that they are not labelled with unrelated buttons.
|
||||||
if ((!label4 || qatom(label4) == QXcbAtom::ButtonWheelUp || qatom(label4) == QXcbAtom::ButtonWheelDown) &&
|
if ((!label4 || qatom(label4) == QXcbAtom::ButtonWheelUp || qatom(label4) == QXcbAtom::ButtonWheelDown) &&
|
||||||
(!label5 || qatom(label5) == QXcbAtom::ButtonWheelUp || qatom(label5) == QXcbAtom::ButtonWheelDown))
|
(!label5 || qatom(label5) == QXcbAtom::ButtonWheelUp || qatom(label5) == QXcbAtom::ButtonWheelDown))
|
||||||
scrollingDevice.legacyOrientations |= Qt::Vertical;
|
scrollingDevice()->legacyOrientations |= Qt::Vertical;
|
||||||
}
|
}
|
||||||
if (bci->num_buttons >= 7) {
|
if (bci->num_buttons >= 7) {
|
||||||
xcb_atom_t label6 = labels[5];
|
xcb_atom_t label6 = labels[5];
|
||||||
xcb_atom_t label7 = labels[6];
|
xcb_atom_t label7 = labels[6];
|
||||||
if ((!label6 || qatom(label6) == QXcbAtom::ButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::ButtonHorizWheelRight))
|
if ((!label6 || qatom(label6) == QXcbAtom::ButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::ButtonHorizWheelRight))
|
||||||
scrollingDevice.legacyOrientations |= Qt::Horizontal;
|
scrollingDevice()->legacyOrientations |= Qt::Horizontal;
|
||||||
}
|
}
|
||||||
buttonCount = bci->num_buttons;
|
buttonCount = bci->num_buttons;
|
||||||
qCDebug(lcQpaXInputDevices, " has %d buttons", bci->num_buttons);
|
qCDebug(lcQpaXInputDevices, " has %d buttons", bci->num_buttons);
|
||||||
@ -332,9 +344,7 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
|
|||||||
isTablet = true;
|
isTablet = true;
|
||||||
|
|
||||||
// But we need to be careful not to take the touch and tablet-button devices as tablets.
|
// But we need to be careful not to take the touch and tablet-button devices as tablets.
|
||||||
QByteArray name = QByteArray(xcb_input_xi_device_info_name(deviceInfo),
|
QByteArray nameLower = nameRaw.toLower();
|
||||||
xcb_input_xi_device_info_name_length(deviceInfo));
|
|
||||||
QByteArray nameLower = name.toLower();
|
|
||||||
QString dbgType = QLatin1String("UNKNOWN");
|
QString dbgType = QLatin1String("UNKNOWN");
|
||||||
if (nameLower.contains("eraser")) {
|
if (nameLower.contains("eraser")) {
|
||||||
isTablet = true;
|
isTablet = true;
|
||||||
@ -377,7 +387,7 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
|
|||||||
|
|
||||||
if (isTablet) {
|
if (isTablet) {
|
||||||
tabletData.deviceId = deviceInfo->deviceid;
|
tabletData.deviceId = deviceInfo->deviceid;
|
||||||
tabletData.name = QLatin1String(name);
|
tabletData.name = name;
|
||||||
m_tabletData.append(tabletData);
|
m_tabletData.append(tabletData);
|
||||||
qCDebug(lcQpaXInputDevices) << " it's a tablet with pointer type" << dbgType;
|
qCDebug(lcQpaXInputDevices) << " it's a tablet with pointer type" << dbgType;
|
||||||
QPointingDevice::Capabilities capsOverride = QInputDevice::Capability::None;
|
QPointingDevice::Capabilities capsOverride = QInputDevice::Capability::None;
|
||||||
@ -394,11 +404,9 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
|
|||||||
}
|
}
|
||||||
#endif // QT_CONFIG(tabletevent)
|
#endif // QT_CONFIG(tabletevent)
|
||||||
|
|
||||||
if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) {
|
if (scrollingDeviceP) {
|
||||||
scrollingDevice.deviceId = deviceInfo->deviceid;
|
|
||||||
// Only use legacy wheel button events when we don't have real scroll valuators.
|
// Only use legacy wheel button events when we don't have real scroll valuators.
|
||||||
scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations;
|
scrollingDeviceP->legacyOrientations &= ~scrollingDeviceP->orientations;
|
||||||
m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice);
|
|
||||||
qCDebug(lcQpaXInputDevices) << " it's a scrolling device";
|
qCDebug(lcQpaXInputDevices) << " it's a scrolling device";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,12 +428,18 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
|
|||||||
if (!QInputDevicePrivate::fromId(deviceInfo->deviceid)) {
|
if (!QInputDevicePrivate::fromId(deviceInfo->deviceid)) {
|
||||||
qCDebug(lcQpaXInputDevices) << " it's a mouse";
|
qCDebug(lcQpaXInputDevices) << " it's a mouse";
|
||||||
QInputDevice::Capabilities caps = QInputDevice::Capability::Position | QInputDevice::Capability::Hover;
|
QInputDevice::Capabilities caps = QInputDevice::Capability::Position | QInputDevice::Capability::Hover;
|
||||||
if (scrollingDevice.orientations || scrollingDevice.legacyOrientations)
|
if (scrollingDeviceP) {
|
||||||
caps.setFlag(QInputDevice::Capability::Scroll);
|
scrollingDeviceP->capabilities |= caps;
|
||||||
QWindowSystemInterface::registerInputDevice(new QPointingDevice(
|
scrollingDeviceP->buttonCount = buttonCount;
|
||||||
QString::fromUtf8(xcb_input_xi_device_info_name(deviceInfo)), deviceInfo->deviceid,
|
if (master)
|
||||||
QInputDevice::DeviceType::Mouse, QPointingDevice::PointerType::Generic,
|
scrollingDeviceP->seatName = master->seatName();
|
||||||
caps, 1, buttonCount, (master ? master->seatName() : QString()), QPointingDeviceUniqueId(), master));
|
QWindowSystemInterface::registerInputDevice(new QXcbScrollingMouse(*scrollingDeviceP, master));
|
||||||
|
} else {
|
||||||
|
QWindowSystemInterface::registerInputDevice(new QPointingDevice(
|
||||||
|
name, deviceInfo->deviceid,
|
||||||
|
QInputDevice::DeviceType::Mouse, QPointingDevice::PointerType::Generic,
|
||||||
|
caps, 1, buttonCount, (master ? master->seatName() : QString()), QPointingDeviceUniqueId(), master));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +448,6 @@ void QXcbConnection::xi2SetupDevices()
|
|||||||
#if QT_CONFIG(tabletevent)
|
#if QT_CONFIG(tabletevent)
|
||||||
m_tabletData.clear();
|
m_tabletData.clear();
|
||||||
#endif
|
#endif
|
||||||
m_scrollingDevices.clear();
|
|
||||||
m_touchDevices.clear();
|
m_touchDevices.clear();
|
||||||
m_xiMasterPointerIds.clear();
|
m_xiMasterPointerIds.clear();
|
||||||
|
|
||||||
@ -659,8 +672,8 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
|
|||||||
}
|
}
|
||||||
#endif // QT_CONFIG(tabletevent)
|
#endif // QT_CONFIG(tabletevent)
|
||||||
|
|
||||||
if (ScrollingDevice *device = scrollingDeviceForId(sourceDeviceId))
|
if (auto device = QPointingDevicePrivate::pointingDeviceById(sourceDeviceId))
|
||||||
xi2HandleScrollEvent(event, *device);
|
xi2HandleScrollEvent(event, device);
|
||||||
|
|
||||||
if (xiDeviceEvent) {
|
if (xiDeviceEvent) {
|
||||||
switch (xiDeviceEvent->event_type) {
|
switch (xiDeviceEvent->event_type) {
|
||||||
@ -968,8 +981,8 @@ void QXcbConnection::xi2HandleDeviceChangedEvent(void *event)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XCB_INPUT_CHANGE_REASON_SLAVE_SWITCH: {
|
case XCB_INPUT_CHANGE_REASON_SLAVE_SWITCH: {
|
||||||
if (ScrollingDevice *scrollingDevice = scrollingDeviceForId(xiEvent->sourceid))
|
if (auto *scrollingDevice = scrollingDeviceForId(xiEvent->sourceid))
|
||||||
xi2UpdateScrollingDevice(*scrollingDevice);
|
xi2UpdateScrollingDevice(scrollingDevice);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -978,16 +991,16 @@ void QXcbConnection::xi2HandleDeviceChangedEvent(void *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QXcbConnection::xi2UpdateScrollingDevice(ScrollingDevice &scrollingDevice)
|
void QXcbConnection::xi2UpdateScrollingDevice(QXcbScrollingDevicePrivate *scrollingDevice)
|
||||||
{
|
{
|
||||||
auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, xcb_connection(), scrollingDevice.deviceId);
|
auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, xcb_connection(), scrollingDevice->systemId);
|
||||||
if (!reply || reply->num_infos <= 0) {
|
if (!reply || reply->num_infos <= 0) {
|
||||||
qCDebug(lcQpaXInputDevices, "scrolling device %d no longer present", scrollingDevice.deviceId);
|
qCDebug(lcQpaXInputDevices, "scrolling device %lld no longer present", scrollingDevice->systemId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QPointF lastScrollPosition;
|
QPointF lastScrollPosition;
|
||||||
if (lcQpaXInputEvents().isDebugEnabled())
|
if (lcQpaXInputEvents().isDebugEnabled())
|
||||||
lastScrollPosition = scrollingDevice.lastScrollPosition;
|
lastScrollPosition = scrollingDevice->lastScrollPosition;
|
||||||
|
|
||||||
xcb_input_xi_device_info_t *deviceInfo = xcb_input_xi_query_device_infos_iterator(reply.get()).data;
|
xcb_input_xi_device_info_t *deviceInfo = xcb_input_xi_query_device_infos_iterator(reply.get()).data;
|
||||||
auto classes_it = xcb_input_xi_device_info_classes_iterator(deviceInfo);
|
auto classes_it = xcb_input_xi_device_info_classes_iterator(deviceInfo);
|
||||||
@ -997,68 +1010,75 @@ void QXcbConnection::xi2UpdateScrollingDevice(ScrollingDevice &scrollingDevice)
|
|||||||
auto *vci = reinterpret_cast<xcb_input_valuator_class_t *>(classInfo);
|
auto *vci = reinterpret_cast<xcb_input_valuator_class_t *>(classInfo);
|
||||||
const int valuatorAtom = qatom(vci->label);
|
const int valuatorAtom = qatom(vci->label);
|
||||||
if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
|
if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
|
||||||
scrollingDevice.lastScrollPosition.setX(fixed3232ToReal(vci->value));
|
scrollingDevice->lastScrollPosition.setX(fixed3232ToReal(vci->value));
|
||||||
else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
|
else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
|
||||||
scrollingDevice.lastScrollPosition.setY(fixed3232ToReal(vci->value));
|
scrollingDevice->lastScrollPosition.setY(fixed3232ToReal(vci->value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled() && lastScrollPosition != scrollingDevice.lastScrollPosition))
|
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled() && lastScrollPosition != scrollingDevice->lastScrollPosition))
|
||||||
qCDebug(lcQpaXInputEvents, "scrolling device %d moved from (%f, %f) to (%f, %f)", scrollingDevice.deviceId,
|
qCDebug(lcQpaXInputEvents, "scrolling device %lld moved from (%f, %f) to (%f, %f)", scrollingDevice->systemId,
|
||||||
lastScrollPosition.x(), lastScrollPosition.y(),
|
lastScrollPosition.x(), lastScrollPosition.y(),
|
||||||
scrollingDevice.lastScrollPosition.x(),
|
scrollingDevice->lastScrollPosition.x(),
|
||||||
scrollingDevice.lastScrollPosition.y());
|
scrollingDevice->lastScrollPosition.y());
|
||||||
}
|
}
|
||||||
|
|
||||||
void QXcbConnection::xi2UpdateScrollingDevices()
|
void QXcbConnection::xi2UpdateScrollingDevices()
|
||||||
{
|
{
|
||||||
QHash<int, ScrollingDevice>::iterator it = m_scrollingDevices.begin();
|
const auto &devices = QInputDevice::devices();
|
||||||
const QHash<int, ScrollingDevice>::iterator end = m_scrollingDevices.end();
|
for (const QInputDevice *dev : devices) {
|
||||||
while (it != end) {
|
if (dev->capabilities().testFlag(QInputDevice::Capability::Scroll)) {
|
||||||
xi2UpdateScrollingDevice(it.value());
|
const auto devPriv = QPointingDevicePrivate::get(static_cast<QPointingDevice *>(const_cast<QInputDevice *>(dev)));
|
||||||
++it;
|
xi2UpdateScrollingDevice(static_cast<QXcbScrollingDevicePrivate *>(devPriv));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QXcbConnection::ScrollingDevice *QXcbConnection::scrollingDeviceForId(int id)
|
QXcbScrollingDevicePrivate *QXcbConnection::scrollingDeviceForId(int id)
|
||||||
{
|
{
|
||||||
ScrollingDevice *dev = nullptr;
|
const QPointingDevice *dev = QPointingDevicePrivate::pointingDeviceById(id);
|
||||||
if (m_scrollingDevices.contains(id))
|
if (!dev)
|
||||||
dev = &m_scrollingDevices[id];
|
return nullptr;
|
||||||
return dev;
|
if (!dev->capabilities().testFlag(QInputDevice::Capability::Scroll))
|
||||||
|
return nullptr;
|
||||||
|
auto devPriv = QPointingDevicePrivate::get(const_cast<QPointingDevice *>(dev));
|
||||||
|
return static_cast<QXcbScrollingDevicePrivate *>(devPriv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice)
|
void QXcbConnection::xi2HandleScrollEvent(void *event, const QPointingDevice *dev)
|
||||||
{
|
{
|
||||||
auto *xiDeviceEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event);
|
auto *xiDeviceEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event);
|
||||||
|
if (!dev->capabilities().testFlag(QInputDevice::Capability::Scroll))
|
||||||
|
return;
|
||||||
|
const auto scrollingDevice = static_cast<const QXcbScrollingDevicePrivate *>(QPointingDevicePrivate::get(dev));
|
||||||
|
|
||||||
if (xiDeviceEvent->event_type == XCB_INPUT_MOTION && scrollingDevice.orientations) {
|
if (xiDeviceEvent->event_type == XCB_INPUT_MOTION && scrollingDevice->orientations) {
|
||||||
if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) {
|
if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) {
|
||||||
QPoint rawDelta;
|
QPoint rawDelta;
|
||||||
QPoint angleDelta;
|
QPoint angleDelta;
|
||||||
double value;
|
double value;
|
||||||
if (scrollingDevice.orientations & Qt::Vertical) {
|
if (scrollingDevice->orientations & Qt::Vertical) {
|
||||||
if (xi2GetValuatorValueIfSet(xiDeviceEvent, scrollingDevice.verticalIndex, &value)) {
|
if (xi2GetValuatorValueIfSet(xiDeviceEvent, scrollingDevice->verticalIndex, &value)) {
|
||||||
double delta = scrollingDevice.lastScrollPosition.y() - value;
|
double delta = scrollingDevice->lastScrollPosition.y() - value;
|
||||||
scrollingDevice.lastScrollPosition.setY(value);
|
scrollingDevice->lastScrollPosition.setY(value);
|
||||||
angleDelta.setY((delta / scrollingDevice.verticalIncrement) * 120);
|
angleDelta.setY((delta / scrollingDevice->verticalIncrement) * 120);
|
||||||
// With most drivers the increment is 1 for wheels.
|
// With most drivers the increment is 1 for wheels.
|
||||||
// For libinput it is hardcoded to a useless 15.
|
// For libinput it is hardcoded to a useless 15.
|
||||||
// For a proper touchpad driver it should be in the same order of magnitude as 120
|
// For a proper touchpad driver it should be in the same order of magnitude as 120
|
||||||
if (scrollingDevice.verticalIncrement > 15)
|
if (scrollingDevice->verticalIncrement > 15)
|
||||||
rawDelta.setY(delta);
|
rawDelta.setY(delta);
|
||||||
else if (scrollingDevice.verticalIncrement < -15)
|
else if (scrollingDevice->verticalIncrement < -15)
|
||||||
rawDelta.setY(-delta);
|
rawDelta.setY(-delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (scrollingDevice.orientations & Qt::Horizontal) {
|
if (scrollingDevice->orientations & Qt::Horizontal) {
|
||||||
if (xi2GetValuatorValueIfSet(xiDeviceEvent, scrollingDevice.horizontalIndex, &value)) {
|
if (xi2GetValuatorValueIfSet(xiDeviceEvent, scrollingDevice->horizontalIndex, &value)) {
|
||||||
double delta = scrollingDevice.lastScrollPosition.x() - value;
|
double delta = scrollingDevice->lastScrollPosition.x() - value;
|
||||||
scrollingDevice.lastScrollPosition.setX(value);
|
scrollingDevice->lastScrollPosition.setX(value);
|
||||||
angleDelta.setX((delta / scrollingDevice.horizontalIncrement) * 120);
|
angleDelta.setX((delta / scrollingDevice->horizontalIncrement) * 120);
|
||||||
// See comment under vertical
|
// See comment under vertical
|
||||||
if (scrollingDevice.horizontalIncrement > 15)
|
if (scrollingDevice->horizontalIncrement > 15)
|
||||||
rawDelta.setX(delta);
|
rawDelta.setX(delta);
|
||||||
else if (scrollingDevice.horizontalIncrement < -15)
|
else if (scrollingDevice->horizontalIncrement < -15)
|
||||||
rawDelta.setX(-delta);
|
rawDelta.setX(-delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1070,20 +1090,22 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin
|
|||||||
angleDelta = angleDelta.transposed();
|
angleDelta = angleDelta.transposed();
|
||||||
rawDelta = rawDelta.transposed();
|
rawDelta = rawDelta.transposed();
|
||||||
}
|
}
|
||||||
qCDebug(lcQpaXInputEvents) << "scroll wheel @ window pos" << local << "delta px" << rawDelta << "angle" << angleDelta;
|
qCDebug(lcQpaXInputEvents) << "scroll wheel from device" << scrollingDevice->systemId
|
||||||
QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiDeviceEvent->time, local, global, rawDelta, angleDelta, modifiers);
|
<< "@ window pos" << local << "delta px" << rawDelta << "angle" << angleDelta;
|
||||||
|
QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiDeviceEvent->time, dev,
|
||||||
|
local, global, rawDelta, angleDelta, modifiers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (xiDeviceEvent->event_type == XCB_INPUT_BUTTON_RELEASE && scrollingDevice.legacyOrientations) {
|
} else if (xiDeviceEvent->event_type == XCB_INPUT_BUTTON_RELEASE && scrollingDevice->legacyOrientations) {
|
||||||
if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) {
|
if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) {
|
||||||
QPoint angleDelta;
|
QPoint angleDelta;
|
||||||
if (scrollingDevice.legacyOrientations & Qt::Vertical) {
|
if (scrollingDevice->legacyOrientations & Qt::Vertical) {
|
||||||
if (xiDeviceEvent->detail == 4)
|
if (xiDeviceEvent->detail == 4)
|
||||||
angleDelta.setY(120);
|
angleDelta.setY(120);
|
||||||
else if (xiDeviceEvent->detail == 5)
|
else if (xiDeviceEvent->detail == 5)
|
||||||
angleDelta.setY(-120);
|
angleDelta.setY(-120);
|
||||||
}
|
}
|
||||||
if (scrollingDevice.legacyOrientations & Qt::Horizontal) {
|
if (scrollingDevice->legacyOrientations & Qt::Horizontal) {
|
||||||
if (xiDeviceEvent->detail == 6)
|
if (xiDeviceEvent->detail == 6)
|
||||||
angleDelta.setX(120);
|
angleDelta.setX(120);
|
||||||
else if (xiDeviceEvent->detail == 7)
|
else if (xiDeviceEvent->detail == 7)
|
||||||
@ -1096,7 +1118,8 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin
|
|||||||
if (modifiers & Qt::AltModifier)
|
if (modifiers & Qt::AltModifier)
|
||||||
angleDelta = angleDelta.transposed();
|
angleDelta = angleDelta.transposed();
|
||||||
qCDebug(lcQpaXInputEvents) << "scroll wheel (button" << xiDeviceEvent->detail << ") @ window pos" << local << "delta angle" << angleDelta;
|
qCDebug(lcQpaXInputEvents) << "scroll wheel (button" << xiDeviceEvent->detail << ") @ window pos" << local << "delta angle" << angleDelta;
|
||||||
QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiDeviceEvent->time, local, global, QPoint(), angleDelta, modifiers);
|
QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiDeviceEvent->time, dev,
|
||||||
|
local, global, QPoint(), angleDelta, modifiers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
50
src/plugins/platforms/xcb/qxcbscrollingdevice.cpp
Normal file
50
src/plugins/platforms/xcb/qxcbscrollingdevice.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the plugins of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 2.0 or (at your option) the GNU General
|
||||||
|
** Public license version 3 or any later version approved by the KDE Free
|
||||||
|
** Qt Foundation. The licenses are as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||||
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#include "qxcbscrollingdevice_p.h"
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
QXcbScrollingDevicePrivate::QXcbScrollingDevicePrivate(const QString &name, qint64 id, QInputDevice::Capabilities caps,
|
||||||
|
int buttonCount, const QString &seatName)
|
||||||
|
: QPointingDevicePrivate(name, id, QInputDevice::DeviceType::Mouse, QPointingDevice::PointerType::Generic,
|
||||||
|
caps, 1, buttonCount, seatName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
79
src/plugins/platforms/xcb/qxcbscrollingdevice_p.h
Normal file
79
src/plugins/platforms/xcb/qxcbscrollingdevice_p.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the plugins of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 2.0 or (at your option) the GNU General
|
||||||
|
** Public license version 3 or any later version approved by the KDE Free
|
||||||
|
** Qt Foundation. The licenses are as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||||
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QXCBSCROLLINGDEVICE_P_H
|
||||||
|
#define QXCBSCROLLINGDEVICE_P_H
|
||||||
|
|
||||||
|
#include <QtGui/private/qpointingdevice_p.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
/*! \internal
|
||||||
|
On the xcb platform, if a device's QPointingDevice::capabilities() includes
|
||||||
|
QInputDevice::Capability::Scroll, then its d-pointer must point to
|
||||||
|
an instance of this subclass, which tracks the scrolling valuators.
|
||||||
|
*/
|
||||||
|
class QXcbScrollingDevicePrivate : public QPointingDevicePrivate
|
||||||
|
{
|
||||||
|
Q_DECLARE_PUBLIC(QPointingDevice)
|
||||||
|
public:
|
||||||
|
QXcbScrollingDevicePrivate(const QString &name, qint64 id, QPointingDevice::Capabilities caps,
|
||||||
|
int buttonCount = 3, const QString &seatName = QString());
|
||||||
|
|
||||||
|
// scrolling-related data
|
||||||
|
int verticalIndex = 0;
|
||||||
|
int horizontalIndex = 0;
|
||||||
|
double verticalIncrement = 0;
|
||||||
|
double horizontalIncrement = 0;
|
||||||
|
Qt::Orientations orientations;
|
||||||
|
Qt::Orientations legacyOrientations;
|
||||||
|
mutable QPointF lastScrollPosition;
|
||||||
|
// end of scrolling-related data
|
||||||
|
};
|
||||||
|
|
||||||
|
class QXcbScrollingMouse : public QPointingDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QXcbScrollingMouse(QXcbScrollingDevicePrivate &d, QObject *parent)
|
||||||
|
: QPointingDevice(d, parent) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // QXCBSCROLLINGDEVICE_P_H
|
@ -13,6 +13,7 @@ SOURCES = \
|
|||||||
qxcbconnection.cpp \
|
qxcbconnection.cpp \
|
||||||
qxcbintegration.cpp \
|
qxcbintegration.cpp \
|
||||||
qxcbkeyboard.cpp \
|
qxcbkeyboard.cpp \
|
||||||
|
qxcbscrollingdevice.cpp \
|
||||||
qxcbmime.cpp \
|
qxcbmime.cpp \
|
||||||
qxcbscreen.cpp \
|
qxcbscreen.cpp \
|
||||||
qxcbwindow.cpp \
|
qxcbwindow.cpp \
|
||||||
@ -35,6 +36,7 @@ HEADERS = \
|
|||||||
qxcbconnection.h \
|
qxcbconnection.h \
|
||||||
qxcbintegration.h \
|
qxcbintegration.h \
|
||||||
qxcbkeyboard.h \
|
qxcbkeyboard.h \
|
||||||
|
qxcbscrollingdevice_p.h \
|
||||||
qxcbmime.h \
|
qxcbmime.h \
|
||||||
qxcbobject.h \
|
qxcbobject.h \
|
||||||
qxcbscreen.h \
|
qxcbscreen.h \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user