From 041815aa0570b53eb587b960ded70a5a4c8d8184 Mon Sep 17 00:00:00 2001 From: Rusty Lynch Date: Thu, 8 Aug 2013 21:20:38 -0700 Subject: [PATCH] window.c: Add touch handlers This adds basic infrastructure for handling touch events in the toytoolkit. --- clients/window.c | 236 +++++++++++++++++++++++++++++++++++++++++++++++ clients/window.h | 36 +++++++- 2 files changed, 271 insertions(+), 1 deletion(-) diff --git a/clients/window.c b/clients/window.c index cbf8bf58..ae1bc6ad 100644 --- a/clients/window.c +++ b/clients/window.c @@ -274,6 +274,11 @@ struct widget { widget_leave_handler_t leave_handler; widget_motion_handler_t motion_handler; widget_button_handler_t button_handler; + widget_touch_down_handler_t touch_down_handler; + widget_touch_up_handler_t touch_up_handler; + widget_touch_motion_handler_t touch_motion_handler; + widget_touch_frame_handler_t touch_frame_handler; + widget_touch_cancel_handler_t touch_cancel_handler; widget_axis_handler_t axis_handler; void *user_data; int opaque; @@ -281,13 +286,22 @@ struct widget { int default_cursor; }; +struct touch_point { + int32_t id; + struct widget *widget; + struct wl_list link; +}; + struct input { struct display *display; struct wl_seat *seat; struct wl_pointer *pointer; struct wl_keyboard *keyboard; + struct wl_touch *touch; + struct wl_list touch_point_list; struct window *pointer_focus; struct window *keyboard_focus; + struct window *touch_focus; int current_cursor; uint32_t cursor_anim_start; struct wl_callback *cursor_frame_cb; @@ -1889,6 +1903,41 @@ widget_set_button_handler(struct widget *widget, widget->button_handler = handler; } +void +widget_set_touch_up_handler(struct widget *widget, + widget_touch_up_handler_t handler) +{ + widget->touch_up_handler = handler; +} + +void +widget_set_touch_down_handler(struct widget *widget, + widget_touch_down_handler_t handler) +{ + widget->touch_down_handler = handler; +} + +void +widget_set_touch_motion_handler(struct widget *widget, + widget_touch_motion_handler_t handler) +{ + widget->touch_motion_handler = handler; +} + +void +widget_set_touch_frame_handler(struct widget *widget, + widget_touch_frame_handler_t handler) +{ + widget->touch_frame_handler = handler; +} + +void +widget_set_touch_cancel_handler(struct widget *widget, + widget_touch_cancel_handler_t handler) +{ + widget->touch_cancel_handler = handler; +} + void widget_set_axis_handler(struct widget *widget, widget_axis_handler_t handler) @@ -2303,6 +2352,35 @@ frame_button_button_handler(struct widget *widget, } } +static void +frame_button_touch_down_handler(struct widget *widget, uint32_t serial, + uint32_t time, int32_t id, + float x, float y, void *data) +{ + struct frame_button *frame_button = data; + struct window *window = widget->window; + + switch (frame_button->type) { + case FRAME_BUTTON_CLOSE: + if (window->close_handler) + window->close_handler(window->parent, + window->user_data); + else + display_exit(window->display); + break; + case FRAME_BUTTON_MINIMIZE: + fprintf(stderr,"Minimize stub\n"); + break; + case FRAME_BUTTON_MAXIMIZE: + window_set_maximized(window, window->type != TYPE_MAXIMIZED); + break; + default: + /* Unknown operation */ + break; + } +} + + static int frame_button_motion_handler(struct widget *widget, struct input *input, uint32_t time, @@ -2402,6 +2480,7 @@ frame_button_create(struct frame *frame, void *data, enum frame_button_action ty widget_set_redraw_handler(frame_button->widget, frame_button_redraw_handler); widget_set_enter_handler(frame_button->widget, frame_button_enter_handler); widget_set_leave_handler(frame_button->widget, frame_button_leave_handler); + widget_set_touch_down_handler(frame_button->widget, frame_button_touch_down_handler); widget_set_button_handler(frame_button->widget, frame_button_button_handler); widget_set_motion_handler(frame_button->widget, frame_button_motion_handler); return frame_button->widget; @@ -3115,6 +3194,153 @@ static const struct wl_keyboard_listener keyboard_listener = { keyboard_handle_modifiers, }; +static void +touch_handle_down(void *data, struct wl_touch *wl_touch, + uint32_t serial, uint32_t time, struct wl_surface *surface, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + struct input *input = data; + struct widget *widget; + float sx = wl_fixed_to_double(x_w); + float sy = wl_fixed_to_double(y_w); + + DBG("touch_handle_down: %i %i\n", id, wl_list_length(&input->touch_point_list)); + + input->touch_focus = wl_surface_get_user_data(surface); + if (!input->touch_focus) { + DBG("Failed to find to touch focus for surface %p\n", surface); + return; + } + + widget = window_find_widget(input->touch_focus, + wl_fixed_to_double(x_w), + wl_fixed_to_double(y_w)); + if (widget) { + struct touch_point *tp = xmalloc(sizeof *tp); + if (tp) { + tp->id = id; + tp->widget = widget; + wl_list_insert(&input->touch_point_list, &tp->link); + + if (widget->touch_down_handler) + (*widget->touch_down_handler)(widget, serial, + time, id, + sx, sy, + widget->user_data); + } + } +} + +static void +touch_handle_up(void *data, struct wl_touch *wl_touch, + uint32_t serial, uint32_t time, int32_t id) +{ + struct input *input = data; + struct touch_point *tp, *tmp; + + DBG("touch_handle_up: %i %i\n", id, wl_list_length(&input->touch_point_list)); + + if (!input->touch_focus) { + DBG("No touch focus found for touch up event!\n"); + return; + } + + wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) { + if (tp->id != id) + continue; + + if (tp->widget->touch_up_handler) + (*tp->widget->touch_up_handler)(tp->widget, serial, + time, id, + tp->widget->user_data); + + wl_list_remove(&tp->link); + free(tp); + + return; + } +} + +static void +touch_handle_motion(void *data, struct wl_touch *wl_touch, + uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + struct input *input = data; + struct touch_point *tp; + float sx = wl_fixed_to_double(x_w); + float sy = wl_fixed_to_double(y_w); + + DBG("touch_handle_motion: %i %i\n", id, wl_list_length(&input->touch_point_list)); + + if (!input->touch_focus) { + DBG("No touch focus found for touch motion event!\n"); + return; + } + + wl_list_for_each(tp, &input->touch_point_list, link) { + if (tp->id != id) + continue; + + if (tp->widget->touch_motion_handler) + (*tp->widget->touch_motion_handler)(tp->widget, time, + id, sx, sy, + tp->widget->user_data); + return; + } +} + +static void +touch_handle_frame(void *data, struct wl_touch *wl_touch) +{ + struct input *input = data; + struct touch_point *tp, *tmp; + + DBG("touch_handle_frame\n"); + + if (!input->touch_focus) { + DBG("No touch focus found for touch frame event!\n"); + return; + } + + wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) { + if (tp->widget->touch_frame_handler) + (*tp->widget->touch_frame_handler)(tp->widget, tp->widget->user_data); + + wl_list_remove(&tp->link); + free(tp); + } +} + +static void +touch_handle_cancel(void *data, struct wl_touch *wl_touch) +{ + struct input *input = data; + struct touch_point *tp, *tmp; + + DBG("touch_handle_cancel\n"); + + if (!input->touch_focus) { + DBG("No touch focus found for touch cancel event!\n"); + return; + } + + wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) { + if (tp->widget->touch_cancel_handler) + (*tp->widget->touch_cancel_handler)(tp->widget, tp->widget->user_data); + + wl_list_remove(&tp->link); + free(tp); + } +} + +static const struct wl_touch_listener touch_listener = { + touch_handle_down, + touch_handle_up, + touch_handle_motion, + touch_handle_frame, + touch_handle_cancel, +}; + static void seat_handle_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability caps) @@ -3140,6 +3366,15 @@ seat_handle_capabilities(void *data, struct wl_seat *seat, wl_keyboard_destroy(input->keyboard); input->keyboard = NULL; } + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) { + input->touch = wl_seat_get_touch(seat); + wl_touch_set_user_data(input->touch, input); + wl_touch_add_listener(input->touch, &touch_listener, input); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch) { + wl_touch_destroy(input->touch); + input->touch = NULL; + } } static const struct wl_seat_listener seat_listener = { @@ -4693,6 +4928,7 @@ display_add_input(struct display *d, uint32_t id) input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1); input->pointer_focus = NULL; input->keyboard_focus = NULL; + wl_list_init(&input->touch_point_list); wl_list_insert(d->input_list.prev, &input->link); wl_seat_add_listener(input->seat, &seat_listener, input); diff --git a/clients/window.h b/clients/window.h index 3c600819..a8177341 100644 --- a/clients/window.h +++ b/clients/window.h @@ -232,6 +232,26 @@ typedef void (*widget_button_handler_t)(struct widget *widget, uint32_t button, enum wl_pointer_button_state state, void *data); +typedef void (*widget_touch_down_handler_t)(struct widget *widget, + uint32_t serial, + uint32_t time, + int32_t id, + float x, + float y, + void *data); +typedef void (*widget_touch_up_handler_t)(struct widget *widget, + uint32_t serial, + uint32_t time, + int32_t id, + void *data); +typedef void (*widget_touch_motion_handler_t)(struct widget *widget, + uint32_t time, + int32_t id, + float x, + float y, + void *data); +typedef void (*widget_touch_frame_handler_t)(struct widget *widget,void *data); +typedef void (*widget_touch_cancel_handler_t)(struct widget *widget, void *data); typedef void (*widget_axis_handler_t)(struct widget *widget, struct input *input, uint32_t time, uint32_t axis, @@ -457,9 +477,23 @@ void widget_set_button_handler(struct widget *widget, widget_button_handler_t handler); void +widget_set_touch_down_handler(struct widget *widget, + widget_touch_down_handler_t handler); +void +widget_set_touch_up_handler(struct widget *widget, + widget_touch_up_handler_t handler); +void +widget_set_touch_motion_handler(struct widget *widget, + widget_touch_motion_handler_t handler); +void +widget_set_touch_frame_handler(struct widget *widget, + widget_touch_frame_handler_t handler); +void +widget_set_touch_cancel_handler(struct widget *widget, + widget_touch_cancel_handler_t handler); +void widget_set_axis_handler(struct widget *widget, widget_axis_handler_t handler); - void widget_schedule_redraw(struct widget *widget);