roundabout,
created on Sunday, 3 August 2025, 10:01:55 (1754215315),
received on Saturday, 9 August 2025, 12:22:37 (1754742157)
Author identity: Vlad <vlad.muntoiu@gmail.com>
a8f5ff444af58b2c9c81666ab317ff82da49abca
applets/wf-window-list/__init__.py
@@ -15,7 +15,7 @@ import gi
gi.require_version("Gtk", "4.0")
gi.require_version("GdkWayland", "4.0")
from gi.repository import Gtk, GLib, Gtk4LayerShell, Gio, Gdk
from gi.repository import Gtk, GLib, Gtk4LayerShell, Gio, Gdk, Pango
import ctypes
@@ -82,6 +82,47 @@ class WindowState:
return instance
from gi.repository import Gtk, Gdk
class WindowButtonOptions:
def __init__(self, max_width: int):
self.max_width = max_width
class WindowButtonLayoutManager(Gtk.LayoutManager):
def __init__(self, options: WindowButtonOptions, **kwargs):
super().__init__(**kwargs)
self.options = options
def do_measure(self, widget, orientation, for_size):
child = widget.get_first_child()
if child is None:
return 0, 0, 0, 0
if orientation == Gtk.Orientation.HORIZONTAL:
# Measure child's preferred width, clamp to MAX_WIDTH
min_width, nat_width, min_height, nat_height = child.measure(Gtk.Orientation.HORIZONTAL, for_size)
width = min(nat_width, self.options.max_width)
# Height is unrestricted, so measure height for given width
return min_width, width, min_height, nat_height
else:
# Vertical measurement
min_width, nat_width, min_height, nat_height = child.measure(Gtk.Orientation.VERTICAL, for_size)
# Width is clamped during horizontal measure
return min_height, nat_height, 0, 0
def do_allocate(self, widget, width, height, baseline):
child = widget.get_first_child()
if child is None:
return
alloc_width = min(width, self.options.max_width)
alloc = Gdk.Rectangle()
alloc.x = 0
alloc.y = 0
alloc.width = alloc_width
alloc.height = height
child.allocate(alloc.width, alloc.height, baseline)
class WindowButton(Gtk.ToggleButton):
def __init__(self, window_id, window_title, **kwargs):
super().__init__(**kwargs)
@@ -98,6 +139,10 @@ class WindowButton(Gtk.ToggleButton):
self.window_title = window_title
self.window_state = WindowState(False, False, False, False)
self.label.set_ellipsize(Pango.EllipsizeMode.END)
self.set_hexpand(True)
self.set_vexpand(True)
@property
def window_title(self):
return self.label.get_text()
@@ -137,6 +182,9 @@ class WFWindowList(panorama_panel.Applet):
if config is None:
config = {}
self.set_homogeneous(True)
self.window_button_options = WindowButtonOptions(240)
self.toplevel_buttons: dict[ZwlrForeignToplevelHandleV1, WindowButton] = {}
# This button doesn't belong to any window but is used for the button group and to be
# selected when no window is focused
@@ -162,6 +210,7 @@ class WFWindowList(panorama_panel.Applet):
options_action.connect("activate", self.show_options)
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.options_window = None
@@ -175,7 +224,8 @@ class WFWindowList(panorama_panel.Applet):
ffi.cast("void *", ctypes.pythonapi.PyCapsule_GetPointer(self.get_root().get_native().get_display().__gpointer__, None)))
self.display._ptr = wl_display_ptr
#self.display.connect()
# Intentionally commented: the display is already connected by GTK
# self.display.connect()
self.registry = self.display.get_registry()
self.registry.dispatcher["global"] = self.on_global
@@ -216,6 +266,7 @@ class WFWindowList(panorama_panel.Applet):
if handle not in self.toplevel_buttons:
button = WindowButton(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.toplevel_buttons[handle] = button
self.append(button)