island: card on one monitor, live bars only on the focused one

- the card opens on the monitor that was clicked (keybinds: the focused
  monitor); the others keep their pill. moving the card to another monitor
  restarts its open animation there
- only the focused monitor's window (and the one with the card) reads
  Spectrum, so the other pills show still bars and rest
- hover lights only the pill under the pointer
- measured with music on 3 monitors: pill 10.7% of a core (was 27.5%),
  open card 20.7% (was 58%), ~62 frames a second in total, 0-1 slow
  frames per open/close (was 7-14), back to one island's cost
This commit is contained in:
server2
2026-10-08 01:25:33 +02:00
parent 967ff37b78
commit 7844a98828
4 changed files with 85 additions and 22 deletions
+6 -1
View File
@@ -30,7 +30,9 @@ The equalizer: one `setsid -f pipewire -c eq-<key>.conf` process per player with
### The view (island.rs `view`)
- One `LayerWindow` (namespace `magic-island`, `Layer::Overlay` because the user's windows are fullscreen) sized for the open card; an `InputArea` lets clicks outside the island through.
- One `LayerWindow` per monitor (`window_per_monitor`, namespace `magic-island`, `Layer::Overlay` because the user's windows are fullscreen) sized for the open card; an `InputArea` lets clicks outside the island through.
- All windows share the `Island` state. `opened_on` names the monitor the card is open on (others show their pill), `pointer_on` the monitor whose pill is hovered. Only the focused monitor's window (and the one with the card) reads `Spectrum`, so the others don't redraw for every cava frame: with music, pill ~11% of a core and open card ~21%, as with one island. `focused_monitor()` comes from `Workspaces`, which follows the mouse on Hyprland.
- `Spectrum::listen` first `pkill -KILL -f`s any cava running our `cava.conf`: a stopped shell leaves its cava behind, and cava ignores SIGTERM.
- `phases(open)` splits the one linear 560 ms timeline: pill fades out over 0–0.18, the empty shape grows over 0–0.6 (cubic ease-out), the card fades in over 0.6–1 (smoothstep). Closing runs it backwards. At most one face (pill or card) is built per frame.
- `veiled()` fades a face by laying the backdrop gradient over it with alpha `1 - shown` instead of `.opacity()`: same picture, no GPU layer.
- `backdrop_colors()` / `backdrop()`: one 150° three-stop gradient from the palette (dominant, `colors()[1]`, `background()`), each darkened by `deepen()` to a max brightness of 0.22 / 0.15 / 0.07.
@@ -96,6 +98,9 @@ tools/amane-remote.sh $H sh 'COMMAND' # anything inside the graphical sessi
- Pick a fake player with `ipc island next` until `status` names it, before anything that changes sound.
- The island follows the focused monitor: read its geometry from `hyprctl layers -j` (namespace `magic-island`) right before each `grim` capture.
- With one window per monitor, `fps` and `anim` count every window's frames together; resting windows add ~1000 ms gaps (one frame a second for the time bar). Those aren't stalls.
- The desktop's `$XDG_RUNTIME_DIR/hypr/` keeps folders of dead Hyprland instances; the live one is the one with `.socket.sock`, which `amane-remote.sh` now picks. A shell started with a dead signature gets an empty `Workspaces` list.
- Once, a fresh shell exited with "lost the gpu (Device is lost)" (Mesa warns the Xe driver is experimental); starting it again worked.
- The user's pointer may be over the island and open or collapse it during a test; check `status` and capture right after `open`.
- To tune a visualiser, sample the real levels read-only (`pw-record --target <stream> | cava`, with `timeout -s KILL` on each stage; a plain `timeout` on a pipeline orphans cava) and look at the distribution first. Typical music sits at 0.15–0.35.
- In `pkill -f` patterns over SSH, use `[p]ython3 ...` so the pattern doesn't match the remote shell itself.