xwayland: Keep track of outputs per window
Add a list of outputs a window is placed on, adding an output whenever the surface enters the output and removing it once it leaves the output. Note that not all Wayland compositors actually send a leave surface event on output removal, so we need to make sure to remove the output from the list for each window, otherwise we might end up pointing to freed memory. Signed-off-by: Olivier Fourdan <ofourdan@redhat.com> Reviewed-By: Kenny Levinsen <kl@kl.wtf> Acked-by: Peter Hutterer <peter.hutterer@who-t.net> Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1197>
This commit is contained in:
parent
cd0c43df13
commit
4248bfb0da
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue