diff options
Diffstat (limited to 'desktop/README.md')
| -rw-r--r-- | desktop/README.md | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/desktop/README.md b/desktop/README.md new file mode 100644 index 0000000..0350f9a --- /dev/null +++ b/desktop/README.md @@ -0,0 +1,133 @@ +# desktop + +One drawer, left of DP-1, hosting the things a desktop lets you adjust. +Reached from a launcher at the left end of waybar. + +The drawer opens as a grid of tiles, and clicking a tile either opens that +module's page or fires an action. Escape, a click outside, or a module's back +arrow returns to the grid; Escape again closes the drawer. It takes keyboard +focus while it is open, so those keys reach it. + +## Running it + + qs -p ./desktop + + qs -p ./desktop ipc call drawer toggle # the grid + qs -p ./desktop ipc call drawer open mail # straight to a page + +`open` always takes a page name, because quickshell 0.3.1 IPC requires every +declared argument to be present and a defaulted parameter registers as a type +the IPC layer rejects. The page-less grid entry is therefore the zero-argument +`toggle`. `ipc call drawer close` closes it. + +## The modules + + modules/sound/ output and input volume, the OSD, the player + modules/mail/ unread per account, threads, the watcher dot + modules/vm/ libvirt state, live stats, snapshots + modules/appearance/ a tile that opens the separate appearance shell + +Sound, mail and vm each carry their own README. Appearance is a tile onto the +separate appearance shell, whose README covers the picker it opens. + +## Writing a module + +A module is a `Module` (from `Module.qml` in this directory) declaring what the +drawer needs to show it: + +- `name`: identifies the module, both for grid ordering and for IPC, where it + is the page name `ipc call drawer open <name>` takes. +- `icon` and `label`: the glyph and the text on the tile. +- `tileContent`: a `Component` for the short state line under the label, or + null for a tile that says nothing beyond its name. +- `page`: a `Component` for the full-height page behind the tile, or null. +- `activate()`: what a tile with no page does when clicked. +- `alwaysActive`: whether the module's background service runs while the + drawer is closed, covered below. + +A module provides a tile, a page, both, or neither. The drawer does not care +which: it reads those properties and does the obvious thing. A page is wrapped +in `Page.qml` for the header and back arrow, and a tile with no page is +fire-and-forget, so its click calls `activate()` and closes the drawer. + +`modules/appearance/AppearanceModule.qml` is the smallest complete example: a +name, an icon, a label, and an `activate()` that launches the separate +appearance shell. It has no page and no service. Sound, mail and vm each add a +service and a page on top of that same shape. + +Module files live under `desktop/modules/<name>/` and reference root types +(`Module`, `Page`, `Button`, `Theme`), so each needs `import "../.."`. A plain +directory import does not reach the parent. The moved `TransportButton.qml` and +`Stat.qml` gained that import for the same reason. + +## alwaysActive + +Sound and mail are `alwaysActive: true`; vm is false. The property governs the +module's background service, not its page: pages are lazily loaded either way. + +Sound's OSD has to answer a volume keypress with no drawer open, which is the +whole point of it, so its PipeWire service runs for the session. Mail's unread +count outlives the drawer and its config watcher makes a newly added account +appear without a restart, so its service runs too. The vm module's 2s stats +poll exists only to paint a page nobody is looking at, so it starts and stops +with the page. + +That last line is not the whole story for vm: its lifecycle event stream runs +unconditionally, which is what keeps the VM list and the tile's dots current +while the page is closed. `alwaysActive` gates the poll, not everything the +module does. + +## Geometry + +The panel is 600px wide and full height, on `DP-1`. Waybar runs there and the +launcher sits at its left end, while conky holds the right side of the screen, +so the drawer belongs on the left. It falls back to the first screen when +`DP-1` is not connected, so the drawer is never invisible. + +The window uses `ExclusionMode.Normal`, not `Ignore`. Waybar claims an +exclusive zone at the top of the screen, so respecting it puts the drawer below +the bar without this code knowing the bar's height, and the bar stays visible +and clickable while the drawer is open. The whole surface is an overlay so a +click outside closes it. + +The top of the panel is an empty reserved area for the notification engine. It +is an empty `Item` claiming the space, not a placeholder graphic, so the grid +below it sits where it will sit once notifications arrive. The bottom is a +fixed, never-scrolled `Flow` grid: three columns at 180px minimum, wrapping +and adding rows up to a 3x3 ceiling for the modules that exist. + +## Hyprland and waybar + +Nothing here is in the repo's control, and the drawer works without it. Two +pieces of outside configuration belong to it. + +Frosting is the compositor's, matched on the namespace this window sets. The +drawer sets `quickshell-desktop`, so it needs: + + hl.layer_rule({ + name = "blur-desktop", + match = { namespace = "^(quickshell-desktop)$" }, + blur = true, + xray = false, + ignore_alpha = 0.1, + }) + +The sound module's OSD owns its own window and keeps its old +`quickshell-volume-osd` namespace, so the existing `blur-volume-osd` rule still +matches and stays. Without any of these the surfaces still render, just flat +translucent. + +The waybar launcher is a static `custom` module with no `exec`, so it cannot +show whether the drawer is open. Its `on-click` runs the zero-argument toggle: + + "on-click": "qs -p ~/Programming/GIT/quickshell/desktop ipc call drawer toggle" + +The mail module's waybar count keeps its own `custom` module, whose click +deep-links to the mail page with `ipc call drawer open mail`. `SUPER+v` reaches +the vm page the same way, with `ipc call drawer open vm`. The full list of +edits to the live Hyprland and waybar configuration is Task 10 of the plan in +`docs/superpowers/plans/2026-09-14-desktop-shell.md`. + +## Theme + +`Theme.qml` is a symlink to `shared/Theme.qml`, as in every component here. |
