config.json gains a "layouts" key to narrow which hypr/layouts-discovered layouts astro-menu offers (and reorder them), plus per-layout option overrides (trim directions, hide fit_method/stepper), without touching the .lua layout sources. Also: the taskbar's workspace/layout panel now polls every second while the menu is open, since switching workspaces doesn't notify (or get blocked by) the menu and the panel previously only refreshed on open. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| backend | ||
| lib | ||
| modules | ||
| services | ||
| style | ||
| ui | ||
| .gitignore | ||
| README.md | ||
| appservices.py | ||
| config.py | ||
| main.py | ||
| module_base.py | ||
| paths.py | ||
| registry.py | ||
| settings.py | ||
| theme.py | ||
| window.py | ||
README.md
astro-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/astro-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
astro-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