Qt下QAbstractNativeEventFilter无法接收XCB_KEY_PRESS事件问题
问题原因说明
1. 响应码85的本质
你对枚举值的对应逻辑完全错误:XCB_ALLOC_NAMED_COLOR是XCB核心请求的操作码,和事件类型不属于同一个枚举体系。
X11核心协议的事件类型值范围是0-31,大于31的事件都属于扩展事件,你拿到的85是X11扩展(比如XInput2、XRender等)推送的事件偏移后的值,和XCB_ALLOC_NAMED_COLOR没有任何关系,属于匹配错误。
2. 收不到XCB_KEY_PRESS事件的核心原因
X11服务默认只会给窗口推送你显式声明要接收的事件,你当前代码不满足接收按键事件的条件:
- 你没有创建任何应用窗口,也没有给root窗口设置
XCB_EVENT_MASK_KEY_PRESS事件掩码,X服务不会向你推送按键事件 - 你注释了全局按键抓取的
xcb_grab_key代码,无法捕获全局范围的按键输入 - 你析构函数中调用了
xcb_disconnect断开Qt管理的xcb连接,会导致Qt内部逻辑异常,属于严重错误,该连接是Qt通过QX11Info对外暴露的内部资源,禁止开发者手动销毁。
修正方案
根据你的使用场景二选一即可:
场景1:仅监听当前应用窗口的按键
在主函数中创建并显示Qt窗口,当窗口处于激活状态时,Qt会默认注册按键事件掩码,你就可以收到对应XCB_KEY_PRESS事件:
// main.cpp 补充修改 #include <QApplication> #include <QX11Info> #include <QWidget> // 新增窗口头文件 #include <xcb/xcb.h> #include "myfilter.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); QWidget w; w.show(); // 显示应用窗口,获得焦点后即可收到按键事件 xcb_connection_t *conn = QX11Info::connection(); MyFilter myFilter(conn); return a.exec(); }
同时删除myfilter.cpp析构函数中的xcb_disconnect(this->_conn);代码,避免Qt崩溃。
场景2:监听全局所有按键输入
放开你注释的全局按键抓取代码,同时补充释放逻辑:
// myfilter.cpp 修改 MyFilter::MyFilter(xcb_connection_t *conn, QObject *parent) : QObject(parent) { this->_conn = conn; xcb_screen_t *screen; screen = xcb_setup_roots_iterator(xcb_get_setup(this->_conn)).data; this->_rootWindow = screen->root; qDebug() << "Root window: " << this->_rootWindow; // 放开全局按键抓取,注意该操作会抢占所有按键输入,其他应用无法收到按键 xcb_grab_key(this->_conn, 1, screen->root, XCB_MOD_MASK_ANY, XCB_GRAB_ANY, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); QCoreApplication::instance()->installNativeEventFilter(this); } MyFilter::~MyFilter() { // 先释放全局按键抓取 xcb_ungrab_key(this->_conn, XCB_GRAB_ANY, _rootWindow, XCB_MOD_MASK_ANY); // 删除xcb_disconnect调用,不要销毁Qt管理的连接 }
修改后你就可以收到全局范围的XCB_KEY_PRESS事件。
内容的提问来源于stack exchange,提问作者hardboiled65
相关产品推荐
相关产品推荐

