xwayland: support views that change override-redirect status

This commit is contained in:
Tobias Langendorf 2020-08-29 17:14:55 +02:00 committed by Simon Ser
parent 392d4808c3
commit 657587964e
2 changed files with 68 additions and 20 deletions

View file

@ -162,6 +162,7 @@ struct sway_xwayland_view {
struct wl_listener map; struct wl_listener map;
struct wl_listener unmap; struct wl_listener unmap;
struct wl_listener destroy; struct wl_listener destroy;
struct wl_listener override_redirect;
}; };
struct sway_xwayland_unmanaged { struct sway_xwayland_unmanaged {
@ -176,6 +177,7 @@ struct sway_xwayland_unmanaged {
struct wl_listener map; struct wl_listener map;
struct wl_listener unmap; struct wl_listener unmap;
struct wl_listener destroy; struct wl_listener destroy;
struct wl_listener override_redirect;
}; };
#endif #endif
struct sway_view_child; struct sway_view_child;

View file

@ -118,12 +118,36 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) {
struct sway_xwayland_unmanaged *surface = struct sway_xwayland_unmanaged *surface =
wl_container_of(listener, surface, destroy); wl_container_of(listener, surface, destroy);
wl_list_remove(&surface->request_configure.link);
wl_list_remove(&surface->map.link); wl_list_remove(&surface->map.link);
wl_list_remove(&surface->unmap.link); wl_list_remove(&surface->unmap.link);
wl_list_remove(&surface->destroy.link); wl_list_remove(&surface->destroy.link);
wl_list_remove(&surface->override_redirect.link);
free(surface); free(surface);
} }
static void handle_map(struct wl_listener *listener, void *data);
struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface);
static void unmanaged_handle_override_redirect(struct wl_listener *listener, void *data) {
struct sway_xwayland_unmanaged *surface =
wl_container_of(listener, surface, override_redirect);
struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
bool mapped = xsurface->mapped;
if (mapped) {
unmanaged_handle_unmap(&surface->unmap, NULL);
}
unmanaged_handle_destroy(&surface->destroy, NULL);
xsurface->data = NULL;
struct sway_xwayland_view *xwayland_view = create_xwayland_view(xsurface);
if (mapped) {
handle_map(&xwayland_view->map, xsurface);
}
}
static struct sway_xwayland_unmanaged *create_unmanaged( static struct sway_xwayland_unmanaged *create_unmanaged(
struct wlr_xwayland_surface *xsurface) { struct wlr_xwayland_surface *xsurface) {
struct sway_xwayland_unmanaged *surface = struct sway_xwayland_unmanaged *surface =
@ -144,6 +168,8 @@ static struct sway_xwayland_unmanaged *create_unmanaged(
surface->unmap.notify = unmanaged_handle_unmap; surface->unmap.notify = unmanaged_handle_unmap;
wl_signal_add(&xsurface->events.destroy, &surface->destroy); wl_signal_add(&xsurface->events.destroy, &surface->destroy);
surface->destroy.notify = unmanaged_handle_destroy; surface->destroy.notify = unmanaged_handle_destroy;
wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect);
surface->override_redirect.notify = unmanaged_handle_override_redirect;
return surface; return surface;
} }
@ -418,6 +444,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&xwayland_view->set_decorations.link); wl_list_remove(&xwayland_view->set_decorations.link);
wl_list_remove(&xwayland_view->map.link); wl_list_remove(&xwayland_view->map.link);
wl_list_remove(&xwayland_view->unmap.link); wl_list_remove(&xwayland_view->unmap.link);
wl_list_remove(&xwayland_view->override_redirect.link);
view_begin_destroy(&xwayland_view->view); view_begin_destroy(&xwayland_view->view);
} }
@ -441,16 +468,6 @@ static void handle_map(struct wl_listener *listener, void *data) {
struct wlr_xwayland_surface *xsurface = data; struct wlr_xwayland_surface *xsurface = data;
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
if (xsurface->override_redirect) {
// This window used not to have the override redirect flag and has it
// now. Switch to unmanaged.
handle_destroy(&xwayland_view->destroy, view);
xsurface->data = NULL;
struct sway_xwayland_unmanaged *unmanaged = create_unmanaged(xsurface);
unmanaged_handle_map(&unmanaged->map, xsurface);
return;
}
view->natural_width = xsurface->width; view->natural_width = xsurface->width;
view->natural_height = xsurface->height; view->natural_height = xsurface->height;
@ -465,6 +482,25 @@ static void handle_map(struct wl_listener *listener, void *data) {
transaction_commit_dirty(); transaction_commit_dirty();
} }
static void handle_override_redirect(struct wl_listener *listener, void *data) {
struct sway_xwayland_view *xwayland_view =
wl_container_of(listener, xwayland_view, override_redirect);
struct wlr_xwayland_surface *xsurface = data;
struct sway_view *view = &xwayland_view->view;
bool mapped = xsurface->mapped;
if (mapped) {
handle_unmap(&xwayland_view->unmap, NULL);
}
handle_destroy(&xwayland_view->destroy, view);
xsurface->data = NULL;
struct sway_xwayland_unmanaged *unmanaged = create_unmanaged(xsurface);
if (mapped) {
unmanaged_handle_map(&unmanaged->map, xsurface);
}
}
static void handle_request_configure(struct wl_listener *listener, void *data) { static void handle_request_configure(struct wl_listener *listener, void *data) {
struct sway_xwayland_view *xwayland_view = struct sway_xwayland_view *xwayland_view =
wl_container_of(listener, xwayland_view, request_configure); wl_container_of(listener, xwayland_view, request_configure);
@ -637,22 +673,14 @@ struct sway_view *view_from_wlr_xwayland_surface(
return xsurface->data; return xsurface->data;
} }
void handle_xwayland_surface(struct wl_listener *listener, void *data) { struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface) {
struct wlr_xwayland_surface *xsurface = data;
if (xsurface->override_redirect) {
sway_log(SWAY_DEBUG, "New xwayland unmanaged surface");
create_unmanaged(xsurface);
return;
}
sway_log(SWAY_DEBUG, "New xwayland surface title='%s' class='%s'", sway_log(SWAY_DEBUG, "New xwayland surface title='%s' class='%s'",
xsurface->title, xsurface->class); xsurface->title, xsurface->class);
struct sway_xwayland_view *xwayland_view = struct sway_xwayland_view *xwayland_view =
calloc(1, sizeof(struct sway_xwayland_view)); calloc(1, sizeof(struct sway_xwayland_view));
if (!sway_assert(xwayland_view, "Failed to allocate view")) { if (!sway_assert(xwayland_view, "Failed to allocate view")) {
return; return NULL;
} }
view_init(&xwayland_view->view, SWAY_VIEW_XWAYLAND, &view_impl); view_init(&xwayland_view->view, SWAY_VIEW_XWAYLAND, &view_impl);
@ -711,7 +739,25 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
wl_signal_add(&xsurface->events.map, &xwayland_view->map); wl_signal_add(&xsurface->events.map, &xwayland_view->map);
xwayland_view->map.notify = handle_map; xwayland_view->map.notify = handle_map;
wl_signal_add(&xsurface->events.set_override_redirect,
&xwayland_view->override_redirect);
xwayland_view->override_redirect.notify = handle_override_redirect;
xsurface->data = xwayland_view; xsurface->data = xwayland_view;
return xwayland_view;
}
void handle_xwayland_surface(struct wl_listener *listener, void *data) {
struct wlr_xwayland_surface *xsurface = data;
if (xsurface->override_redirect) {
sway_log(SWAY_DEBUG, "New xwayland unmanaged surface");
create_unmanaged(xsurface);
return;
}
create_xwayland_view(xsurface);
} }
void handle_xwayland_ready(struct wl_listener *listener, void *data) { void handle_xwayland_ready(struct wl_listener *listener, void *data) {