Initial app menu

by roundabout, Thursday, 14 August 2025, 13:11:32 (1755177092), pushed by roundabout, Thursday, 14 August 2025, 13:11:35 (1755177095)

Author identity: Vlad <vlad.muntoiu@gmail.com>

11b989bd7696b1e1b3e70aca01f45d89ea130d48

applets/app-menu/__init__.py

@@ -0,0 +1,243 @@

                                
                                
                                
                            
                                
                                    
                                        
                                        """
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        MATE-like app menu applet for the Panorama panel.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        Copyright 2025, roundabout-host.com <vlad@roundabout-host.com>
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        This program is free software: you can redistribute it and/or modify
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        it under the terms of the GNU General Public Licence as published by
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        the Free Software Foundation, either version 3 of the Licence, or
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        (at your option) any later version.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        This program is distributed in the hope that it will be useful,
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        but WITHOUT ANY WARRANTY; without even the implied warranty of
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        GNU General Public Licence for more details.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        You should have received a copy of the GNU General Public Licence
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        along with this program. If not, see <https://www.gnu.org/licenses/>.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        """
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import os
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from pathlib import Path
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import locale
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import panorama_panel
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import gi
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        gi.require_version("Gtk", "4.0")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from gi.repository import Gtk, GLib, Gio, Gdk
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        module_directory = Path(__file__).resolve().parent
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        locale.bindtextdomain("panorama-app-menu", module_directory / "locale")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        _ = lambda x: locale.dgettext("panorama-app-menu", x)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        CATEGORY_MAPPINGS = {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            "Utility": (_("Accessories"), "applications-accessories"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            "Development": (_("Programming"), "applications-development"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            "Game": (_("Games"), "applications-games"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            "Graphics": (_("Graphics"), "applications-graphics"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            "Network": (_("Network"), "applications-internet"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            "AudioVideo": (_("Multimedia"), "applications-multimedia"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            "Office": (_("Office"), "applications-office"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            "Science": (_("Science"), "applications-science"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            "Education": (_("Education"), "applications-education"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            "System": (_("System"), "applications-system"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            "Settings": (_("Settings"), "preferences-desktop"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            "Other": (_("Other"), "applications-other"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        }
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        custom_css = """
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        .no-menu-item-padding:dir(ltr) {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            padding-left: 0;
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        }
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        .no-menu-item-padding:dir(rtl) {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            padding-right: 0;
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        }
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        """
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        css_provider = Gtk.CssProvider()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        css_provider.load_from_data(custom_css)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        Gtk.StyleContext.add_provider_for_display(
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            Gdk.Display.get_default(),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            css_provider,
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        )
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        def force_visible_on_visible_notify(widget, *args):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            if not widget.get_visible():
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                widget.set_visible(True)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        def add_icons_to_menu(popover: Gtk.PopoverMenu):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            section = popover.get_child().get_first_child().get_first_child().get_first_child()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            while section is not None:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                child = section.get_first_child().get_first_child()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                while child is not None:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    gutter_box: Gtk.Box = child.get_first_child()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    if isinstance(gutter_box.get_next_sibling(), Gtk.Image):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        # For some reason GTK creates images but they're hidden?
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        image: Gtk.Image = gutter_box.get_next_sibling()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        label: Gtk.Label = image.get_next_sibling()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        image.unparent()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        gutter_box.unparent()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        gutter_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        gutter_box.insert_before(child, label)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        gutter_box.append(image)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        image.set_icon_size(Gtk.IconSize.LARGE)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        image.set_margin_start(8)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        image.set_margin_end(8)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        child.add_css_class("no-menu-item-padding")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        # Push the arrow to the left
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        label.set_halign(Gtk.Align.FILL)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        label.set_hexpand(True)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        label.set_xalign(0)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        # GTK pushes its stance on icons so hard it makes them invisible multiple times;
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        # force it visible
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        image.set_visible(True)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        image.connect("notify::visible", force_visible_on_visible_notify)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    # Find the submenu if there is one
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    subchild = child.get_first_child()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    submenu = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    while subchild is not None:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        if isinstance(subchild, Gtk.PopoverMenu):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            submenu = subchild
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        subchild = subchild.get_next_sibling()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    # Recursive
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    if submenu is not None:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        add_icons_to_menu(submenu)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    child = child.get_next_sibling()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                section = section.get_next_sibling()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        class AppMenu(panorama_panel.Applet):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            name = _("App menu")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            description = _("Show apps installed on your system, grouped by category")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def __init__(self, orientation=Gtk.Orientation.HORIZONTAL, config=None):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                super().__init__(orientation=orientation, config=config)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if config is None:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    config = {}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.button = Gtk.MenuButton()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.button.set_has_frame(False)   # flat look
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.icon = Gtk.Image.new_from_icon_name("start-here")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.button.set_child(self.icon)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.apps_by_id: dict[int, Gio.AppInfo] = {}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.menu = Gio.Menu()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.popover = Gtk.PopoverMenu.new_from_model_full(self.menu, Gtk.PopoverMenuFlags.NESTED)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.popover.set_has_arrow(False)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                panorama_panel.track_popover(self.popover)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.button.set_popover(self.popover)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.generate_app_menu()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.append(self.button)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.context_menu = self.make_context_menu()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                panorama_panel.track_popover(self.context_menu)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                right_click_controller = Gtk.GestureClick()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                right_click_controller.set_button(3)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                right_click_controller.connect("pressed", self.show_context_menu)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.add_controller(right_click_controller)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                action_group = Gio.SimpleActionGroup()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                options_action = Gio.SimpleAction.new("options", None)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                options_action.connect("activate", self.show_options)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                action_group.add_action(options_action)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                options_action = Gio.SimpleAction.new("launch-app", GLib.VariantType.new("s"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                options_action.connect("activate", self.launch_app)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                action_group.add_action(options_action)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.insert_action_group("applet", action_group)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.options_window = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def launch_app(self, action, id: GLib.Variant):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                app = self.apps_by_id[int(id.get_string())]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                app.launch()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def make_context_menu(self):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                menu = Gio.Menu()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                menu.append(_("Menu _options"), "applet.options")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                context_menu = Gtk.PopoverMenu.new_from_model(menu)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                context_menu.set_has_arrow(False)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                context_menu.set_parent(self)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                context_menu.set_halign(Gtk.Align.START)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                context_menu.set_flags(Gtk.PopoverMenuFlags.NESTED)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return context_menu
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def show_context_menu(self, gesture, n_presses, x, y):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                rect = Gdk.Rectangle()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                rect.x = int(x)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                rect.y = int(y)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                rect.width = 1
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                rect.height = 1
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.context_menu.set_pointing_to(rect)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.context_menu.popup()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def show_options(self, _0=None, _1=None):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                ...
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def get_config(self):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return {}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def set_panel_position(self, position):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.popover.set_position(panorama_panel.OPPOSITE_POSITION[position])
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.button.set_direction(panorama_panel.POSITION_TO_ARROW[panorama_panel.OPPOSITE_POSITION[position]])
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def generate_app_menu(self):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.menu.remove_all()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.apps_by_id = {}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                all_apps = Gio.AppInfo.get_all()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                apps_by_category: dict[str, list[Gio.AppInfo]] = {}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for category, info in CATEGORY_MAPPINGS.items():
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    apps_by_category[category] = []
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for app in all_apps:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    category_found = False
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    if isinstance(app, Gio.DesktopAppInfo):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        if app.get_categories() is not None:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            categories = app.get_categories().split(";")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            for category in categories:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                                if category in apps_by_category:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                                    apps_by_category[category].append(app)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                                    category_found = True
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    if not category_found:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        apps_by_category["Other"].append(app)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for category, info in CATEGORY_MAPPINGS.items():
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    if apps_by_category[category]:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        item = Gio.MenuItem.new(info[0])
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        item.set_icon(Gio.ThemedIcon.new(info[1]))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        submenu = Gio.Menu()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        for app in apps_by_category[category]:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            if isinstance(app, Gio.DesktopAppInfo) and (app.get_is_hidden() or app.get_nodisplay()):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                                continue
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            subitem = Gio.MenuItem.new(app.get_display_name(), f"applet.launch-app::{id(app)}")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            subitem.set_icon(app.get_icon() or Gio.ThemedIcon.new("image-missing"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            self.apps_by_id[id(app)] = app
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            submenu.append_item(subitem)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        item.set_submenu(submenu)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        self.menu.append_item(item)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                add_icons_to_menu(self.popover)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                            
                                

config.yaml

@@ -7,6 +7,7 @@ panels:

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                              can_capture_keyboard: false
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                              applets:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                left:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            - AppMenu: {}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                - WFWindowList:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    max_button_width: 256
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                centre: []
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                            
                                

docs/accessibility.md

@@ -11,8 +11,8 @@ Get a plugin like

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            [wf-panel-focus by Scott Moreau (for Wayfire)](https://github.com/soreau/wf-panel-focus)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            which will add a keybinding to cycle between displayed panels (default:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            Control-Alt-Tab) and one to return to the working area (Control-Alt-Esc). Enable
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        `can_capture_keyboard` on your panels so it will be able to be focused.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        Then you can use normal GTK widget navigation in the panel.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        `can_capture_keyboard` on your panels, so they will be able to be focused.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        Then you can use normal GTK widget navigation in the panels.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            If you enable that option without a suitable plugin, panels can be focused in
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            Wayfire by clicking them, which is not the expected UX, so don't enable it