swc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/swc
Log | Files | Refs | README | LICENSE

commit a15785e7a51769d04f06f8e3dba9e3c0ae7ae640
parent 5761f826baad7cffdd37dbd84fd87a0cfbe02a3a
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Fri, 21 May 2021 20:55:50 -0500

touch: send events to focused client

Diffstat:
Mlibswc/compositor.c | 3++-
Mlibswc/seat.c | 13++++---------
Mlibswc/touch.c | 199+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mlibswc/touch.h | 22++++++++++++++++------
4 files changed, 201 insertions(+), 36 deletions(-)

diff --git a/libswc/compositor.c b/libswc/compositor.c @@ -754,7 +754,8 @@ handle_touch_down(struct touch_handler *handler, uint32_t time, int32_t slot, wl } } - touch_set_focus(swc.seat->touch, found ? view : NULL); + if (found) + touch_point_add(swc.seat->touch, view, slot, fx, fy); return false; } diff --git a/libswc/seat.c b/libswc/seat.c @@ -337,16 +337,11 @@ handle_libinput_data(int fd, uint32_t mask, void *data) y = wl_fixed_from_double(libinput_event_touch_get_y_transformed(event.t, rect->height)); touch_handle_motion(seat->base.touch, time, slot, x, y); break; - case LIBINPUT_EVENT_TOUCH_CANCEL: - event.t = libinput_event_get_touch_event(generic_event); - time = libinput_event_touch_get_time(event.t); - slot = libinput_event_touch_get_seat_slot(event.t); - touch_handle_cancel(seat->base.touch, time); - break; case LIBINPUT_EVENT_TOUCH_FRAME: - event.t = libinput_event_get_touch_event(generic_event); - time = libinput_event_touch_get_time(event.t); - touch_handle_frame(seat->base.touch, time); + touch_handle_frame(seat->base.touch); + break; + case LIBINPUT_EVENT_TOUCH_CANCEL: + touch_handle_cancel(seat->base.touch); break; default: break; diff --git a/libswc/touch.c b/libswc/touch.c @@ -1,60 +1,63 @@ #include <wayland-server.h> +#include "compositor.h" +#include "internal.h" +#include "surface.h" #include "touch.h" #include "util.h" void -touch_handle_down(struct touch *touch, uint32_t time, int32_t slot, uint32_t x, uint32_t y) +touch_handle_down(struct touch *touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) { struct touch_handler *handler; wl_list_for_each (handler, &touch->handlers, link) { - if (handler->down && handler->down(handler, time, slot, x, y)) + if (handler->down && handler->down(handler, time, id, x, y)) break; } } void -touch_handle_up(struct touch *touch, uint32_t time, int32_t slot) +touch_handle_up(struct touch *touch, uint32_t time, int32_t id) { struct touch_handler *handler; wl_list_for_each (handler, &touch->handlers, link) { - if (handler->up && handler->up(handler, time, slot)) + if (handler->up && handler->up(handler, time, id)) break; } } void -touch_handle_motion(struct touch *touch, uint32_t time, int32_t slot, uint32_t x, uint32_t y) +touch_handle_motion(struct touch *touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) { struct touch_handler *handler; wl_list_for_each (handler, &touch->handlers, link) { - if (handler->motion && handler->motion(handler, time, slot, x, y)) + if (handler->motion && handler->motion(handler, time, id, x, y)) break; } } void -touch_handle_frame(struct touch *touch, uint32_t time) +touch_handle_frame(struct touch *touch) { struct touch_handler *handler; wl_list_for_each (handler, &touch->handlers, link) { - if (handler->frame && handler->frame(handler, time)) + if (handler->frame && handler->frame(handler)) break; } } void -touch_handle_cancel(struct touch *touch, uint32_t time) +touch_handle_cancel(struct touch *touch) { struct touch_handler *handler; wl_list_for_each (handler, &touch->handlers, link) { - if (handler->cancel && handler->cancel(handler, time)) + if (handler->cancel && handler->cancel(handler)) break; } } @@ -65,15 +68,52 @@ touch_set_focus(struct touch *touch, struct compositor_view *view) input_focus_set(&touch->focus, view); } -/* TODO these don't really make sense in the context of touch, - * but we need them for input focus for now */ -static void -enter(struct input_focus_handler *handler, struct wl_list *resources, struct compositor_view *view) +void +touch_point_add(struct touch *touch, struct compositor_view *view, int32_t id, wl_fixed_t x, wl_fixed_t y) +{ + struct point *point; + + point = wl_array_add(&touch->points, sizeof(*point)); + if (!point) + return; + + point->x = x; + point->y = y; + point->id = id; + point->view = view; + point->dead = false; +} + +void +touch_point_update(struct touch *touch, int32_t id, wl_fixed_t x, wl_fixed_t y) { + struct point *point; + + wl_array_for_each (point, &touch->points) { + if (point->id == id) { + point->x = x; + point->y = y; + break; + } + } } +void +touch_point_remove(struct touch *touch, int32_t id) +{ + struct point *point; + wl_array_for_each (point, &touch->points) { + if (point->id == id) { + array_remove(&touch->points, point, sizeof(*point)); + break; + } + } +} + +/* TODO these don't really make sense in the context of touch, + * but we need them for input focus for now */ static void -leave(struct input_focus_handler *handler, struct wl_list *resources, struct compositor_view *view) +ifhandler(struct input_focus_handler *handler, struct wl_list *resources, struct compositor_view *view) { } @@ -85,6 +125,117 @@ touch_destroy(struct touch *touch) free(touch); } +static bool +client_handle_down(struct touch_handler *handler, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) +{ + struct touch *touch = wl_container_of(handler, touch, client_handler); + struct point *point; + struct wl_resource *surface = NULL; + struct wl_resource *resource; + wl_fixed_t sx, sy; + + wl_array_for_each (point, &touch->points) { + if (point->id == id) { + surface = point->view->surface->resource; + break; + } + } + + if (!surface) + return true; + + point->serial = wl_display_next_serial(swc.display); + sx = x - wl_fixed_from_int(point->view->base.geometry.x); + sy = y - wl_fixed_from_int(point->view->base.geometry.y); + wl_resource_for_each (resource, &touch->resources) { + if (wl_resource_get_client(resource) == wl_resource_get_client(surface)) + wl_touch_send_down(resource, point->serial, time, surface, id, sx, sy); + } + return true; +} + +static bool +client_handle_up(struct touch_handler *handler, uint32_t time, int32_t id) +{ + struct touch *touch = wl_container_of(handler, touch, client_handler); + struct point *point; + struct wl_resource *surface = NULL; + struct wl_resource *resource; + + wl_array_for_each (point, &touch->points) { + if (point->id == id) { + surface = point->view->surface->resource; + break; + } + } + + if (!surface) + return true; + + wl_resource_for_each (resource, &touch->resources) { + if (wl_resource_get_client(resource) == wl_resource_get_client(surface)) + wl_touch_send_up(resource, point->serial, time, id); + } + touch_point_remove(touch, id); + return true; +} + +static bool +client_handle_motion(struct touch_handler *handler, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) +{ + struct touch *touch = wl_container_of(handler, touch, client_handler); + struct point *point; + struct wl_resource *surface = NULL; + struct wl_resource *resource; + wl_fixed_t sx, sy; + + wl_array_for_each (point, &touch->points) { + if (point->id == id) { + surface = point->view->surface->resource; + break; + } + } + + if (!surface) + return true; + + touch_point_update(touch, id, x, y); + + sx = x - wl_fixed_from_int(point->view->base.geometry.x); + sy = y - wl_fixed_from_int(point->view->base.geometry.y); + wl_resource_for_each (resource, &touch->resources) { + if (wl_resource_get_client(resource) == wl_resource_get_client(surface)) + wl_touch_send_motion(resource, time, id, sx, sy); + } + return true; +} + +static bool +client_handle_frame(struct touch_handler *handler) +{ + struct touch *touch = wl_container_of(handler, touch, client_handler); + struct wl_resource *resource; + + /* TODO only send to clients that received touch events since last frame */ + wl_resource_for_each (resource, &touch->resources) { + wl_touch_send_frame(resource); + } + return true; +} + +static bool +client_handle_cancel(struct touch_handler *handler) +{ + struct touch *touch = wl_container_of(handler, touch, client_handler); + struct wl_resource *resource; + + /* TODO only send to clients that received touch events since last frame */ + wl_resource_for_each (resource, &touch->resources) { + wl_touch_send_frame(resource); + } + return true; +} + struct touch * touch_create() { @@ -94,13 +245,21 @@ touch_create() if (!touch) goto error0; - wl_list_init(&touch->handlers); wl_array_init(&touch->points); + wl_list_init(&touch->resources); - touch->focus_handler.enter = enter; - touch->focus_handler.leave = leave; + touch->focus_handler.enter = ifhandler; + touch->focus_handler.leave = ifhandler; input_focus_initialize(&touch->focus, &touch->focus_handler); + wl_list_init(&touch->handlers); + touch->client_handler.down = client_handle_down; + touch->client_handler.up = client_handle_up; + touch->client_handler.motion = client_handle_motion; + touch->client_handler.frame = client_handle_frame; + touch->client_handler.cancel = client_handle_cancel; + wl_list_insert(&touch->handlers, &touch->client_handler.link); + return touch; error0: @@ -119,8 +278,8 @@ touch_bind(struct touch *touch, struct wl_client *client, uint32_t version, uint client_resource = wl_resource_create(client, &wl_touch_interface, version, id); if (!client_resource) return NULL; - wl_resource_set_implementation(client_resource, &touch_impl, touch, NULL); + wl_resource_set_implementation(client_resource, &touch_impl, touch, &remove_resource); - input_focus_add_resource(&touch->focus, client_resource); + wl_list_insert(&touch->resources, wl_resource_get_link(client_resource)); return client_resource; } diff --git a/libswc/touch.h b/libswc/touch.h @@ -8,30 +8,40 @@ struct touch_handler { bool (*down)(struct touch_handler *handler, uint32_t time, int32_t slot, wl_fixed_t x, wl_fixed_t y); bool (*up)(struct touch_handler *handler, uint32_t time, int32_t slot); bool (*motion)(struct touch_handler *handler, uint32_t time, int32_t slot, wl_fixed_t x, wl_fixed_t y); - bool (*frame)(struct touch_handler *handler, uint32_t time); - bool (*cancel)(struct touch_handler *handler, uint32_t time); + bool (*frame)(struct touch_handler *handler); + bool (*cancel)(struct touch_handler *handler); struct wl_list link; }; struct point { wl_fixed_t x, y; + int32_t id; + uint32_t last_update, serial; + struct compositor_view *view; + bool dead; }; struct touch { struct input_focus focus; struct input_focus_handler focus_handler; + struct touch_handler client_handler; struct wl_list handlers; struct wl_array points; + /* TODO: store resources by client */ + struct wl_list resources; }; -void touch_handle_down(struct touch *touch, uint32_t time, int32_t slot, uint32_t x, uint32_t y); +void touch_handle_down(struct touch *touch, uint32_t time, int32_t slot, wl_fixed_t x, wl_fixed_t y); void touch_handle_up(struct touch *touch, uint32_t time, int32_t slot); -void touch_handle_motion(struct touch *touch, uint32_t time, int32_t slot, uint32_t x, uint32_t y); -void touch_handle_frame(struct touch *touch, uint32_t time); -void touch_handle_cancel(struct touch *touch, uint32_t time); +void touch_handle_motion(struct touch *touch, uint32_t time, int32_t slot, wl_fixed_t x, wl_fixed_t y); +void touch_handle_frame(struct touch *touch); +void touch_handle_cancel(struct touch *touch); void touch_set_focus(struct touch *touch, struct compositor_view *view); +void touch_point_add(struct touch *touch, struct compositor_view *view, int32_t id, wl_fixed_t x, wl_fixed_t y); +void touch_point_update(struct touch *touch, int32_t id, wl_fixed_t x, wl_fixed_t y); +void touch_point_remove(struct touch *touch, int32_t id); void touch_destroy(struct touch *touch); struct touch *touch_create(); struct wl_resource *touch_bind(struct touch *touch, struct wl_client *client, uint32_t version, uint32_t id);