This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch tymux
in repository terminology.
View the commit online.
commit 2c9d8e89b59e6d74c638be3924f548bd8b79bd92
Author: [email protected] <[email protected]>
AuthorDate: Mon May 4 18:56:59 2026 -0600
fix(tymux): propagate Synchronized Output (2026) through daemon-proxy pipe
Upstream commit 1a636d01 added support for DECSET/DECRST 2026
(Synchronized Output, BSU/ESU) to preserve application-level frame
intent. The tymux daemon was bypassing this: it would emit intermediate
frames mid-application-frame, defeating the atomic-frame guarantee that
tymux clients depend on.
This change gates frame emission at both layers:
termd_tymux.c (daemon-side gate): _pty_change_cb now early-returns when
sync_output.active is true, holding off NOTIFY while the application is
mid-frame. ESU, watchdog, soft-reset, and explicit resize will fire
cb.change again with active=FALSE, at which point the animator is armed
and exactly one frame ships. The TSRV_MSG_RESIZE handler now explicitly
cancels any pending animator and calls _tymux_flush_and_notify after
termpty_resize (which clears sync without firing cb.change), mirroring
the behaviour of _pty_exit_cb.
tymux.c (proxy-side wrapper): _render_screen wraps each per-NOTIFY
repaint in BSU/ESU (\x1b[?2026h...l) so the outer host terminal flips
the proxy's clear+content as one atomic frame. Outer terminals without
2026 support ignore the sequences harmlessly.
The two layers are complementary: the daemon gate preserves
application-level frame intent across the tymux wire; the proxy wrapper
avoids cosmetic glyph tearing from the proxy's multi-write emit on the
host. Neither subsumes the other. Zero behaviour change for apps that
never send 2026, or for non-tymux Terminology sessions.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
---
src/bin/termd_tymux.c | 23 ++++++++++++++++++++---
src/bin/tymux.c | 8 ++++++++
2 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/src/bin/termd_tymux.c b/src/bin/termd_tymux.c
index f60d5ef2..b2ca1b81 100644
--- a/src/bin/termd_tymux.c
+++ b/src/bin/termd_tymux.c
@@ -413,6 +413,11 @@ _pty_change_cb(void *data)
TermDTymux *sess = data;
sess->dirty = EINA_TRUE;
+ /* While the application is mid-frame (BSU active), hold off NOTIFY.
+ * ESU (or the watchdog / soft-reset / resize) will fire cb.change again
+ * with active == EINA_FALSE, at which point the animator is armed and
+ * exactly one frame is shipped. */
+ if (sess->pty->sync_output.active) return;
if (!sess->notify_anim)
sess->notify_anim = ecore_animator_add(_tymux_notify_anim_cb, sess);
}
@@ -507,10 +512,22 @@ _cb_client_data(void *data, Ecore_Fd_Handler *fd_handler EINA_UNUSED)
if (cols > 0 && rows > 0 &&
cols <= TERMSRV_MAX_COLS && rows <= TERMSRV_MAX_ROWS)
{
- /* termpty_resize triggers _pty_change_cb which flushes
- * to shm and sends NOTIFY to all clients — no explicit
- * _flush_screen_to_shm call needed here. */
+ /* termpty_resize calls termpty_sync_output_reset, which
+ * clears sync_output.active but does NOT fire cb.change.
+ * With the sync gate in _pty_change_cb the old comment
+ * (resize triggers change-cb → flush) is no longer
+ * reliable: if active was TRUE before the resize the
+ * animator was never armed. Cancel any stale animator
+ * and flush explicitly so clients get the new dimensions
+ * immediately, matching the behaviour of _pty_exit_cb. */
termpty_resize(sess->pty, (int)cols, (int)rows);
+ if (sess->notify_anim)
+ {
+ ecore_animator_del(sess->notify_anim);
+ sess->notify_anim = NULL;
+ }
+ sess->dirty = EINA_FALSE;
+ _tymux_flush_and_notify(sess);
}
}
break;
diff --git a/src/bin/tymux.c b/src/bin/tymux.c
index 5086c86a..e2b6fba4 100644
--- a/src/bin/tymux.c
+++ b/src/bin/tymux.c
@@ -843,6 +843,12 @@ _render_screen(const void *shm,
*prev_rows_io = srows;
}
+ /* Wrap the entire repaint in BSU/ESU so the outer terminal flips the
+ * delta (or full repaint + clear) as one atomic frame. The 2J clear is
+ * inside the window so that clear+content land together. Outer terminals
+ * that do not support DECSET 2026 ignore these sequences harmlessly. */
+ write(STDOUT_FILENO, "\x1b[?2026h", 8);
+
if (dim_changed)
{
/* Clear screen before full repaint on resize */
@@ -853,6 +859,8 @@ _render_screen(const void *shm,
{
_render_delta(shm, *prev_cells_io, scols, srows);
}
+
+ write(STDOUT_FILENO, "\x1b[?2026l", 8);
}
/* ── commands ────────────────────────────────────────────────────────── */
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.