--- /dev/null
+#!/usr/bin/env python3
+
+import subprocess
+import time
+import Xlib
+import Xlib.display
+
+display = Xlib.display.Display()
+root = display.screen().root
+NET_ACTIVE_WINDOW = display.intern_atom('_NET_ACTIVE_WINDOW')
+
+def main():
+ root.change_attributes(event_mask=Xlib.X.PropertyChangeMask)
+
+ handle_active_window_change()
+
+ while True:
+ event = display.next_event()
+ if is_active_window_change(event):
+ handle_active_window_change()
+
+def is_active_window_change(event):
+ return (
+ event.type == Xlib.X.PropertyNotify and
+ event.atom == NET_ACTIVE_WINDOW
+ )
+
+def handle_active_window_change():
+ window_id = get_active_window_id()
+ if not window_id:
+ focus_xfdesktop()
+
+def get_active_window_id():
+ prop = root.get_full_property(NET_ACTIVE_WINDOW, Xlib.X.AnyPropertyType)
+ if prop and prop.value:
+ return prop.value[0]
+
+def try_with_sleep(fn):
+ def wrapper(*args, **kwargs):
+ count = 0
+ while True:
+ try:
+ return fn(*args, **kwargs)
+ except:
+ if count > 5:
+ print("Failed finally")
+ raise
+ print("Failed, will retry")
+ time.sleep(1)
+ count += 1
+ return wrapper
+
+@try_with_sleep
+def focus_xfdesktop():
+ print("Focusing xfdesktop")
+ subprocess.check_output([
+ 'xdotool',
+ 'search',
+ '--onlyvisible',
+ '--class', 'xfdesktop',
+ 'windowfocus',
+ ])
+
+if __name__ == '__main__':
+ main()