backend/wayland: give wlr_touch ownership to wlr_wl_seat

This commit is contained in:
Simon Zeni 2022-03-07 13:33:20 -05:00 committed by Kirill Primak
parent e723dd928b
commit d3fb44314c
2 changed files with 59 additions and 77 deletions

View file

@ -21,8 +21,6 @@
#include "util/signal.h"
#include "util/time.h"
static const struct wlr_touch_impl touch_impl;
static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
uint32_t format, int32_t fd, uint32_t size) {
close(fd);
@ -119,11 +117,17 @@ void init_seat_keyboard(struct wlr_wl_seat *seat) {
&seat->wlr_keyboard.base);
}
static void touch_coordinates_to_absolute(struct wlr_wl_input_device *device,
static void touch_coordinates_to_absolute(struct wlr_wl_seat *seat,
wl_fixed_t x, wl_fixed_t y, double *sx, double *sy) {
// TODO: each output needs its own touch
/**
* TODO: multi-output touch support
* Although the wayland backend supports multi-output pointers, the support
* for multi-output touch has been left on the side for simplicity reasons.
* If this is a feature you want/need, please open an issue on the wlroots
* tracker here https://gitlab.freedesktop.org/wlroots/wlroots/-/issues
*/
struct wlr_wl_output *output, *tmp;
wl_list_for_each_safe(output, tmp, &device->backend->outputs, link) {
wl_list_for_each_safe(output, tmp, &seat->backend->outputs, link) {
*sx = wl_fixed_to_double(x) / output->wlr_output.width;
*sy = wl_fixed_to_double(y) / output->wlr_output.height;
return; // Choose the first output in the list
@ -135,56 +139,46 @@ static void touch_coordinates_to_absolute(struct wlr_wl_input_device *device,
static void touch_handle_down(void *data, struct wl_touch *wl_touch,
uint32_t serial, uint32_t time, struct wl_surface *surface,
int32_t id, wl_fixed_t x, wl_fixed_t y) {
struct wlr_wl_input_device *device = data;
assert(device && device->wlr_input_device.touch);
struct wlr_wl_seat *seat = data;
double sx, sy;
touch_coordinates_to_absolute(device, x, y, &sx, &sy);
struct wlr_event_touch_down event = {
.device = &device->wlr_input_device,
.device = &seat->wlr_touch.base,
.time_msec = time,
.touch_id = id,
.x = sx,
.y = sy
};
wlr_signal_emit_safe(&device->wlr_input_device.touch->events.down, &event);
touch_coordinates_to_absolute(seat, x, y, &event.x, &event.y);
wlr_signal_emit_safe(&seat->wlr_touch.events.down, &event);
}
static void touch_handle_up(void *data, struct wl_touch *wl_touch,
uint32_t serial, uint32_t time, int32_t id) {
struct wlr_wl_input_device *device = data;
assert(device && device->wlr_input_device.touch);
struct wlr_wl_seat *seat = data;
struct wlr_event_touch_up event = {
.device = &device->wlr_input_device,
.device = &seat->wlr_touch.base,
.time_msec = time,
.touch_id = id,
};
wlr_signal_emit_safe(&device->wlr_input_device.touch->events.up, &event);
wlr_signal_emit_safe(&seat->wlr_touch.events.up, &event);
}
static void touch_handle_motion(void *data, struct wl_touch *wl_touch,
uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) {
struct wlr_wl_input_device *device = data;
assert(device && device->wlr_input_device.touch);
struct wlr_wl_seat *seat = data;
struct wlr_input_device *device = &seat->wlr_touch.base;
double sx, sy;
touch_coordinates_to_absolute(device, x, y, &sx, &sy);
struct wlr_event_touch_motion event = {
.device = &device->wlr_input_device,
.device = device,
.time_msec = time,
.touch_id = id,
.x = sx,
.y = sy
};
wlr_signal_emit_safe(&device->wlr_input_device.touch->events.motion, &event);
touch_coordinates_to_absolute(seat, x, y, &event.x, &event.y);
wlr_signal_emit_safe(&seat->wlr_touch.events.motion, &event);
}
static void touch_handle_frame(void *data, struct wl_touch *wl_touch) {
struct wlr_wl_input_device *device = data;
assert(device && device->wlr_input_device.touch);
wlr_signal_emit_safe(&device->wlr_input_device.touch->events.frame, NULL);
struct wlr_wl_seat *seat = data;
wlr_signal_emit_safe(&seat->wlr_touch.events.frame, NULL);
}
static void touch_handle_cancel(void *data, struct wl_touch *wl_touch) {
@ -211,6 +205,23 @@ static const struct wl_touch_listener touch_listener = {
.orientation = touch_handle_orientation,
};
static const struct wlr_touch_impl touch_impl = {
.name = "wl-touch",
};
static void init_seat_touch(struct wlr_wl_seat *seat) {
assert(seat->wl_touch);
char name[128] = {0};
snprintf(name, sizeof(name), "wayland-touch-%s", seat->name);
wlr_touch_init(&seat->wlr_touch, &touch_impl, name);
wl_touch_add_listener(seat->wl_touch, &touch_listener, seat);
wlr_signal_emit_safe(&seat->backend->backend.events.new_input,
&seat->wlr_touch.base);
}
static struct wlr_wl_input_device *get_wl_input_device_from_input_device(
struct wlr_input_device *wlr_dev) {
assert(wlr_input_device_is_wl(wlr_dev));
@ -233,8 +244,9 @@ bool create_wl_seat(struct wl_seat *wl_seat, struct wlr_wl_backend *wl) {
void destroy_wl_seats(struct wlr_wl_backend *wl) {
struct wlr_wl_seat *seat, *tmp_seat;
wl_list_for_each_safe(seat, tmp_seat, &wl->seats, link) {
if (seat->touch) {
wl_touch_destroy(seat->touch);
if (seat->wl_touch) {
wl_touch_release(seat->wl_touch);
wlr_touch_finish(&seat->wlr_touch);
}
if (seat->wl_pointer) {
finish_seat_pointer(seat);
@ -302,8 +314,9 @@ struct wlr_wl_input_device *create_wl_input_device(
free(dev);
return NULL;
case WLR_INPUT_DEVICE_TOUCH:
type_name = "touch";
break;
wlr_log(WLR_ERROR, "can't create touch wlr_wl_input_device");
free(dev);
return NULL;
case WLR_INPUT_DEVICE_TABLET_TOOL:
type_name = "tablet-tool";
break;
@ -350,8 +363,7 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) {
free(wlr_dev->tablet);
break;
case WLR_INPUT_DEVICE_TOUCH:
wlr_touch_finish(wlr_dev->touch);
free(wlr_dev->touch);
wlr_log(WLR_ERROR, "wlr_wl_input_device has no touch");
break;
default:
break;
@ -361,29 +373,6 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) {
free(dev);
}
void create_wl_touch(struct wlr_wl_seat *seat) {
assert(seat->touch);
struct wl_touch *wl_touch = seat->touch;
struct wlr_wl_input_device *dev =
create_wl_input_device(seat, WLR_INPUT_DEVICE_TOUCH);
if (!dev) {
return;
}
struct wlr_input_device *wlr_dev = &dev->wlr_input_device;
wlr_dev->touch = calloc(1, sizeof(*wlr_dev->touch));
if (!wlr_dev->touch) {
wlr_log_errno(WLR_ERROR, "Allocation failed");
destroy_wl_input_device(dev);
return;
}
wlr_touch_init(wlr_dev->touch, &touch_impl, wlr_dev->name);
wl_touch_add_listener(wl_touch, &touch_listener, dev);
wlr_signal_emit_safe(&seat->backend->backend.events.new_input, wlr_dev);
}
static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
enum wl_seat_capability caps) {
struct wlr_wl_seat *seat = data;
@ -419,26 +408,18 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
seat->wl_keyboard = NULL;
}
if ((caps & WL_SEAT_CAPABILITY_TOUCH) && seat->touch == NULL) {
wlr_log(WLR_DEBUG, "seat %p offered touch", (void *)wl_seat);
if ((caps & WL_SEAT_CAPABILITY_TOUCH) && seat->wl_touch == NULL) {
wlr_log(WLR_DEBUG, "seat '%s' offering touch", seat->name);
seat->touch = wl_seat_get_touch(wl_seat);
if (backend->started) {
create_wl_touch(seat);
}
seat->wl_touch = wl_seat_get_touch(wl_seat);
init_seat_touch(seat);
}
if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && seat->touch != NULL) {
wlr_log(WLR_DEBUG, "seat %p dropped touch", (void *)wl_seat);
if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && seat->wl_touch != NULL) {
wlr_log(WLR_DEBUG, "seat '%s' dropping touch", seat->name);
struct wlr_wl_input_device *device, *tmp;
wl_list_for_each_safe(device, tmp, &backend->devices, link) {
if (device->wlr_input_device.type == WLR_INPUT_DEVICE_TOUCH) {
destroy_wl_input_device(device);
}
}
wl_touch_release(seat->touch);
seat->touch = NULL;
wl_touch_release(seat->wl_touch);
wlr_touch_finish(&seat->wlr_touch);
seat->wl_touch = NULL;
}
}

View file

@ -10,6 +10,7 @@
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_keyboard.h>
#include <wlr/types/wlr_pointer.h>
#include <wlr/types/wlr_touch.h>
#include <wlr/render/drm_format_set.h>
struct wlr_wl_backend {
@ -128,7 +129,8 @@ struct wlr_wl_seat {
struct zwp_pointer_gesture_hold_v1 *gesture_hold;
struct zwp_relative_pointer_v1 *relative_pointer;
struct wl_touch *touch;
struct wl_touch *wl_touch;
struct wlr_touch wlr_touch;
struct wl_list link; // wlr_wl_backend.seats
};
@ -142,7 +144,6 @@ void init_seat_pointer(struct wlr_wl_seat *seat);
void finish_seat_pointer(struct wlr_wl_seat *seat);
void create_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output);
void create_wl_touch(struct wlr_wl_seat *seat);
struct wlr_wl_input_device *create_wl_input_device(
struct wlr_wl_seat *seat, enum wlr_input_device_type type);
bool create_wl_seat(struct wl_seat *wl_seat, struct wlr_wl_backend *wl);