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;
|
bool m_xi2Enabled = false;
|
||||||
int m_xi2Minor = -1;
|
int m_xi2Minor = -1;
|
||||||
void initializeXInput2();
|
void initializeXInput2();
|
||||||
|
void xi2SetupDevice(void *info, bool removeExisting = true);
|
||||||
void xi2SetupDevices();
|
void xi2SetupDevices();
|
||||||
struct TouchDeviceData {
|
struct TouchDeviceData {
|
||||||
QTouchDevice *qtTouchDevice = nullptr;
|
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)
|
#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
|
#endif
|
||||||
m_scrollingDevices.clear();
|
m_scrollingDevices.remove(deviceInfo->deviceid);
|
||||||
m_touchDevices.clear();
|
m_touchDevices.remove(deviceInfo->deviceid);
|
||||||
|
}
|
||||||
|
|
||||||
Display *xDisplay = static_cast<Display *>(m_xlib_display);
|
qCDebug(lcQpaXInputDevices) << "input device " << deviceInfo->name << "ID" << deviceInfo->deviceid;
|
||||||
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;
|
|
||||||
#if QT_CONFIG(tabletevent)
|
#if QT_CONFIG(tabletevent)
|
||||||
TabletData tabletData;
|
TabletData tabletData;
|
||||||
#endif
|
#endif
|
||||||
ScrollingDevice scrollingDevice;
|
ScrollingDevice scrollingDevice;
|
||||||
for (int c = 0; c < devices[i].num_classes; ++c) {
|
for (int c = 0; c < deviceInfo->num_classes; ++c) {
|
||||||
XIAnyClassInfo *classinfo = devices[i].classes[c];
|
XIAnyClassInfo *classinfo = deviceInfo->classes[c];
|
||||||
switch (classinfo->type) {
|
switch (classinfo->type) {
|
||||||
case XIValuatorClass: {
|
case XIValuatorClass: {
|
||||||
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
|
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
|
||||||
@ -193,7 +194,7 @@ void QXcbConnection::xi2SetupDevices()
|
|||||||
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(devices[i].name).toLower();
|
QByteArray name = QByteArray(deviceInfo->name).toLower();
|
||||||
QString dbgType = QLatin1String("UNKNOWN");
|
QString dbgType = QLatin1String("UNKNOWN");
|
||||||
if (name.contains("eraser")) {
|
if (name.contains("eraser")) {
|
||||||
isTablet = true;
|
isTablet = true;
|
||||||
@ -231,7 +232,7 @@ void QXcbConnection::xi2SetupDevices()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isTablet) {
|
if (isTablet) {
|
||||||
tabletData.deviceId = devices[i].deviceid;
|
tabletData.deviceId = deviceInfo->deviceid;
|
||||||
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;
|
||||||
}
|
}
|
||||||
@ -239,7 +240,7 @@ void QXcbConnection::xi2SetupDevices()
|
|||||||
|
|
||||||
#ifdef XCB_USE_XINPUT21
|
#ifdef XCB_USE_XINPUT21
|
||||||
if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) {
|
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.
|
// Only use legacy wheel button events when we don't have real scroll valuators.
|
||||||
scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations;
|
scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations;
|
||||||
m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice);
|
m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice);
|
||||||
@ -248,7 +249,7 @@ void QXcbConnection::xi2SetupDevices()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!isTablet) {
|
if (!isTablet) {
|
||||||
TouchDeviceData *dev = populateTouchDevices(&devices[i]);
|
TouchDeviceData *dev = populateTouchDevices(deviceInfo);
|
||||||
if (dev && lcQpaXInputDevices().isDebugEnabled()) {
|
if (dev && lcQpaXInputDevices().isDebugEnabled()) {
|
||||||
if (dev->qtTouchDevice->type() == QTouchDevice::TouchScreen)
|
if (dev->qtTouchDevice->type() == QTouchDevice::TouchScreen)
|
||||||
qCDebug(lcQpaXInputDevices, " it's a touchscreen with type %d capabilities 0x%X max touch points %d",
|
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());
|
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);
|
XIFreeDeviceInfo(devices);
|
||||||
}
|
}
|
||||||
@ -835,8 +855,16 @@ void QXcbConnection::xi2HandleDeviceChangedEvent(void *event)
|
|||||||
{
|
{
|
||||||
xXIDeviceChangedEvent *xiEvent = reinterpret_cast<xXIDeviceChangedEvent *>(event);
|
xXIDeviceChangedEvent *xiEvent = reinterpret_cast<xXIDeviceChangedEvent *>(event);
|
||||||
switch (xiEvent->reason) {
|
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;
|
break;
|
||||||
|
}
|
||||||
case XISlaveSwitch: {
|
case XISlaveSwitch: {
|
||||||
#ifdef XCB_USE_XINPUT21
|
#ifdef XCB_USE_XINPUT21
|
||||||
if (ScrollingDevice *scrollingDevice = scrollingDeviceForId(xiEvent->sourceid))
|
if (ScrollingDevice *scrollingDevice = scrollingDeviceForId(xiEvent->sourceid))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user