vt: expose focus encoding in C and Zig APIs

Add focus event encoding (CSI I / CSI O) to the libghostty-vt public
API, following the same patterns as key and mouse encoding.

The focus Event enum uses lib.Enum for C ABI compatibility. The C API
provides ghostty_focus_encode() which writes into a caller-provided
buffer and returns GHOSTTY_OUT_OF_SPACE with the required size when
the buffer is too small.

Also update key and mouse encoders to return GHOSTTY_OUT_OF_SPACE
instead of GHOSTTY_OUT_OF_MEMORY for buffer-too-small errors,
reserving OUT_OF_MEMORY for actual allocation failures. Update all
corresponding header documentation.
This commit is contained in:
Mitchell Hashimoto
2026-03-16 14:23:15 -07:00
parent c1326c57f9
commit bed9d92f04
12 changed files with 226 additions and 16 deletions

View File

@@ -30,14 +30,17 @@
* The API is organized into the following groups:
* - @ref terminal "Terminal" - Complete terminal emulator state and rendering
* - @ref formatter "Formatter" - Format terminal content as plain text, VT sequences, or HTML
* - @ref key "Key Encoding" - Encode key events into terminal sequences
* - @ref mouse "Mouse Encoding" - Encode mouse events into terminal sequences
* - @ref osc "OSC Parser" - Parse OSC (Operating System Command) sequences
* - @ref sgr "SGR Parser" - Parse SGR (Select Graphic Rendition) sequences
* - @ref paste "Paste Utilities" - Validate paste data safety
* - @ref allocator "Memory Management" - Memory management and custom allocators
* - @ref wasm "WebAssembly Utilities" - WebAssembly convenience functions
*
* Encoding related APIs:
* - @ref focus "Focus Encoding" - Encode focus in/out events into terminal sequences
* - @ref key "Key Encoding" - Encode key events into terminal sequences
* - @ref mouse "Mouse Encoding" - Encode mouse events into terminal sequences
*
* @section examples_sec Examples
*
* Complete working examples:
@@ -90,6 +93,7 @@ extern "C" {
#include <ghostty/vt/types.h>
#include <ghostty/vt/allocator.h>
#include <ghostty/vt/focus.h>
#include <ghostty/vt/formatter.h>
#include <ghostty/vt/terminal.h>
#include <ghostty/vt/osc.h>

View File

@@ -0,0 +1,94 @@
/**
* @file focus.h
*
* Focus encoding - encode focus in/out events into terminal escape sequences.
*/
#ifndef GHOSTTY_VT_FOCUS_H
#define GHOSTTY_VT_FOCUS_H
/** @defgroup focus Focus Encoding
*
* Utilities for encoding focus gained/lost events into terminal escape
* sequences (CSI I / CSI O) for focus reporting mode (mode 1004).
*
* ## Basic Usage
*
* Use ghostty_focus_encode() to encode a focus event into a caller-provided
* buffer. If the buffer is too small, the function returns
* GHOSTTY_OUT_OF_SPACE and sets the required size in the output parameter.
*
* ## Example
*
* @code{.c}
* #include <stdio.h>
* #include <ghostty/vt.h>
*
* int main() {
* char buf[8];
* size_t written = 0;
*
* GhosttyResult result = ghostty_focus_encode(
* GHOSTTY_FOCUS_GAINED, buf, sizeof(buf), &written);
*
* if (result == GHOSTTY_SUCCESS) {
* printf("Encoded %zu bytes: ", written);
* fwrite(buf, 1, written, stdout);
* printf("\n");
* }
*
* return 0;
* }
* @endcode
*
* @{
*/
#include <stddef.h>
#include <ghostty/vt/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Focus event types for focus reporting mode (mode 1004).
*/
typedef enum {
/** Terminal window gained focus */
GHOSTTY_FOCUS_GAINED = 0,
/** Terminal window lost focus */
GHOSTTY_FOCUS_LOST = 1,
} GhosttyFocusEvent;
/**
* Encode a focus event into a terminal escape sequence.
*
* Encodes a focus gained (CSI I) or focus lost (CSI O) report into the
* provided buffer.
*
* If the buffer is too small, the function returns GHOSTTY_OUT_OF_SPACE
* and writes the required buffer size to @p out_written. The caller can
* then retry with a sufficiently sized buffer.
*
* @param event The focus event to encode
* @param buf Output buffer to write the encoded sequence into (may be NULL)
* @param buf_len Size of the output buffer in bytes
* @param[out] out_written On success, the number of bytes written. On
* GHOSTTY_OUT_OF_SPACE, the required buffer size.
* @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_SPACE if the buffer
* is too small
*/
GhosttyResult ghostty_focus_encode(
GhosttyFocusEvent event,
char* buf,
size_t buf_len,
size_t* out_written);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* GHOSTTY_VT_FOCUS_H */

View File

@@ -185,7 +185,7 @@ void ghostty_key_encoder_setopt_from_terminal(GhosttyKeyEncoder encoder, Ghostty
* typically don't generate escape sequences. Check the out_len parameter to
* determine if any data was written.
*
* If the output buffer is too small, this function returns GHOSTTY_OUT_OF_MEMORY
* If the output buffer is too small, this function returns GHOSTTY_OUT_OF_SPACE
* and out_len will contain the required buffer size. The caller can then
* allocate a larger buffer and call the function again.
*
@@ -194,15 +194,15 @@ void ghostty_key_encoder_setopt_from_terminal(GhosttyKeyEncoder encoder, Ghostty
* @param out_buf Buffer to write the encoded sequence to
* @param out_buf_size Size of the output buffer in bytes
* @param out_len Pointer to store the number of bytes written (may be NULL)
* @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_MEMORY if buffer too small, or other error code
* @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_SPACE if buffer too small, or other error code
*
* ## Example: Calculate required buffer size
*
* @code{.c}
* // Query the required size with a NULL buffer (always returns OUT_OF_MEMORY)
* // Query the required size with a NULL buffer (always returns OUT_OF_SPACE)
* size_t required = 0;
* GhosttyResult result = ghostty_key_encoder_encode(encoder, event, NULL, 0, &required);
* assert(result == GHOSTTY_OUT_OF_MEMORY);
* assert(result == GHOSTTY_OUT_OF_SPACE);
*
* // Allocate buffer of required size
* char *buf = malloc(required);
@@ -228,7 +228,7 @@ void ghostty_key_encoder_setopt_from_terminal(GhosttyKeyEncoder encoder, Ghostty
* if (result == GHOSTTY_SUCCESS) {
* // Write the encoded sequence to the terminal
* write(pty_fd, buf, written);
* } else if (result == GHOSTTY_OUT_OF_MEMORY) {
* } else if (result == GHOSTTY_OUT_OF_SPACE) {
* // Buffer too small, written contains required size
* char *dynamic_buf = malloc(written);
* result = ghostty_key_encoder_encode(encoder, event, dynamic_buf, written, &written);

View File

@@ -189,7 +189,7 @@ void ghostty_mouse_encoder_reset(GhosttyMouseEncoder encoder);
* Not all mouse events produce output. In such cases this returns
* GHOSTTY_SUCCESS with out_len set to 0.
*
* If the output buffer is too small, this returns GHOSTTY_OUT_OF_MEMORY
* If the output buffer is too small, this returns GHOSTTY_OUT_OF_SPACE
* and out_len contains the required size.
*
* @param encoder The encoder handle, must not be NULL
@@ -197,7 +197,7 @@ void ghostty_mouse_encoder_reset(GhosttyMouseEncoder encoder);
* @param out_buf Buffer to write encoded bytes to, or NULL to query required size
* @param out_buf_size Size of out_buf in bytes
* @param out_len Pointer to store bytes written (or required bytes on failure)
* @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_MEMORY if buffer is too small,
* @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_SPACE if buffer is too small,
* or another error code
*
* @ingroup mouse