2011-02-25 113 views
4

我需要讀取多個條形碼掃描儀並根據其來源綁定讀取的數據。檢測鍵盤/條形碼掃描儀事件的來源

換句話說,我的應用程序需要知道哪些按鍵能夠採取正確的操作,比如更新UI並將命令發送到專用外部硬件。

如何將不同鍵盤/掃描儀的輸入「路由」到我的應用程序中的特定事件,或者檢索允許我的應用程序查找輸入內容來自哪裏的信息? (我從條形碼掃描儀只是一個鍵盤到系統的點開始。)

我知道我可以「打開」特定的「設備」來讀取它的原始數據,但它是不一樣的在我的應用程序中有一個「鍵盤事件」。 (也考慮到我的應用程序是用Qt編寫的,但我並不需要綁定它。)

謝謝。

編輯: 我最好說它必須在Linux上運行。沒有Windows和.NET,也沒有嵌入式Linux。我也打算用C++/Qt編寫代碼,但是我可以向其他框架開放。 對不起。

+0

這個問題已經被問了很多次在許多不同的方式: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

鏈接1沒有足夠的解決方案。鏈接3和4是關於.NET的,我需要一個Linux解決方案。鏈接2有一個答案,說這很容易,但沒有告訴更多...但是,它現在是更好的指針。謝謝。 – j4x 2011-02-25 20:41:38

回答

4

其實這是一個解決方案。

我stil沒有工作的應用程序來顯示,但概念是使用XI2。 我要消化XI2 Recipes並嘗試將其綁定到QApplication::x11EventFilter()

如XI2 Recipes, Part 3所示,我能確定事件的源與場sourceid存在於XIButtonClassInfoXIKeyClassInfoXIValuatorClassInfo

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將傳入事件路由到相應的「客戶端」。

1

我正在研究一個非常類似的問題,並發現這個答案非常有幫助。只是爲了擴大提供的代碼示例,這裏是創建可執行文件所需的頭文件和主代碼。請注意,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(); 
} 
相關問題