From b5999349a9013a4d80ca8085bba5b9d06a104739 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Fri, 23 Oct 2026 15:26:27 +0200 Subject: companion: above the assistant's dim, and typing means a run of keys The assistant canvas is a full-screen Overlay surface mapped on open, so it covered her and her think and wave were never seen. She moves to the Overlay layer and unmaps and maps again when the canvas opens, since a later surface stacks above an earlier one and Hyprland 0.56.2 has no layer rule to order them: an `order` key was tried, raised no config error, and did nothing. Every key sent her into watching, a shortcut included. The pulse comes at most once a second, so a lone key is one pulse; she now watches from the second pulse within 2.5 s. The hypr-theme hook drops modifiers and chords on its side. Co-Authored-By: Claude Opus 5.5 --- desktop/companion/Companion.qml | 25 +++++++++++++++++++++++-- desktop/companion/README.md | 8 ++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) (limited to 'desktop') diff --git a/desktop/companion/Companion.qml b/desktop/companion/Companion.qml index 0a1360f..1e96ff4 100644 --- a/desktop/companion/Companion.qml +++ b/desktop/companion/Companion.qml @@ -51,7 +51,9 @@ PanelWindow { implicitHeight: 260 color: "transparent" exclusionMode: ExclusionMode.Ignore - WlrLayershell.layer: WlrLayer.Top + // Overlay, the assistant canvas's layer, so she can sit above its dim + // (see remap below). + WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.namespace: "keystone-companion" WlrLayershell.keyboardFocus: WlrKeyboardFocus.None // Her body only: clicks anywhere else, the bubble included, reach the @@ -69,6 +71,7 @@ PanelWindow { property double repliedAt: 0 property double mockAt: 0 property double typingAt: 0 + property double pulseAt: 0 property double wakeAt: 0 property double lastLineAt: 0 property double lastMonologueAt: 0 @@ -112,7 +115,11 @@ PanelWindow { const what = event.data.trim(); const t = Date.now(); if (what === "keystone-typing") { - root.typingAt = t; + // Pulses come at most once a second, so a lone key (a + // shortcut, an arrow) is one pulse and typing is a run + // of them: she watches from the second within 2.5 s. + if (t - root.pulseAt < 2500) root.typingAt = t; + root.pulseAt = t; } else if (what === "keystone-delete") { root.typingAt = t; if (Mood.mockAllowed(root.mockAt, t)) { @@ -129,12 +136,26 @@ PanelWindow { Connections { target: root.asst + function onOpenChanged() { + if (!root.asst.open) return; + root.remapping = true; + remap.restart(); + } function onReplied() { root.repliedAt = Date.now(); root.say("ready"); } } + // Hyprland stacks a later surface above an earlier one on the same layer + // and 0.56.2 has no layer rule to order them, so the canvas's full-screen + // dim covered her and her think and wave were never seen. When it opens + // she unmaps and maps again, after it. + // ponytail: a remap per open; a surface mapped later still covers her. + property bool remapping: false + visible: !root.remapping + Timer { id: remap; interval: 100; onTriggered: root.remapping = false } + // Balloons stack bottom-right of their screen. When that is her corner, // any balloon on screen shoves her left past the stack. readonly property bool shoved: { diff --git a/desktop/companion/README.md b/desktop/companion/README.md index e0eaaf3..a7ce37f 100644 --- a/desktop/companion/README.md +++ b/desktop/companion/README.md @@ -37,6 +37,14 @@ frame falls back to its outfit's `base`. `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 when the assistant canvas opens: + 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). - 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. -- cgit v1.2.3