diff options
author | 2018-05-31 19:35:17 -0400 | |
---|---|---|
committer | 2018-06-01 18:52:36 -0400 | |
commit | a056419ad720e20fdc04f3a7d05bce62fa639755 (patch) | |
tree | 5248788d8b24cbcea07897b884c243700997e460 /sway | |
parent | Use XKB keycode numbering for bindcode (diff) | |
download | sway-a056419ad720e20fdc04f3a7d05bce62fa639755.tar.gz sway-a056419ad720e20fdc04f3a7d05bce62fa639755.tar.zst sway-a056419ad720e20fdc04f3a7d05bce62fa639755.zip |
Rewrite shortcut handling code to avoid hardcoded values
The same shortcut algorithm is now used for keycodes,
raw keysyms, and translated keysyms. Pressed keysyms
are now stored in association with the keycodes that
generated them. Modifier keycodes (and associated
keysyms) are identified retroactively by the subsequent
change to the modifier flags.
Diffstat (limited to 'sway')
-rw-r--r-- | sway/input/keyboard.c | 411 |
1 files changed, 154 insertions, 257 deletions
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index e873eea3..e59d9c03 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -9,88 +9,93 @@ | |||
9 | #include "sway/commands.h" | 9 | #include "sway/commands.h" |
10 | #include "log.h" | 10 | #include "log.h" |
11 | 11 | ||
12 | static bool keysym_is_modifier(xkb_keysym_t keysym) { | 12 | /** |
13 | switch (keysym) { | 13 | * Update the shortcut model state in response to new input |
14 | case XKB_KEY_Shift_L: case XKB_KEY_Shift_R: | 14 | */ |
15 | case XKB_KEY_Control_L: case XKB_KEY_Control_R: | 15 | static void update_shortcut_model(struct sway_shortcut_state* state, |
16 | case XKB_KEY_Caps_Lock: | 16 | struct wlr_event_keyboard_key * event, |
17 | case XKB_KEY_Shift_Lock: | 17 | uint32_t new_key, |
18 | case XKB_KEY_Meta_L: case XKB_KEY_Meta_R: | 18 | bool last_key_was_a_modifier) { |
19 | case XKB_KEY_Alt_L: case XKB_KEY_Alt_R: | 19 | if (event->state == WLR_KEY_PRESSED) { |
20 | case XKB_KEY_Super_L: case XKB_KEY_Super_R: | 20 | if (last_key_was_a_modifier && state->last_key_index >= 0) { |
21 | case XKB_KEY_Hyper_L: case XKB_KEY_Hyper_R: | 21 | // Last pressed key before this one was a modifier. We nullify |
22 | return true; | 22 | // the key id but not the keycode (as that is used for erasure |
23 | default: | 23 | // on release) |
24 | return false; | 24 | state->pressed_keys[state->last_key_index] = 0; |
25 | } | 25 | state->last_key_index = -1; |
26 | } | ||
27 | |||
28 | static size_t pressed_keysyms_length(xkb_keysym_t *pressed_keysyms) { | ||
29 | size_t n = 0; | ||
30 | for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) { | ||
31 | if (pressed_keysyms[i] != XKB_KEY_NoSymbol) { | ||
32 | ++n; | ||
33 | } | 26 | } |
34 | } | ||
35 | return n; | ||
36 | } | ||
37 | 27 | ||
38 | static ssize_t pressed_keysyms_index(xkb_keysym_t *pressed_keysyms, | 28 | // Add current key to set; there may be duplicates |
39 | xkb_keysym_t keysym) { | 29 | for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYS_CAP; i++) { |
40 | for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) { | 30 | if (!state->pressed_keys[i]) { |
41 | if (pressed_keysyms[i] == keysym) { | 31 | state->pressed_keys[i] = new_key; |
42 | return i; | 32 | state->pressed_keycodes[i] = event->keycode; |
33 | state->last_key_index = i; | ||
34 | break; | ||
35 | } | ||
43 | } | 36 | } |
44 | } | 37 | } else { |
45 | return -1; | 38 | for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYS_CAP; i++) { |
46 | } | 39 | // The same keycode may match multiple keysyms. |
47 | 40 | if (state->pressed_keycodes[i] == event->keycode) { | |
48 | static void pressed_keysyms_add(xkb_keysym_t *pressed_keysyms, | 41 | state->pressed_keys[i] = 0; |
49 | xkb_keysym_t keysym) { | 42 | state->pressed_keycodes[i] = 0; |
50 | ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym); | 43 | } |
51 | if (i < 0) { | ||
52 | i = pressed_keysyms_index(pressed_keysyms, XKB_KEY_NoSymbol); | ||
53 | if (i >= 0) { | ||
54 | pressed_keysyms[i] = keysym; | ||
55 | } | 44 | } |
56 | } | 45 | } |
57 | } | 46 | } |
58 | 47 | ||
59 | static void pressed_keysyms_remove(xkb_keysym_t *pressed_keysyms, | 48 | /** |
60 | xkb_keysym_t keysym) { | 49 | * |
61 | ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym); | 50 | * Returns a binding which matches the shortcut model state (ignoring the |
62 | if (i >= 0) { | 51 | * `release` flag). |
63 | pressed_keysyms[i] = XKB_KEY_NoSymbol; | 52 | */ |
53 | static struct sway_binding* check_shortcut_model( | ||
54 | struct sway_shortcut_state* state, list_t* bindings, | ||
55 | uint32_t modifiers, bool locked) { | ||
56 | int npressed_keys = 0; | ||
57 | for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYS_CAP; i++) { | ||
58 | if (state->pressed_keys[i]) { | ||
59 | ++npressed_keys; | ||
60 | } | ||
64 | } | 61 | } |
65 | } | 62 | for (int i = 0; i < bindings->length; ++i) { |
63 | struct sway_binding *binding = bindings->items[i]; | ||
66 | 64 | ||
67 | static void pressed_keysyms_update(xkb_keysym_t *pressed_keysyms, | 65 | if (modifiers ^ binding->modifiers || |
68 | const xkb_keysym_t *keysyms, size_t keysyms_len, | 66 | npressed_keys != binding->keys->length || |
69 | enum wlr_key_state state) { | 67 | locked > binding->locked) { |
70 | for (size_t i = 0; i < keysyms_len; ++i) { | ||
71 | if (keysym_is_modifier(keysyms[i])) { | ||
72 | continue; | 68 | continue; |
73 | } | 69 | } |
74 | if (state == WLR_KEY_PRESSED) { | 70 | |
75 | pressed_keysyms_add(pressed_keysyms, keysyms[i]); | 71 | bool match = true; |
76 | } else { // WLR_KEY_RELEASED | 72 | for (int j = 0; j < binding->keys->length; ++j) { |
77 | pressed_keysyms_remove(pressed_keysyms, keysyms[i]); | 73 | uint32_t key = *(uint32_t*)binding->keys->items[j]; |
74 | |||
75 | bool key_found = false; | ||
76 | for (int k = 0; k < SWAY_KEYBOARD_PRESSED_KEYS_CAP; k++) { | ||
77 | if (state->pressed_keys[k] == key) { | ||
78 | key_found = true; | ||
79 | break; | ||
80 | } | ||
81 | } | ||
82 | if (!key_found) { | ||
83 | match = false; | ||
84 | break; | ||
85 | } | ||
78 | } | 86 | } |
79 | } | ||
80 | } | ||
81 | 87 | ||
82 | static bool binding_matches_key_state(struct sway_binding *binding, | 88 | if (match) { |
83 | enum wlr_key_state key_state) { | 89 | return binding; |
84 | if (key_state == WLR_KEY_PRESSED && !binding->release) { | 90 | } |
85 | return true; | ||
86 | } | ||
87 | if (key_state == WLR_KEY_RELEASED && binding->release) { | ||
88 | return true; | ||
89 | } | 91 | } |
90 | 92 | ||
91 | return false; | 93 | return NULL; |
92 | } | 94 | } |
93 | 95 | ||
96 | /** | ||
97 | * Execute the command associated to a binding | ||
98 | */ | ||
94 | static void keyboard_execute_command(struct sway_keyboard *keyboard, | 99 | static void keyboard_execute_command(struct sway_keyboard *keyboard, |
95 | struct sway_binding *binding) { | 100 | struct sway_binding *binding) { |
96 | wlr_log(L_DEBUG, "running command for binding: %s", | 101 | wlr_log(L_DEBUG, "running command for binding: %s", |
@@ -113,7 +118,7 @@ static void keyboard_execute_command(struct sway_keyboard *keyboard, | |||
113 | * should be propagated to clients. | 118 | * should be propagated to clients. |
114 | */ | 119 | */ |
115 | static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, | 120 | static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, |
116 | xkb_keysym_t *pressed_keysyms, uint32_t modifiers, size_t keysyms_len) { | 121 | const xkb_keysym_t *pressed_keysyms, uint32_t modifiers, size_t keysyms_len) { |
117 | for (size_t i = 0; i < keysyms_len; ++i) { | 122 | for (size_t i = 0; i < keysyms_len; ++i) { |
118 | xkb_keysym_t keysym = pressed_keysyms[i]; | 123 | xkb_keysym_t keysym = pressed_keysyms[i]; |
119 | if (keysym >= XKB_KEY_XF86Switch_VT_1 && | 124 | if (keysym >= XKB_KEY_XF86Switch_VT_1 && |
@@ -134,157 +139,6 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, | |||
134 | } | 139 | } |
135 | 140 | ||
136 | /** | 141 | /** |
137 | * Execute keyboard bindings bound with `bindysm` for the given keyboard state. | ||
138 | * | ||
139 | * Returns true if the keysym was handled by a binding and false if the event | ||
140 | * should be propagated to clients. | ||
141 | */ | ||
142 | static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard, | ||
143 | xkb_keysym_t *pressed_keysyms, uint32_t modifiers, | ||
144 | enum wlr_key_state key_state, bool locked) { | ||
145 | // configured bindings | ||
146 | int n = pressed_keysyms_length(pressed_keysyms); | ||
147 | list_t *keysym_bindings = config->current_mode->keysym_bindings; | ||
148 | for (int i = 0; i < keysym_bindings->length; ++i) { | ||
149 | struct sway_binding *binding = keysym_bindings->items[i]; | ||
150 | if (!binding_matches_key_state(binding, key_state) || | ||
151 | modifiers ^ binding->modifiers || | ||
152 | n != binding->keys->length || locked > binding->locked) { | ||
153 | continue; | ||
154 | } | ||
155 | |||
156 | bool match = true; | ||
157 | for (int j = 0; j < binding->keys->length; ++j) { | ||
158 | match = | ||
159 | pressed_keysyms_index(pressed_keysyms, | ||
160 | *(int*)binding->keys->items[j]) >= 0; | ||
161 | |||
162 | if (!match) { | ||
163 | break; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | if (match) { | ||
168 | keyboard_execute_command(keyboard, binding); | ||
169 | return true; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | return false; | ||
174 | } | ||
175 | |||
176 | static bool binding_matches_keycodes(struct wlr_keyboard *keyboard, | ||
177 | struct sway_binding *binding, struct wlr_event_keyboard_key *event, bool locked) { | ||
178 | assert(binding->bindcode); | ||
179 | |||
180 | uint32_t keycode = event->keycode + 8; | ||
181 | |||
182 | if (!binding_matches_key_state(binding, event->state)) { | ||
183 | return false; | ||
184 | } | ||
185 | |||
186 | if (locked > binding->locked) { | ||
187 | return false; | ||
188 | } | ||
189 | |||
190 | uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard); | ||
191 | if (modifiers ^ binding->modifiers) { | ||
192 | return false; | ||
193 | } | ||
194 | |||
195 | // on release, the released key must be in the binding | ||
196 | if (event->state == WLR_KEY_RELEASED) { | ||
197 | bool found = false; | ||
198 | for (int i = 0; i < binding->keys->length; ++i) { | ||
199 | uint32_t binding_keycode = *(uint32_t*)binding->keys->items[i] + 8; | ||
200 | if (binding_keycode == keycode) { | ||
201 | found = true; | ||
202 | break; | ||
203 | } | ||
204 | } | ||
205 | if (!found) { | ||
206 | return false; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | // every keycode in the binding must be present in the pressed keys on the | ||
211 | // keyboard | ||
212 | for (int i = 0; i < binding->keys->length; ++i) { | ||
213 | uint32_t binding_keycode = *(uint32_t*)binding->keys->items[i] + 8; | ||
214 | if (event->state == WLR_KEY_RELEASED && keycode == binding_keycode) { | ||
215 | continue; | ||
216 | } | ||
217 | |||
218 | bool found = false; | ||
219 | for (size_t j = 0; j < keyboard->num_keycodes; ++j) { | ||
220 | xkb_keycode_t keycode = keyboard->keycodes[j] + 8; | ||
221 | if (keycode == binding_keycode) { | ||
222 | found = true; | ||
223 | break; | ||
224 | } | ||
225 | } | ||
226 | |||
227 | if (!found) { | ||
228 | return false; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | // every keycode pressed on the keyboard must be present within the binding | ||
233 | // keys (unless it is a modifier) | ||
234 | for (size_t i = 0; i < keyboard->num_keycodes; ++i) { | ||
235 | xkb_keycode_t keycode = keyboard->keycodes[i] + 8; | ||
236 | bool found = false; | ||
237 | for (int j = 0; j < binding->keys->length; ++j) { | ||
238 | uint32_t binding_keycode = *(uint32_t*)binding->keys->items[j] + 8; | ||
239 | if (binding_keycode == keycode) { | ||
240 | found = true; | ||
241 | break; | ||
242 | } | ||
243 | } | ||
244 | |||
245 | if (!found) { | ||
246 | if (!binding->modifiers) { | ||
247 | return false; | ||
248 | } | ||
249 | |||
250 | // check if it is a modifier, which we know matched from the check | ||
251 | // above | ||
252 | const xkb_keysym_t *keysyms; | ||
253 | int num_keysyms = | ||
254 | xkb_state_key_get_syms(keyboard->xkb_state, | ||
255 | keycode, &keysyms); | ||
256 | if (num_keysyms != 1 || !keysym_is_modifier(keysyms[0])) { | ||
257 | return false; | ||
258 | } | ||
259 | } | ||
260 | } | ||
261 | |||
262 | return true; | ||
263 | } | ||
264 | |||
265 | /** | ||
266 | * Execute keyboard bindings bound with `bindcode` for the given keyboard state. | ||
267 | * | ||
268 | * Returns true if the keysym was handled by a binding and false if the event | ||
269 | * should be propagated to clients. | ||
270 | */ | ||
271 | static bool keyboard_execute_bindcode(struct sway_keyboard *keyboard, | ||
272 | struct wlr_event_keyboard_key *event, bool locked) { | ||
273 | struct wlr_keyboard *wlr_keyboard = | ||
274 | keyboard->seat_device->input_device->wlr_device->keyboard; | ||
275 | list_t *keycode_bindings = config->current_mode->keycode_bindings; | ||
276 | for (int i = 0; i < keycode_bindings->length; ++i) { | ||
277 | struct sway_binding *binding = keycode_bindings->items[i]; | ||
278 | if (binding_matches_keycodes(wlr_keyboard, binding, event, locked)) { | ||
279 | keyboard_execute_command(keyboard, binding); | ||
280 | return true; | ||
281 | } | ||
282 | } | ||
283 | |||
284 | return false; | ||
285 | } | ||
286 | |||
287 | /** | ||
288 | * Get keysyms and modifiers from the keyboard as xkb sees them. | 142 | * Get keysyms and modifiers from the keyboard as xkb sees them. |
289 | * | 143 | * |
290 | * This uses the xkb keysyms translation based on pressed modifiers and clears | 144 | * This uses the xkb keysyms translation based on pressed modifiers and clears |
@@ -339,61 +193,100 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { | |||
339 | struct wlr_event_keyboard_key *event = data; | 193 | struct wlr_event_keyboard_key *event = data; |
340 | bool input_inhibited = keyboard->seat_device->sway_seat->exclusive_client != NULL; | 194 | bool input_inhibited = keyboard->seat_device->sway_seat->exclusive_client != NULL; |
341 | 195 | ||
196 | // Identify new keycode, raw keysym(s), and translated keysym(s) | ||
342 | xkb_keycode_t keycode = event->keycode + 8; | 197 | xkb_keycode_t keycode = event->keycode + 8; |
343 | bool handled = false; | ||
344 | |||
345 | // handle keycodes | ||
346 | handled = keyboard_execute_bindcode(keyboard, event, input_inhibited); | ||
347 | 198 | ||
348 | // handle translated keysyms | ||
349 | if (!handled && event->state == WLR_KEY_RELEASED) { | ||
350 | handled = keyboard_execute_bindsym(keyboard, | ||
351 | keyboard->pressed_keysyms_translated, | ||
352 | keyboard->modifiers_translated, | ||
353 | event->state, input_inhibited); | ||
354 | } | ||
355 | const xkb_keysym_t *translated_keysyms; | 199 | const xkb_keysym_t *translated_keysyms; |
200 | uint32_t translated_modifiers; | ||
356 | size_t translated_keysyms_len = | 201 | size_t translated_keysyms_len = |
357 | keyboard_keysyms_translated(keyboard, keycode, &translated_keysyms, | 202 | keyboard_keysyms_translated(keyboard, keycode, &translated_keysyms, |
358 | &keyboard->modifiers_translated); | 203 | &translated_modifiers); |
359 | pressed_keysyms_update(keyboard->pressed_keysyms_translated, | ||
360 | translated_keysyms, translated_keysyms_len, event->state); | ||
361 | if (!handled && event->state == WLR_KEY_PRESSED) { | ||
362 | handled = keyboard_execute_bindsym(keyboard, | ||
363 | keyboard->pressed_keysyms_translated, | ||
364 | keyboard->modifiers_translated, | ||
365 | event->state, input_inhibited); | ||
366 | } | ||
367 | 204 | ||
368 | // Handle raw keysyms | ||
369 | if (!handled && event->state == WLR_KEY_RELEASED) { | ||
370 | handled = keyboard_execute_bindsym(keyboard, | ||
371 | keyboard->pressed_keysyms_raw, keyboard->modifiers_raw, | ||
372 | event->state, input_inhibited); | ||
373 | } | ||
374 | const xkb_keysym_t *raw_keysyms; | 205 | const xkb_keysym_t *raw_keysyms; |
206 | uint32_t raw_modifiers; | ||
375 | size_t raw_keysyms_len = | 207 | size_t raw_keysyms_len = |
376 | keyboard_keysyms_raw(keyboard, keycode, &raw_keysyms, &keyboard->modifiers_raw); | 208 | keyboard_keysyms_raw(keyboard, keycode, &raw_keysyms, &raw_modifiers); |
377 | pressed_keysyms_update(keyboard->pressed_keysyms_raw, raw_keysyms, | 209 | |
378 | raw_keysyms_len, event->state); | 210 | struct wlr_input_device *device = |
379 | if (!handled && event->state == WLR_KEY_PRESSED) { | 211 | keyboard->seat_device->input_device->wlr_device; |
380 | handled = keyboard_execute_bindsym(keyboard, | 212 | uint32_t code_modifiers = wlr_keyboard_get_modifiers(device->keyboard); |
381 | keyboard->pressed_keysyms_raw, keyboard->modifiers_raw, | 213 | |
382 | event->state, input_inhibited); | 214 | bool last_key_was_a_modifier = code_modifiers != keyboard->last_modifiers; |
215 | keyboard->last_modifiers = code_modifiers; | ||
216 | |||
217 | // Update shortcut models | ||
218 | update_shortcut_model(&keyboard->state_keycodes, event, | ||
219 | (uint32_t)keycode, last_key_was_a_modifier); | ||
220 | for (size_t i=0;i<translated_keysyms_len;i++) { | ||
221 | update_shortcut_model(&keyboard->state_keysyms_translated, | ||
222 | event, (uint32_t)translated_keysyms[i], | ||
223 | last_key_was_a_modifier); | ||
224 | } | ||
225 | for (size_t i=0;i<raw_keysyms_len;i++) { | ||
226 | update_shortcut_model(&keyboard->state_keysyms_raw, | ||
227 | event, (uint32_t)raw_keysyms[i], | ||
228 | last_key_was_a_modifier); | ||
229 | } | ||
230 | |||
231 | // identify which binding should be executed. | ||
232 | struct sway_binding *binding = | ||
233 | check_shortcut_model(&keyboard->state_keycodes, | ||
234 | config->current_mode->keycode_bindings, | ||
235 | code_modifiers, input_inhibited); | ||
236 | for (size_t i=0;i<translated_keysyms_len;i++) { | ||
237 | struct sway_binding *translated_binding = | ||
238 | check_shortcut_model(&keyboard->state_keysyms_translated, | ||
239 | config->current_mode->keysym_bindings, | ||
240 | translated_modifiers, input_inhibited); | ||
241 | if (translated_binding && !binding) { | ||
242 | binding = translated_binding; | ||
243 | } else if (binding && translated_binding && binding != translated_binding) { | ||
244 | wlr_log(L_DEBUG, "encountered duplicate bindings %d and %d", | ||
245 | binding->order, translated_binding->order); | ||
246 | } | ||
247 | } | ||
248 | for (size_t i=0;i<raw_keysyms_len;i++) { | ||
249 | struct sway_binding *raw_binding = | ||
250 | check_shortcut_model(&keyboard->state_keysyms_raw, | ||
251 | config->current_mode->keysym_bindings, | ||
252 | raw_modifiers, input_inhibited); | ||
253 | if (raw_binding && !binding) { | ||
254 | binding = raw_binding; | ||
255 | } else if (binding && raw_binding && binding != raw_binding) { | ||
256 | wlr_log(L_DEBUG, "encountered duplicate bindings %d and %d", | ||
257 | binding->order, raw_binding->order); | ||
258 | } | ||
259 | } | ||
260 | |||
261 | bool handled = false; | ||
262 | |||
263 | // Execute the identified binding if need be. | ||
264 | if (keyboard->held_binding && binding != keyboard->held_binding && | ||
265 | event->state == WLR_KEY_RELEASED) { | ||
266 | keyboard_execute_command(keyboard, keyboard->held_binding); | ||
267 | handled = true; | ||
268 | } | ||
269 | if (binding != keyboard->held_binding) { | ||
270 | keyboard->held_binding = NULL; | ||
271 | } | ||
272 | if (binding && event->state == WLR_KEY_PRESSED) { | ||
273 | if (binding->release) { | ||
274 | keyboard->held_binding = binding; | ||
275 | } else { | ||
276 | keyboard_execute_command(keyboard, binding); | ||
277 | handled = true; | ||
278 | } | ||
383 | } | 279 | } |
384 | 280 | ||
385 | // Compositor bindings | 281 | // Compositor bindings |
386 | if (!handled && event->state == WLR_KEY_PRESSED) { | 282 | if (!handled && event->state == WLR_KEY_PRESSED) { |
387 | handled = | 283 | handled = keyboard_execute_compositor_binding( |
388 | keyboard_execute_compositor_binding(keyboard, | 284 | keyboard, translated_keysyms, translated_modifiers, |
389 | keyboard->pressed_keysyms_translated, | ||
390 | keyboard->modifiers_translated, | ||
391 | translated_keysyms_len); | 285 | translated_keysyms_len); |
392 | } | 286 | } |
393 | if (!handled && event->state == WLR_KEY_PRESSED) { | 287 | if (!handled && event->state == WLR_KEY_PRESSED) { |
394 | handled = | 288 | handled = keyboard_execute_compositor_binding( |
395 | keyboard_execute_compositor_binding(keyboard, | 289 | keyboard, raw_keysyms, raw_modifiers, |
396 | keyboard->pressed_keysyms_raw, keyboard->modifiers_raw, | ||
397 | raw_keysyms_len); | 290 | raw_keysyms_len); |
398 | } | 291 | } |
399 | 292 | ||
@@ -429,6 +322,10 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, | |||
429 | wl_list_init(&keyboard->keyboard_key.link); | 322 | wl_list_init(&keyboard->keyboard_key.link); |
430 | wl_list_init(&keyboard->keyboard_modifiers.link); | 323 | wl_list_init(&keyboard->keyboard_modifiers.link); |
431 | 324 | ||
325 | keyboard->state_keycodes.last_key_index = -1; | ||
326 | keyboard->state_keysyms_raw.last_key_index = -1; | ||
327 | keyboard->state_keysyms_translated.last_key_index = -1; | ||
328 | |||
432 | return keyboard; | 329 | return keyboard; |
433 | } | 330 | } |
434 | 331 | ||