aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar xdavidwu <xdavidwuph@gmail.com>2021-03-12 19:18:08 +0800
committerLibravatar GitHub <noreply@github.com>2021-03-12 12:18:08 +0100
commite5913f81064d4c5b89cdab0cd75d2b5ff5a47c48 (patch)
treeb6ae5729ed88f6c9730a15d633cf833b3f343b93
parentxwayland: simplify override-redirect focus restoration (diff)
downloadsway-e5913f81064d4c5b89cdab0cd75d2b5ff5a47c48.tar.gz
sway-e5913f81064d4c5b89cdab0cd75d2b5ff5a47c48.tar.zst
sway-e5913f81064d4c5b89cdab0cd75d2b5ff5a47c48.zip
Implement input method keyboard grab
-rw-r--r--include/sway/input/text_input.h3
-rw-r--r--sway/input/keyboard.c74
-rw-r--r--sway/input/text_input.c34
3 files changed, 102 insertions, 9 deletions
diff --git a/include/sway/input/text_input.h b/include/sway/input/text_input.h
index 6cf9bdb3..37744266 100644
--- a/include/sway/input/text_input.h
+++ b/include/sway/input/text_input.h
@@ -28,7 +28,10 @@ struct sway_input_method_relay {
28 28
29 struct wl_listener input_method_new; 29 struct wl_listener input_method_new;
30 struct wl_listener input_method_commit; 30 struct wl_listener input_method_commit;
31 struct wl_listener input_method_grab_keyboard;
31 struct wl_listener input_method_destroy; 32 struct wl_listener input_method_destroy;
33
34 struct wl_listener input_method_keyboard_grab_destroy;
32}; 35};
33 36
34struct sway_text_input { 37struct sway_text_input {
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 */
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
381static void handle_key_event(struct sway_keyboard *keyboard, 403static 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);
diff --git a/sway/input/text_input.c b/sway/input/text_input.c
index 2a8f6222..b8c19c17 100644
--- a/sway/input/text_input.c
+++ b/sway/input/text_input.c
@@ -55,6 +55,37 @@ static void handle_im_commit(struct wl_listener *listener, void *data) {
55 wlr_text_input_v3_send_done(text_input->input); 55 wlr_text_input_v3_send_done(text_input->input);
56} 56}
57 57
58static void handle_im_keyboard_grab_destroy(struct wl_listener *listener, void *data) {
59 struct sway_input_method_relay *relay = wl_container_of(listener, relay,
60 input_method_keyboard_grab_destroy);
61 struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
62 wl_list_remove(&relay->input_method_keyboard_grab_destroy.link);
63
64 if (keyboard_grab->keyboard) {
65 // send modifier state to original client
66 wlr_seat_keyboard_notify_modifiers(keyboard_grab->input_method->seat,
67 &keyboard_grab->keyboard->modifiers);
68 }
69}
70
71static void handle_im_grab_keyboard(struct wl_listener *listener, void *data) {
72 struct sway_input_method_relay *relay = wl_container_of(listener, relay,
73 input_method_grab_keyboard);
74 struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
75
76 // send modifier state to grab
77 struct wlr_keyboard *active_keyboard = wlr_seat_get_keyboard(relay->seat->wlr_seat);
78 wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab,
79 active_keyboard);
80 wlr_input_method_keyboard_grab_v2_send_modifiers(keyboard_grab,
81 &active_keyboard->modifiers);
82
83 wl_signal_add(&keyboard_grab->events.destroy,
84 &relay->input_method_keyboard_grab_destroy);
85 relay->input_method_keyboard_grab_destroy.notify =
86 handle_im_keyboard_grab_destroy;
87}
88
58static void text_input_set_pending_focused_surface( 89static void text_input_set_pending_focused_surface(
59 struct sway_text_input *text_input, struct wlr_surface *surface) { 90 struct sway_text_input *text_input, struct wlr_surface *surface) {
60 wl_list_remove(&text_input->pending_focused_surface_destroy.link); 91 wl_list_remove(&text_input->pending_focused_surface_destroy.link);
@@ -245,6 +276,9 @@ static void relay_handle_input_method(struct wl_listener *listener,
245 wl_signal_add(&relay->input_method->events.commit, 276 wl_signal_add(&relay->input_method->events.commit,
246 &relay->input_method_commit); 277 &relay->input_method_commit);
247 relay->input_method_commit.notify = handle_im_commit; 278 relay->input_method_commit.notify = handle_im_commit;
279 wl_signal_add(&relay->input_method->events.grab_keyboard,
280 &relay->input_method_grab_keyboard);
281 relay->input_method_grab_keyboard.notify = handle_im_grab_keyboard;
248 wl_signal_add(&relay->input_method->events.destroy, 282 wl_signal_add(&relay->input_method->events.destroy,
249 &relay->input_method_destroy); 283 &relay->input_method_destroy);
250 relay->input_method_destroy.notify = handle_im_destroy; 284 relay->input_method_destroy.notify = handle_im_destroy;