diff --git a/scripts/keyd-application-mapper b/scripts/keyd-application-mapper index ddcac86..46bbd3d 100755 --- a/scripts/keyd-application-mapper +++ b/scripts/keyd-application-mapper @@ -176,7 +176,7 @@ class KDE(): # so this only works for wlroots based compositors :(. class Wayland(): - def __init__(self, interface_name): + def __init__(self, *interfaces): path = os.getenv("WAYLAND_DISPLAY") if path == None: raise Exception("WAYLAND_DISPLAY not set (is wayland running?)") @@ -186,7 +186,8 @@ class Wayland(): self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.sock.connect(path) - self._bind_interface(interface_name) + + self._bind_interfaces(interfaces) def send_msg(self, object_id, opcode, payload): opcode |= (len(payload)+8) << 16 @@ -208,24 +209,31 @@ class Wayland(): return b[4:4+struct.unpack('I', b[:4])[0]-1].decode('utf8') # Will bind the requested interface to object id 4 - def _bind_interface(self, name): + def _bind_interfaces(self, interfaces): # bind the registry object to id 2 self.send_msg(1, 1, b'\x02\x00\x00\x00') # solicit a sync message to bookend the registry events self.send_msg(1, 0, b'\x03\x00\x00\x00') + + interface_object_number = 4 while True: (obj, event, payload) = self.recv_msg() if obj == 2 and event == 0: # registry.global event wl_name = struct.unpack('I', payload[0:4])[0] - wl_interface = self.read_string(payload[4:]) - if wl_interface == name: - self.send_msg(2, 0, payload+b'\x04\x00\x00\x00') - return + for interface in interfaces: + if wl_interface == interface: + bind_payload = payload + struct.pack('I', interface_object_number) + self.send_msg(2, 0, bind_payload) + setattr(self, interface, interface_object_number) + interface_object_number += 1 if obj == 3: # sync message - raise Exception(f"Could not find interface {name}") + for interface in interfaces: + if not hasattr(self, interface): + raise Exception(f"Could not find interface {interface}") + return class Wlroots(): @@ -246,45 +254,42 @@ class Wlroots(): continue (obj, event, payload) = msg - if obj == 4 and event == 0: + if obj == self.wl.zwlr_foreign_toplevel_manager_v1 and event == 0: # zwlr_foreign_toplevel_manager_v1::toplevel event windows[struct.unpack('I', payload)[0]] = {'title': '', 'appid': ''} continue - - if obj not in windows: - continue - - if event == 0: - # zwlr_foreign_toplevel_handle_v1::title event - windows[obj]['title'] = self.wl.read_string(payload) - elif event == 1: - # zwlr_foreign_toplevel_handle_v1::app_id event - windows[obj]['appid'] = self.wl.read_string(payload) - elif event == 4: - # zwlr_foreign_toplevel_handle_v1::state event - if active_window == windows[obj]: - active_window = None - window_is_active = False - - array_size = struct.unpack('I', payload[0:4])[0] - for i in range(0, array_size, 4): - start_offset = i + 4 - end_offset = start_offset + 4 - state = struct.unpack('I', payload[start_offset:end_offset])[0] - # zwlr_foreign_toplevel_handle_v1::state enum -> activated - if state == 2: - window_is_active = True - - if window_is_active: - active_window = windows[obj] - elif event == 5 and active_window == windows[obj]: - # zwlr_foreign_toplevel_handle_v1::done event - self.on_window_change(active_window['appid'], active_window['title']) - elif event == 6: - # zwlr_foreign_toplevel_handle_v1::closed event - closed_window = windows.pop(obj) - if closed_window == active_window: - active_window = None + elif obj in windows: + if event == 0: + # zwlr_foreign_toplevel_handle_v1::title event + windows[obj]['title'] = self.wl.read_string(payload) + elif event == 1: + # zwlr_foreign_toplevel_handle_v1::app_id event + windows[obj]['appid'] = self.wl.read_string(payload) + elif event == 4: + # zwlr_foreign_toplevel_handle_v1::state event + if active_window == windows[obj]: + active_window = None + window_is_active = False + + array_size = struct.unpack('I', payload[0:4])[0] + for i in range(0, array_size, 4): + start_offset = i + 4 + end_offset = start_offset + 4 + state = struct.unpack('I', payload[start_offset:end_offset])[0] + # zwlr_foreign_toplevel_handle_v1::state enum -> activated + if state == 2: + window_is_active = True + + if window_is_active: + active_window = windows[obj] + elif event == 5 and active_window == windows[obj]: + # zwlr_foreign_toplevel_handle_v1::done event + self.on_window_change(active_window['appid'], active_window['title']) + elif event == 6: + # zwlr_foreign_toplevel_handle_v1::closed event + closed_window = windows.pop(obj) + if closed_window == active_window: + active_window = None class Cosmic(): def __init__(self, on_window_change):