diff options
author | Semi Malinen <semi.malinen@ge.com> | 2018-05-02 11:10:32 +0200 |
---|---|---|
committer | Pekka Paalanen <pekka.paalanen@collabora.co.uk> | 2018-05-21 16:51:05 +0300 |
commit | 99f8c085594dba25006fa29fbfb09b60105bbaf9 (patch) | |
tree | 6c0333fe5524ec7588a552439a1191bca460904a /desktop-shell | |
parent | e7a52fbb7d86c6810346ae0f058fb44a84d0754e (diff) | |
download | weston-99f8c085594dba25006fa29fbfb09b60105bbaf9.tar.gz |
desktop-shell: detect stale shell surface outputs
When displays are hot (un)plugged, it may happen that
a shell surface is left with a stale pointer to an output
that has already been freed. Add an output destroy listener
to catch such situations and set the output pointer to NULL.
Signed-off-by: Semi Malinen <semi.malinen@ge.com>
Signed-off-by: Fabien Lahoudere <fabien.lahoudere@collabora.com>
Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Diffstat (limited to 'desktop-shell')
-rw-r--r-- | desktop-shell/shell.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index 1e153cb5..64db89fc 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -128,6 +128,7 @@ struct shell_surface { struct weston_output *fullscreen_output; struct weston_output *output; + struct wl_listener output_destroy_listener; struct surface_state { bool fullscreen; @@ -1934,6 +1935,17 @@ shell_surface_update_layer(struct shell_surface *shsurf) } static void +notify_output_destroy(struct wl_listener *listener, void *data) +{ + struct shell_surface *shsurf = + container_of(listener, + struct shell_surface, output_destroy_listener); + + shsurf->output = NULL; + shsurf->output_destroy_listener.notify = NULL; +} + +static void shell_surface_set_output(struct shell_surface *shsurf, struct weston_output *output) { @@ -1948,6 +1960,18 @@ shell_surface_set_output(struct shell_surface *shsurf, shsurf->output = es->output; else shsurf->output = get_default_output(es->compositor); + + if (shsurf->output_destroy_listener.notify) { + wl_list_remove(&shsurf->output_destroy_listener.link); + shsurf->output_destroy_listener.notify = NULL; + } + + if (!shsurf->output) + return; + + shsurf->output_destroy_listener.notify = notify_output_destroy; + wl_signal_add(&shsurf->output->destroy_signal, + &shsurf->output_destroy_listener); } static void @@ -1986,7 +2010,7 @@ unset_maximized(struct shell_surface *shsurf) weston_desktop_surface_get_surface(shsurf->desktop_surface); /* undo all maximized things here */ - shsurf->output = get_default_output(surface->compositor); + shell_surface_set_output(shsurf, get_default_output(surface->compositor)); if (shsurf->saved_position_valid) weston_view_set_position(shsurf->view, @@ -2348,7 +2372,8 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface, shsurf->fullscreen.black_view = NULL; wl_list_init(&shsurf->fullscreen.transform.link); - shsurf->output = get_default_output(shsurf->shell->compositor); + shell_surface_set_output( + shsurf, get_default_output(shsurf->shell->compositor)); wl_signal_init(&shsurf->destroy_signal); |