1616import type { Ghostty } from './ghostty' ;
1717import type { KeyEncoder } from './ghostty' ;
1818import type { IKeyEvent } from './interfaces' ;
19- import { Key , KeyAction , Mods } from './types' ;
19+ import { Key , KeyAction , KeyEncoderOption , Mods } from './types' ;
2020
2121/**
2222 * Map KeyboardEvent.code values to USB HID Key enum values
@@ -135,8 +135,8 @@ const KEY_MAP: Record<string, Key> = {
135135 NumpadDecimal : Key . KP_PERIOD ,
136136
137137 // International
138- IntlBackslash : Key . NON_US_BACKSLASH ,
139- ContextMenu : Key . APPLICATION ,
138+ IntlBackslash : Key . INTL_BACKSLASH ,
139+ ContextMenu : Key . CONTEXT_MENU ,
140140
141141 // Additional function keys
142142 F13 : Key . F13 ,
@@ -165,6 +165,7 @@ export class InputHandler {
165165 private onBellCallback : ( ) => void ;
166166 private onKeyCallback ?: ( keyEvent : IKeyEvent ) => void ;
167167 private customKeyEventHandler ?: ( event : KeyboardEvent ) => boolean ;
168+ private getModeCallback ?: ( mode : number ) => boolean ;
168169 private keydownListener : ( ( e : KeyboardEvent ) => void ) | null = null ;
169170 private keypressListener : ( ( e : KeyboardEvent ) => void ) | null = null ;
170171 private pasteListener : ( ( e : ClipboardEvent ) => void ) | null = null ;
@@ -178,21 +179,24 @@ export class InputHandler {
178179 * @param onBell - Callback for bell/beep event
179180 * @param onKey - Optional callback for raw key events
180181 * @param customKeyEventHandler - Optional custom key event handler
182+ * @param getMode - Optional callback to query terminal mode state (for application cursor mode)
181183 */
182184 constructor (
183185 ghostty : Ghostty ,
184186 container : HTMLElement ,
185187 onData : ( data : string ) => void ,
186188 onBell : ( ) => void ,
187189 onKey ?: ( keyEvent : IKeyEvent ) => void ,
188- customKeyEventHandler ?: ( event : KeyboardEvent ) => boolean
190+ customKeyEventHandler ?: ( event : KeyboardEvent ) => boolean ,
191+ getMode ?: ( mode : number ) => boolean
189192 ) {
190193 this . encoder = ghostty . createKeyEncoder ( ) ;
191194 this . container = container ;
192195 this . onDataCallback = onData ;
193196 this . onBellCallback = onBell ;
194197 this . onKeyCallback = onKey ;
195198 this . customKeyEventHandler = customKeyEventHandler ;
199+ this . getModeCallback = getMode ;
196200
197201 // Attach event listeners
198202 this . attach ( ) ;
@@ -347,19 +351,7 @@ export class InputHandler {
347351 case Key . ESCAPE :
348352 simpleOutput = '\x1B' ; // ESC
349353 break ;
350- // Arrow keys (CSI sequences)
351- case Key . UP :
352- simpleOutput = '\x1B[A' ;
353- break ;
354- case Key . DOWN :
355- simpleOutput = '\x1B[B' ;
356- break ;
357- case Key . RIGHT :
358- simpleOutput = '\x1B[C' ;
359- break ;
360- case Key . LEFT :
361- simpleOutput = '\x1B[D' ;
362- break ;
354+ // Arrow keys are handled by the encoder (respects application cursor mode)
363355 // Navigation keys
364356 case Key . HOME :
365357 simpleOutput = '\x1B[H' ;
@@ -430,6 +422,13 @@ export class InputHandler {
430422
431423 // For non-printable keys or keys with modifiers, encode using Ghostty
432424 try {
425+ // Sync encoder options with terminal mode state
426+ // Mode 1 (DECCKM) controls whether arrow keys send CSI or SS3 sequences
427+ if ( this . getModeCallback ) {
428+ const appCursorMode = this . getModeCallback ( 1 ) ;
429+ this . encoder . setOption ( KeyEncoderOption . CURSOR_KEY_APPLICATION , appCursorMode ) ;
430+ }
431+
433432 // For letter/number keys, even with modifiers, pass the base character
434433 // This helps the encoder produce correct control sequences (e.g., Ctrl+A = 0x01)
435434 // For special keys (Enter, Arrow keys, etc.), don't pass utf8
0 commit comments