diff options
Diffstat (limited to 'sway/input/keyboard.c')
-rw-r--r-- | sway/input/keyboard.c | 74 |
1 files changed, 65 insertions, 9 deletions
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 95e53934..f258ac7d 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -378,6 +378,28 @@ static void update_keyboard_state(struct sway_keyboard *keyboard, | |||
378 | } | 378 | } |
379 | } | 379 | } |
380 | 380 | ||
381 | /** | ||
382 | * Get keyboard grab of the seat from sway_keyboard if we should forward events | ||
383 | * to it. | ||
384 | * | ||
385 | * Returns NULL if the keyboard is not grabbed by an input method, | ||
386 | * or if event is from virtual keyboard of the same client as grab. | ||
387 | * TODO: see swaywm/wlroots#2322 | ||
388 | */ | ||
389 | static struct wlr_input_method_keyboard_grab_v2 *keyboard_get_im_grab( | ||
390 | struct sway_keyboard *keyboard) { | ||
391 | struct wlr_input_method_v2 *input_method = keyboard->seat_device-> | ||
392 | sway_seat->im_relay.input_method; | ||
393 | struct wlr_virtual_keyboard_v1 *virtual_keyboard = | ||
394 | wlr_input_device_get_virtual_keyboard(keyboard->seat_device->input_device->wlr_device); | ||
395 | if (!input_method || !input_method->keyboard_grab || (virtual_keyboard && | ||
396 | wl_resource_get_client(virtual_keyboard->resource) == | ||
397 | wl_resource_get_client(input_method->keyboard_grab->resource))) { | ||
398 | return NULL; | ||
399 | } | ||
400 | return input_method->keyboard_grab; | ||
401 | } | ||
402 | |||
381 | static void handle_key_event(struct sway_keyboard *keyboard, | 403 | static void handle_key_event(struct sway_keyboard *keyboard, |
382 | struct wlr_event_keyboard_key *event) { | 404 | struct wlr_event_keyboard_key *event) { |
383 | struct sway_seat *seat = keyboard->seat_device->sway_seat; | 405 | struct sway_seat *seat = keyboard->seat_device->sway_seat; |
@@ -488,17 +510,42 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
488 | keyinfo.raw_keysyms_len); | 510 | keyinfo.raw_keysyms_len); |
489 | } | 511 | } |
490 | 512 | ||
491 | if (!handled || event->state == WL_KEYBOARD_KEY_STATE_RELEASED) { | 513 | if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED) { |
514 | // If the pressed event was sent to a client, also send the released | ||
515 | // event. In particular, don't send the released event to the IM grab. | ||
492 | bool pressed_sent = update_shortcut_state( | 516 | bool pressed_sent = update_shortcut_state( |
493 | &keyboard->state_pressed_sent, event->keycode, event->state, | 517 | &keyboard->state_pressed_sent, event->keycode, |
494 | keyinfo.keycode, 0); | 518 | event->state, keyinfo.keycode, 0); |
495 | if (pressed_sent || event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { | 519 | if (pressed_sent) { |
496 | wlr_seat_set_keyboard(wlr_seat, wlr_device); | 520 | wlr_seat_set_keyboard(wlr_seat, wlr_device); |
497 | wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, | 521 | wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, |
498 | event->keycode, event->state); | 522 | event->keycode, event->state); |
523 | handled = true; | ||
524 | } | ||
525 | } | ||
526 | |||
527 | if (!handled) { | ||
528 | struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard); | ||
529 | |||
530 | if (kb_grab) { | ||
531 | wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, | ||
532 | wlr_device->keyboard); | ||
533 | wlr_input_method_keyboard_grab_v2_send_key(kb_grab, | ||
534 | event->time_msec, event->keycode, event->state); | ||
535 | handled = true; | ||
499 | } | 536 | } |
500 | } | 537 | } |
501 | 538 | ||
539 | if (!handled && event->state != WL_KEYBOARD_KEY_STATE_RELEASED) { | ||
540 | // If a released event failed pressed sent test, and not in sent to | ||
541 | // keyboard grab, it is still not handled. Don't handle released here. | ||
542 | update_shortcut_state( | ||
543 | &keyboard->state_pressed_sent, event->keycode, event->state, | ||
544 | keyinfo.keycode, 0); | ||
545 | wlr_seat_set_keyboard(wlr_seat, wlr_device); | ||
546 | wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, | ||
547 | event->keycode, event->state); | ||
548 | } | ||
502 | 549 | ||
503 | free(device_identifier); | 550 | free(device_identifier); |
504 | } | 551 | } |
@@ -614,10 +661,19 @@ static void handle_modifier_event(struct sway_keyboard *keyboard) { | |||
614 | struct wlr_input_device *wlr_device = | 661 | struct wlr_input_device *wlr_device = |
615 | keyboard->seat_device->input_device->wlr_device; | 662 | keyboard->seat_device->input_device->wlr_device; |
616 | if (!wlr_device->keyboard->group) { | 663 | if (!wlr_device->keyboard->group) { |
617 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; | 664 | struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard); |
618 | wlr_seat_set_keyboard(wlr_seat, wlr_device); | 665 | |
619 | wlr_seat_keyboard_notify_modifiers(wlr_seat, | 666 | if (kb_grab) { |
620 | &wlr_device->keyboard->modifiers); | 667 | wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, |
668 | wlr_device->keyboard); | ||
669 | wlr_input_method_keyboard_grab_v2_send_modifiers(kb_grab, | ||
670 | &wlr_device->keyboard->modifiers); | ||
671 | } else { | ||
672 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; | ||
673 | wlr_seat_set_keyboard(wlr_seat, wlr_device); | ||
674 | wlr_seat_keyboard_notify_modifiers(wlr_seat, | ||
675 | &wlr_device->keyboard->modifiers); | ||
676 | } | ||
621 | 677 | ||
622 | uint32_t modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard); | 678 | uint32_t modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard); |
623 | determine_bar_visibility(modifiers); | 679 | determine_bar_visibility(modifiers); |