You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Xlib的简易窗口管理器上下文菜单消失Bug求助

解决Xlib窗口管理器中Chromium上下文菜单消失的问题

问题原因分析

你的窗口管理器存在三个核心问题,直接导致了菜单消失的现象:

  1. 强制修改所有窗口的大小位置:在ConfigureRequest事件处理中,你对所有请求调整的窗口(包括Chromium的上下文菜单、通知这类小窗口)都执行全屏缩放。这些菜单本来应该在鼠标附近以小尺寸显示,被强制改成全屏后要么被主窗口遮挡,要么视觉上看起来“消失”了。
  2. 未正确处理窗口映射请求:你没有单独处理MapRequest事件,而是在ConfigureRequest里调用XMapWindow,这会干扰菜单、通知这类临时窗口的正常显示逻辑。
  3. 未区分普通窗口与特殊窗口:菜单、通知等窗口通常带有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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 15:01:39