]> git.mdlowis.com Git - proto/labwc.git/commitdiff
xwayland: connect commit and surface_destroy handlers together
authorJohn Lindgren <john@jlindgren.net>
Sat, 8 Nov 2025 03:20:18 +0000 (22:20 -0500)
committerJohan Malm <johanmalm@users.noreply.github.com>
Sun, 9 Nov 2025 18:27:39 +0000 (18:27 +0000)
Factor out set_surface() which consolidates connecting/disconnecting
the wlr_surface event listeners in one place.

In theory, this means we can receive commit events for minimized views.
However, with a test app that resizes itself, I didn't see any change,
i.e. the commits still don't come through until un-minimize. It's
possible they are being filtered at wlroots or protocol level.

Also remove an old, semi-related TODO from view.c.

src/view.c
src/xwayland.c

index f0b053a48888e487a7f45829730dd130a596f518..45e9fc4516ed3fea536892c927da75df12a836a5 100644 (file)
@@ -2479,11 +2479,6 @@ handle_unmap(struct wl_listener *listener, void *data)
        view->impl->unmap(view, /* client_request */ true);
 }
 
-/*
- * TODO: after the release of wlroots 0.17, consider incorporating this
- * function into a more general view_set_surface() function, which could
- * connect other surface event handlers (like commit) as well.
- */
 void
 view_connect_map(struct view *view, struct wlr_surface *surface)
 {
index 6b408a78ae0ac433e7fe8d70784e92554c7f43e1..1a1cc9b0666df76c01b5e29b4d7fbe1fff7c4a7e 100644 (file)
@@ -38,6 +38,7 @@ static_assert(ARRAY_SIZE(atom_names) == ATOM_COUNT, "atom names out of sync");
 
 static xcb_atom_t atoms[ATOM_COUNT] = {0};
 
+static void set_surface(struct view *view, struct wlr_surface *surface);
 static void xwayland_view_unmap(struct view *view, bool client_request);
 
 static struct xwayland_view *
@@ -332,8 +333,7 @@ handle_surface_destroy(struct wl_listener *listener, void *data)
        struct view *view = wl_container_of(listener, view, surface_destroy);
        assert(data && data == view->surface);
 
-       view->surface = NULL;
-       wl_list_remove(&view->surface_destroy.link);
+       set_surface(view, NULL);
 }
 
 static void
@@ -343,15 +343,7 @@ handle_destroy(struct wl_listener *listener, void *data)
        struct xwayland_view *xwayland_view = xwayland_view_from_view(view);
        assert(xwayland_view->xwayland_surface->data == view);
 
-       if (view->surface) {
-               /*
-                * We got the destroy signal from
-                * wlr_xwayland_surface before the
-                * destroy signal from wlr_surface.
-                */
-               wl_list_remove(&view->surface_destroy.link);
-       }
-       view->surface = NULL;
+       set_surface(view, NULL);
 
        /*
         * Break view <-> xsurface association.  Note that the xsurface
@@ -792,6 +784,24 @@ init_foreign_toplevel(struct view *view)
        foreign_toplevel_set_parent(view->foreign_toplevel, parent->foreign_toplevel);
 }
 
+static void
+set_surface(struct view *view, struct wlr_surface *surface)
+{
+       if (view->surface) {
+               /* Disconnect wlr_surface event listeners */
+               wl_list_remove(&view->commit.link);
+               wl_list_remove(&view->surface_destroy.link);
+       }
+       view->surface = surface;
+       if (surface) {
+               /* Connect wlr_surface event listeners */
+               view->commit.notify = handle_commit;
+               wl_signal_add(&surface->events.commit, &view->commit);
+               view->surface_destroy.notify = handle_surface_destroy;
+               wl_signal_add(&surface->events.destroy, &view->surface_destroy);
+       }
+}
+
 static void
 xwayland_view_map(struct view *view)
 {
@@ -826,14 +836,7 @@ xwayland_view_map(struct view *view)
        wlr_scene_node_set_enabled(&view->scene_tree->node, true);
 
        if (view->surface != xwayland_surface->surface) {
-               if (view->surface) {
-                       wl_list_remove(&view->surface_destroy.link);
-               }
-               view->surface = xwayland_surface->surface;
-
-               /* Required to set the surface to NULL when destroyed by the client */
-               view->surface_destroy.notify = handle_surface_destroy;
-               wl_signal_add(&view->surface->events.destroy, &view->surface_destroy);
+               set_surface(view, xwayland_surface->surface);
 
                /* Will be free'd automatically once the surface is being destroyed */
                struct wlr_scene_tree *tree = wlr_scene_subsurface_tree_create(
@@ -872,10 +875,6 @@ xwayland_view_map(struct view *view)
                view_moved(view);
        }
 
-       /* Add commit here, as xwayland map/unmap can change the wlr_surface */
-       wl_signal_add(&xwayland_surface->surface->events.commit, &view->commit);
-       view->commit.notify = handle_commit;
-
        /*
         * If the view was focused (on the xwayland server side) before
         * being mapped, update the seat focus now. Note that this only
@@ -904,7 +903,6 @@ xwayland_view_unmap(struct view *view, bool client_request)
                goto out;
        }
        view->mapped = false;
-       wl_list_remove(&view->commit.link);
        wlr_scene_node_set_enabled(&view->scene_tree->node, false);
        view_impl_unmap(view);