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 722c92cd9276546a6b0fe026e63354729469cd98
Author: Cedric BAIL <[email protected]>
AuthorDate: Tue Aug 11 00:00:05 2026 -0600

    e_comp_wl - an unmapped surface must be transparent, not just deaf
    
    Input aimed at a window sitting under an unmapped surface reached nothing
    at all. Two separate reasons, and the first has been hiding in a comment
    claiming the opposite since 494453e5d.
    
    Freezing events is not the same as passing them through. Evas leaves a
    frozen object out of the list of objects under the pointer and then ends
    the walk anyway, because the object is still there and still opaque to
    events - see the no_rep assignment right after the freezes_through test in
    evas_events.c. So freezing an unmapped surface does stop it answering, and
    stops everything beneath it answering too. evas_event_passes_through is
    tested earlier, before the geometry, and lets the walk carry on down.
    
    The second is that a sub-surface is its own client with its own frame. A
    parent that has gone quiet says nothing about its children: they sit on
    the canvas in their own right and go on taking input for a surface tree
    the client has unmapped. Walk the tree instead and give each surface the
    state it has earned - transparent when it is unmapped or when anything it
    hangs off is. On the way back up, that walk has to run after mapped is set
    rather than before, since it reads it, and a sub-surface still unmapped in
    its own right stays transparent even when its parent maps.
    
    wlcs: 649 passed -> 691, no regressions. SurfaceInputRegions goes from 40
    failures to 4, and six ToplevelInputRegions cases that were never on the
    list come with it - a toplevel unmapped by committing a null buffer is the
    same bug seen from a different suite.
    
    The 4 left are input_seen_after_surface_unmapped_and_remapped and its
    subsurface twin, and only for the one builder that sets a window geometry
    offset. Those are the offset being applied a second time on remap, not an
    unmap problem.
---
 src/bin/e_comp_wl.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 56 insertions(+), 4 deletions(-)

diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c
index 935b62b8f..877b3b2e7 100644
--- a/src/bin/e_comp_wl.c
+++ b/src/bin/e_comp_wl.c
@@ -1502,6 +1502,42 @@ _e_comp_wl_surface_state_attach(E_Client *ec, E_Comp_Wl_Surface_State *state)
    e_pixmap_refresh(ec->pixmap);
 }
 
+/* A sub-surface is its own client with its own frame, so a parent that stops
+ * taking input says nothing about its children - they sit on the canvas in
+ * their own right and go on answering for a surface tree the client has
+ * unmapped. Push the state down: a surface is transparent to input when it is
+ * unmapped or when anything it hangs off is. */
+static Eina_Bool
+_e_comp_wl_surface_ancestor_unmapped(E_Client *ec)
+{
+   E_Comp_Wl_Subsurf_Data *sdata;
+
+   while (ec->comp_data && (sdata = ec->comp_data->sub.data) && sdata->parent)
+     {
+        ec = sdata->parent;
+        if (!ec->comp_data) return EINA_FALSE;
+        if (!ec->comp_data->mapped) return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+static void
+_e_comp_wl_surface_input_passthrough_update(E_Client *ec, Eina_Bool parent_unmapped)
+{
+   E_Client *subc;
+   Eina_List *l;
+   Eina_Bool unmapped;
+
+   if (!ec->comp_data) return;
+
+   unmapped = parent_unmapped || (!ec->comp_data->mapped);
+   evas_object_pass_events_set(ec->frame, unmapped);
+
+   EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
+     if (subc != ec) _e_comp_wl_surface_input_passthrough_update(subc, unmapped);
+}
+
 static void
 _e_comp_wl_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state)
 {
@@ -1662,7 +1698,7 @@ _e_comp_wl_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state)
               * pointer, and still being handed input for a surface the client
               * has already unmapped.
               *
-              * Freezing events stops the delivery without touching the
+              * Passing events through stops the delivery without touching the
               * animation - the window still fades out, it just stops
               * answering. Evas tests this up the smart parent chain, so it
               * also covers the input-region rectangles parented to the frame;
@@ -1670,10 +1706,21 @@ _e_comp_wl_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state)
               * input through cw->obj, where clearing the region would have
               * done nothing.
               *
-              * Thawed on map, below. */
+              * Freezing events looks like the way to say this, and is not.
+              * Frozen and pass-through are not two spellings of one idea:
+              * evas leaves a frozen object out of the list of things under
+              * the pointer and then ends the walk anyway, since as far as it
+              * is concerned the object is still there and still opaque to
+              * events. So freezing silences this surface and blinds every
+              * surface beneath it, and input aimed at the window below lands
+              * nowhere at all. pass_events is tested earlier, before the
+              * geometry, and lets the walk carry on down.
+              *
+              * Undone on map, below. */
              if (!ec->comp_data->mapped)
                {
-                  evas_object_freeze_events_set(ec->frame, 1);
+                  _e_comp_wl_surface_input_passthrough_update(ec,
+                     _e_comp_wl_surface_ancestor_unmapped(ec));
                   /* And tell the client the pointer has left, while its
                    * surface is still around to be named. Without this the
                    * seat goes on believing the pointer is inside a surface
@@ -1688,7 +1735,6 @@ _e_comp_wl_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state)
      {
         if (!ec->comp_data->mapped)
           {
-             evas_object_freeze_events_set(ec->frame, 0);
              if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.map))
                ec->comp_data->shell.map(ec->comp_data->shell.surface);
              else if ((ec == e_comp->pointer->client.ec) || e_client_has_xwindow(ec) || ec->internal_elm_win ||
@@ -1705,6 +1751,12 @@ _e_comp_wl_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state)
                          evas_object_hide(ec->frame);
                     }
                }
+
+             /* After mapped is set, not before: the walk reads it. A
+              * sub-surface that is still unmapped in its own right stays
+              * transparent even though we have just mapped its parent. */
+             _e_comp_wl_surface_input_passthrough_update(ec,
+                _e_comp_wl_surface_ancestor_unmapped(ec));
           }
      }
 

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

Reply via email to