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 bc22568e552555e8f4ec5cfa080ca4f6a9bcda93
Author: Cedric BAIL <[email protected]>
AuthorDate: Tue Aug 11 16:40:53 2026 -0600
e_comp_wl - activate a pointer constraint without waiting for motion
E only ever evaluated pointer constraints from the motion path:
_e_comp_cb_mouse_move() is the sole caller of
e_comp_wl_extension_pointer_constraints_update() in the tree. So a lock
taken while the pointer was already sitting inside a focused surface was
never activated and never announced - and that is not an edge case, it is
the normal one. A client locks the pointer precisely *because* the pointer
is already where it wants it; Chromium and Firefox both take pointer lock
on a click in the content area, with the pointer stationary.
Nothing has to move for the answer to change, so evaluate it in the three
places where it can: creating the constraint, committing one, and the
surface gaining the focus. The last of those was missing entirely - grep
found no focus-change hook touching constraints anywhere - which is also
why half the protocol was unimplemented in the other direction: a
constraint has to deactivate when its surface loses the pointer, and a
oneshot one is defunct from then on, so only a persistent one may be
activated again. Hence the dead flag.
Worth being precise about where this does *not* go: an earlier attempt put
the activation pass at the end of pointer_constraints_commit() alone, and
measured nothing at all. Instrumenting says why - the client commits its
surface and only then asks for the lock, and never commits again, so under
test that hook is never reached after a constraint exists. Creation is
where it has to happen.
wlcs PointerConstraints+RelativePointer: 8 passed -> 14.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01W6z4GbxmqypzCzUHPwzFMd
---
src/bin/e_comp_wl_extensions.c | 94 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 90 insertions(+), 4 deletions(-)
diff --git a/src/bin/e_comp_wl_extensions.c b/src/bin/e_comp_wl_extensions.c
index 7de8de268..ec1099276 100644
--- a/src/bin/e_comp_wl_extensions.c
+++ b/src/bin/e_comp_wl_extensions.c
@@ -40,10 +40,86 @@ typedef struct Constraint
Eina_Bool lock E_BITFIELD; // if not lock, confine
Eina_Bool persistent E_BITFIELD;
Eina_Bool active E_BITFIELD;
+ Eina_Bool dead E_BITFIELD; // oneshot, already deactivated once
} Constraint;
static Eina_List *active_constraints;
+static Eina_Bool _inside_tiler(Eina_Tiler *r, Eina_Bool active, int x, int y, int px, int py, int *ax, int *ay);
+
+/* A constraint becomes active when its surface holds the focus and the pointer
+ * is already inside it, and nothing has to move for that to become true: a
+ * client locks the pointer precisely *because* the pointer is already sitting
+ * where it wants it, which is what both browsers do on a click in the content
+ * area. So the motion path cannot be the only thing that evaluates this - it
+ * was, and a lock taken over a stationary pointer was simply never announced.
+ *
+ * Called from the places where the answer can change without motion: creating
+ * the constraint, committing one, and the surface gaining the focus. */
+static void
+_constraints_activate(E_Client *ec)
+{
+ Eina_List *l;
+ Constraint *c;
+ int px, py;
+
+ if ((!ec) || (!ec->comp_data) || (!ec->frame)) return;
+ if (ec != e_client_focused_get()) return;
+ evas_pointer_canvas_xy_get(e_comp->evas, &px, &py);
+ if (!e_comp_object_coords_inside_input_area(ec->frame, px, py)) return;
+
+ EINA_LIST_FOREACH(ec->comp_data->constraints, l, c)
+ {
+ int ax = 0, ay = 0;
+
+ if (c->active || c->dead) continue;
+ if (!_inside_tiler(c->region, EINA_FALSE, px - ec->client.x, py - ec->client.y,
+ px - ec->client.x, py - ec->client.y, &ax, &ay))
+ continue;
+ c->active = 1;
+ active_constraints = eina_list_append(active_constraints, c);
+ if (c->lock)
+ zwp_locked_pointer_v1_send_locked(c->res);
+ else
+ zwp_confined_pointer_v1_send_confined(c->res);
+ }
+}
+
+/* The protocol requires a constraint to deactivate when its surface stops
+ * being the one the pointer is directed at, and a oneshot constraint is
+ * defunct from then on - only a persistent one may be activated again. */
+static void
+_constraints_deactivate(E_Client *ec)
+{
+ Eina_List *l;
+ Constraint *c;
+
+ if ((!ec) || (!ec->comp_data)) return;
+ EINA_LIST_FOREACH(ec->comp_data->constraints, l, c)
+ {
+ if (!c->active) continue;
+ c->active = 0;
+ if (!c->persistent) c->dead = 1;
+ active_constraints = eina_list_remove(active_constraints, c);
+ if (c->lock)
+ zwp_locked_pointer_v1_send_unlocked(c->res);
+ else
+ zwp_confined_pointer_v1_send_unconfined(c->res);
+ }
+}
+
+static void
+_e_comp_wl_extensions_client_focus_set(void *d EINA_UNUSED, E_Client *ec)
+{
+ _constraints_activate(ec);
+}
+
+static void
+_e_comp_wl_extensions_client_focus_unset(void *d EINA_UNUSED, E_Client *ec)
+{
+ _constraints_deactivate(ec);
+}
+
static void
_e_comp_wl_extensions_client_move_begin(void *d EINA_UNUSED, E_Client *ec)
{
@@ -494,15 +570,20 @@ _e_comp_wl_zwp_pointer_constraints_v1_lock_pointer(struct wl_client *client, str
c = do_constraint(&zwp_locked_pointer_v1_interface, &_e_comp_wl_locked_pointer_v1_interface,
client, resource, id, surface, pointer, region, lifetime);
- if (c)
- c->lock = 1;
+ if (!c) return;
+ c->lock = 1;
+ _constraints_activate(c->ec);
}
static void
_e_comp_wl_zwp_pointer_constraints_v1_confine_pointer(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface, struct wl_resource *pointer, struct wl_resource *region, uint32_t lifetime)
{
- do_constraint(&zwp_confined_pointer_v1_interface, &_e_comp_wl_confined_pointer_v1_interface,
+ Constraint *c;
+
+ c = do_constraint(&zwp_confined_pointer_v1_interface, &_e_comp_wl_confined_pointer_v1_interface,
client, resource, id, surface, pointer, region, lifetime);
+ if (c)
+ _constraints_activate(c->ec);
}
/////////////////////////////////////////////////////////
@@ -1021,6 +1102,9 @@ e_comp_wl_extensions_init(void)
e_client_hook_add(E_CLIENT_HOOK_MOVE_BEGIN, _e_comp_wl_extensions_client_move_begin, NULL);
e_client_hook_add(E_CLIENT_HOOK_MOVE_END, _e_comp_wl_extensions_client_move_end, NULL);
+ e_client_hook_add(E_CLIENT_HOOK_FOCUS_SET, _e_comp_wl_extensions_client_focus_set, NULL);
+ e_client_hook_add(E_CLIENT_HOOK_FOCUS_UNSET, _e_comp_wl_extensions_client_focus_unset, NULL);
+
act = e_action_add("key_route");
act->func.go_key = _e_comp_wl_action_route_act_key_route_go;
act->func.end_key = _e_comp_wl_action_route_act_key_route_go_end;
@@ -1079,6 +1163,8 @@ e_comp_wl_extension_pointer_constraints_commit(E_Client *ec)
c->pending_xy = NULL;
}
}
+ /* a newly committed region can be what makes a constraint eligible */
+ _constraints_activate(ec);
}
static Eina_Bool
@@ -1211,7 +1297,7 @@ e_comp_wl_extension_pointer_constraints_update(E_Client *ec, int x, int y)
int ax = px - ec->client.x, ay = py - ec->client.y;
Eina_Bool inside_region = _inside_tiler(c->region, c->active, x - ec->client.x, y - ec->client.y,
px - ec->client.x, py - ec->client.y, &ax, &ay);
- if ((!c->active) && inside && inside_region)
+ if ((!c->active) && (!c->dead) && inside && inside_region)
{
c->active = 1;
active_constraints = eina_list_append(active_constraints, c);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.