3.0 KiB
3.0 KiB
astal-menu
A touch-friendly GTK4 popup control centre for the hyprlua desktop, replacing
nwg-dock and nwg-drawer. Triggered from the EWW top bar (or Super+D).
Layout: a 2×2 quad grid of feature modules over a full-width application drawer. Any quad can expand to overlay the other three; the drawer can expand to the bottom of the screen. A single margined root box letterboxes the menu identically in every state.
Stack
- Frontend: Python + PyGObject + GTK4, as a
wlr-layer-shellsurface (gtk4-layer-shell). Chosen over Lua because lgi/Astal-Lua only support GTK3. - Location map: a static OSM image stitched from tiles (
backend/staticmap.py, Pillow). libshumate does not paint tiles in this environment (the officialshumate-demoshows the same blank map), though tile downloads work — hence the static fallback. - Services: Astal GObject libraries via introspection —
AstalNetwork,AstalBluetooth,AstalApps— plus our own IP-geolocation singleton. - Backends: Python/Bash scripts in
backend/(JSON on stdout), run async viaGio.Subprocessso nothing blocks the UI. - Theme:
style/_colors.css(@define-color, generated from~/Dotfiles/colors.confbyapply-theme.sh) +style/style.css.
Running
main.py is single-instance. The autostart launches a hidden resident daemon;
verbs are forwarded over D-Bus:
scripts/astal-menu-start.sh # resident daemon (hidden); sets LD_PRELOAD
scripts/menu-toggle.sh # --toggle
scripts/menu-toggle.sh appdrawer # open with the app drawer expanded
astal-menu-start.sh must LD_PRELOAD libgtk4-layer-shell (it loads after
libwayland under PyGObject otherwise).
Adding a module
- Create
modules/<name>.pyexposing a top-levelSPEC = ModuleSpec(...)whosebuild(ctx)returns aModuleInstance(compact=…, expanded=…, …).compactshows in the 2×2 cell; a distinctexpandedwidget enables the expand button (they must be separate instances — GTK widgets have one parent).- Declare per-feature toggles via
features=[Feature("id", "Label", default)]; read them withctx.feature("id"). A disabled quad never callsbuild(). - Shared state (network, bluetooth, location) is on
ctx.services.
- Append its
SPECtoALL_SPECSinregistry.py. Nothing else changes.
Files
main.py app + single-instance IPC window.py layer-shell + letterbox
registry.py module list (extension seam) settings.py JSON toggles/order
module_base.py ModuleSpec / ModuleInstance / ModuleContext
appservices.py shared Astal services + location
ui/ quadcard, quadgrid, appdrawer
modules/ location, weather, bluetooth, network
services/ location (geolocation singleton)
lib/ ansi (SGR→TextTag), proc (async subprocess)
backend/ geolocate.py, weather.sh, network.sh
style/ _colors.css, style.css