From f3d848da019c6cc970b078b0b032d609ee83e083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 8 Jun 2024 08:39:47 +0200 Subject: [PATCH] osc: 52: treat OSC-52 replies as paste data (after all, they are) This fixes an issue where other data (such as replies to other requests) being interleaved with the OSC-52 reply. The patch piggy backs on the already existing mechanism for handling regular pastes, where other data is queued up until the paste is done. There's one corner case that won't work; if the user *just* did a normal paste (i.e. at virtually the same time the application requested OSC-52 data), the OSC-52 request will return an empty reply. Likewise, if there are multiple OSC-52 requests at the same time, only the first will return data. Closes #1734 --- CHANGELOG.md | 3 +++ osc.c | 39 +++++++++++++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10ed8876..9cb9b38c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -91,10 +91,13 @@ * Unicode-mode in one foot client affecting other clients, in foot server mode ([#1717][1717]). * IME interfering in URL-mode ([#1718][1718]). +* OSC-52 reply interleaved with other data sent to the client + ([#1734][1734]). [1694]: https://codeberg.org/dnkl/foot/issues/1694 [1717]: https://codeberg.org/dnkl/foot/issues/1717 [1718]: https://codeberg.org/dnkl/foot/issues/1718 +[1734]: https://codeberg.org/dnkl/foot/issues/1734 ### Security diff --git a/osc.c b/osc.c index 446461a2..546421f5 100644 --- a/osc.c +++ b/osc.c @@ -5,6 +5,8 @@ #include #include +#include + #define LOG_MODULE "osc" #define LOG_ENABLE_DBG 0 #include "log.h" @@ -124,7 +126,7 @@ from_clipboard_cb(char *text, size_t size, void *user) xassert(chunk != NULL); xassert(strlen(chunk) == 4); - term_to_slave(term, chunk, 4); + term_paste_data_to_slave(term, chunk, 4); free(chunk); ctx->idx = 0; @@ -144,7 +146,7 @@ from_clipboard_cb(char *text, size_t size, void *user) char *chunk = base64_encode((const uint8_t *)t, left / 3 * 3); xassert(chunk != NULL); xassert(strlen(chunk) % 4 == 0); - term_to_slave(term, chunk, strlen(chunk)); + term_paste_data_to_slave(term, chunk, strlen(chunk)); free(chunk); } @@ -157,13 +159,19 @@ from_clipboard_done(void *user) if (ctx->idx > 0) { char res[4]; base64_encode_final(ctx->buf, ctx->idx, res); - term_to_slave(term, res, 4); + term_paste_data_to_slave(term, res, 4); } if (term->vt.osc.bel) - term_to_slave(term, "\a", 1); + term_paste_data_to_slave(term, "\a", 1); else - term_to_slave(term, "\033\\", 2); + term_paste_data_to_slave(term, "\033\\", 2); + + term->is_sending_paste_data = false; + + /* Make sure we send any queued up non-paste data */ + if (tll_length(term->ptmx_buffers) > 0) + fdm_event_add(term->fdm, term->ptmx, EPOLLOUT); free(ctx); } @@ -214,9 +222,24 @@ osc_from_clipboard(struct terminal *term, const char *source) if (!from_clipboard && !from_primary) return; - term_to_slave(term, "\033]52;", 5); - term_to_slave(term, &src, 1); - term_to_slave(term, ";", 1); + if (term->is_sending_paste_data) { + /* FIXME: we should wait for the paste to end, then continue + with the OSC-52 reply */ + term_to_slave(term, "\033]52;", 5); + term_to_slave(term, &src, 1); + term_to_slave(term, ";", 1); + if (term->vt.osc.bel) + term_to_slave(term, "\a", 1); + else + term_to_slave(term, "\033\\", 2); + return; + } + + term->is_sending_paste_data = true; + + term_paste_data_to_slave(term, "\033]52;", 5); + term_paste_data_to_slave(term, &src, 1); + term_paste_data_to_slave(term, ";", 1); struct clip_context *ctx = xmalloc(sizeof(*ctx)); *ctx = (struct clip_context) {.seat = seat, .term = term};