core: window-list: Switch to output names instead of indexes
This fixes multiple per-output window-lists.
By using this site, you agree to have cookies stored on your device, strictly for functional purposes, such as storing your session and preferences.
This fixes multiple per-output window-lists.
soreau,
created on Tuesday, 2 September 2025, 23:47:39 (1756856859),
received on Saturday, 6 September 2025, 21:54:28 (1757195668)
Author identity: Scott Moreau <oreaus@gmail.com>
87533785b9cbbf224e9cfaadc82ba344e89a3632
toplevel = widget.get_root()
if not toplevel:
return None, None, width, height
return 0, 0, width, height
x, y = widget.translate_coordinates(toplevel, 0, 0)
x = int(x)
def wl_output_enter(self, output, name):
print("wl_output_enter")
if name == self.get_root().monitor_name and self.get_root().get_native().get_surface():
wl_surface_ptr = gtk.gdk_wayland_surface_get_wl_surface(
ffi.cast("void *", ctypes.pythonapi.PyCapsule_GetPointer(
self.get_root().get_native().get_surface().__gpointer__, None)))
self.wl_surface = WlSurface()
self.wl_surface._ptr = wl_surface_ptr
self.set_live_preview_output(None)
if name == self.get_live_preview_output_name():
self.set_live_preview_output(output)
return
if name.startswith("live-preview"):
return
self.wl_surface = None
if name == self.get_root().monitor_name:
if self.get_root().get_native().get_surface():
wl_surface_ptr = gtk.gdk_wayland_surface_get_wl_surface(
ffi.cast("void *", ctypes.pythonapi.PyCapsule_GetPointer(
self.get_root().get_native().get_surface().__gpointer__, None)))
self.wl_surface = WlSurface()
self.wl_surface._ptr = wl_surface_ptr
self.my_output = output
else:
toplevel_buttons = self.toplevel_buttons.copy()
for handle in toplevel_buttons:
self.foreign_toplevel_closed(handle)
if name != self.get_live_preview_output_name():
return
self.set_live_preview_output(output)
button = self.toplevel_buttons[handle]
if output != button.output:
self.foreign_toplevel_closed(handle)
def wl_output_leave(self, output, name):
print("wl_output_leave")
if self.my_output == output:
self.my_output = None
toplevel_buttons = self.toplevel_buttons.copy()
for handle in toplevel_buttons:
self.foreign_toplevel_closed(handle)
if self.get_live_preview_output() == output:
self.set_live_preview_output(None)
return
if name.startswith("live-preview"):
return
toplevel_buttons = self.toplevel_buttons.copy()
for handle in toplevel_buttons:
self.foreign_toplevel_closed(handle)
if self.my_output == output:
self.my_output = None
def foreign_toplevel_output_enter(self, handle, output):
print("foreign_toplevel_output_enter")
button = WindowButton(handle, handle.title, self)
button.icon.set_pixel_size(self.icon_size)
button.output = None
if self.show_only_this_output and output != self.my_output:
if self.show_only_this_output and output.name != self.get_root().monitor_name:
return
button = WindowButton(handle, handle.title, self)
button.icon.set_pixel_size(self.icon_size)
button.output = output
self.set_title(button, handle.title)
button.set_group(self.initial_button)
def set_all_rectangles(self):
child = self.get_first_child()
while child is not None:
while child is not None and self.wl_surface:
if isinstance(child, WindowButton):
child.window_id.set_rectangle(self.wl_surface, *get_widget_rect(child))
x, y, w, h = get_widget_rect(child)
if w > 0 and h > 0:
child.window_id.set_rectangle(self.wl_surface, x, y, w, h)
child = child.get_next_sibling()
self.wl_globals.append(output)
print(f"global {name} {interface} {version}")
output.global_name = name
output.dispatcher["name"] = self.receive_output_name
output.name = None
self.got_output_name = False
while not output.name or not self.foreign_toplevel_manager_id:
output.dispatcher["name"] = self.receive_output_name
while not output.name or not self.foreign_toplevel_version:
self.wl_display.dispatch(block=True)
print(output.name)
# This is a hack to ensure output_enter/leave is called for toplevels
self.wl_output_ids.add(output.global_name)
if output.name == "DP-1":
if not output.name.startswith("live-preview"):
self.generate_panels()
for panel in self.panels:
panel.wl_output_enter(output, output.name)
if output.name == "DP-1":
if output.name == panel.monitor_name or output.name.startswith("live-preview"):
panel.wl_output_enter(output, output.name)
if not output.name.startswith("live-preview"):
if self.manager:
self.manager.destroy()
self.wl_globals.remove(self.manager)
self.manager.dispatcher["toplevel"] = self.on_new_toplevel
self.manager.dispatcher["finished"] = lambda *a: print("Toplevel manager finished")
self.wl_display.roundtrip()
self.got_output_name = True
# End hack
self.panels_generated = True
print(f"Monitor {name} ({interface}) connected", file=sys.stderr)
elif interface == "wl_seat":
if name in self.wl_output_ids:
print(f"Monitor {name} disconnected", file=sys.stderr)
#self.generate_panels()
self.panels_generated = False
for g in self.wl_globals:
if g.id == name:
for panel in self.panels:
panel.wl_output_leave(g, g.name)
break
#for g in self.wl_globals:
# if g.id == name:
# for panel in self.panels:
# panel.wl_output_leave(g, g.name)
# break
self.wl_output_ids.discard(name)
for g in self.wl_globals:
if g.id == name:
position = PANEL_POSITIONS[panel_data["position"]]
my_monitor = None
for monitor in self.display.get_monitors():
if monitor.get_connector() == "DP-1":
if monitor.get_connector() == panel_data["monitor"]:
my_monitor = monitor
break
if not my_monitor:
continue
size = panel_data["size"]
hide_time = panel_data["hide_time"]
can_capture_keyboard = panel_data["can_capture_keyboard"]
panel = Panel(self, monitor, position, size, autohide, hide_time, can_capture_keyboard)
panel = Panel(self, my_monitor, position, size, autohide, hide_time, can_capture_keyboard)
self.panels.append(panel)
print(f"{size}px panel on {position}, autohide is {autohide} ({hide_time}ms)")
# Intentionally commented: the display is already connected by GTK
# self.display.connect() # Iterate through monitors and get their Wayland output (wl_output)
# This is a hack to ensure output_enter/leave is called for toplevels
#if self.my_output:
# self.my_output.destroy()
#for monitor in self.monitors:
# wl_output = gtk.gdk_wayland_monitor_get_wl_output(ffi.cast("void *", ctypes.pythonapi.PyCapsule_GetPointer(monitor.__gpointer__, None)))
# if wl_output:
# print("Create proxy")
# output_proxy = WlOutputProxy(wl_output, self.wl_display)
# output_proxy.interface.registry[output_proxy._ptr] = output_proxy
# End hack
self.panels_generated = False
self.got_output_name = False