xwayland: connect commit and surface_destroy handlers together

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.
This commit is contained in:
John Lindgren 2025-11-07 22:20:18 -05:00 committed by Johan Malm
parent 0501f0ac9e
commit b6f7bacdde
2 changed files with 22 additions and 29 deletions

View 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)
{

View 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);