Python / X11:了解用户是否切换虚拟桌面

时间:2010-04-14 23:32:36

标签: python gtk pygtk x11

我正在寻找一种方法来确定用户是否在X11下切换虚拟桌面。

我正在使用Python和X11库以及PyGTK。我在C中找到了一些工作示例,但是我缺乏将它们翻译成Python的专业知识,并且我阅读了几个X11寻呼机应用程序(fbpanel,pypanel)的源代码,但我似乎无法找到我正在寻找的内容

我必须注册信号吗?使用X11还是GTK? 我是否需要忙碌等待?

我对X11和GTK都是全新的,所以任何提示/帮助都会非常感激。

电贺, 菲利普

PS:我目前的努力可以找到here

4 个答案:

答案 0 :(得分:1)

这是基于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包含通常与工作区交换机关联的事件。不过,这个解决方案感觉有点尴尬。有什么想法吗?

电贺, 菲利普

答案 1 :(得分:0)

您可能需要查看libwnck或可能的Python绑定。

答案 2 :(得分:0)

通常,根窗口上的属性更改会向客户端通知桌面更改, 所以听一下PROPERTY_CHANGE_MASK而不是SUBSTRUCTURE_MASK; 这样可以减少噪音。

对于属性发生变化的,我怀疑它们之间有所不同 不同的windowmanagers /桌面/无论如何;我正在运行ubuntu / unity和 当我做" xprop -root"在桌面切换之前和之后,并对结果进行区分, 我发现更改的属性是_NET_DESKTOP_VIEWPORT。

我得到的主要噪音是根窗口 每次活动窗口更改时,_NET_ACTIVE_WINDOW属性都会更改。

答案 3 :(得分:0)

另一种改进:使用GDK_SUBSTRUCTURE_MASK代替Don Hatch says,而不是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();
}