aboutsummaryrefslogtreecommitdiffstats
path: root/sway/input/input-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/input/input-manager.c')
-rw-r--r--sway/input/input-manager.c149
1 files changed, 97 insertions, 52 deletions
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c
index f04a8ce0..248ca34e 100644
--- a/sway/input/input-manager.c
+++ b/sway/input/input-manager.c
@@ -1,12 +1,12 @@
1#define _POSIX_C_SOURCE 200809L
2#include <ctype.h> 1#include <ctype.h>
3#include <stdio.h> 2#include <stdio.h>
4#include <string.h> 3#include <string.h>
5#include <math.h> 4#include <math.h>
5#include <assert.h>
6#include <wlr/config.h>
6#include <wlr/backend/libinput.h> 7#include <wlr/backend/libinput.h>
7#include <wlr/types/wlr_cursor.h> 8#include <wlr/types/wlr_cursor.h>
8#include <wlr/types/wlr_keyboard_group.h> 9#include <wlr/types/wlr_keyboard_group.h>
9#include <wlr/types/wlr_input_inhibitor.h>
10#include <wlr/types/wlr_virtual_keyboard_v1.h> 10#include <wlr/types/wlr_virtual_keyboard_v1.h>
11#include <wlr/types/wlr_virtual_pointer_v1.h> 11#include <wlr/types/wlr_virtual_pointer_v1.h>
12#include "sway/config.h" 12#include "sway/config.h"
@@ -22,6 +22,10 @@
22#include "list.h" 22#include "list.h"
23#include "log.h" 23#include "log.h"
24 24
25#if WLR_HAS_LIBINPUT_BACKEND
26#include <wlr/backend/libinput.h>
27#endif
28
25#define DEFAULT_SEAT "seat0" 29#define DEFAULT_SEAT "seat0"
26 30
27struct input_config *current_input_config = NULL; 31struct input_config *current_input_config = NULL;
@@ -63,8 +67,15 @@ struct sway_seat *input_manager_sway_seat_from_wlr_seat(struct wlr_seat *wlr_sea
63} 67}
64 68
65char *input_device_get_identifier(struct wlr_input_device *device) { 69char *input_device_get_identifier(struct wlr_input_device *device) {
66 int vendor = device->vendor; 70 int vendor = 0, product = 0;
67 int product = device->product; 71#if WLR_HAS_LIBINPUT_BACKEND
72 if (wlr_input_device_is_libinput(device)) {
73 struct libinput_device *libinput_dev = wlr_libinput_get_device_handle(device);
74 vendor = libinput_device_get_id_vendor(libinput_dev);
75 product = libinput_device_get_id_product(libinput_dev);
76 }
77#endif
78
68 char *name = strdup(device->name ? device->name : ""); 79 char *name = strdup(device->name ? device->name : "");
69 strip_whitespace(name); 80 strip_whitespace(name);
70 81
@@ -76,20 +87,13 @@ char *input_device_get_identifier(struct wlr_input_device *device) {
76 } 87 }
77 } 88 }
78 89
79 const char *fmt = "%d:%d:%s"; 90 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); 91 free(name);
89 return identifier; 92 return identifier;
90} 93}
91 94
92static bool device_is_touchpad(struct sway_input_device *device) { 95static bool device_is_touchpad(struct sway_input_device *device) {
96#if WLR_HAS_LIBINPUT_BACKEND
93 if (device->wlr_device->type != WLR_INPUT_DEVICE_POINTER || 97 if (device->wlr_device->type != WLR_INPUT_DEVICE_POINTER ||
94 !wlr_input_device_is_libinput(device->wlr_device)) { 98 !wlr_input_device_is_libinput(device->wlr_device)) {
95 return false; 99 return false;
@@ -99,6 +103,9 @@ static bool device_is_touchpad(struct sway_input_device *device) {
99 wlr_libinput_get_device_handle(device->wlr_device); 103 wlr_libinput_get_device_handle(device->wlr_device);
100 104
101 return libinput_device_config_tap_get_finger_count(libinput_device) > 0; 105 return libinput_device_config_tap_get_finger_count(libinput_device) > 0;
106#else
107 return false;
108#endif
102} 109}
103 110
104const char *input_device_get_type(struct sway_input_device *device) { 111const char *input_device_get_type(struct sway_input_device *device) {
@@ -113,7 +120,7 @@ const char *input_device_get_type(struct sway_input_device *device) {
113 return "keyboard"; 120 return "keyboard";
114 case WLR_INPUT_DEVICE_TOUCH: 121 case WLR_INPUT_DEVICE_TOUCH:
115 return "touch"; 122 return "touch";
116 case WLR_INPUT_DEVICE_TABLET_TOOL: 123 case WLR_INPUT_DEVICE_TABLET:
117 return "tablet_tool"; 124 return "tablet_tool";
118 case WLR_INPUT_DEVICE_TABLET_PAD: 125 case WLR_INPUT_DEVICE_TABLET_PAD:
119 return "tablet_pad"; 126 return "tablet_pad";
@@ -236,7 +243,11 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
236 243
237 apply_input_type_config(input_device); 244 apply_input_type_config(input_device);
238 245
239 sway_input_configure_libinput_device(input_device); 246#if WLR_HAS_LIBINPUT_BACKEND
247 bool config_changed = sway_input_configure_libinput_device(input_device);
248#else
249 bool config_changed = false;
250#endif
240 251
241 wl_signal_add(&device->events.destroy, &input_device->device_destroy); 252 wl_signal_add(&device->events.destroy, &input_device->device_destroy);
242 input_device->device_destroy.notify = handle_device_destroy; 253 input_device->device_destroy.notify = handle_device_destroy;
@@ -274,29 +285,9 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
274 } 285 }
275 286
276 ipc_event_input("added", input_device); 287 ipc_event_input("added", input_device);
277}
278 288
279static void handle_inhibit_activate(struct wl_listener *listener, void *data) { 289 if (config_changed) {
280 struct sway_input_manager *input_manager = wl_container_of( 290 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
288static 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 } 291 }
301} 292}
302 293
@@ -377,7 +368,7 @@ void handle_virtual_keyboard(struct wl_listener *listener, void *data) {
377 struct sway_input_manager *input_manager = 368 struct sway_input_manager *input_manager =
378 wl_container_of(listener, input_manager, virtual_keyboard_new); 369 wl_container_of(listener, input_manager, virtual_keyboard_new);
379 struct wlr_virtual_keyboard_v1 *keyboard = data; 370 struct wlr_virtual_keyboard_v1 *keyboard = data;
380 struct wlr_input_device *device = &keyboard->input_device; 371 struct wlr_input_device *device = &keyboard->keyboard.base;
381 372
382 // TODO: Amend protocol to allow NULL seat 373 // TODO: Amend protocol to allow NULL seat
383 struct sway_seat *seat = keyboard->seat ? 374 struct sway_seat *seat = keyboard->seat ?
@@ -410,7 +401,7 @@ void handle_virtual_pointer(struct wl_listener *listener, void *data) {
410 wl_container_of(listener, input_manager, virtual_pointer_new); 401 wl_container_of(listener, input_manager, virtual_pointer_new);
411 struct wlr_virtual_pointer_v1_new_pointer_event *event = data; 402 struct wlr_virtual_pointer_v1_new_pointer_event *event = data;
412 struct wlr_virtual_pointer_v1 *pointer = event->new_pointer; 403 struct wlr_virtual_pointer_v1 *pointer = event->new_pointer;
413 struct wlr_input_device *device = &pointer->input_device; 404 struct wlr_input_device *device = &pointer->pointer.base;
414 405
415 struct sway_seat *seat = event->suggested_seat ? 406 struct sway_seat *seat = event->suggested_seat ?
416 input_manager_sway_seat_from_wlr_seat(event->suggested_seat) : 407 input_manager_sway_seat_from_wlr_seat(event->suggested_seat) :
@@ -442,6 +433,20 @@ void handle_virtual_pointer(struct wl_listener *listener, void *data) {
442 } 433 }
443} 434}
444 435
436static void handle_transient_seat_manager_create_seat(
437 struct wl_listener *listener, void *data) {
438 struct wlr_transient_seat_v1 *transient_seat = data;
439 static uint64_t i;
440 char name[256];
441 snprintf(name, sizeof(name), "transient-%"PRIx64, i++);
442 struct sway_seat *seat = seat_create(name);
443 if (seat && seat->wlr_seat) {
444 wlr_transient_seat_v1_ready(transient_seat, seat->wlr_seat);
445 } else {
446 wlr_transient_seat_v1_deny(transient_seat);
447 }
448}
449
445struct sway_input_manager *input_manager_create(struct sway_server *server) { 450struct sway_input_manager *input_manager_create(struct sway_server *server) {
446 struct sway_input_manager *input = 451 struct sway_input_manager *input =
447 calloc(1, sizeof(struct sway_input_manager)); 452 calloc(1, sizeof(struct sway_input_manager));
@@ -468,14 +473,6 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
468 &input->virtual_pointer_new); 473 &input->virtual_pointer_new);
469 input->virtual_pointer_new.notify = handle_virtual_pointer; 474 input->virtual_pointer_new.notify = handle_virtual_pointer;
470 475
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 = 476 input->keyboard_shortcuts_inhibit =
480 wlr_keyboard_shortcuts_inhibit_v1_create(server->wl_display); 477 wlr_keyboard_shortcuts_inhibit_v1_create(server->wl_display);
481 input->keyboard_shortcuts_inhibit_new_inhibitor.notify = 478 input->keyboard_shortcuts_inhibit_new_inhibitor.notify =
@@ -483,6 +480,17 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
483 wl_signal_add(&input->keyboard_shortcuts_inhibit->events.new_inhibitor, 480 wl_signal_add(&input->keyboard_shortcuts_inhibit->events.new_inhibitor,
484 &input->keyboard_shortcuts_inhibit_new_inhibitor); 481 &input->keyboard_shortcuts_inhibit_new_inhibitor);
485 482
483 input->pointer_gestures = wlr_pointer_gestures_v1_create(server->wl_display);
484
485 input->transient_seat_manager =
486 wlr_transient_seat_manager_v1_create(server->wl_display);
487 assert(input->transient_seat_manager);
488
489 input->transient_seat_create.notify =
490 handle_transient_seat_manager_create_seat;
491 wl_signal_add(&input->transient_seat_manager->events.create_seat,
492 &input->transient_seat_create);
493
486 return input; 494 return input;
487} 495}
488 496
@@ -520,21 +528,50 @@ static void retranslate_keysyms(struct input_config *input_config) {
520 return; 528 return;
521 } 529 }
522 } 530 }
531
532 for (int i = 0; i < config->input_type_configs->length; ++i) {
533 struct input_config *ic = config->input_type_configs->items[i];
534 if (ic->xkb_layout || ic->xkb_file) {
535 // this is the first config with xkb_layout or xkb_file
536 if (ic->identifier == input_config->identifier) {
537 translate_keysyms(ic);
538 }
539
540 return;
541 }
542 }
523} 543}
524 544
525static void input_manager_configure_input( 545static void input_manager_configure_input(
526 struct sway_input_device *input_device) { 546 struct sway_input_device *input_device) {
527 sway_input_configure_libinput_device(input_device); 547#if WLR_HAS_LIBINPUT_BACKEND
548 bool config_changed = sway_input_configure_libinput_device(input_device);
549#else
550 bool config_changed = false;
551#endif
528 struct sway_seat *seat = NULL; 552 struct sway_seat *seat = NULL;
529 wl_list_for_each(seat, &server.input->seats, link) { 553 wl_list_for_each(seat, &server.input->seats, link) {
530 seat_configure_device(seat, input_device); 554 seat_configure_device(seat, input_device);
531 } 555 }
556 if (config_changed) {
557 ipc_event_input("libinput_config", input_device);
558 }
532} 559}
533 560
534void input_manager_configure_all_inputs(void) { 561void input_manager_configure_all_input_mappings(void) {
535 struct sway_input_device *input_device = NULL; 562 struct sway_input_device *input_device;
536 wl_list_for_each(input_device, &server.input->devices, link) { 563 wl_list_for_each(input_device, &server.input->devices, link) {
537 input_manager_configure_input(input_device); 564 struct sway_seat *seat;
565 wl_list_for_each(seat, &server.input->seats, link) {
566 seat_configure_device_mapping(seat, input_device);
567 }
568
569#if WLR_HAS_LIBINPUT_BACKEND
570 // Input devices mapped to unavailable outputs get their libinput
571 // send_events setting switched to false. We need to re-enable this
572 // when the output appears.
573 sway_input_configure_libinput_device_send_events(input_device);
574#endif
538 } 575 }
539} 576}
540 577
@@ -556,7 +593,9 @@ void input_manager_apply_input_config(struct input_config *input_config) {
556} 593}
557 594
558void input_manager_reset_input(struct sway_input_device *input_device) { 595void input_manager_reset_input(struct sway_input_device *input_device) {
596#if WLR_HAS_LIBINPUT_BACKEND
559 sway_input_reset_libinput_device(input_device); 597 sway_input_reset_libinput_device(input_device);
598#endif
560 struct sway_seat *seat = NULL; 599 struct sway_seat *seat = NULL;
561 wl_list_for_each(seat, &server.input->seats, link) { 600 wl_list_for_each(seat, &server.input->seats, link) {
562 seat_reset_device(seat, input_device); 601 seat_reset_device(seat, input_device);
@@ -564,6 +603,13 @@ void input_manager_reset_input(struct sway_input_device *input_device) {
564} 603}
565 604
566void input_manager_reset_all_inputs(void) { 605void input_manager_reset_all_inputs(void) {
606 // Set the active keyboard to NULL to avoid spamming configuration updates
607 // for all keyboard devices.
608 struct sway_seat *seat;
609 wl_list_for_each(seat, &server.input->seats, link) {
610 wlr_seat_set_keyboard(seat->wlr_seat, NULL);
611 }
612
567 struct sway_input_device *input_device = NULL; 613 struct sway_input_device *input_device = NULL;
568 wl_list_for_each(input_device, &server.input->devices, link) { 614 wl_list_for_each(input_device, &server.input->devices, link) {
569 input_manager_reset_input(input_device); 615 input_manager_reset_input(input_device);
@@ -572,7 +618,6 @@ void input_manager_reset_all_inputs(void) {
572 // If there is at least one keyboard using the default keymap, repeat delay, 618 // 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 619 // and repeat rate, then it is possible that there is a keyboard group that
574 // need their keyboard disarmed. 620 // need their keyboard disarmed.
575 struct sway_seat *seat;
576 wl_list_for_each(seat, &server.input->seats, link) { 621 wl_list_for_each(seat, &server.input->seats, link) {
577 struct sway_keyboard_group *group; 622 struct sway_keyboard_group *group;
578 wl_list_for_each(group, &seat->keyboard_groups, link) { 623 wl_list_for_each(group, &seat->keyboard_groups, link) {