How to “correctly” detect application name when changing focus event occurs with python xlib
application-name, detect, focus, python, xlib
Solution
Your code is almost right, but it misses two things:
- rather than listening only to focus changes, it should also listen to window property events which include changes of `WM_NAME` property, that also happen when you cycle tabs in your browser.
- rather than listening only in root window, it should listen to every window (that gets focused). You can attach the event handler the same way as you do with the root window.
That being said, here is a working sample:
#!/usr/bin/python3
import Xlib
import Xlib.display
disp = Xlib.display.Display()
root = disp.screen().root
NET_WM_NAME = disp.intern_atom('_NET_WM_NAME')
NET_ACTIVE_WINDOW = disp.intern_atom('_NET_ACTIVE_WINDOW')
root.change_attributes(event_mask=Xlib.X.FocusChangeMask)
while True:
try:
window_id = root.get_full_property(NET_ACTIVE_WINDOW, Xlib.X.AnyPropertyType).value[0]
window = disp.create_resource_object('window', window_id)
window.change_attributes(event_mask=Xlib.X.PropertyChangeMask)
window_name = window.get_full_property(NET_WM_NAME, 0).value
except Xlib.error.XError: #simplify dealing with BadWindow
window_name = None
print(window_name)
event = disp.next_event()
Problem
I want to detect applications window name when changing focus event occurs with python xlib, so in the first step I use this code: ``` #!/usr/bin/env python #-*- coding:utf-8 -*- import Xlib.display import time display = Xlib.display.Display() while True: window = display.get_input_focus().focus wmname = window.get_wm_name() wmclass = window.get_wm_class() if wmclass is None and wmname is None: window = window.query_tree().parent wmname = window.get_wm_name() print "WM Name: %s" % ( wmname, ) time.sleep(3) ``` But I want a correct way, then I research about xlib events and find Input Focus Events and write this code: ``` #!/usr/bin/env python #-*- coding:utf-8 -*- import Xlib.display from Xlib import X def main(): display = Xlib.display.Display(':0') root = display.screen().root root.change_attributes(event_mask=Xlib.X.FocusChangeMask) while True: event = root.display.next_event() #if event.type == X.FocusIn or event.type == X.FocusOut: if event.type == X.FocusOut : window = display.get_input_focus().focus wmname = window.get_wm_name() wmclass = window.get_wm_class() if wmclass is None and wmname is None: window = window.query_tree().parent wmname = window.get_wm_name() print "WM Name: %s" % ( wmname, ) if __name__ == "__main__": main() ``` Sadly it's not work correctly especially in tabbed browsing on google chrome and firefox, so Is there a correct way for this situation?