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, } }