From 69a6777bf3b849ec2ab0627b6ad66a57298f9d45 Mon Sep 17 00:00:00 2001 From: Sébastien Dailly Date: Thu, 12 Jun 2025 11:00:44 +0200 Subject: Fixed the xlib handler when _NET_WM_NAME is not set --- xlib.py | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'xlib.py') diff --git a/xlib.py b/xlib.py index d28dfd4..b4954da 100644 --- a/xlib.py +++ b/xlib.py @@ -34,6 +34,7 @@ class Listener(Thread): self.NET_WM_NAME = self.disp.intern_atom('_NET_WM_NAME') self.WM_CLASS = self.disp.intern_atom('WM_CLASS') + self.WM_NAME = self.disp.intern_atom('WM_NAME') self.NET_ACTIVE_WINDOW = self.disp.intern_atom('_NET_ACTIVE_WINDOW') component.handle(Debug("Waiting for xlib event")) self.running = True @@ -45,18 +46,29 @@ class Listener(Thread): component.handle(Debug( str(e) )) print(e) - def handle_event(self, root, event): + def get_property_value(self, window, property_): + """ Return the requested property for the given window, or None if the + property is not defined. """ + prop_name = window.get_full_property(property_, 0) + if prop_name is not None: + return str(prop_name.value).lower() + return None + + + def handle_event(self, root, _event): try: - window_id_property = root.get_full_property(self.NET_ACTIVE_WINDOW, Xlib.X.AnyPropertyType) + window_id_property = root.get_full_property( + self.NET_ACTIVE_WINDOW, + Xlib.X.AnyPropertyType + ) if window_id_property is None: return window_id = window_id_property.value[0] window = self.disp.create_resource_object('window', window_id) - window_prop = window.get_full_property(self.NET_WM_NAME, 0) - if window_prop is None: - return - window_name = str(window_prop.value).lower() - class_name = str(window.get_full_property(self.WM_CLASS, 0).value).lower() + + window_name = self.get_property_value(window, self.NET_WM_NAME) \ + or self.get_property_value(window, self.WM_NAME) + class_name = self.get_property_value(window, self.WM_CLASS) except Xlib.error.XError: return @@ -73,7 +85,8 @@ class Listener(Thread): # Ignore the default layout if pattern == "default": continue - if not (pattern.lstrip() in window_name or pattern.lstrip() in class_name): + if not ((window_name is not None and pattern.lstrip() in window_name) + or (class_name is not None and pattern.lstrip() in class_name)): continue code = self.mapping[pattern] # We found something. At this point, even if we do not update @@ -89,6 +102,8 @@ class Listener(Thread): # same as the current one, we break the loop in order to # prevent another layer to update. break + if not found: + print(f"Mapping '{window_name}' / '{class_name}' to default") if not found and self.last_code != "default": default = self.mapping.get("default", None) if default is None: @@ -99,4 +114,6 @@ class Listener(Thread): def stop(self) -> None: + """ Stop the thread properly. + """ self.running = False -- cgit v1.2.3