我正在运行“dwm”平铺窗口管理器。在另一个虚拟终端中,我使用
sudo gdb -p $(pidof dwm)
将 gdb 连接到 dwm,并在 enternotify
函数 (b enternotify
) 上设置了断点。每次收到 EnterNotify 事件时都会调用 enternotify
函数,因此通过在此处设置断点,我可以检测 dwm 何时收到 EnterNotify 事件。
正如预期的那样,当我将鼠标移动到另一个窗口时,断点被命中,我必须告诉 gdb 继续执行程序。当鼠标位于空监视器上并且我将窗口移动到该监视器上时,也会命中断点。
问题出在以下场景中:我打开了两个窗口“A”和“B”,每个窗口占据了显示器的一半。指针位于屏幕右上角的“A”窗口上方(请参见第一张图片)。然后我使用键盘快捷键打开另一个窗口,该窗口出现在屏幕左侧,dwm 将“A”移动到右下角,将“B”移动到右上角。现在指针位于窗口“B”上方(参见第二张图片)。现在,指针位于与之前不同的窗口上,但未命中断点,这意味着未生成 EnterNotify 事件。怎么会这样? docs 说“如果指针移动或窗口层次结构更改导致指针位于与以前不同的窗口中,X 服务器将向选择这些事件的客户端报告 EnterNotify 或 LeaveNotify 事件。”。在这种情况下,显然窗口层次结构已发生变化,导致指针位于与以前不同的窗口中,因此肯定应该生成 EnterNotify 事件。
编辑:如果我执行相同的操作,但不是创建新窗口,而是将现有窗口从不同的监视器移动到带有指针的监视器上,那么断点就会命中?!
所有窗口都订阅 EnterNotify 事件:
...
/* called after MapRequest */
XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
...
...
/* on setup, the root window is subscribed */
wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask
|ButtonPressMask|PointerMotionMask|EnterWindowMask
|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
XSelectInput(dpy, root, wa.event_mask);
...
完整的 dwm 源代码位于
git://git.suckless.org/dwm