XI_试图打开设备的Xlib程序中的BadClass错误(在打开第二个设备时失败)
我正在编写一个我需要的“实用”程序,它需要用Xlib之类的语言编写。程序将要做的一件事是读取用户所做的所有按键,为此,我必须“打开”XI_键盘的XDevices 所以我有一个循环,可以“打开”需要打开的XDevicesXI_试图打开设备的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
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();
}