[英]Strange results while reading mouse button press in X11 (repeated values)
我正在制作一个简单的控制台应用程序,在其中测试从 Linux 上的 X11 读取各种事件。 我在阅读鼠标按钮时被打断了。 我可以阅读它们,但结果很奇怪。
这是代码:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <ctime>
//X11
#include <X11/Xlib.h>
#include <X11/extensions/XI.h>
#include <X11/extensions/XInput.h>
std::vector<XID> findCandidates(Display* display) {
std::vector<XID> result;
int dev_count;
XDeviceInfo* dev_list = XListInputDevices(display, &dev_count);
if( dev_count == 0 ) { //no devices
XFreeDeviceList(dev_list);
return result;
}
for(int i=0; i<dev_count; ++i) {
XID id = dev_list[i].id;
if( dev_list[i].type == 0 ) continue; //Omit wrong devices
//classes
auto ici = dev_list[i].inputclassinfo;
bool hasButtons = false;
bool hasValuators = false;
for(int cl=dev_list[i].num_classes; cl>0; --cl) {
if( ici->c_class == ButtonClass ) hasButtons = true;
if( ici->c_class == ValuatorClass ) hasValuators = true;
ici = reinterpret_cast<decltype(ici)>(reinterpret_cast<char*>(ici) + ici->length);
}
if( hasButtons && hasValuators ) {
//we have found a candidate
result.push_back(id);
}
}
//cleanup
XFreeDeviceList(dev_list);
return result;
}
void traceInputs(std::ofstream &outputFile, Display* display, XDevice* device);
int main (int argc, char **argv)
{
Display* display = XOpenDisplay(nullptr);
if(display == nullptr) {
std::cerr << "Can't connect to the display" << std::endl;
return 1;
}
std::vector<XID> candidates = findCandidates(display);
std::cout << "Candidates: ";
if( candidates.empty() ) {
std::cout << "none" << std::endl;
} else {
bool needComma = false;
for(auto candidate : candidates) {
if( needComma ) std::cout << ", ";
std::cout << candidate;
needComma = true;
}
std::cout << std::endl;
for(auto deviceID : candidates) {
std::cout << "Opening device #" << deviceID << "...";
XDevice* device = XOpenDevice(display, deviceID);
if( device == nullptr ) {
std::cout << "error" << std::endl;
continue;
}
std::cout << "OK" << std::endl;
std::ofstream outputFile{std::string("Dev_")+std::to_string(deviceID), std::ios_base::out | std::ios_base::trunc};
traceInputs(outputFile, display, device);
outputFile.close();
XCloseDevice(display, device);
}
}
//cleanup
XCloseDisplay(display);
return 0;
}
void traceInputs(std::ofstream &outputFile, Display* display, XDevice* device) {
int type;
XEventClass event_class;
constexpr int EVENT_COUNT = 2;
constexpr int BTN_PRESS_EVENT = 0;
constexpr int BTN_RELEASE_EVENT = 1;
XEventClass registered_event_classes[EVENT_COUNT];
int registered_event_types[EVENT_COUNT];
//button events
DeviceButtonPress(device, type, event_class);
registered_event_classes[BTN_PRESS_EVENT] = event_class;
registered_event_types[BTN_PRESS_EVENT] = type;
DeviceButtonRelease(device, type, event_class);
registered_event_classes[BTN_RELEASE_EVENT] = event_class;
registered_event_types[BTN_RELEASE_EVENT] = type;
//register events
Window w = XDefaultRootWindow(display);
XSelectExtensionEvent(display, w, registered_event_classes, EVENT_COUNT);
std::time_t start, stop;
start = std::time(nullptr);
do{
XEvent event;
for(int i = 0; i < EVENT_COUNT; ++i) {
int event_type = registered_event_types[i];
if( XCheckTypedEvent(display, event_type, &event) ) {
outputFile << "Type: " << event.type << ' ';
switch(i) {
case BTN_PRESS_EVENT:
outputFile << "ButtonPress";
outputFile << "\tx=" << event.xbutton.x_root << " y=" << event.xbutton.y_root;
outputFile << " state=" << event.xbutton.state << " button=" << event.xbutton.button;
break;
case BTN_RELEASE_EVENT:
outputFile << "ButtonRelease";
outputFile << "\tx=" << event.xbutton.x_root << " y=" << event.xbutton.y_root;
outputFile << " state=" << event.xbutton.state << " button=" << event.xbutton.button;
break;
}
outputFile << std::endl;
}
}
stop = std::time(nullptr);
}while(stop - start < 3); //less than 3 seconds
}
这就是它写入与我的鼠标设备对应的文件的内容:
Type: 69 ButtonPress x=1221 y=732 state=1221 button=732
Type: 70 ButtonRelease x=1221 y=732 state=1221 button=732
Type: 69 ButtonPress x=1221 y=732 state=1221 button=732
Type: 70 ButtonRelease x=1221 y=732 state=1221 button=732
Type: 69 ButtonPress x=1221 y=732 state=1221 button=732
如果仔细观察,您会发现x
和state
字段以及y
和button
字段显示相同的值。 这绝对不应该,但我无法确定这种现象的根源。
[编辑]我修改了代码和结果,因为我发现了重复的值。
69 和 70 不是 X11 ButtonPress
和ButtonRelease
事件类型。 分别是 4 和 5。 (在我写这篇文章时,最后一个 X11 事件类型是 36)。 您将获得与 X11 核心事件不同的扩展事件。
您需要针对event_type_base
的XInputClassInfo
成员检查您的类型,例如按钮按下事件将生成XI_DeviceButtonPress+event_type_base
事件类型,并且事件结构是XDeviceButtonEvent
而不是XButtonEvent
。 这些不是XEvent
联合的成员,因此您需要使用 ((XDeviceButtonEvent&)event) 而不是event.xbutton
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.