diff options
author | Ryan Walklin <ryan@testtoast.com> | 2019-03-20 14:47:29 +1100 |
---|---|---|
committer | Brian Ashworth <bosrsf04@gmail.com> | 2019-03-19 23:58:47 -0400 |
commit | bdb402404cd6d54242b0b1dc2360cfc5679e52f2 (patch) | |
tree | 5a355e025c24b3de0bc69db4b8cc9d002bbd1167 /sway/input | |
parent | Clean up focus follows mouse logic (diff) | |
download | sway-bdb402404cd6d54242b0b1dc2360cfc5679e52f2.tar.gz sway-bdb402404cd6d54242b0b1dc2360cfc5679e52f2.tar.zst sway-bdb402404cd6d54242b0b1dc2360cfc5679e52f2.zip |
Support WLR_INPUT_DEVICE_SWITCH in sway
This commit adds support for laptop lid and tablet
mode switches as provided by evdev/libinput and
handled by wlroots.
Adds a new bindswitch command with syntax:
bindswitch <switch>:<state> <command>
Where <switch> is one of:
tablet for WLR_SWITCH_TYPE_TABLET_MODE
lid for WLR_SWITCH_TYPE_LID
<state> is one of:
on for WLR_SWITCH_STATE_ON
off for WLR_SWITCH_STATE_OFF
toggle for WLR_SWITCH_STATE_TOGGLE
(Note that WLR_SWITCH_STATE_TOGGLE doesn't map to
libinput and will trigger at both on and off events)
Diffstat (limited to 'sway/input')
-rw-r--r-- | sway/input/input-manager.c | 47 | ||||
-rw-r--r-- | sway/input/seat.c | 18 | ||||
-rw-r--r-- | sway/input/switch.c | 85 |
3 files changed, 146 insertions, 4 deletions
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index f99fc395..adb36af9 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c | |||
@@ -155,6 +155,47 @@ static void input_manager_libinput_reset_keyboard( | |||
155 | libinput_device, send_events)); | 155 | libinput_device, send_events)); |
156 | } | 156 | } |
157 | 157 | ||
158 | static void input_manager_libinput_config_switch( | ||
159 | struct sway_input_device *input_device) { | ||
160 | struct wlr_input_device *wlr_device = input_device->wlr_device; | ||
161 | struct input_config *ic = input_device_get_config(input_device); | ||
162 | struct libinput_device *libinput_device; | ||
163 | |||
164 | if (!ic || !wlr_input_device_is_libinput(wlr_device)) { | ||
165 | return; | ||
166 | } | ||
167 | |||
168 | libinput_device = wlr_libinput_get_device_handle(wlr_device); | ||
169 | sway_log(SWAY_DEBUG, "input_manager_libinput_config_switch(%s)", | ||
170 | ic->identifier); | ||
171 | |||
172 | if (ic->send_events != INT_MIN) { | ||
173 | sway_log(SWAY_DEBUG, "libinput_config_switch(%s) send_events_set_mode(%d)", | ||
174 | ic->identifier, ic->send_events); | ||
175 | log_libinput_config_status(libinput_device_config_send_events_set_mode( | ||
176 | libinput_device, ic->send_events)); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | static void input_manager_libinput_reset_switch( | ||
181 | struct sway_input_device *input_device) { | ||
182 | struct wlr_input_device *wlr_device = input_device->wlr_device; | ||
183 | struct libinput_device *libinput_device; | ||
184 | |||
185 | if (!wlr_input_device_is_libinput(wlr_device)) { | ||
186 | return; | ||
187 | } | ||
188 | |||
189 | libinput_device = wlr_libinput_get_device_handle(wlr_device); | ||
190 | |||
191 | uint32_t send_events = | ||
192 | libinput_device_config_send_events_get_default_mode(libinput_device); | ||
193 | sway_log(SWAY_DEBUG, "libinput_reset_switch(%s) send_events_set_mode(%d)", | ||
194 | input_device->identifier, send_events); | ||
195 | log_libinput_config_status(libinput_device_config_send_events_set_mode( | ||
196 | libinput_device, send_events)); | ||
197 | } | ||
198 | |||
158 | static void input_manager_libinput_config_touch( | 199 | static void input_manager_libinput_config_touch( |
159 | struct sway_input_device *input_device) { | 200 | struct sway_input_device *input_device) { |
160 | struct wlr_input_device *wlr_device = input_device->wlr_device; | 201 | struct wlr_input_device *wlr_device = input_device->wlr_device; |
@@ -471,6 +512,8 @@ static void handle_new_input(struct wl_listener *listener, void *data) { | |||
471 | input_manager_libinput_config_pointer(input_device); | 512 | input_manager_libinput_config_pointer(input_device); |
472 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) { | 513 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) { |
473 | input_manager_libinput_config_keyboard(input_device); | 514 | input_manager_libinput_config_keyboard(input_device); |
515 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_SWITCH) { | ||
516 | input_manager_libinput_config_switch(input_device); | ||
474 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_TOUCH) { | 517 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_TOUCH) { |
475 | input_manager_libinput_config_touch(input_device); | 518 | input_manager_libinput_config_touch(input_device); |
476 | } | 519 | } |
@@ -624,6 +667,8 @@ void input_manager_apply_input_config(struct input_config *input_config) { | |||
624 | input_manager_libinput_config_pointer(input_device); | 667 | input_manager_libinput_config_pointer(input_device); |
625 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) { | 668 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) { |
626 | input_manager_libinput_config_keyboard(input_device); | 669 | input_manager_libinput_config_keyboard(input_device); |
670 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_SWITCH) { | ||
671 | input_manager_libinput_config_switch(input_device); | ||
627 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_TOUCH) { | 672 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_TOUCH) { |
628 | input_manager_libinput_config_touch(input_device); | 673 | input_manager_libinput_config_touch(input_device); |
629 | } | 674 | } |
@@ -642,6 +687,8 @@ void input_manager_reset_input(struct sway_input_device *input_device) { | |||
642 | input_manager_libinput_reset_pointer(input_device); | 687 | input_manager_libinput_reset_pointer(input_device); |
643 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) { | 688 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) { |
644 | input_manager_libinput_reset_keyboard(input_device); | 689 | input_manager_libinput_reset_keyboard(input_device); |
690 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_SWITCH) { | ||
691 | input_manager_libinput_reset_switch(input_device); | ||
645 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_TOUCH) { | 692 | } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_TOUCH) { |
646 | input_manager_libinput_reset_touch(input_device); | 693 | input_manager_libinput_reset_touch(input_device); |
647 | } | 694 | } |
diff --git a/sway/input/seat.c b/sway/input/seat.c index 7fc87ee4..d58ff9e6 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "sway/input/input-manager.h" | 15 | #include "sway/input/input-manager.h" |
16 | #include "sway/input/keyboard.h" | 16 | #include "sway/input/keyboard.h" |
17 | #include "sway/input/seat.h" | 17 | #include "sway/input/seat.h" |
18 | #include "sway/input/switch.h" | ||
18 | #include "sway/ipc-server.h" | 19 | #include "sway/ipc-server.h" |
19 | #include "sway/layers.h" | 20 | #include "sway/layers.h" |
20 | #include "sway/output.h" | 21 | #include "sway/output.h" |
@@ -482,8 +483,8 @@ static void seat_update_capabilities(struct sway_seat *seat) { | |||
482 | case WLR_INPUT_DEVICE_TABLET_TOOL: | 483 | case WLR_INPUT_DEVICE_TABLET_TOOL: |
483 | caps |= WL_SEAT_CAPABILITY_POINTER; | 484 | caps |= WL_SEAT_CAPABILITY_POINTER; |
484 | break; | 485 | break; |
485 | case WLR_INPUT_DEVICE_TABLET_PAD: | ||
486 | case WLR_INPUT_DEVICE_SWITCH: | 486 | case WLR_INPUT_DEVICE_SWITCH: |
487 | case WLR_INPUT_DEVICE_TABLET_PAD: | ||
487 | break; | 488 | break; |
488 | } | 489 | } |
489 | } | 490 | } |
@@ -570,6 +571,15 @@ static void seat_configure_keyboard(struct sway_seat *seat, | |||
570 | } | 571 | } |
571 | } | 572 | } |
572 | 573 | ||
574 | static void seat_configure_switch(struct sway_seat *seat, | ||
575 | struct sway_seat_device *seat_device) { | ||
576 | if (!seat_device->switch_device) { | ||
577 | sway_switch_create(seat, seat_device); | ||
578 | } | ||
579 | seat_apply_input_config(seat, seat_device); | ||
580 | sway_switch_configure(seat_device->switch_device); | ||
581 | } | ||
582 | |||
573 | static void seat_configure_touch(struct sway_seat *seat, | 583 | static void seat_configure_touch(struct sway_seat *seat, |
574 | struct sway_seat_device *sway_device) { | 584 | struct sway_seat_device *sway_device) { |
575 | wlr_cursor_attach_input_device(seat->cursor->cursor, | 585 | wlr_cursor_attach_input_device(seat->cursor->cursor, |
@@ -611,6 +621,9 @@ void seat_configure_device(struct sway_seat *seat, | |||
611 | case WLR_INPUT_DEVICE_KEYBOARD: | 621 | case WLR_INPUT_DEVICE_KEYBOARD: |
612 | seat_configure_keyboard(seat, seat_device); | 622 | seat_configure_keyboard(seat, seat_device); |
613 | break; | 623 | break; |
624 | case WLR_INPUT_DEVICE_SWITCH: | ||
625 | seat_configure_switch(seat, seat_device); | ||
626 | break; | ||
614 | case WLR_INPUT_DEVICE_TOUCH: | 627 | case WLR_INPUT_DEVICE_TOUCH: |
615 | seat_configure_touch(seat, seat_device); | 628 | seat_configure_touch(seat, seat_device); |
616 | break; | 629 | break; |
@@ -620,9 +633,6 @@ void seat_configure_device(struct sway_seat *seat, | |||
620 | case WLR_INPUT_DEVICE_TABLET_PAD: | 633 | case WLR_INPUT_DEVICE_TABLET_PAD: |
621 | sway_log(SWAY_DEBUG, "TODO: configure tablet pad"); | 634 | sway_log(SWAY_DEBUG, "TODO: configure tablet pad"); |
622 | break; | 635 | break; |
623 | case WLR_INPUT_DEVICE_SWITCH: | ||
624 | sway_log(SWAY_DEBUG, "TODO: configure switch device"); | ||
625 | break; | ||
626 | } | 636 | } |
627 | } | 637 | } |
628 | 638 | ||
diff --git a/sway/input/switch.c b/sway/input/switch.c new file mode 100644 index 00000000..d56e6525 --- /dev/null +++ b/sway/input/switch.c | |||
@@ -0,0 +1,85 @@ | |||
1 | #include "sway/config.h" | ||
2 | #include "sway/desktop/transaction.h" | ||
3 | #include "sway/input/switch.h" | ||
4 | #include <wlr/types/wlr_idle.h> | ||
5 | #include "log.h" | ||
6 | |||
7 | struct sway_switch *sway_switch_create(struct sway_seat *seat, | ||
8 | struct sway_seat_device *device) { | ||
9 | struct sway_switch *switch_device = | ||
10 | calloc(1, sizeof(struct sway_switch)); | ||
11 | if (!sway_assert(switch_device, "could not allocate switch")) { | ||
12 | return NULL; | ||
13 | } | ||
14 | device->switch_device = switch_device; | ||
15 | switch_device->seat_device = device; | ||
16 | wl_list_init(&switch_device->switch_toggle.link); | ||
17 | sway_log(SWAY_DEBUG, "Allocated switch for device"); | ||
18 | |||
19 | return switch_device; | ||
20 | } | ||
21 | |||
22 | static void handle_switch_toggle(struct wl_listener *listener, void *data) { | ||
23 | struct sway_switch *sway_switch = | ||
24 | wl_container_of(listener, sway_switch, switch_toggle); | ||
25 | struct sway_seat* seat = sway_switch->seat_device->sway_seat; | ||
26 | struct wlr_seat *wlr_seat = seat->wlr_seat; | ||
27 | struct wlr_input_device *wlr_device = | ||
28 | sway_switch->seat_device->input_device->wlr_device; | ||
29 | |||
30 | wlr_idle_notify_activity(server.idle, wlr_seat); | ||
31 | bool input_inhibited = seat->exclusive_client != NULL; | ||
32 | |||
33 | char *device_identifier = input_device_get_identifier(wlr_device); | ||
34 | |||
35 | struct wlr_event_switch_toggle *event = data; | ||
36 | enum wlr_switch_type type = event->switch_type; | ||
37 | enum wlr_switch_state state = event->switch_state; | ||
38 | sway_log(SWAY_DEBUG, "%s: type %d state %d", device_identifier, type, state); | ||
39 | |||
40 | list_t *bindings = config->current_mode->switch_bindings; | ||
41 | for (int i = 0; i < bindings->length; ++i) { | ||
42 | struct sway_switch_binding *binding = bindings->items[i]; | ||
43 | if (binding->type != type) { | ||
44 | continue; | ||
45 | } | ||
46 | if (binding->state != WLR_SWITCH_STATE_TOGGLE && | ||
47 | binding->state != state) { | ||
48 | continue; | ||
49 | } | ||
50 | bool binding_locked = binding->flags & BINDING_LOCKED; | ||
51 | if (!binding_locked && input_inhibited) { | ||
52 | continue; | ||
53 | } | ||
54 | |||
55 | struct sway_binding *dummy_binding = calloc(1, sizeof(struct sway_binding)); | ||
56 | dummy_binding->type = BINDING_SWITCH; | ||
57 | dummy_binding->flags = binding->flags; | ||
58 | dummy_binding->command = binding->command; | ||
59 | |||
60 | seat_execute_command(seat, dummy_binding); | ||
61 | free(dummy_binding); | ||
62 | } | ||
63 | |||
64 | transaction_commit_dirty(); | ||
65 | |||
66 | free(device_identifier); | ||
67 | } | ||
68 | |||
69 | void sway_switch_configure(struct sway_switch *sway_switch) { | ||
70 | struct wlr_input_device *wlr_device = | ||
71 | sway_switch->seat_device->input_device->wlr_device; | ||
72 | wl_list_remove(&sway_switch->switch_toggle.link); | ||
73 | wl_signal_add(&wlr_device->switch_device->events.toggle, | ||
74 | &sway_switch->switch_toggle); | ||
75 | sway_switch->switch_toggle.notify = handle_switch_toggle; | ||
76 | sway_log(SWAY_DEBUG, "Configured switch for device"); | ||
77 | } | ||
78 | |||
79 | void sway_switch_destroy(struct sway_switch *sway_switch) { | ||
80 | if (!sway_switch) { | ||
81 | return; | ||
82 | } | ||
83 | wl_list_remove(&sway_switch->switch_toggle.link); | ||
84 | free(sway_switch); | ||
85 | } | ||