From 774c60602b32f50e82b75404ea9631f23c7d7c83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 28 Jun 2024 18:38:03 +0200 Subject: [PATCH] csi: implement private modes 2034 + 2038 2034 enables window resize notifications, with the notifications being in pixels. 2038 does the same, but in characters instead of pixels. See https://gist.github.com/rockorager/e695fb2924d36b2bcf1fff4a3704bd83 for specification --- CHANGELOG.md | 2 ++ csi.c | 54 +++++++++++++++------------------ doc/foot-ctlseqs.7.scd | 6 ++++ render.c | 5 +++ terminal.c | 69 ++++++++++++++++++++++++++++++++++++++++++ terminal.h | 13 ++++++++ 6 files changed, 119 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 901f5a6b..f21b4b8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,8 @@ will now utilize the new single-pixel buffer protocol. This mainly reduces the memory usage, but should also be slightly faster. * Support for high-res mouse wheel scroll events ([#1738][1738]). +* Support for private modes 2034 and 2038 ([in-band window resize + notifications](https://gist.github.com/rockorager/e695fb2924d36b2bcf1fff4a3704bd83)). [1707]: https://codeberg.org/dnkl/foot/issues/1707 [1738]: https://codeberg.org/dnkl/foot/issues/1738 diff --git a/csi.c b/csi.c index be470e70..805c291e 100644 --- a/csi.c +++ b/csi.c @@ -500,6 +500,20 @@ decset_decrst(struct terminal *term, unsigned param, bool enable) term->grapheme_shaping = enable; break; + case 2034: + if (enable) + term_enable_size_notifications_pixels(term); + else + term_disable_size_notifications_pixels(term); + break; + + case 2038: + if (enable) + term_enable_size_notifications_chars(term); + else + term_disable_size_notifications_chars(term); + break; + case 8452: term->sixel.cursor_right_of_graphics = enable; break; @@ -587,6 +601,8 @@ decrqm(const struct terminal *term, unsigned param) case 2027: return term->conf->tweak.grapheme_width_method != GRAPHEME_WIDTH_DOUBLE ? DECRPM_PERMANENTLY_RESET : decrpm(term->grapheme_shaping); + case 2034: return decrpm(term->size_notifications_pixels); + case 2038: return decrpm(term->size_notifications_chars); case 8452: return decrpm(term->sixel.cursor_right_of_graphics); case 737769: return decrpm(term_ime_is_enabled(term)); } @@ -631,6 +647,8 @@ xtsave(struct terminal *term, unsigned param) case 2004: term->xtsave.bracketed_paste = term->bracketed_paste; break; case 2026: term->xtsave.app_sync_updates = term->render.app_sync_updates.enabled; break; case 2027: term->xtsave.grapheme_shaping = term->grapheme_shaping; break; + case 2034: term->xtsave.size_notifications_pixels = term->size_notifications_pixels; break; + case 2038: term->xtsave.size_notifications_chars = term->size_notifications_chars; break; case 8452: term->xtsave.sixel_cursor_right_of_graphics = term->sixel.cursor_right_of_graphics; break; case 737769: term->xtsave.ime = term_ime_is_enabled(term); break; } @@ -674,6 +692,8 @@ xtrestore(struct terminal *term, unsigned param) case 2004: enable = term->xtsave.bracketed_paste; break; case 2026: enable = term->xtsave.app_sync_updates; break; case 2027: enable = term->xtsave.grapheme_shaping; break; + case 2034: enable = term->xtsave.size_notifications_pixels; break; + case 2038: enable = term->xtsave.size_notifications_chars; break; case 8452: enable = term->xtsave.sixel_cursor_right_of_graphics; break; case 737769: enable = term->xtsave.ime; break; @@ -1204,33 +1224,10 @@ csi_dispatch(struct terminal *term, uint8_t final) break; } - case 14: { /* report window size in pixels */ - int width = -1; - int height = -1; - + case 14: { /* report window/text-area size in pixels */ switch (vt_param_get(term, 1, 0)) { - case 0: - /* text area size */ - width = term->width - term->margins.left - term->margins.right; - height = term->height - term->margins.top - term->margins.bottom; - break; - - case 2: - /* window size */ - width = term->width; - height = term->height; - break; - - default: - UNHANDLED(); - break; - } - - if (width >= 0 && height >= 0) { - char reply[64]; - size_t n = xsnprintf( - reply, sizeof(reply), "\033[4;%d;%dt", height, width); - term_to_slave(term, reply, n); + case 0: term_report_window_size_pixels(term, false); break; + case 2: term_report_window_size_pixels(term, true); break; } break; } @@ -1259,10 +1256,7 @@ csi_dispatch(struct terminal *term, uint8_t final) } case 18: { /* text area size in chars */ - char reply[64]; - size_t n = xsnprintf(reply, sizeof(reply), "\033[8;%d;%dt", - term->rows, term->cols); - term_to_slave(term, reply, n); + term_report_window_size_chars(term); break; } diff --git a/doc/foot-ctlseqs.7.scd b/doc/foot-ctlseqs.7.scd index 38742aa3..4af3c67a 100644 --- a/doc/foot-ctlseqs.7.scd +++ b/doc/foot-ctlseqs.7.scd @@ -331,6 +331,12 @@ that corresponds to one of the following modes: | 2027 : contour : Grapheme cluster processing +| 2034 +: TODO +: In-band window resize notifications, in pixels +| 2038 +: TODO +: In-band window resize notifications, in characters | 8452 : xterm : Position cursor to the right of sixels, instead of on the next line diff --git a/render.c b/render.c index fd7e743a..cd625a6b 100644 --- a/render.c +++ b/render.c @@ -3866,6 +3866,11 @@ tiocswinsz(struct terminal *term) { LOG_ERRNO("TIOCSWINSZ"); } + + if (term->size_notifications_chars) + term_report_window_size_chars(term); + if (term->size_notifications_pixels) + term_report_window_size_pixels(term, false); } } diff --git a/terminal.c b/terminal.c index 55c387c1..35d89d7f 100644 --- a/terminal.c +++ b/terminal.c @@ -44,6 +44,7 @@ #include "util.h" #include "vt.h" #include "xmalloc.h" +#include "xsnprintf.h" #define PTMX_TIMING 0 @@ -4098,3 +4099,71 @@ term_set_user_mouse_cursor(struct terminal *term, const char *cursor) : NULL; term_xcursor_update(term); } + +void +term_enable_size_notifications_pixels(struct terminal *term) +{ + if (term->size_notifications_pixels) + return; + + term->size_notifications_pixels = true; + term_report_window_size_pixels(term, false); +} + +void +term_disable_size_notifications_pixels(struct terminal *term) +{ + if (!term->size_notifications_pixels) + return; + + term->size_notifications_chars = false; +} + +void +term_enable_size_notifications_chars(struct terminal *term) +{ + if (term->size_notifications_chars) + return; + + term->size_notifications_chars = true; + term_report_window_size_chars(term); +} + +void +term_disable_size_notifications_chars(struct terminal *term) +{ + if (!term->size_notifications_chars) + return; + + term->size_notifications_chars = false; +} + +void +term_report_window_size_pixels(struct terminal *term, bool include_padding) +{ + int width = -1; + int height = -1; + + if (!include_padding) { + /* The text area only */ + width = term->width - term->margins.left - term->margins.right; + height = term->height - term->margins.top - term->margins.bottom; + } else { + /* The entire window, including padding */ + width = term->width; + height = term->height; + } + + char reply[64]; + size_t n = xsnprintf(reply, sizeof(reply), "\033[4;%d;%dt", height, width); + term_to_slave(term, reply, n); +} + +void +term_report_window_size_chars(struct terminal *term) +{ + char reply[64]; + size_t n = xsnprintf( + reply, sizeof(reply), "\033[8;%d;%dt", term->rows, term->cols); + term_to_slave(term, reply, n); +} diff --git a/terminal.h b/terminal.h index 5033c550..f6e781a5 100644 --- a/terminal.h +++ b/terminal.h @@ -479,6 +479,9 @@ struct terminal { bool sixel_display_mode:1; bool sixel_private_palette:1; bool sixel_cursor_right_of_graphics:1; + + bool size_notifications_pixels:1; + bool size_notifications_chars:1; } xtsave; bool window_title_has_been_set; @@ -741,6 +744,9 @@ struct terminal { char *cwd; bool grapheme_shaping; + + bool size_notifications_pixels; /* Private mode 2034 */ + bool size_notifications_chars; /* Private mode 2038 */ }; struct config; @@ -860,6 +866,13 @@ bool term_spawn_new(const struct terminal *term); void term_enable_app_sync_updates(struct terminal *term); void term_disable_app_sync_updates(struct terminal *term); +void term_enable_size_notifications_pixels(struct terminal *term); +void term_disable_size_notifications_pixels(struct terminal *term); +void term_enable_size_notifications_chars(struct terminal *term); +void term_disable_size_notifications_chars(struct terminal *term); +void term_report_window_size_pixels(struct terminal *term, bool include_padding); +void term_report_window_size_chars(struct terminal *term); + enum term_surface term_surface_kind( const struct terminal *term, const struct wl_surface *surface);