diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c index 2c987a39f..f77ba8278 100644 --- a/hw/xwayland/xwayland-output.c +++ b/hw/xwayland/xwayland-output.c @@ -962,8 +962,13 @@ xwl_output_remove(struct xwl_output *xwl_output) { struct xwl_output *it; struct xwl_screen *xwl_screen = xwl_output->xwl_screen; + struct xwl_window *xwl_window; int width = 0, height = 0; + /* Not all compositors send a "leave" event on output removal */ + xorg_list_for_each_entry(xwl_window, &xwl_screen->window_list, link_window) + xwl_window_leave_output(xwl_window, xwl_output); + xorg_list_del(&xwl_output->link); if (xwl_output->randr_output) diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c index d419e3070..b439c3a47 100644 --- a/hw/xwayland/xwayland-window.c +++ b/hw/xwayland/xwayland-window.c @@ -794,6 +794,40 @@ static const struct xdg_surface_listener xdg_surface_listener = { xdg_surface_handle_configure, }; +static void +xwl_window_enter_output(struct xwl_window *xwl_window, struct xwl_output *xwl_output) +{ + struct xwl_window_output *window_output; + + window_output = xnfcalloc(1, sizeof(struct xwl_window_output)); + window_output->xwl_output = xwl_output; + xorg_list_add(&window_output->link, &xwl_window->xwl_output_list); +} + +void +xwl_window_leave_output(struct xwl_window *xwl_window, struct xwl_output *xwl_output) +{ + struct xwl_window_output *window_output, *tmp; + + xorg_list_for_each_entry_safe(window_output, tmp, &xwl_window->xwl_output_list, link) { + if (window_output->xwl_output == xwl_output) { + xorg_list_del(&window_output->link); + free(window_output); + } + } +} + +static void +xwl_window_free_outputs(struct xwl_window *xwl_window) +{ + struct xwl_window_output *window_output, *tmp; + + xorg_list_for_each_entry_safe(window_output, tmp, &xwl_window->xwl_output_list, link) { + xorg_list_del(&window_output->link); + free(window_output); + } +} + static void xwl_window_surface_enter(void *data, struct wl_surface *wl_surface, @@ -801,6 +835,10 @@ xwl_window_surface_enter(void *data, { struct xwl_window *xwl_window = data; struct xwl_screen *xwl_screen = xwl_window->xwl_screen; + struct xwl_output *xwl_output = xwl_output_from_wl_output(xwl_screen, wl_output); + + if (xwl_output) + xwl_window_enter_output(xwl_window, xwl_output); if (xwl_window->wl_output != wl_output) { xwl_window->wl_output = wl_output; @@ -816,6 +854,11 @@ xwl_window_surface_leave(void *data, struct wl_output *wl_output) { struct xwl_window *xwl_window = data; + struct xwl_screen *xwl_screen = xwl_window->xwl_screen; + struct xwl_output *xwl_output = xwl_output_from_wl_output(xwl_screen, wl_output); + + if (xwl_output) + xwl_window_leave_output(xwl_window, xwl_output); if (xwl_window->wl_output == wl_output) xwl_window->wl_output = NULL; @@ -913,9 +956,6 @@ xwl_create_root_surface(struct xwl_window *xwl_window) goto err_surf; } - wl_surface_add_listener(xwl_window->surface, - &surface_listener, xwl_window); - xdg_surface_add_listener(xwl_window->xdg_surface, &xdg_surface_listener, xwl_window); @@ -924,6 +964,9 @@ xwl_create_root_surface(struct xwl_window *xwl_window) xwl_window); } + wl_surface_add_listener(xwl_window->surface, + &surface_listener, xwl_window); + xwl_window_rootful_update_title(xwl_window); xwl_window_rootful_set_app_id(xwl_window); wl_surface_commit(xwl_window->surface); @@ -981,6 +1024,7 @@ ensure_surface_for_window(WindowPtr window) xwl_window->window = window; xwl_window->viewport_scale_x = 1.0; xwl_window->viewport_scale_y = 1.0; + xorg_list_init(&xwl_window->xwl_output_list); xwl_window->surface = wl_compositor_create_surface(xwl_screen->compositor); if (xwl_window->surface == NULL) { ErrorF("wl_display_create_surface failed\n"); @@ -1230,6 +1274,8 @@ xwl_unrealize_window(WindowPtr window) if (xwl_window->frame_callback) wl_callback_destroy(xwl_window->frame_callback); + xwl_window_free_outputs(xwl_window); + free(xwl_window); dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL); diff --git a/hw/xwayland/xwayland-window.h b/hw/xwayland/xwayland-window.h index 08629877f..0e45f08d2 100644 --- a/hw/xwayland/xwayland-window.h +++ b/hw/xwayland/xwayland-window.h @@ -49,6 +49,11 @@ struct xwl_wl_surface { struct xorg_list link; }; +struct xwl_window_output { + struct xorg_list link; + struct xwl_output *xwl_output; +}; + struct xwl_window { struct xwl_screen *xwl_screen; struct wl_surface *surface; @@ -66,6 +71,7 @@ struct xwl_window { OsTimerPtr window_buffers_timer; struct wl_output *wl_output; struct wl_output *wl_output_fullscreen; + struct xorg_list xwl_output_list; struct xorg_list frame_callback_list; #ifdef XWL_HAS_LIBDECOR struct libdecor_frame *libdecor_frame; @@ -92,6 +98,8 @@ void xwl_window_rootful_update_fullscreen(struct xwl_window *xwl_window, struct xwl_output *xwl_output); void xwl_window_set_window_pixmap(WindowPtr window, PixmapPtr pixmap); +void xwl_window_leave_output(struct xwl_window *xwl_window, + struct xwl_output *xwl_output); Bool xwl_realize_window(WindowPtr window); Bool xwl_unrealize_window(WindowPtr window); Bool xwl_change_window_attributes(WindowPtr window, unsigned long mask);