mirror of
https://cagebreak.project-repo.co/cagebreak.git
synced 2026-08-09 15:19:11 +02:00
Fix grouping of virtual keyboards
This commit is contained in:
parent
ed575c36ab
commit
39505dc8b2
2 changed files with 64 additions and 68 deletions
|
|
@ -92,12 +92,7 @@ input_manager_handle_device_destroy(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
static void
|
||||
handle_new_input(struct wl_listener *listener, void *data) {
|
||||
struct cg_input_manager *input =
|
||||
wl_container_of(listener, input, new_input);
|
||||
struct cg_server *server = input->server;
|
||||
struct wlr_input_device *device = data;
|
||||
|
||||
new_input(struct cg_input_manager *input, struct wlr_input_device *device, bool virtual) {
|
||||
struct cg_input_device *input_device =
|
||||
calloc(1, sizeof(struct cg_input_device));
|
||||
if(!input_device) {
|
||||
|
|
@ -106,9 +101,10 @@ handle_new_input(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
device->data = input_device;
|
||||
|
||||
input_device->is_virtual=virtual;
|
||||
input_device->wlr_device = device;
|
||||
input_device->identifier = input_device_get_identifier(device);
|
||||
input_device->server = server;
|
||||
input_device->server = input->server;
|
||||
input_device->pointer = NULL;
|
||||
input_device->touch = NULL;
|
||||
|
||||
|
|
@ -119,39 +115,28 @@ handle_new_input(struct wl_listener *listener, void *data) {
|
|||
wl_signal_add(&device->events.destroy, &input_device->device_destroy);
|
||||
input_device->device_destroy.notify = input_manager_handle_device_destroy;
|
||||
|
||||
struct cg_seat *seat = server->seat;
|
||||
struct cg_seat *seat = input->server->seat;
|
||||
seat_add_device(seat, input_device);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_new_input(struct wl_listener *listener, void *data) {
|
||||
struct cg_input_manager *input =
|
||||
wl_container_of(listener, input, new_input);
|
||||
struct wlr_input_device *device = data;
|
||||
|
||||
new_input(input,device,false);
|
||||
}
|
||||
|
||||
void
|
||||
handle_virtual_keyboard(struct wl_listener *listener, void *data) {
|
||||
struct cg_input_manager *input_manager =
|
||||
wl_container_of(listener, input_manager, virtual_keyboard_new);
|
||||
|
||||
struct cg_input_manager *input =
|
||||
wl_container_of(listener, input, virtual_keyboard_new);
|
||||
struct wlr_virtual_keyboard_v1 *keyboard = data;
|
||||
struct wlr_input_device *device = &keyboard->input_device;
|
||||
|
||||
struct cg_seat *seat = input_manager->server->seat;
|
||||
|
||||
struct cg_input_device *input_device =
|
||||
calloc(1, sizeof(struct cg_input_device));
|
||||
if(!input_device) {
|
||||
wlr_log(WLR_ERROR, "could not allocate input device");
|
||||
return;
|
||||
}
|
||||
device->data = input_device;
|
||||
|
||||
input_device->is_virtual = true;
|
||||
input_device->wlr_device = device;
|
||||
input_device->identifier = input_device_get_identifier(device);
|
||||
wl_list_insert(&input_manager->devices, &input_device->link);
|
||||
input_device->server = input_manager->server;
|
||||
input_device->pointer = NULL;
|
||||
input_device->touch = NULL;
|
||||
|
||||
wl_signal_add(&device->events.destroy, &input_device->device_destroy);
|
||||
input_device->device_destroy.notify = input_manager_handle_device_destroy;
|
||||
|
||||
seat_add_device(seat, input_device);
|
||||
new_input(input,device,true);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -162,31 +147,10 @@ handle_virtual_pointer(struct wl_listener *listener, void *data) {
|
|||
struct wlr_virtual_pointer_v1 *pointer = event->new_pointer;
|
||||
struct wlr_input_device *device = &pointer->input_device;
|
||||
|
||||
struct cg_seat *seat = input_manager->server->seat;
|
||||
|
||||
struct cg_input_device *input_device =
|
||||
calloc(1, sizeof(struct cg_input_device));
|
||||
if(!input_device) {
|
||||
wlr_log(WLR_ERROR, "could not allocate input device");
|
||||
return;
|
||||
}
|
||||
device->data = input_device;
|
||||
|
||||
input_device->is_virtual = true;
|
||||
input_device->wlr_device = device;
|
||||
input_device->identifier = input_device_get_identifier(device);
|
||||
wl_list_insert(&input_manager->devices, &input_device->link);
|
||||
input_device->server = input_manager->server;
|
||||
input_device->pointer = NULL;
|
||||
input_device->touch = NULL;
|
||||
|
||||
wl_signal_add(&device->events.destroy, &input_device->device_destroy);
|
||||
input_device->device_destroy.notify = input_manager_handle_device_destroy;
|
||||
|
||||
seat_add_device(seat, input_device);
|
||||
new_input(input_manager,device,true);
|
||||
|
||||
if(event->suggested_output) {
|
||||
wlr_cursor_map_input_to_output(seat->cursor, device,
|
||||
wlr_cursor_map_input_to_output(input_manager->server->seat->cursor, device,
|
||||
event->suggested_output);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
58
seat.c
58
seat.c
|
|
@ -326,15 +326,24 @@ handle_keyboard_group_modifiers(struct wl_listener *listener, void *_data) {
|
|||
handle_modifier_event(group->wlr_group->input_device, group->seat);
|
||||
}
|
||||
|
||||
static bool repeat_info_match(struct wlr_keyboard *a, struct wlr_keyboard *b) {
|
||||
return a->repeat_info.rate == b->repeat_info.rate &&
|
||||
a->repeat_info.delay == b->repeat_info.delay;
|
||||
}
|
||||
|
||||
static void
|
||||
cg_keyboard_group_add(struct wlr_input_device *device, struct cg_seat *seat) {
|
||||
cg_keyboard_group_add(struct cg_input_device *input_device, struct cg_seat *seat) {
|
||||
struct wlr_input_device *device=input_device->wlr_device;
|
||||
struct wlr_keyboard *wlr_keyboard = device->keyboard;
|
||||
struct cg_keyboard_group *group;
|
||||
wl_list_for_each(group, &seat->keyboard_groups, link) {
|
||||
struct wlr_keyboard_group *wlr_group = group->wlr_group;
|
||||
if(wlr_keyboard_group_add_keyboard(wlr_group, wlr_keyboard)) {
|
||||
wlr_log(WLR_DEBUG, "Adding keyboard to existing group.");
|
||||
return;
|
||||
// Virtual devices should not be grouped
|
||||
if(!input_device->is_virtual) {
|
||||
struct cg_keyboard_group *group;
|
||||
wl_list_for_each(group, &seat->keyboard_groups, link) {
|
||||
struct wlr_keyboard_group *wlr_group = group->wlr_group;
|
||||
if(wlr_keyboard_keymaps_match(wlr_keyboard->keymap,wlr_group->keyboard.keymap) && repeat_info_match(wlr_keyboard,&wlr_group->keyboard) && wlr_keyboard_group_add_keyboard(wlr_group, wlr_keyboard)) {
|
||||
wlr_log(WLR_DEBUG, "Adding keyboard to existing group.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* This is reached if and only if the keyboard could not be inserted into
|
||||
|
|
@ -406,7 +415,7 @@ new_keyboard(struct cg_seat *seat, struct cg_input_device *input_device) {
|
|||
xkb_context_unref(context);
|
||||
wlr_keyboard_set_repeat_info(device->keyboard, 25, 600);
|
||||
|
||||
cg_keyboard_group_add(device, seat);
|
||||
cg_keyboard_group_add(input_device, seat);
|
||||
++seat->num_keyboards;
|
||||
|
||||
wlr_seat_set_keyboard(seat->seat, device);
|
||||
|
|
@ -436,6 +445,10 @@ seat_add_device(struct cg_seat *seat, struct cg_input_device *device) {
|
|||
update_capabilities(seat);
|
||||
}
|
||||
|
||||
static void destroy_empty_wlr_keyboard_group(void *data) {
|
||||
wlr_keyboard_group_destroy(data);
|
||||
}
|
||||
|
||||
void
|
||||
remove_keyboard(struct cg_seat *seat, struct cg_input_device *keyboard) {
|
||||
if(!keyboard) {
|
||||
|
|
@ -443,12 +456,31 @@ remove_keyboard(struct cg_seat *seat, struct cg_input_device *keyboard) {
|
|||
}
|
||||
struct wlr_seat *wlr_seat = seat->seat;
|
||||
struct wlr_keyboard *wlr_keyboard = keyboard->wlr_device->keyboard;
|
||||
if(keyboard->wlr_device->keyboard->group) {
|
||||
wlr_keyboard_group_remove_keyboard(wlr_keyboard->group, wlr_keyboard);
|
||||
}
|
||||
if(wlr_seat_get_keyboard(wlr_seat) == wlr_keyboard) {
|
||||
wlr_seat_set_keyboard(wlr_seat, NULL);
|
||||
struct wlr_keyboard_group *wlr_group = wlr_keyboard->group;
|
||||
if(wlr_group) {
|
||||
wlr_keyboard_group_remove_keyboard(wlr_group, wlr_keyboard);
|
||||
|
||||
if (wl_list_empty(&wlr_group->devices)) {
|
||||
wlr_log(DEBUG, "Destroying empty keyboard group %p",
|
||||
wlr_group);
|
||||
struct cg_keyboard_group *group = wlr_group->data;
|
||||
if(wlr_seat_get_keyboard(wlr_seat) == &wlr_group->keyboard) {
|
||||
wlr_seat_set_keyboard(wlr_seat, NULL);
|
||||
}
|
||||
wlr_group->data = NULL;
|
||||
wl_list_remove(&group->link);
|
||||
wl_list_remove(&group->key.link);
|
||||
wl_list_remove(&group->modifiers.link);
|
||||
free(group);
|
||||
|
||||
// To prevent use-after-free conditions when handling key events, defer
|
||||
// freeing the wlr_keyboard_group until idle
|
||||
wl_event_loop_add_idle(seat->server->event_loop,
|
||||
destroy_empty_wlr_keyboard_group, wlr_group);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
--seat->num_keyboards;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue