Skip to main content

libghostty_vt/
key.rs

1//! Encoding key events into terminal escape sequences,
2//!
3//! Supports both legacy encoding as well as Kitty Keyboard Protocol.
4//!
5//! # Basic Usage
6//!
7//!  1. Create an encoder instance with [`Encoder::new`].
8//!  2. Configure encoder options with the various `Encoder::set_*` methods
9//!     or [`Encoder::set_options_from_terminal`] if you have a [`Terminal`].
10//!  3. For each key event:
11//!     *  Create a key event with [`Event::new`] (or reuse an existing one)
12//!     *  Set event properties (action, key, modifiers, etc.)
13//!     *  Encode with [`Encoder::encode_to_vec`] (with a growable `Vec` buffer)
14//!        or [`Encoder::encode`] (with a fixed byte buffer).
15use std::mem::MaybeUninit;
16
17use crate::{
18    Error,
19    alloc::{Allocator, Object},
20    error::{Result, from_result, from_result_with_len},
21    ffi::{self, KeyEncoderOption as Opt},
22    terminal::Terminal,
23};
24
25/// Key encoder that converts key events into terminal escape sequences.
26#[derive(Debug)]
27pub struct Encoder<'alloc>(Object<'alloc, ffi::KeyEncoderImpl>);
28
29impl<'alloc> Encoder<'alloc> {
30    /// Create a new key encoder instance.
31    pub fn new() -> Result<Self> {
32        // SAFETY: A NULL allocator is always valid
33        unsafe { Self::new_inner(std::ptr::null()) }
34    }
35
36    /// Create a new key encoder instance with a custom allocator.
37    ///
38    /// See the [crate-level documentation](crate#memory-management-and-lifetimes)
39    /// regarding custom memory management and lifetimes.
40    pub fn new_with_alloc<'ctx: 'alloc>(alloc: &'alloc Allocator<'ctx>) -> Result<Self> {
41        // SAFETY: Borrow checking should forbid invalid allocators
42        unsafe { Self::new_inner(alloc.to_raw()) }
43    }
44
45    unsafe fn new_inner(alloc: *const ffi::Allocator) -> Result<Self> {
46        let mut raw: ffi::KeyEncoder = std::ptr::null_mut();
47        let result = unsafe { ffi::ghostty_key_encoder_new(alloc, &raw mut raw) };
48        from_result(result)?;
49        Ok(Self(Object::new(raw)?))
50    }
51
52    unsafe fn setopt(
53        &mut self,
54        option: ffi::KeyEncoderOption::Type,
55        value: *const std::ffi::c_void,
56    ) {
57        unsafe { ffi::ghostty_key_encoder_setopt(self.0.as_raw(), option, value) }
58    }
59
60    /// Encode a key event into a terminal escape sequence.
61    ///
62    /// Converts a key event into the appropriate terminal escape sequence
63    /// based on the encoder's current options.
64    ///
65    /// Not all key events produce output. For example, unmodified modifier
66    /// keys typically don't generate escape sequences. Check the returned
67    /// `Vec` to determine if any data was written.
68    pub fn encode_to_vec(&mut self, event: &Event, vec: &mut Vec<u8>) -> Result<()> {
69        let remaining = vec.capacity() - vec.len();
70
71        let written = match self.encode_to_uninit_buf(event, vec.spare_capacity_mut()) {
72            Ok(v) => Ok(v),
73            Err(Error::OutOfSpace { required }) => {
74                // Retry with more capacity
75                vec.reserve(required - remaining);
76                self.encode_to_uninit_buf(event, vec.spare_capacity_mut())
77            }
78            Err(e) => Err(e),
79        };
80
81        // SAFETY: A successful call to `encode_to_uninit_buf` assures us
82        // that a `written` number of bytes have been initialized.
83        unsafe { vec.set_len(vec.len() + written?) };
84        Ok(())
85    }
86
87    /// Encode a key event into a terminal escape sequence.
88    ///
89    /// Converts a key event into the appropriate terminal escape sequence
90    /// based on the encoder's current options. The sequence is written to
91    /// the provided buffer.
92    ///
93    /// Not all key events produce output. For example, unmodified modifier
94    /// keys typically don't generate escape sequences. Check the returned
95    /// `usize` to determine if any data was written.
96    ///
97    /// If the output buffer is too small, this returns
98    /// `Err(Error::OutOfSpace { required })` where `required` is the required
99    /// buffer size. The caller can then allocate a larger buffer and call
100    /// the method again.
101    pub fn encode(&mut self, event: &Event, buf: &mut [u8]) -> Result<usize> {
102        // SAFETY: It is always safe to reinterpret T as a MaybeUninit<T>.
103        self.encode_to_uninit_buf(event, unsafe {
104            std::slice::from_raw_parts_mut(buf.as_mut_ptr().cast(), buf.len())
105        })
106    }
107
108    fn encode_to_uninit_buf(
109        &mut self,
110        event: &Event,
111        buf: &mut [MaybeUninit<u8>],
112    ) -> Result<usize> {
113        let mut written: usize = 0;
114        let result = unsafe {
115            ffi::ghostty_key_encoder_encode(
116                self.0.as_raw(),
117                event.inner.as_raw(),
118                buf.as_mut_ptr().cast(),
119                buf.len(),
120                &raw mut written,
121            )
122        };
123        from_result_with_len(result, written)
124    }
125
126    /// Set encoder options from a terminal's current state.
127    ///
128    /// Reads the terminal's current modes and flags and applies them to the
129    /// encoder's options. This sets cursor key application mode, keypad mode,
130    /// alt escape prefix, modifyOtherKeys state, and Kitty keyboard protocol
131    /// flags from the terminal state.
132    ///
133    /// Note that the `macos_option_as_alt` option cannot be determined from
134    /// terminal state and is reset to [`OptionAsAlt::False`] by this call.
135    /// Use [`Encoder::set_macos_option_as_alt`] to set it afterward if needed.
136    pub fn set_options_from_terminal(&mut self, terminal: &Terminal<'_, '_>) -> &mut Self {
137        unsafe {
138            ffi::ghostty_key_encoder_setopt_from_terminal(self.0.as_raw(), terminal.inner.as_raw());
139        }
140        self
141    }
142
143    /// Set terminal DEC mode 1: cursor key application mode.
144    pub fn set_cursor_key_application(&mut self, value: bool) -> &mut Self {
145        unsafe {
146            self.setopt(
147                Opt::CURSOR_KEY_APPLICATION,
148                std::ptr::from_ref(&value).cast(),
149            );
150        }
151        self
152    }
153    /// Set terminal DEC mode 66: keypad key application mode.
154    pub fn set_keypad_key_application(&mut self, value: bool) -> &mut Self {
155        unsafe {
156            self.setopt(
157                Opt::KEYPAD_KEY_APPLICATION,
158                std::ptr::from_ref(&value).cast(),
159            );
160        }
161        self
162    }
163    /// Set terminal DEC mode 1035: ignore keypad with numlock.
164    pub fn set_ignore_keypad_with_numlock(&mut self, value: bool) -> &mut Self {
165        unsafe {
166            self.setopt(
167                Opt::IGNORE_KEYPAD_WITH_NUMLOCK,
168                std::ptr::from_ref(&value).cast(),
169            );
170        }
171        self
172    }
173    /// Set terminal DEC mode 1036: alt sends escape prefix.
174    pub fn set_alt_esc_prefix(&mut self, value: bool) -> &mut Self {
175        unsafe {
176            self.setopt(Opt::ALT_ESC_PREFIX, std::ptr::from_ref(&value).cast());
177        }
178        self
179    }
180    /// Set xterm modifyOtherKeys mode 2.
181    pub fn set_modify_other_keys_state_2(&mut self, value: bool) -> &mut Self {
182        unsafe {
183            self.setopt(
184                Opt::MODIFY_OTHER_KEYS_STATE_2,
185                std::ptr::from_ref(&value).cast(),
186            );
187        }
188        self
189    }
190    /// Set Kitty keyboard protocol flags.
191    pub fn set_kitty_flags(&mut self, value: KittyKeyFlags) -> &mut Self {
192        let value = value.bits();
193        unsafe {
194            self.setopt(Opt::KITTY_FLAGS, std::ptr::from_ref(&value).cast());
195        }
196        self
197    }
198    /// Set macOS option-as-alt setting.
199    pub fn set_macos_option_as_alt(&mut self, value: OptionAsAlt) -> &mut Self {
200        unsafe {
201            self.setopt(Opt::MACOS_OPTION_AS_ALT, std::ptr::from_ref(&value).cast());
202        }
203        self
204    }
205    /// Backarrow key mode.
206    ///
207    /// See <https://vt100.net/dec/ek-vt3xx-tp-002.pdf> page 170.
208    ///
209    /// If `false` (the default), `backspace` emits 0x7f.
210    /// If `true`, `backspace` emits 0x08.
211    pub fn set_backarrow_key_mode(&mut self, value: bool) -> &mut Self {
212        unsafe {
213            self.setopt(Opt::BACKARROW_KEY_MODE, std::ptr::from_ref(&value).cast());
214        }
215        self
216    }
217}
218
219impl Drop for Encoder<'_> {
220    fn drop(&mut self) {
221        unsafe { ffi::ghostty_key_encoder_free(self.0.as_raw()) }
222    }
223}
224
225/// Keyboard input event containing information about the physical key pressed,
226/// modifiers, and generated text.
227#[derive(Debug)]
228pub struct Event<'alloc> {
229    inner: Object<'alloc, ffi::KeyEventImpl>,
230    text: Option<String>,
231}
232
233impl<'alloc> Event<'alloc> {
234    /// Create a new key event instance.
235    pub fn new() -> Result<Self> {
236        // SAFETY: A NULL allocator is always valid
237        unsafe { Self::new_inner(std::ptr::null()) }
238    }
239
240    /// Create a new key event instance with a custom allocator.
241    ///
242    /// See the [crate-level documentation](crate#memory-management-and-lifetimes)
243    /// regarding custom memory management and lifetimes.
244    pub fn new_with_alloc<'ctx: 'alloc>(alloc: &'alloc Allocator<'ctx>) -> Result<Self> {
245        // SAFETY: Borrow checking should forbid invalid allocators
246        unsafe { Self::new_inner(alloc.to_raw()) }
247    }
248
249    unsafe fn new_inner(alloc: *const ffi::Allocator) -> Result<Self> {
250        let mut raw: ffi::KeyEvent = std::ptr::null_mut();
251        let result = unsafe { ffi::ghostty_key_event_new(alloc, &raw mut raw) };
252        from_result(result)?;
253        Ok(Self {
254            inner: Object::new(raw)?,
255            text: None,
256        })
257    }
258
259    /// Set the key action (press, release, repeat).
260    pub fn set_action(&mut self, action: Action) -> &mut Self {
261        unsafe { ffi::ghostty_key_event_set_action(self.inner.as_raw(), action.into()) }
262        self
263    }
264
265    /// Get the key action (press, release, repeat).
266    #[must_use]
267    pub fn action(&self) -> Action {
268        Action::try_from(unsafe { ffi::ghostty_key_event_get_action(self.inner.as_raw()) })
269            .unwrap_or(Action::Press)
270    }
271
272    /// Set the physical key code.
273    pub fn set_key(&mut self, key: Key) -> &mut Self {
274        unsafe { ffi::ghostty_key_event_set_key(self.inner.as_raw(), key.into()) }
275        self
276    }
277
278    /// Get the physical key code.
279    #[must_use]
280    pub fn key(&self) -> Key {
281        Key::try_from(unsafe { ffi::ghostty_key_event_get_key(self.inner.as_raw()) })
282            .unwrap_or(Key::Unidentified)
283    }
284
285    /// Set the modifier keys bitmask.
286    pub fn set_mods(&mut self, mods: Mods) -> &mut Self {
287        unsafe { ffi::ghostty_key_event_set_mods(self.inner.as_raw(), mods.bits()) }
288        self
289    }
290
291    /// Get the modifier keys bitmask.
292    #[must_use]
293    pub fn mods(&self) -> Mods {
294        Mods::from_bits_retain(unsafe { ffi::ghostty_key_event_get_mods(self.inner.as_raw()) })
295    }
296
297    /// Set the consumed modifiers bitmask.
298    pub fn set_consumed_mods(&mut self, mods: Mods) -> &mut Self {
299        unsafe { ffi::ghostty_key_event_set_consumed_mods(self.inner.as_raw(), mods.bits()) }
300        self
301    }
302
303    /// Get the consumed modifiers bitmask.
304    #[must_use]
305    pub fn consumed_mods(&self) -> Mods {
306        Mods::from_bits_retain(unsafe {
307            ffi::ghostty_key_event_get_consumed_mods(self.inner.as_raw())
308        })
309    }
310
311    /// Set whether the key event is part of a composition sequence.
312    pub fn set_composing(&mut self, composing: bool) -> &mut Self {
313        unsafe { ffi::ghostty_key_event_set_composing(self.inner.as_raw(), composing) }
314        self
315    }
316
317    /// Get whether the key event is part of a composition sequence.
318    #[must_use]
319    pub fn is_composing(&self) -> bool {
320        unsafe { ffi::ghostty_key_event_get_composing(self.inner.as_raw()) }
321    }
322
323    /// Set the UTF-8 text generated by the key for the current keyboard layout.
324    ///
325    /// Must contain the unmodified character before any Ctrl/Meta transformations.
326    /// The encoder derives modifier sequences from the logical key and mods
327    /// bitmask, not from this text. Do not pass C0 control characters
328    /// (U+0000-U+001F, U+007F) or platform function key codes (e.g. macOS PUA
329    /// U+F700-U+F8FF); pass NULL instead and let the encoder use the logical key.
330    ///
331    /// The event makes an internal copy of the text since the C API
332    /// may reuse it without any rigid lifetime guarantees.
333    pub fn set_utf8<S: Into<String>>(&mut self, text: Option<S>) -> &mut Self {
334        self.text = text.map(Into::into);
335
336        match &self.text {
337            Some(text) => unsafe {
338                ffi::ghostty_key_event_set_utf8(
339                    self.inner.as_raw(),
340                    text.as_ptr().cast(),
341                    text.len(),
342                );
343            },
344            None => unsafe {
345                ffi::ghostty_key_event_set_utf8(self.inner.as_raw(), std::ptr::null(), 0);
346            },
347        }
348        self
349    }
350
351    /// Get the UTF-8 text generated by the key event.
352    pub fn utf8(&mut self) -> Option<&str> {
353        // We actually sidestep the `ghostty_key_event_get_utf8` method to
354        // avoid unclear lifetimes. See `set_utf8`.
355        self.text.as_deref()
356    }
357
358    /// Set the unshifted Unicode codepoint.
359    pub fn set_unshifted_codepoint(&mut self, codepoint: char) -> &mut Self {
360        unsafe {
361            ffi::ghostty_key_event_set_unshifted_codepoint(self.inner.as_raw(), codepoint.into());
362        }
363        self
364    }
365
366    /// Get the unshifted Unicode codepoint.
367    #[must_use]
368    pub fn unshifted_codepoint(&self) -> char {
369        unsafe {
370            char::from_u32_unchecked(ffi::ghostty_key_event_get_unshifted_codepoint(
371                self.inner.as_raw(),
372            ))
373        }
374    }
375}
376
377impl Drop for Event<'_> {
378    fn drop(&mut self) {
379        unsafe { ffi::ghostty_key_event_free(self.inner.as_raw()) }
380    }
381}
382
383#[repr(u32)]
384#[derive(Clone, Copy, Debug, PartialEq, Eq, int_enum::IntEnum)]
385#[non_exhaustive]
386#[expect(missing_docs, reason = "self-explanatory")]
387pub enum Key {
388    Unidentified = 0,
389    Backquote = 1,
390    Backslash = 2,
391    BracketLeft = 3,
392    BracketRight = 4,
393    Comma = 5,
394    Digit0 = 6,
395    Digit1 = 7,
396    Digit2 = 8,
397    Digit3 = 9,
398    Digit4 = 10,
399    Digit5 = 11,
400    Digit6 = 12,
401    Digit7 = 13,
402    Digit8 = 14,
403    Digit9 = 15,
404    Equal = 16,
405    IntlBackslash = 17,
406    IntlRo = 18,
407    IntlYen = 19,
408    A = 20,
409    B = 21,
410    C = 22,
411    D = 23,
412    E = 24,
413    F = 25,
414    G = 26,
415    H = 27,
416    I = 28,
417    J = 29,
418    K = 30,
419    L = 31,
420    M = 32,
421    N = 33,
422    O = 34,
423    P = 35,
424    Q = 36,
425    R = 37,
426    S = 38,
427    T = 39,
428    U = 40,
429    V = 41,
430    W = 42,
431    X = 43,
432    Y = 44,
433    Z = 45,
434    Minus = 46,
435    Period = 47,
436    Quote = 48,
437    Semicolon = 49,
438    Slash = 50,
439    AltLeft = 51,
440    AltRight = 52,
441    Backspace = 53,
442    CapsLock = 54,
443    ContextMenu = 55,
444    ControlLeft = 56,
445    ControlRight = 57,
446    Enter = 58,
447    MetaLeft = 59,
448    MetaRight = 60,
449    ShiftLeft = 61,
450    ShiftRight = 62,
451    Space = 63,
452    Tab = 64,
453    Convert = 65,
454    KanaMode = 66,
455    NonConvert = 67,
456    Delete = 68,
457    End = 69,
458    Help = 70,
459    Home = 71,
460    Insert = 72,
461    PageDown = 73,
462    PageUp = 74,
463    ArrowDown = 75,
464    ArrowLeft = 76,
465    ArrowRight = 77,
466    ArrowUp = 78,
467    NumLock = 79,
468    Numpad0 = 80,
469    Numpad1 = 81,
470    Numpad2 = 82,
471    Numpad3 = 83,
472    Numpad4 = 84,
473    Numpad5 = 85,
474    Numpad6 = 86,
475    Numpad7 = 87,
476    Numpad8 = 88,
477    Numpad9 = 89,
478    NumpadAdd = 90,
479    NumpadBackspace = 91,
480    NumpadClear = 92,
481    NumpadClearEntry = 93,
482    NumpadComma = 94,
483    NumpadDecimal = 95,
484    NumpadDivide = 96,
485    NumpadEnter = 97,
486    NumpadEqual = 98,
487    NumpadMemoryAdd = 99,
488    NumpadMemoryClear = 100,
489    NumpadMemoryRecall = 101,
490    NumpadMemoryStore = 102,
491    NumpadMemorySubtract = 103,
492    NumpadMultiply = 104,
493    NumpadParenLeft = 105,
494    NumpadParenRight = 106,
495    NumpadSubtract = 107,
496    NumpadSeparator = 108,
497    NumpadUp = 109,
498    NumpadDown = 110,
499    NumpadRight = 111,
500    NumpadLeft = 112,
501    NumpadBegin = 113,
502    NumpadHome = 114,
503    NumpadEnd = 115,
504    NumpadInsert = 116,
505    NumpadDelete = 117,
506    NumpadPageUp = 118,
507    NumpadPageDown = 119,
508    Escape = 120,
509    F1 = 121,
510    F2 = 122,
511    F3 = 123,
512    F4 = 124,
513    F5 = 125,
514    F6 = 126,
515    F7 = 127,
516    F8 = 128,
517    F9 = 129,
518    F10 = 130,
519    F11 = 131,
520    F12 = 132,
521    F13 = 133,
522    F14 = 134,
523    F15 = 135,
524    F16 = 136,
525    F17 = 137,
526    F18 = 138,
527    F19 = 139,
528    F20 = 140,
529    F21 = 141,
530    F22 = 142,
531    F23 = 143,
532    F24 = 144,
533    F25 = 145,
534    Fn = 146,
535    FnLock = 147,
536    PrintScreen = 148,
537    ScrollLock = 149,
538    Pause = 150,
539    BrowserBack = 151,
540    BrowserFavorites = 152,
541    BrowserForward = 153,
542    BrowserHome = 154,
543    BrowserRefresh = 155,
544    BrowserSearch = 156,
545    BrowserStop = 157,
546    Eject = 158,
547    LaunchApp1 = 159,
548    LaunchApp2 = 160,
549    LaunchMail = 161,
550    MediaPlayPause = 162,
551    MediaSelect = 163,
552    MediaStop = 164,
553    MediaTrackNext = 165,
554    MediaTrackPrevious = 166,
555    Power = 167,
556    Sleep = 168,
557    AudioVolumeDown = 169,
558    AudioVolumeMute = 170,
559    AudioVolumeUp = 171,
560    WakeUp = 172,
561    Copy = 173,
562    Cut = 174,
563    Paste = 175,
564}
565
566/// Key event action type.
567#[repr(u32)]
568#[derive(Clone, Copy, Debug, PartialEq, Eq, int_enum::IntEnum)]
569#[non_exhaustive]
570pub enum Action {
571    /// Key was pressed.
572    Press = ffi::KeyAction::PRESS,
573    /// Key was released.
574    Release = ffi::KeyAction::RELEASE,
575    /// Key is being repeated (held down).
576    Repeat = ffi::KeyAction::REPEAT,
577}
578
579/// macOS option key behavior.
580///
581/// Determines whether the "option" key on macOS is treated as "alt" or not.
582/// See the Ghostty `macos-option-as-alt` configuration option for more details.
583#[repr(u32)]
584#[derive(Clone, Copy, Debug, PartialEq, Eq, int_enum::IntEnum)]
585pub enum OptionAsAlt {
586    /// Option key is not treated as alt.
587    False = ffi::OptionAsAlt::FALSE,
588    /// Option key is treated as alt.
589    True = ffi::OptionAsAlt::TRUE,
590    /// Only left option key is treated as alt.
591    Left = ffi::OptionAsAlt::LEFT,
592    /// Only right option key is treated as alt.
593    Right = ffi::OptionAsAlt::RIGHT,
594}
595
596bitflags::bitflags! {
597    /// Keyboard modifier keys bitmask.
598    ///
599    /// A bitmask representing all keyboard modifiers. This tracks which modifier
600    /// keys are pressed and, where supported by the platform, which side (left or
601    /// right) of each modifier is active.
602    ///
603    /// Modifier side bits are only meaningful when the corresponding modifier bit
604    /// is set. Not all platforms support distinguishing between left and right
605    /// modifier keys and Ghostty is built to expect that some platforms may not
606    /// provide this information.
607    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
608    pub struct Mods: u16 {
609        /// Shift key is pressed.
610        const SHIFT = ffi::MODS_SHIFT;
611        /// Alt key is pressed.
612        const ALT = ffi::MODS_ALT;
613        /// Control key is pressed.
614        const CTRL = ffi::MODS_CTRL;
615        /// Super/Command/Windows key is pressed.
616        const SUPER = ffi::MODS_SUPER;
617        /// Caps Lock is active.
618        const CAPS_LOCK = ffi::MODS_CAPS_LOCK;
619        /// Num Lock is active.
620        const NUM_LOCK = ffi::MODS_NUM_LOCK;
621        /// Right Shift is pressed (unset = left, set = right).
622        ///
623        /// Only valid when [`Mods::SHIFT`] is set.
624        const SHIFT_SIDE = ffi::MODS_SHIFT_SIDE;
625        /// Right Alt is pressed (unset = left, set = right).
626        ///
627        /// Only valid when [`Mods::ALT`] is set.
628        const ALT_SIDE = ffi::MODS_ALT_SIDE;
629        /// Right Control is pressed (unset = left, set = right).
630        ///
631        /// Only valid when [`Mods::CTRL`] is set.
632        const CTRL_SIDE = ffi::MODS_CTRL_SIDE;
633        /// Right Super is pressed (unset = left, set = right).
634        ///
635        /// Only valid when [`Mods::SUPER`] is set.
636        const SUPER_SIDE = ffi::MODS_SUPER_SIDE;
637    }
638
639    /// Kitty keyboard protocol flags.
640    ///
641    /// Bitflags representing the various modes of the Kitty keyboard protocol.
642    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
643    pub struct KittyKeyFlags: u8 {
644        /// Kitty keyboard protocol disabled (all flags off).
645        const DISABLED = ffi::KITTY_KEY_DISABLED;
646        /// Disambiguate escape codes.
647        const DISAMBIGUATE = ffi::KITTY_KEY_DISAMBIGUATE;
648        /// Report key press and release events.
649        const REPORT_EVENTS = ffi::KITTY_KEY_REPORT_EVENTS;
650        /// Report alternate key codes.
651        const REPORT_ALTERNATES = ffi::KITTY_KEY_REPORT_ALTERNATES;
652        /// Report all key events including those normally handled by the terminal.
653        const REPORT_ALL = ffi::KITTY_KEY_REPORT_ALL;
654        /// Report associated text with key events
655        const REPORT_ASSOCIATED = ffi::KITTY_KEY_REPORT_ASSOCIATED;
656        /// All Kitty keyboard protocol flags enabled
657        const ALL = ffi::KITTY_KEY_ALL;
658    }
659}