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