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 05eba7893ca1969c9c39a75e70445a9cf6194ea3
Author: [email protected] <[email protected]>
AuthorDate: Mon May 4 21:53:29 2026 -0600

    feat(tymux): add native Ctrl+b d detach chord in tymux input path
    
    The user-visible detach gesture is implemented as a two-state machine in
    _tymux_write_cb, the input forward path that routes every keystroke from
    a native tymux widget to the daemon. Ctrl+b (0x02) is swallowed and sets
    prefix_pending; if the next byte is 'd' (0x64), both bytes are dropped
    and TSRV_MSG_DETACH is sent; otherwise, the pending 0x02 is emitted to
    preserve literal Ctrl+b passthrough for programs like emacs/vim/readline.
    
    This reuses the detach plumbing established earlier: DETACH → daemon
    replies with CWD → daemon closes → client reads CWD into last_cwd → EOF
    fires cb_exit → _smart_pty_exited calls _termio_tymux_demote. The user's
    tab survives, the daemon stays in tymux list, and a fresh shell appears
    at the inner shell's last cwd, matching the CLI proxy chord from cdc86dca.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
---
 src/bin/termtymux.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++----
 src/bin/termtymux.h |  3 ++-
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/src/bin/termtymux.c b/src/bin/termtymux.c
index 78498b30..dcd6bfb7 100644
--- a/src/bin/termtymux.c
+++ b/src/bin/termtymux.c
@@ -388,13 +388,55 @@ static void
 _tymux_write_cb(const char *buf, int len, void *data)
 {
    TermTymux *ts = data;
+   char       *out;
+   int         on  = 0;
+   int         i;
+   Eina_Bool   detach_now = EINA_FALSE;
 
-   if (!ts || ts->sock_fd < 0 || len <= 0)
-     return;
+   if (!ts || ts->sock_fd < 0 || len <= 0) return;
 
-   if (termsrv_msg_send(ts->sock_fd, TSRV_MSG_INPUT,
-                        buf, (uint32_t)len) < 0)
+   /* Output may be up to len+1 bytes when a previous read ended with a
+    * pending prefix and the next read starts with a non-'d' byte. */
+   out = malloc((size_t)len + 1);
+   if (!out) return;
+
+   for (i = 0; i < len; i++)
+     {
+        unsigned char b = (unsigned char)buf[i];
+        if (ts->prefix_pending)
+          {
+             ts->prefix_pending = EINA_FALSE;
+             if (b == 0x64) /* 'd' — chord completes */
+               {
+                  detach_now = EINA_TRUE;
+                  /* swallow both 0x02 and 'd'; do not forward */
+               }
+             else
+               {
+                  /* literal Ctrl+b passthrough */
+                  out[on++] = 0x02;
+                  out[on++] = (char)b;
+               }
+          }
+        else if (b == 0x02)
+          {
+             ts->prefix_pending = EINA_TRUE;
+             /* swallow; will be emitted on next byte if not 'd' */
+          }
+        else
+          {
+             out[on++] = (char)b;
+          }
+     }
+
+   if (on > 0 &&
+       termsrv_msg_send(ts->sock_fd, TSRV_MSG_INPUT,
+                        out, (uint32_t)on) < 0)
      ERR("termtymux: failed to send INPUT: %s", strerror(errno));
+   free(out);
+
+   if (detach_now)
+     termsrv_msg_send(ts->sock_fd, TSRV_MSG_DETACH, NULL, 0);
 }
 
 /* ── shadow Termpty ─────────────────────────────────────────────────── */
diff --git a/src/bin/termtymux.h b/src/bin/termtymux.h
index e0e74089..3d26a3a8 100644
--- a/src/bin/termtymux.h
+++ b/src/bin/termtymux.h
@@ -51,7 +51,8 @@ struct _TermTymux {
       void *data;
    } cb_pause, cb_resume;
 
-   Eina_Bool paused;  /* EINA_TRUE when session is paused by hijacker */
+   Eina_Bool paused;          /* EINA_TRUE when session is paused by hijacker */
+   Eina_Bool prefix_pending;  /* TRUE after Ctrl+b (0x02), waiting for 'd' */
 };
 
 /*

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to