This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch feat/e-wl-proxy-planb
in repository enlightenment.

View the commit online.

commit eedfea4c72b309251d4f560e5ff4935313e93955
Author: [email protected] <[email protected]>
AuthorDate: Sat Jun 13 11:41:14 2026 -0600

    feat(wl): run Enlightenment behind e_wl_proxy (opt-in via E_WL_PROXY=1)
    
    Integrate the proxy into the Enlightenment startup path. With E_WL_PROXY=1,
    enlightenment_start launches e_wl_proxy as a persistent sibling that owns the
    public Wayland socket and outlives each Enlightenment restart, and points
    Enlightenment at a private backend socket; it waits on a readiness pipe so
    clients can connect the moment the session comes up.
    
    Enlightenment then:
    - creates its compositor on the private backend socket (E_WL_SOCKET) while
      preserving the public WAYLAND_DISPLAY, so spawned clients reach the proxy and
      not the backend directly;
    - routes its own internal display and internal elm windows onto that same
      direct backend connection so surface matching keeps working;
    - auto-loads the wl_proxy companion module when running behind the proxy.
    
    Without E_WL_PROXY the original behavior is unchanged.
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
---
 src/bin/e_comp_wl.c    | 46 ++++++++++++++++++++++++++++++++---
 src/bin/e_start_main.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/bin/e_win.c        | 39 +++++++++++++++++++++++++++---
 3 files changed, 144 insertions(+), 6 deletions(-)

diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c
index 14427dafb..fcd0a2a36 100644
--- a/src/bin/e_comp_wl.c
+++ b/src/bin/e_comp_wl.c
@@ -159,6 +159,23 @@ _e_comp_wl_modules_load(void)
         if (mod)
           e_module_enable(mod);
      }
+
+#ifdef USE_MODULE_WL_PROXY
+   /* The wl_proxy companion mirrors each window's WM-state (geometry, desktop,
+    * stacking, focus) to the e_wl_proxy proxy so it can be restored after a
+    * compositor crash. It is only useful when E runs behind the proxy, which
+    * exports E_WL_PROXY_SOCK (the control socket the module connects to). */
+   if (getenv("E_WL_PROXY_SOCK"))
+     {
+        E_Module *mod = e_module_find("wl_proxy");
+
+        if (!mod)
+          mod = e_module_new("wl_proxy");
+
+        if (mod)
+          e_module_enable(mod);
+     }
+#endif
 }
 
 static void
@@ -2792,15 +2809,32 @@ _e_comp_wl_compositor_create(void)
    /* set wayland log handler */
    /* wl_log_set_handler_server(_e_comp_wl_log_cb_print); */
 
-   /* try to create an ecore_wl2 display */
-   cdata->ewd = ecore_wl2_display_create(NULL);
+   /* try to create an ecore_wl2 display. When run behind e_wl_proxy,
+    * E_WL_SOCKET names the private backend socket the proxy connects to;
+    * otherwise NULL keeps the auto-named socket. ecore_wl2_display_create()
+    * overwrites WAYLAND_DISPLAY with the socket name it created, so capture
+    * the proxy's public name first and restore it afterwards — otherwise every
+    * client E spawns would connect straight to the backend, bypassing the
+    * proxy. */
+   const char *backend = getenv("E_WL_SOCKET");
+   char *public_disp = (backend && getenv("WAYLAND_DISPLAY")) ?
+                       strdup(getenv("WAYLAND_DISPLAY")) : NULL;
+
+   cdata->ewd = ecore_wl2_display_create(backend);
    if (!cdata->ewd)
      {
         ERR("Could not create a Wayland display");
+        free(public_disp);
         free(cdata);
         return EINA_FALSE;
      }
 
+   if (public_disp)
+     {
+        e_env_set("WAYLAND_DISPLAY", public_disp);
+        free(public_disp);
+     }
+
    cdata->wl.disp = ecore_wl2_display_get(cdata->ewd);
    if (!cdata->wl.disp)
      {
@@ -2855,7 +2889,13 @@ _e_comp_wl_compositor_create(void)
         ERR("Could not initialize input");
         goto input_err;
      }
