如何获得和同步,所有X11窗口的完整列表?(How do I obtain, and synchro

2019-06-23 16:43发布

我想监视X11下的所有打开的窗口。 目前,我这样做如下:

  1. 最初由递归从根窗口调用XQueryTree走在整个树
  2. 监听整个桌面上变化子: XSelectInput( display, root_window, SubstructureNotifyMask | PropertyChangeMask )
  3. 处理所有MapNotify,UnmapNotify和DestroyNotify事件,更新的过程中我自己的窗口列表

我主要是担心点1.在递归,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;
}

Answer 1:

看一看xwininfo

你可能还喜欢xpropxspy用于获取更多信息。

更新:是的。 尝试使用xwininfo-root有两种-tree-children涉足所有窗口。

和变化可以被跟踪xprop -spy



Answer 2:

我认为,抓住了X服务器(XGrabServer(3))将阻止更改窗口层次结构。 这是一个有点重手的,所以你应该只有这样做,如果你真的需要它。

对于走在窗口层次,构建了一棵树,使用窗口事件,以保持它是最新的,并且忽略了由于比赛是不可避免的X协议错误的代码示例,请参阅文件的src /垂直框/添加/ X11 / VBoxClient /seamless-x11.cpp在VirtualBox的源代码。



Answer 3:

X11是一个远程协议。 这意味着当您查询X服务器的任何信息,你总能得到自己的副本。 当X服务器更新其内部数据结构的副本永远不会改变。

这意味着树不会突然改变,而你穿越它,但是当你使用它的信息(如检查的窗口),这些信息可能是陈旧的(有人可能已经关闭了窗口)。 这就是为什么你需要做适当的错误处理。



文章来源: How do I obtain, and synchronize, a complete list of all X11 windows?