Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
XI_试图打开设备的Xlib程序中的BadClass错误(在打开第二个设备时失败)_C_Linux_X11_Xlib_Xinput - Fatal编程技术网

XI_试图打开设备的Xlib程序中的BadClass错误(在打开第二个设备时失败)

XI_试图打开设备的Xlib程序中的BadClass错误(在打开第二个设备时失败),c,linux,x11,xlib,xinput,C,Linux,X11,Xlib,Xinput,我正在编写一个我需要的“实用”程序,它需要用Xlib之类的语言编写。程序将要做的一件事是读取用户所做的所有按键,为此,我必须“打开”XI_键盘的XDevices 所以我有一个循环,可以“打开”需要打开的XDevices for(i = 0; i < devicesN; i++) { if(deviceInfo[i].type == keyboardAtom) { printf("%s %d %d %d\n", device

我正在编写一个我需要的“实用”程序,它需要用Xlib之类的语言编写。程序将要做的一件事是读取用户所做的所有按键,为此,我必须“打开”XI_键盘的XDevices

所以我有一个循环,可以“打开”需要打开的XDevices

for(i = 0; i < devicesN; i++) {
        if(deviceInfo[i].type == keyboardAtom) {
                printf("%s %d %d %d\n", deviceInfo[i].name, deviceInfo[i].type, deviceInfo[i].id, keyboardAtom);

                device = XOpenDevice(display, deviceInfo[i].id);

                inputInfo = device->classes;
                for(j = 0; j < deviceInfo->num_classes; j++, inputInfo++) {
                        printf("%d %d\n", inputInfo->input_class, KeyClass);
                        if(inputInfo->input_class == KeyClass) {
                                DeviceKeyPress(device, keypressType, events[eventsN++]);
                        }
                }

                if(XSelectExtensionEvent(display, RootWindow(display, screen), events, eventsN))
                        return 1;
        }
}
根据我的调试,此错误发生在设备打开期间,因此在这一行:
device=XOpenDevice(display,deviceInfo[i].id)

我尝试跳过第7台设备,直接转到下一台设备,但错误仍然发生。看起来它总是发生在第二个设备“打开”上

感谢您的帮助


PS:如果你认为这可以在xcb上更容易、更轻松地完成,那么你也可以建议一种使用xcb的方法。

我在编写类似内容时也有类似的问题。然而,我不认为我可以复制你的问题。这就是我所拥有的:

  • 如果将
    XSelectExtensionEvent
    移动到for循环之外,则可能会成功调用
    XOpenDevice
    ,并在
    XSelectExtensionEvent
    上获得X错误。(这是一种奇怪的行为,我不知道发生了什么)

  • 您可以尝试使用
    xinput test[-approxity]
    确保您的设备可以打开。对于我的一些设备,如果添加
    -proximition
    标志,
    xinput
    也会抛出X错误:

  • 这是我的节目。你这边行吗
  • //gcc-lX11-lXi
    #包括
    #包括
    #包括
    显示*显示;
    无符号长屏幕;
    窗口根!;
    #定义无效的\u事件\u类型-1
    静态int运动类型=无效事件类型;
    静态int按钮\按下\类型=无效\事件\类型;
    静态int按钮\释放\类型=无效\事件\类型;
    静态int键\按下\类型=无效\事件\类型;
    静态int键\释放\类型=无效\事件\类型;
    静态整数接近度类型=无效事件类型;
    静态整数接近度\输出\类型=无效\事件\类型;
    #定义添加事件(事件,类型)\
    do{EVENT(device,TYPE,EVENT_list[number]);number++}while(0)
    无效寄存器\扩展\事件(){
    //从xinput中的test.c复制
    XDeviceInfo*设备;
    内部设备;
    设备=XListInputDevices(显示器和设备);
    整数=0;
    XEventClass事件列表[8*n设备];
    对于(int i=0;inum\u类;i++){
    开关(设备->类[i]。输入类){
    案例类别:
    添加事件(设备按键、按键类型);
    添加按键事件(DeviceKeyRelease,按键释放类型);
    打破
    案例按钮类别:
    添加事件(设备按钮按下、按钮按下类型);
    添加事件(设备按钮释放、按钮释放类型);
    打破
    案例评估类:
    添加事件(DeviceMotionNotify,运动类型);
    //还有“xinput测试-邻近性”的错误`
    //添加_事件(ProximityIn,proximit_类型);
    //添加事件(接近、接近、输出类型);
    打破
    违约:
    //fprintf(stderr,“未知类”\n);
    打破
    }
    }
    }
    
    assert(number我在写类似的东西时也有类似的问题。但是,我认为我无法重现您的问题。因此,我有以下问题:

  • 如果将
    XSelectExtensionEvent
    移动到for循环之外,您可能会成功调用
    XOpenDevice
    ,并在
    XSelectExtensionEvent
    上得到X错误(这是一个奇怪的行为,我不知道发生了什么)

  • 您可以尝试使用
    xinput test[-approxity]
    确保您的设备可以打开。对于我的一些设备,如果我添加
    -approxity
    标志,
    xinput
    也会抛出X错误:

  • 这是我的计划,对你有用吗
  • //gcc-lX11-lXi
    #包括
    #包括
    #包括
    显示*显示;
    无符号长屏幕;
    窗口根!;
    #定义无效的\u事件\u类型-1
    静态int运动类型=无效事件类型;
    静态int按钮\按下\类型=无效\事件\类型;
    静态int按钮\释放\类型=无效\事件\类型;
    静态int键\按下\类型=无效\事件\类型;
    静态int键\释放\类型=无效\事件\类型;
    静态整数接近度类型=无效事件类型;
    静态整数接近度\输出\类型=无效\事件\类型;
    #定义添加事件(事件,类型)\
    do{EVENT(device,TYPE,EVENT_list[number]);number++}while(0)
    无效寄存器\扩展\事件(){
    //从xinput中的test.c复制
    XDeviceInfo*设备;
    内部设备;
    设备=XListInputDevices(显示器和设备);
    整数=0;
    XEventClass事件列表[8*n设备];
    对于(int i=0;inum\u类;i++){
    开关(设备->类[i]。输入类){
    案例类别:
    添加_事件(设备按键)
    
    X Error of failed request:  XI_BadClass (invalid Class parameter)
      Major opcode of failed request:  131 (XInputExtension)
      Minor opcode of failed request:  6 (X_SelectExtensionEvent)
      Class id in failed request: 0x6bf
      Serial number of failed request:  19
      Current serial number in output stream:  20
    
    $ xinput test -proximity 4
    X Error of failed request:  XI_BadClass (invalid Class parameter)
      Major opcode of failed request:  131 (XInputExtension)
      Minor opcode of failed request:  6 (X_SelectExtensionEvent)
      Class id in failed request: 0x135
      Serial number of failed request:  19
      Current serial number in output stream:  19
    $ 
    
    // gcc -lX11 -lXi
    
    #include <stdio.h>
    #include <assert.h>
    #include <X11/extensions/XInput.h>
    
    Display* display;
    unsigned long screen;
    Window root_win;
    
    #define INVALID_EVENT_TYPE  -1
    
    static int motion_type = INVALID_EVENT_TYPE;
    static int button_press_type = INVALID_EVENT_TYPE;
    static int button_release_type = INVALID_EVENT_TYPE;
    static int key_press_type = INVALID_EVENT_TYPE;
    static int key_release_type = INVALID_EVENT_TYPE;
    static int proximity_in_type = INVALID_EVENT_TYPE;
    static int proximity_out_type = INVALID_EVENT_TYPE;
    
    #define ADD_EVENT(EVENT, TYPE) \
     do { EVENT(device, TYPE, event_list[number]); number++; } while(0)
    
    void register_extension_events() {
        // Copied from test.c in xinput
        XDeviceInfo* devices;
        int ndevices;
        devices = XListInputDevices(display, &ndevices);
        int number = 0;
        XEventClass event_list[8 * ndevices];
        for (int i = 0; i < ndevices; i++) {
            // Filter out master devices. See XListInputDevices(3) and XI.h
            if (devices[i].use < IsXExtensionDevice)
                continue;
            if (!"list all devices")
                printf("%d\t%d\t%s\t%s\n", i, devices[i].id, 
                    devices[i].type ? XGetAtomName(display, devices[i].type) : "",
                    devices[i].name);
            XDevice* device = XOpenDevice(display, devices[i].id);
            for (int i = 0; i < device->num_classes; i++) {
                switch (device->classes[i].input_class) {
                case KeyClass:
                    ADD_EVENT(DeviceKeyPress, key_press_type);
                    ADD_EVENT(DeviceKeyRelease, key_release_type);
                    break;
                case ButtonClass:
                    ADD_EVENT(DeviceButtonPress, button_press_type);
                    ADD_EVENT(DeviceButtonRelease, button_release_type);
                    break;
                case ValuatorClass:
                    ADD_EVENT(DeviceMotionNotify, motion_type);
                    // Also errors with `xinput test -proximity <id>`
                    // ADD_EVENT(ProximityIn, proximity_in_type);
                    // ADD_EVENT(ProximityOut, proximity_out_type);
                    break;
                default:
                    // fprintf(stderr, "unknown class\n");
                    break;
                }
            }
        }
        assert(number <= 8 * ndevices);
        if (number && XSelectExtensionEvent(display, root_win, event_list, number))
            fprintf(stderr, "error selecting extended events\n");
        while (1) {
            XEvent Event;
            XNextEvent(display, &Event);
            printf(".");
            fflush(stdout);
        }
    }
    
    int main() {
        display = XOpenDisplay(NULL);
        if (display == NULL) {
            fprintf(stderr, "Unable to connect to X server\n");
            return 1;
        }
        screen = DefaultScreen(display);
        root_win = RootWindow(display, screen);
        register_extension_events();
    }