Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
#define _POSIX_C_SOURCE 200809L
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <wayland-server-core.h>
|
2020-10-21 17:21:23 +02:00
|
|
|
#include <wayland-server-protocol.h>
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
#include <xkbcommon/xkbcommon.h>
|
2020-05-31 23:10:15 +02:00
|
|
|
#include "types/wlr_keyboard.h"
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
#include "wlr/interfaces/wlr_keyboard.h"
|
|
|
|
#include "wlr/types/wlr_keyboard.h"
|
|
|
|
#include "wlr/types/wlr_keyboard_group.h"
|
|
|
|
#include "wlr/util/log.h"
|
|
|
|
|
|
|
|
struct keyboard_group_device {
|
|
|
|
struct wlr_keyboard *keyboard;
|
|
|
|
struct wl_listener key;
|
|
|
|
struct wl_listener modifiers;
|
|
|
|
struct wl_listener keymap;
|
|
|
|
struct wl_listener repeat_info;
|
|
|
|
struct wl_listener destroy;
|
|
|
|
struct wl_list link; // wlr_keyboard_group::devices
|
|
|
|
};
|
|
|
|
|
|
|
|
struct keyboard_group_key {
|
|
|
|
uint32_t keycode;
|
|
|
|
size_t count;
|
|
|
|
struct wl_list link; // wlr_keyboard_group::keys
|
|
|
|
};
|
|
|
|
|
|
|
|
static void keyboard_set_leds(struct wlr_keyboard *kb, uint32_t leds) {
|
|
|
|
struct wlr_keyboard_group *group = wlr_keyboard_group_from_wlr_keyboard(kb);
|
|
|
|
struct keyboard_group_device *device;
|
|
|
|
wl_list_for_each(device, &group->devices, link) {
|
|
|
|
wlr_keyboard_led_update(device->keyboard, leds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct wlr_keyboard_impl impl = {
|
2022-03-01 20:49:30 +01:00
|
|
|
.name = "keyboard-group",
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
.led_update = keyboard_set_leds
|
|
|
|
};
|
|
|
|
|
|
|
|
struct wlr_keyboard_group *wlr_keyboard_group_create(void) {
|
|
|
|
struct wlr_keyboard_group *group =
|
|
|
|
calloc(1, sizeof(struct wlr_keyboard_group));
|
|
|
|
if (!group) {
|
|
|
|
wlr_log(WLR_ERROR, "Failed to allocate wlr_keyboard_group");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-03-01 20:49:30 +01:00
|
|
|
wlr_keyboard_init(&group->keyboard, &impl, "wlr_keyboard_group");
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
wl_list_init(&group->devices);
|
|
|
|
wl_list_init(&group->keys);
|
|
|
|
|
2020-05-31 23:10:15 +02:00
|
|
|
wl_signal_init(&group->events.enter);
|
|
|
|
wl_signal_init(&group->events.leave);
|
|
|
|
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
return group;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct wlr_keyboard_group *wlr_keyboard_group_from_wlr_keyboard(
|
|
|
|
struct wlr_keyboard *keyboard) {
|
|
|
|
if (keyboard->impl != &impl) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return (struct wlr_keyboard_group *)keyboard;
|
|
|
|
}
|
|
|
|
|
2020-05-31 23:10:15 +02:00
|
|
|
static bool process_key(struct keyboard_group_device *group_device,
|
2022-03-09 21:05:12 +01:00
|
|
|
struct wlr_keyboard_key_event *event) {
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
struct wlr_keyboard_group *group = group_device->keyboard->group;
|
|
|
|
|
|
|
|
struct keyboard_group_key *key, *tmp;
|
|
|
|
wl_list_for_each_safe(key, tmp, &group->keys, link) {
|
|
|
|
if (key->keycode != event->keycode) {
|
|
|
|
continue;
|
|
|
|
}
|
2020-10-21 17:21:23 +02:00
|
|
|
if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
key->count++;
|
2020-05-31 23:10:15 +02:00
|
|
|
return false;
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
}
|
2020-10-21 17:21:23 +02:00
|
|
|
if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
key->count--;
|
|
|
|
if (key->count > 0) {
|
2020-05-31 23:10:15 +02:00
|
|
|
return false;
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
}
|
|
|
|
wl_list_remove(&key->link);
|
|
|
|
free(key);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-10-21 17:21:23 +02:00
|
|
|
if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
struct keyboard_group_key *key =
|
|
|
|
calloc(1, sizeof(struct keyboard_group_key));
|
|
|
|
if (!key) {
|
|
|
|
wlr_log(WLR_ERROR, "Failed to allocate keyboard_group_key");
|
2020-05-31 23:10:15 +02:00
|
|
|
return false;
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
}
|
|
|
|
key->keycode = event->keycode;
|
|
|
|
key->count = 1;
|
|
|
|
wl_list_insert(&group->keys, &key->link);
|
|
|
|
}
|
|
|
|
|
2020-05-31 23:10:15 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handle_keyboard_key(struct wl_listener *listener, void *data) {
|
|
|
|
struct keyboard_group_device *group_device =
|
|
|
|
wl_container_of(listener, group_device, key);
|
|
|
|
if (process_key(group_device, data)) {
|
|
|
|
wlr_keyboard_notify_key(&group_device->keyboard->group->keyboard, data);
|
|
|
|
}
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void handle_keyboard_modifiers(struct wl_listener *listener,
|
|
|
|
void *data) {
|
|
|
|
// Sync the effective layout (group modifier) to all keyboards. The rest of
|
|
|
|
// the modifiers will be derived from the wlr_keyboard_group's key state
|
|
|
|
struct keyboard_group_device *group_device =
|
|
|
|
wl_container_of(listener, group_device, modifiers);
|
|
|
|
struct wlr_keyboard_modifiers mods = group_device->keyboard->modifiers;
|
|
|
|
|
|
|
|
struct keyboard_group_device *device;
|
|
|
|
wl_list_for_each(device, &group_device->keyboard->group->devices, link) {
|
|
|
|
if (mods.depressed != device->keyboard->modifiers.depressed ||
|
|
|
|
mods.latched != device->keyboard->modifiers.latched ||
|
|
|
|
mods.locked != device->keyboard->modifiers.locked ||
|
|
|
|
mods.group != device->keyboard->modifiers.group) {
|
|
|
|
wlr_keyboard_notify_modifiers(device->keyboard,
|
|
|
|
mods.depressed, mods.latched, mods.locked, mods.group);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
wlr_keyboard_notify_modifiers(&group_device->keyboard->group->keyboard,
|
|
|
|
mods.depressed, mods.latched, mods.locked, mods.group);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handle_keyboard_keymap(struct wl_listener *listener, void *data) {
|
|
|
|
struct keyboard_group_device *group_device =
|
|
|
|
wl_container_of(listener, group_device, keymap);
|
|
|
|
struct wlr_keyboard *keyboard = group_device->keyboard;
|
|
|
|
|
2020-05-08 04:15:26 +02:00
|
|
|
if (!wlr_keyboard_keymaps_match(keyboard->group->keyboard.keymap,
|
|
|
|
keyboard->keymap)) {
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
struct keyboard_group_device *device;
|
|
|
|
wl_list_for_each(device, &keyboard->group->devices, link) {
|
2020-05-08 04:15:26 +02:00
|
|
|
if (!wlr_keyboard_keymaps_match(keyboard->keymap,
|
|
|
|
device->keyboard->keymap)) {
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
wlr_keyboard_set_keymap(device->keyboard, keyboard->keymap);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
wlr_keyboard_set_keymap(&keyboard->group->keyboard, keyboard->keymap);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handle_keyboard_repeat_info(struct wl_listener *listener,
|
|
|
|
void *data) {
|
|
|
|
struct keyboard_group_device *group_device =
|
|
|
|
wl_container_of(listener, group_device, repeat_info);
|
|
|
|
struct wlr_keyboard *keyboard = group_device->keyboard;
|
|
|
|
|
|
|
|
struct keyboard_group_device *device;
|
|
|
|
wl_list_for_each(device, &keyboard->group->devices, link) {
|
|
|
|
struct wlr_keyboard *devkb = device->keyboard;
|
|
|
|
if (devkb->repeat_info.rate != keyboard->repeat_info.rate ||
|
|
|
|
devkb->repeat_info.delay != keyboard->repeat_info.delay) {
|
|
|
|
wlr_keyboard_set_repeat_info(devkb, keyboard->repeat_info.rate,
|
|
|
|
keyboard->repeat_info.delay);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
wlr_keyboard_set_repeat_info(&keyboard->group->keyboard,
|
|
|
|
keyboard->repeat_info.rate, keyboard->repeat_info.delay);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void refresh_state(struct keyboard_group_device *device,
|
2020-10-21 17:21:23 +02:00
|
|
|
enum wl_keyboard_key_state state) {
|
2020-05-31 23:10:15 +02:00
|
|
|
struct wl_array keys;
|
|
|
|
wl_array_init(&keys);
|
|
|
|
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
for (size_t i = 0; i < device->keyboard->num_keycodes; i++) {
|
|
|
|
struct timespec now;
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
2022-03-09 21:05:12 +01:00
|
|
|
struct wlr_keyboard_key_event event = {
|
2019-12-29 23:04:17 +01:00
|
|
|
.time_msec = (int64_t)now.tv_sec * 1000 + now.tv_nsec / 1000000,
|
|
|
|
.keycode = device->keyboard->keycodes[i],
|
|
|
|
.update_state = true,
|
|
|
|
.state = state
|
|
|
|
};
|
2020-05-31 23:10:15 +02:00
|
|
|
|
|
|
|
// Update the group's key state and determine whether this is a unique
|
|
|
|
// key that needs to be passed on to the compositor
|
|
|
|
if (process_key(device, &event)) {
|
|
|
|
// Update state for wlr_keyboard_group's keyboard
|
|
|
|
keyboard_key_update(&device->keyboard->group->keyboard, &event);
|
|
|
|
keyboard_modifier_update(&device->keyboard->group->keyboard);
|
|
|
|
keyboard_led_update(&device->keyboard->group->keyboard);
|
|
|
|
|
|
|
|
// Add the key to the array
|
|
|
|
uint32_t *key = wl_array_add(&keys, sizeof(uint32_t));
|
|
|
|
*key = event.keycode;
|
|
|
|
}
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
}
|
2020-05-31 23:10:15 +02:00
|
|
|
|
|
|
|
// If there are any unique keys, emit the enter/leave event
|
|
|
|
if (keys.size > 0) {
|
2020-10-21 17:21:23 +02:00
|
|
|
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
2022-08-18 13:16:16 +02:00
|
|
|
wl_signal_emit_mutable(&device->keyboard->group->events.enter, &keys);
|
2020-05-31 23:10:15 +02:00
|
|
|
} else {
|
2022-08-18 13:16:16 +02:00
|
|
|
wl_signal_emit_mutable(&device->keyboard->group->events.leave, &keys);
|
2020-05-31 23:10:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
wl_array_release(&keys);
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void remove_keyboard_group_device(struct keyboard_group_device *device) {
|
2020-10-21 17:21:23 +02:00
|
|
|
refresh_state(device, WL_KEYBOARD_KEY_STATE_RELEASED);
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
device->keyboard->group = NULL;
|
|
|
|
wl_list_remove(&device->link);
|
|
|
|
wl_list_remove(&device->key.link);
|
|
|
|
wl_list_remove(&device->modifiers.link);
|
|
|
|
wl_list_remove(&device->keymap.link);
|
|
|
|
wl_list_remove(&device->repeat_info.link);
|
|
|
|
wl_list_remove(&device->destroy.link);
|
|
|
|
free(device);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handle_keyboard_destroy(struct wl_listener *listener, void *data) {
|
|
|
|
struct keyboard_group_device *device =
|
|
|
|
wl_container_of(listener, device, destroy);
|
|
|
|
remove_keyboard_group_device(device);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool wlr_keyboard_group_add_keyboard(struct wlr_keyboard_group *group,
|
|
|
|
struct wlr_keyboard *keyboard) {
|
|
|
|
if (keyboard->group) {
|
|
|
|
wlr_log(WLR_ERROR, "A wlr_keyboard can only belong to one group");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (keyboard->impl == &impl) {
|
|
|
|
wlr_log(WLR_ERROR, "Cannot add a group's keyboard to a group");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-05-08 04:15:26 +02:00
|
|
|
if (!wlr_keyboard_keymaps_match(group->keyboard.keymap, keyboard->keymap)) {
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
wlr_log(WLR_ERROR, "Device keymap does not match keyboard group's");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct keyboard_group_device *device =
|
|
|
|
calloc(1, sizeof(struct keyboard_group_device));
|
|
|
|
if (!device) {
|
|
|
|
wlr_log(WLR_ERROR, "Failed to allocate keyboard_group_device");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
device->keyboard = keyboard;
|
|
|
|
keyboard->group = group;
|
|
|
|
wl_list_insert(&group->devices, &device->link);
|
|
|
|
|
|
|
|
wl_signal_add(&keyboard->events.key, &device->key);
|
|
|
|
device->key.notify = handle_keyboard_key;
|
|
|
|
|
|
|
|
wl_signal_add(&keyboard->events.modifiers, &device->modifiers);
|
|
|
|
device->modifiers.notify = handle_keyboard_modifiers;
|
|
|
|
|
|
|
|
wl_signal_add(&keyboard->events.keymap, &device->keymap);
|
|
|
|
device->keymap.notify = handle_keyboard_keymap;
|
|
|
|
|
|
|
|
wl_signal_add(&keyboard->events.repeat_info, &device->repeat_info);
|
|
|
|
device->repeat_info.notify = handle_keyboard_repeat_info;
|
|
|
|
|
2022-03-08 21:53:21 +01:00
|
|
|
wl_signal_add(&keyboard->base.events.destroy, &device->destroy);
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
device->destroy.notify = handle_keyboard_destroy;
|
|
|
|
|
|
|
|
struct wlr_keyboard *group_kb = &group->keyboard;
|
|
|
|
if (keyboard->modifiers.group != group_kb->modifiers.group) {
|
|
|
|
wlr_keyboard_notify_modifiers(keyboard, keyboard->modifiers.depressed,
|
|
|
|
keyboard->modifiers.latched, keyboard->modifiers.locked,
|
|
|
|
group_kb->modifiers.group);
|
|
|
|
}
|
|
|
|
if (keyboard->repeat_info.rate != group_kb->repeat_info.rate ||
|
|
|
|
keyboard->repeat_info.delay != group_kb->repeat_info.delay) {
|
|
|
|
wlr_keyboard_set_repeat_info(keyboard, group_kb->repeat_info.rate,
|
|
|
|
group_kb->repeat_info.delay);
|
|
|
|
}
|
|
|
|
|
2020-10-21 17:21:23 +02:00
|
|
|
refresh_state(device, WL_KEYBOARD_KEY_STATE_PRESSED);
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void wlr_keyboard_group_remove_keyboard(struct wlr_keyboard_group *group,
|
|
|
|
struct wlr_keyboard *keyboard) {
|
|
|
|
struct keyboard_group_device *device, *tmp;
|
|
|
|
wl_list_for_each_safe(device, tmp, &group->devices, link) {
|
|
|
|
if (device->keyboard == keyboard) {
|
|
|
|
remove_keyboard_group_device(device);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wlr_log(WLR_ERROR, "keyboard not found in group");
|
|
|
|
}
|
|
|
|
|
|
|
|
void wlr_keyboard_group_destroy(struct wlr_keyboard_group *group) {
|
|
|
|
struct keyboard_group_device *device, *tmp;
|
|
|
|
wl_list_for_each_safe(device, tmp, &group->devices, link) {
|
|
|
|
wlr_keyboard_group_remove_keyboard(group, device->keyboard);
|
|
|
|
}
|
2022-03-01 20:49:30 +01:00
|
|
|
wlr_keyboard_finish(&group->keyboard);
|
2020-05-31 23:10:15 +02:00
|
|
|
wl_list_remove(&group->events.enter.listener_list);
|
|
|
|
wl_list_remove(&group->events.leave.listener_list);
|
Introduce wlr_keyboard_group
A wlr_keyboard_group allows for multiple keyboard devices to be
combined into one logical keyboard. Each keyboard device can only be
added to one keyboard group. This helps with the situation where one
physical keyboard is exposed as multiple keyboard devices. It is up to
the compositors on how they group keyboards together, if at all.
Since a wlr_keyboard_group is one logical keyboard, the keys are a set.
This means that if a key is pressed on multiple keyboard devices, the
key event will only be emitted once, but the internal state will count
the number of devices that the key is pressed on. Likewise, the key
release will not be emitted until the key is released from all devices.
If the compositor wants access to which keys are pressed and released
on each keyboard device, the events for those devices can be listened
to, as they currently are, in addition to the group keyboard's events.
Also, all keyboard devices in the group must share the same keymap. If
the keymap's differ, the keyboard device will not be able to be added
to the group. Once in the group, if the keymap or effective layout for
one keyboard device changes, it will be synced to all keyboard devices
in the group. The repeat info and keyboard modifiers are also synced
2019-11-03 20:18:41 +01:00
|
|
|
free(group);
|
|
|
|
}
|