summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Olbrich <m.olbrich@pengutronix.de>2021-01-20 09:11:41 +0100
committerDaniel Stone <daniels@collabora.com>2023-03-31 12:10:26 +0000
commitd24af4323300c737b2da19f23af5c42d593c4df9 (patch)
treeefdbe76035c1a0b6c7dab56e8c993ce74caba075
parent03596a9d065ccb38059c9b782e1d4cd4eaf5a59e (diff)
downloadweston-d24af4323300c737b2da19f23af5c42d593c4df9.tar.gz
input: add tablet focus handling
Closely modelled after the pointer focus handling Co-authored-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Lyude Paul <thatslyude@gmail.com> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Bastian Farkas <bfarkas@de.adit-jv.com> Based on a patch from Peter Hutterer <peter.hutterer@who-t.net> Lyude Paul <thatslyude@gmail.com> Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
-rw-r--r--include/libweston/libweston.h12
-rw-r--r--libweston/input.c101
2 files changed, 113 insertions, 0 deletions
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;
@@ -957,6 +963,12 @@ 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
@@ -425,6 +425,26 @@ touch_focus_resource_destroyed(struct wl_listener *listener, void *data)
}
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)
{
wl_list_insert_list(destination, 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);
}