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?
Your code is almost right, but it misses two things:
WM_NAME
property, that also happen when you cycle tabs in your browser.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()