summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ådahl <jadahl@gmail.com>2016-02-26 14:02:06 +0800
committerJonas Ådahl <jadahl@gmail.com>2016-04-22 10:31:21 +0800
commitd3a3ee980d58d826c0c0122f9661066cd760a77e (patch)
tree20c8deb9cc1e935060bdaeeba861e948860a4469
parent3c53094e2413050617dcae400d117449a800c50e (diff)
desktop-shell: Unset the shell surface owner when it goes away
On client destruction, the shell object may be destroyed before the shell surface objects. If this happens to two surfaces of the same client, and one surface being destroyed results in the focus being switched to the other, this would trigger a ping event. The ping event sending function relies on having a valid owner, and if the shell would be destoryed prior to the shell surface, we'd crash in this function. Solve this by unsetting the owner pointer when the shell client goes away and early out in the ping event sending function if the owner is gone. Signed-off-by: Jonas Ådahl <jadahl@gmail.com> Reviewed-by: Mike Blumenkrantz <zmike@osg.samsung.com>
-rw-r--r--desktop-shell/shell.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 24437d8d..f705c994 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -2149,6 +2149,8 @@ ping_handler(struct weston_surface *surface, uint32_t serial)
return;
if (shsurf->surface == shsurf->shell->grab_surface)
return;
+ if (!shsurf->owner)
+ return;
handle_xdg_ping(shsurf, serial);
}
@@ -3778,7 +3780,8 @@ shell_get_shell_surface(struct wl_client *client,
wl_resource_set_implementation(shsurf->resource,
&shell_surface_implementation,
shsurf, shell_destroy_shell_surface);
- wl_list_init(wl_resource_get_link(shsurf->resource));
+ wl_list_insert(&sc->surface_list,
+ wl_resource_get_link(shsurf->resource));
}
static bool
@@ -5864,6 +5867,8 @@ handle_shell_client_destroy(struct wl_listener *listener, void *data)
{
struct shell_client *sc =
container_of(listener, struct shell_client, destroy_listener);
+ struct wl_resource *shsurf_resource;
+ struct shell_surface *shsurf;
if (sc->ping_timer)
wl_event_source_remove(sc->ping_timer);
@@ -5872,6 +5877,10 @@ handle_shell_client_destroy(struct wl_listener *listener, void *data)
* head of the surface list so we don't use that freed list node
* during surface clean up later on.
*/
+ wl_resource_for_each(shsurf_resource, &sc->surface_list) {
+ shsurf = wl_resource_get_user_data(shsurf_resource);
+ shsurf->owner = NULL;
+ }
wl_list_remove(&sc->surface_list);
free(sc);