diff options
Diffstat (limited to 'sway/input/keyboard.c')
-rw-r--r-- | sway/input/keyboard.c | 171 |
1 files changed, 126 insertions, 45 deletions
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index ba0e020c..541fc90d 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -124,7 +124,7 @@ static void state_add_key(struct sway_shortcut_state *state, | |||
124 | * Update the shortcut model state in response to new input | 124 | * Update the shortcut model state in response to new input |
125 | */ | 125 | */ |
126 | static bool update_shortcut_state(struct sway_shortcut_state *state, | 126 | static bool update_shortcut_state(struct sway_shortcut_state *state, |
127 | struct wlr_event_keyboard_key *event, uint32_t new_key, | 127 | uint32_t keycode, enum wlr_key_state keystate, uint32_t new_key, |
128 | uint32_t raw_modifiers) { | 128 | uint32_t raw_modifiers) { |
129 | bool last_key_was_a_modifier = raw_modifiers != state->last_raw_modifiers; | 129 | bool last_key_was_a_modifier = raw_modifiers != state->last_raw_modifiers; |
130 | state->last_raw_modifiers = raw_modifiers; | 130 | state->last_raw_modifiers = raw_modifiers; |
@@ -134,12 +134,12 @@ static bool update_shortcut_state(struct sway_shortcut_state *state, | |||
134 | state_erase_key(state, state->last_keycode); | 134 | state_erase_key(state, state->last_keycode); |
135 | } | 135 | } |
136 | 136 | ||
137 | if (event->state == WLR_KEY_PRESSED) { | 137 | if (keystate == WLR_KEY_PRESSED) { |
138 | // Add current key to set; there may be duplicates | 138 | // Add current key to set; there may be duplicates |
139 | state_add_key(state, event->keycode, new_key); | 139 | state_add_key(state, keycode, new_key); |
140 | state->last_keycode = event->keycode; | 140 | state->last_keycode = keycode; |
141 | } else { | 141 | } else { |
142 | return state_erase_key(state, event->keycode); | 142 | return state_erase_key(state, keycode); |
143 | } | 143 | } |
144 | 144 | ||
145 | return false; | 145 | return false; |
@@ -334,9 +334,53 @@ void sway_keyboard_disarm_key_repeat(struct sway_keyboard *keyboard) { | |||
334 | } | 334 | } |
335 | } | 335 | } |
336 | 336 | ||
337 | struct key_info { | ||
338 | uint32_t keycode; | ||
339 | uint32_t code_modifiers; | ||
340 | |||
341 | const xkb_keysym_t *raw_keysyms; | ||
342 | uint32_t raw_modifiers; | ||
343 | size_t raw_keysyms_len; | ||
344 | |||
345 | const xkb_keysym_t *translated_keysyms; | ||
346 | uint32_t translated_modifiers; | ||
347 | size_t translated_keysyms_len; | ||
348 | }; | ||
349 | |||
350 | static void update_keyboard_state(struct sway_keyboard *keyboard, | ||
351 | uint32_t raw_keycode, enum wlr_key_state keystate, | ||
352 | struct key_info *keyinfo) { | ||
353 | // Identify new keycode, raw keysym(s), and translated keysym(s) | ||
354 | keyinfo->keycode = raw_keycode + 8; | ||
355 | |||
356 | keyinfo->raw_keysyms_len = keyboard_keysyms_raw(keyboard, keyinfo->keycode, | ||
357 | &keyinfo->raw_keysyms, &keyinfo->raw_modifiers); | ||
358 | |||
359 | keyinfo->translated_keysyms_len = keyboard_keysyms_translated(keyboard, | ||
360 | keyinfo->keycode, &keyinfo->translated_keysyms, | ||
361 | &keyinfo->translated_modifiers); | ||
362 | |||
363 | keyinfo->code_modifiers = wlr_keyboard_get_modifiers( | ||
364 | keyboard->seat_device->input_device->wlr_device->keyboard); | ||
365 | |||
366 | // Update shortcut model keyinfo | ||
367 | update_shortcut_state(&keyboard->state_keycodes, raw_keycode, keystate, | ||
368 | keyinfo->keycode, keyinfo->code_modifiers); | ||
369 | for (size_t i = 0; i < keyinfo->raw_keysyms_len; ++i) { | ||
370 | update_shortcut_state(&keyboard->state_keysyms_raw, | ||
371 | raw_keycode, keystate, keyinfo->raw_keysyms[i], | ||
372 | keyinfo->code_modifiers); | ||
373 | } | ||
374 | for (size_t i = 0; i < keyinfo->translated_keysyms_len; ++i) { | ||
375 | update_shortcut_state(&keyboard->state_keysyms_translated, | ||
376 | raw_keycode, keystate, keyinfo->translated_keysyms[i], | ||
377 | keyinfo->code_modifiers); | ||
378 | } | ||
379 | } | ||
380 | |||
337 | static void handle_key_event(struct sway_keyboard *keyboard, | 381 | static void handle_key_event(struct sway_keyboard *keyboard, |
338 | struct wlr_event_keyboard_key *event) { | 382 | struct wlr_event_keyboard_key *event) { |
339 | struct sway_seat* seat = keyboard->seat_device->sway_seat; | 383 | struct sway_seat *seat = keyboard->seat_device->sway_seat; |
340 | struct wlr_seat *wlr_seat = seat->wlr_seat; | 384 | struct wlr_seat *wlr_seat = seat->wlr_seat; |
341 | struct wlr_input_device *wlr_device = | 385 | struct wlr_input_device *wlr_device = |
342 | keyboard->seat_device->input_device->wlr_device; | 386 | keyboard->seat_device->input_device->wlr_device; |
@@ -349,51 +393,25 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
349 | bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active; | 393 | bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active; |
350 | 394 | ||
351 | // Identify new keycode, raw keysym(s), and translated keysym(s) | 395 | // Identify new keycode, raw keysym(s), and translated keysym(s) |
352 | xkb_keycode_t keycode = event->keycode + 8; | 396 | struct key_info keyinfo; |
353 | 397 | update_keyboard_state(keyboard, event->keycode, event->state, &keyinfo); | |
354 | const xkb_keysym_t *raw_keysyms; | ||
355 | uint32_t raw_modifiers; | ||
356 | size_t raw_keysyms_len = | ||
357 | keyboard_keysyms_raw(keyboard, keycode, &raw_keysyms, &raw_modifiers); | ||
358 | |||
359 | const xkb_keysym_t *translated_keysyms; | ||
360 | uint32_t translated_modifiers; | ||
361 | size_t translated_keysyms_len = | ||
362 | keyboard_keysyms_translated(keyboard, keycode, &translated_keysyms, | ||
363 | &translated_modifiers); | ||
364 | |||
365 | uint32_t code_modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard); | ||
366 | |||
367 | // Update shortcut model state | ||
368 | update_shortcut_state(&keyboard->state_keycodes, event, | ||
369 | (uint32_t)keycode, code_modifiers); | ||
370 | for (size_t i = 0; i < raw_keysyms_len; ++i) { | ||
371 | update_shortcut_state(&keyboard->state_keysyms_raw, | ||
372 | event, (uint32_t)raw_keysyms[i], | ||
373 | code_modifiers); | ||
374 | } | ||
375 | for (size_t i = 0; i < translated_keysyms_len; ++i) { | ||
376 | update_shortcut_state(&keyboard->state_keysyms_translated, | ||
377 | event, (uint32_t)translated_keysyms[i], | ||
378 | code_modifiers); | ||
379 | } | ||
380 | 398 | ||
381 | bool handled = false; | 399 | bool handled = false; |
382 | // Identify active release binding | 400 | // Identify active release binding |
383 | struct sway_binding *binding_released = NULL; | 401 | struct sway_binding *binding_released = NULL; |
384 | get_active_binding(&keyboard->state_keycodes, | 402 | get_active_binding(&keyboard->state_keycodes, |
385 | config->current_mode->keycode_bindings, &binding_released, | 403 | config->current_mode->keycode_bindings, &binding_released, |
386 | code_modifiers, true, input_inhibited, | 404 | keyinfo.code_modifiers, true, input_inhibited, |
387 | shortcuts_inhibited, device_identifier, | 405 | shortcuts_inhibited, device_identifier, |
388 | exact_identifier, keyboard->effective_layout); | 406 | exact_identifier, keyboard->effective_layout); |
389 | get_active_binding(&keyboard->state_keysyms_raw, | 407 | get_active_binding(&keyboard->state_keysyms_raw, |
390 | config->current_mode->keysym_bindings, &binding_released, | 408 | config->current_mode->keysym_bindings, &binding_released, |
391 | raw_modifiers, true, input_inhibited, | 409 | keyinfo.raw_modifiers, true, input_inhibited, |
392 | shortcuts_inhibited, device_identifier, | 410 | shortcuts_inhibited, device_identifier, |
393 | exact_identifier, keyboard->effective_layout); | 411 | exact_identifier, keyboard->effective_layout); |
394 | get_active_binding(&keyboard->state_keysyms_translated, | 412 | get_active_binding(&keyboard->state_keysyms_translated, |
395 | config->current_mode->keysym_bindings, &binding_released, | 413 | config->current_mode->keysym_bindings, &binding_released, |
396 | translated_modifiers, true, input_inhibited, | 414 | keyinfo.translated_modifiers, true, input_inhibited, |
397 | shortcuts_inhibited, device_identifier, | 415 | shortcuts_inhibited, device_identifier, |
398 | exact_identifier, keyboard->effective_layout); | 416 | exact_identifier, keyboard->effective_layout); |
399 | 417 | ||
@@ -415,17 +433,17 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
415 | if (event->state == WLR_KEY_PRESSED) { | 433 | if (event->state == WLR_KEY_PRESSED) { |
416 | get_active_binding(&keyboard->state_keycodes, | 434 | get_active_binding(&keyboard->state_keycodes, |
417 | config->current_mode->keycode_bindings, &binding, | 435 | config->current_mode->keycode_bindings, &binding, |
418 | code_modifiers, false, input_inhibited, | 436 | keyinfo.code_modifiers, false, input_inhibited, |
419 | shortcuts_inhibited, device_identifier, | 437 | shortcuts_inhibited, device_identifier, |
420 | exact_identifier, keyboard->effective_layout); | 438 | exact_identifier, keyboard->effective_layout); |
421 | get_active_binding(&keyboard->state_keysyms_raw, | 439 | get_active_binding(&keyboard->state_keysyms_raw, |
422 | config->current_mode->keysym_bindings, &binding, | 440 | config->current_mode->keysym_bindings, &binding, |
423 | raw_modifiers, false, input_inhibited, | 441 | keyinfo.raw_modifiers, false, input_inhibited, |
424 | shortcuts_inhibited, device_identifier, | 442 | shortcuts_inhibited, device_identifier, |
425 | exact_identifier, keyboard->effective_layout); | 443 | exact_identifier, keyboard->effective_layout); |
426 | get_active_binding(&keyboard->state_keysyms_translated, | 444 | get_active_binding(&keyboard->state_keysyms_translated, |
427 | config->current_mode->keysym_bindings, &binding, | 445 | config->current_mode->keysym_bindings, &binding, |
428 | translated_modifiers, false, input_inhibited, | 446 | keyinfo.translated_modifiers, false, input_inhibited, |
429 | shortcuts_inhibited, device_identifier, | 447 | shortcuts_inhibited, device_identifier, |
430 | exact_identifier, keyboard->effective_layout); | 448 | exact_identifier, keyboard->effective_layout); |
431 | } | 449 | } |
@@ -457,18 +475,19 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
457 | // Compositor bindings | 475 | // Compositor bindings |
458 | if (!handled && event->state == WLR_KEY_PRESSED) { | 476 | if (!handled && event->state == WLR_KEY_PRESSED) { |
459 | handled = keyboard_execute_compositor_binding( | 477 | handled = keyboard_execute_compositor_binding( |
460 | keyboard, translated_keysyms, translated_modifiers, | 478 | keyboard, keyinfo.translated_keysyms, |
461 | translated_keysyms_len); | 479 | keyinfo.translated_modifiers, keyinfo.translated_keysyms_len); |
462 | } | 480 | } |
463 | if (!handled && event->state == WLR_KEY_PRESSED) { | 481 | if (!handled && event->state == WLR_KEY_PRESSED) { |
464 | handled = keyboard_execute_compositor_binding( | 482 | handled = keyboard_execute_compositor_binding( |
465 | keyboard, raw_keysyms, raw_modifiers, | 483 | keyboard, keyinfo.raw_keysyms, keyinfo.raw_modifiers, |
466 | raw_keysyms_len); | 484 | keyinfo.raw_keysyms_len); |
467 | } | 485 | } |
468 | 486 | ||
469 | if (!handled || event->state == WLR_KEY_RELEASED) { | 487 | if (!handled || event->state == WLR_KEY_RELEASED) { |
470 | bool pressed_sent = update_shortcut_state( | 488 | bool pressed_sent = update_shortcut_state( |
471 | &keyboard->state_pressed_sent, event, (uint32_t)keycode, 0); | 489 | &keyboard->state_pressed_sent, event->keycode, event->state, |
490 | keyinfo.keycode, 0); | ||
472 | if (pressed_sent || event->state == WLR_KEY_PRESSED) { | 491 | if (pressed_sent || event->state == WLR_KEY_PRESSED) { |
473 | wlr_seat_set_keyboard(wlr_seat, wlr_device); | 492 | wlr_seat_set_keyboard(wlr_seat, wlr_device); |
474 | wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, | 493 | wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, |
@@ -494,6 +513,60 @@ static void handle_keyboard_group_key(struct wl_listener *listener, | |||
494 | handle_key_event(sway_group->seat_device->keyboard, data); | 513 | handle_key_event(sway_group->seat_device->keyboard, data); |
495 | } | 514 | } |
496 | 515 | ||
516 | static void handle_keyboard_group_enter(struct wl_listener *listener, | ||
517 | void *data) { | ||
518 | struct sway_keyboard_group *sway_group = | ||
519 | wl_container_of(listener, sway_group, enter); | ||
520 | struct sway_keyboard *keyboard = sway_group->seat_device->keyboard; | ||
521 | struct wl_array *keycodes = data; | ||
522 | |||
523 | uint32_t *keycode; | ||
524 | wl_array_for_each(keycode, keycodes) { | ||
525 | struct key_info keyinfo; | ||
526 | update_keyboard_state(keyboard, *keycode, WLR_KEY_PRESSED, &keyinfo); | ||
527 | } | ||
528 | } | ||
529 | |||
530 | static void handle_keyboard_group_leave(struct wl_listener *listener, | ||
531 | void *data) { | ||
532 | struct sway_keyboard_group *sway_group = | ||
533 | wl_container_of(listener, sway_group, leave); | ||
534 | struct sway_keyboard *keyboard = sway_group->seat_device->keyboard; | ||
535 | struct wl_array *keycodes = data; | ||
536 | |||
537 | bool pressed_sent = false; | ||
538 | |||
539 | uint32_t *keycode; | ||
540 | wl_array_for_each(keycode, keycodes) { | ||
541 | struct key_info keyinfo; | ||
542 | update_keyboard_state(keyboard, *keycode, WLR_KEY_RELEASED, &keyinfo); | ||
543 | |||
544 | pressed_sent |= update_shortcut_state(&keyboard->state_pressed_sent, | ||
545 | *keycode, WLR_KEY_RELEASED, keyinfo.keycode, 0); | ||
546 | } | ||
547 | |||
548 | if (!pressed_sent) { | ||
549 | return; | ||
550 | } | ||
551 | |||
552 | // Refocus the focused node, layer surface, or unmanaged surface so that | ||
553 | // it picks up the current keyboard state. | ||
554 | struct sway_seat *seat = keyboard->seat_device->sway_seat; | ||
555 | struct sway_node *focus = seat_get_focus(seat); | ||
556 | if (focus) { | ||
557 | seat_set_focus(seat, NULL); | ||
558 | seat_set_focus(seat, focus); | ||
559 | } else if (seat->focused_layer) { | ||
560 | struct wlr_layer_surface_v1 *layer = seat->focused_layer; | ||
561 | seat_set_focus_layer(seat, NULL); | ||
562 | seat_set_focus_layer(seat, layer); | ||
563 | } else { | ||
564 | struct wlr_surface *unmanaged = seat->wlr_seat->keyboard_state.focused_surface; | ||
565 | seat_set_focus_surface(seat, NULL, false); | ||
566 | seat_set_focus_surface(seat, unmanaged, false); | ||
567 | } | ||
568 | } | ||
569 | |||
497 | static int handle_keyboard_repeat(void *data) { | 570 | static int handle_keyboard_repeat(void *data) { |
498 | struct sway_keyboard *keyboard = (struct sway_keyboard *)data; | 571 | struct sway_keyboard *keyboard = (struct sway_keyboard *)data; |
499 | struct wlr_keyboard *wlr_device = | 572 | struct wlr_keyboard *wlr_device = |
@@ -702,6 +775,8 @@ static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) { | |||
702 | wl_list_remove(&sway_group->link); | 775 | wl_list_remove(&sway_group->link); |
703 | wl_list_remove(&sway_group->keyboard_key.link); | 776 | wl_list_remove(&sway_group->keyboard_key.link); |
704 | wl_list_remove(&sway_group->keyboard_modifiers.link); | 777 | wl_list_remove(&sway_group->keyboard_modifiers.link); |
778 | wl_list_remove(&sway_group->enter.link); | ||
779 | wl_list_remove(&sway_group->leave.link); | ||
705 | sway_keyboard_destroy(sway_group->seat_device->keyboard); | 780 | sway_keyboard_destroy(sway_group->seat_device->keyboard); |
706 | free(sway_group->seat_device->input_device); | 781 | free(sway_group->seat_device->input_device); |
707 | free(sway_group->seat_device); | 782 | free(sway_group->seat_device); |
@@ -835,6 +910,12 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) { | |||
835 | wl_signal_add(&sway_group->wlr_group->keyboard.events.modifiers, | 910 | wl_signal_add(&sway_group->wlr_group->keyboard.events.modifiers, |
836 | &sway_group->keyboard_modifiers); | 911 | &sway_group->keyboard_modifiers); |
837 | sway_group->keyboard_modifiers.notify = handle_keyboard_group_modifiers; | 912 | sway_group->keyboard_modifiers.notify = handle_keyboard_group_modifiers; |
913 | |||
914 | wl_signal_add(&sway_group->wlr_group->events.enter, &sway_group->enter); | ||
915 | sway_group->enter.notify = handle_keyboard_group_enter; | ||
916 | |||
917 | wl_signal_add(&sway_group->wlr_group->events.leave, &sway_group->leave); | ||
918 | sway_group->leave.notify = handle_keyboard_group_leave; | ||
838 | return; | 919 | return; |
839 | 920 | ||
840 | cleanup: | 921 | cleanup: |