aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2019-08-15 00:59:39 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2019-08-27 09:37:10 +0900
commit091b87bfb89726bc13b4763d4f730f7d17cfc575 (patch)
treeabe31357795cf803bd0797963520319fb4ace144
parentlayer-shell: add support for popups (diff)
downloadsway-091b87bfb89726bc13b4763d4f730f7d17cfc575.tar.gz
sway-091b87bfb89726bc13b4763d4f730f7d17cfc575.tar.zst
sway-091b87bfb89726bc13b4763d4f730f7d17cfc575.zip
input/keyboard: send released only if pressed sent
This keeps track of whether surfaces received a key press event and will only send a key release event if the pressed event was sent. This also requires changing the keycodes that are sent via wl_keyboard_enter to only include those that were previously sent. This makes it so surfaces do not receive key release events for keys that they never received a key press for and makes it so switching focus doesn't leak keycodes that were consumed by bindings.
-rw-r--r--include/sway/input/keyboard.h1
-rw-r--r--sway/input/keyboard.c22
-rw-r--r--sway/input/seat.c58
3 files changed, 54 insertions, 27 deletions
diff --git a/include/sway/input/keyboard.h b/include/sway/input/keyboard.h
index 1ff63c94..4aa0d8f4 100644
--- a/include/sway/input/keyboard.h
+++ b/include/sway/input/keyboard.h
@@ -60,6 +60,7 @@ struct sway_keyboard {
60 struct sway_shortcut_state state_keysyms_translated; 60 struct sway_shortcut_state state_keysyms_translated;
61 struct sway_shortcut_state state_keysyms_raw; 61 struct sway_shortcut_state state_keysyms_raw;
62 struct sway_shortcut_state state_keycodes; 62 struct sway_shortcut_state state_keycodes;
63 struct sway_shortcut_state state_pressed_sent;
63 struct sway_binding *held_binding; 64 struct sway_binding *held_binding;
64 65
65 struct wl_event_source *key_repeat_source; 66 struct wl_event_source *key_repeat_source;
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c
index 680d1f69..3e196ae1 100644
--- a/sway/input/keyboard.c
+++ b/sway/input/keyboard.c
@@ -69,8 +69,9 @@ int get_modifier_names(const char **names, uint32_t modifier_masks) {
69/** 69/**
70 * Remove all key ids associated to a keycode from the list of pressed keys 70 * Remove all key ids associated to a keycode from the list of pressed keys
71 */ 71 */
72static void state_erase_key(struct sway_shortcut_state *state, 72static bool state_erase_key(struct sway_shortcut_state *state,
73 uint32_t keycode) { 73 uint32_t keycode) {
74 bool found = false;
74 size_t j = 0; 75 size_t j = 0;
75 for (size_t i = 0; i < state->npressed; ++i) { 76 for (size_t i = 0; i < state->npressed; ++i) {
76 if (i > j) { 77 if (i > j) {
@@ -79,6 +80,8 @@ static void state_erase_key(struct sway_shortcut_state *state,
79 } 80 }
80 if (state->pressed_keycodes[i] != keycode) { 81 if (state->pressed_keycodes[i] != keycode) {
81 ++j; 82 ++j;
83 } else {
84 found = true;
82 } 85 }
83 } 86 }
84 while(state->npressed > j) { 87 while(state->npressed > j) {
@@ -87,6 +90,7 @@ static void state_erase_key(struct sway_shortcut_state *state,
87 state->pressed_keycodes[state->npressed] = 0; 90 state->pressed_keycodes[state->npressed] = 0;
88 } 91 }
89 state->current_key = 0; 92 state->current_key = 0;
93 return found;
90} 94}
91 95
92/** 96/**
@@ -117,7 +121,7 @@ static void state_add_key(struct sway_shortcut_state *state,
117/** 121/**
118 * Update the shortcut model state in response to new input 122 * Update the shortcut model state in response to new input
119 */ 123 */
120static void update_shortcut_state(struct sway_shortcut_state *state, 124static bool update_shortcut_state(struct sway_shortcut_state *state,
121 struct wlr_event_keyboard_key *event, uint32_t new_key, 125 struct wlr_event_keyboard_key *event, uint32_t new_key,
122 uint32_t raw_modifiers) { 126 uint32_t raw_modifiers) {
123 bool last_key_was_a_modifier = raw_modifiers != state->last_raw_modifiers; 127 bool last_key_was_a_modifier = raw_modifiers != state->last_raw_modifiers;
@@ -133,8 +137,10 @@ static void update_shortcut_state(struct sway_shortcut_state *state,
133 state_add_key(state, event->keycode, new_key); 137 state_add_key(state, event->keycode, new_key);
134 state->last_keycode = event->keycode; 138 state->last_keycode = event->keycode;
135 } else { 139 } else {
136 state_erase_key(state, event->keycode); 140 return state_erase_key(state, event->keycode);
137 } 141 }
142
143 return false;
138} 144}
139 145
140/** 146/**
@@ -430,9 +436,13 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
430 } 436 }
431 437
432 if (!handled || event->state == WLR_KEY_RELEASED) { 438 if (!handled || event->state == WLR_KEY_RELEASED) {
433 wlr_seat_set_keyboard(wlr_seat, wlr_device); 439 bool pressed_sent = update_shortcut_state(
434 wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, 440 &keyboard->state_pressed_sent, event, (uint32_t)keycode, 0);
435 event->keycode, event->state); 441 if (pressed_sent || event->state == WLR_KEY_PRESSED) {
442 wlr_seat_set_keyboard(wlr_seat, wlr_device);
443 wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,
444 event->keycode, event->state);
445 }
436 } 446 }
437 447
438 transaction_commit_dirty(); 448 transaction_commit_dirty();
diff --git a/sway/input/seat.c b/sway/input/seat.c
index f28c1cb9..a4118a18 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -1,4 +1,5 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#include <assert.h>
2#include <linux/input-event-codes.h> 3#include <linux/input-event-codes.h>
3#include <string.h> 4#include <string.h>
4#include <strings.h> 5#include <strings.h>
@@ -85,6 +86,38 @@ static void seat_send_activate(struct sway_node *node, struct sway_seat *seat) {
85 } 86 }
86} 87}
87 88
89static struct sway_keyboard *sway_keyboard_for_wlr_keyboard(
90 struct sway_seat *seat, struct wlr_keyboard *wlr_keyboard) {
91 struct sway_seat_device *seat_device;
92 wl_list_for_each(seat_device, &seat->devices, link) {
93 struct sway_input_device *input_device = seat_device->input_device;
94 if (input_device->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) {
95 continue;
96 }
97 if (input_device->wlr_device->keyboard == wlr_keyboard) {
98 return seat_device->keyboard;
99 }
100 }
101 return NULL;
102}
103
104static void seat_keyboard_notify_enter(struct sway_seat *seat,
105 struct wlr_surface *surface) {
106 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
107 if (!keyboard) {
108 wlr_seat_keyboard_notify_enter(seat->wlr_seat, surface, NULL, 0, NULL);
109 return;
110 }
111
112 struct sway_keyboard *sway_keyboard =
113 sway_keyboard_for_wlr_keyboard(seat, keyboard);
114 assert(sway_keyboard && "Cannot find sway_keyboard for seat keyboard");
115
116 struct sway_shortcut_state *state = &sway_keyboard->state_pressed_sent;
117 wlr_seat_keyboard_notify_enter(seat->wlr_seat, surface,
118 state->pressed_keycodes, state->npressed, &keyboard->modifiers);
119}
120
88/** 121/**
89 * If con is a view, set it as active and enable keyboard input. 122 * If con is a view, set it as active and enable keyboard input.
90 * If con is a container, set all child views as active and don't enable 123 * If con is a container, set all child views as active and don't enable
@@ -103,15 +136,8 @@ static void seat_send_focus(struct sway_node *node, struct sway_seat *seat) {
103 wlr_xwayland_set_seat(xwayland, seat->wlr_seat); 136 wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
104 } 137 }
105#endif 138#endif
106 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); 139
107 if (keyboard) { 140 seat_keyboard_notify_enter(seat, view->surface);
108 wlr_seat_keyboard_notify_enter(seat->wlr_seat,
109 view->surface, keyboard->keycodes,
110 keyboard->num_keycodes, &keyboard->modifiers);
111 } else {
112 wlr_seat_keyboard_notify_enter(
113 seat->wlr_seat, view->surface, NULL, 0, NULL);
114 }
115 141
116 struct wlr_pointer_constraint_v1 *constraint = 142 struct wlr_pointer_constraint_v1 *constraint =
117 wlr_pointer_constraints_v1_constraint_for_surface( 143 wlr_pointer_constraints_v1_constraint_for_surface(
@@ -578,8 +604,6 @@ static void seat_configure_keyboard(struct sway_seat *seat,
578 if (!seat_device->keyboard) { 604 if (!seat_device->keyboard) {
579 sway_keyboard_create(seat, seat_device); 605 sway_keyboard_create(seat, seat_device);
580 } 606 }
581 struct wlr_keyboard *wlr_keyboard =
582 seat_device->input_device->wlr_device->keyboard;
583 sway_keyboard_configure(seat_device->keyboard); 607 sway_keyboard_configure(seat_device->keyboard);
584 wlr_seat_set_keyboard(seat->wlr_seat, 608 wlr_seat_set_keyboard(seat->wlr_seat,
585 seat_device->input_device->wlr_device); 609 seat_device->input_device->wlr_device);
@@ -587,9 +611,7 @@ static void seat_configure_keyboard(struct sway_seat *seat,
587 if (focus && node_is_view(focus)) { 611 if (focus && node_is_view(focus)) {
588 // force notify reenter to pick up the new configuration 612 // force notify reenter to pick up the new configuration
589 wlr_seat_keyboard_clear_focus(seat->wlr_seat); 613 wlr_seat_keyboard_clear_focus(seat->wlr_seat);
590 wlr_seat_keyboard_notify_enter(seat->wlr_seat, 614 seat_keyboard_notify_enter(seat, focus->sway_container->view->surface);
591 focus->sway_container->view->surface, wlr_keyboard->keycodes,
592 wlr_keyboard->num_keycodes, &wlr_keyboard->modifiers);
593 } 615 }
594} 616}
595 617
@@ -1049,13 +1071,7 @@ void seat_set_focus_surface(struct sway_seat *seat,
1049 seat_send_unfocus(focus, seat); 1071 seat_send_unfocus(focus, seat);
1050 seat->has_focus = false; 1072 seat->has_focus = false;
1051 } 1073 }
1052 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); 1074 seat_keyboard_notify_enter(seat, surface);
1053 if (keyboard) {
1054 wlr_seat_keyboard_notify_enter(seat->wlr_seat, surface,
1055 keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers);
1056 } else {
1057 wlr_seat_keyboard_notify_enter(seat->wlr_seat, surface, NULL, 0, NULL);
1058 }
1059} 1075}
1060 1076
1061void seat_set_focus_layer(struct sway_seat *seat, 1077void seat_set_focus_layer(struct sway_seat *seat,