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 9110226c14af5c9044f3abf945b0bf5ee2762a36
Author: [email protected] <[email protected]>
AuthorDate: Fri Mar 20 22:27:26 2026 -0600

    feat: tymux attach switches Terminology to native session widget
    
    When tymux attach runs inside Terminology, it writes the escape
    sequence \033}at;<name>\0 to the PTY. Terminology's command handler
    recognizes the "at;" opcode and calls _termio_tymux_switch(), which:
    
    1. Connects to the tymuxd daemon via termsession_attach()
    2. Kills the old PTY (shell + tymux process get SIGHUP)
    3. Installs the shadow Termpty with write_cb forwarding
    4. Wires session callbacks (change/title/bell/exit)
    5. Enables the green tymux indicator
    
    If tymux attach is running in a non-Terminology terminal, the
    escape sequence is silently consumed and it falls through to the
    inline proxy path as before.
    
    This means session save/restore works correctly for terminals that
    were switched to tymux via "tymux attach" — the widget has native
    session_name set, so it gets saved as mux_type="tymux" and restored
    via termsession_attach on reload.
    
    New public API: term_tymux_indicator_set() in win.h allows termio.c
    to toggle the green indicator without accessing Term internals.
    
    Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---
 src/bin/termio.c     | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/bin/termptyext.c |  3 ++
 src/bin/tymux.c      | 21 +++++++++++
 src/bin/win.c        | 16 ++++++---
 src/bin/win.h        |  4 +++
 5 files changed, 139 insertions(+), 4 deletions(-)

diff --git a/src/bin/termio.c b/src/bin/termio.c
index f91fd4b8..16568308 100644
--- a/src/bin/termio.c
+++ b/src/bin/termio.c
@@ -23,6 +23,7 @@
 #include "gravatar.h"
 #include "sb.h"
 #include "utils.h"
+#include "win.h"
 
 #if defined (__MacOSX__) || (defined (__MACH__) && defined (__APPLE__))
 # include <sys/proc_info.h>
@@ -3793,6 +3794,91 @@ _handle_query_esc(Termio *sd)
      }
 }
 
+#ifdef HAVE_TYMUX
+/*
+ * _termio_tymux_switch - replace the current plain PTY with a native tymux session.
+ *
+ * Called from _smart_pty_command() when the running 'tymux attach' tool emits
+ * the \033}at;<name>\0 escape sequence.  On success:
+ *   - the old PTY (and its shell) is freed/killed
+ *   - a shadow Termpty backed by the tymux daemon is installed in its place
+ *   - the Term's tymux indicator is lit
+ *
+ * If attaching fails the current PTY is left untouched.
+ */
+static Eina_Bool
+_tymux_name_valid(const char *name)
+{
+   if (!name || name[0] == '\0' || strchr(name, '/')) return EINA_FALSE;
+   return EINA_TRUE;
+}
+
+static void
+_termio_tymux_switch(Evas_Object *obj, Termio *sd, const char *tymux_name)
+{
+   Termpty   *spty  = NULL;
+   TermTymux *tymux = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN(tymux_name);
+   if (!_tymux_name_valid(tymux_name)) return;
+
+   /* Clean up any previous tymux or plain PTY state before attaching. */
+   if (sd->tymux)
+     {
+        /* Already in a tymux session — tear it down first.
+         * termtymux_free() also frees the shadow Termpty. */
+        termtymux_free(sd->tymux);
+        sd->tymux = NULL;
+        sd->pty = NULL;  /* freed by termtymux_free */
+        eina_stringshare_del(sd->tymux_name);
+        sd->tymux_name = NULL;
+     }
+   else if (sd->pty)
+     {
+        /* Plain PTY — free it.  The shell and 'tymux attach' helper both
+         * receive SIGHUP when the PTY master is closed. */
+        termpty_free(sd->pty);
+        sd->pty = NULL;
+     }
+
+   tymux = termtymux_attach(tymux_name,
+                             sd->grid.w,
+                             sd->grid.h,
+                             sd->config, &spty);
+   if (!tymux)
+     {
+        ERR("tymux switch: could not attach to '%s'", tymux_name);
+        return;
+     }
+
+   /* Install the shadow PTY that renders the tymux session. */
+   sd->pty = spty;
+   sd->pty->obj = obj;
+
+   /* Replace tymux tracking fields. */
+   eina_stringshare_del(sd->tymux_name);
+   sd->tymux_name = eina_stringshare_add(tymux_name);
+   sd->tymux = tymux;
+
+   /* Wire callbacks — same pattern as the tymux branch in termio_add(). */
+   sd->tymux->cb_change.func = _smart_pty_change;
+   sd->tymux->cb_change.data = ""
+   sd->tymux->cb_title.func  = _smart_pty_title;
+   sd->tymux->cb_title.data  = ""
+   sd->tymux->cb_bell.func   = _smart_pty_bell;
+   sd->tymux->cb_bell.data   = ""
+   sd->tymux->cb_exit.func   = _smart_pty_exited;
+   sd->tymux->cb_exit.data   = ""
+
+   /* Light up the tymux indicator in the containing Term widget. */
+   if (sd->term)
+     term_tymux_indicator_set(sd->term, EINA_TRUE);
+
+   /* Force an immediate redraw so the session content appears. */
+   _smart_apply(obj);
+}
+#endif /* HAVE_TYMUX */
+
 static void
 _smart_pty_command(void *data)
 {
@@ -3813,6 +3899,19 @@ _smart_pty_command(void *data)
         return;
      }
 
