diff options
author | Brian Ashworth <bosrsf04@gmail.com> | 2019-08-15 00:59:39 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2019-08-20 11:14:56 +0900 |
commit | 384afc5cb5000374414eeaec8cbb667451fcce5b (patch) | |
tree | 3327591d7074585375addf18e5f013db057e93a5 | |
parent | Remove xdg-shell v6 support (diff) | |
download | sway-384afc5cb5000374414eeaec8cbb667451fcce5b.tar.gz sway-384afc5cb5000374414eeaec8cbb667451fcce5b.tar.zst sway-384afc5cb5000374414eeaec8cbb667451fcce5b.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.h | 1 | ||||
-rw-r--r-- | sway/input/keyboard.c | 22 | ||||
-rw-r--r-- | sway/input/seat.c | 58 |
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 | */ |
72 | static void state_erase_key(struct sway_shortcut_state *state, | 72 | static 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 | */ |
120 | static void update_shortcut_state(struct sway_shortcut_state *state, | 124 | static 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 | ||
89 | static 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 | |||
104 | static 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 | ||
1061 | void seat_set_focus_layer(struct sway_seat *seat, | 1077 | void seat_set_focus_layer(struct sway_seat *seat, |