[PATCH weston 07/19] tablet: Add support for tablet tool objects
Stephen Chandler Paul
thatslyude at gmail.com
Wed Aug 6 16:07:57 PDT 2014
Signed-off-by: Stephen Chandler Paul <thatslyude at gmail.com>
---
src/compositor.h | 16 ++++++++++
src/input.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
src/libinput-device.c | 72 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 171 insertions(+), 3 deletions(-)
diff --git a/src/compositor.h b/src/compositor.h
index be28591..46619e3 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -398,6 +398,16 @@ struct weston_touch {
uint32_t grab_time;
};
+struct weston_tablet_tool {
+ enum wl_tablet_tool_type type;
+ uint32_t serial;
+
+ struct wl_signal destroy_signal;
+
+ struct wl_list resource_list;
+ struct wl_list link;
+};
+
struct weston_tablet {
struct weston_seat *seat;
struct evdev_device *device;
@@ -409,6 +419,8 @@ struct weston_tablet {
struct wl_listener focus_resource_listener;
uint32_t focus_serial;
+ struct weston_tablet_tool *current_tool;
+
int32_t hotspot_x, hotspot_y;
wl_fixed_t x, y;
@@ -579,6 +591,7 @@ struct weston_seat {
struct weston_keyboard *keyboard;
struct weston_touch *touch;
struct wl_list tablet_list;
+ struct wl_list tablet_tool_list;
int pointer_device_count;
int keyboard_device_count;
int touch_device_count;
@@ -1101,6 +1114,9 @@ notify_touch_frame(struct weston_seat *seat);
void
notify_tablet_added(struct weston_tablet *tablet);
void
+notify_tablet_proximity_in(struct weston_tablet *tablet, uint32_t time,
+ struct weston_tablet_tool *tool);
+void
notify_tablet_proximity_out(struct weston_tablet *tablet, uint32_t time);
void
notify_tablet_motion(struct weston_tablet *tablet, uint32_t time,
diff --git a/src/input.c b/src/input.c
index 6048bb8..19e9971 100644
--- a/src/input.c
+++ b/src/input.c
@@ -441,6 +441,16 @@ static const struct weston_keyboard_grab_interface
};
static void
+default_grab_tablet_proximity_in(struct weston_tablet_grab *grab, uint32_t time,
+ struct weston_tablet_tool *tool)
+{
+ /* default_grab_tablet_motion handles sending proximity_in events,
+ * since we can't figure out what surface to send the events to until
+ * we have the first motion event after proximity_in, so just don't do
+ * anything here */
+}
+
+static void
default_grab_tablet_proximity_out(struct weston_tablet_grab *grab,
uint32_t time)
{
@@ -489,7 +499,7 @@ default_grab_tablet_cancel(struct weston_tablet_grab *grab)
}
static struct weston_tablet_grab_interface default_tablet_grab_interface = {
- NULL,
+ default_grab_tablet_proximity_in,
default_grab_tablet_proximity_out,
default_grab_tablet_motion,
NULL,
@@ -728,6 +738,11 @@ weston_tablet_destroy(struct weston_tablet *tablet)
free(tablet);
}
+static const struct wl_tablet_tool_interface tablet_tool_interface;
+
+static void
+unbind_tablet_tool_resource(struct wl_resource *resource);
+
WL_EXPORT void
weston_tablet_set_focus(struct weston_tablet *tablet, struct weston_view *view,
uint32_t time)
@@ -735,6 +750,7 @@ weston_tablet_set_focus(struct weston_tablet *tablet, struct weston_view *view,
struct wl_list *focus_resource_list;
struct wl_resource *resource;
struct weston_seat *seat = tablet->seat;
+ struct weston_tablet_tool *tool = tablet->current_tool;
focus_resource_list = &tablet->focus_resource_list;
@@ -757,11 +773,39 @@ weston_tablet_set_focus(struct weston_tablet *tablet, struct weston_view *view,
tablet->focus_serial =
wl_display_next_serial(seat->compositor->wl_display);
- wl_resource_for_each(resource, focus_resource_list)
+ if (!tool)
+ return;
+
+ wl_resource_for_each(resource, focus_resource_list) {
+ struct wl_resource *tool_resource;
+
+ tool_resource = wl_resource_find_for_client(
+ &tool->resource_list, surface_client);
+ if (!tool_resource) {
+ tool_resource = wl_resource_create(
+ surface_client, &wl_tablet_tool_interface,
+ 1, 0);
+
+ wl_resource_set_implementation(
+ tool_resource, &tablet_tool_interface, tool,
+ unbind_tablet_tool_resource);
+
+ wl_list_insert(
+ &tool->resource_list,
+ wl_resource_get_link(tool_resource));
+
+ wl_tablet_manager_send_tool_added(
+ wl_resource_find_for_client(
+ &seat->tablet_manager_resource_list,
+ surface_client),
+ tool_resource, tool->type, tool->serial);
+ }
+
wl_tablet_send_proximity_in(resource,
tablet->focus_serial,
- time, NULL,
+ time, tool_resource,
view->surface->resource);
+ }
} else if (tablet->sprite)
tablet_unmap_sprite(tablet);
@@ -1785,6 +1829,17 @@ notify_tablet_added(struct weston_tablet *tablet)
}
WL_EXPORT void
+notify_tablet_proximity_in(struct weston_tablet *tablet,
+ uint32_t time, struct weston_tablet_tool *tool)
+{
+ struct weston_tablet_grab *grab = tablet->grab;
+
+ tablet->current_tool = tool;
+
+ grab->interface->proximity_in(grab, time, tool);
+}
+
+WL_EXPORT void
notify_tablet_proximity_out(struct weston_tablet *tablet, uint32_t time)
{
struct weston_tablet_grab *grab = tablet->grab;
@@ -2087,6 +2142,30 @@ static const struct wl_seat_interface seat_interface = {
seat_get_touch,
};
+static void unbind_tablet_tool_resource(struct wl_resource *resource)
+{
+ struct weston_tablet_tool *tool = wl_resource_get_user_data(resource);
+
+ unbind_resource(resource);
+
+ if (wl_list_empty(&tool->resource_list)) {
+ wl_signal_emit(&tool->destroy_signal, tool);
+
+ wl_list_remove(&tool->link);
+ free(tool);
+ }
+}
+
+static void
+tablet_tool_release(struct wl_client *client, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static const struct wl_tablet_tool_interface tablet_tool_interface = {
+ tablet_tool_release,
+};
+
static void
tablet_release(struct wl_client *client, struct wl_resource *resource)
{
@@ -2658,6 +2737,7 @@ weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
wl_signal_init(&seat->updated_caps_signal);
wl_list_init(&seat->tablet_list);
wl_list_init(&seat->tablet_manager_resource_list);
+ wl_list_init(&seat->tablet_tool_list);
seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 4,
seat, bind_seat);
diff --git a/src/libinput-device.c b/src/libinput-device.c
index f5ed2a0..0501e9b 100644
--- a/src/libinput-device.c
+++ b/src/libinput-device.c
@@ -218,6 +218,74 @@ handle_touch_frame(struct libinput_device *libinput_device,
notify_touch_frame(seat);
}
+struct tool_destroy_listener {
+ struct wl_listener base;
+ struct libinput_tool *tool;
+};
+
+/* Because a libinput tool has the potential to stay in the memory after the
+ * last tablet disconnects, we need to make sure that we clear the user data on
+ * the tool after one of our tool objects is destroyed */
+static void
+reset_libinput_tool_data(struct wl_listener *listener, void *data)
+{
+ struct tool_destroy_listener *tool_destroy_listener =
+ container_of(listener, struct tool_destroy_listener, base);
+
+ libinput_tool_set_user_data(tool_destroy_listener->tool, NULL);
+ free(tool_destroy_listener);
+}
+
+static void
+handle_tablet_proximity_in(struct libinput_device *libinput_device,
+ struct libinput_event_tablet *proximity_in_event)
+{
+ struct evdev_device *device =
+ libinput_device_get_user_data(libinput_device);
+ struct weston_tablet *tablet = device->tablet;
+ struct libinput_tool *libinput_tool;
+ struct weston_tablet_tool *tool;
+ uint32_t time;
+
+ time = libinput_event_tablet_get_time(proximity_in_event);
+ libinput_tool = libinput_event_tablet_get_tool(proximity_in_event);
+ tool = libinput_tool_get_user_data(libinput_tool);
+ if (!tool) {
+ struct tool_destroy_listener *listener;
+
+ listener = malloc(sizeof *listener);
+ if (!listener) {
+ weston_log("failed to allocate memory for a new tablet "
+ "tool destroy listener, events with this "
+ "tool will be dropped\n");
+ return;
+ }
+
+ tool = malloc(sizeof *tool);
+ if (!tool) {
+ weston_log("failed to allocate memory for a new "
+ "tablet tool, events from this tool will be "
+ "dropped\n");
+ free(listener);
+ return;
+ }
+
+ tool->type = libinput_tool_get_type(libinput_tool);
+ tool->serial = libinput_tool_get_serial(libinput_tool);
+ wl_list_init(&tool->resource_list);
+ wl_list_insert(&tablet->seat->tablet_tool_list, &tool->link);
+
+ listener->base.notify = reset_libinput_tool_data;
+ listener->tool = libinput_tool;
+ wl_signal_init(&tool->destroy_signal);
+ wl_signal_add(&tool->destroy_signal, &listener->base);
+
+ libinput_tool_set_user_data(libinput_tool, tool);
+ }
+
+ notify_tablet_proximity_in(tablet, time, tool);
+}
+
static void
handle_tablet_axis(struct libinput_device *libinput_device,
struct libinput_event_tablet *axis_event)
@@ -312,6 +380,10 @@ evdev_device_process_event(struct libinput_event *event)
handle_tablet_axis(libinput_device,
libinput_event_get_tablet_event(event));
break;
+ case LIBINPUT_EVENT_TABLET_PROXIMITY_IN:
+ handle_tablet_proximity_in(
+ libinput_device, libinput_event_get_tablet_event(event));
+ break;
case LIBINPUT_EVENT_TABLET_PROXIMITY_OUT:
handle_tablet_proximity_out(
libinput_device,
--
1.8.5.5
More information about the wayland-devel
mailing list