Как получить и синхронизировать полный список всех окон X11? - PullRequest
13 голосов
/ 19 июня 2009

Я хочу контролировать все открытые окна под 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 только события direct подокна вместо всего поддерева?

Кстати, этого, очевидно, не происходит, когда 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;
}

Ответы [ 3 ]

16 голосов
/ 19 июня 2009

Посмотрите на xwininfo.

Вам также могут понравиться xprop и xspy для получения дополнительной информации.

Обновление: Да. Попробуйте использовать xwininfo и -root с -tree или -children, чтобы задействовать все окна.

И изменения можно отслеживать с помощью xprop -spy.

3 голосов
/ 17 марта 2010

Я считаю, что захват X-сервера (XGrabServer (3)) предотвратит изменения в иерархии окон. Это немного тяжеловато, поэтому вам, вероятно, следует делать это только в том случае, если вам это действительно нужно.

Пример кода, который обходит иерархию окон, создает дерево, использует события окна для его обновления и игнорирует ошибки протокола X, которые неизбежны из-за гонок, см. В файле src / VBox /Additions/x11/VBoxClient/seamless-x11.cpp в исходном коде для VirtualBox.

0 голосов
/ 15 августа 2013

X11 - это удаленный протокол. Это означает, что когда вы запрашиваете у X-сервера любую информацию, вы всегда получаете свою собственную копию. Ваша копия никогда не меняется, когда X-сервер обновляет свои внутренние структуры данных.

Это означает, что дерево не будет внезапно меняться, пока вы проходите по нему, но когда вы используете информацию в нем (например, при исследовании окна), эта информация может быть устаревшей (кто-то мог закрыть окно). Вот почему вам нужно правильно обрабатывать ошибки.

...