diff options
Diffstat (limited to 'sway/input/input-manager.c')
-rw-r--r-- | sway/input/input-manager.c | 112 |
1 files changed, 63 insertions, 49 deletions
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index f04a8ce0..c1bbdde0 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c | |||
@@ -3,10 +3,9 @@ | |||
3 | #include <stdio.h> | 3 | #include <stdio.h> |
4 | #include <string.h> | 4 | #include <string.h> |
5 | #include <math.h> | 5 | #include <math.h> |
6 | #include <wlr/backend/libinput.h> | 6 | #include <wlr/config.h> |
7 | #include <wlr/types/wlr_cursor.h> | 7 | #include <wlr/types/wlr_cursor.h> |
8 | #include <wlr/types/wlr_keyboard_group.h> | 8 | #include <wlr/types/wlr_keyboard_group.h> |
9 | #include <wlr/types/wlr_input_inhibitor.h> | ||
10 | #include <wlr/types/wlr_virtual_keyboard_v1.h> | 9 | #include <wlr/types/wlr_virtual_keyboard_v1.h> |
11 | #include <wlr/types/wlr_virtual_pointer_v1.h> | 10 | #include <wlr/types/wlr_virtual_pointer_v1.h> |
12 | #include "sway/config.h" | 11 | #include "sway/config.h" |
@@ -22,6 +21,10 @@ | |||
22 | #include "list.h" | 21 | #include "list.h" |
23 | #include "log.h" | 22 | #include "log.h" |
24 | 23 | ||
24 | #if WLR_HAS_LIBINPUT_BACKEND | ||
25 | #include <wlr/backend/libinput.h> | ||
26 | #endif | ||
27 | |||
25 | #define DEFAULT_SEAT "seat0" | 28 | #define DEFAULT_SEAT "seat0" |
26 | 29 | ||
27 | struct input_config *current_input_config = NULL; | 30 | struct input_config *current_input_config = NULL; |
@@ -76,20 +79,13 @@ char *input_device_get_identifier(struct wlr_input_device *device) { | |||
76 | } | 79 | } |
77 | } | 80 | } |
78 | 81 | ||
79 | const char *fmt = "%d:%d:%s"; | 82 | char *identifier = format_str("%d:%d:%s", vendor, product, name); |
80 | int len = snprintf(NULL, 0, fmt, vendor, product, name) + 1; | ||
81 | char *identifier = malloc(len); | ||
82 | if (!identifier) { | ||
83 | sway_log(SWAY_ERROR, "Unable to allocate unique input device name"); | ||
84 | return NULL; | ||
85 | } | ||
86 | |||
87 | snprintf(identifier, len, fmt, vendor, product, name); | ||
88 | free(name); | 83 | free(name); |
89 | return identifier; | 84 | return identifier; |
90 | } | 85 | } |
91 | 86 | ||
92 | static bool device_is_touchpad(struct sway_input_device *device) { | 87 | static bool device_is_touchpad(struct sway_input_device *device) { |
88 | #if WLR_HAS_LIBINPUT_BACKEND | ||
93 | if (device->wlr_device->type != WLR_INPUT_DEVICE_POINTER || | 89 | if (device->wlr_device->type != WLR_INPUT_DEVICE_POINTER || |
94 | !wlr_input_device_is_libinput(device->wlr_device)) { | 90 | !wlr_input_device_is_libinput(device->wlr_device)) { |
95 | return false; | 91 | return false; |
@@ -99,6 +95,9 @@ static bool device_is_touchpad(struct sway_input_device *device) { | |||
99 | wlr_libinput_get_device_handle(device->wlr_device); | 95 | wlr_libinput_get_device_handle(device->wlr_device); |
100 | 96 | ||
101 | return libinput_device_config_tap_get_finger_count(libinput_device) > 0; | 97 | return libinput_device_config_tap_get_finger_count(libinput_device) > 0; |
98 | #else | ||
99 | return false; | ||
100 | #endif | ||
102 | } | 101 | } |
103 | 102 | ||
104 | const char *input_device_get_type(struct sway_input_device *device) { | 103 | const char *input_device_get_type(struct sway_input_device *device) { |
@@ -236,7 +235,11 @@ static void handle_new_input(struct wl_listener *listener, void *data) { | |||
236 | 235 | ||
237 | apply_input_type_config(input_device); | 236 | apply_input_type_config(input_device); |
238 | 237 | ||
239 | sway_input_configure_libinput_device(input_device); | 238 | #if WLR_HAS_LIBINPUT_BACKEND |
239 | bool config_changed = sway_input_configure_libinput_device(input_device); | ||
240 | #else | ||
241 | bool config_changed = false; | ||
242 | #endif | ||
240 | 243 | ||
241 | wl_signal_add(&device->events.destroy, &input_device->device_destroy); | 244 | wl_signal_add(&device->events.destroy, &input_device->device_destroy); |
242 | input_device->device_destroy.notify = handle_device_destroy; | 245 | input_device->device_destroy.notify = handle_device_destroy; |
@@ -274,29 +277,9 @@ static void handle_new_input(struct wl_listener *listener, void *data) { | |||
274 | } | 277 | } |
275 | 278 | ||
276 | ipc_event_input("added", input_device); | 279 | ipc_event_input("added", input_device); |
277 | } | ||
278 | 280 | ||
279 | static void handle_inhibit_activate(struct wl_listener *listener, void *data) { | 281 | if (config_changed) { |
280 | struct sway_input_manager *input_manager = wl_container_of( | 282 | ipc_event_input("libinput_config", input_device); |
281 | listener, input_manager, inhibit_activate); | ||
282 | struct sway_seat *seat; | ||
283 | wl_list_for_each(seat, &input_manager->seats, link) { | ||
284 | seat_set_exclusive_client(seat, input_manager->inhibit->active_client); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | static void handle_inhibit_deactivate(struct wl_listener *listener, void *data) { | ||
289 | struct sway_input_manager *input_manager = wl_container_of( | ||
290 | listener, input_manager, inhibit_deactivate); | ||
291 | struct sway_seat *seat; | ||
292 | wl_list_for_each(seat, &input_manager->seats, link) { | ||
293 | seat_set_exclusive_client(seat, NULL); | ||
294 | struct sway_node *previous = seat_get_focus(seat); | ||
295 | if (previous) { | ||
296 | // Hack to get seat to re-focus the return value of get_focus | ||
297 | seat_set_focus(seat, NULL); | ||
298 | seat_set_focus(seat, previous); | ||
299 | } | ||
300 | } | 283 | } |
301 | } | 284 | } |
302 | 285 | ||
@@ -377,7 +360,7 @@ void handle_virtual_keyboard(struct wl_listener *listener, void *data) { | |||
377 | struct sway_input_manager *input_manager = | 360 | struct sway_input_manager *input_manager = |
378 | wl_container_of(listener, input_manager, virtual_keyboard_new); | 361 | wl_container_of(listener, input_manager, virtual_keyboard_new); |
379 | struct wlr_virtual_keyboard_v1 *keyboard = data; | 362 | struct wlr_virtual_keyboard_v1 *keyboard = data; |
380 | struct wlr_input_device *device = &keyboard->input_device; | 363 | struct wlr_input_device *device = &keyboard->keyboard.base; |
381 | 364 | ||
382 | // TODO: Amend protocol to allow NULL seat | 365 | // TODO: Amend protocol to allow NULL seat |
383 | struct sway_seat *seat = keyboard->seat ? | 366 | struct sway_seat *seat = keyboard->seat ? |
@@ -410,7 +393,7 @@ void handle_virtual_pointer(struct wl_listener *listener, void *data) { | |||
410 | wl_container_of(listener, input_manager, virtual_pointer_new); | 393 | wl_container_of(listener, input_manager, virtual_pointer_new); |
411 | struct wlr_virtual_pointer_v1_new_pointer_event *event = data; | 394 | struct wlr_virtual_pointer_v1_new_pointer_event *event = data; |
412 | struct wlr_virtual_pointer_v1 *pointer = event->new_pointer; | 395 | struct wlr_virtual_pointer_v1 *pointer = event->new_pointer; |
413 | struct wlr_input_device *device = &pointer->input_device; | 396 | struct wlr_input_device *device = &pointer->pointer.base; |
414 | 397 | ||
415 | struct sway_seat *seat = event->suggested_seat ? | 398 | struct sway_seat *seat = event->suggested_seat ? |
416 | input_manager_sway_seat_from_wlr_seat(event->suggested_seat) : | 399 | input_manager_sway_seat_from_wlr_seat(event->suggested_seat) : |
@@ -468,14 +451,6 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) { | |||
468 | &input->virtual_pointer_new); | 451 | &input->virtual_pointer_new); |
469 | input->virtual_pointer_new.notify = handle_virtual_pointer; | 452 | input->virtual_pointer_new.notify = handle_virtual_pointer; |
470 | 453 | ||
471 | input->inhibit = wlr_input_inhibit_manager_create(server->wl_display); | ||
472 | input->inhibit_activate.notify = handle_inhibit_activate; | ||
473 | wl_signal_add(&input->inhibit->events.activate, | ||
474 | &input->inhibit_activate); | ||
475 | input->inhibit_deactivate.notify = handle_inhibit_deactivate; | ||
476 | wl_signal_add(&input->inhibit->events.deactivate, | ||
477 | &input->inhibit_deactivate); | ||
478 | |||
479 | input->keyboard_shortcuts_inhibit = | 454 | input->keyboard_shortcuts_inhibit = |
480 | wlr_keyboard_shortcuts_inhibit_v1_create(server->wl_display); | 455 | wlr_keyboard_shortcuts_inhibit_v1_create(server->wl_display); |
481 | input->keyboard_shortcuts_inhibit_new_inhibitor.notify = | 456 | input->keyboard_shortcuts_inhibit_new_inhibitor.notify = |
@@ -483,6 +458,8 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) { | |||
483 | wl_signal_add(&input->keyboard_shortcuts_inhibit->events.new_inhibitor, | 458 | wl_signal_add(&input->keyboard_shortcuts_inhibit->events.new_inhibitor, |
484 | &input->keyboard_shortcuts_inhibit_new_inhibitor); | 459 | &input->keyboard_shortcuts_inhibit_new_inhibitor); |
485 | 460 | ||
461 | input->pointer_gestures = wlr_pointer_gestures_v1_create(server->wl_display); | ||
462 | |||
486 | return input; | 463 | return input; |
487 | } | 464 | } |
488 | 465 | ||
@@ -520,21 +497,50 @@ static void retranslate_keysyms(struct input_config *input_config) { | |||
520 | return; | 497 | return; |
521 | } | 498 | } |
522 | } | 499 | } |
500 | |||
501 | for (int i = 0; i < config->input_type_configs->length; ++i) { | ||
502 | struct input_config *ic = config->input_type_configs->items[i]; | ||
503 | if (ic->xkb_layout || ic->xkb_file) { | ||
504 | // this is the first config with xkb_layout or xkb_file | ||
505 | if (ic->identifier == input_config->identifier) { | ||
506 | translate_keysyms(ic); | ||
507 | } | ||
508 | |||
509 | return; | ||
510 | } | ||
511 | } | ||
523 | } | 512 | } |
524 | 513 | ||
525 | static void input_manager_configure_input( | 514 | static void input_manager_configure_input( |
526 | struct sway_input_device *input_device) { | 515 | struct sway_input_device *input_device) { |
527 | sway_input_configure_libinput_device(input_device); | 516 | #if WLR_HAS_LIBINPUT_BACKEND |
517 | bool config_changed = sway_input_configure_libinput_device(input_device); | ||
518 | #else | ||
519 | bool config_changed = false; | ||
520 | #endif | ||
528 | struct sway_seat *seat = NULL; | 521 | struct sway_seat *seat = NULL; |
529 | wl_list_for_each(seat, &server.input->seats, link) { | 522 | wl_list_for_each(seat, &server.input->seats, link) { |
530 | seat_configure_device(seat, input_device); | 523 | seat_configure_device(seat, input_device); |
531 | } | 524 | } |
525 | if (config_changed) { | ||
526 | ipc_event_input("libinput_config", input_device); | ||
527 | } | ||
532 | } | 528 | } |
533 | 529 | ||
534 | void input_manager_configure_all_inputs(void) { | 530 | void input_manager_configure_all_input_mappings(void) { |
535 | struct sway_input_device *input_device = NULL; | 531 | struct sway_input_device *input_device; |
536 | wl_list_for_each(input_device, &server.input->devices, link) { | 532 | wl_list_for_each(input_device, &server.input->devices, link) { |
537 | input_manager_configure_input(input_device); | 533 | struct sway_seat *seat; |
534 | wl_list_for_each(seat, &server.input->seats, link) { | ||
535 | seat_configure_device_mapping(seat, input_device); | ||
536 | } | ||
537 | |||
538 | #if WLR_HAS_LIBINPUT_BACKEND | ||
539 | // Input devices mapped to unavailable outputs get their libinput | ||
540 | // send_events setting switched to false. We need to re-enable this | ||
541 | // when the output appears. | ||
542 | sway_input_configure_libinput_device_send_events(input_device); | ||
543 | #endif | ||
538 | } | 544 | } |
539 | } | 545 | } |
540 | 546 | ||
@@ -556,7 +562,9 @@ void input_manager_apply_input_config(struct input_config *input_config) { | |||
556 | } | 562 | } |
557 | 563 | ||
558 | void input_manager_reset_input(struct sway_input_device *input_device) { | 564 | void input_manager_reset_input(struct sway_input_device *input_device) { |
565 | #if WLR_HAS_LIBINPUT_BACKEND | ||
559 | sway_input_reset_libinput_device(input_device); | 566 | sway_input_reset_libinput_device(input_device); |
567 | #endif | ||
560 | struct sway_seat *seat = NULL; | 568 | struct sway_seat *seat = NULL; |
561 | wl_list_for_each(seat, &server.input->seats, link) { | 569 | wl_list_for_each(seat, &server.input->seats, link) { |
562 | seat_reset_device(seat, input_device); | 570 | seat_reset_device(seat, input_device); |
@@ -564,6 +572,13 @@ void input_manager_reset_input(struct sway_input_device *input_device) { | |||
564 | } | 572 | } |
565 | 573 | ||
566 | void input_manager_reset_all_inputs(void) { | 574 | void input_manager_reset_all_inputs(void) { |
575 | // Set the active keyboard to NULL to avoid spamming configuration updates | ||
576 | // for all keyboard devices. | ||
577 | struct sway_seat *seat; | ||
578 | wl_list_for_each(seat, &server.input->seats, link) { | ||
579 | wlr_seat_set_keyboard(seat->wlr_seat, NULL); | ||
580 | } | ||
581 | |||
567 | struct sway_input_device *input_device = NULL; | 582 | struct sway_input_device *input_device = NULL; |
568 | wl_list_for_each(input_device, &server.input->devices, link) { | 583 | wl_list_for_each(input_device, &server.input->devices, link) { |
569 | input_manager_reset_input(input_device); | 584 | input_manager_reset_input(input_device); |
@@ -572,7 +587,6 @@ void input_manager_reset_all_inputs(void) { | |||
572 | // If there is at least one keyboard using the default keymap, repeat delay, | 587 | // If there is at least one keyboard using the default keymap, repeat delay, |
573 | // and repeat rate, then it is possible that there is a keyboard group that | 588 | // and repeat rate, then it is possible that there is a keyboard group that |
574 | // need their keyboard disarmed. | 589 | // need their keyboard disarmed. |
575 | struct sway_seat *seat; | ||
576 | wl_list_for_each(seat, &server.input->seats, link) { | 590 | wl_list_for_each(seat, &server.input->seats, link) { |
577 | struct sway_keyboard_group *group; | 591 | struct sway_keyboard_group *group; |
578 | wl_list_for_each(group, &seat->keyboard_groups, link) { | 592 | wl_list_for_each(group, &seat->keyboard_groups, link) { |