#!/usr/bin/python3 import Xlib import Xlib.display from zope import interface from interfaces import desktopEvent from threading import Thread from interfaces.message import IMessage, Debug from zope import component @interface.implementer(desktopEvent.IDesktop) class Listener(Thread): def __init__(self, mapping, queue): Thread.__init__(self) self.queue = queue self.mapping = mapping self.active_window = None self.last_code = None self.running = False def getForegroundWindowTitle(self): """ Return the name of the selected window """ return self.active_window def run(self): disp = Xlib.display.Display() NET_WM_NAME = disp.intern_atom('_NET_WM_NAME') WM_CLASS = disp.intern_atom('WM_CLASS') NET_ACTIVE_WINDOW = disp.intern_atom('_NET_ACTIVE_WINDOW') root = disp.screen().root root.change_attributes(event_mask=Xlib.X.PropertyChangeMask) component.handle(Debug("Waiting for xlib event")) self.running = True while self.running: 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 = str(window.get_full_property(NET_WM_NAME, 0).value).lower() class_name = str(window.get_full_property(WM_CLASS, 0).value).lower() except Xlib.error.XError: window_name = None class_name = None if window_name is not None and window_name != self.active_window: self.active_window = window_name for pattern, code in self.mapping.items(): if (pattern in window_name or pattern in class_name) and code != self.last_code: component.handle(Debug("Switching to '%s' for '%s'" % (code, window_name))) self.queue.put ( (code, None) ) self.last_code = code break event = disp.next_event() def stop(self): self.running = False