diff options
Diffstat (limited to 'sway/input/keyboard.c')
-rw-r--r-- | sway/input/keyboard.c | 250 |
1 files changed, 136 insertions, 114 deletions
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index ce259eb2..b97f0152 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -1,15 +1,13 @@ | |||
1 | #include <assert.h> | 1 | #include <assert.h> |
2 | #include <limits.h> | 2 | #include <limits.h> |
3 | #include <strings.h> | 3 | #include <strings.h> |
4 | #include <wlr/config.h> | ||
4 | #include <wlr/backend/multi.h> | 5 | #include <wlr/backend/multi.h> |
5 | #include <wlr/backend/session.h> | ||
6 | #include <wlr/interfaces/wlr_keyboard.h> | 6 | #include <wlr/interfaces/wlr_keyboard.h> |
7 | #include <wlr/types/wlr_idle.h> | ||
8 | #include <wlr/types/wlr_keyboard.h> | 7 | #include <wlr/types/wlr_keyboard.h> |
9 | #include <wlr/types/wlr_keyboard_group.h> | 8 | #include <wlr/types/wlr_keyboard_group.h> |
10 | #include <xkbcommon/xkbcommon-names.h> | 9 | #include <xkbcommon/xkbcommon-names.h> |
11 | #include "sway/commands.h" | 10 | #include "sway/commands.h" |
12 | #include "sway/desktop/transaction.h" | ||
13 | #include "sway/input/input-manager.h" | 11 | #include "sway/input/input-manager.h" |
14 | #include "sway/input/keyboard.h" | 12 | #include "sway/input/keyboard.h" |
15 | #include "sway/input/seat.h" | 13 | #include "sway/input/seat.h" |
@@ -17,6 +15,10 @@ | |||
17 | #include "sway/ipc-server.h" | 15 | #include "sway/ipc-server.h" |
18 | #include "log.h" | 16 | #include "log.h" |
19 | 17 | ||
18 | #if WLR_HAS_SESSION | ||
19 | #include <wlr/backend/session.h> | ||
20 | #endif | ||
21 | |||
20 | static struct modifier_key { | 22 | static struct modifier_key { |
21 | char *name; | 23 | char *name; |
22 | uint32_t mod; | 24 | uint32_t mod; |
@@ -265,14 +267,12 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, | |||
265 | xkb_keysym_t keysym = pressed_keysyms[i]; | 267 | xkb_keysym_t keysym = pressed_keysyms[i]; |
266 | if (keysym >= XKB_KEY_XF86Switch_VT_1 && | 268 | if (keysym >= XKB_KEY_XF86Switch_VT_1 && |
267 | keysym <= XKB_KEY_XF86Switch_VT_12) { | 269 | keysym <= XKB_KEY_XF86Switch_VT_12) { |
268 | if (wlr_backend_is_multi(server.backend)) { | 270 | #if WLR_HAS_SESSION |
269 | struct wlr_session *session = | 271 | if (server.session) { |
270 | wlr_backend_get_session(server.backend); | 272 | unsigned vt = keysym - XKB_KEY_XF86Switch_VT_1 + 1; |
271 | if (session) { | 273 | wlr_session_change_vt(server.session, vt); |
272 | unsigned vt = keysym - XKB_KEY_XF86Switch_VT_1 + 1; | ||
273 | wlr_session_change_vt(session, vt); | ||
274 | } | ||
275 | } | 274 | } |
275 | #endif | ||
276 | return true; | 276 | return true; |
277 | } | 277 | } |
278 | } | 278 | } |
@@ -292,14 +292,12 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, | |||
292 | static size_t keyboard_keysyms_translated(struct sway_keyboard *keyboard, | 292 | static size_t keyboard_keysyms_translated(struct sway_keyboard *keyboard, |
293 | xkb_keycode_t keycode, const xkb_keysym_t **keysyms, | 293 | xkb_keycode_t keycode, const xkb_keysym_t **keysyms, |
294 | uint32_t *modifiers) { | 294 | uint32_t *modifiers) { |
295 | struct wlr_input_device *device = | 295 | *modifiers = wlr_keyboard_get_modifiers(keyboard->wlr); |
296 | keyboard->seat_device->input_device->wlr_device; | ||
297 | *modifiers = wlr_keyboard_get_modifiers(device->keyboard); | ||
298 | xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods2( | 296 | xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods2( |
299 | device->keyboard->xkb_state, keycode, XKB_CONSUMED_MODE_XKB); | 297 | keyboard->wlr->xkb_state, keycode, XKB_CONSUMED_MODE_XKB); |
300 | *modifiers = *modifiers & ~consumed; | 298 | *modifiers = *modifiers & ~consumed; |
301 | 299 | ||
302 | return xkb_state_key_get_syms(device->keyboard->xkb_state, | 300 | return xkb_state_key_get_syms(keyboard->wlr->xkb_state, |
303 | keycode, keysyms); | 301 | keycode, keysyms); |
304 | } | 302 | } |
305 | 303 | ||
@@ -315,13 +313,11 @@ static size_t keyboard_keysyms_translated(struct sway_keyboard *keyboard, | |||
315 | static size_t keyboard_keysyms_raw(struct sway_keyboard *keyboard, | 313 | static size_t keyboard_keysyms_raw(struct sway_keyboard *keyboard, |
316 | xkb_keycode_t keycode, const xkb_keysym_t **keysyms, | 314 | xkb_keycode_t keycode, const xkb_keysym_t **keysyms, |
317 | uint32_t *modifiers) { | 315 | uint32_t *modifiers) { |
318 | struct wlr_input_device *device = | 316 | *modifiers = wlr_keyboard_get_modifiers(keyboard->wlr); |
319 | keyboard->seat_device->input_device->wlr_device; | ||
320 | *modifiers = wlr_keyboard_get_modifiers(device->keyboard); | ||
321 | 317 | ||
322 | xkb_layout_index_t layout_index = xkb_state_key_get_layout( | 318 | xkb_layout_index_t layout_index = xkb_state_key_get_layout( |
323 | device->keyboard->xkb_state, keycode); | 319 | keyboard->wlr->xkb_state, keycode); |
324 | return xkb_keymap_key_get_syms_by_level(device->keyboard->keymap, | 320 | return xkb_keymap_key_get_syms_by_level(keyboard->wlr->keymap, |
325 | keycode, layout_index, 0, keysyms); | 321 | keycode, layout_index, 0, keysyms); |
326 | } | 322 | } |
327 | 323 | ||
@@ -361,8 +357,7 @@ static void update_keyboard_state(struct sway_keyboard *keyboard, | |||
361 | keyinfo->keycode, &keyinfo->translated_keysyms, | 357 | keyinfo->keycode, &keyinfo->translated_keysyms, |
362 | &keyinfo->translated_modifiers); | 358 | &keyinfo->translated_modifiers); |
363 | 359 | ||
364 | keyinfo->code_modifiers = wlr_keyboard_get_modifiers( | 360 | keyinfo->code_modifiers = wlr_keyboard_get_modifiers(keyboard->wlr); |
365 | keyboard->seat_device->input_device->wlr_device->keyboard); | ||
366 | 361 | ||
367 | // Update shortcut model keyinfo | 362 | // Update shortcut model keyinfo |
368 | update_shortcut_state(&keyboard->state_keycodes, raw_keycode, keystate, | 363 | update_shortcut_state(&keyboard->state_keycodes, raw_keycode, keystate, |
@@ -379,16 +374,38 @@ static void update_keyboard_state(struct sway_keyboard *keyboard, | |||
379 | } | 374 | } |
380 | } | 375 | } |
381 | 376 | ||
377 | /** | ||
378 | * Get keyboard grab of the seat from sway_keyboard if we should forward events | ||
379 | * to it. | ||
380 | * | ||
381 | * Returns NULL if the keyboard is not grabbed by an input method, | ||
382 | * or if event is from virtual keyboard of the same client as grab. | ||
383 | * TODO: see swaywm/wlroots#2322 | ||
384 | */ | ||
385 | static struct wlr_input_method_keyboard_grab_v2 *keyboard_get_im_grab( | ||
386 | struct sway_keyboard *keyboard) { | ||
387 | struct wlr_input_method_v2 *input_method = keyboard->seat_device-> | ||
388 | sway_seat->im_relay.input_method; | ||
389 | struct wlr_virtual_keyboard_v1 *virtual_keyboard = | ||
390 | wlr_input_device_get_virtual_keyboard(keyboard->seat_device->input_device->wlr_device); | ||
391 | if (!input_method || !input_method->keyboard_grab || (virtual_keyboard && | ||
392 | wl_resource_get_client(virtual_keyboard->resource) == | ||
393 | wl_resource_get_client(input_method->keyboard_grab->resource))) { | ||
394 | return NULL; | ||
395 | } | ||
396 | return input_method->keyboard_grab; | ||
397 | } | ||
398 | |||
382 | static void handle_key_event(struct sway_keyboard *keyboard, | 399 | static void handle_key_event(struct sway_keyboard *keyboard, |
383 | struct wlr_event_keyboard_key *event) { | 400 | struct wlr_keyboard_key_event *event) { |
384 | struct sway_seat *seat = keyboard->seat_device->sway_seat; | 401 | struct sway_seat *seat = keyboard->seat_device->sway_seat; |
385 | struct wlr_seat *wlr_seat = seat->wlr_seat; | 402 | struct wlr_seat *wlr_seat = seat->wlr_seat; |
386 | struct wlr_input_device *wlr_device = | 403 | struct wlr_input_device *wlr_device = |
387 | keyboard->seat_device->input_device->wlr_device; | 404 | keyboard->seat_device->input_device->wlr_device; |
388 | char *device_identifier = input_device_get_identifier(wlr_device); | 405 | char *device_identifier = input_device_get_identifier(wlr_device); |
389 | bool exact_identifier = wlr_device->keyboard->group != NULL; | 406 | bool exact_identifier = keyboard->wlr->group != NULL; |
390 | seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD); | 407 | seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD); |
391 | bool input_inhibited = seat->exclusive_client != NULL; | 408 | bool locked = server.session_lock.lock; |
392 | struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = | 409 | struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = |
393 | keyboard_shortcuts_inhibitor_get_for_focused_surface(seat); | 410 | keyboard_shortcuts_inhibitor_get_for_focused_surface(seat); |
394 | bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active; | 411 | bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active; |
@@ -406,17 +423,17 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
406 | struct sway_binding *binding_released = NULL; | 423 | struct sway_binding *binding_released = NULL; |
407 | get_active_binding(&keyboard->state_keycodes, | 424 | get_active_binding(&keyboard->state_keycodes, |
408 | config->current_mode->keycode_bindings, &binding_released, | 425 | config->current_mode->keycode_bindings, &binding_released, |
409 | keyinfo.code_modifiers, true, input_inhibited, | 426 | keyinfo.code_modifiers, true, locked, |
410 | shortcuts_inhibited, device_identifier, | 427 | shortcuts_inhibited, device_identifier, |
411 | exact_identifier, keyboard->effective_layout); | 428 | exact_identifier, keyboard->effective_layout); |
412 | get_active_binding(&keyboard->state_keysyms_raw, | 429 | get_active_binding(&keyboard->state_keysyms_raw, |
413 | config->current_mode->keysym_bindings, &binding_released, | 430 | config->current_mode->keysym_bindings, &binding_released, |
414 | keyinfo.raw_modifiers, true, input_inhibited, | 431 | keyinfo.raw_modifiers, true, locked, |
415 | shortcuts_inhibited, device_identifier, | 432 | shortcuts_inhibited, device_identifier, |
416 | exact_identifier, keyboard->effective_layout); | 433 | exact_identifier, keyboard->effective_layout); |
417 | get_active_binding(&keyboard->state_keysyms_translated, | 434 | get_active_binding(&keyboard->state_keysyms_translated, |
418 | config->current_mode->keysym_bindings, &binding_released, | 435 | config->current_mode->keysym_bindings, &binding_released, |
419 | keyinfo.translated_modifiers, true, input_inhibited, | 436 | keyinfo.translated_modifiers, true, locked, |
420 | shortcuts_inhibited, device_identifier, | 437 | shortcuts_inhibited, device_identifier, |
421 | exact_identifier, keyboard->effective_layout); | 438 | exact_identifier, keyboard->effective_layout); |
422 | 439 | ||
@@ -438,17 +455,17 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
438 | if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { | 455 | if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { |
439 | get_active_binding(&keyboard->state_keycodes, | 456 | get_active_binding(&keyboard->state_keycodes, |
440 | config->current_mode->keycode_bindings, &binding, | 457 | config->current_mode->keycode_bindings, &binding, |
441 | keyinfo.code_modifiers, false, input_inhibited, | 458 | keyinfo.code_modifiers, false, locked, |
442 | shortcuts_inhibited, device_identifier, | 459 | shortcuts_inhibited, device_identifier, |
443 | exact_identifier, keyboard->effective_layout); | 460 | exact_identifier, keyboard->effective_layout); |
444 | get_active_binding(&keyboard->state_keysyms_raw, | 461 | get_active_binding(&keyboard->state_keysyms_raw, |
445 | config->current_mode->keysym_bindings, &binding, | 462 | config->current_mode->keysym_bindings, &binding, |
446 | keyinfo.raw_modifiers, false, input_inhibited, | 463 | keyinfo.raw_modifiers, false, locked, |
447 | shortcuts_inhibited, device_identifier, | 464 | shortcuts_inhibited, device_identifier, |
448 | exact_identifier, keyboard->effective_layout); | 465 | exact_identifier, keyboard->effective_layout); |
449 | get_active_binding(&keyboard->state_keysyms_translated, | 466 | get_active_binding(&keyboard->state_keysyms_translated, |
450 | config->current_mode->keysym_bindings, &binding, | 467 | config->current_mode->keysym_bindings, &binding, |
451 | keyinfo.translated_modifiers, false, input_inhibited, | 468 | keyinfo.translated_modifiers, false, locked, |
452 | shortcuts_inhibited, device_identifier, | 469 | shortcuts_inhibited, device_identifier, |
453 | exact_identifier, keyboard->effective_layout); | 470 | exact_identifier, keyboard->effective_layout); |
454 | } | 471 | } |
@@ -456,10 +473,10 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
456 | // Set up (or clear) keyboard repeat for a pressed binding. Since the | 473 | // Set up (or clear) keyboard repeat for a pressed binding. Since the |
457 | // binding may remove the keyboard, the timer needs to be updated first | 474 | // binding may remove the keyboard, the timer needs to be updated first |
458 | if (binding && !(binding->flags & BINDING_NOREPEAT) && | 475 | if (binding && !(binding->flags & BINDING_NOREPEAT) && |
459 | wlr_device->keyboard->repeat_info.delay > 0) { | 476 | keyboard->wlr->repeat_info.delay > 0) { |
460 | keyboard->repeat_binding = binding; | 477 | keyboard->repeat_binding = binding; |
461 | if (wl_event_source_timer_update(keyboard->key_repeat_source, | 478 | if (wl_event_source_timer_update(keyboard->key_repeat_source, |
462 | wlr_device->keyboard->repeat_info.delay) < 0) { | 479 | keyboard->wlr->repeat_info.delay) < 0) { |
463 | sway_log(SWAY_DEBUG, "failed to set key repeat timer"); | 480 | sway_log(SWAY_DEBUG, "failed to set key repeat timer"); |
464 | } | 481 | } |
465 | } else if (keyboard->repeat_binding) { | 482 | } else if (keyboard->repeat_binding) { |
@@ -471,7 +488,7 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
471 | handled = true; | 488 | handled = true; |
472 | } | 489 | } |
473 | 490 | ||
474 | if (!handled && wlr_device->keyboard->group) { | 491 | if (!handled && keyboard->wlr->group) { |
475 | // Only handle device specific bindings for keyboards in a group | 492 | // Only handle device specific bindings for keyboards in a group |
476 | free(device_identifier); | 493 | free(device_identifier); |
477 | return; | 494 | return; |
@@ -489,18 +506,41 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
489 | keyinfo.raw_keysyms_len); | 506 | keyinfo.raw_keysyms_len); |
490 | } | 507 | } |
491 | 508 | ||
492 | if (!handled || event->state == WL_KEYBOARD_KEY_STATE_RELEASED) { | 509 | if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED) { |
510 | // If the pressed event was sent to a client, also send the released | ||
511 | // event. In particular, don't send the released event to the IM grab. | ||
493 | bool pressed_sent = update_shortcut_state( | 512 | bool pressed_sent = update_shortcut_state( |
494 | &keyboard->state_pressed_sent, event->keycode, event->state, | 513 | &keyboard->state_pressed_sent, event->keycode, |
495 | keyinfo.keycode, 0); | 514 | event->state, keyinfo.keycode, 0); |
496 | if (pressed_sent || event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { | 515 | if (pressed_sent) { |
497 | wlr_seat_set_keyboard(wlr_seat, wlr_device); | 516 | wlr_seat_set_keyboard(wlr_seat, keyboard->wlr); |
498 | wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, | 517 | wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, |
499 | event->keycode, event->state); | 518 | event->keycode, event->state); |
519 | handled = true; | ||
520 | } | ||
521 | } | ||
522 | |||
523 | if (!handled) { | ||
524 | struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard); | ||
525 | |||
526 | if (kb_grab) { | ||
527 | wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, keyboard->wlr); | ||
528 | wlr_input_method_keyboard_grab_v2_send_key(kb_grab, | ||
529 | event->time_msec, event->keycode, event->state); | ||
530 | handled = true; | ||
500 | } | 531 | } |
501 | } | 532 | } |
502 | 533 | ||
503 | transaction_commit_dirty(); | 534 | if (!handled && event->state != WL_KEYBOARD_KEY_STATE_RELEASED) { |
535 | // If a released event failed pressed sent test, and not in sent to | ||
536 | // keyboard grab, it is still not handled. Don't handle released here. | ||
537 | update_shortcut_state( | ||
538 | &keyboard->state_pressed_sent, event->keycode, event->state, | ||
539 | keyinfo.keycode, 0); | ||
540 | wlr_seat_set_keyboard(wlr_seat, keyboard->wlr); | ||
541 | wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, | ||
542 | event->keycode, event->state); | ||
543 | } | ||
504 | 544 | ||
505 | free(device_identifier); | 545 | free(device_identifier); |
506 | } | 546 | } |
@@ -573,21 +613,18 @@ static void handle_keyboard_group_leave(struct wl_listener *listener, | |||
573 | } | 613 | } |
574 | 614 | ||
575 | static int handle_keyboard_repeat(void *data) { | 615 | static int handle_keyboard_repeat(void *data) { |
576 | struct sway_keyboard *keyboard = (struct sway_keyboard *)data; | 616 | struct sway_keyboard *keyboard = data; |
577 | struct wlr_keyboard *wlr_device = | ||
578 | keyboard->seat_device->input_device->wlr_device->keyboard; | ||
579 | if (keyboard->repeat_binding) { | 617 | if (keyboard->repeat_binding) { |
580 | if (wlr_device->repeat_info.rate > 0) { | 618 | if (keyboard->wlr->repeat_info.rate > 0) { |
581 | // We queue the next event first, as the command might cancel it | 619 | // We queue the next event first, as the command might cancel it |
582 | if (wl_event_source_timer_update(keyboard->key_repeat_source, | 620 | if (wl_event_source_timer_update(keyboard->key_repeat_source, |
583 | 1000 / wlr_device->repeat_info.rate) < 0) { | 621 | 1000 / keyboard->wlr->repeat_info.rate) < 0) { |
584 | sway_log(SWAY_DEBUG, "failed to update key repeat timer"); | 622 | sway_log(SWAY_DEBUG, "failed to update key repeat timer"); |
585 | } | 623 | } |
586 | } | 624 | } |
587 | 625 | ||
588 | seat_execute_command(keyboard->seat_device->sway_seat, | 626 | seat_execute_command(keyboard->seat_device->sway_seat, |
589 | keyboard->repeat_binding); | 627 | keyboard->repeat_binding); |
590 | transaction_commit_dirty(); | ||
591 | } | 628 | } |
592 | return 0; | 629 | return 0; |
593 | } | 630 | } |
@@ -614,22 +651,28 @@ static void determine_bar_visibility(uint32_t modifiers) { | |||
614 | } | 651 | } |
615 | 652 | ||
616 | static void handle_modifier_event(struct sway_keyboard *keyboard) { | 653 | static void handle_modifier_event(struct sway_keyboard *keyboard) { |
617 | struct wlr_input_device *wlr_device = | 654 | if (!keyboard->wlr->group) { |
618 | keyboard->seat_device->input_device->wlr_device; | 655 | struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard); |
619 | if (!wlr_device->keyboard->group) { | ||
620 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; | ||
621 | wlr_seat_set_keyboard(wlr_seat, wlr_device); | ||
622 | wlr_seat_keyboard_notify_modifiers(wlr_seat, | ||
623 | &wlr_device->keyboard->modifiers); | ||
624 | 656 | ||
625 | uint32_t modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard); | 657 | if (kb_grab) { |
658 | wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, keyboard->wlr); | ||
659 | wlr_input_method_keyboard_grab_v2_send_modifiers(kb_grab, | ||
660 | &keyboard->wlr->modifiers); | ||
661 | } else { | ||
662 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; | ||
663 | wlr_seat_set_keyboard(wlr_seat, keyboard->wlr); | ||
664 | wlr_seat_keyboard_notify_modifiers(wlr_seat, | ||
665 | &keyboard->wlr->modifiers); | ||
666 | } | ||
667 | |||
668 | uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->wlr); | ||
626 | determine_bar_visibility(modifiers); | 669 | determine_bar_visibility(modifiers); |
627 | } | 670 | } |
628 | 671 | ||
629 | if (wlr_device->keyboard->modifiers.group != keyboard->effective_layout) { | 672 | if (keyboard->wlr->modifiers.group != keyboard->effective_layout) { |
630 | keyboard->effective_layout = wlr_device->keyboard->modifiers.group; | 673 | keyboard->effective_layout = keyboard->wlr->modifiers.group; |
631 | 674 | ||
632 | if (!wlr_keyboard_group_from_wlr_keyboard(wlr_device->keyboard)) { | 675 | if (!wlr_keyboard_group_from_wlr_keyboard(keyboard->wlr)) { |
633 | ipc_event_input("xkb_layout", keyboard->seat_device->input_device); | 676 | ipc_event_input("xkb_layout", keyboard->seat_device->input_device); |
634 | } | 677 | } |
635 | } | 678 | } |
@@ -658,6 +701,7 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, | |||
658 | } | 701 | } |
659 | 702 | ||
660 | keyboard->seat_device = device; | 703 | keyboard->seat_device = device; |
704 | keyboard->wlr = wlr_keyboard_from_input_device(device->input_device->wlr_device); | ||
661 | device->keyboard = keyboard; | 705 | device->keyboard = keyboard; |
662 | 706 | ||
663 | wl_list_init(&keyboard->keyboard_key.link); | 707 | wl_list_init(&keyboard->keyboard_key.link); |
@@ -671,23 +715,11 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, | |||
671 | 715 | ||
672 | static void handle_xkb_context_log(struct xkb_context *context, | 716 | static void handle_xkb_context_log(struct xkb_context *context, |
673 | enum xkb_log_level level, const char *format, va_list args) { | 717 | enum xkb_log_level level, const char *format, va_list args) { |
674 | va_list args_copy; | 718 | char *error = vformat_str(format, args); |
675 | va_copy(args_copy, args); | ||
676 | size_t length = vsnprintf(NULL, 0, format, args_copy) + 1; | ||
677 | va_end(args_copy); | ||
678 | |||
679 | char *error = malloc(length); | ||
680 | if (!error) { | ||
681 | sway_log(SWAY_ERROR, "Failed to allocate libxkbcommon log message"); | ||
682 | return; | ||
683 | } | ||
684 | |||
685 | va_copy(args_copy, args); | ||
686 | vsnprintf(error, length, format, args_copy); | ||
687 | va_end(args_copy); | ||
688 | 719 | ||
689 | if (error[length - 2] == '\n') { | 720 | size_t len = strlen(error); |
690 | error[length - 2] = '\0'; | 721 | if (error[len - 1] == '\n') { |
722 | error[len - 1] = '\0'; | ||
691 | } | 723 | } |
692 | 724 | ||
693 | sway_log_importance_t importance = SWAY_DEBUG; | 725 | sway_log_importance_t importance = SWAY_DEBUG; |
@@ -708,7 +740,7 @@ static void handle_xkb_context_log(struct xkb_context *context, | |||
708 | 740 | ||
709 | struct xkb_keymap *sway_keyboard_compile_keymap(struct input_config *ic, | 741 | struct xkb_keymap *sway_keyboard_compile_keymap(struct input_config *ic, |
710 | char **error) { | 742 | char **error) { |
711 | struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); | 743 | struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_SECURE_GETENV); |
712 | if (!sway_assert(context, "cannot create XKB context")) { | 744 | if (!sway_assert(context, "cannot create XKB context")) { |
713 | return NULL; | 745 | return NULL; |
714 | } | 746 | } |
@@ -722,13 +754,8 @@ struct xkb_keymap *sway_keyboard_compile_keymap(struct input_config *ic, | |||
722 | if (!keymap_file) { | 754 | if (!keymap_file) { |
723 | sway_log_errno(SWAY_ERROR, "cannot read xkb file %s", ic->xkb_file); | 755 | sway_log_errno(SWAY_ERROR, "cannot read xkb file %s", ic->xkb_file); |
724 | if (error) { | 756 | if (error) { |
725 | size_t len = snprintf(NULL, 0, "cannot read xkb file %s: %s", | 757 | *error = format_str("cannot read xkb file %s: %s", |
726 | ic->xkb_file, strerror(errno)) + 1; | 758 | ic->xkb_file, strerror(errno)); |
727 | *error = malloc(len); | ||
728 | if (*error) { | ||
729 | snprintf(*error, len, "cannot read xkb_file %s: %s", | ||
730 | ic->xkb_file, strerror(errno)); | ||
731 | } | ||
732 | } | 759 | } |
733 | goto cleanup; | 760 | goto cleanup; |
734 | } | 761 | } |
@@ -766,13 +793,12 @@ static void destroy_empty_wlr_keyboard_group(void *data) { | |||
766 | 793 | ||
767 | static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) { | 794 | static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) { |
768 | struct sway_input_device *device = keyboard->seat_device->input_device; | 795 | struct sway_input_device *device = keyboard->seat_device->input_device; |
769 | struct wlr_keyboard *wlr_keyboard = device->wlr_device->keyboard; | 796 | struct wlr_keyboard_group *wlr_group = keyboard->wlr->group; |
770 | struct wlr_keyboard_group *wlr_group = wlr_keyboard->group; | ||
771 | 797 | ||
772 | sway_log(SWAY_DEBUG, "Removing keyboard %s from group %p", | 798 | sway_log(SWAY_DEBUG, "Removing keyboard %s from group %p", |
773 | device->identifier, wlr_group); | 799 | device->identifier, wlr_group); |
774 | 800 | ||
775 | wlr_keyboard_group_remove_keyboard(wlr_keyboard->group, wlr_keyboard); | 801 | wlr_keyboard_group_remove_keyboard(keyboard->wlr->group, keyboard->wlr); |
776 | 802 | ||
777 | if (wl_list_empty(&wlr_group->devices)) { | 803 | if (wl_list_empty(&wlr_group->devices)) { |
778 | sway_log(SWAY_DEBUG, "Destroying empty keyboard group %p", | 804 | sway_log(SWAY_DEBUG, "Destroying empty keyboard group %p", |
@@ -797,9 +823,7 @@ static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) { | |||
797 | } | 823 | } |
798 | 824 | ||
799 | static void sway_keyboard_group_remove_invalid(struct sway_keyboard *keyboard) { | 825 | static void sway_keyboard_group_remove_invalid(struct sway_keyboard *keyboard) { |
800 | struct sway_input_device *device = keyboard->seat_device->input_device; | 826 | if (!keyboard->wlr->group) { |
801 | struct wlr_keyboard *wlr_keyboard = device->wlr_device->keyboard; | ||
802 | if (!wlr_keyboard->group) { | ||
803 | return; | 827 | return; |
804 | } | 828 | } |
805 | 829 | ||
@@ -815,7 +839,7 @@ static void sway_keyboard_group_remove_invalid(struct sway_keyboard *keyboard) { | |||
815 | break; | 839 | break; |
816 | case KEYBOARD_GROUP_DEFAULT: /* fallthrough */ | 840 | case KEYBOARD_GROUP_DEFAULT: /* fallthrough */ |
817 | case KEYBOARD_GROUP_SMART:; | 841 | case KEYBOARD_GROUP_SMART:; |
818 | struct wlr_keyboard_group *group = wlr_keyboard->group; | 842 | struct wlr_keyboard_group *group = keyboard->wlr->group; |
819 | if (!wlr_keyboard_keymaps_match(keyboard->keymap, group->keyboard.keymap) || | 843 | if (!wlr_keyboard_keymaps_match(keyboard->keymap, group->keyboard.keymap) || |
820 | !repeat_info_match(keyboard, &group->keyboard)) { | 844 | !repeat_info_match(keyboard, &group->keyboard)) { |
821 | sway_keyboard_group_remove(keyboard); | 845 | sway_keyboard_group_remove(keyboard); |
@@ -826,7 +850,6 @@ static void sway_keyboard_group_remove_invalid(struct sway_keyboard *keyboard) { | |||
826 | 850 | ||
827 | static void sway_keyboard_group_add(struct sway_keyboard *keyboard) { | 851 | static void sway_keyboard_group_add(struct sway_keyboard *keyboard) { |
828 | struct sway_input_device *device = keyboard->seat_device->input_device; | 852 | struct sway_input_device *device = keyboard->seat_device->input_device; |
829 | struct wlr_keyboard *wlr_keyboard = device->wlr_device->keyboard; | ||
830 | struct sway_seat *seat = keyboard->seat_device->sway_seat; | 853 | struct sway_seat *seat = keyboard->seat_device->sway_seat; |
831 | struct seat_config *sc = seat_get_config(seat); | 854 | struct seat_config *sc = seat_get_config(seat); |
832 | 855 | ||
@@ -858,7 +881,7 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) { | |||
858 | repeat_info_match(keyboard, &wlr_group->keyboard)) { | 881 | repeat_info_match(keyboard, &wlr_group->keyboard)) { |
859 | sway_log(SWAY_DEBUG, "Adding keyboard %s to group %p", | 882 | sway_log(SWAY_DEBUG, "Adding keyboard %s to group %p", |
860 | device->identifier, wlr_group); | 883 | device->identifier, wlr_group); |
861 | wlr_keyboard_group_add_keyboard(wlr_group, wlr_keyboard); | 884 | wlr_keyboard_group_add_keyboard(wlr_group, keyboard->wlr); |
862 | return; | 885 | return; |
863 | } | 886 | } |
864 | break; | 887 | break; |
@@ -897,7 +920,7 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) { | |||
897 | goto cleanup; | 920 | goto cleanup; |
898 | } | 921 | } |
899 | sway_group->seat_device->input_device->wlr_device = | 922 | sway_group->seat_device->input_device->wlr_device = |
900 | sway_group->wlr_group->input_device; | 923 | &sway_group->wlr_group->keyboard.base; |
901 | 924 | ||
902 | if (!sway_keyboard_create(seat, sway_group->seat_device)) { | 925 | if (!sway_keyboard_create(seat, sway_group->seat_device)) { |
903 | sway_log(SWAY_ERROR, "Failed to allocate sway_keyboard for group"); | 926 | sway_log(SWAY_ERROR, "Failed to allocate sway_keyboard for group"); |
@@ -906,7 +929,7 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) { | |||
906 | 929 | ||
907 | sway_log(SWAY_DEBUG, "Adding keyboard %s to group %p", | 930 | sway_log(SWAY_DEBUG, "Adding keyboard %s to group %p", |
908 | device->identifier, sway_group->wlr_group); | 931 | device->identifier, sway_group->wlr_group); |
909 | wlr_keyboard_group_add_keyboard(sway_group->wlr_group, wlr_keyboard); | 932 | wlr_keyboard_group_add_keyboard(sway_group->wlr_group, keyboard->wlr); |
910 | 933 | ||
911 | wl_list_insert(&seat->keyboard_groups, &sway_group->link); | 934 | wl_list_insert(&seat->keyboard_groups, &sway_group->link); |
912 | 935 | ||
@@ -938,10 +961,8 @@ cleanup: | |||
938 | void sway_keyboard_configure(struct sway_keyboard *keyboard) { | 961 | void sway_keyboard_configure(struct sway_keyboard *keyboard) { |
939 | struct input_config *input_config = | 962 | struct input_config *input_config = |
940 | input_device_get_config(keyboard->seat_device->input_device); | 963 | input_device_get_config(keyboard->seat_device->input_device); |
941 | struct wlr_input_device *wlr_device = | ||
942 | keyboard->seat_device->input_device->wlr_device; | ||
943 | 964 | ||
944 | if (!sway_assert(!wlr_keyboard_group_from_wlr_keyboard(wlr_device->keyboard), | 965 | if (!sway_assert(!wlr_keyboard_group_from_wlr_keyboard(keyboard->wlr), |
945 | "sway_keyboard_configure should not be called with a " | 966 | "sway_keyboard_configure should not be called with a " |
946 | "keyboard group's keyboard")) { | 967 | "keyboard group's keyboard")) { |
947 | return; | 968 | return; |
@@ -983,11 +1004,11 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { | |||
983 | 1004 | ||
984 | sway_keyboard_group_remove_invalid(keyboard); | 1005 | sway_keyboard_group_remove_invalid(keyboard); |
985 | 1006 | ||
986 | wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); | 1007 | wlr_keyboard_set_keymap(keyboard->wlr, keyboard->keymap); |
987 | wlr_keyboard_set_repeat_info(wlr_device->keyboard, | 1008 | wlr_keyboard_set_repeat_info(keyboard->wlr, |
988 | keyboard->repeat_rate, keyboard->repeat_delay); | 1009 | keyboard->repeat_rate, keyboard->repeat_delay); |
989 | 1010 | ||
990 | if (!wlr_device->keyboard->group) { | 1011 | if (!keyboard->wlr->group) { |
991 | sway_keyboard_group_add(keyboard); | 1012 | sway_keyboard_group_add(keyboard); |
992 | } | 1013 | } |
993 | 1014 | ||
@@ -1007,40 +1028,42 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { | |||
1007 | } | 1028 | } |
1008 | } | 1029 | } |
1009 | if (locked_mods) { | 1030 | if (locked_mods) { |
1010 | wlr_keyboard_notify_modifiers(wlr_device->keyboard, 0, 0, | 1031 | wlr_keyboard_notify_modifiers(keyboard->wlr, 0, 0, |
1011 | locked_mods, 0); | 1032 | locked_mods, 0); |
1012 | uint32_t leds = 0; | 1033 | uint32_t leds = 0; |
1013 | for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { | 1034 | for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { |
1014 | if (xkb_state_led_index_is_active( | 1035 | if (xkb_state_led_index_is_active(keyboard->wlr->xkb_state, |
1015 | wlr_device->keyboard->xkb_state, | 1036 | keyboard->wlr->led_indexes[i])) { |
1016 | wlr_device->keyboard->led_indexes[i])) { | ||
1017 | leds |= (1 << i); | 1037 | leds |= (1 << i); |
1018 | } | 1038 | } |
1019 | } | 1039 | } |
1020 | if (wlr_device->keyboard->group) { | 1040 | if (keyboard->wlr->group) { |
1021 | wlr_keyboard_led_update( | 1041 | wlr_keyboard_led_update(&keyboard->wlr->group->keyboard, leds); |
1022 | &wlr_device->keyboard->group->keyboard, leds); | ||
1023 | } else { | 1042 | } else { |
1024 | wlr_keyboard_led_update(wlr_device->keyboard, leds); | 1043 | wlr_keyboard_led_update(keyboard->wlr, leds); |
1025 | } | 1044 | } |
1026 | } | 1045 | } |
1027 | } else { | 1046 | } else { |
1028 | xkb_keymap_unref(keymap); | 1047 | xkb_keymap_unref(keymap); |
1029 | sway_keyboard_group_remove_invalid(keyboard); | 1048 | sway_keyboard_group_remove_invalid(keyboard); |
1030 | if (!wlr_device->keyboard->group) { | 1049 | if (!keyboard->wlr->group) { |
1031 | sway_keyboard_group_add(keyboard); | 1050 | sway_keyboard_group_add(keyboard); |
1032 | } | 1051 | } |
1033 | } | 1052 | } |
1034 | 1053 | ||
1054 | // If the seat has no active keyboard, set this one | ||
1035 | struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat; | 1055 | struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat; |
1036 | wlr_seat_set_keyboard(seat, wlr_device); | 1056 | struct wlr_keyboard *current_keyboard = seat->keyboard_state.keyboard; |
1057 | if (current_keyboard == NULL) { | ||
1058 | wlr_seat_set_keyboard(seat, keyboard->wlr); | ||
1059 | } | ||
1037 | 1060 | ||
1038 | wl_list_remove(&keyboard->keyboard_key.link); | 1061 | wl_list_remove(&keyboard->keyboard_key.link); |
1039 | wl_signal_add(&wlr_device->keyboard->events.key, &keyboard->keyboard_key); | 1062 | wl_signal_add(&keyboard->wlr->events.key, &keyboard->keyboard_key); |
1040 | keyboard->keyboard_key.notify = handle_keyboard_key; | 1063 | keyboard->keyboard_key.notify = handle_keyboard_key; |
1041 | 1064 | ||
1042 | wl_list_remove(&keyboard->keyboard_modifiers.link); | 1065 | wl_list_remove(&keyboard->keyboard_modifiers.link); |
1043 | wl_signal_add(&wlr_device->keyboard->events.modifiers, | 1066 | wl_signal_add(&keyboard->wlr->events.modifiers, |
1044 | &keyboard->keyboard_modifiers); | 1067 | &keyboard->keyboard_modifiers); |
1045 | keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; | 1068 | keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; |
1046 | 1069 | ||
@@ -1057,12 +1080,11 @@ void sway_keyboard_destroy(struct sway_keyboard *keyboard) { | |||
1057 | if (!keyboard) { | 1080 | if (!keyboard) { |
1058 | return; | 1081 | return; |
1059 | } | 1082 | } |
1060 | if (keyboard->seat_device->input_device->wlr_device->keyboard->group) { | 1083 | if (keyboard->wlr->group) { |
1061 | sway_keyboard_group_remove(keyboard); | 1084 | sway_keyboard_group_remove(keyboard); |
1062 | } | 1085 | } |
1063 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; | 1086 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; |
1064 | struct sway_input_device *device = keyboard->seat_device->input_device; | 1087 | if (wlr_seat_get_keyboard(wlr_seat) == keyboard->wlr) { |
1065 | if (wlr_seat_get_keyboard(wlr_seat) == device->wlr_device->keyboard) { | ||
1066 | wlr_seat_set_keyboard(wlr_seat, NULL); | 1088 | wlr_seat_set_keyboard(wlr_seat, NULL); |
1067 | } | 1089 | } |
1068 | if (keyboard->keymap) { | 1090 | if (keyboard->keymap) { |