其實這是一個解決方案。
我stil沒有工作的應用程序來顯示,但概念是使用XI2。 我要消化XI2 Recipes並嘗試將其綁定到QApplication::x11EventFilter()
。
如XI2 Recipes, Part 3所示,我能確定事件的源與場sourceid
存在於XIButtonClassInfo
,XIKeyClassInfo
和XIValuatorClassInfo
。
Recipes, Part 4顯示如何打印有關事件源的信息(在void print_deviceevent(XIDeviceEvent* event)
中)。聽起來很容易這樣。
(即使是沒有工作的解決方案還沒有,我決定發佈一個答案,以便它可以幫助其他人有相同的問題。只要我做,我會更好的報告編輯我自己的答案進步。)
編輯:
正如所承諾的,這裏要說的是打印出的鍵盤事件源的工作片段:
#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;
}
它輸出像(commente d):
-------------------------------------------
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
的xinput list
的輸出是:
# xinput list
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ Dell Dell USB Optical Mouse id=9 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ Power Button id=6 [slave keyboard (3)]
↳ Power Button id=7 [slave keyboard (3)]
↳ Dell Dell USB Keyboard id=8 [slave keyboard (3)]
↳ Cypress-Weikeng USB Adapter id=10 [slave keyboard (3)]
這種超簡單的測試表明,儘管所有的事件都來自主dev_ev->deviceid = 3
,從屬是dev_ev->sourceid
區分。
我想現在我可以根據在應用程序上配置的dev_ev->sourceid
將傳入事件路由到相應的「客戶端」。
這個問題已經被問了很多次在許多不同的方式:http://stackoverflow.com/questions/5088374/ HTTP:/ /stackoverflow.com/questions/4764274/ http://stackoverflow.com/questions/4487153/ http://stackoverflow.com/questions/4464072/ – 2011-02-25 20:34:14
鏈接1沒有足夠的解決方案。鏈接3和4是關於.NET的,我需要一個Linux解決方案。鏈接2有一個答案,說這很容易,但沒有告訴更多...但是,它現在是更好的指針。謝謝。 – j4x 2011-02-25 20:41:38