-   e_comp_wl->wl.client_disp = ecore_wl2_display_connect(NULL);
+   /* Behind e_wl_proxy, connect E's internal display directly to the private
+    * backend socket (E_WL_SOCKET) so all of E's internal wayland traffic — this
+    * connection and the internal elm windows (see e_win.c) — lives on the same
+    * direct connection to E, not split across the proxy. Keeping them unified is
+    * what lets the internal_elm_win machinery match surfaces correctly. getenv
+    * returns NULL without the proxy, preserving the original behavior. */
+   e_comp_wl->wl.client_disp = ecore_wl2_display_connect(getenv("E_WL_SOCKET"));
 
    _e_comp_wl_modules_load();
 
diff --git a/src/bin/e_start_main.c b/src/bin/e_start_main.c
index 2e7c50ed9..dc26d5b75 100644
--- a/src/bin/e_start_main.c
+++ b/src/bin/e_start_main.c
@@ -517,6 +517,68 @@ done:
    return ret;
 }
 
+/* Launch e_wl_proxy as a persistent sibling that owns the public Wayland
+ * socket, and point E at a private backend socket. Opt-in via E_WL_PROXY=1.
+ * The proxy outlives each E restart, so connected clients survive an E crash.
+ * Returns the proxy pid, or -1 if not started. */
+static pid_t
+_e_wl_proxy_start(void)
+{
+   const char *enable = getenv("E_WL_PROXY");
+   char *proxy_bin = NULL;
+   char fdbuf[16];
+   int rdy[2];
+   pid_t pid;
+   char c;
+   ssize_t n;
+
+   if (!enable || strcmp(enable, "1") != 0) return -1;
+
+   /* the name clients will use (default wayland-0), inherited by the session */
+   if (!getenv("WAYLAND_DISPLAY")) env_set("WAYLAND_DISPLAY", "wayland-0");
+   /* the private socket E will create and the proxy will connect to */
+   if (!getenv("E_WL_SOCKET")) env_set("E_WL_SOCKET", "wayland-e");
+   /* control socket the wl_proxy module connects to for WM-state mirroring */
+   if (!getenv("E_WL_PROXY_SOCK")) env_set("E_WL_PROXY_SOCK", "e_wl_proxy-0");
+
+   myasprintf(&proxy_bin, "%s/e_wl_proxy", eina_prefix_bin_get(pfx));
+
+   /* readiness pipe: the proxy writes a byte once its public socket is up, so
+    * we start E only after clients can actually connect (no startup race). */
+   if (pipe(rdy) != 0) return -1;
+
+   pid = fork();
+   if (pid < 0) { close(rdy[0]); close(rdy[1]); return -1; }
+   if (pid == 0)
+     {
+        /* die with enlightenment_start so the proxy never outlives the session */
+#ifdef HAVE_PRCTL
+        prctl(PR_SET_PDEATHSIG, SIGTERM);
+#elif defined(HAVE_PROCCTL)
+        int sig = SIGTERM;
+        procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &sig);
+#endif
+        close(rdy[0]);   /* child only writes */
+        snprintf(fdbuf, sizeof(fdbuf), "%d", rdy[1]);
+        env_set("E_WL_PROXY_READY_FD", fdbuf);
+        execl(proxy_bin, proxy_bin, (char *)NULL);
+        _exit(127);
+     }
+
+   /* parent: block until the proxy signals readiness (1 byte) or dies (EOF). */
+   close(rdy[1]);   /* parent only reads */
+   n = read(rdy[0], &c, 1);
+   close(rdy[0]);
+   if (n != 1)
+     {
+        fprintf(stderr, "e_wl_proxy did not come up; continuing without it\n");
+        waitpid(pid, NULL, WNOHANG);   /* reap if it already exited */
+        return -1;
+     }
+
+   return pid;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -730,6 +792,9 @@ main(int argc, char **argv)
        args[argc] = NULL;
      }
 
