backend/wayland: give wlr_keyboard ownership to wlr_wl_seat

This commit is contained in:
Simon Zeni 2022-03-03 13:23:08 -05:00 committed by Kirill Primak
parent 64fe6ab300
commit f9b6aa3079
3 changed files with 62 additions and 75 deletions

View file

@ -413,8 +413,8 @@ static bool backend_start(struct wlr_backend *backend) {
struct wlr_wl_seat *seat; struct wlr_wl_seat *seat;
wl_list_for_each(seat, &wl->seats, link) { wl_list_for_each(seat, &wl->seats, link) {
if (seat->keyboard) { if (seat->wl_keyboard) {
create_wl_keyboard(seat); init_seat_keyboard(seat);
} }
if (wl->tablet_manager) { if (wl->tablet_manager) {

View file

@ -26,9 +26,6 @@
#include "util/time.h" #include "util/time.h"
static const struct wlr_pointer_impl pointer_impl; static const struct wlr_pointer_impl pointer_impl;
static const struct wlr_keyboard_impl keyboard_impl = {
.name = "wl-keyboard",
};
static const struct wlr_touch_impl touch_impl; static const struct wlr_touch_impl touch_impl;
static struct wlr_wl_pointer *output_get_pointer( static struct wlr_wl_pointer *output_get_pointer(
@ -223,31 +220,27 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard, static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { uint32_t serial, struct wl_surface *surface, struct wl_array *keys) {
struct wlr_input_device *dev = data; struct wlr_keyboard *keyboard = data;
uint32_t time = get_current_time_msec();
uint32_t *keycode_ptr; uint32_t *keycode_ptr;
wl_array_for_each(keycode_ptr, keys) { wl_array_for_each(keycode_ptr, keys) {
struct wlr_event_keyboard_key event = { struct wlr_event_keyboard_key event = {
.keycode = *keycode_ptr, .keycode = *keycode_ptr,
.state = WL_KEYBOARD_KEY_STATE_PRESSED, .state = WL_KEYBOARD_KEY_STATE_PRESSED,
.time_msec = time, .time_msec = get_current_time_msec(),
.update_state = false, .update_state = false,
}; };
wlr_keyboard_notify_key(dev->keyboard, &event); wlr_keyboard_notify_key(keyboard, &event);
} }
} }
static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard, static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, struct wl_surface *surface) { uint32_t serial, struct wl_surface *surface) {
struct wlr_input_device *dev = data; struct wlr_keyboard *keyboard = data;
uint32_t time = get_current_time_msec(); size_t num_keycodes = keyboard->num_keycodes;
size_t num_keycodes = dev->keyboard->num_keycodes;
uint32_t pressed[num_keycodes + 1]; uint32_t pressed[num_keycodes + 1];
memcpy(pressed, dev->keyboard->keycodes, memcpy(pressed, keyboard->keycodes,
num_keycodes * sizeof(uint32_t)); num_keycodes * sizeof(uint32_t));
for (size_t i = 0; i < num_keycodes; ++i) { for (size_t i = 0; i < num_keycodes; ++i) {
@ -256,17 +249,16 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
struct wlr_event_keyboard_key event = { struct wlr_event_keyboard_key event = {
.keycode = keycode, .keycode = keycode,
.state = WL_KEYBOARD_KEY_STATE_RELEASED, .state = WL_KEYBOARD_KEY_STATE_RELEASED,
.time_msec = time, .time_msec = get_current_time_msec(),
.update_state = false, .update_state = false,
}; };
wlr_keyboard_notify_key(dev->keyboard, &event); wlr_keyboard_notify_key(keyboard, &event);
} }
} }
static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard, static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
struct wlr_input_device *dev = data; struct wlr_keyboard *keyboard = data;
assert(dev && dev->keyboard);
struct wlr_event_keyboard_key wlr_event = { struct wlr_event_keyboard_key wlr_event = {
.keycode = key, .keycode = key,
@ -274,15 +266,14 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard,
.time_msec = time, .time_msec = time,
.update_state = false, .update_state = false,
}; };
wlr_keyboard_notify_key(dev->keyboard, &wlr_event); wlr_keyboard_notify_key(keyboard, &wlr_event);
} }
static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard, static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched,
uint32_t mods_locked, uint32_t group) { uint32_t mods_locked, uint32_t group) {
struct wlr_input_device *dev = data; struct wlr_keyboard *keyboard = data;
assert(dev && dev->keyboard); wlr_keyboard_notify_modifiers(keyboard, mods_depressed, mods_latched,
wlr_keyboard_notify_modifiers(dev->keyboard, mods_depressed, mods_latched,
mods_locked, group); mods_locked, group);
} }
@ -300,6 +291,24 @@ static const struct wl_keyboard_listener keyboard_listener = {
.repeat_info = keyboard_handle_repeat_info .repeat_info = keyboard_handle_repeat_info
}; };
static const struct wlr_keyboard_impl keyboard_impl = {
.name = "wl-keyboard",
};
void init_seat_keyboard(struct wlr_wl_seat *seat) {
assert(seat->wl_keyboard);
char name[128] = {0};
snprintf(name, sizeof(name), "wayland-keyboard-%s", seat->name);
wlr_keyboard_init(&seat->wlr_keyboard, &keyboard_impl, name);
wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener,
&seat->wlr_keyboard);
wlr_signal_emit_safe(&seat->backend->backend.events.new_input,
&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_input_device *device,
wl_fixed_t x, wl_fixed_t y, double *sx, double *sy) { wl_fixed_t x, wl_fixed_t y, double *sx, double *sy) {
// TODO: each output needs its own touch // TODO: each output needs its own touch
@ -420,10 +429,11 @@ void destroy_wl_seats(struct wlr_wl_backend *wl) {
if (seat->pointer) { if (seat->pointer) {
wl_pointer_destroy(seat->pointer); wl_pointer_destroy(seat->pointer);
} }
if (seat->keyboard && !wl->started) { if (seat->wl_keyboard) {
// early termination will not be handled by input_device_destroy wl_keyboard_release(seat->wl_keyboard);
wl_keyboard_destroy(seat->keyboard); wlr_keyboard_finish(&seat->wlr_keyboard);
} }
free(seat->name); free(seat->name);
assert(seat->wl_seat); assert(seat->wl_seat);
wl_seat_destroy(seat->wl_seat); wl_seat_destroy(seat->wl_seat);
@ -474,8 +484,9 @@ struct wlr_wl_input_device *create_wl_input_device(
switch (type) { switch (type) {
case WLR_INPUT_DEVICE_KEYBOARD: case WLR_INPUT_DEVICE_KEYBOARD:
type_name = "keyboard"; wlr_log(WLR_ERROR, "can't create keyboard wlr_wl_input_device");
break; free(dev);
return NULL;
case WLR_INPUT_DEVICE_POINTER: case WLR_INPUT_DEVICE_POINTER:
type_name = "pointer"; type_name = "pointer";
break; break;
@ -550,8 +561,7 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) {
struct wlr_input_device *wlr_dev = &dev->wlr_input_device; struct wlr_input_device *wlr_dev = &dev->wlr_input_device;
switch (wlr_dev->type) { switch (wlr_dev->type) {
case WLR_INPUT_DEVICE_KEYBOARD: case WLR_INPUT_DEVICE_KEYBOARD:
wlr_keyboard_finish(wlr_dev->keyboard); wlr_log(WLR_ERROR, "wlr_wl_input_device has no keyboard");
free(wlr_dev->keyboard);
break; break;
case WLR_INPUT_DEVICE_POINTER: case WLR_INPUT_DEVICE_POINTER:
/* Owned by wlr_wl_pointer */ /* Owned by wlr_wl_pointer */
@ -814,29 +824,6 @@ void create_wl_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output) {
wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev); wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev);
} }
void create_wl_keyboard(struct wlr_wl_seat *seat) {
assert(seat->keyboard);
struct wl_keyboard *wl_keyboard = seat->keyboard;
struct wlr_wl_input_device *dev =
create_wl_input_device(seat, WLR_INPUT_DEVICE_KEYBOARD);
if (!dev) {
return;
}
struct wlr_input_device *wlr_dev = &dev->wlr_input_device;
wlr_dev->keyboard = calloc(1, sizeof(*wlr_dev->keyboard));
if (!wlr_dev->keyboard) {
wlr_log_errno(WLR_ERROR, "Allocation failed");
destroy_wl_input_device(dev);
return;
}
wlr_keyboard_init(wlr_dev->keyboard, &keyboard_impl, wlr_dev->name);
wl_keyboard_add_listener(wl_keyboard, &keyboard_listener, wlr_dev);
wlr_signal_emit_safe(&seat->backend->backend.events.new_input, wlr_dev);
}
void create_wl_touch(struct wlr_wl_seat *seat) { void create_wl_touch(struct wlr_wl_seat *seat) {
assert(seat->touch); assert(seat->touch);
struct wl_touch *wl_touch = seat->touch; struct wl_touch *wl_touch = seat->touch;
@ -903,31 +890,23 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
seat->pointer = NULL; seat->pointer = NULL;
} }
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && seat->keyboard == NULL) { if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && seat->wl_keyboard == NULL) {
wlr_log(WLR_DEBUG, "seat %p offered keyboard", (void *)wl_seat); wlr_log(WLR_DEBUG, "seat '%s' offering keyboard", seat->name);
struct wl_keyboard *wl_keyboard = wl_seat_get_keyboard(wl_seat); struct wl_keyboard *wl_keyboard = wl_seat_get_keyboard(wl_seat);
seat->keyboard = wl_keyboard; seat->wl_keyboard = wl_keyboard;
if (backend->started) { if (backend->started) {
create_wl_keyboard(seat); init_seat_keyboard(seat);
} }
} }
if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && seat->keyboard != NULL) { if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && seat->wl_keyboard != NULL) {
wlr_log(WLR_DEBUG, "seat %p dropped keyboard", (void *)wl_seat); wlr_log(WLR_DEBUG, "seat '%s' dropping keyboard", seat->name);
struct wlr_wl_input_device *device, *tmp; wl_keyboard_release(seat->wl_keyboard);
wl_list_for_each_safe(device, tmp, &backend->devices, link) { wlr_keyboard_finish(&seat->wlr_keyboard);
if (device->wlr_input_device.type != WLR_INPUT_DEVICE_KEYBOARD) {
continue;
}
if (device->seat != seat) { seat->wl_keyboard = NULL;
continue;
}
destroy_wl_input_device(device);
}
assert(seat->keyboard == NULL); // free'ed by input_device_destroy
} }
if ((caps & WL_SEAT_CAPABILITY_TOUCH) && seat->touch == NULL) { if ((caps & WL_SEAT_CAPABILITY_TOUCH) && seat->touch == NULL) {

View file

@ -8,6 +8,7 @@
#include <wlr/backend/wayland.h> #include <wlr/backend/wayland.h>
#include <wlr/render/wlr_renderer.h> #include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_keyboard.h>
#include <wlr/types/wlr_pointer.h> #include <wlr/types/wlr_pointer.h>
#include <wlr/render/drm_format_set.h> #include <wlr/render/drm_format_set.h>
@ -112,23 +113,29 @@ struct wlr_wl_pointer {
}; };
struct wlr_wl_seat { struct wlr_wl_seat {
char *name;
struct wl_seat *wl_seat; struct wl_seat *wl_seat;
struct wl_list link; // wlr_wl_backend.seats struct wlr_wl_backend *backend;
char *name;
struct wl_keyboard *wl_keyboard;
struct wlr_keyboard wlr_keyboard;
struct wl_touch *touch; struct wl_touch *touch;
struct wl_pointer *pointer; struct wl_pointer *pointer;
struct wl_keyboard *keyboard;
struct wlr_wl_backend *backend;
struct wlr_wl_pointer *active_pointer; struct wlr_wl_pointer *active_pointer;
struct wl_list link; // wlr_wl_backend.seats
}; };
struct wlr_wl_backend *get_wl_backend_from_backend(struct wlr_backend *backend); struct wlr_wl_backend *get_wl_backend_from_backend(struct wlr_backend *backend);
void update_wl_output_cursor(struct wlr_wl_output *output); void update_wl_output_cursor(struct wlr_wl_output *output);
struct wlr_wl_pointer *pointer_get_wl(struct wlr_pointer *wlr_pointer); struct wlr_wl_pointer *pointer_get_wl(struct wlr_pointer *wlr_pointer);
void init_seat_keyboard(struct wlr_wl_seat *seat);
void create_wl_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output); void create_wl_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output);
void create_wl_keyboard(struct wlr_wl_seat *seat);
void create_wl_touch(struct wlr_wl_seat *seat); void create_wl_touch(struct wlr_wl_seat *seat);
struct wlr_wl_input_device *create_wl_input_device( struct wlr_wl_input_device *create_wl_input_device(
struct wlr_wl_seat *seat, enum wlr_input_device_type type); struct wlr_wl_seat *seat, enum wlr_input_device_type type);
@ -138,6 +145,7 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev);
void destroy_wl_buffer(struct wlr_wl_buffer *buffer); void destroy_wl_buffer(struct wlr_wl_buffer *buffer);
extern const struct wl_seat_listener seat_listener; extern const struct wl_seat_listener seat_listener;
extern const struct wlr_tablet_pad_impl tablet_pad_impl; extern const struct wlr_tablet_pad_impl tablet_pad_impl;
extern const struct wlr_tablet_impl tablet_impl; extern const struct wlr_tablet_impl tablet_impl;