Finding certain X window with Python's Xlib

6,455

The reason why there is no string "urxvt", "URxvt" is that XWindows are in hierrarchy. And for some reason, on my desktop, urxvt windows are not at the first level.

So one must traverse whole tree like this:

from Xlib.display import Display

def printWindowHierrarchy(window, indent):
    children = window.query_tree().children
    for w in children:
        print(indent, w.get_wm_class())
        printWindowHierrarchy(w, indent+'-')

display = Display()
root = display.screen().root
printWindowHierrarchy(root, '-')

One line of the (probably quite long) script output is then:

--- ('urxvt', 'URxvt')
Share:
6,455

Related videos on Youtube

Martin Jiřička
Author by

Martin Jiřička

Updated on September 18, 2022

Comments

  • Martin Jiřička
    Martin Jiřička over 1 year

    I am trying to find an unmapped window on my X server in order to map it back and send it some EWMH hint. Because the window is unmapped I cannot use EWMH to ask the window manager directly. So I am trying to get it through Xlib, but I am experiencing problems with it. The whole API is very confusing for me.

    I am using Python's Xlib wrapper. Now lets have a look at following Python script:

    import subprocess
    from time import sleep
    from ewmh import EWMH
    
    subprocess.Popen(['urxvt']) # Run some program, here it is URXVT terminal.
    sleep(1) # Wait until the term is ready, 1 second is really enought time.
    
    ewmh = EWMH() # Python has a lib for EWMH, I use it for simplicity here.
    
    # Get all windows?
    windows = ewmh.display.screen().root.query_tree().children
    
    # Print WM_CLASS properties of all windows.
    for w in windows: print(w.get_wm_class())
    

    What is output of the script? One opened URXVT terminal and something like this:

    None
    None
    None
    None
    ('xscreensaver', 'XScreenSaver')
    ('firefox', 'Firefox')
    ('Toplevel', 'Firefox')
    None
    ('Popup', 'Firefox')
    None
    ('Popup', 'Firefox')
    ('VIM', 'Vim_xterm')
    

    But when I run this command and click on the opened terminal:

    $ xprop | grep WM_CLASS
    WM_CLASS(STRING) = "urxvt", "URxvt"
    

    The same is with WM_NAME property.

    So finally a questions: Why there is no "URxvt" string in the output of the script?

  • Shi B.
    Shi B. over 4 years
    Thank you for the excellent answer Martin. However, would you consider revise your code? Because you are iterating the children of the root window and for each of the child, you are printing the parent WM_CLASS instead of the child's WM_CLASS. Changiing line 6 into print(indent, w.get_wm_class()) would make it much more meaningful in this case.
  • Martin Jiřička
    Martin Jiřička over 4 years
    @ShiB. Thank you for spotting the mistake! I fixed it exactly as you said.