+   /* start the wayland proxy (if enabled) before the restart loop, so it
+    * persists across E restarts and keeps clients alive across an E crash. */
+   _e_wl_proxy_start();
 
    /* Now looping until */
    while (restart)
diff --git a/src/bin/e_win.c b/src/bin/e_win.c
index 0c56afdbc..108383d9f 100644
--- a/src/bin/e_win.c
+++ b/src/bin/e_win.c
@@ -510,16 +510,45 @@ e_win_no_reopen_set(Evas_Object *obj, Eina_Bool no_reopen)
      ctx->client->internal_no_reopen = !!no_reopen;
 }
 
+/* Internal windows (E's own dialogs/menus/popups) must connect to E directly,
+ * not via e_wl_proxy: a forwarded connection makes their peer credentials read
+ * as the proxy's pid, so E fails the pid==getpid() internal test and the
+ * internal_elm_win machinery (which assumes a direct connection) desyncs. Point
+ * the elm connect at the private backend socket (E_WL_SOCKET) for its duration;
+ * externally spawned apps keep the proxy's public WAYLAND_DISPLAY and still get
+ * crash recovery. No-op when not running behind the proxy. */
+static char *
+_e_win_disp_to_backend(void)
+{
+   const char *be = getenv("E_WL_SOCKET");
+   char *saved;
+
+   if (!be) return NULL;
+   saved = eina_strdup(getenv("WAYLAND_DISPLAY"));
+   e_util_env_set("WAYLAND_DISPLAY", be);
+   return saved;
+}
+
+static void
+_e_win_disp_restore(char *saved)
+{
+   if (!getenv("E_WL_SOCKET")) return;
+   e_util_env_set("WAYLAND_DISPLAY", saved);
+   free(saved);
+}
+
 E_API Evas_Object *
 e_elm_win_add(Evas_Object *parent, const char *name, Elm_Win_Type type)
 {
-   char *eng;
+   char *eng, *wld;
    Evas_Object *o;
 
    if (type == ELM_WIN_INLINED_IMAGE) return elm_win_add(parent, name, type);
    eng = eina_strdup(getenv("ELM_ACCEL"));
    e_util_env_set("ELM_ACCEL", "none");
+   wld = _e_win_disp_to_backend();
    o = elm_win_add(parent, name, type);
+   _e_win_disp_restore(wld);
    e_util_env_set("ELM_ACCEL", eng);
    elm_win_alpha_set(o, 1);
    free(eng);
@@ -529,12 +558,14 @@ e_elm_win_add(Evas_Object *parent, const char *name, Elm_Win_Type type)
 E_API Evas_Object *
 e_elm_win_util_standard_add(const char *name, const char *title)
 {
-   char *eng;
+   char *eng, *wld;
    Evas_Object *o;
 
    eng = eina_strdup(getenv("ELM_ACCEL"));
    e_util_env_set("ELM_ACCEL", "none");
+   wld = _e_win_disp_to_backend();
    o = elm_win_util_standard_add(name, title);
+   _e_win_disp_restore(wld);
    e_util_env_set("ELM_ACCEL", eng);
    elm_win_alpha_set(o, 1);
    free(eng);
@@ -544,12 +575,14 @@ e_elm_win_util_standard_add(const char *name, const char *title)
 E_API Evas_Object *
 e_elm_win_util_dialog_add(Evas_Object *parent, const char *name, const char *title)
 {
-   char *eng;
+   char *eng, *wld;
    Evas_Object *o;
 
    eng = eina_strdup(getenv("ELM_ACCEL"));
    e_util_env_set("ELM_ACCEL", "none");
+   wld = _e_win_disp_to_backend();
    o = elm_win_util_dialog_add(parent, name, title);
+   _e_win_disp_restore(wld);
    e_util_env_set("ELM_ACCEL", eng);
    elm_win_alpha_set(o, 1);
    free(eng);

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

Reply via email to