By using this site, you agree to have cookies stored on your device, strictly for functional purposes, such as storing your session and preferences.

Dismiss

core: window-list: Use single registry handler for all window-lists

soreau,
created on Tuesday, 2 September 2025, 17:31:54 (1756834314), received on Saturday, 6 September 2025, 21:54:28 (1757195668)
Author identity: Scott Moreau <oreaus@gmail.com>

c140e138cdeb816d02a41245749463879c98237a

applets/wf-window-list/__init__.py

@@ -26,7 +26,7 @@ import typing

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            from pathlib import Path
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            from pywayland.utils import AnonymousFile
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            from pywayland.client import Display, EventQueue
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from pywayland.protocol.wayland import WlRegistry, WlSeat, WlSurface, WlCompositor, WlOutput, WlBuffer, WlShm, WlShmPool
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from pywayland.protocol.wayland import WlRegistry, WlSeat, WlSurface, WlCompositor, WlOutput, WlBuffer, WlShmPool
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            from pywayland.protocol.wayland.wl_output import WlOutputProxy
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            from pywayland.protocol.wlr_foreign_toplevel_management_unstable_v1 import (
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                ZwlrForeignToplevelManagerV1,
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -36,7 +36,7 @@ from pywayland.protocol.wlr_screencopy_unstable_v1 import (

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                ZwlrScreencopyManagerV1,
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                ZwlrScreencopyFrameV1
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            )
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from OpenGL import GL
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            import panorama_panel
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            import gi
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -421,12 +421,15 @@ class WFWindowList(panorama_panel.Applet):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    # selected when no window is focused
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.initial_button = Gtk.ToggleButton()
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.display = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.my_output = None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.wl_surface_ptr = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.registry = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.wl_surface = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.compositor = None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.seat = None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.output = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.wl_shm = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                #self.manager = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.screencopy_manager = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.live_preview_output_name = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.context_menu = self.make_context_menu()
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    panorama_panel.track_popover(self.context_menu)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -563,62 +566,23 @@ class WFWindowList(panorama_panel.Applet):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                                self.remove(button)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                def get_wl_resources(self, widget):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                ctypes.pythonapi.PyCapsule_GetPointer.argtypes = (ctypes.py_object,)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.display = Display()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                wl_display_ptr = gtk.gdk_wayland_display_get_wl_display(
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        ffi.cast("void *", ctypes.pythonapi.PyCapsule_GetPointer(self.get_root().get_native().get_display().__gpointer__, None)))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.display._ptr = wl_display_ptr
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.event_queue = EventQueue(self.display)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                # Intentionally commented: the display is already connected by GTK
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                # self.display.connect()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                my_monitor = Gtk4LayerShell.get_monitor(self.get_root())
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                # 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_application().monitors:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    wl_output = gtk.gdk_wayland_monitor_get_wl_output(ffi.cast("void *", ctypes.pythonapi.PyCapsule_GetPointer(monitor.__gpointer__, None)))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    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 = monitor.output_proxy
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                # End hack
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if self.wl_shm:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    return
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.my_output = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                #self.wl_surface = self.get_root().get_application().wl_surface
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.compositor = self.get_root().get_application().compositor
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.seat = self.get_root().get_application().seat
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.output = None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.wl_shm = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.manager = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.screencopy_manager = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.wl_shm = self.get_root().get_application().wl_shm
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                #self.manager = self.get_root().get_application().manager
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.screencopy_manager = self.get_root().get_application().screencopy_manager
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.live_preview_output_name = 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
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if self.screencopy_manager is None:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    print("Protocol zwlr_screencopy_manager_v1 not found, live (minimized) window previews will not work!")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                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()
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_display_event(self, source, condition):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if condition & GLib.IO_IN:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.display.dispatch(queue=self.event_queue)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return True
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                def set_live_preview_output(self, output):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.output = output
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -631,48 +595,34 @@ class WFWindowList(panorama_panel.Applet):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                def get_live_preview_output_name(self):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    return self.live_preview_output_name
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def wl_output_handle_name(self, output, name):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if name != self.get_live_preview_output_name():
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    output.release()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    output.destroy()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    return
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.set_live_preview_output(output)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_global(self, registry, name, interface, version):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if interface == "zwlr_foreign_toplevel_manager_v1":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.print_log("Interface registered")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.manager = registry.bind(name, ZwlrForeignToplevelManagerV1, version)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                elif interface == "wl_output":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    if self.live_preview_output_name is None:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        return
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    wl_output = registry.bind(name, WlOutput, version)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    wl_output.dispatcher["name"] = self.wl_output_handle_name
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                elif interface == "wl_seat":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.print_log("Seat found")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.seat = registry.bind(name, WlSeat, version)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                elif interface == "wl_shm":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.wl_shm = registry.bind(name, WlShm, version)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                elif interface == "wl_compositor":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.compositor = registry.bind(name, WlCompositor, version)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            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
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                elif interface == "zwlr_screencopy_manager_v1":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.screencopy_manager = registry.bind(name, ZwlrScreencopyManagerV1, version)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_new_toplevel(self, manager: ZwlrForeignToplevelManagerV1,
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                                 handle: ZwlrForeignToplevelHandleV1):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                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"] = self.on_state_changed
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                handle.dispatcher["closed"] = self.on_closed
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.display.roundtrip()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_output_entered(self, handle, output):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.my_output = output
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    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)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            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)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            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
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -690,7 +640,8 @@ class WFWindowList(panorama_panel.Applet):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.append(button)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.set_all_rectangles()
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_output_left(self, handle, output):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_output_leave(self, handle, output):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                print("foreign_toplevel_output_leave")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    if handle in self.toplevel_buttons:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        button = self.toplevel_buttons[handle]
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        if button.get_parent() == self:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -703,7 +654,7 @@ class WFWindowList(panorama_panel.Applet):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    if not self.live_preview_tooltips:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        button.set_tooltip_text(title)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_title_changed(self, handle, title):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_title(self, handle, title):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    handle.title = title
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    if handle in self.toplevel_buttons:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        button = self.toplevel_buttons[handle]
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -728,7 +679,7 @@ class WFWindowList(panorama_panel.Applet):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        else:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            button.window_id.activate(self.seat)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_state_changed(self, handle, states):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_state(self, handle, states):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    if handle in self.toplevel_buttons:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        state_info = WindowState.from_state_array(states)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        button = self.toplevel_buttons[handle]
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -748,13 +699,13 @@ class WFWindowList(panorama_panel.Applet):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        if app_id.startswith("wf-ipc-"):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            self.toplevel_buttons_by_wf_id[int(app_id.removeprefix("wf-ipc-"))] = button
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_app_id_changed(self, handle, app_id):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_app_id(self, handle, app_id):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    handle.app_id = app_id
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    if handle in self.toplevel_buttons:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        button = self.toplevel_buttons[handle]
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        self.set_app_id(button, app_id)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_closed(self, handle):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_closed(self, handle):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    if handle not in self.toplevel_buttons:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        return
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    button: WindowButton = self.toplevel_buttons[handle]
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                            
                                

