Finden eines bestimmten X-Fensters mit Pythons Xlib

8

Ich versuche, ein nicht zugeordnetes Fenster auf meinem X-Server zu finden, um es wieder zuzuordnen und einen EWMH- Hinweis zu senden . Da das Fenster nicht zugeordnet ist, kann ich EWMH nicht verwenden, um den Fenstermanager direkt zu fragen. Ich versuche es über Xlib zu bekommen, aber ich habe Probleme damit. Die gesamte API ist für mich sehr verwirrend.

Ich verwende Pythons Xlib-Wrapper . Schauen wir uns nun das folgende Python-Skript an:

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())

Was ist die Ausgabe des Skripts? Ein geöffnetes URXVT-Terminal und so etwas:

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

Aber wenn ich diesen Befehl ausführe und auf das geöffnete Terminal klicke:

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

Gleiches gilt für die Eigenschaft WM_NAME .

Also endlich eine Frage: Warum gibt es keine "URxvt" -String in der Ausgabe des Skripts?

Martin Jiřička
quelle

Antworten:

5

Der Grund, warum es keine Zeichenfolge "urxvt", "URxvt" gibt, ist, dass XWindows in Hierarchie sind. Und aus irgendeinem Grund befinden sich urxvt-Fenster auf meinem Desktop nicht auf der ersten Ebene.

Man muss also den ganzen Baum so durchqueren:

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, '-')

Eine Zeile der (wahrscheinlich ziemlich langen) Skriptausgabe lautet dann:

--- ('urxvt', 'URxvt')
Martin Jiřička
quelle
1
Vielen Dank für die hervorragende Antwort Martin. Würden Sie jedoch in Betracht ziehen, Ihren Code zu überarbeiten? Da Sie die untergeordneten Elemente des Stammfensters und für jedes untergeordnete Element iterieren, drucken Sie die übergeordnete WM_CLASS anstelle der untergeordneten WM_CLASS. Das Ändern von Zeile 6 in print (Einzug, w.get_wm_class ()) würde es in diesem Fall viel aussagekräftiger machen.
Shi B.
2
@ ShiB. Vielen Dank, dass Sie den Fehler entdeckt haben! Ich habe es genau so repariert, wie du es gesagt hast.
Martin Jiřička