C语言Xorg编程中XNextEvent仅前三次返回 窗口静止时无响应
问题分析与解决
你的代码本身不存在逻辑错误,问题出在对X11事件模型的机制理解偏差:
- XNextEvent是阻塞调用,只有当你注册监听的事件产生时才会返回,没有匹配事件时会一直挂起等待。
- 你通过
XSelectInput(dis, win, ExposureMask | KeyPressMask)仅注册了两类事件监听:- Expose事件:仅在窗口需要重绘时触发,包括首次显示、被遮挡后重新露出、调整窗口大小、切换全屏等场景,这就是你操作窗口时XNextEvent会恢复返回的原因。
- KeyPress事件:仅在窗口获得焦点时,按下键盘按键才会触发。
- 前三次调用XNextEvent正常返回,是窗口首次调用
XMapRaised显示时,窗口管理器会连续推送2~3次初始Expose事件,这批初始事件处理完成后没有新的匹配事件产生,XNextEvent自然会进入阻塞状态。
验证方法
运行程序后点击窗口使其获得焦点,按下任意键盘按键,就能看到对应的printf输出,验证事件监听逻辑本身是正常的。
非阻塞轮询的修改方案
如果你需要窗口静止无事件时也能运行自定义逻辑,可以用XPending先判断是否有待处理事件,没有的话直接执行业务代码即可,参考修改如下:
#include <X11/keysym.h> // 新增头文件用于识别按键 // 其余原有代码保持不变 int main(){ init(); while (1){ if (XPending(dis) > 0) { // 先判断有没有待处理的事件 XNextEvent(dis, &event); if (event.type == Expose){ printf("Will this execute? Prolly not.\n"); } else if (event.type == KeyPress) { // 示例:按ESC键退出程序 if (XLookupKeysym(&event.xkey, 0) == XK_Escape) { close_program(); } } printf("Will this execute? no.\n"); } // 此处编写窗口静止时需要执行的逻辑 usleep(16000); // 控制循环帧率约为60FPS,避免CPU空转占用过高 } return 0; }
内容的提问来源于stack exchange,提问作者Caleb Burke
相关产品推荐
相关产品推荐

