This is actually a solution.
I do not have a working application for display, but the concept uses XI2. I am going to digest XI2 Recipes and try to bind it to QApplication::x11EventFilter() .
As shown in XI2 Recipes, Part 3 , I can determine the event source with the sourceid field present in XIButtonClassInfo , XIKeyClassInfo and XIValuatorClassInfo .
Recipes, Part 4 shows how to print event source information (in void print_deviceevent(XIDeviceEvent* event) ). It just sounds like that.
(Even if you don’t have a working solution yet, I decided to post an answer so that it would help someone else with the same problem. As soon as I have time, I will edit my own answer with the best reports.)
EDIT:
As promised, here is a working snippet that prints the source of keyboard events:
#include <QDebug> #include "qxi2application.h" #include <QX11Info> #include <X11/extensions/XInput2.h> // XI2 Event types. static const char *_xi2_event_names[] = { "Reserved 0", "XI_DeviceChanged", "XI_KeyPress", "XI_KeyRelease", "XI_ButtonPress", "XI_ButtonRelease", "XI_Motion", "XI_Enter", "XI_Leave", "XI_FocusIn", "XI_FocusOut", "XI_HierarchyChanged", "XI_PropertyEvent", "XI_RawKeyPress", "XI_RawKeyRelease", "XI_RawButtonPress", "XI_RawButtonRelease", "XI_RawMotion" }; #include <QMainWindow> QXI2Application::QXI2Application( int &argc, char **argv, int qt_version ) : QApplication( argc, argv, qt_version ) { int event, error; _display = QX11Info::display( ); if ( !XQueryExtension( _display, "XInputExtension", &xi_opcode, &event, &error ) ) qDebug( ) << "X Input extension not available.\n"; // We support XI 2.0. int major = 2; int minor = 0; int rc = XIQueryVersion( _display, &major, &minor ); if ( rc == BadRequest ) qDebug( ) << "No XI2 support. Server supports version " << major << "." << minor << " only.\n"; else if ( rc != Success ) qDebug( ) << "Internal Error! This is a bug in Xlib.\n"; else qDebug( ) << "XI2 supported. Server provides version " << major << "." << minor; } void QXI2Application::setMainWindow( QMainWindow *wnd ) { XIEventMask evmasks[ 1 ]; unsigned char mask1[ ( XI_LASTEVENT + 7 ) / 8 ]; memset( mask1, 0, sizeof( mask1 ) ); // Select for key events from all master devices. XISetMask( mask1, XI_KeyPress ); XISetMask( mask1, XI_KeyRelease ); evmasks[ 0 ].deviceid = XIAllMasterDevices; evmasks[ 0 ].mask_len = sizeof( mask1 ); evmasks[ 0 ].mask = mask1; XISelectEvents( _display, wnd->winId( ), evmasks, 1 ); XFlush( _display ); } bool QXI2Application::x11EventFilter( XEvent *event ) { XGenericEventCookie *cookie = &event->xcookie; if ( event->type != GenericEvent || cookie->extension != xi_opcode || !XGetEventData( _display, cookie ) ) { return false; } qDebug( ) << "cookie->evtype = " << cookie->evtype << " (" << _xi2_event_names[ cookie->evtype < XI_LASTEVENT ? cookie->evtype : XI_LASTEVENT ] << ")"; switch( cookie->evtype ) { case XI_KeyPress: { qDebug( ) << "\tXI_KeyPress"; XIDeviceEvent *dev_ev = ( XIDeviceEvent * )event->xcookie.data; qDebug( ) << "\tdev_ev->deviceid = " << dev_ev->deviceid; qDebug( ) << "\tdev_ev->sourceid = " << dev_ev->sourceid; break; } case XI_KeyRelease: { qDebug( ) << "\tXI_KeyRelease"; XIDeviceEvent *dev_ev = ( XIDeviceEvent * )event->xcookie.data; qDebug( ) << "\tdev_ev->deviceid = " << dev_ev->deviceid; qDebug( ) << "\tdev_ev->sourceid = " << dev_ev->sourceid; break; } default: qDebug( ) << "\tcookie->evtype = " << cookie->evtype; break; } XFreeEventData( _display, cookie ); return false; }
He outputs something like (commented):
------------------------------------------- XI2 supported. Server provides version 2 . 0 ------------------------------------------- [Keyboard] ↳ Dell Dell USB Keyboard id=8 [slave keyboard (3)] cookie->evtype = 2 ( XI_KeyPress ) XI_KeyPress dev_ev->deviceid = 3 dev_ev->sourceid = 8 cookie->evtype = 3 ( XI_KeyRelease ) XI_KeyRelease dev_ev->deviceid = 3 dev_ev->sourceid = 8 ------------------------------------------- [Barcode] ↳ Cypress-Weikeng USB Adapter id=10 [slave keyboard (3)] cookie->evtype = 2 ( XI_KeyPress ) XI_KeyPress dev_ev->deviceid = 3 dev_ev->sourceid = 10 cookie->evtype = 3 ( XI_KeyRelease ) XI_KeyRelease dev_ev->deviceid = 3 dev_ev->sourceid = 10
The output of xinput list :
This ultra- dev_ev->deviceid = 3 test shows that although all events come from master dev_ev->deviceid = 3 , the slave is recognized by dev_ev->sourceid .
I think now I can direct incoming events to the corresponding "clients" based on dev_ev->sourceid configured for the application.