Does xlib have an active window event?
Asked Answered
M

3

5

I am trying to write a program that tracks when the active window changes using Xlib. I am have trouble figuring out the best way to do this. These are my ideas so far:

  • Every second use _NET_ACTIVE_WINDOW to get the active window and if it has changed then running the related code for the event.
  • Get a list of all windows and listen to their focus in event. I would have to figure out how to keep an up to date list of open windows though.

Is their an easier/better way? I am new to programming with Xlib.

Meddlesome answered 10/3, 2011 at 16:10 Comment(2)
Listening to all focus events plus registering all the handlers for all the windows seems extremely expensive. I wonder if, in fact, listening to PointerMove in general and then calling XGetInputFocus() from the event handler to find out who has it when moved would be less overhead. How realtime does this have to be ? If the answer to that is "a sec is fine" then the polling method seems best.Gemination
It doesn't have to be real time, with in a couple of seconds would be okay. I will give my first method a try. Thanks FrankH.Meddlesome
C
7

Here's a Python implementation of what @alanc proposed.

import Xlib
import Xlib.display

disp = Xlib.display.Display()
root = disp.screen().root

NET_ACTIVE_WINDOW = disp.intern_atom('_NET_ACTIVE_WINDOW')
NET_WM_NAME = disp.intern_atom('_NET_WM_NAME')

last_seen = {'xid': None}
def get_active_window():
    window_id = root.get_full_property(NET_ACTIVE_WINDOW,
                                       Xlib.X.AnyPropertyType).value[0]

    focus_changed = (window_id != last_seen['xid'])
    last_seen['xid'] = window_id

    return window_id, focus_changed

def get_window_name(window_id):
    try:
        window_obj = disp.create_resource_object('window', window_id)
        window_name = window_obj.get_full_property(NET_WM_NAME, 0).value
    except Xlib.error.XError:
        window_name = None

    return window_name


if __name__ == '__main__':
    root.change_attributes(event_mask=Xlib.X.PropertyChangeMask)
    while True:
        win, changed = get_active_window()
        if changed:
            print(get_window_name(win))

        while True:
            event = disp.next_event()
            if (event.type == Xlib.X.PropertyNotify and
                    event.atom == NET_ACTIVE_WINDOW):
                break

The more fully-commented version I wrote as an example for someone is in this gist.

Crab answered 2/1, 2017 at 11:50 Comment(0)
A
3

Can't you just select PropertyChange on the root window to get sent PropertyNotify events when any property is updated and then check each event to see if it was for _NET_ACTIVE_WINDOW?

Ashlynashman answered 16/6, 2011 at 21:28 Comment(0)
H
-1

I've been looking for "active windows change event grabber" as well. What I use in mean time (and might be helpful for you) is combination of xdotool and xwininfo.

xwininfo -id "$(xdotool getactivewindow)"
Hadsall answered 16/6, 2011 at 11:54 Comment(2)
this gets the active window information, but how does it help in registering an event handler?Beckett
Once again, this is not a 'C' answer. And coming from someone with 10.7k?!? Stackoverflow, you are killing yourself. You use to be so good, now you've lost the plot.Assumpsit

© 2022 - 2024 — McMap. All rights reserved.