// Fenrir console screen reader. // Copyright (c) 2026 Storm Dragon // SPDX-License-Identifier: GPL-3.0-or-later // // This program is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation, either version 3 of the License, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // // You should have received a copy of the GNU General Public License along with // this program. If not, see . package input import ( "git.stormux.org/storm/fenrir/internal/interaction" "time" ) // Capture changes ownership without forgetting physical keys. Keys held on // entry cannot navigate the UI; keys held on exit cannot repeat into a terminal. // Backends release previously forwarded keys before enabling capture. func (r *Router) Capture(enabled bool) { r.lastPress = time.Time{} r.captured = enabled r.capsUsed = true r.passArmed, r.passing = false, false for _, held := range r.keys { for code, state := range held { state.forwarded, state.ui = false, false state.commandID = "" held[code] = state } } } func (r *Router) Captured() bool { return r.captured } func (r *Router) ui_key(code uint16) Decision { key := &interaction.Key{ Shift: r.down(KeyShift) || r.down(KeyRightShift), Ctrl: r.down(KeyCtrl) || r.down(KeyRightCtrl), Alt: r.down(KeyAlt), // Right Alt is text input (AltGr). AltGr: r.down(KeyRightAlt), } switch code { case KeyEsc: key.Name = "escape" case KeyTab: key.Name = "tab" case KeyEnter, KeyKPEnter: key.Name = "enter" case KeySpace: key.Name = "space" key.Text = " " case KeyUp: key.Name = "up" case KeyDown: key.Name = "down" case KeyLeft: key.Name = "left" case KeyRight: key.Name = "right" case KeyHome: key.Name = "home" case KeyEnd: key.Name = "end" case KeyBackspace: key.Name = "backspace" case KeyDelete: key.Name = "delete" } return Decision{UI: key, Interrupt: true} }