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

git pushed a commit to branch wl/browser-all
in repository enlightenment.

View the commit online.

commit 2e4ae105337b99a8187ebb21fb41393abd04437e
Author: Cedric BAIL <[email protected]>
AuthorDate: Wed Aug 19 21:15:30 2026 -0600

    e_utils - suppress test dialogs at the funnel, not at one caller
    
    A test session has nobody to read a dialog, and a window appearing
    unbidden takes the keyboard focus off whatever the test is driving.
    That is not cosmetic: every assertion after it is about the wrong
    window, and the failure names something unrelated. It cost a run of the
    input-method tests, which reported that their own window "did not take
    keyboard focus" while an error dialog sat on top holding it.
    
    E_TEST_NO_DIALOGS already existed. 7f0fffc91 honoured it in e_system.c,
    which covered the one dialog somebody had been bitten by - the
    enlightenment_system spawn failure - and nothing else. The dialog that
    stole focus came from somewhere else, and a per-caller guard covers
    exactly the callers someone remembered.
    
    Every error dialog in E arrives through e_util_dialog_internal;
    e_util_dialog_show is a macro over it. So the guard goes there and one
    check covers all of them.
    
    **The message is not dropped, it moves.** A test session's channel for
    "something went wrong" is the compositor log, which run-nested.sh prints
    on failure, so what a person would have read in the dialog is still in
    front of whoever is debugging - and it names itself, which is how the
    next one will be identified without a bisect. Suppressing a fault report
    silently would be hiding it; relocating it is not.
    
    The guard in e_system.c stays. It is no longer load-bearing, but it also
    stops the five-second timer being armed at all, which beats arming it in
    order to log a line five seconds later.
    
    The test raises a dialog from real compositor code rather than something
    invented: E's own window_focus action, given a direction that does not
    exist, calls e_util_dialog_show with an "Invalid parameter" message, and
    wl_test.client_action can reach it. It then checks both halves - no
    window with the _error_dialog app_id, and the test's own window still
    focused, which is the property everything else depends on.
    
    Removing the guard makes it fail and names the dialog exactly: "an error
    dialog appeared (app_id '_error_dialog', title 'Error: window_focus
    action', 215x125+404+332)". Checked against a build with it removed.
    
    Measured: full wlcs 780 passed / 14 failed, failure set identical to
    d63249c9d. In-tree 38 -> 39.
---
 src/bin/e_system.c                  |   6 ++-
 src/bin/e_utils.c                   |  25 +++++++++
 src/tests/wayland/meson.build       |   1 +
 src/tests/wayland/test_no_dialogs.c | 103 ++++++++++++++++++++++++++++++++++++
 4 files changed, 133 insertions(+), 2 deletions(-)

diff --git a/src/bin/e_system.c b/src/bin/e_system.c
index e48da038f..bf627c4eb 100644
--- a/src/bin/e_system.c
+++ b/src/bin/e_system.c
@@ -119,8 +119,10 @@ static void
 _system_spawn_error(int exit_code)
 {
 #ifdef E_TESTS
-   /* a test compositor has nobody to read a dialog, and a window appearing
-    * unbidden takes the focus off whatever the test is driving */
+   /* Not the only guard any more, and no longer the load-bearing one: every
+    * dialog is suppressed centrally in e_util_dialog_internal. This one stays
+    * because it also stops the five-second timer being armed at all, which is
+    * cheaper than arming it in order to log a line five seconds later. */
    if (getenv("E_TEST_NO_DIALOGS")) return;
 #endif
    if (_error_dialog_timer) ecore_timer_del(_error_dialog_timer);
diff --git a/src/bin/e_utils.c b/src/bin/e_utils.c
index 4b34abba9..20da6bbb8 100644
--- a/src/bin/e_utils.c
+++ b/src/bin/e_utils.c
@@ -393,6 +393,31 @@ e_util_dialog_internal(const char *title, const char *txt)
 {
    E_Dialog *dia;
 
+#ifdef E_TESTS
+   /* A test session has nobody to read a dialog, and a window appearing
+    * unbidden takes the focus off whatever the test is driving - which is not
+    * cosmetic: every assertion after it is then about the wrong window, and
+    * the failure names something unrelated.
+    *
+    * The guard belongs here rather than at a call site. Every error dialog E
+    * raises arrives through this function - e_util_dialog_show is a macro over
+    * it - so one check covers all of them, where a per-caller check covers
+    * exactly the caller someone remembered. 7f0fffc91 put one in e_system.c
+    * and it is why the enlightenment_system dialog is quiet; the dialog that
+    * stole focus from an input-method test came from somewhere else.
+    *
+    * The message is not dropped, it moves. A test session's channel for
+    * "something went wrong" is the compositor log, which run-nested.sh prints
+    * on failure - so what a person would have read in the dialog is still in
+    * front of whoever is debugging, and it names itself. Suppressing it
+    * silently would be hiding a fault; relocating it is not. */
+   if (getenv("E_TEST_NO_DIALOGS"))
+     {
+        ERR("E_TEST_NO_DIALOGS: suppressed dialog: '%s': %s", title, txt);
+        return NULL;
+     }
+#endif
+
    dia = e_dialog_new(NULL, "E", "_error_dialog");
    if (!dia) return NULL;
    e_dialog_title_set(dia, title);
diff --git a/src/tests/wayland/meson.build b/src/tests/wayland/meson.build
index 4579a5b27..190cffa51 100644
--- a/src/tests/wayland/meson.build
+++ b/src/tests/wayland/meson.build
@@ -99,6 +99,7 @@ wl_protocol_tests = [
   ['text-input', 'test_text_input.c'],
   ['input-method-keyboard', 'test_input_method_keyboard.c'],
   ['input-popup', 'test_input_popup.c'],
+  ['no-dialogs', 'test_no_dialogs.c'],
 ]
 
 # Shared plumbing: registry binding, toplevel construction, enumeration and a
diff --git a/src/tests/wayland/test_no_dialogs.c b/src/tests/wayland/test_no_dialogs.c
new file mode 100644
index 000000000..3ccef67f0
--- /dev/null
+++ b/src/tests/wayland/test_no_dialogs.c
@@ -0,0 +1,103 @@
+/* A test session must never be shown a dialog.
+ *
+ * There is nobody to read one, and a window appearing unbidden takes the
+ * keyboard focus off whatever the test is driving. That is not a cosmetic
+ * problem: every assertion after it is about the wrong window, and the failure
+ * names something unrelated to the actual fault. It cost a run of the
+ * input-method tests before this existed - a dialog won the focus race and the
+ * test reported that its own window "did not take keyboard focus".
+ *
+ * E_TEST_NO_DIALOGS is the switch, set by run-nested.sh and by the wlcs
+ * driver. It used to be honoured at one call site, in e_system.c, which
+ * covered the one dialog somebody had been bitten by and nothing else. It is
+ * now honoured in e_util_dialog_internal, which every error dialog in E goes
+ * through - e_util_dialog_show is a macro over it.
+ *
+ * The trigger here is E's own window_focus action given a direction that does
+ * not exist. That path calls e_util_dialog_show with an "Invalid parameter"
+ * message, which makes it a real dialog raised by real compositor code rather
+ * than something invented for the test. Any other dialog would do; this one is
+ * reachable from wl_test.client_action, which is what makes it usable.
+ *
+ * The suppressed message is not lost - it goes to the compositor log, which
+ * run-nested.sh prints on failure. This test cannot check that from the client
+ * side, so it checks the part a client can see: no window.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "e_wl_testkit.h"
+
+#define PROG "test-no-dialogs"
+
+/* The name every error dialog is created with - e_dialog_new(NULL, "E",
+ * "_error_dialog") in e_util_dialog_internal - and what E reports as the
+ * window's app_id. */
+#define DIALOG_APP_ID "_error_dialog"
+
+static Tk_Client *
+_dialog_window(Tk *tk)
+{
+   static Tk_Client all[TK_MAX_CLIENTS];
+   int n, i;
+
+   n = tk_clients(tk, all, TK_MAX_CLIENTS);
+   for (i = 0; i < n; i++)
+     if (!strcmp(all[i].app_id, DIALOG_APP_ID)) return &all[i];
+   return NULL;
+}
+
+int
+main(void)
+{
+   Tk *tk;
+   Tk_Toplevel *top;
+   Tk_Client *c, *dia;
+   unsigned int id;
+   int i;
+
+   tk = tk_connect(PROG);
+
+   top = tk_toplevel_new(tk, "no-dialogs", "no dialogs", 200, 200);
+   tk_settle(tk);
+   c = tk_expect(tk, "no-dialogs");
+   id = c->id;
+
+   if (_dialog_window(tk))
+     tk_fail(tk, "a dialog was already on screen before this test did "
+                 "anything - something raised one during startup, which is "
+                 "the case E_TEST_NO_DIALOGS exists for");
+
+   /* Raise one, from compositor code, through the ordinary path. */
+   tk_action(tk, id, "window_focus", "no-such-direction");
+   tk_settle(tk);
+
+   /* Dialogs are built and shown from the main loop, so give it several
+    * iterations rather than one before concluding nothing appeared. */
+   for (i = 0; i < 10; i++)
+     {
+        dia = _dialog_window(tk);
+        if (dia)
+          tk_fail(tk, "an error dialog appeared (app_id '%s', title '%s', "
+                      "%dx%d+%d+%d) with E_TEST_NO_DIALOGS set. It is honoured "
+                      "in e_util_dialog_internal, which every dialog in E goes "
+                      "through - if this one got past, it was built some other "
+                      "way and that path needs the same guard",
+                  dia->app_id, dia->title, dia->w, dia->h, dia->x, dia->y);
+        tk_sync(tk);
+     }
+
+   /* The harm a dialog does, checked directly: focus stays where the test put
+    * it. A dialog that appeared and did *not* take focus would still be wrong,
+    * but this is the property everything else depends on. */
+   c = tk_expect(tk, "no-dialogs");
+   if (!(c->states & WL_TEST_CLIENT_STATE_FOCUSED))
+     tk_fail(tk, "the test's own window lost focus after an action that would "
+                 "have raised a dialog");
+
+   printf(PROG ": ok - no dialog, focus undisturbed\n");
+
+   tk_disconnect(tk);
+   return 0;
+}

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

Reply via email to