summaryrefslogtreecommitdiff
path: root/desktop-shell
diff options
context:
space:
mode:
authorSemi Malinen <semi.malinen@ge.com>2018-05-02 11:10:32 +0200
committerPekka Paalanen <pekka.paalanen@collabora.co.uk>2018-05-21 16:51:05 +0300
commit99f8c085594dba25006fa29fbfb09b60105bbaf9 (patch)
tree6c0333fe5524ec7588a552439a1191bca460904a /desktop-shell
parente7a52fbb7d86c6810346ae0f058fb44a84d0754e (diff)
downloadweston-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.c29
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);