I'd like to monitor which window is active on a Linux system running X, and when that active window gets resized or moved. I can monitor the active window (it's held in the _NET_ACTIVE_WINDOW
property on the root window, and I can register for PropertyNotify
events on the root window to discover when that property changes). However, I don't know how to monitor the active window to know whether it gets resized or moved.
import Xlib
import Xlib.display
disp = Xlib.display.Display()
Xroot = disp.screen().root
NET_ACTIVE_WINDOW = disp.intern_atom('_NET_ACTIVE_WINDOW')
Xroot.change_attributes(event_mask=Xlib.X.PropertyChangeMask)
while True:
# loop until an event happens that we care about
# we care about a change to which window is active
# (NET_ACTIVE_WINDOW property changes on the root)
# or about the currently active window changing
# in size or position (don't know how to do this)
event = disp.next_event()
if (event.type == Xlib.X.PropertyNotify and
event.atom == NET_ACTIVE_WINDOW):
active = disp.get_input_focus().focus
try:
name = active.get_wm_class()[1]
except TypeError:
name = "unknown"
print("The active window has changed! It is now", name)
Is there a way to do this? It might involve listening to ConfigureNotify events on the currently active window (and calling change_attributes
on that window when it becomes active to set an appropriate mask), but I can't get this to work.
(Note: I'm not using Gtk, so no Gtk solutions, please.)
Update: there is a rather suspect approach to detecting window resizes, by watching the active window for the value of the _NET_WM_OPAQUE_REGION
property changing (since I correctly receive PropertyChange events, although I don't receive ConfigureNotify events). However, it's not clear that all window managers set this property, and this only changes on a window resize; it does not change on a window move (and nor does any other property).