aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/companion/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/companion/README.md')
-rw-r--r--desktop/companion/README.md117
1 files changed, 0 insertions, 117 deletions
diff --git a/desktop/companion/README.md b/desktop/companion/README.md
deleted file mode 100644
index 2bd6c4e..0000000
--- a/desktop/companion/README.md
+++ /dev/null
@@ -1,117 +0,0 @@
-# companion
-
-A chibi 2B in the bottom-right corner of the focused monitor, on SUPER+\.
-The design, with what was measured on the way, is
-`docs/superpowers/specs/2026-10-23-companion-design.md`.
-
-## Files
-
-| File | |
-| --- | --- |
-| `Companion.qml` | the window, inputs, timers, speech, IPC (`companion toggle/show/hide`) |
-| `Figure.qml` | draws a frame: crossfade, bob, drop out and back, explosion |
-| `Mood.js` | which state wins, from a snapshot; all the timings are its `T` |
-| `Lines.js` | her reaction, per-app and per-artist lines, and the opening monologue |
-| `Admired.qml` | the wallpaper list she blushes at, and what wallp has on each monitor |
-| `ListFile.js` | that list as plain text: parse and toggle |
-| `prep-frames` | generated images to display frames |
-| `gen-frames`, `frames.txt` | the generated images, through sd-server |
-
-`Figure.qml` is not `Sprite.qml` because QtQuick has a `Sprite` type, and
-it wins over the directory's own file (see AGENTS.md).
-
-Whether she is shown is `companion` in `Prefs.qml`, so it survives a
-restart: SUPER+\ and the switch on Settings > Companion
-(`desktop/modules/companion/`) both set it.
-
-A hide by SUPER+\ or that switch plays a goodbye first: she waves (`wave`,
-`wave-l` and `wave-r` cycling) and then drops out. One hide in four she also
-says a `bye` line, under the usual 30 s line cooldown; with a line she holds
-`Mood.T.goodbye` (2 s, enough to read it), silently only
-`Mood.T.goodbyeSilent` (0.5 s). Fullscreen, the lock screen and the monitor
-hop keep their own exits and do not wave.
-
-## Art
-
-Not in the repo: the character is Square Enix's and this repo is GPLv2.
-It lives in `~/.local/share/keystone/companion/2b/`:
-
- dress/<name>.png, leotard/<name>.png generated, 1024x1024 on white
- frames/<outfit>/<name>.png what she shows, from prep-frames
- recipe.txt how each was made, and what failed
-
-Run `prep-frames` after adding or replacing any generated image. A missing
-frame falls back to its outfit's `base`.
-
-## Inputs
-
-- Typing and BackSpace come from `sections/companion.lua` in the
- hypr-theme repo, as `custom>>keystone-typing` and
- `custom>>keystone-delete` on socket2. Nothing else about the keyboard
- reaches her. The BackSpace bind is `non_consuming`; checked by hand that
- it still deletes in a terminal and in the browser.
-- The typing pulse skips modifiers and any key pressed with Ctrl, Alt or
- Super held, so a shortcut is not typing; Shift and AltGr still count.
- She watches only from the second pulse within 2.5 s, so a lone key is
- not typing either.
-- She is on the Overlay layer and remaps whenever another layer surface
- opens (Hyprland's `openlayer` event: the assistant's dim, rofi, the
- keybind reminder), vanishing and hopping back in, because Hyprland
- stacks a later surface above an earlier one on a layer, and 0.56.2 has
- no layer rule to order them (no `order` key in the binary; an unknown
- key raises no config error).
-- The assistant's tall card (a chat, or its history, picker or models
- panel) seats her on its top edge, right of centre, through the monitor
- hop. `Assistant.qml` gives `tall` and `cardTop`; seated she ignores
- balloons and shows `Mood.seatFrame` of her frame, the `sit-*` set. The
- bar and the file card leave her in the corner: standing frames face
- out, not down at the text. Typing and BackSpace still reach her under
- the canvas's exclusive keyboard (checked on socket2).
-- The program in front of her is Hyprland's `activewindow` event,
- `class,title`. It also fires on every title change, so she reacts
- only when the class changes, a third of the time, under the 30 s line
- cooldown. Lines are by lowercased class in `Lines.js`; a class with
- none says nothing. Settings > Companion > Companion phrases edits them
- into `Prefs.companionApps`, which then replaces the defaults.
-- A listed wallpaper (Settings > Companion for the file, the
- heart in the wallpaper picker for entries) on an empty workspace: she
- turns to it with `watch` and blushes with `blush3`, at most every 3
- minutes. Checked on `workspacev2` and `closewindow`, and whenever she
- stops being away. Her monitor's wallpaper comes from wallp's
- `wallp.conf` outputs and `wall_h`/`wall_v`.
-- Sony headphones connecting are the island's rule (`island/StatusPill.qml`:
- `WH-`/`WF-`/`LinkBuds` by name, since BlueZ has no headphones class): she
- sings once for `Mood.T.singHold`, 4 s, and says a line if the usual 30 s
- cooldown allows it. A shell start with them already on is not a connection:
- Bluetooth reads empty for ~2 s, then populates.
-- What is playing is `modules/sound/Player.qml`, which already drops the
- playerctld and browser-integration duplicates. A new artist+title while
- playing makes her DJ for `Mood.T.djHold`, 6 s (`dj` and `dj-scratch`
- cycling), and say the artist's line if one matches: lowercased keys in
- `Lines.artists`, matched as a substring, edited on Settings > Companion
- artists into `Prefs.companionArtists`. Pause and resume of the same
- track is not a change; a shell start with music on DJs once. While
- music plays, the first idle stage is a groove instead of bored:
- `whistle`, `headbang` (`headbang-up`/`-down` cycling) or `airguitar`,
- picked at random, with a `groove` line; yawning and lying down are
- unchanged.
-- She only feels the pointer while it is over her: Quickshell has no
- global pointer and Hyprland sends no motion events. Hence the 0.6 s
- dodge rather than moving away as the pointer approaches.
-- Idle stages are 20, 40 and 70% of wscreensavers' `idleTimeoutMinutes`,
- read live from its config, so she lies down before the saver starts.
-- `IdleMonitor.enabled` read false on creation when left out, so each of
- the three sets it. It also reads false at `Component.onCompleted` even
- when set, and true a moment later; do not trust that first reading.
-- The monitors ignore inhibitors. No lock holds an idle inhibitor for as
- long as it is on, and with `respectInhibitors: true` she never idled
- (measured: a 5 s monitor respecting them never fired, one ignoring them
- did). Presentation and gaming mode keep her awake by name instead.
-- Fullscreen is `lastIpcObject.fullscreen === 2`. Maximised is 1, and
- most windows here are maximised.
-- The lock screen covers every layer, so locking needs no code.
-
-## Check
-
- node desktop/companion/test_mood.js
- node desktop/companion/test_lines.js