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 <pekka.paalanen@collabora.co.uk>
Reviewed-by: Daniel Stone <daniels@collabora.com>
dev
Pekka Paalanen 7 years ago committed by Daniel Stone
parent 8d6e14c991
commit 72e183bd2b
  1. 10
      libweston/input.c

@ -1460,6 +1460,14 @@ weston_keyboard_set_focus(struct weston_keyboard *keyboard,
uint32_t serial; uint32_t serial;
struct wl_list *focus_resource_list; 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; focus_resource_list = &keyboard->focus_resource_list;
if (!wl_list_empty(focus_resource_list) && keyboard->focus != surface) { 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_remove(&keyboard->focus_resource_listener.link);
wl_list_init(&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, wl_resource_add_destroy_listener(surface->resource,
&keyboard->focus_resource_listener); &keyboard->focus_resource_listener);

Loading…
Cancel
Save