Signed-off-by: Stephen Chandler Paul <thatsly...@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 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel