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 7bb7a8bf9132967c532d4f92c294a08532a74118
Merge: 81a94fc14 ddaa2e0d8
Author: Cedric BAIL <[email protected]>
AuthorDate: Tue Aug 18 18:31:51 2026 -0600
Merge branch 'wl/test-ecore-input' into wl/browser-all
Resolved by deleting what the rework subsumes. Five hand-written
replications had accumulated in wl_test, each added when a feature turned
out to be unreachable from the canvas half of an input event: relative
pointer motion and pointer constraints (E-20), the screensaver idle timer
(E-09), xdg_popup grab dismissal, and the whole _pointer_motion helper
they lived in.
All five now happen because E's own ecore handlers run, which is the
point of the branch. Keeping them alongside would have fired each twice
and left the harness still carrying a copy of E's input routing.
In-tree 25/26 on the first run: every protocol, gl and x11 test green,
browser-brave failed with an E startup error dialog stealing focus mid
resize and then passed three times in a row on its own. That is the known
dialog flake, not this change.
src/modules/wl_test/e_mod_main.c | 224 ++++++++++++++++++++++++++-------------
1 file changed, 148 insertions(+), 76 deletions(-)
diff --cc src/modules/wl_test/e_mod_main.c
index aa6f531da,3c6457d5b..0f321a4e3
--- a/src/modules/wl_test/e_mod_main.c
+++ b/src/modules/wl_test/e_mod_main.c
@@@ -300,135 -124,93 +300,164 @@@ _wl_test_cb_zone_add(struct wl_client *
ERR("wl_test: could not create wl_output for zone %d", num);
}
+ /* Input goes in the way the backends put it in: as an ecore event.
+ *
+ * The obvious shortcut is to feed evas directly, and this harness did that for
+ * a long time. It works for anything that reads input through an evas callback
+ * on a client's frame object, which is most of what a Wayland client sees -
+ * and it silently misses everything E does on the *ecore* half of the same
+ * event. That half is not small: relative pointer motion, pointer constraints,
+ * the screensaver's idle timer, key bindings, and drag-and-drop all hang off
+ * ECORE_EVENT_MOUSE_* / ECORE_EVENT_KEY_* handlers and never saw a thing.
+ *
+ * Four features hit that gap one at a time - E-20, E-09, E-12, E-15 - and each
+ * was patched by having the harness call, by hand, whatever the ecore handler
+ * would have called. That works until the fifth, and it means the harness has
+ * its own growing copy of E's input routing which can drift from the real one
+ * without any test noticing. This is the fix the plan called overdue: post the
+ * event, and let E's own handlers run.
+ *
+ * `window` is e_comp->ee_win because that is what the compositor's own code
+ * compares against - e_dnd's _drag_win, for one - and an event on any other
+ * window is skipped by exactly the handlers this exists to reach.
+ */
+ static unsigned int
+ _input_timestamp(void)
+ {
+ /* ecore timestamps are milliseconds and only ever compared with each
+ * other, so any monotonic source will do. */
+ return (unsigned int)(ecore_time_get() * 1000.0);
+ }
+
+ static void
+ _pointer_ecore_move(int x, int y)
+ {
+ Ecore_Event_Mouse_Move *ev;
+
+ ev = calloc(1, sizeof(*ev));
+ if (!ev) return;
+
+ ev->window = e_comp->ee_win;
+ ev->event_window = e_comp->ee_win;
+ ev->root_window = e_comp->ee_win;
+ ev->timestamp = _input_timestamp();
+ ev->same_screen = 1;
+ ev->x = ev->root.x = x;
+ ev->y = ev->root.y = y;
+ ev->multi.x = ev->multi.root.x = x;
+ ev->multi.y = ev->multi.root.y = y;
+ ev->multi.radius = 1;
+ ev->multi.radius_x = 1;
+ ev->multi.radius_y = 1;
+ ev->multi.pressure = 1.0;
+
+ ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL);
+ }
+
+ static void
+ _pointer_ecore_button(int b, int pressed, int x, int y)
+ {
+ Ecore_Event_Mouse_Button *ev;
+
+ ev = calloc(1, sizeof(*ev));
+ if (!ev) return;
+
+ ev->window = e_comp->ee_win;
+ ev->event_window = e_comp->ee_win;
+ ev->root_window = e_comp->ee_win;
+ ev->timestamp = _input_timestamp();
+ ev->same_screen = 1;
+ ev->buttons = b;
+ ev->x = ev->root.x = x;
+ ev->y = ev->root.y = y;
+ ev->multi.x = ev->multi.root.x = x;
+ ev->multi.y = ev->multi.root.y = y;
+ ev->multi.radius = 1;
+ ev->multi.radius_x = 1;
+ ev->multi.radius_y = 1;
+ ev->multi.pressure = 1.0;
+
+ ecore_event_add(pressed ? ECORE_EVENT_MOUSE_BUTTON_DOWN
+ : ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
+ }
+
+static void
+_wl_test_cb_screensaver_enable(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, uint32_t enable, uint32_t timeout)
+{
+ e_config->screensaver_enable = !!enable;
+ e_config->screensaver_timeout = (int)timeout;
+ /* Re-arm from the new configuration, the way changing it in the settings
+ * dialog would. */
+ e_comp_wl_notidle();
+}
+
+static void
+_wl_test_cb_get_idle_inhibit(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+ wl_test_send_idle_inhibit(resource, !!e_comp_wl_idle_inhibited_get());
+}
+
+static void
+_wl_test_cb_output_scale_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, uint32_t index, int32_t scale)
+{
+ E_Comp_Wl_Output *output;
+ struct wl_resource *res;
+ Eina_List *l;
+
+ if (scale < 1)
+ {
+ ERR("wl_test: output scale must be at least 1, got %d", scale);
+ return;
+ }
+
+ output = eina_list_nth(e_comp_wl->outputs, index);
+ if (!output)
+ {
+ ERR("wl_test: no output %u to scale", index);
+ return;
+ }
+
+ output->scale = scale;
+
+ /* Tell whoever is already bound, the way a real scale change would. A
+ * client that never asked about outputs is unaffected, which is correct -
+ * the compositor's own idea of the scale has changed either way, and that
+ * is what surface sizing reads. */
+ EINA_LIST_FOREACH(output->resources, l, res)
+ {
+ if (wl_resource_get_version(res) < WL_OUTPUT_SCALE_SINCE_VERSION)
+ continue;
+ wl_output_send_scale(res, scale);
+ if (wl_resource_get_version(res) >= WL_OUTPUT_DONE_SINCE_VERSION)
+ wl_output_send_done(res);
+ }
+}
+
+/* Where the pointer is, asked of E rather than remembered here. A module-side
+ * tally is only right while nothing but this module moves the pointer, and a
+ * constraint does: once one has held the pointer at an edge, E's answer and
+ * the caller's arithmetic have parted company, and E's is the true one. */
+static void
+_pointer_xy_get(int *x, int *y)
+{
+ evas_pointer_canvas_xy_get(e_comp->evas, x, y);
+}
+
- static void
- _pointer_motion(int x, int y)
- {
- E_Client *focused;
- int px, py;
-
- _pointer_xy_get(&px, &py);
-
- /* Feeding evas delivers to the client: E's wayland pointer handlers are
- * evas callbacks on the client's frame object, so a synthesised evas event
- * reaches the client exactly as a real one would. No uinput, no libinput,
- * no seat. It is not the whole story for buttons - see below - and it is
- * not the whole story for motion either.
- *
- * A real session hands motion to ecore first, and E hangs two protocols off
- * that half in _e_comp_cb_mouse_move() (e_comp_canvas.c): relative-pointer
- * and pointer-constraints. Neither is reachable from the canvas, so with
- * only the evas feed a locked pointer never locks, a confined one never
- * confines, and relative motion is never reported - which reads from the
- * outside exactly like a protocol nobody implemented. It is implemented;
- * the harness was talking to the wrong half of E.
- *
- * Same shape as the button case below, so the same remedy: call what the
- * manager would have called, in the order it would have called it. */
- focused = e_client_focused_get();
- if (focused && (!e_comp_util_mouse_grabbed()) && ((x != px) || (y != py)))
- {
- /* Unaccelerated equals accelerated here: there is no pointer
- * acceleration in front of synthesised input, so reporting 0 for the
- * unaccelerated pair was not "unknown", it was wrong. */
- if ((!e_comp->screen) || (!e_comp->screen->relative_motion))
- e_comp_wl_extension_relative_motion_event(ecore_time_unix_get() * 1000ULL,
- x - px, y - py, x - px, y - py);
-
- /* A constraint that swallows the motion has already warped the pointer
- * somewhere of its own choosing, and the canvas must not then be told
- * it went where the caller asked. The real handler answers
- * ECORE_CALLBACK_CANCEL at this point for the same reason. */
- if (e_comp_wl_extension_pointer_constraints_update(focused, x, y))
- return;
- }
-
- /* A third thing hangs off that same ecore half: the screensaver's idle
- * timer, re-armed from _e_comp_wl_cb_mouse_move. Without this the harness
- * can move the pointer all day and E never counts it as activity, so
- * anything about idling - inhibitors above all - reads as working whether
- * or not it does. */
- e_comp_canvas_notidle();
-
- evas_event_feed_mouse_move(e_comp->evas, x, y, 0, NULL);
- }
-
static void
_wl_test_cb_pointer_warp(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, int32_t x, int32_t y)
{
- _pointer_motion(x, y);
+ _pointer_ecore_move(x, y);
}
+static void
+_wl_test_cb_pointer_move(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, int32_t dx, int32_t dy)
+{
+ int px, py;
+
+ _pointer_xy_get(&px, &py);
- _pointer_motion(px + dx, py + dy);
++ _pointer_ecore_move(px + dx, py + dy);
+}
+
static void
_wl_test_cb_pointer_button(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, uint32_t button, uint32_t pressed)
{
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.