termd/internal/session/modes.go
2026-07-02 22:13:49 -03:00

75 lines
1.6 KiB
Go

package session
import (
"github.com/charmbracelet/x/ansi"
"termd/internal/api"
)
// modeState mirrors the DEC private modes we care about. Fields are written
// from the emulator's mode callbacks, which fire synchronously inside
// em.Write while the session mutex is already held — so plain fields, no
// locking of their own.
type modeState struct {
mouseX10 bool // ?9
mouseNormal bool // ?1000
mouseButton bool // ?1002
mouseAny bool // ?1003
sgrExt bool // ?1006
appCursorKeys bool // ?1 DECCKM
bracketedPaste bool // ?2004
altScreen bool
cursorVisible bool
title string
}
func (m *modeState) set(mode ansi.Mode, on bool) {
switch mode {
case ansi.ModeMouseX10:
m.mouseX10 = on
case ansi.ModeMouseNormal:
m.mouseNormal = on
case ansi.ModeMouseButtonEvent:
m.mouseButton = on
case ansi.ModeMouseAnyEvent:
m.mouseAny = on
case ansi.ModeMouseExtSgr:
m.sgrExt = on
case ansi.ModeCursorKeys:
m.appCursorKeys = on
case ansi.ModeBracketedPaste:
m.bracketedPaste = on
}
}
// mouseMode reports the effective tracking mode — the highest one set, which
// is also the one the emulator's SendMouse picks.
func (m *modeState) mouseMode() string {
switch {
case m.mouseAny:
return "any_event"
case m.mouseButton:
return "button_event"
case m.mouseNormal:
return "normal"
case m.mouseX10:
return "x10"
default:
return "off"
}
}
func (m *modeState) api() api.Modes {
enc := "default"
if m.sgrExt {
enc = "sgr"
}
return api.Modes{
Mouse: m.mouseMode(),
MouseEncoding: enc,
AppCursorKeys: m.appCursorKeys,
BracketedPaste: m.bracketedPaste,
}
}