You are not logged in.

#1 2011-08-11 20:28:31

BurntSushi
Member
From: Massachusetts
Registered: 2009-06-28
Posts: 362
Website

xpybutil - A python library that makes X programming easier

This library is built on top of xpyb which uses XCB. It basically makes quite a few nasty things a bit less nasty. One big example is easy access to ICCCM and EWMH properties on the root and client windows.

As a trivial example, say you want to get the current desktop name:

from xpybutil import conn, root
import xpybutil.ewmh as ewmh

names = ewmh.get_desktop_names(conn, root).reply()
desk = ewmh.get_current_desktop(conn, root).reply()

print names[desk] if desk < len(names) else desk

I've had this library sitting around for a while, and to the best of my knowledge, everything in the EWMH spec is available in the ewmh module.

I think most of the stuff in ewmh/icccm is going to be pretty accessible to anyone with some experience in Python. They are also the most complete parts of xpybutil. The rest of xpybutil focuses on making other things easier, but still may require some X knowledge. (For example, keysym.py makes grabbing keys much much easier.)

As a more useful example, here's a short script that will run in the background and make all unfocused windows slightly transparent while making the active window completely opaque (if you have a compositing manager running):

# Makes all inactive windows transparent and keeps the active window opaque.

# Range of values: 0 <= opacity <= 1
# where 1 is fully opaque and 0 is completely invisible
opacity = 0.8

import xcb

from xpybutil import conn, root
import xpybutil.event as event
import xpybutil.ewmh as ewmh
import xpybutil.util as util

conn.core.ChangeWindowAttributes(root, xcb.xproto.CW.EventMask,
                                 [xcb.xproto.EventMask.PropertyChange])
conn.flush()

get_atom = util.get_atom
get_parent = util.get_parent_window
get_active = ewmh.get_active_window
set_opacity = ewmh.set_wm_window_opacity

def update_window_opacity():
    activewin = get_active(conn, root).reply()
    if not activewin:
        return

    for client in clients:
        set_opacity(conn, get_parent(conn, client), 
                    1 if client == activewin else opacity)

    conn.flush()

def client_is_normal(client):
    wtype = ewmh.get_wm_window_type(conn, client).reply()
    if not wtype or wtype[0] == get_atom(conn, '_NET_WM_WINDOW_TYPE_NORMAL'):
        return True
    return False

clients = filter(client_is_normal, ewmh.get_client_list(conn, root).reply())
update_window_opacity()

while True:
    event.read(conn, block=True)
    for e in event.queue():
        if not isinstance(e, xcb.xproto.PropertyNotifyEvent):
            continue

        aname = util.get_atom_name(conn, e.atom)
        if aname == '_NET_ACTIVE_WINDOW':
            update_window_opacity()
        elif aname == '_NET_CLIENT_LIST':
            clients = filter(client_is_normal, 
                             ewmh.get_client_list(conn, root).reply())

I've tested this on Openbox/xcompmgr, but it should work on any window manager that decorates their windows and complies with EWMH. It would work on an EWMH compliant tiling manager with some slight modification. (i.e., removing calls to get_parent and setting the opacity directly on the client.)

The API can be found here. And both examples are in the git respository.

TODO: More examples/explanations :-) I'll do my best to answer any questions here too.

xpybutil-git in the AUR.

Last edited by BurntSushi (2011-08-11 20:38:17)


Education is favorable to liberty. Freedom can exist only in a society of knowledge. Without learning, men are incapable of knowing their rights, and where learning is confined to a few people, liberty can be neither equal nor universal.

Tu ne cede malis sed contra audentior ito

Offline

Board footer

Powered by FluxBB