vtgl

terminal emulator implemented in OpenGL
git clone anongit@rnpnr.xyz:vtgl.git
Log | Files | Refs | Feed | LICENSE

Commit: 7b84d363f59f92a8c04278366957a77dc90d03e2
Parent: fb2a386b925dd7b30837831039ae6742e8e7c88a
Author: Randy Palamar
Date:   Thu,  7 Nov 2024 22:04:22 -0700

move window title setting out of the terminal

Diffstat:
Mplatform_linux_x11.c | 30++++++++++++++++++++++++------
Mterminal.c | 25++++++-------------------
Mtest.c | 3---
Mutil.c | 10----------
Mutil.h | 6++++--
Mvtgl.c | 3+++
Mvtgl.h | 16++++++++++------
7 files changed, 47 insertions(+), 46 deletions(-)

diff --git a/platform_linux_x11.c b/platform_linux_x11.c @@ -88,6 +88,8 @@ do_debug(TerminalMemory *t, Stream *err) #endif /* _DEBUG */ +static GLFWwindow *g_window; + static void button_action(ButtonState *button, b32 pressed) { @@ -326,14 +328,12 @@ update_input(GLFWwindow *win, TerminalInput *input, posix_platform_process child input->data_available = os_child_data_available(child.handle); } -static PLATFORM_GET_CLIPBOARD_FN(x11_get_clipboard) +static PLATFORM_CLIPBOARD_FN(x11_get_clipboard) { /* NOTE: this does a bunch of extra copying and other garbage. both GLFW and X11 are * at fault. The API is designed to do what the terminal wants and not be constrained * by GLFW and X11 garbage */ - b32 result = 0; ASSERT(buffer); - char *text = 0; switch (clipboard) { case CLIPBOARD_0: text = (c8 *)glfwGetClipboardString(0); break; @@ -342,13 +342,12 @@ static PLATFORM_GET_CLIPBOARD_FN(x11_get_clipboard) if (text) { /* TODO: we may need to replace '\n' with '\r\n' */ stream_push_s8(buffer, c_str_to_s8(text)); - result = !buffer->errors; } - return result; + return !buffer->errors; } -static PLATFORM_SET_CLIPBOARD_FN(x11_set_clipboard) +static PLATFORM_CLIPBOARD_FN(x11_set_clipboard) { ASSERT(buffer); stream_push_byte(buffer, 0); @@ -359,6 +358,22 @@ static PLATFORM_SET_CLIPBOARD_FN(x11_set_clipboard) case CLIPBOARD_1: glfwSetX11SelectionString((c8 *)buffer->buf); break; } } + return !buffer->errors; +} + +static PLATFORM_WINDOW_TITLE_FN(x11_get_window_title) +{ + ASSERT(buffer); + char *title = (c8 *)glfwGetWindowTitle(g_window); + if (title) stream_push_s8(buffer, c_str_to_s8(title)); +} + +static PLATFORM_WINDOW_TITLE_FN(x11_set_window_title) +{ + ASSERT(buffer); + stream_push_byte(buffer, 0); + if (!buffer->errors) + glfwSetWindowTitle(g_window, (c8 *)buffer->buf); } static void @@ -393,6 +408,8 @@ main(i32 argc, char *argv[], char *envp[]) term_memory.platform_api.allocate_ring_buffer = posix_allocate_ring_buffer; term_memory.platform_api.get_clipboard = x11_get_clipboard; term_memory.platform_api.set_clipboard = x11_set_clipboard; + term_memory.platform_api.get_window_title = x11_get_window_title; + term_memory.platform_api.set_window_title = x11_set_window_title; Arena platform_arena = os_new_arena(2 * MEGABYTE); Stream error_stream = stream_alloc(&platform_arena, MEGABYTE / 4); @@ -465,6 +482,7 @@ main(i32 argc, char *argv[], char *envp[]) iv2 window_size = {.w = 1280, .h = 720}; GLFWwindow *window = init_window(&ctx, window_size); + g_window = window; posix_platform_process child = os_fork_child("/bin/sh"); diff --git a/terminal.c b/terminal.c @@ -34,12 +34,6 @@ get_word_around_cell(Term *t, iv2 cell) return result; } -static void -set_window_title(GLFWwindow *win, Arena a, s8 title) -{ - glfwSetWindowTitle(win, s8_to_cstr(&a, title)); -} - static s8 consume(s8 raw, size count) { @@ -774,17 +768,9 @@ set_scrolling_region(Term *t, CSI *csi) static void window_manipulation(Term *t, CSI *csi) { - const char *s; - u32 i; - switch (csi->argv[0]) { - case 22: - s = glfwGetWindowTitle(t->gl.window); - for (i = 0; i < ARRAY_COUNT(t->saved_title) - 1 && s[i]; i++) - t->saved_title[i] = s[i]; - t->saved_title[i] = 0; - break; - case 23: glfwSetWindowTitle(t->gl.window, t->saved_title); break; + case 22: t->platform->get_window_title(&t->saved_title); break; + case 23: t->platform->set_window_title(&t->saved_title); break; default: stream_push_s8(&t->error_stream, s8("unhandled xtwinops: ")); stream_push_i64(&t->error_stream, csi->argv[0]); @@ -1009,10 +995,11 @@ handle_osc(Term *t, s8 *raw, Arena a) i32 ret = parse_osc(raw, &osc); ASSERT(ret != -1); + Stream buffer = arena_stream(a); switch (osc.cmd) { - case 0: set_window_title(t->gl.window, a, osc.arg); break; - case 1: /* IGNORED: set icon name */ break; - case 2: set_window_title(t->gl.window, a, osc.arg); break; + case 0: stream_push_s8(&buffer, osc.arg); t->platform->set_window_title(&buffer); break; + case 1: break; /* IGNORED: set icon name */ + case 2: stream_push_s8(&buffer, osc.arg); t->platform->set_window_title(&buffer); break; default: stream_push_s8(&t->error_stream, s8("unhandled osc cmd: ")); dump_osc(&osc, &t->error_stream); diff --git a/test.c b/test.c @@ -18,9 +18,6 @@ #include "config.h" /* NOTE: stubs for stuff we aren't testing */ -void glfwSetWindowTitle(GLFWwindow *w, const char *s) {} -const char *glfwGetWindowTitle(GLFWwindow *w) { return "test"; } - static void get_gpu_glyph_index(Arena, void *, void *, u32, u32, u32, CachedGlyph **); static GlyphCacheStats get_and_clear_glyph_cache_stats(void *p) { return (GlyphCacheStats){0}; } static void init_font(void *a, void *b) {} diff --git a/util.c b/util.c @@ -187,16 +187,6 @@ c_str_to_s8(char *s) return result; } -static char * -s8_to_cstr(Arena *a, s8 s) -{ - char *cstr = alloc(a, char, s.len + 1); - for (size i = 0; i < s.len; i++) - cstr[i] = s.data[i]; - cstr[s.len] = 0; - return cstr; -} - static struct conversion_result i32_from_cstr(char *s, char delim) { diff --git a/util.h b/util.h @@ -16,6 +16,7 @@ #endif #define PI 3.1415926535897932384f +#define KILOBYTE (1024ULL) #define MEGABYTE (1024ULL * 1024ULL) #define ARRAY_COUNT(a) (sizeof(a) / sizeof(*a)) @@ -481,9 +482,10 @@ typedef struct Term { * this would mean that cells are ~4px wide which is unreadable */ u32 tabs[32]; - char saved_title[1024]; - + Stream saved_title; Stream error_stream; + + PlatformAPI *platform; } Term; static f32 dt_for_frame; diff --git a/vtgl.c b/vtgl.c @@ -808,6 +808,8 @@ DEBUG_EXPORT VTGL_INITIALIZE_FN(vtgl_initialize) Term *t = (Term *)memory->memory; Arena a = {.beg = (u8 *)(t + 1), .end = memory->memory + memory->memory_size}; + t->platform = &memory->platform_api; + t->cursor.state = CURSOR_NORMAL; cursor_reset(t); @@ -827,6 +829,7 @@ DEBUG_EXPORT VTGL_INITIALIZE_FN(vtgl_initialize) t->size = (uv2){.x = 1, .y = 1}; t->error_stream = stream_alloc(&a, MEGABYTE / 4); + t->saved_title = stream_alloc(&a, 16 * KILOBYTE); t->arena_for_frame = a; t->child = child; diff --git a/vtgl.h b/vtgl.h @@ -11,18 +11,22 @@ typedef PLATFORM_WRITE_FN(platform_write_fn); #define PLATFORM_READ_FN(name) size name(iptr file, s8 buffer, size offset) typedef PLATFORM_READ_FN(platform_read_fn); -#define PLATFORM_GET_CLIPBOARD_FN(name) b32 name(Stream *buffer, u32 clipboard) -typedef PLATFORM_GET_CLIPBOARD_FN(platform_get_clipboard_fn); -#define PLATFORM_SET_CLIPBOARD_FN(name) void name(Stream *buffer, u32 clipboard) -typedef PLATFORM_SET_CLIPBOARD_FN(platform_set_clipboard_fn); +#define PLATFORM_CLIPBOARD_FN(name) b32 name(Stream *buffer, u32 clipboard) +typedef PLATFORM_CLIPBOARD_FN(platform_clipboard_fn); + +#define PLATFORM_WINDOW_TITLE_FN(name) void name(Stream *buffer) +typedef PLATFORM_WINDOW_TITLE_FN(platform_window_title_fn); typedef struct { platform_allocate_ring_buffer_fn *allocate_ring_buffer; platform_read_fn *read; platform_write_fn *write; - platform_get_clipboard_fn *get_clipboard; - platform_set_clipboard_fn *set_clipboard; + platform_clipboard_fn *get_clipboard; + platform_clipboard_fn *set_clipboard; + + platform_window_title_fn *get_window_title; + platform_window_title_fn *set_window_title; } PlatformAPI; /* NOTE: CLIPBOARD_1 need not be supported on all platforms */