我想监视X11下所有打开的窗口。目前,我这样做如下:
XSelectInput( display, root_window, SubstructureNotifyMask | PropertyChangeMask )我主要担心的是第一点,在递归过程中,XQueryTree将被多次调用。有没有办法确保这棵树在这段时间内不发生变化?换句话说,在某个时间点获得整棵树的“快照”?
另外,我注意到在某些X11系统中,并不是所有事件都能正确到达。例如,当在桌面上打开一个新窗口时,该窗口的MapNotify可能永远不会到达我的监视应用程序。这怎么可能呢?它有可能在到达前被扔掉吗?
更新:
我编写了一个小程序来监视根窗口上的X事件(见下文)。现在,当我运行这个程序并启动和退出xcalc时,我得到以下输出:
Reparented: 0x4a0005b to 0x1001e40
Mapped : 0x1001e40
Destroyed : 0x1001e40就这样。我从未被告知真正的窗口(0x4a0005b)正在被销毁。甚至连地图都没有!有人能告诉我为什么吗?SubStructureNotifyMask只会导致直接子窗口的事件被发送而不是整个子树吗?
顺便说一下,这显然不是在Compiz运行时发生的。然后不进行任何赔偿:
Mapped : 0x4a0005b
Mapped : 0x4e00233
Destroyed : 0x4a0005b
Destroyed : 0x4e00233监测程序来源:
#include <X11/Xlib.h>
#include <cstdio>
int main()
{
Display *display;
Window rootwin;
display = XOpenDisplay( NULL );
rootwin = DefaultRootWindow( display );
XSelectInput( display, rootwin, SubstructureNotifyMask );
XEvent event;
while ( 1 ) {
XNextEvent( display, &event );
if ( event.type == MapNotify ) {
XMapEvent *mapevent = (XMapEvent *)&event;
printf( "Mapped : 0x%x\n", (unsigned int)(mapevent->window) );
}
if ( event.type == DestroyNotify ) {
XDestroyWindowEvent *destroywindowevent = (XDestroyWindowEvent *)&event;
printf( "Destroyed : 0x%x\n", (unsigned int)(destroywindowevent->window) );
}
if ( event.type == ReparentNotify ) {
XReparentEvent *reparentevent = (XReparentEvent *)&event;
printf( "Reparented: 0x%x to 0x%x\n", (unsigned int)(reparentevent->window), (unsigned int)(reparentevent->parent) );
}
}
return 0;
}发布于 2009-06-19 14:17:50
看看xwininfo。
您可能还喜欢xprop和xspy来获取更多信息。
更新:是的。尝试将xwininfo和-root与-tree或-children一起使用,以使所有的窗口都参与进来。
并且可以使用xprop -spy跟踪更改。
发布于 2010-03-17 11:53:04
我相信抓取X服务器(XGrabServer(3))将防止对窗口层次结构的更改。这是一个有点沉重的手,所以你可能应该做它,只有当你真的需要它。
对于一个代码示例,它可以遍历窗口层次结构、构建树、使用窗口事件来保持其最新,并忽略由于种族而不可避免的X协议错误,请参阅VirtualBox源代码中的文件VirtualBox。
发布于 2013-08-15 07:54:03
X11是一种远程协议。这意味着当您查询X服务器的任何信息时,总是会得到您自己的副本。当X服务器更新其内部数据结构时,您的副本不会更改。
这意味着当您遍历树时,树不会突然改变,但是当您使用其中的信息(比如检查窗口)时,该信息可能会过时(可能有人已经关闭了该窗口)。这就是为什么您需要进行正确的错误处理。
https://stackoverflow.com/questions/1018052
复制相似问题