Qt中存在一个错误,多个触摸屏导致Qt处于不一致状态。有关此问题的更多信息,请点击此处。
作为一个短期补丁,我想使用事件过滤器(Qt为xcb事件提供)来防止Qt一次处理多个设备。
步骤如下。
- 输入的一系列事件正在开始(鼠标按下、触摸按下等)
- 阻止不属于正在使用的当前设备的设备的所有其他事件
- 事件序列完成后,从步骤1开始恢复所有设备的事件
实际上,我想选通事件,这样一次只能使用一个设备。我希望这个get能绕过Qt的bug。
首先,我试图为一个硬编码设备过滤事件,看看这是否绕过了Qt的错误,但它没有。
class DuplicateHardwareEventFilter : public QAbstractNativeEventFilter
{
public:
DuplicateHardwareEventFilter() {}
bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override
{
if (eventType == "xcb_generic_event_t") {
xcb_generic_event_t* ev = static_cast<xcb_generic_event_t *>(message);
uint responseType = ev->response_type & ~0x80;
if(responseType == XCB_GE_GENERIC) {
xcb_ge_event_t* gev = reinterpret_cast<xcb_ge_event_t*>(ev);
// assume input event
xcb_input_button_press_event_t* xiEvent = reinterpret_cast<xcb_input_button_press_event_t*>(ev);
if(xiEvent->event_type == XCB_INPUT_DEVICE_CHANGED) {
auto inputChangedEvent = reinterpret_cast<xcb_input_device_changed_event_t *>(gev);
if(inputChangedEvent->sourceid == 11) {
return true;
}
qDebug("xcb device changed: %d source: %d", xiEvent->deviceid, inputChangedEvent->sourceid);
return false;
}
if(xiEvent->event_type == XCB_INPUT_MOTION) {
auto inputMotionEvent = reinterpret_cast<xcb_input_motion_event_t*>(gev);
if(inputMotionEvent->sourceid == 11) {
return true;
}
qDebug("xcb motion: %d source: %d", inputMotionEvent->deviceid, inputMotionEvent->sourceid);
return false;
}
if(xiEvent->event_type == XCB_INPUT_ENTER) {
auto inputEnterEvent = reinterpret_cast<xcb_input_enter_event_t*>(gev);
if(inputEnterEvent->sourceid == 11) {
return true;
}
qDebug("xcb enter: %d source: %d", inputEnterEvent->deviceid, inputEnterEvent->sourceid);
return false;
}
if(xiEvent->event_type == XCB_INPUT_LEAVE) {
auto inputLeaveEvent = reinterpret_cast<xcb_input_leave_event_t*>(gev);
qDebug("xcb leave: %d source: %d", inputLeaveEvent->deviceid, inputLeaveEvent->sourceid);
return false;
}
if(xiEvent->event_type == XCB_INPUT_BUTTON_PRESS) {
auto buttonPressEvent = reinterpret_cast<xcb_input_button_press_event_t*>(gev);
qDebug("xcb buttonPress: %d source: %d", buttonPressEvent->deviceid, buttonPressEvent->sourceid);
return false;
}
if(xiEvent->event_type == XCB_INPUT_BUTTON_RELEASE) {
auto buttonReleaseEvent = reinterpret_cast<xcb_input_button_release_event_t*>(gev);
qDebug("xcb buttonRelease: %d source: %d", buttonReleaseEvent->deviceid, buttonReleaseEvent->sourceid);
return false;
}
if(xiEvent->event_type == XCB_INPUT_TOUCH_BEGIN) {
auto touchBeginEvent = reinterpret_cast<xcb_input_touch_begin_event_t*>(gev);
if(touchBeginEvent->sourceid == 11) {
return true;
}
qDebug("xcb touchBegin: %d source: %d", touchBeginEvent->deviceid, touchBeginEvent->sourceid);
return false;
}
if(xiEvent->event_type == XCB_INPUT_TOUCH_UPDATE) {
auto touchUpdateEvent = reinterpret_cast<xcb_input_touch_update_event_t*>(gev);
if(touchUpdateEvent->sourceid == 11) {
return true;
}
qDebug("xcb touchUpdate: %d source: %d", touchUpdateEvent->deviceid, touchUpdateEvent->sourceid);
return false;
}
if(xiEvent->event_type == XCB_INPUT_TOUCH_END) {
auto touchEndEvent = reinterpret_cast<xcb_input_touch_end_event_t*>(gev);
if(touchEndEvent->sourceid == 11) {
return true;
}
qDebug("touchEnd: %d source: %d", touchEndEvent->deviceid, touchEndEvent->sourceid);
return false;
}
if(xiEvent->event_type == XCB_INPUT_PROPERTY) {
auto propertyEvent = reinterpret_cast<xcb_input_property_event_t*>(gev);
qDebug("property: %d", propertyEvent->deviceid);
return false;
}
return false;
}
}
return false;
}
};
Qt仍然处于它的古怪状态。
如何在过滤xcb_wait_for_event
事件的情况下完全阻止设备
我不清楚你的问题在哪里,因为我不清楚不一致状态的作用,但如果你绝望了,这里绝对是一个可能的途径。
对于wayland,我想创建一个API,它将与我的触摸屏接口,比如autohotkey
或xdotools
。使用linux内核的uinput
,我取得了显著的成功,与设备接口,并让它发出命令,这确实证明了它是多么容易工作。看看这里:
https://www.kernel.org/doc/html/v4.12/input/uinput.html
当然值得建立一个API,甚至可能是一个虚拟设备驱动程序。