1/**
2 * @file event.h
3 *
4 * Key event representation and manipulation.
5 */
6
7#ifndef GHOSTTY_VT_KEY_EVENT_H
8#define GHOSTTY_VT_KEY_EVENT_H
9
10#include <stdbool.h>
11#include <stddef.h>
12#include <stdint.h>
13#include <ghostty/vt/types.h>
14#include <ghostty/vt/allocator.h>
15
16/**
17 * Opaque handle to a key event.
18 *
19 * This handle represents a keyboard input event containing information about
20 * the physical key pressed, modifiers, and generated text.
21 *
22 * @ingroup key
23 */
24typedef struct GhosttyKeyEventImpl *GhosttyKeyEvent;
25
26/**
27 * Keyboard input event types.
28 *
29 * @ingroup key
30 */
31typedef enum GHOSTTY_ENUM_TYPED {
32 /** Key was released */
33 GHOSTTY_KEY_ACTION_RELEASE = 0,
34 /** Key was pressed */
35 GHOSTTY_KEY_ACTION_PRESS = 1,
36 /** Key is being repeated (held down) */
37 GHOSTTY_KEY_ACTION_REPEAT = 2,
38 GHOSTTY_KEY_ACTION_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
39} GhosttyKeyAction;
40
41/**
42 * Keyboard modifier keys bitmask.
43 *
44 * A bitmask representing all keyboard modifiers. This tracks which modifier keys
45 * are pressed and, where supported by the platform, which side (left or right)
46 * of each modifier is active.
47 *
48 * Use the GHOSTTY_MODS_* constants to test and set individual modifiers.
49 *
50 * Modifier side bits are only meaningful when the corresponding modifier bit is set.
51 * Not all platforms support distinguishing between left and right modifier
52 * keys and Ghostty is built to expect that some platforms may not provide this
53 * information.
54 *
55 * @ingroup key
56 */
57typedef uint16_t GhosttyMods;
58
59/** Shift key is pressed */
60#define GHOSTTY_MODS_SHIFT (1 << 0)
61/** Control key is pressed */
62#define GHOSTTY_MODS_CTRL (1 << 1)
63/** Alt/Option key is pressed */
64#define GHOSTTY_MODS_ALT (1 << 2)
65/** Super/Command/Windows key is pressed */
66#define GHOSTTY_MODS_SUPER (1 << 3)
67/** Caps Lock is active */
68#define GHOSTTY_MODS_CAPS_LOCK (1 << 4)
69/** Num Lock is active */
70#define GHOSTTY_MODS_NUM_LOCK (1 << 5)
71
72/**
73 * Right shift is pressed (0 = left, 1 = right).
74 * Only meaningful when GHOSTTY_MODS_SHIFT is set.
75 */
76#define GHOSTTY_MODS_SHIFT_SIDE (1 << 6)
77/**
78 * Right ctrl is pressed (0 = left, 1 = right).
79 * Only meaningful when GHOSTTY_MODS_CTRL is set.
80 */
81#define GHOSTTY_MODS_CTRL_SIDE (1 << 7)
82/**
83 * Right alt is pressed (0 = left, 1 = right).
84 * Only meaningful when GHOSTTY_MODS_ALT is set.
85 */
86#define GHOSTTY_MODS_ALT_SIDE (1 << 8)
87/**
88 * Right super is pressed (0 = left, 1 = right).
89 * Only meaningful when GHOSTTY_MODS_SUPER is set.
90 */
91#define GHOSTTY_MODS_SUPER_SIDE (1 << 9)
92
93/**
94 * Physical key codes.
95 *
96 * The set of key codes that Ghostty is aware of. These represent physical keys
97 * on the keyboard and are layout-independent. For example, the "a" key on a US
98 * keyboard is the same as the "ф" key on a Russian keyboard, but both will
99 * report the same key_a value.
100 *
101 * Layout-dependent strings are provided separately as UTF-8 text and are produced
102 * by the platform. These values are based on the W3C UI Events KeyboardEvent code
103 * standard. See: https://www.w3.org/TR/uievents-code
104 *
105 * @ingroup key
106 */
107typedef enum GHOSTTY_ENUM_TYPED {
108 GHOSTTY_KEY_UNIDENTIFIED = 0,
109
110 // Writing System Keys (W3C § 3.1.1)
111 GHOSTTY_KEY_BACKQUOTE,
112 GHOSTTY_KEY_BACKSLASH,
113 GHOSTTY_KEY_BRACKET_LEFT,
114 GHOSTTY_KEY_BRACKET_RIGHT,
115 GHOSTTY_KEY_COMMA,
116 GHOSTTY_KEY_DIGIT_0,
117 GHOSTTY_KEY_DIGIT_1,
118 GHOSTTY_KEY_DIGIT_2,
119 GHOSTTY_KEY_DIGIT_3,
120 GHOSTTY_KEY_DIGIT_4,
121 GHOSTTY_KEY_DIGIT_5,
122 GHOSTTY_KEY_DIGIT_6,
123 GHOSTTY_KEY_DIGIT_7,
124 GHOSTTY_KEY_DIGIT_8,
125 GHOSTTY_KEY_DIGIT_9,
126 GHOSTTY_KEY_EQUAL,
127 GHOSTTY_KEY_INTL_BACKSLASH,
128 GHOSTTY_KEY_INTL_RO,
129 GHOSTTY_KEY_INTL_YEN,
130 GHOSTTY_KEY_A,
131 GHOSTTY_KEY_B,
132 GHOSTTY_KEY_C,
133 GHOSTTY_KEY_D,
134 GHOSTTY_KEY_E,
135 GHOSTTY_KEY_F,
136 GHOSTTY_KEY_G,
137 GHOSTTY_KEY_H,
138 GHOSTTY_KEY_I,
139 GHOSTTY_KEY_J,
140 GHOSTTY_KEY_K,
141 GHOSTTY_KEY_L,
142 GHOSTTY_KEY_M,
143 GHOSTTY_KEY_N,
144 GHOSTTY_KEY_O,
145 GHOSTTY_KEY_P,
146 GHOSTTY_KEY_Q,
147 GHOSTTY_KEY_R,
148 GHOSTTY_KEY_S,
149 GHOSTTY_KEY_T,
150 GHOSTTY_KEY_U,
151 GHOSTTY_KEY_V,
152 GHOSTTY_KEY_W,
153 GHOSTTY_KEY_X,
154 GHOSTTY_KEY_Y,
155 GHOSTTY_KEY_Z,
156 GHOSTTY_KEY_MINUS,
157 GHOSTTY_KEY_PERIOD,
158 GHOSTTY_KEY_QUOTE,
159 GHOSTTY_KEY_SEMICOLON,
160 GHOSTTY_KEY_SLASH,
161
162 // Functional Keys (W3C § 3.1.2)
163 GHOSTTY_KEY_ALT_LEFT,
164 GHOSTTY_KEY_ALT_RIGHT,
165 GHOSTTY_KEY_BACKSPACE,
166 GHOSTTY_KEY_CAPS_LOCK,
167 GHOSTTY_KEY_CONTEXT_MENU,
168 GHOSTTY_KEY_CONTROL_LEFT,
169 GHOSTTY_KEY_CONTROL_RIGHT,
170 GHOSTTY_KEY_ENTER,
171 GHOSTTY_KEY_META_LEFT,
172 GHOSTTY_KEY_META_RIGHT,
173 GHOSTTY_KEY_SHIFT_LEFT,
174 GHOSTTY_KEY_SHIFT_RIGHT,
175 GHOSTTY_KEY_SPACE,
176 GHOSTTY_KEY_TAB,
177 GHOSTTY_KEY_CONVERT,
178 GHOSTTY_KEY_KANA_MODE,
179 GHOSTTY_KEY_NON_CONVERT,
180
181 // Control Pad Section (W3C § 3.2)
182 GHOSTTY_KEY_DELETE,
183 GHOSTTY_KEY_END,
184 GHOSTTY_KEY_HELP,
185 GHOSTTY_KEY_HOME,
186 GHOSTTY_KEY_INSERT,
187 GHOSTTY_KEY_PAGE_DOWN,
188 GHOSTTY_KEY_PAGE_UP,
189
190 // Arrow Pad Section (W3C § 3.3)
191 GHOSTTY_KEY_ARROW_DOWN,
192 GHOSTTY_KEY_ARROW_LEFT,
193 GHOSTTY_KEY_ARROW_RIGHT,
194 GHOSTTY_KEY_ARROW_UP,
195
196 // Numpad Section (W3C § 3.4)
197 GHOSTTY_KEY_NUM_LOCK,
198 GHOSTTY_KEY_NUMPAD_0,
199 GHOSTTY_KEY_NUMPAD_1,
200 GHOSTTY_KEY_NUMPAD_2,
201 GHOSTTY_KEY_NUMPAD_3,
202 GHOSTTY_KEY_NUMPAD_4,
203 GHOSTTY_KEY_NUMPAD_5,
204 GHOSTTY_KEY_NUMPAD_6,
205 GHOSTTY_KEY_NUMPAD_7,
206 GHOSTTY_KEY_NUMPAD_8,
207 GHOSTTY_KEY_NUMPAD_9,
208 GHOSTTY_KEY_NUMPAD_ADD,
209 GHOSTTY_KEY_NUMPAD_BACKSPACE,
210 GHOSTTY_KEY_NUMPAD_CLEAR,
211 GHOSTTY_KEY_NUMPAD_CLEAR_ENTRY,
212 GHOSTTY_KEY_NUMPAD_COMMA,
213 GHOSTTY_KEY_NUMPAD_DECIMAL,
214 GHOSTTY_KEY_NUMPAD_DIVIDE,
215 GHOSTTY_KEY_NUMPAD_ENTER,
216 GHOSTTY_KEY_NUMPAD_EQUAL,
217 GHOSTTY_KEY_NUMPAD_MEMORY_ADD,
218 GHOSTTY_KEY_NUMPAD_MEMORY_CLEAR,
219 GHOSTTY_KEY_NUMPAD_MEMORY_RECALL,
220 GHOSTTY_KEY_NUMPAD_MEMORY_STORE,
221 GHOSTTY_KEY_NUMPAD_MEMORY_SUBTRACT,
222 GHOSTTY_KEY_NUMPAD_MULTIPLY,
223 GHOSTTY_KEY_NUMPAD_PAREN_LEFT,
224 GHOSTTY_KEY_NUMPAD_PAREN_RIGHT,
225 GHOSTTY_KEY_NUMPAD_SUBTRACT,
226 GHOSTTY_KEY_NUMPAD_SEPARATOR,
227 GHOSTTY_KEY_NUMPAD_UP,
228 GHOSTTY_KEY_NUMPAD_DOWN,
229 GHOSTTY_KEY_NUMPAD_RIGHT,
230 GHOSTTY_KEY_NUMPAD_LEFT,
231 GHOSTTY_KEY_NUMPAD_BEGIN,
232 GHOSTTY_KEY_NUMPAD_HOME,
233 GHOSTTY_KEY_NUMPAD_END,
234 GHOSTTY_KEY_NUMPAD_INSERT,
235 GHOSTTY_KEY_NUMPAD_DELETE,
236 GHOSTTY_KEY_NUMPAD_PAGE_UP,
237 GHOSTTY_KEY_NUMPAD_PAGE_DOWN,
238
239 // Function Section (W3C § 3.5)
240 GHOSTTY_KEY_ESCAPE,
241 GHOSTTY_KEY_F1,
242 GHOSTTY_KEY_F2,
243 GHOSTTY_KEY_F3,
244 GHOSTTY_KEY_F4,
245 GHOSTTY_KEY_F5,
246 GHOSTTY_KEY_F6,
247 GHOSTTY_KEY_F7,
248 GHOSTTY_KEY_F8,
249 GHOSTTY_KEY_F9,
250 GHOSTTY_KEY_F10,
251 GHOSTTY_KEY_F11,
252 GHOSTTY_KEY_F12,
253 GHOSTTY_KEY_F13,
254 GHOSTTY_KEY_F14,
255 GHOSTTY_KEY_F15,
256 GHOSTTY_KEY_F16,
257 GHOSTTY_KEY_F17,
258 GHOSTTY_KEY_F18,
259 GHOSTTY_KEY_F19,
260 GHOSTTY_KEY_F20,
261 GHOSTTY_KEY_F21,
262 GHOSTTY_KEY_F22,
263 GHOSTTY_KEY_F23,
264 GHOSTTY_KEY_F24,
265 GHOSTTY_KEY_F25,
266 GHOSTTY_KEY_FN,
267 GHOSTTY_KEY_FN_LOCK,
268 GHOSTTY_KEY_PRINT_SCREEN,
269 GHOSTTY_KEY_SCROLL_LOCK,
270 GHOSTTY_KEY_PAUSE,
271
272 // Media Keys (W3C § 3.6)
273 GHOSTTY_KEY_BROWSER_BACK,
274 GHOSTTY_KEY_BROWSER_FAVORITES,
275 GHOSTTY_KEY_BROWSER_FORWARD,
276 GHOSTTY_KEY_BROWSER_HOME,
277 GHOSTTY_KEY_BROWSER_REFRESH,
278 GHOSTTY_KEY_BROWSER_SEARCH,
279 GHOSTTY_KEY_BROWSER_STOP,
280 GHOSTTY_KEY_EJECT,
281 GHOSTTY_KEY_LAUNCH_APP_1,
282 GHOSTTY_KEY_LAUNCH_APP_2,
283 GHOSTTY_KEY_LAUNCH_MAIL,
284 GHOSTTY_KEY_MEDIA_PLAY_PAUSE,
285 GHOSTTY_KEY_MEDIA_SELECT,
286 GHOSTTY_KEY_MEDIA_STOP,
287 GHOSTTY_KEY_MEDIA_TRACK_NEXT,
288 GHOSTTY_KEY_MEDIA_TRACK_PREVIOUS,
289 GHOSTTY_KEY_POWER,
290 GHOSTTY_KEY_SLEEP,
291 GHOSTTY_KEY_AUDIO_VOLUME_DOWN,
292 GHOSTTY_KEY_AUDIO_VOLUME_MUTE,
293 GHOSTTY_KEY_AUDIO_VOLUME_UP,
294 GHOSTTY_KEY_WAKE_UP,
295
296 // Legacy, Non-standard, and Special Keys (W3C § 3.7)
297 GHOSTTY_KEY_COPY,
298 GHOSTTY_KEY_CUT,
299 GHOSTTY_KEY_PASTE,
300 GHOSTTY_KEY_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
301} GhosttyKey;
302
303/**
304 * Create a new key event instance.
305 *
306 * Creates a new key event with default values. The event must be freed using
307 * ghostty_key_event_free() when no longer needed.
308 *
309 * @param allocator Pointer to the allocator to use for memory management, or NULL to use the default allocator
310 * @param event Pointer to store the created key event handle
311 * @return GHOSTTY_SUCCESS on success, or an error code on failure
312 *
313 * @ingroup key
314 */
315GHOSTTY_API GhosttyResult ghostty_key_event_new(const GhosttyAllocator *allocator, GhosttyKeyEvent *event);
316
317/**
318 * Free a key event instance.
319 *
320 * Releases all resources associated with the key event. After this call,
321 * the event handle becomes invalid and must not be used.
322 *
323 * @param event The key event handle to free (may be NULL)
324 *
325 * @ingroup key
326 */
327GHOSTTY_API void ghostty_key_event_free(GhosttyKeyEvent event);
328
329/**
330 * Set the key action (press, release, repeat).
331 *
332 * @param event The key event handle, must not be NULL
333 * @param action The action to set
334 *
335 * @ingroup key
336 */
337GHOSTTY_API void ghostty_key_event_set_action(GhosttyKeyEvent event, GhosttyKeyAction action);
338
339/**
340 * Get the key action (press, release, repeat).
341 *
342 * @param event The key event handle, must not be NULL
343 * @return The key action
344 *
345 * @ingroup key
346 */
347GHOSTTY_API GhosttyKeyAction ghostty_key_event_get_action(GhosttyKeyEvent event);
348
349/**
350 * Set the physical key code.
351 *
352 * @param event The key event handle, must not be NULL
353 * @param key The physical key code to set
354 *
355 * @ingroup key
356 */
357GHOSTTY_API void ghostty_key_event_set_key(GhosttyKeyEvent event, GhosttyKey key);
358
359/**
360 * Get the physical key code.
361 *
362 * @param event The key event handle, must not be NULL
363 * @return The physical key code
364 *
365 * @ingroup key
366 */
367GHOSTTY_API GhosttyKey ghostty_key_event_get_key(GhosttyKeyEvent event);
368
369/**
370 * Set the modifier keys bitmask.
371 *
372 * @param event The key event handle, must not be NULL
373 * @param mods The modifier keys bitmask to set
374 *
375 * @ingroup key
376 */
377GHOSTTY_API void ghostty_key_event_set_mods(GhosttyKeyEvent event, GhosttyMods mods);
378
379/**
380 * Get the modifier keys bitmask.
381 *
382 * @param event The key event handle, must not be NULL
383 * @return The modifier keys bitmask
384 *
385 * @ingroup key
386 */
387GHOSTTY_API GhosttyMods ghostty_key_event_get_mods(GhosttyKeyEvent event);
388
389/**
390 * Set the consumed modifiers bitmask.
391 *
392 * @param event The key event handle, must not be NULL
393 * @param consumed_mods The consumed modifiers bitmask to set
394 *
395 * @ingroup key
396 */
397GHOSTTY_API void ghostty_key_event_set_consumed_mods(GhosttyKeyEvent event, GhosttyMods consumed_mods);
398
399/**
400 * Get the consumed modifiers bitmask.
401 *
402 * @param event The key event handle, must not be NULL
403 * @return The consumed modifiers bitmask
404 *
405 * @ingroup key
406 */
407GHOSTTY_API GhosttyMods ghostty_key_event_get_consumed_mods(GhosttyKeyEvent event);
408
409/**
410 * Set whether the key event is part of a composition sequence.
411 *
412 * @param event The key event handle, must not be NULL
413 * @param composing Whether the key event is part of a composition sequence
414 *
415 * @ingroup key
416 */
417GHOSTTY_API void ghostty_key_event_set_composing(GhosttyKeyEvent event, bool composing);
418
419/**
420 * Get whether the key event is part of a composition sequence.
421 *
422 * @param event The key event handle, must not be NULL
423 * @return Whether the key event is part of a composition sequence
424 *
425 * @ingroup key
426 */
427GHOSTTY_API bool ghostty_key_event_get_composing(GhosttyKeyEvent event);
428
429/**
430 * Set the UTF-8 text generated by the key for the current keyboard layout.
431 *
432 * Must contain the unmodified character before any Ctrl/Meta transformations.
433 * The encoder derives modifier sequences from the logical key and mods
434 * bitmask, not from this text. Do not pass C0 control characters
435 * (U+0000-U+001F, U+007F) or platform function key codes (e.g. macOS PUA
436 * U+F700-U+F8FF); pass NULL instead and let the encoder use the logical key.
437 *
438 * The key event does NOT take ownership of the text pointer. The caller
439 * must ensure the string remains valid for the lifetime needed by the event.
440 *
441 * @param event The key event handle, must not be NULL
442 * @param utf8 The UTF-8 text to set (or NULL for empty)
443 * @param len Length of the UTF-8 text in bytes
444 *
445 * @ingroup key
446 */
447GHOSTTY_API void ghostty_key_event_set_utf8(GhosttyKeyEvent event, const char *utf8, size_t len);
448
449/**
450 * Get the UTF-8 text generated by the key event.
451 *
452 * The returned pointer is valid until the event is freed or the UTF-8 text is modified.
453 *
454 * @param event The key event handle, must not be NULL
455 * @param len Pointer to store the length of the UTF-8 text in bytes (may be NULL)
456 * @return The UTF-8 text (or NULL for empty)
457 *
458 * @ingroup key
459 */
460GHOSTTY_API const char *ghostty_key_event_get_utf8(GhosttyKeyEvent event, size_t *len);
461
462/**
463 * Set the unshifted Unicode codepoint.
464 *
465 * @param event The key event handle, must not be NULL
466 * @param codepoint The unshifted Unicode codepoint to set
467 *
468 * @ingroup key
469 */
470GHOSTTY_API void ghostty_key_event_set_unshifted_codepoint(GhosttyKeyEvent event, uint32_t codepoint);
471
472/**
473 * Get the unshifted Unicode codepoint.
474 *
475 * @param event The key event handle, must not be NULL
476 * @return The unshifted Unicode codepoint
477 *
478 * @ingroup key
479 */
480GHOSTTY_API uint32_t ghostty_key_event_get_unshifted_codepoint(GhosttyKeyEvent event);
481
482#endif /* GHOSTTY_VT_KEY_EVENT_H */