From d24af4323300c737b2da19f23af5c42d593c4df9 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Wed, 20 Jan 2021 09:11:41 +0100 Subject: [PATCH] input: add tablet focus handling Closely modelled after the pointer focus handling Co-authored-by: Peter Hutterer Signed-off-by: Lyude Paul Signed-off-by: Peter Hutterer Signed-off-by: Bastian Farkas Based on a patch from Peter Hutterer Lyude Paul Signed-off-by: Michael Olbrich --- include/libweston/libweston.h | 12 ++++ libweston/input.c | 101 ++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 1aa146e1..19ae42f2 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -845,8 +845,14 @@ struct weston_touch { struct weston_tablet_tool { struct weston_seat *seat; uint32_t type; + struct weston_tablet *current_tablet; struct wl_list resource_list; + struct wl_list focus_resource_list; + struct weston_view *focus; + struct wl_listener focus_view_listener; + struct wl_listener focus_resource_listener; + uint32_t focus_serial; struct wl_list link; @@ -956,6 +962,12 @@ void weston_touch_send_frame(struct weston_touch *touch); +void +weston_tablet_tool_set_focus(struct weston_tablet_tool *tool, + struct weston_view *view, + const struct timespec *time); + + void weston_seat_set_selection(struct weston_seat *seat, struct weston_data_source *source, uint32_t serial); diff --git a/libweston/input.c b/libweston/input.c index 1365502a..30a76161 100644 --- a/libweston/input.c +++ b/libweston/input.c @@ -424,6 +424,26 @@ touch_focus_resource_destroyed(struct wl_listener *listener, void *data) weston_touch_set_focus(touch, NULL); } +static void +tablet_tool_focus_view_destroyed(struct wl_listener *listener, void *data) +{ + struct weston_tablet_tool *tool = + container_of(listener, struct weston_tablet_tool, + focus_view_listener); + + weston_tablet_tool_set_focus(tool, NULL, 0); +} + +static void +tablet_tool_focus_resource_destroyed(struct wl_listener *listener, void *data) +{ + struct weston_tablet_tool *tool = + container_of(listener, struct weston_tablet_tool, + focus_resource_listener); + + weston_tablet_tool_set_focus(tool, NULL, 0); +} + static void move_resources(struct wl_list *destination, struct wl_list *source) { @@ -1120,6 +1140,16 @@ find_resource_for_surface(struct wl_list *list, struct weston_surface *surface) return wl_resource_find_for_client(list, wl_resource_get_client(surface->resource)); } +static struct wl_resource * +find_resource_for_view(struct wl_list *list, struct weston_view *view) +{ + if (!view) + return NULL; + + return find_resource_for_surface(list, + view->surface); +} + /** Send wl_keyboard.modifiers events to focused resources and pointer * focused resources. * @@ -1441,6 +1471,64 @@ weston_tablet_destroy(struct weston_tablet *tablet) } } +WL_EXPORT void +weston_tablet_tool_set_focus(struct weston_tablet_tool *tool, + struct weston_view *view, + const struct timespec *time) +{ + struct wl_list *focus_resource_list; + struct wl_resource *resource; + struct weston_seat *seat = tool->seat; + uint32_t msecs; + + focus_resource_list = &tool->focus_resource_list; + /* FIXME: correct timestamp? */ + msecs = time ? timespec_to_msec(time) : 0; + if (tool->focus && !wl_list_empty(focus_resource_list)) { + wl_resource_for_each(resource, focus_resource_list) { + zwp_tablet_tool_v2_send_proximity_out(resource); + zwp_tablet_tool_v2_send_frame(resource, msecs); + } + + move_resources(&tool->resource_list, focus_resource_list); + } + + if (find_resource_for_view(&tool->resource_list, view)) { + struct wl_client *surface_client = + wl_resource_get_client(view->surface->resource); + + move_resources_for_client(focus_resource_list, + &tool->resource_list, + surface_client); + + tool->focus_serial = wl_display_next_serial(seat->compositor->wl_display); + wl_resource_for_each(resource, focus_resource_list) { + struct wl_resource *tr; + + tr = wl_resource_find_for_client(&tool->current_tablet->resource_list, + surface_client); + + zwp_tablet_tool_v2_send_proximity_in(resource, tool->focus_serial, + tr, view->surface->resource); + zwp_tablet_tool_v2_send_frame(resource, msecs); + } + } + + wl_list_remove(&tool->focus_view_listener.link); + wl_list_init(&tool->focus_view_listener.link); + wl_list_remove(&tool->focus_resource_listener.link); + wl_list_init(&tool->focus_resource_listener.link); + + if (view) + wl_signal_add(&view->destroy_signal, + &tool->focus_view_listener); + if (view && view->surface->resource) + wl_resource_add_destroy_listener(view->surface->resource, + &tool->focus_resource_listener); + tool->focus = view; + tool->focus_view_listener.notify = tablet_tool_focus_view_destroyed; +} + WL_EXPORT struct weston_tablet_tool * weston_tablet_tool_create(void) { @@ -1451,6 +1539,13 @@ weston_tablet_tool_create(void) return NULL; wl_list_init(&tool->resource_list); + wl_list_init(&tool->focus_resource_list); + + wl_list_init(&tool->focus_view_listener.link); + tool->focus_view_listener.notify = tablet_tool_focus_view_destroyed; + + wl_list_init(&tool->focus_resource_listener.link); + tool->focus_resource_listener.notify = tablet_tool_focus_resource_destroyed; return tool; } @@ -1464,9 +1559,15 @@ weston_tablet_tool_destroy(struct weston_tablet_tool *tool) zwp_tablet_tool_v2_send_removed(resource); wl_resource_set_user_data(resource, NULL); } + wl_resource_for_each(resource, &tool->focus_resource_list) { + wl_resource_set_user_data(resource, NULL); + } wl_list_remove(&tool->link); wl_list_remove(&tool->resource_list); + wl_list_remove(&tool->focus_resource_list); + wl_list_remove(&tool->focus_view_listener.link); + wl_list_remove(&tool->focus_resource_listener.link); free(tool); }