2009-06-19 5 views
13

私はX11で開いているすべてのウィンドウを監視したいと思います。次のように現在、私はこれをやっている:すべてのX11ウィンドウの完全なリストを取得して同期するにはどうすればよいですか?

  1. は、最初は再帰的に全体のデスクトップ上の部分構造変化のリスニングルートウィンドウ
  2. からXQueryTreeを呼び出すことによって、ツリー全体を歩いて:すべてのMapNotify、UnmapNotifyの取り扱いXSelectInput(display, root_window, SubstructureNotifyMask | PropertyChangeMask)
  3. DestroyNotifyイベントを使用して、プロセス内のウィンドウのリストを更新します。

私は主にポイント1が気になります。再帰中に、XQueryTreeが複数回呼び出されます。その間に木が変わらないようにする方法はありますか?言い換えれば、ある時点でツリー全体の「スナップショット」を取得することですか?

また、私はいくつかのX11システムの下で、すべてのイベントが正しく到着していないことに気付きました。たとえば、デスクトップ上で新しいウィンドウを開くと、そのウィンドウのMapNotifyが自分の監視アプリケーションに届かないことがあります。どうすればいいの?到着する前に捨てられる可能性はありますか?

更新:

私は(下記参照)ルートウィンドウ上でXのイベントを監視する小さなプログラムを書いています。

Reparented: 0x4a0005b to 0x1001e40 
Mapped : 0x1001e40 
Destroyed : 0x1001e40 

ことだ:私はこのプログラムを実行し、xcalcを開始し、終了時に今、私は次の出力を取得します。 本当のウィンドウ(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; 
} 

答えて

16

xwininfoを見てください。

はまた、より多くの情報を得るためxpropxspyを好むかもしれません。

更新:うん。関連するすべてのウィンドウを取得するか-treeまたは-childrenxwininfo-rootを使用してみてください。

や変更はxprop -spyで追跡することができます。

+1

ありがとうございます!私はxwininfoのソースコードを見て、それと同じように木を横断するように見えます。 XQueryTreeの呼び出しの間にツリーが変更される可能性がある場合、xwininfoも影響を受けて、私が推測する正しい結果は得られません。 – Marten

+1

@Marten、はい。 xwininfoはスナップショットですが、それはあなたに階層を与えます。次に、いくつかのウィンドウを開き、それらを使ってxprop -spyを実行して更新をチェックすることができます。これらのツールのかなりの数があります。 http://www.x.org/archive/X11R6.9.0/doc/html/manindex1.html –

3

私はXサーバ(XGrabServer(3))をつかんでもウィンドウ階層の変更ができなくなると思います。しかし、少し重いですので、本当に必要な場合は、おそらくそれを行う必要があります。

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

+1

のmanページリストを見てください。XGrabServerは完全な注意を払いますが、他のすべてのクライアントとの接続も切断しますこのために役に立たない –

+0

XGrabServerは他のクライアント接続を閉じることはありません。XGrabServerは、Xサーバーがそれらの上の要求を処理するのを止め、グラブを解放するまでそれらをすべて凍結します。あなたのコードは、しかし、グラブ中にハングアップしている場合は、あなたはかなりあなたと一緒に残して、ユーザーセッションを基本的に凍結している。 – alanc

0

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

これは、横断中にツリーが突然変更されないことを意味しますが、(ウィンドウの検査のような)その情報を使用すると、その情報は古くなっている可能性があります。そのため、適切なエラー処理を行う必要があります。

関連する問題