aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/types/wlr_keyboard.h8
-rw-r--r--include/wlr/types/wlr_keyboard_group.h24
-rw-r--r--types/wlr_keyboard.c7
-rw-r--r--types/wlr_keyboard_group.c57
4 files changed, 84 insertions, 12 deletions
diff --git a/include/types/wlr_keyboard.h b/include/types/wlr_keyboard.h
new file mode 100644
index 00000000..e28462b5
--- /dev/null
+++ b/include/types/wlr_keyboard.h
@@ -0,0 +1,8 @@
+#include "wlr/types/wlr_keyboard.h"
+
+void keyboard_key_update(struct wlr_keyboard *keyboard,
+ struct wlr_event_keyboard_key *event);
+
+bool keyboard_modifier_update(struct wlr_keyboard *keyboard);
+
+void keyboard_led_update(struct wlr_keyboard *keyboard);
diff --git a/include/wlr/types/wlr_keyboard_group.h b/include/wlr/types/wlr_keyboard_group.h
index 023887f3..0b3df226 100644
--- a/include/wlr/types/wlr_keyboard_group.h
+++ b/include/wlr/types/wlr_keyboard_group.h
@@ -18,6 +18,30 @@ struct wlr_keyboard_group {
struct wlr_input_device *input_device;
struct wl_list devices; // keyboard_group_device::link
struct wl_list keys; // keyboard_group_key::link
+
+ struct {
+ /*
+ * Sent when a keyboard has entered the group with keys currently
+ * pressed that are not pressed by any other keyboard in the group. The
+ * data for this signal will be a wl_array containing the key codes.
+ * This should be used to update the compositor's internal state.
+ * Bindings should not be triggered based off of these key codes and
+ * they should also not notify any surfaces of the key press.
+ */
+ struct wl_signal enter;
+
+ /*
+ * Sent when a keyboard has left the group with keys currently pressed
+ * that are not pressed by any other keyboard in the group. The data for
+ * this signal will be a wl_array containing the key codes. This should
+ * be used to update the compositor's internal state. Bindings should
+ * not be triggered based off of these key codes. Additionally, surfaces
+ * should only be notified if they received a corresponding key press
+ * for the key code.
+ */
+ struct wl_signal leave;
+ } events;
+
void *data;
};
diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c
index 72b8eab5..50363fed 100644
--- a/types/wlr_keyboard.c
+++ b/types/wlr_keyboard.c
@@ -6,9 +6,10 @@
#include <wlr/interfaces/wlr_keyboard.h>
#include <wlr/types/wlr_keyboard.h>
#include <wlr/util/log.h>
+#include "types/wlr_keyboard.h"
#include "util/signal.h"
-static void keyboard_led_update(struct wlr_keyboard *keyboard) {
+void keyboard_led_update(struct wlr_keyboard *keyboard) {
if (keyboard->xkb_state == NULL) {
return;
}
@@ -27,7 +28,7 @@ static void keyboard_led_update(struct wlr_keyboard *keyboard) {
* Update the modifier state of the wlr-keyboard. Returns true if the modifier
* state changed.
*/
-static bool keyboard_modifier_update(struct wlr_keyboard *keyboard) {
+bool keyboard_modifier_update(struct wlr_keyboard *keyboard) {
if (keyboard->xkb_state == NULL) {
return false;
}
@@ -55,7 +56,7 @@ static bool keyboard_modifier_update(struct wlr_keyboard *keyboard) {
return true;
}
-static void keyboard_key_update(struct wlr_keyboard *keyboard,
+void keyboard_key_update(struct wlr_keyboard *keyboard,
struct wlr_event_keyboard_key *event) {
if (event->state == WLR_KEY_PRESSED) {
set_add(keyboard->keycodes, &keyboard->num_keycodes,
diff --git a/types/wlr_keyboard_group.c b/types/wlr_keyboard_group.c
index 059a4767..ace1fcd2 100644
--- a/types/wlr_keyboard_group.c
+++ b/types/wlr_keyboard_group.c
@@ -5,6 +5,8 @@
#include <time.h>
#include <wayland-server-core.h>
#include <xkbcommon/xkbcommon.h>
+#include "types/wlr_keyboard.h"
+#include "util/signal.h"
#include "wlr/interfaces/wlr_keyboard.h"
#include "wlr/types/wlr_keyboard.h"
#include "wlr/types/wlr_keyboard_group.h"
@@ -70,6 +72,9 @@ struct wlr_keyboard_group *wlr_keyboard_group_create(void) {
wl_list_init(&group->devices);
wl_list_init(&group->keys);
+ wl_signal_init(&group->events.enter);
+ wl_signal_init(&group->events.leave);
+
return group;
}
@@ -81,11 +86,9 @@ struct wlr_keyboard_group *wlr_keyboard_group_from_wlr_keyboard(
return (struct wlr_keyboard_group *)keyboard;
}
-static void handle_keyboard_key(struct wl_listener *listener, void *data) {
- struct keyboard_group_device *group_device =
- wl_container_of(listener, group_device, key);
+static bool process_key(struct keyboard_group_device *group_device,
+ struct wlr_event_keyboard_key *event) {
struct wlr_keyboard_group *group = group_device->keyboard->group;
- struct wlr_event_keyboard_key *event = data;
struct keyboard_group_key *key, *tmp;
wl_list_for_each_safe(key, tmp, &group->keys, link) {
@@ -94,12 +97,12 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
}
if (event->state == WLR_KEY_PRESSED) {
key->count++;
- return;
+ return false;
}
if (event->state == WLR_KEY_RELEASED) {
key->count--;
if (key->count > 0) {
- return;
+ return false;
}
wl_list_remove(&key->link);
free(key);
@@ -112,14 +115,22 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
calloc(1, sizeof(struct keyboard_group_key));
if (!key) {
wlr_log(WLR_ERROR, "Failed to allocate keyboard_group_key");
- return;
+ return false;
}
key->keycode = event->keycode;
key->count = 1;
wl_list_insert(&group->keys, &key->link);
}
- wlr_keyboard_notify_key(&group_device->keyboard->group->keyboard, data);
+ 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);
+ }
}
static void handle_keyboard_modifiers(struct wl_listener *listener,
@@ -189,6 +200,9 @@ static void handle_keyboard_repeat_info(struct wl_listener *listener,
static void refresh_state(struct keyboard_group_device *device,
enum wlr_key_state state) {
+ struct wl_array keys;
+ wl_array_init(&keys);
+
for (size_t i = 0; i < device->keyboard->num_keycodes; i++) {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -198,8 +212,31 @@ static void refresh_state(struct keyboard_group_device *device,
.update_state = true,
.state = state
};
- handle_keyboard_key(&device->key, &event);
+
+ // 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;
+ }
}
+
+ // If there are any unique keys, emit the enter/leave event
+ if (keys.size > 0) {
+ if (state == WLR_KEY_PRESSED) {
+ wlr_signal_emit_safe(&device->keyboard->group->events.enter, &keys);
+ } else {
+ wlr_signal_emit_safe(&device->keyboard->group->events.leave, &keys);
+ }
+ }
+
+ wl_array_release(&keys);
}
static void remove_keyboard_group_device(struct keyboard_group_device *device) {
@@ -298,6 +335,8 @@ void wlr_keyboard_group_destroy(struct wlr_keyboard_group *group) {
}
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);
}