使用XCB开发窗口管理器时无法全局捕获键盘问题求助
问题根因
你没有为根窗口注册按键按下事件的监听权限,X11的事件投递机制要求客户端主动声明需要接收对应类型事件,未注册的事件不会被推送给客户端。同时你的代码还存在缓冲区未刷新、事件内存未释放的问题。
修正后完整代码
#include <stdio.h> #include <stdlib.h> #include <xcb/xcb.h> xcb_connection_t *conn; xcb_screen_t *screen; const xcb_setup_t *setup; xcb_generic_event_t *ev; void dieout(){ printf("Die out\n"); xcb_disconnect(conn); exit(0); } void prepare(){ conn = xcb_connect(NULL,NULL); if (xcb_connection_has_error(conn)) { dieout(); } setup = xcb_get_setup(conn); screen = xcb_setup_roots_iterator(setup).data; // 新增:给根窗口注册按键按下事件监听 uint32_t values[1] = {XCB_EVENT_MASK_KEY_PRESS}; xcb_change_window_attributes(conn, screen->root, XCB_CW_EVENT_MASK, values); xcb_flush(conn); } int main(){ prepare(); while(1){ ev = xcb_wait_for_event(conn); if (!ev) { dieout(); } switch(ev->response_type & ~0x80){ case XCB_KEY_PRESS: // 加换行符刷新标准输出缓冲区,确保内容立刻打印 printf("Keyboard Pressed\n"); break; } // 释放事件结构体内存,避免泄漏 free(ev); } return 0; }
主要修改点
- 在
prepare函数中新增了根窗口的事件掩码注册,声明需要接收按键按下事件 - 新增XCB连接异常校验,避免连接失败无提示
printf添加换行符,触发行缓冲刷新,确保内容即时输出- 事件处理完成后释放事件内存,避免内存泄漏
- 响应类型判断时屏蔽最高位(0x80是事件标记位,避免部分场景下事件类型判断错误)
验证步骤
编译运行命令和你之前的操作一致:
gcc main.c -lxcb Xephyr +xinerama -screen 500x500 -screen 500x500 -ac :1& DISPLAY=:1 ./a.out
此时在Xephyr窗口中按下按键,终端会正常输出Keyboard Pressed日志。
内容的提问来源于stack exchange,提问作者guannan zhou
相关产品推荐
相关产品推荐

