[PATCH 3/3] compositor: properly restore keyboard_focus in notify_keyboard_focus()
Kristian Hoegsberg
hoegsberg at gmail.com
Tue Mar 20 13:07:26 PDT 2012
On Fri, Mar 16, 2012 at 05:25:11PM +0200, Ander Conselvan de Oliveira wrote:
> Commit f992b2fc removed the saved keyboard focus logic to fix a crash
> when the saved surface is destroyed. However, setting keyboard focus to
> the first surface on the list ends up trying to set the focus to the
> cursor surface most of the time. The end result is a NULL keyboard
> focus.
>
> This patch restores the saved keyboard focus logic and fixes the crash
> mentioned above using a destroy listener.
Thanks, that's a good fix. This and the two previous fixes applied.
We really need that wl_guard thing that Pekka suggested now... too
many destroy listeners that just set a pointer to NULL.
We didn't find a really good way to make it both typesafe and
convenient, but I think I prefer the approach where wl_guard manages a
wl_resource pointer internally the best. We put the wl_resource
pointer and the wl_listener in a wl_guard struct:
struct wl_resource_ref {
struct wl_resource *resource;
struct wl_listener listener;
};
and then we can just say wl_resource_ref_set(ref, resource). If we
want a typesafe pointer as well, we have to add it in the containing
struct and set it from resource->data:
wd->saved_kbd_focus = es;
wl_guard_set(&wd->saved_kbd_guard, &es->surface.resource);
The wl_resource_ref will not clear the guard->resource pointer, but the
typesafe pointer, so access to the typesafe pointer has to be guarded
by checking ref->resource != NULL:
es = wd->saved_kbd_focus;
if (wd->saved_kbd_guard.resource) {
/* do stuff with es */
}
Kristian
> ---
> src/compositor.c | 36 +++++++++++++++++++++++++++++-------
> src/compositor.h | 2 ++
> 2 files changed, 31 insertions(+), 7 deletions(-)
>
> diff --git a/src/compositor.c b/src/compositor.c
> index 09b14ae..ceb36ed 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -1636,6 +1636,18 @@ notify_pointer_focus(struct wl_input_device *device,
> }
> }
>
> +static void
> +destroy_device_saved_kbd_focus(struct wl_listener *listener,
> + struct wl_resource *resource, uint32_t time)
> +{
> + struct weston_input_device *wd;
> +
> + wd = container_of(listener, struct weston_input_device,
> + saved_kbd_focus_listener);
> +
> + wd->saved_kbd_focus = NULL;
> +}
> +
> WL_EXPORT void
> notify_keyboard_focus(struct wl_input_device *device,
> uint32_t time, struct weston_output *output,
> @@ -1647,12 +1659,6 @@ notify_keyboard_focus(struct wl_input_device *device,
> struct weston_surface *es;
> uint32_t *k;
>
> - if (!wl_list_empty(&compositor->surface_list))
> - es = container_of(compositor->surface_list.next,
> - struct weston_surface, link);
> - else
> - es = NULL;
> -
> if (output) {
> wl_array_copy(&wd->input_device.keys, keys);
> wd->modifier_state = 0;
> @@ -1661,14 +1667,30 @@ notify_keyboard_focus(struct wl_input_device *device,
> update_modifier_state(wd, *k, 1);
> }
>
> - if (es && es->surface.resource.client)
> + es = wd->saved_kbd_focus;
> +
> + if (es) {
> + wl_list_remove(&wd->saved_kbd_focus_listener.link);
> wl_input_device_set_keyboard_focus(&wd->input_device,
> &es->surface, time);
> + wd->saved_kbd_focus = NULL;
> + }
> } else {
> wl_array_for_each(k, &device->keys)
> weston_compositor_idle_release(compositor);
>
> wd->modifier_state = 0;
> +
> + es = wd->input_device.keyboard_focus;
> +
> + if (es) {
> + wd->saved_kbd_focus = es;
> + wd->saved_kbd_focus_listener.func =
> + destroy_device_saved_kbd_focus;
> + wl_list_insert(es->surface.resource.destroy_listener_list.prev,
> + &wd->saved_kbd_focus_listener.link);
> + }
> +
> wl_input_device_set_keyboard_focus(&wd->input_device,
> NULL, time);
> }
> diff --git a/src/compositor.h b/src/compositor.h
> index 9467cc8..9071c40 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -113,6 +113,8 @@ struct weston_input_device {
> struct wl_list link;
> uint32_t modifier_state;
> int hw_cursor;
> + struct wl_surface *saved_kbd_focus;
> + struct wl_listener saved_kbd_focus_listener;
>
> uint32_t num_tp;
> struct wl_surface *touch_focus;
> --
> 1.7.4.1
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list