Python/X11: узнайте, переключает ли пользователь виртуальные рабочие столы

Я ищу способ определить, переключает ли пользователь виртуальные рабочие столы под X11.

Я использую Python с библиотеками X11 и PyGTK. Я нашел несколько рабочих примеров на C, но мне не хватает опыта, чтобы перевести их на Python, и я прочитал исходный код нескольких приложений пейджера X11 (fbpanel, pypanel), но не могу найти то, что ищу .

Должен ли я регистрироваться для получения сигнала? Используете X11 или GTK? Я должен быть занят-ждать?

Я совершенно новичок как в X11, так и в GTK, поэтому любые подсказки/помощь будут очень признательны.

Приветствую, Филипп

PS: мои текущие усилия можно найти здесь.


person Philip    schedule 14.04.2010    source источник


Ответы (4)


Вот решение на основе GTK:

screen = gtk.gdk.screen_get_default()
root = screen.get_root_window()
root.set_events(gtk.gdk.SUBSTRUCTURE_MASK)
root.add_filter(event_filter)

def event_filter(event, user_data):
        # process event
        return gtk.gdk.FILTER_CONTINUE

По-видимому, SUBSTRUCTURE_MASK содержит события, которые обычно связаны с переключением рабочей области. Тем не менее, это решение кажется немного неудобным. Любые идеи?

Приветствую, Филипп

person Philip    schedule 08.05.2010

Вы можете взглянуть на libwnck или, возможно, на его привязки к Python.

person Ignacio Vazquez-Abrams    schedule 14.04.2010
comment
Я уже изучил libwnck (что исключительно удобно), но я не хочу добавлять еще одну зависимость в программу, когда я могу решить ее с помощью X11/GTK. - person Philip; 15.04.2010

Обычно об изменении рабочего стола сообщается клиентам посредством изменения свойств в корневом окне, поэтому прислушивайтесь к PROPERTY_CHANGE_MASK вместо SUBSTRUCTURE_MASK; это даст вам намного меньше шума.

Что касается изменения свойства какое, я подозреваю, что оно различается для разных оконных менеджеров/рабочих столов/что угодно; Я запускаю ubuntu/unity, и когда я делаю «xprop -root» до и после переключения рабочего стола и сравниваю результаты, я обнаруживаю, что измененным свойством является _NET_DESKTOP_VIEWPORT.

Кроме того, основной шум, который я получаю, заключается в том, что свойство _NET_ACTIVE_WINDOW корневого окна изменяется каждый раз, когда изменяется активное окно.

person Don Hatch    schedule 15.03.2014

Еще одно уточнение: вместо GDK_SUBSTRUCTURE_MASK, как говорит Дон Хэтч, используйте GDK_PROPERTY_CHANGE_MASK. Более того, именно то свойство, которое вас интересует, это _NET_CURRENT_DESKTOP. Это 32-битное свойство, значением которого является номер рабочего стола, отсчитываемый от 0.

Вот полный компилируемый и работающий пример, который улавливает момент переключения рабочего стола и сообщает номер текущего рабочего стола после этого. Пример на C, так как я не владею Python, надеюсь, вы сможете перевести.

#include <gtk/gtk.h>
#include <gdk/gdkx.h>

GdkFilterReturn propertyChangeFilter(GdkXEvent* xevent, GdkEvent*e, gpointer data)
{
    const XPropertyEvent*const propEvt=(const XPropertyEvent*)xevent;

    if(propEvt->type!=PropertyNotify)
        return GDK_FILTER_CONTINUE;
    if(propEvt->state!=PropertyNewValue)
        return GDK_FILTER_CONTINUE;
    const Atom NET_CURRENT_DESKTOP=(Atom)data;
    if(propEvt->atom!=NET_CURRENT_DESKTOP)
        return GDK_FILTER_CONTINUE;

    fprintf(stderr, "Desktop change detected\n");
    Atom actualType;
    int actualFormat;
    unsigned long nitems, remainingBytes;
    unsigned char* prop;
    if(XGetWindowProperty(propEvt->display, propEvt->window, propEvt->atom,
                          0, 1, False, AnyPropertyType,
                          &actualType, &actualFormat, &nitems, &remainingBytes,
                          &prop) != Success)
    {
        fprintf(stderr, "Failed to get current desktop number\n");
        return GDK_FILTER_CONTINUE;
    }
    if(nitems!=1 || remainingBytes!=0 || actualFormat!=32)
    {
        XFree(prop);
        fprintf(stderr, "Unexpected number of items (%lu) or remaining bytes (%lu)"
                        " or format (%d)\n", nitems, remainingBytes, actualFormat);
        return GDK_FILTER_CONTINUE;
    }
    guint32 value;
    memcpy(&value, prop, sizeof value);
    XFree(prop);
    fprintf(stderr, "Current desktop: %u\n", value);

    return GDK_FILTER_CONTINUE;
}

int main(int argc, char** argv)
{
    gtk_init(&argc,&argv);

    GdkDisplay*const gdkDisplay=gdk_display_get_default();
    Display*const display=gdk_x11_display_get_xdisplay(gdkDisplay);
    const Atom atom=XInternAtom(display, "_NET_CURRENT_DESKTOP", True);
    GdkWindow*const root=gdk_get_default_root_window();
    gdk_window_set_events(root, GDK_PROPERTY_CHANGE_MASK);
    gdk_window_add_filter(root, propertyChangeFilter, (gpointer)atom);

    gtk_main();
}
person Ruslan    schedule 12.07.2020