From a1978b1299952586a2fd016aab682c7fdbe735ee Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Fri, 28 Jan 2022 13:55:28 -0500 Subject: [PATCH] types/wlr_keyboard: add base wlr_input_device wlr_keyboard owns its base wlr_input_device. It will be initialized when the keyboard is initialized, and finished when the keyboard is destroyed. --- backend/libinput/keyboard.c | 5 +- backend/wayland/seat.c | 4 +- backend/x11/backend.c | 9 +- backend/x11/input_device.c | 7 +- include/backend/x11.h | 1 - include/wlr/interfaces/wlr_keyboard.h | 2 +- include/wlr/types/wlr_keyboard.h | 3 + include/wlr/types/wlr_keyboard_group.h | 2 - include/wlr/types/wlr_virtual_keyboard_v1.h | 2 +- types/wlr_keyboard.c | 8 +- types/wlr_keyboard_group.c | 13 +-- types/wlr_virtual_keyboard_v1.c | 95 +++++++++------------ 12 files changed, 66 insertions(+), 85 deletions(-) diff --git a/backend/libinput/keyboard.c b/backend/libinput/keyboard.c index d5207f54..be5faf3e 100644 --- a/backend/libinput/keyboard.c +++ b/backend/libinput/keyboard.c @@ -49,7 +49,10 @@ struct wlr_keyboard *create_libinput_keyboard( libinput_device_ref(libinput_dev); libinput_device_led_update(libinput_dev, 0); struct wlr_keyboard *wlr_kb = &kb->wlr_keyboard; - wlr_keyboard_init(wlr_kb, &impl); + const char *name = libinput_device_get_name(libinput_dev); + wlr_keyboard_init(wlr_kb, &impl, name); + wlr_kb->base.vendor = libinput_device_get_id_vendor(libinput_dev); + wlr_kb->base.product = libinput_device_get_id_product(libinput_dev); return wlr_kb; } diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index d22d5e63..90a99950 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -785,14 +785,14 @@ void create_wl_keyboard(struct wlr_wl_seat *seat) { } 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"); wlr_input_device_destroy(wlr_dev); return; } - wlr_keyboard_init(wlr_dev->keyboard, NULL); + + wlr_keyboard_init(wlr_dev->keyboard, NULL, 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); diff --git a/backend/x11/backend.c b/backend/x11/backend.c index 70fc0478..3f2a9f01 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -165,7 +165,7 @@ static bool backend_start(struct wlr_backend *backend) { wlr_log(WLR_INFO, "Starting X11 backend"); - wlr_signal_emit_safe(&x11->backend.events.new_input, &x11->keyboard_dev); + wlr_signal_emit_safe(&x11->backend.events.new_input, &x11->keyboard.base); for (size_t i = 0; i < x11->requested_outputs; ++i) { wlr_x11_output_create(&x11->backend); @@ -186,7 +186,7 @@ static void backend_destroy(struct wlr_backend *backend) { wlr_output_destroy(&output->wlr_output); } - wlr_input_device_destroy(&x11->keyboard_dev); + wlr_keyboard_destroy(&x11->keyboard); wlr_backend_finish(backend); @@ -638,10 +638,7 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display, } #endif - wlr_input_device_init(&x11->keyboard_dev, WLR_INPUT_DEVICE_KEYBOARD, - &input_device_impl, "X11 keyboard"); - wlr_keyboard_init(&x11->keyboard, &keyboard_impl); - x11->keyboard_dev.keyboard = &x11->keyboard; + wlr_keyboard_init(&x11->keyboard, &keyboard_impl, "x11-keyboard"); x11->display_destroy.notify = handle_display_destroy; wl_display_add_destroy_listener(display, &x11->display_destroy); diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c index f9541b06..94b70524 100644 --- a/backend/x11/input_device.c +++ b/backend/x11/input_device.c @@ -336,5 +336,10 @@ void update_x11_pointer_position(struct wlr_x11_output *output, } bool wlr_input_device_is_x11(struct wlr_input_device *wlr_dev) { - return wlr_dev->impl == &input_device_impl; + switch (wlr_dev->type) { + case WLR_INPUT_DEVICE_KEYBOARD: + return wlr_dev->keyboard->impl == &keyboard_impl; + default: + return wlr_dev->impl == &input_device_impl; + } } diff --git a/include/backend/x11.h b/include/backend/x11.h index fadcbedc..b5c430fb 100644 --- a/include/backend/x11.h +++ b/include/backend/x11.h @@ -81,7 +81,6 @@ struct wlr_x11_backend { struct wl_list outputs; // wlr_x11_output::link struct wlr_keyboard keyboard; - struct wlr_input_device keyboard_dev; int drm_fd; struct wlr_drm_format_set dri3_formats; diff --git a/include/wlr/interfaces/wlr_keyboard.h b/include/wlr/interfaces/wlr_keyboard.h index 5d537827..4bcef57b 100644 --- a/include/wlr/interfaces/wlr_keyboard.h +++ b/include/wlr/interfaces/wlr_keyboard.h @@ -18,7 +18,7 @@ struct wlr_keyboard_impl { }; void wlr_keyboard_init(struct wlr_keyboard *keyboard, - const struct wlr_keyboard_impl *impl); + const struct wlr_keyboard_impl *impl, const char *name); void wlr_keyboard_destroy(struct wlr_keyboard *keyboard); void wlr_keyboard_notify_key(struct wlr_keyboard *keyboard, struct wlr_event_keyboard_key *event); diff --git a/include/wlr/types/wlr_keyboard.h b/include/wlr/types/wlr_keyboard.h index ea16c432..b3be053a 100644 --- a/include/wlr/types/wlr_keyboard.h +++ b/include/wlr/types/wlr_keyboard.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #define WLR_LED_COUNT 3 @@ -48,6 +49,8 @@ struct wlr_keyboard_modifiers { }; struct wlr_keyboard { + struct wlr_input_device base; + const struct wlr_keyboard_impl *impl; struct wlr_keyboard_group *group; diff --git a/include/wlr/types/wlr_keyboard_group.h b/include/wlr/types/wlr_keyboard_group.h index cb73899a..3906d948 100644 --- a/include/wlr/types/wlr_keyboard_group.h +++ b/include/wlr/types/wlr_keyboard_group.h @@ -11,11 +11,9 @@ #include #include -#include struct wlr_keyboard_group { struct wlr_keyboard keyboard; - struct wlr_input_device *input_device; struct wl_list devices; // keyboard_group_device::link struct wl_list keys; // keyboard_group_key::link diff --git a/include/wlr/types/wlr_virtual_keyboard_v1.h b/include/wlr/types/wlr_virtual_keyboard_v1.h index a3f4e452..8be6158d 100644 --- a/include/wlr/types/wlr_virtual_keyboard_v1.h +++ b/include/wlr/types/wlr_virtual_keyboard_v1.h @@ -26,7 +26,7 @@ struct wlr_virtual_keyboard_manager_v1 { }; struct wlr_virtual_keyboard_v1 { - struct wlr_input_device input_device; + struct wlr_keyboard keyboard; struct wl_resource *resource; struct wlr_seat *seat; bool has_keymap; diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c index c54e33c6..062c08a0 100644 --- a/types/wlr_keyboard.c +++ b/types/wlr_keyboard.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -114,7 +115,10 @@ void wlr_keyboard_notify_key(struct wlr_keyboard *keyboard, } void wlr_keyboard_init(struct wlr_keyboard *kb, - const struct wlr_keyboard_impl *impl) { + const struct wlr_keyboard_impl *impl, const char *name) { + wlr_input_device_init(&kb->base, WLR_INPUT_DEVICE_KEYBOARD, NULL, name); + kb->base.keyboard = kb; + kb->impl = impl; wl_signal_init(&kb->events.key); wl_signal_init(&kb->events.modifiers); @@ -134,6 +138,8 @@ void wlr_keyboard_destroy(struct wlr_keyboard *kb) { return; } wlr_signal_emit_safe(&kb->events.destroy, kb); + wlr_input_device_finish(&kb->base); + xkb_state_unref(kb->xkb_state); xkb_keymap_unref(kb->keymap); free(kb->keymap_string); diff --git a/types/wlr_keyboard_group.c b/types/wlr_keyboard_group.c index d614f58d..35fc5470 100644 --- a/types/wlr_keyboard_group.c +++ b/types/wlr_keyboard_group.c @@ -60,16 +60,7 @@ struct wlr_keyboard_group *wlr_keyboard_group_create(void) { return NULL; } - group->input_device = calloc(1, sizeof(struct wlr_input_device)); - if (!group->input_device) { - wlr_log(WLR_ERROR, "Failed to allocate wlr_input_device for group"); - free(group); - return NULL; - } - wl_signal_init(&group->input_device->events.destroy); - group->input_device->keyboard = &group->keyboard; - - wlr_keyboard_init(&group->keyboard, &impl); + wlr_keyboard_init(&group->keyboard, &impl, "keyboard-group"); wl_list_init(&group->devices); wl_list_init(&group->keys); @@ -335,9 +326,7 @@ void wlr_keyboard_group_destroy(struct wlr_keyboard_group *group) { wlr_keyboard_group_remove_keyboard(group, device->keyboard); } wlr_keyboard_destroy(&group->keyboard); - wl_list_remove(&group->input_device->events.destroy.listener_list); wl_list_remove(&group->events.enter.listener_list); wl_list_remove(&group->events.leave.listener_list); - free(group->input_device); free(group); } diff --git a/types/wlr_virtual_keyboard_v1.c b/types/wlr_virtual_keyboard_v1.c index 3b195ab3..dc549aa7 100644 --- a/types/wlr_virtual_keyboard_v1.c +++ b/types/wlr_virtual_keyboard_v1.c @@ -11,26 +11,40 @@ #include "util/time.h" #include "virtual-keyboard-unstable-v1-protocol.h" - -static void keyboard_led_update(struct wlr_keyboard *wlr_kb, uint32_t leds) { - // unsupported by virtual keyboard protocol +/** + * Send release event for each pressed key to bring the keyboard back to + * neutral state. + * + * This may be needed for virtual keyboards. For physical devices, kernel + * or libinput will deal with the removal of devices. + */ +static void keyboard_release_pressed_keys(struct wlr_keyboard *keyboard) { + size_t orig_num_keycodes = keyboard->num_keycodes; + for (size_t i = 0; i < orig_num_keycodes; ++i) { + assert(keyboard->num_keycodes == orig_num_keycodes - i); + struct wlr_event_keyboard_key event = { + .time_msec = get_current_time_msec(), + .keycode = keyboard->keycodes[orig_num_keycodes - i - 1], + .update_state = false, + .state = WL_KEYBOARD_KEY_STATE_RELEASED, + }; + wlr_keyboard_notify_key(keyboard, &event); // updates num_keycodes + } } static void keyboard_destroy(struct wlr_keyboard *wlr_kb) { - // safe to ignore - keyboard will be destroyed only iff associated virtual - // keyboard is torn down, no need to tear down the keyboard separately + struct wlr_virtual_keyboard_v1 *keyboard = + (struct wlr_virtual_keyboard_v1 *)wlr_kb; + + keyboard_release_pressed_keys(&keyboard->keyboard); + wl_resource_set_user_data(keyboard->resource, NULL); + wlr_signal_emit_safe(&keyboard->events.destroy, keyboard); + wl_list_remove(&keyboard->link); + free(keyboard); } static const struct wlr_keyboard_impl keyboard_impl = { .destroy = keyboard_destroy, - .led_update = keyboard_led_update -}; - -static void input_device_destroy(struct wlr_input_device *dev) { -} - -static const struct wlr_input_device_impl input_device_impl = { - .destroy = input_device_destroy }; static const struct zwp_virtual_keyboard_v1_interface virtual_keyboard_impl; @@ -44,10 +58,11 @@ static struct wlr_virtual_keyboard_v1 *virtual_keyboard_from_resource( struct wlr_virtual_keyboard_v1 *wlr_input_device_get_virtual_keyboard( struct wlr_input_device *wlr_dev) { - if (wlr_dev->impl != &input_device_impl) { + if (wlr_dev->type != WLR_INPUT_DEVICE_KEYBOARD + || wlr_dev->keyboard->impl != &keyboard_impl) { return NULL; } - return (struct wlr_virtual_keyboard_v1 *)wlr_dev; + return (struct wlr_virtual_keyboard_v1 *)wlr_dev->keyboard; } static void virtual_keyboard_keymap(struct wl_client *client, @@ -70,7 +85,7 @@ static void virtual_keyboard_keymap(struct wl_client *client, if (!keymap) { goto keymap_fail; } - wlr_keyboard_set_keymap(keyboard->input_device.keyboard, keymap); + wlr_keyboard_set_keymap(&keyboard->keyboard, keymap); keyboard->has_keymap = true; xkb_keymap_unref(keymap); xkb_context_unref(context); @@ -101,7 +116,7 @@ static void virtual_keyboard_key(struct wl_client *client, .update_state = false, .state = state, }; - wlr_keyboard_notify_key(keyboard->input_device.keyboard, &event); + wlr_keyboard_notify_key(&keyboard->keyboard, &event); } static void virtual_keyboard_modifiers(struct wl_client *client, @@ -115,39 +130,16 @@ static void virtual_keyboard_modifiers(struct wl_client *client, "Cannot send a modifier state before defining a keymap"); return; } - wlr_keyboard_notify_modifiers(keyboard->input_device.keyboard, + wlr_keyboard_notify_modifiers(&keyboard->keyboard, mods_depressed, mods_latched, mods_locked, group); } -/** - * Send release event for each pressed key to bring the keyboard back to - * neutral state. - * - * This may be needed for virtual keyboards. For physical devices, kernel - * or libinput will deal with the removal of devices. - */ -static void keyboard_release_pressed_keys(struct wlr_keyboard *keyboard) { - size_t orig_num_keycodes = keyboard->num_keycodes; - for (size_t i = 0; i < orig_num_keycodes; ++i) { - assert(keyboard->num_keycodes == orig_num_keycodes - i); - struct wlr_event_keyboard_key event = { - .time_msec = get_current_time_msec(), - .keycode = keyboard->keycodes[orig_num_keycodes - i - 1], - .update_state = false, - .state = WL_KEYBOARD_KEY_STATE_RELEASED, - }; - wlr_keyboard_notify_key(keyboard, &event); // updates num_keycodes - } -} - static void virtual_keyboard_destroy_resource(struct wl_resource *resource) { struct wlr_virtual_keyboard_v1 *keyboard = virtual_keyboard_from_resource(resource); - keyboard_release_pressed_keys(keyboard->input_device.keyboard); - wlr_signal_emit_safe(&keyboard->events.destroy, keyboard); - wl_list_remove(&keyboard->link); - wlr_input_device_destroy(&keyboard->input_device); - free(keyboard); + if (keyboard != NULL) { + wlr_keyboard_destroy(&keyboard->keyboard); + } } static void virtual_keyboard_destroy(struct wl_client *client, @@ -184,20 +176,13 @@ static void virtual_keyboard_manager_create_virtual_keyboard( return; } - struct wlr_keyboard* keyboard = calloc(1, sizeof(struct wlr_keyboard)); - if (!keyboard) { - wlr_log(WLR_ERROR, "Cannot allocate wlr_keyboard"); - free(virtual_keyboard); - wl_client_post_no_memory(client); - return; - } - wlr_keyboard_init(keyboard, &keyboard_impl); + wlr_keyboard_init(&virtual_keyboard->keyboard, &keyboard_impl, + "virtual-keyboard"); struct wl_resource *keyboard_resource = wl_resource_create(client, &zwp_virtual_keyboard_v1_interface, wl_resource_get_version(resource), id); if (!keyboard_resource) { - free(keyboard); free(virtual_keyboard); wl_client_post_no_memory(client); return; @@ -206,12 +191,8 @@ static void virtual_keyboard_manager_create_virtual_keyboard( wl_resource_set_implementation(keyboard_resource, &virtual_keyboard_impl, virtual_keyboard, virtual_keyboard_destroy_resource); - wlr_input_device_init(&virtual_keyboard->input_device, - WLR_INPUT_DEVICE_KEYBOARD, &input_device_impl, "virtual keyboard"); - struct wlr_seat_client *seat_client = wlr_seat_client_from_resource(seat); - virtual_keyboard->input_device.keyboard = keyboard; virtual_keyboard->resource = keyboard_resource; virtual_keyboard->seat = seat_client->seat; wl_signal_init(&virtual_keyboard->events.destroy);