commit 45df267d3c6fdc4e2939d8d6dca95f1e0e6066cb
parent 0c3f36c5ac561cd2adcc9fc09fc8ad0abe6f371a
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Fri, 14 May 2021 22:39:25 -0500
initial touch support
Diffstat:
9 files changed, 214 insertions(+), 10 deletions(-)
diff --git a/libswc/compositor.c b/libswc/compositor.c
@@ -41,6 +41,7 @@
#include "seat.h"
#include "shm.h"
#include "surface.h"
+#include "touch.h"
#include "util.h"
#include "view.h"
@@ -62,11 +63,16 @@ struct target {
struct wl_listener screen_destroy_listener;
};
-static bool handle_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t x, wl_fixed_t y);
+static bool handle_pointer_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t x, wl_fixed_t y);
+static bool handle_touch_down(struct touch_handler *handler, uint32_t time, int32_t slot, wl_fixed_t x, wl_fixed_t y);
static void perform_update(void *data);
static struct pointer_handler pointer_handler = {
- .motion = handle_motion,
+ .motion = handle_pointer_motion,
+};
+
+static struct touch_handler touch_handler = {
+ .down = handle_touch_down,
};
static struct {
@@ -86,6 +92,7 @@ static struct {
struct swc_compositor swc_compositor = {
.pointer_handler = &pointer_handler,
+ .touch_handler = &touch_handler,
};
static void
@@ -698,7 +705,7 @@ perform_update(void *data)
}
bool
-handle_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t fx, wl_fixed_t fy)
+handle_pointer_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t fx, wl_fixed_t fy)
{
struct compositor_view *view;
bool found = false;
@@ -726,6 +733,13 @@ handle_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t fx, wl_
return false;
}
+bool
+handle_touch_down(struct touch_handler *handler, uint32_t time, int32_t slot, wl_fixed_t x, wl_fixed_t y)
+{
+ fprintf(stderr, "touch down\n");
+ return false;
+}
+
static void
handle_terminate(void *data, uint32_t time, uint32_t value, uint32_t state)
{
diff --git a/libswc/compositor.h b/libswc/compositor.h
@@ -32,6 +32,7 @@
struct swc_compositor {
struct pointer_handler *const pointer_handler;
+ struct touch_handler *const touch_handler;
struct {
/**
* Emitted when a new surface is created.
diff --git a/libswc/drm.c b/libswc/drm.c
@@ -301,6 +301,7 @@ drm_initialize(void)
ERROR("Could not find valid DRM device\n");
goto error0;
}
+ fprintf(stderr, "primary device: %s\n", primary);
swc.drm->fd = launch_open_device(primary, O_RDWR | O_CLOEXEC);
if (swc.drm->fd == -1) {
diff --git a/libswc/local.mk b/libswc/local.mk
@@ -49,6 +49,7 @@ SWC_SOURCES = \
libswc/subsurface.c \
libswc/surface.c \
libswc/swc.c \
+ libswc/touch.c \
libswc/util.c \
libswc/view.c \
libswc/wayland_buffer.c \
diff --git a/libswc/seat.c b/libswc/seat.c
@@ -31,6 +31,7 @@
#include "pointer.h"
#include "screen.h"
#include "surface.h"
+#include "touch.h"
#include "util.h"
#include <dirent.h>
@@ -144,7 +145,10 @@ get_keyboard(struct wl_client *client, struct wl_resource *resource, uint32_t id
static void
get_touch(struct wl_client *client, struct wl_resource *resource, uint32_t id)
{
- /* XXX: Implement */
+ struct seat *seat = wl_resource_get_user_data(resource);
+
+ if (!touch_bind(seat->base.touch, client, wl_resource_get_version(resource), id))
+ wl_resource_post_no_memory(resource);
}
static const struct wl_seat_interface seat_impl = {
@@ -212,10 +216,9 @@ device_capabilities(struct libinput_device *device)
capabilities |= WL_SEAT_CAPABILITY_KEYBOARD;
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER))
capabilities |= WL_SEAT_CAPABILITY_POINTER;
- /* TODO: Add touch device support
- * if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH))
- * capabilities |= WL_SEAT_CAPABILITY_TOUCH;
- */
+ if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH))
+ capabilities |= WL_SEAT_CAPABILITY_TOUCH;
+
return capabilities;
}
@@ -243,9 +246,10 @@ handle_libinput_data(int fd, uint32_t mask, void *data)
union {
struct libinput_event_keyboard *k;
struct libinput_event_pointer *p;
+ struct libinput_event_touch *t;
} event;
wl_fixed_t x, y;
- uint32_t time, key, state;
+ uint32_t time, key, slot, state;
if (libinput_dispatch(seat->libinput) != 0) {
WARNING("libinput_dispatch failed: %s\n", strerror(errno));
@@ -307,6 +311,43 @@ handle_libinput_data(int fd, uint32_t mask, void *data)
handle_libinput_axis_event(seat, event.p, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
handle_libinput_axis_event(seat, event.p, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
break;
+ case LIBINPUT_EVENT_TOUCH_DOWN:
+ screen = wl_container_of(swc.screens.next, screen, link);
+ rect = &screen->base.geometry;
+ 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);
+ x = wl_fixed_from_double(libinput_event_touch_get_x_transformed(event.t, rect->width));
+ y = wl_fixed_from_double(libinput_event_touch_get_y_transformed(event.t, rect->height));
+ touch_handle_down(seat->base.touch, time, slot, x, y);
+ break;
+ case LIBINPUT_EVENT_TOUCH_UP:
+ 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_up(seat->base.touch, time, slot);
+ break;
+ case LIBINPUT_EVENT_TOUCH_MOTION:
+ screen = wl_container_of(swc.screens.next, screen, link);
+ rect = &screen->base.geometry;
+ 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);
+ x = wl_fixed_from_double(libinput_event_touch_get_x_transformed(event.t, rect->width));
+ 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);
+ break;
default:
break;
}
@@ -413,11 +454,19 @@ seat_create(struct wl_display *display, const char *seat_name)
}
seat->base.pointer = &seat->pointer;
- if (!initialize_libinput(seat))
+ seat->base.touch = touch_create();
+ if (!seat->base.touch) {
+ ERROR("Could not initialize touch\n");
goto error6;
+ }
+
+ if (!initialize_libinput(seat))
+ goto error7;
return &seat->base;
+error7:
+ touch_destroy(seat->base.touch);
error6:
pointer_finalize(&seat->pointer);
error5:
diff --git a/libswc/seat.h b/libswc/seat.h
@@ -29,6 +29,7 @@ struct wl_display;
struct swc_seat {
struct pointer *pointer;
struct keyboard *keyboard;
+ struct touch *touch;
struct data_device *data_device;
};
diff --git a/libswc/swc.c b/libswc/swc.c
@@ -38,6 +38,7 @@
#include "shell.h"
#include "shm.h"
#include "subcompositor.h"
+#include "touch.h"
#include "util.h"
#include "window.h"
#include "xdg_decoration.h"
@@ -77,6 +78,7 @@ setup_compositor(void)
wl_list_insert(&swc.seat->pointer->handlers, &swc.compositor->pointer_handler->link);
wl_list_insert(&swc.seat->pointer->handlers, &screens_pointer_handler.link);
wl_signal_add(&swc.seat->pointer->focus.event_signal, &window_enter_listener);
+ wl_list_insert(&swc.seat->touch->handlers, &swc.compositor->touch_handler->link);
/* Calculate pointer region */
pixman_region32_init(&pointer_region);
diff --git a/libswc/touch.c b/libswc/touch.c
@@ -0,0 +1,103 @@
+#include <wayland-server.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)
+{
+ struct touch_handler *handler;
+
+ wl_list_for_each (handler, &touch->handlers, link) {
+
+ if (handler->down && handler->down(handler, time, slot, x, y))
+ break;
+ }
+}
+
+void
+touch_handle_up(struct touch *touch, uint32_t time, int32_t slot)
+{
+ struct touch_handler *handler;
+
+ wl_list_for_each (handler, &touch->handlers, link) {
+ if (handler->up && handler->up(handler, time, slot))
+ break;
+ }
+}
+
+void
+touch_handle_motion(struct touch *touch, uint32_t time, int32_t slot, uint32_t x, uint32_t y)
+{
+ struct touch_handler *handler;
+
+ wl_list_for_each (handler, &touch->handlers, link) {
+ if (handler->motion && handler->motion(handler, time, slot, x, y))
+ break;
+ }
+}
+
+void
+touch_handle_frame(struct touch *touch, uint32_t time)
+{
+ struct touch_handler *handler;
+
+ wl_list_for_each (handler, &touch->handlers, link) {
+ if (handler->frame && handler->frame(handler, time))
+ break;
+ }
+}
+
+void
+touch_handle_cancel(struct touch *touch, uint32_t time)
+{
+ struct touch_handler *handler;
+
+ wl_list_for_each (handler, &touch->handlers, link) {
+ if (handler->cancel && handler->cancel(handler, time))
+ break;
+ }
+}
+
+void
+touch_destroy(struct touch *touch)
+{
+ wl_array_release(&touch->points);
+ /* TODO free handlers? */
+ free(touch);
+}
+
+struct touch *
+touch_create()
+{
+ struct touch *touch;
+
+ touch = malloc(sizeof(*touch));
+ if (!touch)
+ goto error0;
+
+ wl_list_init(&touch->handlers);
+ wl_array_init(&touch->points);
+
+ return touch;
+
+error0:
+ return NULL;
+}
+
+static const struct wl_touch_interface touch_impl = {
+ .release = destroy_resource
+};
+
+struct wl_resource *
+touch_bind(struct touch *touch, struct wl_client *client, uint32_t version, uint32_t id)
+{
+ struct wl_resource *client_resource;
+
+ 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);
+
+ return client_resource;
+}
diff --git a/libswc/touch.h b/libswc/touch.h
@@ -0,0 +1,32 @@
+#ifndef SWC_TOUCH_H
+#define SWC_TOUCH_H
+
+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);
+
+ struct wl_list link;
+};
+
+struct point {
+ wl_fixed_t x, y;
+};
+
+struct touch {
+ struct wl_list handlers;
+ struct wl_array points;
+};
+
+void touch_handle_down(struct touch *touch, uint32_t time, int32_t slot, uint32_t x, uint32_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_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);
+
+#endif