feat(lotus): report host call hotkeys from inside the frame (cinny #43)

The host used to add PTT/deafen key listeners to this frame's window,
which needs same-origin access. Now it sends `io.lotus.set_hotkeys
{ codes }` and the fork reports those keys as `io.lotus.hotkey`
(keydown/keyup with modifiers + whether the target is a text field or a
button), plus window focus changes so a held PTT is released. The
default action is cancelled here with the host's rules (not while typing,
not on a focused button). `controls_state` carries `hotkeys: true`.

Fixes a live bug: EC's own shortcuts (M = toggle mic, Space = PTT) also
fired for the host's keys, so with focus in the call and the default
deafen key M, the first press turned the MIC ON instead of deafening
(even in push-to-talk mode). EC's shortcuts now ignore keys the host owns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
Lotus CI
2026-09-26 13:59:34 -04:00
co-authored by Claude Opus 5.5
parent c4f6193888
commit e0eecc5271
7 changed files with 232 additions and 1 deletions
+4
View File
@@ -14,6 +14,7 @@ import {
ReactionSet,
ReactionsRowSize,
} from "./reactions";
import { isLotusHostHotkey } from "./lotus/lotusHotkeys";
/**
* Determines whether focus is in the same part of the tree as the given
@@ -86,6 +87,8 @@ export function useCallViewKeyboardShortcuts(
useCallback(
(event: KeyboardEvent) => {
logger.info("Keydown event", event);
// [lotus] The Lotus host owns its PTT / deafen keys (cinny #43).
if (isLotusHostHotkey(event.code)) return;
if (!mayReceiveKeyEvents()) return;
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)
return;
@@ -132,6 +135,7 @@ export function useCallViewKeyboardShortcuts(
"keyup",
useCallback(
(event: KeyboardEvent) => {
if (isLotusHostHotkey(event.code)) return;
if (!mayReceiveKeyEvents() || !mayReceiveSpaceKeyEvents()) return;
if (event.key === " ") {
spacebarHeld.current = false;