aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsaac Freund <ifreund@ifreund.xyz>2020-03-13 20:22:59 +0100
committerDrew DeVault <sir@cmpwn.com>2020-03-13 22:19:51 +0100
commit3f617631cb68c0e90a755b86f9c241caf0080f9a (patch)
tree5215313ebfd1303150a447bb1bbd7dd8618d1367
parente0bbafc253fc69cd9f0e6629cf33c5d247cc9978 (diff)
Send keyboard enter/leave on capability change
This is more correct according to the protocol and fixes issues with clients that wait for an enter event before processing key events
-rw-r--r--include/types/wlr_seat.h2
-rw-r--r--types/seat/wlr_seat.c13
-rw-r--r--types/seat/wlr_seat_keyboard.c45
3 files changed, 50 insertions, 10 deletions
diff --git a/include/types/wlr_seat.h b/include/types/wlr_seat.h
index 2a3cd69b..f96db148 100644
--- a/include/types/wlr_seat.h
+++ b/include/types/wlr_seat.h
@@ -15,6 +15,8 @@ void seat_client_destroy_pointer(struct wl_resource *resource);
void seat_client_create_keyboard(struct wlr_seat_client *seat_client,
uint32_t version, uint32_t id);
void seat_client_destroy_keyboard(struct wl_resource *resource);
+void seat_client_send_keyboard_leave_raw(struct wlr_seat_client *seat_client,
+ struct wlr_surface *surface);
void seat_client_create_touch(struct wlr_seat_client *seat_client,
uint32_t version, uint32_t id);
diff --git a/types/seat/wlr_seat.c b/types/seat/wlr_seat.c
index b6b58c91..a9507069 100644
--- a/types/seat/wlr_seat.c
+++ b/types/seat/wlr_seat.c
@@ -322,6 +322,19 @@ void wlr_seat_set_capabilities(struct wlr_seat *wlr_seat,
}
}
if ((capabilities & WL_SEAT_CAPABILITY_KEYBOARD) == 0) {
+ struct wlr_seat_client *focused_client =
+ wlr_seat->keyboard_state.focused_client;
+ struct wlr_surface *focused_surface =
+ wlr_seat->keyboard_state.focused_surface;
+
+ if (focused_client != NULL && focused_surface != NULL) {
+ seat_client_send_keyboard_leave_raw(focused_client,
+ focused_surface);
+ }
+
+ // Note: we don't set focused client/surface to NULL since we need
+ // them to send the enter event if the keyboard is recreated
+
struct wl_resource *resource, *tmp;
wl_resource_for_each_safe(resource, tmp, &client->keyboards) {
seat_client_destroy_keyboard(resource);
diff --git a/types/seat/wlr_seat_keyboard.c b/types/seat/wlr_seat_keyboard.c
index 52a4222a..93e259c9 100644
--- a/types/seat/wlr_seat_keyboard.c
+++ b/types/seat/wlr_seat_keyboard.c
@@ -218,6 +218,18 @@ void wlr_seat_keyboard_send_modifiers(struct wlr_seat *seat,
}
}
+void seat_client_send_keyboard_leave_raw(struct wlr_seat_client *seat_client,
+ struct wlr_surface *surface) {
+ uint32_t serial = wlr_seat_client_next_serial(seat_client);
+ struct wl_resource *resource;
+ wl_resource_for_each(resource, &seat_client->keyboards) {
+ if (seat_client_from_keyboard_resource(resource) == NULL) {
+ continue;
+ }
+ wl_keyboard_send_leave(resource, serial, surface->resource);
+ }
+}
+
void wlr_seat_keyboard_enter(struct wlr_seat *seat,
struct wlr_surface *surface, uint32_t keycodes[], size_t num_keycodes,
struct wlr_keyboard_modifiers *modifiers) {
@@ -240,14 +252,7 @@ void wlr_seat_keyboard_enter(struct wlr_seat *seat,
// leave the previously entered surface
if (focused_client != NULL && focused_surface != NULL) {
- uint32_t serial = wlr_seat_client_next_serial(focused_client);
- struct wl_resource *resource;
- wl_resource_for_each(resource, &focused_client->keyboards) {
- if (seat_client_from_keyboard_resource(resource) == NULL) {
- continue;
- }
- wl_keyboard_send_leave(resource, serial, focused_surface->resource);
- }
+ seat_client_send_keyboard_leave_raw(focused_client, focused_surface);
}
// enter the current surface
@@ -409,8 +414,28 @@ void seat_client_create_keyboard(struct wlr_seat_client *seat_client,
seat_client_send_keymap(seat_client, keyboard);
seat_client_send_repeat_info(seat_client, keyboard);
- // TODO possibly handle the case where this keyboard needs an enter
- // right away
+ struct wlr_seat_client *focused_client =
+ seat_client->seat->keyboard_state.focused_client;
+ struct wlr_surface *focused_surface =
+ seat_client->seat->keyboard_state.focused_surface;
+
+ // Send an enter event if there is a focused client/surface stored
+ if (focused_client != NULL && focused_surface != NULL) {
+ struct wl_array keys;
+ wl_array_init(&keys);
+ uint32_t serial = wlr_seat_client_next_serial(focused_client);
+ struct wl_resource *resource;
+ wl_resource_for_each(resource, &focused_client->keyboards) {
+ if (wl_resource_get_id(resource) == id) {
+ if (seat_client_from_keyboard_resource(resource) == NULL) {
+ continue;
+ }
+ wl_keyboard_send_enter(resource, serial,
+ focused_surface->resource, &keys);
+ }
+ }
+ wl_array_release(&keys);
+ }
}
void seat_client_destroy_keyboard(struct wl_resource *resource) {