微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

检测键盘/条码扫描器事件的来源

我需要阅读几个条形码扫描仪,并根据其来源绑定读取的数据。

换句话说,我的应用程序需要知道哪些按键能够采取正确的操作,例如更新UI并将命令发送到专用的外部硬件。

如何将不同的键盘/扫描器的input“路由”到我的应用程序中的特定事件,或者检索允许我的应用程序从input中找出哪里来的信息? (我从条码扫描器只是系统的键盘开始。)

我知道我可以“打开”特定的“设备”,从它读取原始数据,但它不同于我的应用程序中的“键盘事件”。 (也考虑到我的应用程序是用Qt编写的,但是我并不需要被绑定到它。)

HID设备(USB)的详细描述

Linux,阅读条码扫描器

谢谢。

编辑:我最好说,它必须在Linux上运行。 没有Windows和.NET,也没有embedded式Linux。 我也打算在C ++ / Qt中编写代码,但是可以向其他框架开放。 对不起,错过了。

其实这是一个解决方案。

我仍然没有工作的应用程序来显示,但这个概念正在使用XI2。 我将消化XI2食谱,并尝试将其绑定到QApplication::x11EventFilter() 。

如XI2 食谱第3部分所述 ,我可以使用XIButtonClassInfo , XIKeyClassInfo和XIValuatorClassInfo的字段sourceid来确定事件的来源。

食谱,第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,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; }

输出类似(注释):

------------------------------------------- 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 ,但是slave可以通过dev_ev->sourceid区分开来。

我想现在我可以根据应用程序上配置的dev_ev->sourceid将传入的事件路由到相应的“客户端”。

我正在处理一个非常类似的问题,发现这个答案非常有帮助。 只是为了扩大提供的代码示例,这里是创建可执行文件所需的头文件和主代码。 请注意, int qt_version参数在类构造函数中被忽略,因为它在类实现中未被使用。 一个简单的析构函数也需要被添加到qxi2application.cpp文件中。

qxi2application.h

#ifndef QXI2APPLICATION_H #define QXI2APPLICATION_H #include <QApplication> #include <QMainWindow> class QXI2Application : public QApplication { Q_OBJECT public: QXI2Application(int &argc,char **argv); ~QXI2Application(); void setMainWindow( QMainWindow *wnd ); bool x11EventFilter( XEvent *event ); private: display* _display; int xi_opcode; }; #endif // QXI2APPLICATION_H

main.cpp中

#include "qxi2application.h" #include <QApplication> #include <QMainWindow> int main(int argc,char *argv[]) { QXI2Application a(argc,argv); QMainWindow* wind = new QMainWindow; a.setMainWindow(wind); wind->show(); return a.exec(); }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