xcb: allow to change XInput device properties at runtime
xinput list-props <device-id> xinput set-prop <device-id> <atom-id> n n n Example: xinput list-props 9 .. Evdev Scrolling Distance (274): 1, 1, 1 .. xinput set-prop 9 274 8 1 1 [ChangeLog][Platform Specific Changes][Linux] XInput device property changes are now detected at runtime (no application restart required). Change-Id: I4d2455eef70857bc2e35c27011a3808a78fa960f Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
This commit is contained in:
parent
46001e6f49
commit
900abb116d
@ -547,6 +547,7 @@ private:
|
||||
bool m_xi2Enabled = false;
|
||||
int m_xi2Minor = -1;
|
||||
void initializeXInput2();
|
||||
void xi2SetupDevice(void *info, bool removeExisting = true);
|
||||
void xi2SetupDevices();
|
||||
struct TouchDeviceData {
|
||||
QTouchDevice *qtTouchDevice = nullptr;
|
||||
|
@ -93,28 +93,29 @@ void QXcbConnection::initializeXInput2()
|
||||
}
|
||||
}
|
||||
|
||||
void QXcbConnection::xi2SetupDevices()
|
||||
void QXcbConnection::xi2SetupDevice(void *info, bool removeExisting)
|
||||
{
|
||||
XIDeviceInfo *deviceInfo = reinterpret_cast<XIDeviceInfo *>(info);
|
||||
if (removeExisting) {
|
||||
#if QT_CONFIG(tabletevent)
|
||||
m_tabletData.clear();
|
||||
for (int i = 0; i < m_tabletData.count(); ++i) {
|
||||
if (m_tabletData.at(i).deviceId == deviceInfo->deviceid) {
|
||||
m_tabletData.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
m_scrollingDevices.clear();
|
||||
m_touchDevices.clear();
|
||||
m_scrollingDevices.remove(deviceInfo->deviceid);
|
||||
m_touchDevices.remove(deviceInfo->deviceid);
|
||||
}
|
||||
|
||||
Display *xDisplay = static_cast<Display *>(m_xlib_display);
|
||||
int deviceCount = 0;
|
||||
XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount);
|
||||
for (int i = 0; i < deviceCount; ++i) {
|
||||
// Only non-master pointing devices are relevant here.
|
||||
if (devices[i].use != XISlavePointer)
|
||||
continue;
|
||||
qCDebug(lcQpaXInputDevices) << "input device " << devices[i].name << "ID" << devices[i].deviceid;
|
||||
qCDebug(lcQpaXInputDevices) << "input device " << deviceInfo->name << "ID" << deviceInfo->deviceid;
|
||||
#if QT_CONFIG(tabletevent)
|
||||
TabletData tabletData;
|
||||
#endif
|
||||
ScrollingDevice scrollingDevice;
|
||||
for (int c = 0; c < devices[i].num_classes; ++c) {
|
||||
XIAnyClassInfo *classinfo = devices[i].classes[c];
|
||||
for (int c = 0; c < deviceInfo->num_classes; ++c) {
|
||||
XIAnyClassInfo *classinfo = deviceInfo->classes[c];
|
||||
switch (classinfo->type) {
|
||||
case XIValuatorClass: {
|
||||
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
|
||||
@ -193,7 +194,7 @@ void QXcbConnection::xi2SetupDevices()
|
||||
isTablet = true;
|
||||
|
||||
// But we need to be careful not to take the touch and tablet-button devices as tablets.
|
||||
QByteArray name = QByteArray(devices[i].name).toLower();
|
||||
QByteArray name = QByteArray(deviceInfo->name).toLower();
|
||||
QString dbgType = QLatin1String("UNKNOWN");
|
||||
if (name.contains("eraser")) {
|
||||
isTablet = true;
|
||||
@ -231,7 +232,7 @@ void QXcbConnection::xi2SetupDevices()
|
||||
}
|
||||
|
||||
if (isTablet) {
|
||||
tabletData.deviceId = devices[i].deviceid;
|
||||
tabletData.deviceId = deviceInfo->deviceid;
|
||||
m_tabletData.append(tabletData);
|
||||
qCDebug(lcQpaXInputDevices) << " it's a tablet with pointer type" << dbgType;
|
||||
}
|
||||
@ -239,7 +240,7 @@ void QXcbConnection::xi2SetupDevices()
|
||||
|
||||
#ifdef XCB_USE_XINPUT21
|
||||
if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) {
|
||||
scrollingDevice.deviceId = devices[i].deviceid;
|
||||
scrollingDevice.deviceId = deviceInfo->deviceid;
|
||||
// Only use legacy wheel button events when we don't have real scroll valuators.
|
||||
scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations;
|
||||
m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice);
|
||||
@ -248,7 +249,7 @@ void QXcbConnection::xi2SetupDevices()
|
||||
#endif
|
||||
|
||||
if (!isTablet) {
|
||||
TouchDeviceData *dev = populateTouchDevices(&devices[i]);
|
||||
TouchDeviceData *dev = populateTouchDevices(deviceInfo);
|
||||
if (dev && lcQpaXInputDevices().isDebugEnabled()) {
|
||||
if (dev->qtTouchDevice->type() == QTouchDevice::TouchScreen)
|
||||
qCDebug(lcQpaXInputDevices, " it's a touchscreen with type %d capabilities 0x%X max touch points %d",
|
||||
@ -261,6 +262,25 @@ void QXcbConnection::xi2SetupDevices()
|
||||
dev->size.width(), dev->size.height());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QXcbConnection::xi2SetupDevices()
|
||||
{
|
||||
#if QT_CONFIG(tabletevent)
|
||||
m_tabletData.clear();
|
||||
#endif
|
||||
m_scrollingDevices.clear();
|
||||
m_touchDevices.clear();
|
||||
|
||||
Display *xDisplay = static_cast<Display *>(m_xlib_display);
|
||||
int deviceCount = 0;
|
||||
XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount);
|
||||
for (int i = 0; i < deviceCount; ++i) {
|
||||
// Only non-master pointing devices are relevant here.
|
||||
if (devices[i].use != XISlavePointer)
|
||||
continue;
|
||||
xi2SetupDevice(&devices[i], false);
|
||||
}
|
||||
XIFreeDeviceInfo(devices);
|
||||
}
|
||||
@ -835,8 +855,16 @@ void QXcbConnection::xi2HandleDeviceChangedEvent(void *event)
|
||||
{
|
||||
xXIDeviceChangedEvent *xiEvent = reinterpret_cast<xXIDeviceChangedEvent *>(event);
|
||||
switch (xiEvent->reason) {
|
||||
case XIDeviceChange:
|
||||
case XIDeviceChange: {
|
||||
int nrDevices = 0;
|
||||
Display *dpy = static_cast<Display *>(m_xlib_display);
|
||||
XIDeviceInfo* deviceInfo = XIQueryDevice(dpy, xiEvent->sourceid, &nrDevices);
|
||||
if (nrDevices <= 0)
|
||||
return;
|
||||
xi2SetupDevice(deviceInfo);
|
||||
XIFreeDeviceInfo(deviceInfo);
|
||||
break;
|
||||
}
|
||||
case XISlaveSwitch: {
|
||||
#ifdef XCB_USE_XINPUT21
|
||||
if (ScrollingDevice *scrollingDevice = scrollingDeviceForId(xiEvent->sourceid))
|
||||
|
Loading…
x
Reference in New Issue
Block a user