swc

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

commit f7e35b15b2e6413d5399c3b04753c1ba3c212ee5
parent a15785e7a51769d04f06f8e3dba9e3c0ae7ae640
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Wed, 26 May 2021 12:40:26 -0500

send cancel point leaves window

Diffstat:
Mlibswc/touch.c | 87++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Mlibswc/touch.h | 13+++++++++++--
2 files changed, 73 insertions(+), 27 deletions(-)

diff --git a/libswc/touch.c b/libswc/touch.c @@ -131,7 +131,7 @@ client_handle_down(struct touch_handler *handler, uint32_t time, int32_t id, wl_ struct touch *touch = wl_container_of(handler, touch, client_handler); struct point *point; struct wl_resource *surface = NULL; - struct wl_resource *resource; + struct touch_client *client; wl_fixed_t sx, sy; wl_array_for_each (point, &touch->points) { @@ -145,11 +145,15 @@ client_handle_down(struct touch_handler *handler, uint32_t time, int32_t id, wl_ 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); + wl_list_for_each (client, &touch->clients, link) { + if (wl_resource_get_client(client->resource) == wl_resource_get_client(surface)) { + point->client = client; + wl_touch_send_down(client->resource, point->serial, time, surface, id, sx, sy); + client->needs_frame = true; + } } return true; } @@ -160,11 +164,13 @@ 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; + struct touch_client *client; + uint32_t serial; wl_array_for_each (point, &touch->points) { if (point->id == id) { surface = point->view->surface->resource; + serial = point->serial; break; } } @@ -172,11 +178,17 @@ client_handle_up(struct touch_handler *handler, uint32_t time, int32_t id) 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); + + if (point->dead) + return true; + + wl_list_for_each (client, &touch->clients, link) { + if (wl_resource_get_client(client->resource) == wl_resource_get_client(surface)) { + wl_touch_send_up(client->resource, serial, time, id); + client->needs_frame = true; + } + } return true; } @@ -186,7 +198,7 @@ client_handle_motion(struct touch_handler *handler, uint32_t time, int32_t id, w struct touch *touch = wl_container_of(handler, touch, client_handler); struct point *point; struct wl_resource *surface = NULL; - struct wl_resource *resource; + struct touch_client *client; wl_fixed_t sx, sy; wl_array_for_each (point, &touch->points) { @@ -196,16 +208,25 @@ client_handle_motion(struct touch_handler *handler, uint32_t time, int32_t id, w } } - if (!surface) + if (!surface || point->dead) return true; + if (!rectangle_contains_point(&point->view->base.geometry, wl_fixed_to_int(x), wl_fixed_to_int(y))) { + point->dead = 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); + wl_list_for_each (client, &touch->clients, link) { + if (wl_resource_get_client(client->resource) == wl_resource_get_client(surface)) { + if (point->dead) + wl_touch_send_cancel(client->resource); + else + wl_touch_send_motion(client->resource, time, id, sx, sy); + client->needs_frame = true; + } } return true; } @@ -214,11 +235,14 @@ static bool client_handle_frame(struct touch_handler *handler) { struct touch *touch = wl_container_of(handler, touch, client_handler); - struct wl_resource *resource; + struct touch_client *client; /* TODO only send to clients that received touch events since last frame */ - wl_resource_for_each (resource, &touch->resources) { - wl_touch_send_frame(resource); + wl_list_for_each (client, &touch->clients, link) { + if (client->needs_frame) { + wl_touch_send_frame(client->resource); + client->needs_frame = false; + } } return true; } @@ -227,12 +251,11 @@ static bool client_handle_cancel(struct touch_handler *handler) { struct touch *touch = wl_container_of(handler, touch, client_handler); - struct wl_resource *resource; + struct touch_client *client; + + wl_list_for_each (client, &touch->clients, link) + wl_touch_send_cancel(client->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; } @@ -246,7 +269,7 @@ touch_create() goto error0; wl_array_init(&touch->points); - wl_list_init(&touch->resources); + wl_list_init(&touch->clients); touch->focus_handler.enter = ifhandler; touch->focus_handler.leave = ifhandler; @@ -266,6 +289,14 @@ error0: return NULL; } +static void +touch_remove_resource(struct wl_resource *res) +{ + struct touch_client *client = wl_resource_get_user_data(res); + wl_list_remove(&client->link); + free(client); +} + static const struct wl_touch_interface touch_impl = { .release = destroy_resource }; @@ -274,12 +305,18 @@ struct wl_resource * touch_bind(struct touch *touch, struct wl_client *client, uint32_t version, uint32_t id) { struct wl_resource *client_resource; + struct touch_client *touch_client = malloc(sizeof(*touch_client)); + if (!touch_client) + return NULL; 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, &remove_resource); + wl_resource_set_implementation(client_resource, &touch_impl, touch_client, &touch_remove_resource); + + touch_client->resource = client_resource; + touch_client->needs_frame = false; - wl_list_insert(&touch->resources, wl_resource_get_link(client_resource)); + wl_list_insert(&touch->clients, &touch_client->link); return client_resource; } diff --git a/libswc/touch.h b/libswc/touch.h @@ -1,6 +1,8 @@ #ifndef SWC_TOUCH_H #define SWC_TOUCH_H +#include <wayland-server.h> +#include <wayland-util.h> #include "input.h" #include "view.h" @@ -14,11 +16,19 @@ struct touch_handler { struct wl_list link; }; +struct touch_client { + struct wl_list link; + struct wl_resource *resource; + /* if a client receives a touch event, it needs to receive a frame event */ + bool needs_frame; +}; + struct point { wl_fixed_t x, y; int32_t id; uint32_t last_update, serial; struct compositor_view *view; + struct touch_client *client; bool dead; }; @@ -29,8 +39,7 @@ struct touch { struct wl_list handlers; struct wl_array points; - /* TODO: store resources by client */ - struct wl_list resources; + struct wl_list clients; }; void touch_handle_down(struct touch *touch, uint32_t time, int32_t slot, wl_fixed_t x, wl_fixed_t y);