aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2020-06-13 11:45:50 -0400
committerLibravatar Simon Ser <contact@emersion.fr>2020-06-16 17:53:23 +0200
commit33aa59d4c6d4aaf907091f5fcc967b1f9b1a0fd8 (patch)
treea1192e0d47d06c7d118a3da21b9e8024c56f1600
parenti3-compat: add GET_BINDING_STATE IPC command (diff)
downloadsway-33aa59d4c6d4aaf907091f5fcc967b1f9b1a0fd8.tar.gz
sway-33aa59d4c6d4aaf907091f5fcc967b1f9b1a0fd8.tar.zst
sway-33aa59d4c6d4aaf907091f5fcc967b1f9b1a0fd8.zip
input/keyboard: wlr_keyboard_group enter and leave
This adds support for wlr_keyboard_group's enter and leave events. The enter event just updates the keyboard's state. The leave event updates the keyboard's state and if the surface was notified of a press event for any of the keycodes, it is refocused so that it can pick up the current keyboard state without triggering any keybinds.
-rw-r--r--include/sway/input/keyboard.h2
-rw-r--r--sway/input/keyboard.c171
2 files changed, 128 insertions, 45 deletions
diff --git a/include/sway/input/keyboard.h b/include/sway/input/keyboard.h
index c9d2e5ce..2c61e5a7 100644
--- a/include/sway/input/keyboard.h
+++ b/include/sway/input/keyboard.h
@@ -75,6 +75,8 @@ struct sway_keyboard_group {
75 struct sway_seat_device *seat_device; 75 struct sway_seat_device *seat_device;
76 struct wl_listener keyboard_key; 76 struct wl_listener keyboard_key;
77 struct wl_listener keyboard_modifiers; 77 struct wl_listener keyboard_modifiers;
78 struct wl_listener enter;
79 struct wl_listener leave;
78 struct wl_list link; // sway_seat::keyboard_groups 80 struct wl_list link; // sway_seat::keyboard_groups
79}; 81};
80 82
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 */
126static bool update_shortcut_state(struct sway_shortcut_state *state, 126static 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
337struct 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
350static 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
337static void handle_key_event(struct sway_keyboard *keyboard, 381static 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
516static 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
530static 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
497static int handle_keyboard_repeat(void *data) { 570static 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
840cleanup: 921cleanup: