keyd-application-mapper: Refactor wayland code

Clean up Wayland() and allow binding to multiple protocol objects simultaneously
master
Raheman Vaiya 1 year ago
parent 74217ba4a7
commit f20bd7a441
  1. 93
      scripts/keyd-application-mapper

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

Loading…
Cancel
Save