From 1782d5e7b7dc5e494cfee72b758d5fa8114aecc8 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 20 Oct 2017 23:19:41 -0400 Subject: [PATCH] Implement simple touch support for rootston --- include/rootston/input.h | 22 +++++++++---- rootston/cursor.c | 70 ++++++++++++++++++++++++++++++++++++++-- rootston/input.c | 4 +-- rootston/meson.build | 1 + rootston/touch.c | 26 +++++++++++++++ 5 files changed, 113 insertions(+), 10 deletions(-) create mode 100644 rootston/touch.c diff --git a/include/rootston/input.h b/include/rootston/input.h index 516104a7..ddd5a05d 100644 --- a/include/rootston/input.h +++ b/include/rootston/input.h @@ -24,18 +24,12 @@ struct roots_keyboard { struct roots_pointer { struct roots_input *input; struct wlr_input_device *device; - // We don't listen to any pointer events directly - they go through - // wlr_cursor struct wl_list link; }; struct roots_touch { struct roots_input *input; struct wlr_input_device *device; - struct wl_listener down; - struct wl_listener up; - struct wl_listener motion; - struct wl_listener cancel; struct wl_list link; }; @@ -70,6 +64,13 @@ struct roots_input_event { struct wlr_input_device *device; }; +struct roots_touch_point { + struct roots_touch *device; + int32_t slot; + double x, y; + struct wl_list link; +}; + struct roots_input { struct roots_config *config; struct roots_server *server; @@ -104,9 +105,16 @@ struct roots_input { struct wl_listener cursor_motion_absolute; struct wl_listener cursor_button; struct wl_listener cursor_axis; + + struct wl_listener cursor_touch_down; + struct wl_listener cursor_touch_up; + struct wl_listener cursor_touch_motion; + struct wl_listener cursor_tool_axis; struct wl_listener cursor_tool_tip; + struct wl_list touch_points; + struct wl_listener pointer_grab_end; struct wl_listener request_set_cursor; @@ -120,6 +128,8 @@ void pointer_add(struct wlr_input_device *device, struct roots_input *input); void pointer_remove(struct wlr_input_device *device, struct roots_input *input); void keyboard_add(struct wlr_input_device *device, struct roots_input *input); void keyboard_remove(struct wlr_input_device *device, struct roots_input *input); +void touch_add(struct wlr_input_device *device, struct roots_input *input); +void touch_remove(struct wlr_input_device *device, struct roots_input *input); void tablet_tool_add(struct wlr_input_device *device, struct roots_input *input); void tablet_tool_remove(struct wlr_input_device *device, struct roots_input *input); diff --git a/rootston/cursor.c b/rootston/cursor.c index b312392d..27a6006b 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 700 +#include #include #include #include @@ -82,8 +83,8 @@ void cursor_update_position(struct roots_input *input, uint32_t time) { double sx, sy; switch (input->mode) { case ROOTS_CURSOR_PASSTHROUGH: - view = view_at(desktop, input->cursor->x, input->cursor->y, &surface, - &sx, &sy); + view = view_at(desktop, input->cursor->x, input->cursor->y, + &surface, &sx, &sy); bool set_compositor_cursor = !view && input->cursor_client; if (view) { struct wl_client *view_client = @@ -286,6 +287,56 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { (uint32_t)(event->time_usec / 1000), event->button, event->state); } +static void handle_touch_down(struct wl_listener *listener, void *data) { + struct wlr_event_touch_down *event = data; + struct roots_input *input = + wl_container_of(listener, input, cursor_touch_down); + struct roots_touch_point *point = + calloc(1, sizeof(struct roots_touch_point)); + point->device = event->device->data; + point->slot = event->slot; + point->x = event->x_mm / event->width_mm; + point->y = event->y_mm / event->height_mm; + wlr_cursor_warp_absolute(input->cursor, event->device, point->x, point->y); + cursor_update_position(input, (uint32_t)(event->time_usec / 1000)); + wl_list_insert(&input->touch_points, &point->link); + do_cursor_button_press(input, input->cursor, event->device, + (uint32_t)(event->time_usec / 1000), BTN_LEFT, 1); +} + +static void handle_touch_up(struct wl_listener *listener, void *data) { + struct wlr_event_touch_up *event = data; + struct roots_input *input = + wl_container_of(listener, input, cursor_touch_up); + struct roots_touch_point *point; + wl_list_for_each(point, &input->touch_points, link) { + if (point->slot == event->slot) { + wl_list_remove(&point->link); + break; + } + } + do_cursor_button_press(input, input->cursor, event->device, + (uint32_t)(event->time_usec / 1000), BTN_LEFT, 0); +} + +static void handle_touch_motion(struct wl_listener *listener, void *data) { + struct wlr_event_touch_motion *event = data; + struct roots_input *input = + wl_container_of(listener, input, cursor_touch_motion); + struct roots_touch_point *point; + wl_list_for_each(point, &input->touch_points, link) { + if (point->slot == event->slot) { + point->x = event->x_mm / event->width_mm; + point->y = event->y_mm / event->height_mm; + wlr_cursor_warp_absolute(input->cursor, event->device, + point->x, point->y); + cursor_update_position(input, + (uint32_t)(event->time_usec / 1000)); + break; + } + } +} + static void handle_tool_axis(struct wl_listener *listener, void *data) { struct roots_input *input = wl_container_of(listener, input, cursor_tool_axis); struct wlr_event_tablet_tool_axis *event = data; @@ -342,6 +393,9 @@ static void handle_request_set_cursor(struct wl_listener *listener, void cursor_initialize(struct roots_input *input) { struct wlr_cursor *cursor = input->cursor; + + // TODO: Does this belong here + wl_list_init(&input->touch_points); wl_list_init(&input->cursor_motion.link); wl_signal_add(&cursor->events.motion, &input->cursor_motion); @@ -360,6 +414,18 @@ void cursor_initialize(struct roots_input *input) { wl_signal_add(&cursor->events.axis, &input->cursor_axis); input->cursor_axis.notify = handle_cursor_axis; + wl_list_init(&input->cursor_touch_down.link); + wl_signal_add(&cursor->events.touch_down, &input->cursor_touch_down); + input->cursor_touch_down.notify = handle_touch_down; + + wl_list_init(&input->cursor_touch_up.link); + wl_signal_add(&cursor->events.touch_up, &input->cursor_touch_up); + input->cursor_touch_up.notify = handle_touch_up; + + wl_list_init(&input->cursor_touch_motion.link); + wl_signal_add(&cursor->events.touch_motion, &input->cursor_touch_motion); + input->cursor_touch_motion.notify = handle_touch_motion; + wl_list_init(&input->cursor_tool_axis.link); wl_signal_add(&cursor->events.tablet_tool_axis, &input->cursor_tool_axis); input->cursor_tool_axis.notify = handle_tool_axis; diff --git a/rootston/input.c b/rootston/input.c index 86a87e24..1784040c 100644 --- a/rootston/input.c +++ b/rootston/input.c @@ -37,7 +37,7 @@ static void input_add_notify(struct wl_listener *listener, void *data) { pointer_add(device, input); break; case WLR_INPUT_DEVICE_TOUCH: - //touch_add(device, input); + touch_add(device, input); break; case WLR_INPUT_DEVICE_TABLET_TOOL: tablet_tool_add(device, input); @@ -58,7 +58,7 @@ static void input_remove_notify(struct wl_listener *listener, void *data) { pointer_remove(device, input); break; case WLR_INPUT_DEVICE_TOUCH: - //touch_remove(device, input); + touch_remove(device, input); break; case WLR_INPUT_DEVICE_TABLET_TOOL: tablet_tool_remove(device, input); diff --git a/rootston/meson.build b/rootston/meson.build index 7ff79f8e..f2621450 100644 --- a/rootston/meson.build +++ b/rootston/meson.build @@ -9,6 +9,7 @@ sources = [ 'output.c', 'pointer.c', 'tablet_tool.c', + 'touch.c', 'xdg_shell_v6.c', 'wl_shell.c', ] diff --git a/rootston/touch.c b/rootston/touch.c new file mode 100644 index 00000000..f6d9b11a --- /dev/null +++ b/rootston/touch.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include "rootston/input.h" + +// TODO: we'll likely want touch events to both control the cursor *and* be +// submitted directly to the seat. + +void touch_add(struct wlr_input_device *device, struct roots_input *input) { + struct roots_touch *touch = calloc(sizeof(struct roots_touch), 1); + device->data = touch; + touch->device = device; + touch->input = input; + wl_list_insert(&input->touch, &touch->link); + wlr_cursor_attach_input_device(input->cursor, device); + cursor_load_config(input->server->config, input->cursor, + input, input->server->desktop); +} + +void touch_remove(struct wlr_input_device *device, struct roots_input *input) { + struct roots_touch *touch = device->data; + wlr_cursor_detach_input_device(input->cursor, device); + wl_list_remove(&touch->link); + free(touch); +}