main.py

@@ -31,6 +31,16 @@ from itertools import accumulate, chain

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            from pathlib import Path
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            import ruamel.yaml as yaml
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            from pywayland.client import Display, EventQueue
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from pywayland.protocol.wayland.wl_output import WlOutputProxy
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from pywayland.protocol.wayland import WlRegistry, WlSeat, WlSurface, WlCompositor, WlOutput, WlShm
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from pywayland.protocol.wlr_foreign_toplevel_management_unstable_v1 import (
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            ZwlrForeignToplevelManagerV1,
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            ZwlrForeignToplevelHandleV1
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        )
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from pywayland.protocol.wlr_screencopy_unstable_v1 import (
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            ZwlrScreencopyManagerV1,
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            ZwlrScreencopyFrameV1
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        )
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            faulthandler.enable()
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -64,7 +74,6 @@ locale.setlocale(locale.LC_ALL)

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            _ = locale.gettext
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            import panorama_panel
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import wl4pgi
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            import asyncio
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            asyncio.set_event_loop_policy(GLibEventLoopPolicy())
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -353,7 +362,7 @@ POSITION_TO_LAYER_SHELL_EDGE = {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            class Panel(Gtk.Window):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def __init__(self, application: Gtk.Application, monitor: Gdk.Monitor, position: Gtk.PositionType = Gtk.PositionType.TOP, size: int = 40, autohide: bool = False, hide_time: int = 0, can_capture_keyboard: bool = False, monitor_index: int = 0):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def __init__(self, application: Gtk.Application, monitor: Gdk.Monitor, position: Gtk.PositionType = Gtk.PositionType.TOP, size: int = 40, autohide: bool = False, hide_time: int = 0, can_capture_keyboard: bool = False):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    super().__init__(application=application)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.drop_motion_controller = None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.motion_controller = None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -543,6 +552,69 @@ class Panel(Gtk.Window):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        self.motion_controller.connect("leave", lambda *args: not self.open_popovers and GLib.timeout_add(self.hide_time // (self.size - 1), self.slide_out))
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        self.drop_motion_controller.connect("leave", lambda *args: not self.open_popovers and GLib.timeout_add(self.hide_time // (self.size - 1), self.slide_out))
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def wl_output_enter(self, output, name):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for area in (self.left_area, self.centre_area, self.right_area):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    applet = area.get_first_child()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    while applet:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet.wl_output_enter(output, name)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet = applet.get_next_sibling()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def wl_output_leave(self, output, name):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for area in (self.left_area, self.centre_area, self.right_area):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    applet = area.get_first_child()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    while applet:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet.wl_output_leave(output, name)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet = applet.get_next_sibling()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_new(self, manager, toplevel):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for area in (self.left_area, self.centre_area, self.right_area):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    applet = area.get_first_child()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    while applet:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet.foreign_toplevel_new(manager, toplevel)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet = applet.get_next_sibling()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_output_enter(self, toplevel, output):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for area in (self.left_area, self.centre_area, self.right_area):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    applet = area.get_first_child()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    while applet:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet.foreign_toplevel_output_enter(toplevel, output)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet = applet.get_next_sibling()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_output_leave(self, toplevel, output):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for area in (self.left_area, self.centre_area, self.right_area):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    applet = area.get_first_child()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    while applet:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet.foreign_toplevel_output_leave(toplevel, output)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet = applet.get_next_sibling()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_app_id(self, toplevel, app_id):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for area in (self.left_area, self.centre_area, self.right_area):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    applet = area.get_first_child()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    while applet:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet.foreign_toplevel_app_id(toplevel, app_id)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet = applet.get_next_sibling()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_title(self, toplevel, title):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for area in (self.left_area, self.centre_area, self.right_area):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    applet = area.get_first_child()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    while applet:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet.foreign_toplevel_title(toplevel, title)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet = applet.get_next_sibling()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_state(self, toplevel, state):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for area in (self.left_area, self.centre_area, self.right_area):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    applet = area.get_first_child()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    while applet:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet.foreign_toplevel_state(toplevel, state)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet = applet.get_next_sibling()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_closed(self, toplevel):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for area in (self.left_area, self.centre_area, self.right_area):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    applet = area.get_first_child()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    while applet:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet.foreign_toplevel_closed(toplevel)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        applet = applet.get_next_sibling()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            def get_all_subclasses(klass: type) -> list[type]:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                subclasses = []
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                for subclass in klass.__subclasses__():
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -595,13 +667,20 @@ class PanoramaPanel(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            application_id="com.roundabout_host.roundabout.PanoramaPanel",
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    )
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.registry = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    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.wl_globals = []
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.wl_display = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.compositor = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.seat = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.output = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.wl_shm = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.manager = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.screencopy_manager = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.manager_window = None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.edit_mode = False
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.drags = {}
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -617,38 +696,117 @@ class PanoramaPanel(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        _("NAME")
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    )
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def receive_output_name(self, output, name: str):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_new_toplevel(self, manager: ZwlrForeignToplevelManagerV1,
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                                 handle: ZwlrForeignToplevelHandleV1):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                print("on_new_toplevel")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for panel in self.panels:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    panel.foreign_toplevel_new(manager, handle)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                handle.dispatcher["title"] = self.on_title_changed
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                handle.dispatcher["app_id"] = self.on_app_id_changed
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                handle.dispatcher["output_enter"] = self.on_output_enter
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                handle.dispatcher["output_leave"] = self.on_output_leave
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                handle.dispatcher["state"] = self.on_state_changed
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                handle.dispatcher["closed"] = self.on_closed
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.wl_display.roundtrip()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_output_leave(self, handle, output):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for panel in self.panels:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    panel.foreign_toplevel_output_leave(handle, output)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_output_enter(self, handle, output):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for panel in self.panels:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    panel.foreign_toplevel_output_enter(handle, output)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_title_changed(self, handle, title):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for panel in self.panels:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    panel.foreign_toplevel_title(handle, title)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_app_id_changed(self, handle, app_id):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for panel in self.panels:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    panel.foreign_toplevel_app_id(handle, app_id)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_state_changed(self, handle, state):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for panel in self.panels:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    panel.foreign_toplevel_state(handle, state)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def on_closed(self, handle):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for panel in self.panels:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    panel.foreign_toplevel_closed(handle)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def receive_output_name(self, output: WlOutput, name: str):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    output.name = name
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                def on_global(self, registry, name, interface, version):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if interface == "wl_output":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    output = registry.bind(name, wl4pgi.wayland.WlOutput.interface_type, version)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if interface == "zwlr_foreign_toplevel_manager_v1":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    print("Interface registered")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.foreign_toplevel_manager_id = name
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.foreign_toplevel_version = version
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                elif interface == "wl_output":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    output = registry.bind(name, WlOutput, version)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    output.id = name
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.wl_globals.append(output)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        print(f"global {name} {interface} {version}")
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        output.global_name = name
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    output.connect("name", self.receive_output_name)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    output.dispatcher["name"] = self.receive_output_name
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        output.name = None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    while not output.name:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.got_output_name = False
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    while not output.name or not self.foreign_toplevel_manager_id:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            self.wl_display.dispatch(block=True)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    if not output.name.startswith("live-preview"):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        self.wl_output_ids.add(output.global_name)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    print(output.name)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.wl_output_ids.add(output.global_name)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    if output.name == "DP-1":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            self.generate_panels()
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    for panel in self.panels:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        panel.wl_output_enter(output, output.name)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        if output.name == panel.monitor_name:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            if self.manager:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                                self.manager.destroy()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                                self.wl_globals.remove(self.manager)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            self.manager = self.registry.bind(self.foreign_toplevel_manager_id, ZwlrForeignToplevelManagerV1, self.foreign_toplevel_version)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            self.manager.id = self.foreign_toplevel_manager_id
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            self.wl_globals.append(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
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.panels_generated = True
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        print(f"Monitor {name} ({interface}) connected", file=sys.stderr)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                elif interface == "wl_seat":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    print("Seat found")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.seat = registry.bind(name, WlSeat, version)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.seat.id = name
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.wl_globals.append(self.seat)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                elif interface == "wl_shm":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.wl_shm = registry.bind(name, WlShm, version)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.wl_shm.id = name
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.wl_globals.append(self.wl_shm)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                elif interface == "wl_compositor":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.compositor = registry.bind(name, WlCompositor, version)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.compositor.id = name
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.wl_globals.append(self.compositor)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                elif interface == "zwlr_screencopy_manager_v1":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.screencopy_manager = registry.bind(name, ZwlrScreencopyManagerV1, version)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.screencopy_manager.id = name
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.wl_globals.append(self.screencopy_manager)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                def on_global_remove(self, registry, name):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                print("global removed")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    if name in self.wl_output_ids:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        print(f"Monitor {name} disconnected", file=sys.stderr)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.generate_panels()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    #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
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        self.wl_output_ids.discard(name)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for g in self.wl_globals:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    if g.id == name:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        g.destroy()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        self.wl_globals.remove(g)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        break
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                def generate_panels(self):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.display = Gdk.Display.get_default()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.monitors = self.display.get_monitors()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for monitor in self.monitors:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    monitor.output_proxy = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    print("Generating panels...", file=sys.stderr)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.exit_all_applets()
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    for panel in self.panels:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -663,19 +821,21 @@ class PanoramaPanel(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        yaml_file = yaml_loader.load(config_file)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        for panel_data in yaml_file["panels"]:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            position = PANEL_POSITIONS[panel_data["position"]]
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        monitor_index = panel_data["monitor"]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        if monitor_index >= len(self.monitors):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        my_monitor = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        for monitor in self.display.get_monitors():
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            if monitor.get_connector() == "DP-1":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                                my_monitor = monitor
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        if not my_monitor:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                                continue
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        monitor = self.monitors[monitor_index]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            size = panel_data["size"]
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            autohide = panel_data["autohide"]
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            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, monitor_index)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        panel = Panel(self, monitor, position, size, autohide, hide_time, can_capture_keyboard)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            self.panels.append(panel)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        print(f"{size}px panel on {position} edge of monitor {monitor_index}, autohide is {autohide} ({hide_time}ms)")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        print(f"{size}px panel on {position}, autohide is {autohide} ({hide_time}ms)")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            for area_name, area in (("left", panel.left_area), ("centre", panel.centre_area), ("right", panel.right_area)):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                                applet_list = panel_data["applets"].get(area_name)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -692,8 +852,8 @@ class PanoramaPanel(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                                    area.append(applet_widget)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        panel.realize()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            panel.present()
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        panel.realize()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                def prepare(self):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.release()
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -717,15 +877,32 @@ class PanoramaPanel(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        self.applets_by_name[subclass.__name__] = subclass
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.wl_display = Display()
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.wl_display._ptr = gtk.gdk_wayland_display_get_wl_display(
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                wl_display_ptr = gtk.gdk_wayland_display_get_wl_display(
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            ffi.cast("void *", ctypes.pythonapi.PyCapsule_GetPointer(self.display.__gpointer__, None)))
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.wl_display._ptr = wl_display_ptr
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    # Intentionally commented: the display is already connected by GTK
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                # self.display.connect()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.registry = wl4pgi.wayland.WlRegistry(self.wl_display.get_registry())
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.registry.connect("global", self.on_global)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.registry.connect("global_remove", self.on_global_remove)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                # 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
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.foreign_toplevel_manager_id = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.foreign_toplevel_version = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.registry = self.wl_display.get_registry()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.registry.dispatcher["global"] = self.on_global
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.registry.dispatcher["global_remove"] = self.on_global_remove
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.wl_display.roundtrip()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.hold()
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                            
                                

shared/panorama_panel.py

@@ -66,6 +66,33 @@ class Applet(Gtk.Box):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                def print_log(cls, *args, **kwargs):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    print(f"{cls.__name__}:", *args, **kwargs)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def wl_output_enter(self, output, name):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                pass
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def wl_output_leave(self, output, name):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                pass
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_new(self, manager, toplevel):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                pass
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_output_enter(self, toplevel, output):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                pass
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_output_leave(self, toplevel, output):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                pass
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_app_id(self, toplevel, app_id):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                pass
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_title(self, toplevel, title):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                pass
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_state(self, toplevel, state):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                pass
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def foreign_toplevel_closed(self, toplevel):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                pass
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            def track_popover(popover: Gtk.Popover):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                popover.connect("show", lambda *args: _popover_shown(popover))