diff options
author | Emilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk> | 2014-02-10 14:23:04 +0100 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2014-02-18 14:04:39 -0800 |
commit | f942b73a1c25260b5903efc573b4d7bbb1c48bcc (patch) | |
tree | edb3443c67e2d94a25ec7ad361da3d382bb4632c /desktop-shell/exposay.c | |
parent | 3b6e68e2c1e3b80173f29b9930f966ce84fd5c77 (diff) |
exposay: don't crash if a view goes away
When a view was destroyed while we were on exposay, we didn't
remove it from the list of views, and so when leaving exposay
we were trying to animate (and sometimes activate) a
non-existent view, causing a crash.
Signed-off-by: Emilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>
Diffstat (limited to 'desktop-shell/exposay.c')
-rw-r--r-- | desktop-shell/exposay.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/desktop-shell/exposay.c b/desktop-shell/exposay.c index b7e32c9a..ca363589 100644 --- a/desktop-shell/exposay.c +++ b/desktop-shell/exposay.c @@ -33,6 +33,7 @@ struct exposay_surface { struct exposay_output *eoutput; struct weston_surface *surface; struct weston_view *view; + struct wl_listener view_destroy_listener; struct wl_list link; int x; @@ -57,6 +58,20 @@ static void exposay_set_state(struct desktop_shell *shell, static void exposay_check_state(struct desktop_shell *shell); static void +exposay_surface_destroy(struct exposay_surface *esurface) +{ + wl_list_remove(&esurface->link); + wl_list_remove(&esurface->view_destroy_listener.link); + + if (esurface->shell->exposay.focus_current == esurface->view) + esurface->shell->exposay.focus_current = NULL; + if (esurface->shell->exposay.focus_prev == esurface->view) + esurface->shell->exposay.focus_prev = NULL; + + free(esurface); +} + +static void exposay_in_flight_inc(struct desktop_shell *shell) { shell->exposay.in_flight++; @@ -110,8 +125,7 @@ exposay_animate_out_done(struct weston_view_animation *animation, void *data) struct exposay_surface *esurface = data; struct desktop_shell *shell = esurface->shell; - wl_list_remove(&esurface->link); - free(esurface); + exposay_surface_destroy(esurface); exposay_in_flight_dec(shell); } @@ -176,6 +190,16 @@ exposay_pick(struct desktop_shell *shell, int x, int y) } } +static void +handle_view_destroy(struct wl_listener *listener, void *data) +{ + struct exposay_surface *esurface = container_of(listener, + struct exposay_surface, + view_destroy_listener); + + exposay_surface_destroy(esurface); +} + /* Pretty lame layout for now; just tries to make a square. Should take * aspect ratio into account really. Also needs to be notified of surface * addition and removal and adjust layout/animate accordingly. */ @@ -267,6 +291,9 @@ exposay_layout(struct desktop_shell *shell, struct shell_output *shell_output) esurface->eoutput = eoutput; esurface->view = view; + esurface->view_destroy_listener.notify = handle_view_destroy; + wl_signal_add(&view->destroy_signal, &esurface->view_destroy_listener); + esurface->row = i / eoutput->grid_size; esurface->column = i % eoutput->grid_size; |