From 38461eef6f3b612277bf48e49b9cc6c3b79e25bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 30 Jun 2024 19:44:17 +0200 Subject: [PATCH] csi: in-band window resize notifications, private mode 2048 This implements https://gist.github.com/rockorager/e695fb2924d36b2bcf1fff4a3704bd83, in-band window resize notifications. When user enables private mode 2048 (in-band resize notifications), *always* send current size, even if the mode is already active. This ensures applications can rely on getting a reply from the terminal. --- CHANGELOG.md | 3 +++ csi.c | 10 ++++++++++ doc/foot-ctlseqs.7.scd | 3 +++ render.c | 2 ++ terminal.c | 35 +++++++++++++++++++++++++++++++++++ terminal.h | 7 +++++++ 6 files changed, 60 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b0e30ad..ce993718 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,9 @@ i.e. color palette stack ([#856][856]). * Log output now respects the [`NO_COLOR`](http://no-color.org/) environment variable ([#1771][1771]). +* Support for [in-band window resize + notifications](https://gist.github.com/rockorager/e695fb2924d36b2bcf1fff4a3704bd83), + private mode `2048`. [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 1f61d3ce..2b9f137d 100644 --- a/csi.c +++ b/csi.c @@ -562,6 +562,13 @@ decset_decrst(struct terminal *term, unsigned param, bool enable) term->grapheme_shaping = enable; break; + case 2048: + if (enable) + term_enable_size_notifications(term); + else + term_disable_size_notifications(term); + break; + case 8452: term->sixel.cursor_right_of_graphics = enable; break; @@ -649,6 +656,7 @@ 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 2048: return decrpm(term->size_notifications); case 8452: return decrpm(term->sixel.cursor_right_of_graphics); case 737769: return decrpm(term_ime_is_enabled(term)); } @@ -693,6 +701,7 @@ 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 2048: term->xtsave.size_notifications = term->size_notifications; 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; } @@ -736,6 +745,7 @@ 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 2048: enable = term->xtsave.size_notifications; break; case 8452: enable = term->xtsave.sixel_cursor_right_of_graphics; break; case 737769: enable = term->xtsave.ime; break; diff --git a/doc/foot-ctlseqs.7.scd b/doc/foot-ctlseqs.7.scd index f73b5793..5c611c92 100644 --- a/doc/foot-ctlseqs.7.scd +++ b/doc/foot-ctlseqs.7.scd @@ -337,6 +337,9 @@ that corresponds to one of the following modes: | 2027 : contour : Grapheme cluster processing +| 2048 +: TODO +: In-band window resize notifications | 8452 : xterm : Position cursor to the right of sixels, instead of on the next line diff --git a/render.c b/render.c index 53c8c90e..ef135b53 100644 --- a/render.c +++ b/render.c @@ -4072,6 +4072,8 @@ tiocswinsz(struct terminal *term) { LOG_ERRNO("TIOCSWINSZ"); } + + term_send_size_notification(term); } } diff --git a/terminal.c b/terminal.c index 6e83d9a0..e1da77f5 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 @@ -4240,3 +4241,37 @@ term_set_user_mouse_cursor(struct terminal *term, const char *cursor) : NULL; term_xcursor_update(term); } + +void +term_enable_size_notifications(struct terminal *term) +{ + /* Note: always send current size upon activation, regardless of + previous state */ + term->size_notifications = true; + term_send_size_notification(term); +} + +void +term_disable_size_notifications(struct terminal *term) +{ + if (!term->size_notifications) + return; + + term->size_notifications = false; +} + +void +term_send_size_notification(struct terminal *term) +{ + if (!term->size_notifications) + return; + + const int height = term->height - term->margins.top - term->margins.bottom; + const int width = term->width - term->margins.left - term->margins.right; + + char buf[128]; + const int n = xsnprintf( + buf, sizeof(buf), "\033[48;%d;%d;%d;%dt", + term->rows, term->cols, height, width); + term_to_slave(term, buf, n); +} diff --git a/terminal.h b/terminal.h index 926870c1..44a101eb 100644 --- a/terminal.h +++ b/terminal.h @@ -541,6 +541,8 @@ struct terminal { bool app_sync_updates:1; bool grapheme_shaping:1; + bool size_notifications:1; + bool sixel_display_mode:1; bool sixel_private_palette:1; bool sixel_cursor_right_of_graphics:1; @@ -800,6 +802,7 @@ struct terminal { char *cwd; bool grapheme_shaping; + bool size_notifications; }; struct config; @@ -946,6 +949,10 @@ void term_osc8_close(struct terminal *term); bool term_ptmx_pause(struct terminal *term); bool term_ptmx_resume(struct terminal *term); +void term_enable_size_notifications(struct terminal *term); +void term_disable_size_notifications(struct terminal *term); +void term_send_size_notification(struct terminal *term); + static inline void term_reset_grapheme_state(struct terminal *term) { #if defined(FOOT_GRAPHEME_CLUSTERING)