13

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;
}
4

3 に答える 3

16

をご覧くださいxwininfo

また、より多くの情報を得るためにxprop好きかもしれません。xspy

更新:はい。xwininfoandをorと-root一緒に使用して、すべてのウィンドウを関与させてみてください。-tree-children

また、変更は で追跡できますxprop -spy

于 2009-06-19T14:17:50.087 に答える
3

X サーバー (XGrabServer(3)) を取得すると、ウィンドウ階層の変更が防止されると思います。ただし、少し手間がかかるため、本当に必要な場合にのみ実行する必要があります。

ウィンドウ階層をたどり、ツリーを構築し、ウィンドウ イベントを使用して最新の状態に保ち、競合のために避けられない X プロトコル エラーを無視するコードの例については、ファイルsrc/VBox/Additions/x11/VBoxClientを参照してください。 VirtualBox のソース コードの/seamless-x11.cpp 。

于 2010-03-17T11:53:04.187 に答える
1

X11 はリモート プロトコルです。これは、X サーバーに何らかの情報を照会すると、常に独自のコピーが取得されることを意味します。X サーバーが内部データ構造を更新しても、コピーが変更されることはありません。

これは、ツリーをトラバースしている間にツリーが突然変化することはありませんが、その情報を使用すると (ウィンドウを調べるなど)、その情報が古くなる可能性があることを意味します (誰かがウィンドウを閉じた可能性があります)。そのため、適切なエラー処理を行う必要があります。

于 2013-08-15T07:54:03.847 に答える