mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-06 07:38:21 +00:00
example: add C mouse encoding example
Add a new c-vt-mouse-encode example that demonstrates how to use the mouse encoder C API. The example creates a mouse encoder configured with SGR format and normal tracking mode, sets up terminal geometry for pixel-to-cell coordinate mapping, and encodes a left button press event into a terminal escape sequence. Mirrors the structure of the existing c-vt-key-encode example. Also adds the corresponding @example doxygen reference in vt.h.
This commit is contained in:
23
example/c-vt-mouse-encode/README.md
Normal file
23
example/c-vt-mouse-encode/README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Example: `ghostty-vt` C Mouse Encoding
|
||||
|
||||
This example demonstrates how to use the `ghostty-vt` C library to encode mouse
|
||||
events into terminal escape sequences.
|
||||
|
||||
This example specifically shows how to:
|
||||
|
||||
1. Create a mouse encoder with the C API
|
||||
2. Configure tracking mode and output format (this example uses SGR)
|
||||
3. Set terminal geometry for pixel-to-cell coordinate mapping
|
||||
4. Create and configure a mouse event
|
||||
5. Encode the mouse event into a terminal escape sequence
|
||||
|
||||
The example encodes a left button press at pixel position (50, 40) using SGR
|
||||
format, producing an escape sequence like `\x1b[<0;6;3M`.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program:
|
||||
|
||||
```shell-session
|
||||
zig build run
|
||||
```
|
||||
42
example/c-vt-mouse-encode/build.zig
Normal file
42
example/c-vt-mouse-encode/build.zig
Normal file
@@ -0,0 +1,42 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_mod.addCSourceFiles(.{
|
||||
.root = b.path("src"),
|
||||
.files = &.{"main.c"},
|
||||
});
|
||||
|
||||
// You'll want to use a lazy dependency here so that ghostty is only
|
||||
// downloaded if you actually need it.
|
||||
if (b.lazyDependency("ghostty", .{
|
||||
// Setting simd to false will force a pure static build that
|
||||
// doesn't even require libc, but it has a significant performance
|
||||
// penalty. If your embedding app requires libc anyway, you should
|
||||
// always keep simd enabled.
|
||||
// .simd = false,
|
||||
})) |dep| {
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_mouse_encode",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Run
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| run_cmd.addArgs(args);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
24
example/c-vt-mouse-encode/build.zig.zon
Normal file
24
example/c-vt-mouse-encode/build.zig.zon
Normal file
@@ -0,0 +1,24 @@
|
||||
.{
|
||||
.name = .c_vt,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0x413a8529a6dd3c51,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.dependencies = .{
|
||||
// Ghostty dependency. In reality, you'd probably use a URL-based
|
||||
// dependency like the one showed (and commented out) below this one.
|
||||
// We use a path dependency here for simplicity and to ensure our
|
||||
// examples always test against the source they're bundled with.
|
||||
.ghostty = .{ .path = "../../" },
|
||||
|
||||
// Example of what a URL-based dependency looks like:
|
||||
// .ghostty = .{
|
||||
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
|
||||
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
|
||||
// },
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
78
example/c-vt-mouse-encode/src/main.c
Normal file
78
example/c-vt-mouse-encode/src/main.c
Normal file
@@ -0,0 +1,78 @@
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
int main() {
|
||||
GhosttyMouseEncoder encoder;
|
||||
GhosttyResult result = ghostty_mouse_encoder_new(NULL, &encoder);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Set tracking mode to normal (button press/release)
|
||||
ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_EVENT,
|
||||
&(GhosttyMouseTrackingMode){GHOSTTY_MOUSE_TRACKING_NORMAL});
|
||||
|
||||
// Set output format to SGR
|
||||
ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_FORMAT,
|
||||
&(GhosttyMouseFormat){GHOSTTY_MOUSE_FORMAT_SGR});
|
||||
|
||||
// Set terminal geometry so the encoder can map pixel positions to cells
|
||||
ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_SIZE,
|
||||
&(GhosttyMouseEncoderSize){
|
||||
.size = sizeof(GhosttyMouseEncoderSize),
|
||||
.screen_width = 800,
|
||||
.screen_height = 600,
|
||||
.cell_width = 10,
|
||||
.cell_height = 20,
|
||||
.padding_top = 0,
|
||||
.padding_bottom = 0,
|
||||
.padding_right = 0,
|
||||
.padding_left = 0,
|
||||
});
|
||||
|
||||
// Create mouse event: left button press at pixel position (50, 40)
|
||||
GhosttyMouseEvent event;
|
||||
result = ghostty_mouse_event_new(NULL, &event);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
ghostty_mouse_event_set_action(event, GHOSTTY_MOUSE_ACTION_PRESS);
|
||||
ghostty_mouse_event_set_button(event, GHOSTTY_MOUSE_BUTTON_LEFT);
|
||||
ghostty_mouse_event_set_position(event, (GhosttyMousePosition){.x = 50.0f, .y = 40.0f});
|
||||
printf("Encoding event: left button press at (50, 40) in SGR format\n");
|
||||
|
||||
// Optionally, encode with null buffer to get required size. You can
|
||||
// skip this step and provide a sufficiently large buffer directly.
|
||||
// If there isn't enough space, the function will return an out of memory
|
||||
// error.
|
||||
size_t required = 0;
|
||||
result = ghostty_mouse_encoder_encode(encoder, event, NULL, 0, &required);
|
||||
assert(result == GHOSTTY_OUT_OF_MEMORY);
|
||||
printf("Required buffer size: %zu bytes\n", required);
|
||||
|
||||
// Encode the mouse event. We don't use our required size above because
|
||||
// that was just an example; we know 128 bytes is enough.
|
||||
char buf[128];
|
||||
size_t written = 0;
|
||||
result = ghostty_mouse_encoder_encode(encoder, event, buf, sizeof(buf), &written);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
printf("Encoded %zu bytes\n", written);
|
||||
|
||||
// Print the encoded sequence (hex and string)
|
||||
printf("Hex: ");
|
||||
for (size_t i = 0; i < written; i++) printf("%02x ", (unsigned char)buf[i]);
|
||||
printf("\n");
|
||||
|
||||
printf("String: ");
|
||||
for (size_t i = 0; i < written; i++) {
|
||||
if (buf[i] == 0x1b) {
|
||||
printf("\\x1b");
|
||||
} else {
|
||||
printf("%c", buf[i]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
ghostty_mouse_event_free(event);
|
||||
ghostty_mouse_encoder_free(encoder);
|
||||
return 0;
|
||||
}
|
||||
@@ -43,6 +43,7 @@
|
||||
* Complete working examples:
|
||||
* - @ref c-vt/src/main.c - OSC parser example
|
||||
* - @ref c-vt-key-encode/src/main.c - Key encoding example
|
||||
* - @ref c-vt-mouse-encode/src/main.c - Mouse encoding example
|
||||
* - @ref c-vt-paste/src/main.c - Paste safety check example
|
||||
* - @ref c-vt-sgr/src/main.c - SGR parser example
|
||||
* - @ref c-vt-formatter/src/main.c - Terminal formatter example
|
||||
@@ -59,6 +60,11 @@
|
||||
* into terminal escape sequences using the Kitty keyboard protocol.
|
||||
*/
|
||||
|
||||
/** @example c-vt-mouse-encode/src/main.c
|
||||
* This example demonstrates how to use the mouse encoder to convert mouse events
|
||||
* into terminal escape sequences using the SGR mouse format.
|
||||
*/
|
||||
|
||||
/** @example c-vt-paste/src/main.c
|
||||
* This example demonstrates how to use the paste utilities to check if
|
||||
* paste data is safe before sending it to the terminal.
|
||||
|
||||
@@ -24,6 +24,90 @@
|
||||
* - Free the event with ghostty_mouse_event_free() or reuse it.
|
||||
* 4. Free the encoder with ghostty_mouse_encoder_free() when done.
|
||||
*
|
||||
* For a complete working example, see example/c-vt-mouse-encode in the
|
||||
* repository.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* @code{.c}
|
||||
* #include <assert.h>
|
||||
* #include <stdio.h>
|
||||
* #include <ghostty/vt.h>
|
||||
*
|
||||
* int main() {
|
||||
* // Create encoder
|
||||
* GhosttyMouseEncoder encoder;
|
||||
* GhosttyResult result = ghostty_mouse_encoder_new(NULL, &encoder);
|
||||
* assert(result == GHOSTTY_SUCCESS);
|
||||
*
|
||||
* // Configure SGR format with normal tracking
|
||||
* ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_EVENT,
|
||||
* &(GhosttyMouseTrackingMode){GHOSTTY_MOUSE_TRACKING_NORMAL});
|
||||
* ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_FORMAT,
|
||||
* &(GhosttyMouseFormat){GHOSTTY_MOUSE_FORMAT_SGR});
|
||||
*
|
||||
* // Set terminal geometry for coordinate mapping
|
||||
* ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_SIZE,
|
||||
* &(GhosttyMouseEncoderSize){
|
||||
* .size = sizeof(GhosttyMouseEncoderSize),
|
||||
* .screen_width = 800, .screen_height = 600,
|
||||
* .cell_width = 10, .cell_height = 20,
|
||||
* });
|
||||
*
|
||||
* // Create and configure a left button press event
|
||||
* GhosttyMouseEvent event;
|
||||
* result = ghostty_mouse_event_new(NULL, &event);
|
||||
* assert(result == GHOSTTY_SUCCESS);
|
||||
* ghostty_mouse_event_set_action(event, GHOSTTY_MOUSE_ACTION_PRESS);
|
||||
* ghostty_mouse_event_set_button(event, GHOSTTY_MOUSE_BUTTON_LEFT);
|
||||
* ghostty_mouse_event_set_position(event,
|
||||
* (GhosttyMousePosition){.x = 50.0f, .y = 40.0f});
|
||||
*
|
||||
* // Encode the mouse event
|
||||
* char buf[128];
|
||||
* size_t written = 0;
|
||||
* result = ghostty_mouse_encoder_encode(encoder, event,
|
||||
* buf, sizeof(buf), &written);
|
||||
* assert(result == GHOSTTY_SUCCESS);
|
||||
*
|
||||
* // Use the encoded sequence (e.g., write to terminal)
|
||||
* fwrite(buf, 1, written, stdout);
|
||||
*
|
||||
* // Cleanup
|
||||
* ghostty_mouse_event_free(event);
|
||||
* ghostty_mouse_encoder_free(encoder);
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* ## Example: Encoding with Terminal State
|
||||
*
|
||||
* When you have a GhosttyTerminal, you can sync its tracking mode and
|
||||
* output format into the encoder automatically:
|
||||
*
|
||||
* @code{.c}
|
||||
* // Create a terminal and feed it some VT data that enables mouse tracking
|
||||
* GhosttyTerminal terminal;
|
||||
* ghostty_terminal_new(NULL, &terminal,
|
||||
* (GhosttyTerminalOptions){.cols = 80, .rows = 24, .max_scrollback = 0});
|
||||
*
|
||||
* // Application might write data that enables mouse reporting, etc.
|
||||
* ghostty_terminal_vt_write(terminal, vt_data, vt_len);
|
||||
*
|
||||
* // Create an encoder and sync its options from the terminal
|
||||
* GhosttyMouseEncoder encoder;
|
||||
* ghostty_mouse_encoder_new(NULL, &encoder);
|
||||
* ghostty_mouse_encoder_setopt_from_terminal(encoder, terminal);
|
||||
*
|
||||
* // Encode a mouse event using the terminal-derived options
|
||||
* char buf[128];
|
||||
* size_t written = 0;
|
||||
* ghostty_mouse_encoder_encode(encoder, event, buf, sizeof(buf), &written);
|
||||
*
|
||||
* ghostty_mouse_encoder_free(encoder);
|
||||
* ghostty_terminal_free(terminal);
|
||||
* @endcode
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user