soreau,
created on Sunday, 17 August 2025, 22:03:49 (1755468229),
received on Monday, 18 August 2025, 06:14:45 (1755497685)
Author identity: Scott Moreau <oreaus@gmail.com>
1a0bc673cb5c634e4731d4e41215be03d129437b
applets/wf-window-list/__init__.py
@@ -339,7 +339,7 @@ class WFWindowList(panorama_panel.Applet):
action_group.add_action(options_action)
self.insert_action_group("applet", action_group)
# Wait for the widget to be in a layer-shell window before doing this
self.connect("realize", lambda *args: self.get_wl_resources())
self.connect("realize", self.get_wl_resources)
self.options_window = None
@@ -378,6 +378,7 @@ class WFWindowList(panorama_panel.Applet):
case "view-workspace-changed":
view = message.get("view", {})
if view["output-name"] == self.get_root().monitor_name:
output = self.get_wf_output_by_name(view["output-name"])
current_workspace = output["workspace"]["x"], output["workspace"]["y"]
if not self.show_only_this_wf_workspace or (message["to"]["x"], message["to"]["y"]) == current_workspace:
if self.toplevel_buttons_by_wf_id[view["id"]].get_parent() is None:
@@ -447,7 +448,7 @@ class WFWindowList(panorama_panel.Applet):
if button.get_parent() is self:
self.remove(button)
def get_wl_resources(self):
def get_wl_resources(self, widget):
ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = (ctypes.py_object,)
@@ -464,22 +465,31 @@ class WFWindowList(panorama_panel.Applet):
# Iterate through monitors and get their Wayland output (wl_output)
# This is a hack to ensure output_enter/leave is called for toplevels
for monitor in self.get_root().get_native().get_display().get_monitors():
for monitor in self.get_root().get_application().monitors:
wl_output = gtk.gdk_wayland_monitor_get_wl_output(ffi.cast("void *", ctypes.pythonapi.PyCapsule_GetPointer(monitor.__gpointer__, None)))
if wl_output:
if wl_output and not monitor.output_proxy:
print("Create proxy")
output_proxy = WlOutputProxy(wl_output, self.display)
output_proxy.interface.registry[output_proxy._ptr] = output_proxy
monitor.output_proxy = output_proxy
if monitor == my_monitor:
self.my_output = output_proxy
if monitor == my_monitor:
self.my_output = monitor.output_proxy
# End hack
fd = self.display.get_fd()
GLib.io_add_watch(fd, GLib.IO_IN, self.on_display_event)
self.manager = None
self.registry = self.display.get_registry()
self.registry.dispatcher["global"] = self.on_global
self.display.roundtrip()
if self.manager is None:
print("Could not load wf-window-list. Is foreign-toplevel protocol advertised by the compositor?")
print("(Wayfire requires enabling foreign-toplevel plugin)")
return
self.manager.dispatcher["toplevel"] = self.on_new_toplevel
self.manager.dispatcher["finished"] = lambda *a: print("Toplevel manager finished")
self.display.roundtrip()
fd = self.display.get_fd()
GLib.io_add_watch(fd, GLib.IO_IN, self.on_display_event)
if self.wf_socket is not None:
self.filter_to_wf_workspace()
@@ -493,10 +503,6 @@ class WFWindowList(panorama_panel.Applet):
if interface == "zwlr_foreign_toplevel_manager_v1":
self.print_log("Interface registered")
self.manager = registry.bind(name, ZwlrForeignToplevelManagerV1, version)
self.manager.dispatcher["toplevel"] = self.on_new_toplevel
self.manager.dispatcher["finished"] = lambda *a: print("Toplevel manager finished")
self.display.roundtrip()
self.display.flush()
elif interface == "wl_seat":
self.print_log("Seat found")
self.seat = registry.bind(name, WlSeat, version)
@@ -508,34 +514,29 @@ class WFWindowList(panorama_panel.Applet):
def on_new_toplevel(self, manager: ZwlrForeignToplevelManagerV1,
handle: ZwlrForeignToplevelHandleV1):
handle.dispatcher["title"] = lambda h, title: self.on_title_changed(h, title)
handle.dispatcher["app_id"] = lambda h, app_id: self.on_app_id_changed(h, app_id)
handle.dispatcher["title"] = self.on_title_changed
handle.dispatcher["app_id"] = self.on_app_id_changed
handle.dispatcher["output_enter"] = self.on_output_entered
handle.dispatcher["output_leave"] = self.on_output_left
handle.dispatcher["state"] = lambda h, states: self.on_state_changed(h, states)
handle.dispatcher["closed"] = lambda h: self.on_closed(h)
handle.dispatcher["state"] = self.on_state_changed
handle.dispatcher["closed"] = self.on_closed
def on_output_entered(self, handle, output):
if handle not in self.toplevel_buttons:
button = WindowButton(handle, handle.title)
self.set_title(button, handle.title)
self.set_app_id(button, handle.app_id)
button.set_group(self.initial_button)
button.set_layout_manager(WindowButtonLayoutManager(self.window_button_options))
button.connect("clicked", self.on_button_click)
self.toplevel_buttons[handle] = button
else:
button = self.toplevel_buttons[handle]
button = WindowButton(handle, handle.title)
if output == self.my_output:
self.append(button)
self.set_all_rectangles()
if self.show_only_this_output and output != self.my_output:
return
self.set_title(button, handle.title)
button.set_group(self.initial_button)
button.set_layout_manager(WindowButtonLayoutManager(self.window_button_options))
button.connect("clicked", self.on_button_click)
self.set_app_id(button, handle.app_id)
self.toplevel_buttons[handle] = button
self.append(button)
self.set_all_rectangles()
def on_output_left(self, handle, output):
if not self.show_only_this_output:
return
if output != self.my_output:
return
if handle in self.toplevel_buttons:
button = self.toplevel_buttons[handle]
self.remove(button)
main.py
@@ -580,6 +580,8 @@ class PanoramaPanel(Gtk.Application):
)
self.display = Gdk.Display.get_default()
self.monitors = self.display.get_monitors()
for monitor in self.monitors:
monitor.output_proxy = None
self.applets_by_name: dict[str, panorama_panel.Applet] = {}
self.panels: list[Panel] = []
self.manager_window = None