我正在使用 arch linux 和一个基本的 cpp 自定义窗口管理器。但是,每次我右键单击打开上下文菜单时,它都会闪烁并消失。我根本无法使用它。我也无法在任何应用程序上使用顶部下拉菜单(文件、编辑、关于等)。 Xlib 中是否有我必须注意的内容以确保我可以正常使用上下文菜单?
我尝试过的每个应用程序都是这种情况。我唯一的线索是勇敢它偶尔会显示以下消息:
XGetWindowAttributes failed for window [WINDOW_ID]
搜索错误带来了一些特定于 chromium 的结果,但没有任何内容适用于一般的 Linux。任何有关如何解决甚至调试此问题的线索都值得赞赏!
以下简化示例展示了此问题:
int main()
{
display = XOpenDisplay(nullptr);
root = DefaultRootWindow(display);
XSelectInput(display, root, SubstructureRedirectMask | SubstructureNotifyMask | StructureNotifyMask);
XGrabServer(display);
Window returned_root;
Window returned_parent;
Window* top_level_windows;
unsigned int num_top_level_windows;
XQueryTree(display, root, &returned_root, &returned_parent, &top_level_windows, &num_top_level_windows);
for(unsigned int i = 0; i < num_top_level_windows; ++i)
{
Frame(top_level_windows[i], true);
}
XFree(top_level_windows);
XUngrabServer(display);
for(;;)
{
XEvent event;
XNextEvent(display, &event);
switch (event.type)
{
case MapRequest:
{
Frame(event.xmaprequest.window, false);
XMapWindow(display, event.xmaprequest.window);
break;
}
case ConfigureRequest:
OnConfigureRequest(event.xconfigurerequest);
break;
case ButtonPress:
XRaiseWindow(display, event.xbutton.window);
break;
}
}
return true;
}
void OnConfigureRequest(const XConfigureRequestEvent& event)
{
XWindowChanges changes;
changes.x = event.x;
changes.y = event.y;
changes.width = event.width;
changes.height = event.height;
changes.border_width = event.border_width;
changes.sibling = event.above;
changes.stack_mode = event.detail;
if(frame_list.count(event.window))
{
const Window frame = event.window;
XConfigureWindow(display, frame, event.value_mask, &changes);
}
//Grant request
XConfigureWindow(display, event.window, event.value_mask, &changes);
}
void Frame(Window window, bool created_before_manager)
{
//Retrieve attributes of window to frame
XWindowAttributes attr = {0};
XGetWindowAttributes(display, window, &attr);
//If window was created before window manager started, we should frame it only if it is visible and does not set override_redirect
if(created_before_manager && (attr.override_redirect || attr.map_state != IsViewable))
{
return;
}
//Create frame
Window frame = XCreateSimpleWindow(display, root, attr.x, attr.y, attr.width, attr.height, 5, 0xff0000, 0xffffff);
XReparentWindow(display, window, frame, 0, 0);
XMapWindow(display, frame);
XGrabButton(display, Button1Mask, Mod1Mask, window, None, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
}
在一个超级简单的示例中也发现了该问题,例如:
int main()
{
Display* display = XOpenDisplay(nullptr);
for(;;) {}
return true;
}
我认为窗口管理器有问题的原因是因为此问题仅在我运行窗口管理器后才会发生。
答案1
答案来自这个问题的堆栈溢出版本:
需要确保客户端窗口有输入。我将输入设置为单击的任何内容(框架、标题栏或客户端),因为就正常输入而言,它工作得很好。但是,只有在确保输入直接设置到客户端窗口时,上下文菜单才会起作用。