+#ifdef HAVE_TYMUX
+   /* at;<session_name> — escape emitted by 'tymux attach' to request a
+    * native session hand-off.  Handled before the ty_escapes gate so that
+    * it works regardless of whether Terminology escapes are enabled. */
+   if (ty->cur_cmd[0] == 'a' && ty->cur_cmd[1] == 't' && ty->cur_cmd[2] == ';')
+     {
+        const char *sess = &ty->cur_cmd[3];
+        if (sess[0] && _tymux_name_valid(sess))
+          _termio_tymux_switch(obj, sd, sess);
+        return;
+     }
+#endif
+
    if (!config->ty_escapes)
      return;
 
diff --git a/src/bin/termptyext.c b/src/bin/termptyext.c
index b0c9627c..863f9097 100644
--- a/src/bin/termptyext.c
+++ b/src/bin/termptyext.c
@@ -541,6 +541,9 @@ termpty_ext_handle(Termpty *ty ARG_USED_FOR_TESTS,
 {
    switch (buf[0]) // major opcode
      {
+      /* 'a' is reserved for tymux attach — handled in termio.c
+       * _smart_pty_command() via the "at;<name>" opcode.  Do NOT add a
+       * case 'a' here or the native attach hand-off will break. */
 #if defined(BINARY_TYTEST) || defined(ENABLE_TEST_UI)
       case 't':
         tytest_handle_escape_codes(ty, buf + 1);
diff --git a/src/bin/tymux.c b/src/bin/tymux.c
index caa87655..985cc6b4 100644
--- a/src/bin/tymux.c
+++ b/src/bin/tymux.c
@@ -1035,6 +1035,27 @@ cmd_attach(int argc, char **argv)
         return 1;
      }
 
+   /* If running inside Terminology, ask it to take over natively.
+    * Write \033}at;<name>\0 — Terminology's escape parser catches \033}
+    * sequences and the 'at' opcode triggers _termio_tymux_switch().
+    * If Terminology handles it, our PTY is killed and we exit below via
+    * the proxy loop's EOF path.  If we are in a different terminal the
+    * escape is silently consumed and we fall through to the proxy path.
+    *
+    * The liveness check is performed first so we never send the escape
+    * for a session that does not exist — Terminology would then attempt
+    * to attach to a dead socket and log a spurious error. */
+   {
+      char esc[128];
+      int  n = snprintf(esc, sizeof(esc), "\033}at;%s", name);
+      if (n > 0 && (size_t)n < sizeof(esc))
+        {
+           ssize_t written = write(STDOUT_FILENO, esc, (size_t)(n + 1)); /* +1 for NUL */
+           if (written < 0 || written != (ssize_t)(n + 1))
+             fprintf(stderr, "tymux: warning: escape delivery failed\n");
+        }
+   }
+
    /* ── Connect ── */
    int sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
    if (sock < 0) { perror("tymux: socket"); return 1; }
diff --git a/src/bin/win.c b/src/bin/win.c
index 73271887..9870ac0c 100644
--- a/src/bin/win.c
+++ b/src/bin/win.c
@@ -456,10 +456,18 @@ static void
 _tymux_indicator_update(Term *term)
 {
    if (term->is_tymux)
-     {
-        elm_layout_signal_emit(term->bg, "tymux,on", "terminology");
-        edje_object_message_signal_process(term->bg_edj);
-     }
+     elm_layout_signal_emit(term->bg, "tymux,on", "terminology");
+   else
+     elm_layout_signal_emit(term->bg, "tymux,off", "terminology");
+   edje_object_message_signal_process(term->bg_edj);
+}
+
+void
+term_tymux_indicator_set(Term *term, Eina_Bool on)
+{
+   EINA_SAFETY_ON_NULL_RETURN(term);
+   term->is_tymux = on ? 1 : 0;
+   _tymux_indicator_update(term);
 }
 #endif
 
diff --git a/src/bin/win.h b/src/bin/win.h
index 58926be1..f9636b5c 100644
--- a/src/bin/win.h
+++ b/src/bin/win.h
@@ -91,4 +91,8 @@ for_each_term_do(Win *wn, For_Each_Term cb, void *data);
 
 void main_trans_update(void);
 
+#ifdef HAVE_TYMUX
+void term_tymux_indicator_set(Term *term, Eina_Bool on);
+#endif
+
 #endif

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

Reply via email to