diff --git a/include/labwc.h b/include/labwc.h index 2a081a89..0fd0f60c 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -310,6 +310,7 @@ struct view { struct wl_listener set_title; struct wl_listener set_app_id; /* class on xwayland */ struct wl_listener set_decorations; /* xwayland only */ + struct wl_listener override_redirect; /* xwayland only */ struct wl_listener new_popup; /* xdg-shell only */ struct wl_listener new_subsurface; /* xdg-shell only */ }; @@ -372,8 +373,9 @@ void xdg_surface_new(struct wl_listener *listener, void *data); #if HAVE_XWAYLAND void xwayland_surface_new(struct wl_listener *listener, void *data); -void xwayland_unmanaged_create(struct server *server, +struct xwayland_unmanaged *xwayland_unmanaged_create(struct server *server, struct wlr_xwayland_surface *xsurface); +void unmanaged_handle_map(struct wl_listener *listener, void *data); #endif void view_child_init(struct view_child *child, struct view *view, diff --git a/src/xwayland-unmanaged.c b/src/xwayland-unmanaged.c index 41ffc05f..41fba938 100644 --- a/src/xwayland-unmanaged.c +++ b/src/xwayland-unmanaged.c @@ -23,7 +23,7 @@ unmanaged_handle_commit(struct wl_listener *listener, void *data) damage_all_outputs(unmanaged->server); } -static void +void unmanaged_handle_map(struct wl_listener *listener, void *data) { struct xwayland_unmanaged *unmanaged = @@ -91,7 +91,7 @@ unmanaged_handle_destroy(struct wl_listener *listener, void *data) free(unmanaged); } -void +struct xwayland_unmanaged * xwayland_unmanaged_create(struct server *server, struct wlr_xwayland_surface *xsurface) { @@ -109,4 +109,5 @@ xwayland_unmanaged_create(struct server *server, unmanaged->unmap.notify = unmanaged_handle_unmap; wl_signal_add(&xsurface->events.destroy, &unmanaged->destroy); unmanaged->destroy.notify = unmanaged_handle_destroy; + return unmanaged; } diff --git a/src/xwayland.c b/src/xwayland.c index c9e897fe..e87d7078 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -96,10 +96,19 @@ handle_destroy(struct wl_listener *listener, void *data) wl_list_remove(&view->link); wl_list_remove(&view->map.link); wl_list_remove(&view->unmap.link); - wl_list_remove(&view->destroy.link); + wl_list_remove(&view->request_move.link); + wl_list_remove(&view->request_resize.link); wl_list_remove(&view->request_configure.link); + wl_list_remove(&view->request_activate.link); + wl_list_remove(&view->request_minimize.link); wl_list_remove(&view->request_maximize.link); wl_list_remove(&view->request_fullscreen.link); + wl_list_remove(&view->set_title.link); + wl_list_remove(&view->set_app_id.link); + wl_list_remove(&view->set_decorations.link); + wl_list_remove(&view->override_redirect.link); + wl_list_remove(&view->destroy.link); + ssd_destroy(view); free(view); } @@ -243,6 +252,25 @@ handle_set_decorations(struct wl_listener *listener, void *data) view_set_decorations(view, want_deco(view)); } +static void +handle_override_redirect(struct wl_listener *listener, void *data) +{ + struct view *view = wl_container_of(listener, view, override_redirect); + struct wlr_xwayland_surface *xsurface = data; + struct server *server = view->server; + bool mapped = xsurface->mapped; + if (mapped) { + handle_unmap(&view->unmap, NULL); + } + handle_destroy(&view->destroy, view); + xsurface->data = NULL; + struct xwayland_unmanaged *unmanaged = + xwayland_unmanaged_create(server, xsurface); + if (mapped) { + unmanaged_handle_map(&unmanaged->map, xsurface); + } +} + static void top_left_edge_boundary_check(struct view *view) { @@ -415,5 +443,9 @@ xwayland_surface_new(struct wl_listener *listener, void *data) wl_signal_add(&xsurface->events.set_decorations, &view->set_decorations); + view->override_redirect.notify = handle_override_redirect; + wl_signal_add(&xsurface->events.set_override_redirect, + &view->override_redirect); + wl_list_insert(&view->server->views, &view->link); }