10

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?

7

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')
2
  • 1
    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.
    – Shi B.
    Oct 29 '19 at 5:58
  • 2
    @ShiB. Thank you for spotting the mistake! I fixed it exactly as you said. Oct 31 '19 at 8:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.