} cursor;
} parent;
+ struct weston_touch_device *touch_device;
+
enum weston_key_state_update keyboard_state_update;
uint32_t key_serial;
uint32_t enter_serial;
};
+static struct weston_touch_device *
+create_touch_device(struct wayland_input *input)
+{
+ struct weston_touch_device *touch_device;
+ char str[128];
+
+ /* manufacture a unique'ish name */
+ snprintf(str, sizeof str, "wayland-touch[%u]",
+ wl_proxy_get_id((struct wl_proxy *)input->parent.seat));
+
+ touch_device = weston_touch_create_touch_device(input->base.touch_state,
+ str, NULL, NULL);
+
+ return touch_device;
+}
+
static void
input_handle_capabilities(void *data, struct wl_seat *seat,
enum wl_seat_capability caps)
wl_touch_add_listener(input->parent.touch,
&touch_listener, input);
weston_seat_init_touch(&input->base);
+ input->touch_device = create_touch_device(input);
} else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->parent.touch) {
+ weston_touch_device_destroy(input->touch_device);
+ input->touch_device = NULL;
if (input->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION)
wl_touch_release(input->parent.touch);
else
struct wl_list timestamps_list;
};
+/** libinput style calibration matrix
+ *
+ * See https://wayland.freedesktop.org/libinput/doc/latest/absolute_axes.html
+ * and libinput_device_config_calibration_set_matrix().
+ */
+struct weston_touch_device_matrix {
+ float m[6];
+};
+
+struct weston_touch_device;
+
+/** Operations for a calibratable touchscreen */
+struct weston_touch_device_ops {
+ /** Get the associated output if existing. */
+ struct weston_output *(*get_output)(struct weston_touch_device *device);
+
+ /** Get the name of the associated head if existing. */
+ const char *
+ (*get_calibration_head_name)(struct weston_touch_device *device);
+
+ /** Retrieve the current calibration matrix. */
+ void (*get_calibration)(struct weston_touch_device *device,
+ struct weston_touch_device_matrix *cal);
+
+ /** Set a new calibration matrix. */
+ void (*set_calibration)(struct weston_touch_device *device,
+ const struct weston_touch_device_matrix *cal);
+};
+
+/** Represents a physical touchscreen input device */
+struct weston_touch_device {
+ char *syspath; /**< unique name */
+ struct weston_touch *aggregate; /**< weston_touch this is part of */
+ struct wl_list link; /**< in weston_touch::device_list */
+ struct wl_signal destroy_signal; /**< destroy notifier */
+
+ void *backend_data; /**< backend-specific private */
+
+ const struct weston_touch_device_ops *ops;
+};
+
+/** Represents a set of touchscreen devices aggregated under a seat */
struct weston_touch {
struct weston_seat *seat;
+ struct wl_list device_list; /* struct weston_touch_device::link */
+
struct wl_list resource_list;
struct wl_list focus_resource_list;
struct weston_view *focus;
void
weston_touch_send_frame(struct weston_touch *touch);
+struct weston_touch_device *
+weston_touch_create_touch_device(struct weston_touch *touch,
+ const char *syspath,
+ void *backend_data,
+ const struct weston_touch_device_ops *ops);
+
+void
+weston_touch_device_destroy(struct weston_touch_device *device);
+
+bool
+weston_touch_device_can_calibrate(struct weston_touch_device *device);
+
void
wl_data_device_set_keyboard_focus(struct weston_seat *seat);
/*
* Copyright © 2013 Intel Corporation
+ * Copyright 2017-2018 Collabora, Ltd.
+ * Copyright 2017-2018 General Electric Company
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
}
}
+/** Register a touchscreen input device
+ *
+ * \param touch The parent weston_touch that identifies the seat.
+ * \param syspath Unique device name.
+ * \param backend_data Backend private data if necessary.
+ * \param ops Calibration operations, or NULL for not able to run calibration.
+ * \return New touch device, or NULL on failure.
+ */
+WL_EXPORT struct weston_touch_device *
+weston_touch_create_touch_device(struct weston_touch *touch,
+ const char *syspath,
+ void *backend_data,
+ const struct weston_touch_device_ops *ops)
+{
+ struct weston_touch_device *device;
+
+ assert(syspath);
+ if (ops) {
+ assert(ops->get_output);
+ assert(ops->get_calibration_head_name);
+ assert(ops->get_calibration);
+ assert(ops->set_calibration);
+ }
+
+ device = zalloc(sizeof *device);
+ if (!device)
+ return NULL;
+
+ wl_signal_init(&device->destroy_signal);
+
+ device->syspath = strdup(syspath);
+ if (!device->syspath) {
+ free(device);
+ return NULL;
+ }
+
+ device->backend_data = backend_data;
+ device->ops = ops;
+
+ device->aggregate = touch;
+ wl_list_insert(touch->device_list.prev, &device->link);
+
+ return device;
+}
+
+/** Destroy the touch device. */
+WL_EXPORT void
+weston_touch_device_destroy(struct weston_touch_device *device)
+{
+ wl_list_remove(&device->link);
+ wl_signal_emit(&device->destroy_signal, device);
+ free(device->syspath);
+ free(device);
+}
+
+/** Is it possible to run calibration on this touch device? */
+WL_EXPORT bool
+weston_touch_device_can_calibrate(struct weston_touch_device *device)
+{
+ return !!device->ops;
+}
+
static struct weston_pointer_client *
weston_pointer_client_create(struct wl_client *client)
{
if (touch == NULL)
return NULL;
+ wl_list_init(&touch->device_list);
wl_list_init(&touch->resource_list);
wl_list_init(&touch->focus_resource_list);
wl_list_init(&touch->focus_view_listener.link);
{
struct wl_resource *resource;
+ assert(wl_list_empty(&touch->device_list));
+
wl_resource_for_each(resource, &touch->resource_list) {
wl_resource_set_user_data(resource, NULL);
}
/*
* Copyright © 2010 Intel Corporation
* Copyright © 2013 Jonas Ådahl
+ * Copyright 2017-2018 Collabora, Ltd.
+ * Copyright 2017-2018 General Electric Company
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
return true;
}
+static struct weston_output *
+touch_get_output(struct weston_touch_device *device)
+{
+ struct evdev_device *evdev_device = device->backend_data;
+
+ return evdev_device->output;
+}
+
+static const char *
+touch_get_calibration_head_name(struct weston_touch_device *device)
+{
+ struct evdev_device *evdev_device = device->backend_data;
+ struct weston_output *output = evdev_device->output;
+ struct weston_head *head;
+
+ if (!output)
+ return NULL;
+
+ assert(output->enabled);
+ if (evdev_device->output_name)
+ return evdev_device->output_name;
+
+ /* No specific head was configured, so the association was made by
+ * the default rule. Just grab whatever head's name.
+ */
+ wl_list_for_each(head, &output->head_list, output_link)
+ return head->name;
+
+ assert(0);
+ return NULL;
+}
+
+static void
+touch_get_calibration(struct weston_touch_device *device,
+ struct weston_touch_device_matrix *cal)
+{
+ struct evdev_device *evdev_device = device->backend_data;
+
+ libinput_device_config_calibration_get_matrix(evdev_device->device,
+ cal->m);
+}
+
+static void
+do_set_calibration(struct evdev_device *evdev_device,
+ const struct weston_touch_device_matrix *cal)
+{
+ enum libinput_config_status status;
+
+ status = libinput_device_config_calibration_set_matrix(evdev_device->device,
+ cal->m);
+ if (status != LIBINPUT_CONFIG_STATUS_SUCCESS)
+ weston_log("Failed to apply calibration.\n");
+}
+
+static void
+touch_set_calibration(struct weston_touch_device *device,
+ const struct weston_touch_device_matrix *cal)
+{
+ struct evdev_device *evdev_device = device->backend_data;
+
+ /* Stop output hotplug from reloading the WL_CALIBRATION values.
+ * libinput will maintain the latest calibration for us.
+ */
+ evdev_device->override_wl_calibration = true;
+
+ do_set_calibration(evdev_device, cal);
+}
+
+static const struct weston_touch_device_ops touch_calibration_ops = {
+ .get_output = touch_get_output,
+ .get_calibration_head_name = touch_get_calibration_head_name,
+ .get_calibration = touch_get_calibration,
+ .set_calibration = touch_set_calibration
+};
+
+static struct weston_touch_device *
+create_touch_device(struct evdev_device *device)
+{
+ const struct weston_touch_device_ops *ops = NULL;
+ struct weston_touch_device *touch_device;
+ struct udev_device *udev_device;
+
+ if (libinput_device_config_calibration_has_matrix(device->device))
+ ops = &touch_calibration_ops;
+
+ udev_device = libinput_device_get_udev_device(device->device);
+ if (!udev_device)
+ return NULL;
+
+ touch_device = weston_touch_create_touch_device(device->seat->touch_state,
+ udev_device_get_syspath(udev_device),
+ device, ops);
+
+ udev_device_unref(udev_device);
+
+ if (!touch_device)
+ return NULL;
+
+ weston_log("Touchscreen - %s - %s\n",
+ libinput_device_get_name(device->device),
+ touch_device->syspath);
+
+ return touch_device;
+}
+
static void
handle_touch_with_coords(struct libinput_device *libinput_device,
struct libinput_event_touch *touch_event,
calibration) != 0)
return;
+ /* touch_set_calibration() has updated the values, do not load old
+ * values from WL_CALIBRATION.
+ */
+ if (device->override_wl_calibration)
+ return;
+
if (!device->output) {
weston_log("input device %s has no enabled output associated "
"(%s named), skipping calibration for now.\n",
LIBINPUT_DEVICE_CAP_TOUCH)) {
weston_seat_init_touch(seat);
device->seat_caps |= EVDEV_SEAT_TOUCH;
+ device->touch_device = create_touch_device(device);
}
libinput_device_set_user_data(libinput_device, device);
weston_seat_release_pointer(device->seat);
if (device->seat_caps & EVDEV_SEAT_KEYBOARD)
weston_seat_release_keyboard(device->seat);
- if (device->seat_caps & EVDEV_SEAT_TOUCH)
+ if (device->seat_caps & EVDEV_SEAT_TOUCH) {
+ weston_touch_device_destroy(device->touch_device);
weston_seat_release_touch(device->seat);
+ }
if (device->output)
wl_list_remove(&device->output_destroy_listener.link);
#include <linux/input.h>
#include <wayland-util.h>
#include <libinput.h>
+#include <stdbool.h>
#include "compositor.h"
struct weston_seat *seat;
enum evdev_device_seat_capability seat_caps;
struct libinput_device *device;
+ struct weston_touch_device *touch_device;
struct wl_list link;
struct weston_output *output;
struct wl_listener output_destroy_listener;
char *output_name;
int fd;
+ bool override_wl_calibration;
};
void
#include "shared/helpers.h"
#include "shared/timespec-util.h"
+#define MAX_TOUCH_DEVICES 32
+
struct weston_test {
struct weston_compositor *compositor;
struct weston_layer layer;
struct weston_process process;
struct weston_seat seat;
+ struct weston_touch_device *touch_device[MAX_TOUCH_DEVICES];
+ int nr_touch_devices;
bool is_seat_initialized;
};
wl_display_terminate(test->compositor->wl_display);
}
+static void
+touch_device_add(struct weston_test *test)
+{
+ char buf[128];
+ int i = test->nr_touch_devices;
+
+ assert(i < MAX_TOUCH_DEVICES);
+ assert(!test->touch_device[i]);
+
+ snprintf(buf, sizeof buf, "test-touch-device-%d", i);
+
+ test->touch_device[i] = weston_touch_create_touch_device(
+ test->seat.touch_state, buf, NULL, NULL);
+ test->nr_touch_devices++;
+}
+
+static void
+touch_device_remove(struct weston_test *test)
+{
+ int i = test->nr_touch_devices - 1;
+
+ assert(i >= 0);
+ assert(test->touch_device[i]);
+ weston_touch_device_destroy(test->touch_device[i]);
+ test->touch_device[i] = NULL;
+ --test->nr_touch_devices;
+}
+
static int
test_seat_init(struct weston_test *test)
{
if (weston_seat_init_keyboard(&test->seat, NULL) < 0)
return -1;
weston_seat_init_touch(&test->seat);
+ touch_device_add(test);
return 0;
}
static void
test_seat_release(struct weston_test *test)
{
+ while (test->nr_touch_devices > 0)
+ touch_device_remove(test);
+
assert(test->is_seat_initialized &&
"Trying to release already released test seat");
test->is_seat_initialized = false;
} else if (strcmp(device, "keyboard") == 0) {
weston_seat_release_keyboard(seat);
} else if (strcmp(device, "touch") == 0) {
+ touch_device_remove(test);
weston_seat_release_touch(seat);
} else if (strcmp(device, "seat") == 0) {
test_seat_release(test);
weston_seat_init_keyboard(seat, NULL);
} else if (strcmp(device, "touch") == 0) {
weston_seat_init_touch(seat);
+ touch_device_add(test);
} else if (strcmp(device, "seat") == 0) {
test_seat_init(test);
} else {