aboutsummaryrefslogtreecommitdiffstats
path: root/sway/input/keyboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/input/keyboard.c')
-rw-r--r--sway/input/keyboard.c77
1 files changed, 65 insertions, 12 deletions
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c
index ce259eb2..f258ac7d 100644
--- a/sway/input/keyboard.c
+++ b/sway/input/keyboard.c
@@ -9,7 +9,6 @@
9#include <wlr/types/wlr_keyboard_group.h> 9#include <wlr/types/wlr_keyboard_group.h>
10#include <xkbcommon/xkbcommon-names.h> 10#include <xkbcommon/xkbcommon-names.h>
11#include "sway/commands.h" 11#include "sway/commands.h"
12#include "sway/desktop/transaction.h"
13#include "sway/input/input-manager.h" 12#include "sway/input/input-manager.h"
14#include "sway/input/keyboard.h" 13#include "sway/input/keyboard.h"
15#include "sway/input/seat.h" 14#include "sway/input/seat.h"
@@ -379,6 +378,28 @@ static void update_keyboard_state(struct sway_keyboard *keyboard,
379 } 378 }
380} 379}
381 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 */
389static 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
382static void handle_key_event(struct sway_keyboard *keyboard, 403static void handle_key_event(struct sway_keyboard *keyboard,
383 struct wlr_event_keyboard_key *event) { 404 struct wlr_event_keyboard_key *event) {
384 struct sway_seat *seat = keyboard->seat_device->sway_seat; 405 struct sway_seat *seat = keyboard->seat_device->sway_seat;
@@ -489,18 +510,42 @@ static void handle_key_event(struct sway_keyboard *keyboard,
489 keyinfo.raw_keysyms_len); 510 keyinfo.raw_keysyms_len);
490 } 511 }
491 512
492 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.
493 bool pressed_sent = update_shortcut_state( 516 bool pressed_sent = update_shortcut_state(
494 &keyboard->state_pressed_sent, event->keycode, event->state, 517 &keyboard->state_pressed_sent, event->keycode,
495 keyinfo.keycode, 0); 518 event->state, keyinfo.keycode, 0);
496 if (pressed_sent || event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { 519 if (pressed_sent) {
497 wlr_seat_set_keyboard(wlr_seat, wlr_device); 520 wlr_seat_set_keyboard(wlr_seat, wlr_device);
498 wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, 521 wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,
499 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;
500 } 536 }
501 } 537 }
502 538
503 transaction_commit_dirty(); 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 }
504 549
505 free(device_identifier); 550 free(device_identifier);
506} 551}
@@ -587,7 +632,6 @@ static int handle_keyboard_repeat(void *data) {
587 632
588 seat_execute_command(keyboard->seat_device->sway_seat, 633 seat_execute_command(keyboard->seat_device->sway_seat,
589 keyboard->repeat_binding); 634 keyboard->repeat_binding);
590 transaction_commit_dirty();
591 } 635 }
592 return 0; 636 return 0;
593} 637}
@@ -617,10 +661,19 @@ static void handle_modifier_event(struct sway_keyboard *keyboard) {
617 struct wlr_input_device *wlr_device = 661 struct wlr_input_device *wlr_device =
618 keyboard->seat_device->input_device->wlr_device; 662 keyboard->seat_device->input_device->wlr_device;
619 if (!wlr_device->keyboard->group) { 663 if (!wlr_device->keyboard->group) {
620 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);
621 wlr_seat_set_keyboard(wlr_seat, wlr_device); 665
622 wlr_seat_keyboard_notify_modifiers(wlr_seat, 666 if (kb_grab) {
623 &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 }
624 677
625 uint32_t modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard); 678 uint32_t modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard);
626 determine_bar_visibility(modifiers); 679 determine_bar_visibility(modifiers);