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:
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);