基于Xlib的简易窗口管理器上下文菜单消失Bug求助
解决Xlib窗口管理器中Chromium上下文菜单消失的问题
问题原因分析
你的窗口管理器存在三个核心问题,直接导致了菜单消失的现象:
- 强制修改所有窗口的大小位置:在
ConfigureRequest事件处理中,你对所有请求调整的窗口(包括Chromium的上下文菜单、通知这类小窗口)都执行全屏缩放。这些菜单本来应该在鼠标附近以小尺寸显示,被强制改成全屏后要么被主窗口遮挡,要么视觉上看起来“消失”了。 - 未正确处理窗口映射请求:你没有单独处理
MapRequest事件,而是在ConfigureRequest里调用XMapWindow,这会干扰菜单、通知这类临时窗口的正常显示逻辑。 - 未区分普通窗口与特殊窗口:菜单、通知等窗口通常带有
override-redirect属性(表示不需要WM干预其位置大小),你的WM没有识别这类窗口,错误地对它们进行了全屏修改。
修复方案
1. 区分处理普通窗口与特殊窗口
在处理窗口请求时,先获取窗口属性,判断是否为override-redirect窗口:
- 对普通应用窗口(非override-redirect)继续保持全屏逻辑
- 对特殊窗口(如菜单、通知)尊重它们的原始位置和大小请求
2. 正确处理MapRequest事件
单独处理窗口映射请求,避免在ConfigureRequest中错误触发映射操作。
修复后的完整代码
#include <X11/Xlib.h> #include <stdlib.h> // 重命名宏,避免和标准库strtok冲突 #define keysym_to_keycode(s) XKeysymToKeycode(dpy, XStringToKeysym(s)) #define grab_key(m, k) XGrabKey(dpy, keysym_to_keycode(k), m, r, True, GrabModeAsync, GrabModeAsync) #define map_key(k, c) if (e.xkey.keycode == keysym_to_keycode(k)) { c; continue; } int main () { Display *dpy = XOpenDisplay(0); Window r = DefaultRootWindow(dpy); XEvent e; XWindowAttributes attr; XSelectInput(dpy, r, SubstructureNotifyMask | SubstructureRedirectMask); grab_key(Mod4Mask, "q"); grab_key(Mod4Mask, "Left"); grab_key(Mod4Mask, "Right"); grab_key(Mod4Mask, "Return"); grab_key(Mod4Mask, "space"); while (!XNextEvent(dpy, &e)) { if (e.type == KeyPress) { map_key("q", XKillClient(dpy, e.xkey.subwindow);); map_key("Left", XCirculateSubwindowsDown(dpy, r)); map_key("Right", XCirculateSubwindowsUp(dpy, r)); map_key("Return", system("xterm &")); map_key("space", system("chromium &")); } if (e.type == MapRequest) { XGetWindowAttributes(dpy, e.xmaprequest.window, &attr); // 仅对普通窗口强制全屏 if (!attr.override_redirect) { XMoveResizeWindow(dpy, e.xmaprequest.window, 0, 0, 1920, 1080); } // 执行映射操作 XMapWindow(dpy, e.xmaprequest.window); } if (e.type == ConfigureRequest) { XGetWindowAttributes(dpy, e.xconfigure.window, &attr); if (!attr.override_redirect) { // 普通窗口保持全屏 XMoveResizeWindow(dpy, e.xconfigure.window, 0, 0, 1920, 1080); } else { // 特殊窗口尊重原始请求 XConfigureWindow(dpy, e.xconfigure.window, e.xconfigure.value_mask, &e.xconfigure); } } } }
额外说明
- 重命名了
strtok宏,避免与C标准库的strtok函数冲突,这是潜在的bug点 - 处理
MapRequest时先判断窗口属性,确保特殊窗口能按预期位置显示 - 特殊窗口的
ConfigureRequest直接使用XConfigureWindow转发原始请求,保证它们的大小和位置正确
内容的提问来源于stack exchange,提问作者user8747928
相关产品推荐
相关产品推荐

