From 72e183bd2b41b888a4d26e3c6b389948964df85c Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Thu, 22 Feb 2018 16:55:15 +0200 Subject: [PATCH] input: never set keyboard focus without wl_resource Do not attempt to set keyboard focus to a surface that has no wl_resource. The destroy listener hangs off the wl_resource, so if that is not present, nothing will clean up the pointer when the weston_surface gets destroyed and it goes stale. As keyboard_focus_resource_destroyed() sets the focus to NULL, this patch should be enough to guarantee that the keyboard focus surface will always have a wl_resource. I have confirmed the added branch in weston_keyboard_set_focus() can be hit, but doing so is hard. My test case has weston/x11 with two outputs, and weston/wayland --sprawl running on top of that, then closing the parent compositor output windows one by one. Sometimes it hits, often it does not. Having the window closing animation enabled may help to hit it. Signed-off-by: Pekka Paalanen Reviewed-by: Daniel Stone --- libweston/input.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libweston/input.c b/libweston/input.c index 3f616941..3e91c266 100644 --- a/libweston/input.c +++ b/libweston/input.c @@ -1460,6 +1460,14 @@ weston_keyboard_set_focus(struct weston_keyboard *keyboard, uint32_t serial; struct wl_list *focus_resource_list; + /* Keyboard focus on a surface without a client is equivalent to NULL + * focus as nothing would react to the keyboard events anyway. + * Just set focus to NULL instead - the destroy listener hangs on the + * wl_resource anyway. + */ + if (surface && !surface->resource) + surface = NULL; + focus_resource_list = &keyboard->focus_resource_list; if (!wl_list_empty(focus_resource_list) && keyboard->focus != surface) { @@ -1495,7 +1503,7 @@ weston_keyboard_set_focus(struct weston_keyboard *keyboard, wl_list_remove(&keyboard->focus_resource_listener.link); wl_list_init(&keyboard->focus_resource_listener.link); - if (surface && surface->resource) + if (surface) wl_resource_add_destroy_listener(surface->resource, &keyboard->focus_resource_listener);