# 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 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 > Desktop > Companion (`desktop/modules/companion/`) both set it. ## 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/.png, leotard/.png generated, 1024x1024 on white frames//.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 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 `app:` in `Lines.js`, class lowercased; a class with none says nothing. - A listed wallpaper (Settings > Desktop > 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`. - 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