diff options
-rw-r--r-- | include/sway/commands.h | 5 | ||||
-rw-r--r-- | include/sway/config.h | 27 | ||||
-rw-r--r-- | include/sway/input/input-manager.h | 9 | ||||
-rw-r--r-- | include/sway/input/keyboard.h | 9 | ||||
-rw-r--r-- | include/sway/input/seat.h | 20 | ||||
-rw-r--r-- | sway/commands.c | 32 | ||||
-rw-r--r-- | sway/commands/input/seat.c | 28 | ||||
-rw-r--r-- | sway/commands/seat.c | 35 | ||||
-rw-r--r-- | sway/commands/seat/attach.c | 26 | ||||
-rw-r--r-- | sway/config.c | 144 | ||||
-rw-r--r-- | sway/input/cursor.c | 8 | ||||
-rw-r--r-- | sway/input/input-manager.c | 139 | ||||
-rw-r--r-- | sway/input/keyboard.c | 51 | ||||
-rw-r--r-- | sway/input/seat.c | 163 | ||||
-rw-r--r-- | sway/meson.build | 3 |
15 files changed, 534 insertions, 165 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index 75340e03..ce74e1ed 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -17,6 +17,7 @@ enum cmd_status { | |||
17 | CMD_BLOCK_BAR, | 17 | CMD_BLOCK_BAR, |
18 | CMD_BLOCK_BAR_COLORS, | 18 | CMD_BLOCK_BAR_COLORS, |
19 | CMD_BLOCK_INPUT, | 19 | CMD_BLOCK_INPUT, |
20 | CMD_BLOCK_SEAT, | ||
20 | CMD_BLOCK_COMMANDS, | 21 | CMD_BLOCK_COMMANDS, |
21 | CMD_BLOCK_IPC, | 22 | CMD_BLOCK_IPC, |
22 | CMD_BLOCK_IPC_EVENTS, | 23 | CMD_BLOCK_IPC_EVENTS, |
@@ -42,6 +43,7 @@ enum expected_args { | |||
42 | }; | 43 | }; |
43 | 44 | ||
44 | void input_cmd_apply(struct input_config *input); | 45 | void input_cmd_apply(struct input_config *input); |
46 | void seat_cmd_apply(struct seat_config *seat); | ||
45 | 47 | ||
46 | struct cmd_results *checkarg(int argc, const char *name, | 48 | struct cmd_results *checkarg(int argc, const char *name, |
47 | enum expected_args type, int val); | 49 | enum expected_args type, int val); |
@@ -111,6 +113,7 @@ sway_cmd cmd_gaps; | |||
111 | sway_cmd cmd_hide_edge_borders; | 113 | sway_cmd cmd_hide_edge_borders; |
112 | sway_cmd cmd_include; | 114 | sway_cmd cmd_include; |
113 | sway_cmd cmd_input; | 115 | sway_cmd cmd_input; |
116 | sway_cmd cmd_seat; | ||
114 | sway_cmd cmd_ipc; | 117 | sway_cmd cmd_ipc; |
115 | sway_cmd cmd_kill; | 118 | sway_cmd cmd_kill; |
116 | sway_cmd cmd_layout; | 119 | sway_cmd cmd_layout; |
@@ -193,6 +196,8 @@ sway_cmd input_cmd_pointer_accel; | |||
193 | sway_cmd input_cmd_scroll_method; | 196 | sway_cmd input_cmd_scroll_method; |
194 | sway_cmd input_cmd_tap; | 197 | sway_cmd input_cmd_tap; |
195 | 198 | ||
199 | sway_cmd seat_cmd_attach; | ||
200 | |||
196 | sway_cmd cmd_ipc_cmd; | 201 | sway_cmd cmd_ipc_cmd; |
197 | sway_cmd cmd_ipc_events; | 202 | sway_cmd cmd_ipc_events; |
198 | sway_cmd cmd_ipc_event_cmd; | 203 | sway_cmd cmd_ipc_event_cmd; |
diff --git a/include/sway/config.h b/include/sway/config.h index 9fcecfd6..5df5d61e 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -69,7 +69,22 @@ struct input_config { | |||
69 | 69 | ||
70 | bool capturable; | 70 | bool capturable; |
71 | struct wlr_box region; | 71 | struct wlr_box region; |
72 | char *seat; | 72 | }; |
73 | |||
74 | /** | ||
75 | * Options for misc device configurations that happen in the seat block | ||
76 | */ | ||
77 | struct seat_attachment_config { | ||
78 | char *identifier; | ||
79 | // TODO other things are configured here for some reason | ||
80 | }; | ||
81 | |||
82 | /** | ||
83 | * Options for multiseat and other misc device configurations | ||
84 | */ | ||
85 | struct seat_config { | ||
86 | char *name; | ||
87 | list_t *attachments; // list of seat_attachment configs | ||
73 | }; | 88 | }; |
74 | 89 | ||
75 | /** | 90 | /** |
@@ -260,6 +275,7 @@ struct sway_config { | |||
260 | list_t *pid_workspaces; | 275 | list_t *pid_workspaces; |
261 | list_t *output_configs; | 276 | list_t *output_configs; |
262 | list_t *input_configs; | 277 | list_t *input_configs; |
278 | list_t *seat_configs; | ||
263 | list_t *criteria; | 279 | list_t *criteria; |
264 | list_t *no_focus; | 280 | list_t *no_focus; |
265 | list_t *active_bar_modifiers; | 281 | list_t *active_bar_modifiers; |
@@ -358,9 +374,16 @@ struct cmd_results *check_security_config(); | |||
358 | int input_identifier_cmp(const void *item, const void *data); | 374 | int input_identifier_cmp(const void *item, const void *data); |
359 | struct input_config *new_input_config(const char* identifier); | 375 | struct input_config *new_input_config(const char* identifier); |
360 | void merge_input_config(struct input_config *dst, struct input_config *src); | 376 | void merge_input_config(struct input_config *dst, struct input_config *src); |
361 | void apply_input_config(struct input_config *ic, struct libinput_device *dev); | ||
362 | void free_input_config(struct input_config *ic); | 377 | void free_input_config(struct input_config *ic); |
363 | 378 | ||
379 | int seat_name_cmp(const void *item, const void *data); | ||
380 | struct seat_config *new_seat_config(const char* name); | ||
381 | void merge_seat_config(struct seat_config *dst, struct seat_config *src); | ||
382 | void free_seat_config(struct seat_config *ic); | ||
383 | struct seat_attachment_config *seat_attachment_config_new(); | ||
384 | struct seat_attachment_config *seat_config_get_attachment( | ||
385 | struct seat_config *seat_config, char *identifier); | ||
386 | |||
364 | int output_name_cmp(const void *item, const void *data); | 387 | int output_name_cmp(const void *item, const void *data); |
365 | void merge_output_config(struct output_config *dst, struct output_config *src); | 388 | void merge_output_config(struct output_config *dst, struct output_config *src); |
366 | /** Sets up a WLC output handle based on a given output_config. | 389 | /** Sets up a WLC output handle based on a given output_config. |
diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 7d7c463f..cdcffab6 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h | |||
@@ -6,6 +6,7 @@ | |||
6 | #include "list.h" | 6 | #include "list.h" |
7 | 7 | ||
8 | extern struct input_config *current_input_config; | 8 | extern struct input_config *current_input_config; |
9 | extern struct seat_config *current_seat_config; | ||
9 | 10 | ||
10 | /** | 11 | /** |
11 | * The global singleton input manager | 12 | * The global singleton input manager |
@@ -17,7 +18,6 @@ struct sway_input_device { | |||
17 | char *identifier; | 18 | char *identifier; |
18 | struct wlr_input_device *wlr_device; | 19 | struct wlr_input_device *wlr_device; |
19 | struct input_config *config; | 20 | struct input_config *config; |
20 | struct sway_keyboard *keyboard; // managed by the seat | ||
21 | struct wl_list link; | 21 | struct wl_list link; |
22 | }; | 22 | }; |
23 | 23 | ||
@@ -40,7 +40,10 @@ void sway_input_manager_set_focus(struct sway_input_manager *input, | |||
40 | 40 | ||
41 | void sway_input_manager_configure_xcursor(struct sway_input_manager *input); | 41 | void sway_input_manager_configure_xcursor(struct sway_input_manager *input); |
42 | 42 | ||
43 | void sway_input_manager_apply_config(struct sway_input_manager *input, | 43 | void sway_input_manager_apply_input_config(struct sway_input_manager *input, |
44 | struct input_config *config); | 44 | struct input_config *input_config); |
45 | |||
46 | void sway_input_manager_apply_seat_config(struct sway_input_manager *input, | ||
47 | struct seat_config *seat_config); | ||
45 | 48 | ||
46 | #endif | 49 | #endif |
diff --git a/include/sway/input/keyboard.h b/include/sway/input/keyboard.h index 881805b4..89cde3fa 100644 --- a/include/sway/input/keyboard.h +++ b/include/sway/input/keyboard.h | |||
@@ -1,15 +1,18 @@ | |||
1 | #include "sway/input/seat.h" | 1 | #include "sway/input/seat.h" |
2 | 2 | ||
3 | struct sway_keyboard { | 3 | struct sway_keyboard { |
4 | struct sway_seat *seat; | 4 | struct sway_seat_device *seat_device; |
5 | struct sway_input_device *device; | ||
6 | struct wl_list link; // sway_seat::keyboards | 5 | struct wl_list link; // sway_seat::keyboards |
7 | 6 | ||
7 | struct xkb_keymap *keymap; | ||
8 | |||
8 | struct wl_listener keyboard_key; | 9 | struct wl_listener keyboard_key; |
9 | struct wl_listener keyboard_modifiers; | 10 | struct wl_listener keyboard_modifiers; |
10 | }; | 11 | }; |
11 | 12 | ||
12 | struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, | 13 | struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, |
13 | struct sway_input_device *device); | 14 | struct sway_seat_device *device); |
15 | |||
16 | void sway_keyboard_configure(struct sway_keyboard *keyboard); | ||
14 | 17 | ||
15 | void sway_keyboard_destroy(struct sway_keyboard *keyboard); | 18 | void sway_keyboard_destroy(struct sway_keyboard *keyboard); |
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index bd94a357..db69f83e 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h | |||
@@ -4,16 +4,25 @@ | |||
4 | #include <wlr/types/wlr_seat.h> | 4 | #include <wlr/types/wlr_seat.h> |
5 | #include "sway/input/input-manager.h" | 5 | #include "sway/input/input-manager.h" |
6 | 6 | ||
7 | struct sway_seat_device { | ||
8 | struct sway_seat *sway_seat; | ||
9 | struct sway_input_device *input_device; | ||
10 | struct sway_keyboard *keyboard; | ||
11 | struct seat_attachment_config *attachment_config; | ||
12 | struct wl_list link; // sway_seat::devices | ||
13 | }; | ||
14 | |||
7 | struct sway_seat { | 15 | struct sway_seat { |
8 | struct wlr_seat *seat; | 16 | struct wlr_seat *wlr_seat; |
17 | struct seat_config *config; | ||
9 | struct sway_cursor *cursor; | 18 | struct sway_cursor *cursor; |
10 | struct sway_input_manager *input; | 19 | struct sway_input_manager *input; |
11 | swayc_t *focus; | 20 | swayc_t *focus; |
12 | 21 | ||
13 | list_t *devices; | ||
14 | |||
15 | struct wl_listener focus_destroy; | 22 | struct wl_listener focus_destroy; |
16 | 23 | ||
24 | struct wl_list devices; // sway_seat_device::link | ||
25 | |||
17 | struct wl_list link; // input_manager::seats | 26 | struct wl_list link; // input_manager::seats |
18 | }; | 27 | }; |
19 | 28 | ||
@@ -23,6 +32,9 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, | |||
23 | void sway_seat_add_device(struct sway_seat *seat, | 32 | void sway_seat_add_device(struct sway_seat *seat, |
24 | struct sway_input_device *device); | 33 | struct sway_input_device *device); |
25 | 34 | ||
35 | void sway_seat_configure_device(struct sway_seat *seat, | ||
36 | struct sway_input_device *device); | ||
37 | |||
26 | void sway_seat_remove_device(struct sway_seat *seat, | 38 | void sway_seat_remove_device(struct sway_seat *seat, |
27 | struct sway_input_device *device); | 39 | struct sway_input_device *device); |
28 | 40 | ||
@@ -30,4 +42,6 @@ void sway_seat_configure_xcursor(struct sway_seat *seat); | |||
30 | 42 | ||
31 | void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container); | 43 | void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container); |
32 | 44 | ||
45 | void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); | ||
46 | |||
33 | #endif | 47 | #endif |
diff --git a/sway/commands.c b/sway/commands.c index 6645436a..e003e06d 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -71,7 +71,24 @@ void input_cmd_apply(struct input_config *input) { | |||
71 | } | 71 | } |
72 | 72 | ||
73 | current_input_config = input; | 73 | current_input_config = input; |
74 | sway_input_manager_apply_config(input_manager, input); | 74 | sway_input_manager_apply_input_config(input_manager, input); |
75 | } | ||
76 | |||
77 | void seat_cmd_apply(struct seat_config *seat) { | ||
78 | int i; | ||
79 | i = list_seq_find(config->seat_configs, seat_name_cmp, seat->name); | ||
80 | if (i >= 0) { | ||
81 | // merge existing config | ||
82 | struct seat_config *sc = config->seat_configs->items[i]; | ||
83 | merge_seat_config(sc, seat); | ||
84 | free_seat_config(seat); | ||
85 | seat = sc; | ||
86 | } else { | ||
87 | list_add(config->seat_configs, seat); | ||
88 | } | ||
89 | |||
90 | current_seat_config = seat; | ||
91 | sway_input_manager_apply_seat_config(input_manager, seat); | ||
75 | } | 92 | } |
76 | 93 | ||
77 | /** | 94 | /** |
@@ -115,6 +132,7 @@ static struct cmd_handler handlers[] = { | |||
115 | { "exit", cmd_exit }, | 132 | { "exit", cmd_exit }, |
116 | { "include", cmd_include }, | 133 | { "include", cmd_include }, |
117 | { "input", cmd_input }, | 134 | { "input", cmd_input }, |
135 | { "seat", cmd_seat }, | ||
118 | }; | 136 | }; |
119 | 137 | ||
120 | static int handler_compare(const void *_a, const void *_b) { | 138 | static int handler_compare(const void *_a, const void *_b) { |
@@ -135,19 +153,27 @@ static struct cmd_handler input_handlers[] = { | |||
135 | { "natural_scroll", input_cmd_natural_scroll }, | 153 | { "natural_scroll", input_cmd_natural_scroll }, |
136 | { "pointer_accel", input_cmd_pointer_accel }, | 154 | { "pointer_accel", input_cmd_pointer_accel }, |
137 | { "scroll_method", input_cmd_scroll_method }, | 155 | { "scroll_method", input_cmd_scroll_method }, |
138 | { "seat", input_cmd_seat }, | ||
139 | { "tap", input_cmd_tap }, | 156 | { "tap", input_cmd_tap }, |
140 | }; | 157 | }; |
141 | 158 | ||
159 | // must be in order for the bsearch | ||
160 | static struct cmd_handler seat_handlers[] = { | ||
161 | { "attach", seat_cmd_attach }, | ||
162 | }; | ||
163 | |||
142 | static struct cmd_handler *find_handler(char *line, enum cmd_status block) { | 164 | static struct cmd_handler *find_handler(char *line, enum cmd_status block) { |
143 | struct cmd_handler d = { .command=line }; | 165 | struct cmd_handler d = { .command=line }; |
144 | struct cmd_handler *res = NULL; | 166 | struct cmd_handler *res = NULL; |
145 | sway_log(L_DEBUG, "find_handler(%s) %d", line, block == CMD_BLOCK_INPUT); | 167 | sway_log(L_DEBUG, "find_handler(%s) %d", line, block == CMD_BLOCK_SEAT); |
146 | 168 | ||
147 | if (block == CMD_BLOCK_INPUT) { | 169 | if (block == CMD_BLOCK_INPUT) { |
148 | res = bsearch(&d, input_handlers, | 170 | res = bsearch(&d, input_handlers, |
149 | sizeof(input_handlers) / sizeof(struct cmd_handler), | 171 | sizeof(input_handlers) / sizeof(struct cmd_handler), |
150 | sizeof(struct cmd_handler), handler_compare); | 172 | sizeof(struct cmd_handler), handler_compare); |
173 | } else if (block == CMD_BLOCK_SEAT) { | ||
174 | res = bsearch(&d, seat_handlers, | ||
175 | sizeof(seat_handlers) / sizeof(struct cmd_handler), | ||
176 | sizeof(struct cmd_handler), handler_compare); | ||
151 | } else { | 177 | } else { |
152 | res = bsearch(&d, handlers, | 178 | res = bsearch(&d, handlers, |
153 | sizeof(handlers) / sizeof(struct cmd_handler), | 179 | sizeof(handlers) / sizeof(struct cmd_handler), |
diff --git a/sway/commands/input/seat.c b/sway/commands/input/seat.c deleted file mode 100644 index 9d86ac0e..00000000 --- a/sway/commands/input/seat.c +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include <string.h> | ||
3 | #include <strings.h> | ||
4 | #include "sway/commands.h" | ||
5 | #include "sway/input/input-manager.h" | ||
6 | #include "log.h" | ||
7 | |||
8 | struct cmd_results *input_cmd_seat(int argc, char **argv) { | ||
9 | sway_log(L_DEBUG, "seat for device: %d %s", | ||
10 | current_input_config==NULL, current_input_config->identifier); | ||
11 | struct cmd_results *error = NULL; | ||
12 | if ((error = checkarg(argc, "seat", EXPECTED_AT_LEAST, 1))) { | ||
13 | return error; | ||
14 | } | ||
15 | if (!current_input_config) { | ||
16 | return cmd_results_new(CMD_FAILURE, "seat", | ||
17 | "No input device defined."); | ||
18 | } | ||
19 | struct input_config *new_config = | ||
20 | new_input_config(current_input_config->identifier); | ||
21 | |||
22 | // TODO validate seat name | ||
23 | free(new_config->seat); | ||
24 | new_config->seat = strdup(argv[0]); | ||
25 | |||
26 | input_cmd_apply(new_config); | ||
27 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
28 | } | ||
diff --git a/sway/commands/seat.c b/sway/commands/seat.c new file mode 100644 index 00000000..4f9e259b --- /dev/null +++ b/sway/commands/seat.c | |||
@@ -0,0 +1,35 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | #include "log.h" | ||
6 | |||
7 | struct cmd_results *cmd_seat(int argc, char **argv) { | ||
8 | struct cmd_results *error = NULL; | ||
9 | if ((error = checkarg(argc, "seat", EXPECTED_AT_LEAST, 2))) { | ||
10 | return error; | ||
11 | } | ||
12 | |||
13 | if (config->reading && strcmp("{", argv[1]) == 0) { | ||
14 | current_seat_config = new_seat_config(argv[0]); | ||
15 | sway_log(L_DEBUG, "entering seat block: %s", current_seat_config->name); | ||
16 | return cmd_results_new(CMD_BLOCK_SEAT, NULL, NULL); | ||
17 | } | ||
18 | |||
19 | if (argc > 2) { | ||
20 | int argc_new = argc-2; | ||
21 | char **argv_new = argv+2; | ||
22 | |||
23 | struct cmd_results *res; | ||
24 | current_seat_config = new_seat_config(argv[0]); | ||
25 | if (strcasecmp("attach", argv[1]) == 0) { | ||
26 | res = seat_cmd_attach(argc_new, argv_new); | ||
27 | } else { | ||
28 | res = cmd_results_new(CMD_INVALID, "seat <name>", "Unknown command %s", argv[1]); | ||
29 | } | ||
30 | current_seat_config = NULL; | ||
31 | return res; | ||
32 | } | ||
33 | |||
34 | return cmd_results_new(CMD_BLOCK_SEAT, NULL, NULL); | ||
35 | } | ||
diff --git a/sway/commands/seat/attach.c b/sway/commands/seat/attach.c new file mode 100644 index 00000000..996c1bda --- /dev/null +++ b/sway/commands/seat/attach.c | |||
@@ -0,0 +1,26 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include <string.h> | ||
3 | #include <strings.h> | ||
4 | #include "sway/input/input-manager.h" | ||
5 | #include "sway/commands.h" | ||
6 | #include "sway/config.h" | ||
7 | #include "log.h" | ||
8 | #include "stringop.h" | ||
9 | |||
10 | struct cmd_results *seat_cmd_attach(int argc, char **argv) { | ||
11 | struct cmd_results *error = NULL; | ||
12 | if ((error = checkarg(argc, "attach", EXPECTED_AT_LEAST, 1))) { | ||
13 | return error; | ||
14 | } | ||
15 | if (!current_seat_config) { | ||
16 | return cmd_results_new(CMD_FAILURE, "attach", "No seat defined"); | ||
17 | } | ||
18 | |||
19 | struct seat_config *new_config = new_seat_config(current_seat_config->name); | ||
20 | struct seat_attachment_config *new_attachment = seat_attachment_config_new(); | ||
21 | new_attachment->identifier = strdup(argv[0]); | ||
22 | list_add(new_config->attachments, new_attachment); | ||
23 | |||
24 | seat_cmd_apply(new_config); | ||
25 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
26 | } | ||
diff --git a/sway/config.c b/sway/config.c index b77b8b4b..52633ad8 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -45,6 +45,7 @@ static void config_defaults(struct sway_config *config) { | |||
45 | if (!(config->criteria = create_list())) goto cleanup; | 45 | if (!(config->criteria = create_list())) goto cleanup; |
46 | if (!(config->no_focus = create_list())) goto cleanup; | 46 | if (!(config->no_focus = create_list())) goto cleanup; |
47 | if (!(config->input_configs = create_list())) goto cleanup; | 47 | if (!(config->input_configs = create_list())) goto cleanup; |
48 | if (!(config->seat_configs = create_list())) goto cleanup; | ||
48 | if (!(config->output_configs = create_list())) goto cleanup; | 49 | if (!(config->output_configs = create_list())) goto cleanup; |
49 | 50 | ||
50 | if (!(config->cmd_queue = create_list())) goto cleanup; | 51 | if (!(config->cmd_queue = create_list())) goto cleanup; |
@@ -258,9 +259,7 @@ struct input_config *new_input_config(const char* identifier) { | |||
258 | 259 | ||
259 | void merge_input_config(struct input_config *dst, struct input_config *src) { | 260 | void merge_input_config(struct input_config *dst, struct input_config *src) { |
260 | if (src->identifier) { | 261 | if (src->identifier) { |
261 | if (dst->identifier) { | 262 | free(dst->identifier); |
262 | free(dst->identifier); | ||
263 | } | ||
264 | dst->identifier = strdup(src->identifier); | 263 | dst->identifier = strdup(src->identifier); |
265 | } | 264 | } |
266 | if (src->accel_profile != INT_MIN) { | 265 | if (src->accel_profile != INT_MIN) { |
@@ -300,7 +299,6 @@ void free_input_config(struct input_config *ic) { | |||
300 | return; | 299 | return; |
301 | } | 300 | } |
302 | free(ic->identifier); | 301 | free(ic->identifier); |
303 | free(ic->seat); | ||
304 | free(ic); | 302 | free(ic); |
305 | } | 303 | } |
306 | 304 | ||
@@ -310,6 +308,128 @@ int input_identifier_cmp(const void *item, const void *data) { | |||
310 | return strcmp(ic->identifier, identifier); | 308 | return strcmp(ic->identifier, identifier); |
311 | } | 309 | } |
312 | 310 | ||
311 | struct seat_config *new_seat_config(const char* name) { | ||
312 | struct seat_config *seat = calloc(1, sizeof(struct seat_config)); | ||
313 | if (!seat) { | ||
314 | sway_log(L_DEBUG, "Unable to allocate seat config"); | ||
315 | return NULL; | ||
316 | } | ||
317 | |||
318 | sway_log(L_DEBUG, "new_seat_config(%s)", name); | ||
319 | seat->name = strdup(name); | ||
320 | if (!sway_assert(seat->name, "could not allocate name for seat")) { | ||
321 | return NULL; | ||
322 | } | ||
323 | |||
324 | seat->attachments = create_list(); | ||
325 | if (!sway_assert(seat->attachments, | ||
326 | "could not allocate seat attachments list")) { | ||
327 | return NULL; | ||
328 | } | ||
329 | |||
330 | return seat; | ||
331 | } | ||
332 | |||
333 | struct seat_attachment_config *seat_attachment_config_new() { | ||
334 | struct seat_attachment_config *attachment = | ||
335 | calloc(1, sizeof(struct seat_attachment_config)); | ||
336 | if (!attachment) { | ||
337 | sway_log(L_DEBUG, "cannot allocate attachment config"); | ||
338 | return NULL; | ||
339 | } | ||
340 | return attachment; | ||
341 | } | ||
342 | |||
343 | static void seat_attachment_config_free( | ||
344 | struct seat_attachment_config *attachment) { | ||
345 | free(attachment->identifier); | ||
346 | free(attachment); | ||
347 | return; | ||
348 | } | ||
349 | |||
350 | static struct seat_attachment_config *seat_attachment_config_copy( | ||
351 | struct seat_attachment_config *attachment) { | ||
352 | struct seat_attachment_config *copy = seat_attachment_config_new(); | ||
353 | if (!copy) { | ||
354 | return NULL; | ||
355 | } | ||
356 | |||
357 | copy->identifier = strdup(attachment->identifier); | ||
358 | |||
359 | return copy; | ||
360 | } | ||
361 | |||
362 | static void merge_seat_attachment_config(struct seat_attachment_config *dest, | ||
363 | struct seat_attachment_config *source) { | ||
364 | // nothing to merge yet, but there will be some day | ||
365 | } | ||
366 | |||
367 | void merge_seat_config(struct seat_config *dest, struct seat_config *source) { | ||
368 | if (source->name) { | ||
369 | free(dest->name); | ||
370 | dest->name = strdup(source->name); | ||
371 | } | ||
372 | |||
373 | for (int i = 0; i < source->attachments->length; ++i) { | ||
374 | struct seat_attachment_config *source_attachment = | ||
375 | source->attachments->items[i]; | ||
376 | bool found = false; | ||
377 | for (int j = 0; j < dest->attachments->length; ++j) { | ||
378 | struct seat_attachment_config *dest_attachment = | ||
379 | dest->attachments->items[j]; | ||
380 | if (strcmp(source_attachment->identifier, | ||
381 | dest_attachment->identifier) == 0) { | ||
382 | merge_seat_attachment_config(dest_attachment, | ||
383 | source_attachment); | ||
384 | found = true; | ||
385 | } | ||
386 | } | ||
387 | |||
388 | if (!found) { | ||
389 | struct seat_attachment_config *copy = | ||
390 | seat_attachment_config_copy(source_attachment); | ||
391 | if (copy) { | ||
392 | list_add(dest->attachments, copy); | ||
393 | } | ||
394 | } | ||
395 | } | ||
396 | } | ||
397 | |||
398 | void free_seat_config(struct seat_config *seat) { | ||
399 | if (!seat) { | ||
400 | return; | ||
401 | } | ||
402 | |||
403 | free(seat->name); | ||
404 | for (int i = 0; i < seat->attachments->length; ++i) { | ||
405 | struct seat_attachment_config *attachment = | ||
406 | seat->attachments->items[i]; | ||
407 | seat_attachment_config_free(attachment); | ||
408 | } | ||
409 | |||
410 | list_free(seat->attachments); | ||
411 | free(seat); | ||
412 | } | ||
413 | |||
414 | int seat_name_cmp(const void *item, const void *data) { | ||
415 | const struct seat_config *sc = item; | ||
416 | const char *name = data; | ||
417 | return strcmp(sc->name, name); | ||
418 | } | ||
419 | |||
420 | struct seat_attachment_config *seat_config_get_attachment( | ||
421 | struct seat_config *seat_config, char *identifier) { | ||
422 | for (int i = 0; i < seat_config->attachments->length; ++i) { | ||
423 | struct seat_attachment_config *attachment = | ||
424 | seat_config->attachments->items[i]; | ||
425 | if (strcmp(attachment->identifier, identifier) == 0) { | ||
426 | return attachment; | ||
427 | } | ||
428 | } | ||
429 | |||
430 | return NULL; | ||
431 | } | ||
432 | |||
313 | bool load_main_config(const char *file, bool is_active) { | 433 | bool load_main_config(const char *file, bool is_active) { |
314 | char *path; | 434 | char *path; |
315 | if (file != NULL) { | 435 | if (file != NULL) { |
@@ -368,7 +488,7 @@ bool load_main_config(const char *file, bool is_active) { | |||
368 | char *_path = secconfigs->items[i]; | 488 | char *_path = secconfigs->items[i]; |
369 | if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || | 489 | if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || |
370 | (((s.st_mode & 0777) != 0644) && | 490 | (((s.st_mode & 0777) != 0644) && |
371 | (s.st_mode & 0777) != 0444)) { | 491 | (s.st_mode & 0777) != 0444)) { |
372 | sway_log(L_ERROR, | 492 | sway_log(L_ERROR, |
373 | "Refusing to load %s - it must be owned by root " | 493 | "Refusing to load %s - it must be owned by root " |
374 | "and mode 644 or 444", _path); | 494 | "and mode 644 or 444", _path); |
@@ -547,6 +667,14 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
547 | } | 667 | } |
548 | break; | 668 | break; |
549 | 669 | ||
670 | case CMD_BLOCK_SEAT: | ||
671 | if (block == CMD_BLOCK_END) { | ||
672 | block = CMD_BLOCK_SEAT; | ||
673 | } else { | ||
674 | sway_log(L_ERROR, "Invalid block '%s'", line); | ||
675 | } | ||
676 | break; | ||
677 | |||
550 | case CMD_BLOCK_BAR: | 678 | case CMD_BLOCK_BAR: |
551 | if (block == CMD_BLOCK_END) { | 679 | if (block == CMD_BLOCK_END) { |
552 | block = CMD_BLOCK_BAR; | 680 | block = CMD_BLOCK_BAR; |
@@ -601,6 +729,12 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
601 | block = CMD_BLOCK_END; | 729 | block = CMD_BLOCK_END; |
602 | break; | 730 | break; |
603 | 731 | ||
732 | case CMD_BLOCK_SEAT: | ||
733 | sway_log(L_DEBUG, "End of seat block"); | ||
734 | current_seat_config = NULL; | ||
735 | block = CMD_BLOCK_END; | ||
736 | break; | ||
737 | |||
604 | case CMD_BLOCK_BAR: | 738 | case CMD_BLOCK_BAR: |
605 | sway_log(L_DEBUG, "End of bar block"); | 739 | sway_log(L_DEBUG, "End of bar block"); |
606 | config->current_bar = NULL; | 740 | config->current_bar = NULL; |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 217c2ddb..3aa2d1bc 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -24,7 +24,7 @@ static void cursor_update_position(struct sway_cursor *cursor) { | |||
24 | 24 | ||
25 | static void cursor_send_pointer_motion(struct sway_cursor *cursor, | 25 | static void cursor_send_pointer_motion(struct sway_cursor *cursor, |
26 | uint32_t time) { | 26 | uint32_t time) { |
27 | struct wlr_seat *seat = cursor->seat->seat; | 27 | struct wlr_seat *seat = cursor->seat->wlr_seat; |
28 | struct wlr_surface *surface = NULL; | 28 | struct wlr_surface *surface = NULL; |
29 | double sx, sy; | 29 | double sx, sy; |
30 | swayc_t *swayc = | 30 | swayc_t *swayc = |
@@ -72,7 +72,7 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { | |||
72 | sway_seat_set_focus(cursor->seat, swayc); | 72 | sway_seat_set_focus(cursor->seat, swayc); |
73 | } | 73 | } |
74 | 74 | ||
75 | wlr_seat_pointer_notify_button(cursor->seat->seat, event->time_msec, | 75 | wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, |
76 | event->button, event->state); | 76 | event->button, event->state); |
77 | } | 77 | } |
78 | 78 | ||
@@ -80,7 +80,7 @@ static void handle_cursor_axis(struct wl_listener *listener, void *data) { | |||
80 | struct sway_cursor *cursor = | 80 | struct sway_cursor *cursor = |
81 | wl_container_of(listener, cursor, axis); | 81 | wl_container_of(listener, cursor, axis); |
82 | struct wlr_event_pointer_axis *event = data; | 82 | struct wlr_event_pointer_axis *event = data; |
83 | wlr_seat_pointer_notify_axis(cursor->seat->seat, event->time_msec, | 83 | wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, |
84 | event->orientation, event->delta); | 84 | event->orientation, event->delta); |
85 | } | 85 | } |
86 | 86 | ||
@@ -173,7 +173,7 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { | |||
173 | wl_signal_add(&wlr_cursor->events.tablet_tool_tip, &cursor->tool_tip); | 173 | wl_signal_add(&wlr_cursor->events.tablet_tool_tip, &cursor->tool_tip); |
174 | cursor->tool_tip.notify = handle_tool_tip; | 174 | cursor->tool_tip.notify = handle_tool_tip; |
175 | 175 | ||
176 | wl_signal_add(&seat->seat->events.request_set_cursor, | 176 | wl_signal_add(&seat->wlr_seat->events.request_set_cursor, |
177 | &cursor->request_set_cursor); | 177 | &cursor->request_set_cursor); |
178 | cursor->request_set_cursor.notify = handle_request_set_cursor; | 178 | cursor->request_set_cursor.notify = handle_request_set_cursor; |
179 | 179 | ||
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index b07a733e..1950b6d9 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c | |||
@@ -18,12 +18,13 @@ static const char *default_seat = "seat0"; | |||
18 | struct sway_input_manager *input_manager; | 18 | struct sway_input_manager *input_manager; |
19 | 19 | ||
20 | struct input_config *current_input_config = NULL; | 20 | struct input_config *current_input_config = NULL; |
21 | struct seat_config *current_seat_config = NULL; | ||
21 | 22 | ||
22 | static struct sway_seat *input_manager_get_seat( | 23 | static struct sway_seat *input_manager_get_seat( |
23 | struct sway_input_manager *input, const char *seat_name) { | 24 | struct sway_input_manager *input, const char *seat_name) { |
24 | struct sway_seat *seat = NULL; | 25 | struct sway_seat *seat = NULL; |
25 | wl_list_for_each(seat, &input->seats, link) { | 26 | wl_list_for_each(seat, &input->seats, link) { |
26 | if (strcmp(seat->seat->name, seat_name) == 0) { | 27 | if (strcmp(seat->wlr_seat->name, seat_name) == 0) { |
27 | return seat; | 28 | return seat; |
28 | } | 29 | } |
29 | } | 30 | } |
@@ -58,56 +59,88 @@ static char *get_device_identifier(struct wlr_input_device *device) { | |||
58 | return identifier; | 59 | return identifier; |
59 | } | 60 | } |
60 | 61 | ||
61 | static struct sway_input_device *input_sway_device_from_wlr(struct sway_input_manager *input, | 62 | static struct sway_input_device *input_sway_device_from_wlr( |
62 | struct wlr_input_device *device) { | 63 | struct sway_input_manager *input, struct wlr_input_device *device) { |
63 | struct sway_input_device *sway_device = NULL; | 64 | struct sway_input_device *input_device = NULL; |
64 | wl_list_for_each(sway_device, &input->devices, link) { | 65 | wl_list_for_each(input_device, &input->devices, link) { |
65 | if (sway_device->wlr_device == device) { | 66 | if (input_device->wlr_device == device) { |
66 | return sway_device; | 67 | return input_device; |
67 | } | 68 | } |
68 | } | 69 | } |
69 | return NULL; | 70 | return NULL; |
70 | } | 71 | } |
71 | 72 | ||
72 | static struct sway_input_device *input_sway_device_from_config(struct sway_input_manager *input, | 73 | static struct sway_input_device *input_sway_device_from_config( |
73 | struct input_config *config) { | 74 | struct sway_input_manager *input, struct input_config *config) { |
74 | struct sway_input_device *sway_device = NULL; | 75 | struct sway_input_device *input_device = NULL; |
75 | wl_list_for_each(sway_device, &input->devices, link) { | 76 | wl_list_for_each(input_device, &input->devices, link) { |
76 | if (strcmp(sway_device->identifier, config->identifier) == 0) { | 77 | if (strcmp(input_device->identifier, config->identifier) == 0) { |
77 | return sway_device; | 78 | return input_device; |
78 | } | 79 | } |
79 | } | 80 | } |
80 | return NULL; | 81 | return NULL; |
81 | } | 82 | } |
82 | 83 | ||
84 | static struct sway_input_device *input_sway_device_from_identifier( | ||
85 | struct sway_input_manager *input, char *identifier) { | ||
86 | struct sway_input_device *input_device = NULL; | ||
87 | wl_list_for_each(input_device, &input->devices, link) { | ||
88 | if (strcmp(input_device->identifier, identifier) == 0) { | ||
89 | return input_device; | ||
90 | } | ||
91 | } | ||
92 | return NULL; | ||
93 | } | ||
94 | |||
95 | static bool input_has_seat_configuration(struct sway_input_manager *input) { | ||
96 | struct sway_seat *seat = NULL; | ||
97 | wl_list_for_each(seat, &input->seats, link) { | ||
98 | if (seat->config) { | ||
99 | return true; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | return false; | ||
104 | } | ||
105 | |||
83 | static void input_add_notify(struct wl_listener *listener, void *data) { | 106 | static void input_add_notify(struct wl_listener *listener, void *data) { |
84 | struct sway_input_manager *input = | 107 | struct sway_input_manager *input = |
85 | wl_container_of(listener, input, input_add); | 108 | wl_container_of(listener, input, input_add); |
86 | struct wlr_input_device *device = data; | 109 | struct wlr_input_device *device = data; |
87 | 110 | ||
88 | struct sway_input_device *sway_device = | 111 | struct sway_input_device *input_device = |
89 | calloc(1, sizeof(struct sway_input_device)); | 112 | calloc(1, sizeof(struct sway_input_device)); |
90 | if (!sway_assert(sway_device, "could not allocate input device")) { | 113 | if (!sway_assert(input_device, "could not allocate input device")) { |
91 | return; | 114 | return; |
92 | } | 115 | } |
93 | 116 | ||
94 | sway_device->wlr_device = device; | 117 | input_device->wlr_device = device; |
95 | sway_device->identifier = get_device_identifier(device); | 118 | input_device->identifier = get_device_identifier(device); |
96 | wl_list_insert(&input->devices, &sway_device->link); | 119 | wl_list_insert(&input->devices, &input_device->link); |
97 | 120 | ||
98 | // find config | 121 | // find config |
99 | for (int i = 0; i < config->input_configs->length; ++i) { | 122 | for (int i = 0; i < config->input_configs->length; ++i) { |
100 | struct input_config *input_config = config->input_configs->items[i]; | 123 | struct input_config *input_config = config->input_configs->items[i]; |
101 | if (strcmp(input_config->identifier, sway_device->identifier) == 0) { | 124 | if (strcmp(input_config->identifier, input_device->identifier) == 0) { |
102 | sway_device->config = input_config; | 125 | input_device->config = input_config; |
103 | break; | 126 | break; |
104 | } | 127 | } |
105 | } | 128 | } |
106 | 129 | ||
107 | const char *seat_name = | 130 | struct sway_seat *seat = NULL; |
108 | (sway_device->config ? sway_device->config->seat : default_seat); | 131 | if (!input_has_seat_configuration(input)) { |
109 | struct sway_seat *seat = input_manager_get_seat(input, seat_name); | 132 | seat = input_manager_get_seat(input, default_seat); |
110 | sway_seat_add_device(seat, sway_device); | 133 | sway_seat_add_device(seat, input_device); |
134 | return; | ||
135 | } | ||
136 | |||
137 | wl_list_for_each(seat, &input->seats, link) { | ||
138 | if (seat->config && | ||
139 | (seat_config_get_attachment(seat->config, input_device->identifier) || | ||
140 | seat_config_get_attachment(seat->config, "*"))) { | ||
141 | sway_seat_add_device(seat, input_device); | ||
142 | } | ||
143 | } | ||
111 | } | 144 | } |
112 | 145 | ||
113 | static void input_remove_notify(struct wl_listener *listener, void *data) { | 146 | static void input_remove_notify(struct wl_listener *listener, void *data) { |
@@ -115,21 +148,21 @@ static void input_remove_notify(struct wl_listener *listener, void *data) { | |||
115 | wl_container_of(listener, input, input_remove); | 148 | wl_container_of(listener, input, input_remove); |
116 | struct wlr_input_device *device = data; | 149 | struct wlr_input_device *device = data; |
117 | 150 | ||
118 | struct sway_input_device *sway_device = | 151 | struct sway_input_device *input_device = |
119 | input_sway_device_from_wlr(input, device); | 152 | input_sway_device_from_wlr(input, device); |
120 | 153 | ||
121 | if (!sway_assert(sway_device, "could not find sway device")) { | 154 | if (!sway_assert(input_device, "could not find sway device")) { |
122 | return; | 155 | return; |
123 | } | 156 | } |
124 | 157 | ||
125 | struct sway_seat *seat = NULL; | 158 | struct sway_seat *seat = NULL; |
126 | wl_list_for_each(seat, &input->seats, link) { | 159 | wl_list_for_each(seat, &input->seats, link) { |
127 | sway_seat_remove_device(seat, sway_device); | 160 | sway_seat_remove_device(seat, input_device); |
128 | } | 161 | } |
129 | 162 | ||
130 | wl_list_remove(&sway_device->link); | 163 | wl_list_remove(&input_device->link); |
131 | free(sway_device->identifier); | 164 | free(input_device->identifier); |
132 | free(sway_device); | 165 | free(input_device); |
133 | } | 166 | } |
134 | 167 | ||
135 | struct sway_input_manager *sway_input_manager_create( | 168 | struct sway_input_manager *sway_input_manager_create( |
@@ -139,7 +172,6 @@ struct sway_input_manager *sway_input_manager_create( | |||
139 | if (!input) { | 172 | if (!input) { |
140 | return NULL; | 173 | return NULL; |
141 | } | 174 | } |
142 | // XXX probably don't need the full server | ||
143 | input->server = server; | 175 | input->server = server; |
144 | 176 | ||
145 | wl_list_init(&input->devices); | 177 | wl_list_init(&input->devices); |
@@ -177,22 +209,53 @@ void sway_input_manager_set_focus(struct sway_input_manager *input, | |||
177 | } | 209 | } |
178 | } | 210 | } |
179 | 211 | ||
180 | void sway_input_manager_apply_config(struct sway_input_manager *input, | 212 | void sway_input_manager_apply_input_config(struct sway_input_manager *input, |
181 | struct input_config *input_config) { | 213 | struct input_config *input_config) { |
182 | struct sway_input_device *sway_device = | 214 | struct sway_input_device *input_device = |
183 | input_sway_device_from_config(input, input_config); | 215 | input_sway_device_from_config(input, input_config); |
184 | if (!sway_device) { | 216 | if (!input_device) { |
185 | return; | 217 | return; |
186 | } | 218 | } |
219 | input_device->config = input_config; | ||
187 | 220 | ||
188 | struct sway_seat *seat = NULL; | 221 | struct sway_seat *seat = NULL; |
189 | wl_list_for_each(seat, &input->seats, link) { | 222 | wl_list_for_each(seat, &input->seats, link) { |
190 | sway_seat_remove_device(seat, sway_device); | 223 | sway_seat_configure_device(seat, input_device); |
224 | } | ||
225 | } | ||
226 | |||
227 | void sway_input_manager_apply_seat_config(struct sway_input_manager *input, | ||
228 | struct seat_config *seat_config) { | ||
229 | struct sway_seat *seat = input_manager_get_seat(input, seat_config->name); | ||
230 | // the old config is invalid so clear it | ||
231 | sway_seat_set_config(seat, NULL); | ||
232 | |||
233 | // clear devices | ||
234 | struct sway_input_device *input_device = NULL; | ||
235 | wl_list_for_each(input_device, &input->devices, link) { | ||
236 | sway_seat_remove_device(seat, input_device); | ||
237 | } | ||
238 | |||
239 | if (seat_config_get_attachment(seat_config, "*")) { | ||
240 | wl_list_for_each(input_device, &input->devices, link) { | ||
241 | sway_seat_add_device(seat, input_device); | ||
242 | } | ||
243 | } else { | ||
244 | for (int i = 0; i < seat_config->attachments->length; ++i) { | ||
245 | struct seat_attachment_config *attachment = | ||
246 | seat_config->attachments->items[i]; | ||
247 | |||
248 | struct sway_input_device *device = | ||
249 | input_sway_device_from_identifier(input, | ||
250 | attachment->identifier); | ||
251 | |||
252 | if (device) { | ||
253 | sway_seat_add_device(seat, device); | ||
254 | } | ||
255 | } | ||
191 | } | 256 | } |
192 | 257 | ||
193 | const char *seat_name = (input_config->seat ? input_config->seat : default_seat); | 258 | sway_seat_set_config(seat, seat_config); |
194 | seat = input_manager_get_seat(input, seat_name); | ||
195 | sway_seat_add_device(seat, sway_device); | ||
196 | } | 259 | } |
197 | 260 | ||
198 | void sway_input_manager_configure_xcursor(struct sway_input_manager *input) { | 261 | void sway_input_manager_configure_xcursor(struct sway_input_manager *input) { |
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 6a792c65..53db3270 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -5,32 +5,46 @@ | |||
5 | static void handle_keyboard_key(struct wl_listener *listener, void *data) { | 5 | static void handle_keyboard_key(struct wl_listener *listener, void *data) { |
6 | struct sway_keyboard *keyboard = | 6 | struct sway_keyboard *keyboard = |
7 | wl_container_of(listener, keyboard, keyboard_key); | 7 | wl_container_of(listener, keyboard, keyboard_key); |
8 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; | ||
9 | struct wlr_input_device *wlr_device = | ||
10 | keyboard->seat_device->input_device->wlr_device; | ||
8 | struct wlr_event_keyboard_key *event = data; | 11 | struct wlr_event_keyboard_key *event = data; |
9 | wlr_seat_set_keyboard(keyboard->seat->seat, keyboard->device->wlr_device); | 12 | wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); |
10 | wlr_seat_keyboard_notify_key(keyboard->seat->seat, event->time_msec, | 13 | wlr_seat_set_keyboard(wlr_seat, wlr_device); |
11 | event->keycode, event->state); | 14 | wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,event->keycode, |
15 | event->state); | ||
12 | } | 16 | } |
13 | 17 | ||
14 | static void handle_keyboard_modifiers(struct wl_listener *listener, | 18 | static void handle_keyboard_modifiers(struct wl_listener *listener, |
15 | void *data) { | 19 | void *data) { |
16 | struct sway_keyboard *keyboard = | 20 | struct sway_keyboard *keyboard = |
17 | wl_container_of(listener, keyboard, keyboard_modifiers); | 21 | wl_container_of(listener, keyboard, keyboard_modifiers); |
18 | wlr_seat_set_keyboard(keyboard->seat->seat, keyboard->device->wlr_device); | 22 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; |
19 | wlr_seat_keyboard_notify_modifiers(keyboard->seat->seat); | 23 | struct wlr_input_device *wlr_device = |
24 | keyboard->seat_device->input_device->wlr_device; | ||
25 | wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); | ||
26 | wlr_seat_set_keyboard(wlr_seat, wlr_device); | ||
27 | wlr_seat_keyboard_notify_modifiers(wlr_seat); | ||
20 | } | 28 | } |
21 | 29 | ||
22 | struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, | 30 | struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, |
23 | struct sway_input_device *device) { | 31 | struct sway_seat_device *device) { |
24 | struct sway_keyboard *keyboard = | 32 | struct sway_keyboard *keyboard = |
25 | calloc(1, sizeof(struct sway_keyboard)); | 33 | calloc(1, sizeof(struct sway_keyboard)); |
26 | if (!sway_assert(keyboard, "could not allocate sway keyboard")) { | 34 | if (!sway_assert(keyboard, "could not allocate sway keyboard")) { |
27 | return NULL; | 35 | return NULL; |
28 | } | 36 | } |
29 | 37 | ||
30 | keyboard->device = device; | 38 | keyboard->seat_device = device; |
31 | keyboard->seat = seat; | 39 | device->keyboard = keyboard; |
32 | 40 | ||
33 | // TODO keyboard config | 41 | wl_list_init(&keyboard->keyboard_key.link); |
42 | wl_list_init(&keyboard->keyboard_modifiers.link); | ||
43 | |||
44 | return keyboard; | ||
45 | } | ||
46 | |||
47 | void sway_keyboard_configure(struct sway_keyboard *keyboard) { | ||
34 | struct xkb_rule_names rules; | 48 | struct xkb_rule_names rules; |
35 | memset(&rules, 0, sizeof(rules)); | 49 | memset(&rules, 0, sizeof(rules)); |
36 | rules.rules = getenv("XKB_DEFAULT_RULES"); | 50 | rules.rules = getenv("XKB_DEFAULT_RULES"); |
@@ -38,27 +52,32 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, | |||
38 | rules.layout = getenv("XKB_DEFAULT_LAYOUT"); | 52 | rules.layout = getenv("XKB_DEFAULT_LAYOUT"); |
39 | rules.variant = getenv("XKB_DEFAULT_VARIANT"); | 53 | rules.variant = getenv("XKB_DEFAULT_VARIANT"); |
40 | rules.options = getenv("XKB_DEFAULT_OPTIONS"); | 54 | rules.options = getenv("XKB_DEFAULT_OPTIONS"); |
55 | |||
41 | struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); | 56 | struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); |
42 | if (!sway_assert(context, "cannot create XKB context")) { | 57 | if (!sway_assert(context, "cannot create XKB context")) { |
43 | return NULL; | 58 | return; |
44 | } | 59 | } |
45 | 60 | ||
46 | wlr_keyboard_set_keymap(device->wlr_device->keyboard, | 61 | keyboard->keymap = |
47 | xkb_map_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS)); | 62 | xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); |
63 | wlr_keyboard_set_keymap(keyboard->seat_device->input_device->wlr_device->keyboard, keyboard->keymap); | ||
48 | xkb_context_unref(context); | 64 | xkb_context_unref(context); |
49 | 65 | ||
50 | wl_signal_add(&device->wlr_device->keyboard->events.key, | 66 | wl_list_remove(&keyboard->keyboard_key.link); |
67 | wl_signal_add( | ||
68 | &keyboard->seat_device->input_device->wlr_device->keyboard->events.key, | ||
51 | &keyboard->keyboard_key); | 69 | &keyboard->keyboard_key); |
52 | keyboard->keyboard_key.notify = handle_keyboard_key; | 70 | keyboard->keyboard_key.notify = handle_keyboard_key; |
53 | 71 | ||
54 | wl_signal_add(&device->wlr_device->keyboard->events.modifiers, | 72 | wl_list_remove(&keyboard->keyboard_modifiers.link); |
73 | wl_signal_add( | ||
74 | &keyboard->seat_device->input_device->wlr_device->keyboard->events.modifiers, | ||
55 | &keyboard->keyboard_modifiers); | 75 | &keyboard->keyboard_modifiers); |
56 | keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; | 76 | keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; |
57 | |||
58 | return keyboard; | ||
59 | } | 77 | } |
60 | 78 | ||
61 | void sway_keyboard_destroy(struct sway_keyboard *keyboard) { | 79 | void sway_keyboard_destroy(struct sway_keyboard *keyboard) { |
80 | xkb_keymap_unref(keyboard->keymap); | ||
62 | wl_list_remove(&keyboard->keyboard_key.link); | 81 | wl_list_remove(&keyboard->keyboard_key.link); |
63 | wl_list_remove(&keyboard->keyboard_modifiers.link); | 82 | wl_list_remove(&keyboard->keyboard_modifiers.link); |
64 | wl_list_remove(&keyboard->link); | 83 | wl_list_remove(&keyboard->link); |
diff --git a/sway/input/seat.c b/sway/input/seat.c index 80c6424f..1b25419b 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -9,6 +9,18 @@ | |||
9 | #include "sway/view.h" | 9 | #include "sway/view.h" |
10 | #include "log.h" | 10 | #include "log.h" |
11 | 11 | ||
12 | static void seat_device_destroy(struct sway_seat_device *seat_device) { | ||
13 | if (!seat_device) { | ||
14 | return; | ||
15 | } | ||
16 | |||
17 | sway_keyboard_destroy(seat_device->keyboard); | ||
18 | wlr_cursor_detach_input_device(seat_device->sway_seat->cursor->cursor, | ||
19 | seat_device->input_device->wlr_device); | ||
20 | wl_list_remove(&seat_device->link); | ||
21 | free(seat_device); | ||
22 | } | ||
23 | |||
12 | struct sway_seat *sway_seat_create(struct sway_input_manager *input, | 24 | struct sway_seat *sway_seat_create(struct sway_input_manager *input, |
13 | const char *seat_name) { | 25 | const char *seat_name) { |
14 | struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); | 26 | struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); |
@@ -16,22 +28,22 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, | |||
16 | return NULL; | 28 | return NULL; |
17 | } | 29 | } |
18 | 30 | ||
19 | seat->seat = wlr_seat_create(input->server->wl_display, seat_name); | 31 | seat->wlr_seat = wlr_seat_create(input->server->wl_display, seat_name); |
20 | if (!sway_assert(seat->seat, "could not allocate seat")) { | 32 | if (!sway_assert(seat->wlr_seat, "could not allocate seat")) { |
21 | return NULL; | 33 | return NULL; |
22 | } | 34 | } |
23 | 35 | ||
24 | seat->cursor = sway_cursor_create(seat); | 36 | seat->cursor = sway_cursor_create(seat); |
25 | if (!seat->cursor) { | 37 | if (!seat->cursor) { |
26 | wlr_seat_destroy(seat->seat); | 38 | wlr_seat_destroy(seat->wlr_seat); |
27 | free(seat); | 39 | free(seat); |
28 | return NULL; | 40 | return NULL; |
29 | } | 41 | } |
30 | 42 | ||
31 | seat->input = input; | 43 | seat->input = input; |
32 | seat->devices = create_list(); | 44 | wl_list_init(&seat->devices); |
33 | 45 | ||
34 | wlr_seat_set_capabilities(seat->seat, | 46 | wlr_seat_set_capabilities(seat->wlr_seat, |
35 | WL_SEAT_CAPABILITY_KEYBOARD | | 47 | WL_SEAT_CAPABILITY_KEYBOARD | |
36 | WL_SEAT_CAPABILITY_POINTER | | 48 | WL_SEAT_CAPABILITY_POINTER | |
37 | WL_SEAT_CAPABILITY_TOUCH); | 49 | WL_SEAT_CAPABILITY_TOUCH); |
@@ -43,88 +55,94 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, | |||
43 | return seat; | 55 | return seat; |
44 | } | 56 | } |
45 | 57 | ||
46 | static void seat_add_pointer(struct sway_seat *seat, | 58 | static void seat_configure_pointer(struct sway_seat *seat, |
47 | struct sway_input_device *sway_device) { | 59 | struct sway_seat_device *sway_device) { |
48 | // TODO pointer configuration | 60 | // TODO pointer configuration |
49 | wlr_cursor_attach_input_device(seat->cursor->cursor, | 61 | wlr_cursor_attach_input_device(seat->cursor->cursor, |
50 | sway_device->wlr_device); | 62 | sway_device->input_device->wlr_device); |
51 | } | 63 | } |
52 | 64 | ||
53 | static void seat_add_keyboard(struct sway_seat *seat, | 65 | static void seat_configure_keyboard(struct sway_seat *seat, |
54 | struct sway_input_device *device) { | 66 | struct sway_seat_device *seat_device) { |
55 | // TODO keyboard configuration | 67 | if (!seat_device->keyboard) { |
56 | sway_keyboard_create(seat, device); | 68 | sway_keyboard_create(seat, seat_device); |
57 | wlr_seat_set_keyboard(seat->seat, device->wlr_device); | 69 | } |
70 | sway_keyboard_configure(seat_device->keyboard); | ||
58 | } | 71 | } |
59 | 72 | ||
60 | bool sway_seat_has_device(struct sway_seat *seat, | 73 | static struct sway_seat_device *sway_seat_get_device(struct sway_seat *seat, |
61 | struct sway_input_device *device) { | 74 | struct sway_input_device *input_device) { |
62 | return false; | 75 | struct sway_seat_device *seat_device = NULL; |
76 | wl_list_for_each(seat_device, &seat->devices, link) { | ||
77 | if (seat_device->input_device == input_device) { | ||
78 | return seat_device; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | return NULL; | ||
63 | } | 83 | } |
64 | 84 | ||
65 | void sway_seat_add_device(struct sway_seat *seat, | 85 | void sway_seat_configure_device(struct sway_seat *seat, |
66 | struct sway_input_device *device) { | 86 | struct sway_input_device *input_device) { |
67 | if (sway_seat_has_device(seat, device)) { | 87 | struct sway_seat_device *seat_device = |
88 | sway_seat_get_device(seat, input_device); | ||
89 | if (!seat_device) { | ||
68 | return; | 90 | return; |
69 | } | 91 | } |
70 | 92 | ||
71 | sway_log(L_DEBUG, "input add: %s", device->identifier); | 93 | if (seat->config) { |
72 | switch (device->wlr_device->type) { | 94 | seat_device->attachment_config = |
95 | seat_config_get_attachment(seat->config, input_device->identifier); | ||
96 | } | ||
97 | |||
98 | switch (input_device->wlr_device->type) { | ||
73 | case WLR_INPUT_DEVICE_POINTER: | 99 | case WLR_INPUT_DEVICE_POINTER: |
74 | seat_add_pointer(seat, device); | 100 | seat_configure_pointer(seat, seat_device); |
75 | break; | 101 | break; |
76 | case WLR_INPUT_DEVICE_KEYBOARD: | 102 | case WLR_INPUT_DEVICE_KEYBOARD: |
77 | seat_add_keyboard(seat, device); | 103 | seat_configure_keyboard(seat, seat_device); |
104 | wlr_seat_set_keyboard(seat->wlr_seat, | ||
105 | seat_device->input_device->wlr_device); | ||
78 | break; | 106 | break; |
79 | case WLR_INPUT_DEVICE_TOUCH: | 107 | case WLR_INPUT_DEVICE_TOUCH: |
80 | case WLR_INPUT_DEVICE_TABLET_PAD: | 108 | case WLR_INPUT_DEVICE_TABLET_PAD: |
81 | case WLR_INPUT_DEVICE_TABLET_TOOL: | 109 | case WLR_INPUT_DEVICE_TABLET_TOOL: |
82 | sway_log(L_DEBUG, "TODO: add other devices"); | 110 | sway_log(L_DEBUG, "TODO: configure other devices"); |
83 | break; | 111 | break; |
84 | } | 112 | } |
85 | |||
86 | list_add(seat->devices, device); | ||
87 | } | 113 | } |
88 | 114 | ||
89 | static void seat_remove_keyboard(struct sway_seat *seat, | 115 | void sway_seat_add_device(struct sway_seat *seat, |
90 | struct sway_input_device *device) { | 116 | struct sway_input_device *input_device) { |
91 | if (device && device->keyboard) { | 117 | if (sway_seat_get_device(seat, input_device)) { |
92 | sway_keyboard_destroy(device->keyboard); | 118 | return; |
93 | } | 119 | } |
94 | } | ||
95 | 120 | ||
96 | static void seat_remove_pointer(struct sway_seat *seat, | 121 | struct sway_seat_device *seat_device = |
97 | struct sway_input_device *device) { | 122 | calloc(1, sizeof(struct sway_seat_device)); |
98 | wlr_cursor_detach_input_device(seat->cursor->cursor, device->wlr_device); | 123 | if (!seat_device) { |
124 | sway_log(L_DEBUG, "could not allocate seat device"); | ||
125 | return; | ||
126 | } | ||
127 | |||
128 | seat_device->sway_seat = seat; | ||
129 | seat_device->input_device = input_device; | ||
130 | wl_list_insert(&seat->devices, &seat_device->link); | ||
131 | |||
132 | sway_seat_configure_device(seat, input_device); | ||
99 | } | 133 | } |
100 | 134 | ||
101 | void sway_seat_remove_device(struct sway_seat *seat, | 135 | void sway_seat_remove_device(struct sway_seat *seat, |
102 | struct sway_input_device *device) { | 136 | struct sway_input_device *input_device) { |
103 | sway_log(L_DEBUG, "input remove: %s", device->identifier); | 137 | sway_log(L_DEBUG, "input remove: %s", input_device->identifier); |
104 | if (!sway_seat_has_device(seat, device)) { | 138 | struct sway_seat_device *seat_device = |
105 | return; | 139 | sway_seat_get_device(seat, input_device); |
106 | } | ||
107 | 140 | ||
108 | switch (device->wlr_device->type) { | 141 | if (!seat_device) { |
109 | case WLR_INPUT_DEVICE_POINTER: | 142 | return; |
110 | seat_remove_pointer(seat, device); | ||
111 | break; | ||
112 | case WLR_INPUT_DEVICE_KEYBOARD: | ||
113 | seat_remove_keyboard(seat, device); | ||
114 | break; | ||
115 | case WLR_INPUT_DEVICE_TOUCH: | ||
116 | case WLR_INPUT_DEVICE_TABLET_PAD: | ||
117 | case WLR_INPUT_DEVICE_TABLET_TOOL: | ||
118 | sway_log(L_DEBUG, "TODO: remove other devices"); | ||
119 | break; | ||
120 | } | 143 | } |
121 | 144 | ||
122 | for (int i = 0; i < seat->devices->length; ++i) { | 145 | seat_device_destroy(seat_device); |
123 | if (seat->devices->items[i] == device) { | ||
124 | list_del(seat->devices, i); | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | } | 146 | } |
129 | 147 | ||
130 | void sway_seat_configure_xcursor(struct sway_seat *seat) { | 148 | void sway_seat_configure_xcursor(struct sway_seat *seat) { |
@@ -135,7 +153,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { | |||
135 | seat->cursor->xcursor_manager = | 153 | seat->cursor->xcursor_manager = |
136 | wlr_xcursor_manager_create("default", 24); | 154 | wlr_xcursor_manager_create("default", 24); |
137 | if (sway_assert(seat->cursor->xcursor_manager, | 155 | if (sway_assert(seat->cursor->xcursor_manager, |
138 | "Cannot create XCursor manager for theme %s", cursor_theme)) { | 156 | "Cannot create XCursor manager for theme %s", |
157 | cursor_theme)) { | ||
139 | return; | 158 | return; |
140 | } | 159 | } |
141 | } | 160 | } |
@@ -183,7 +202,7 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { | |||
183 | view->iface.set_activated(view, true); | 202 | view->iface.set_activated(view, true); |
184 | wl_signal_add(&container->events.destroy, &seat->focus_destroy); | 203 | wl_signal_add(&container->events.destroy, &seat->focus_destroy); |
185 | seat->focus_destroy.notify = handle_focus_destroy; | 204 | seat->focus_destroy.notify = handle_focus_destroy; |
186 | wlr_seat_keyboard_notify_enter(seat->seat, view->surface); | 205 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface); |
187 | } | 206 | } |
188 | 207 | ||
189 | seat->focus = container; | 208 | seat->focus = container; |
@@ -195,3 +214,29 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { | |||
195 | 214 | ||
196 | } | 215 | } |
197 | } | 216 | } |
217 | |||
218 | void sway_seat_set_config(struct sway_seat *seat, | ||
219 | struct seat_config *seat_config) { | ||
220 | // clear configs | ||
221 | seat->config = NULL; | ||
222 | |||
223 | struct sway_seat_device *seat_device = NULL; | ||
224 | wl_list_for_each(seat_device, &seat->devices, link) { | ||
225 | seat_device->attachment_config = NULL; | ||
226 | } | ||
227 | |||
228 | if (!seat_config) { | ||
229 | return; | ||
230 | } | ||
231 | |||
232 | // add configs | ||
233 | seat->config = seat_config; | ||
234 | |||
235 | wl_list_for_each(seat_device, &seat->devices, link) { | ||
236 | seat_device->attachment_config = | ||
237 | seat_config_get_attachment(seat_config, | ||
238 | seat_device->input_device->identifier); | ||
239 | sway_seat_configure_device(seat, seat_device->input_device); | ||
240 | } | ||
241 | |||
242 | } | ||
diff --git a/sway/meson.build b/sway/meson.build index fad1f88c..ad8160eb 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -11,7 +11,8 @@ sway_sources = files( | |||
11 | 'commands/exec_always.c', | 11 | 'commands/exec_always.c', |
12 | 'commands/include.c', | 12 | 'commands/include.c', |
13 | 'commands/input.c', | 13 | 'commands/input.c', |
14 | 'commands/input/seat.c', | 14 | 'commands/seat.c', |
15 | 'commands/seat/attach.c', | ||
15 | 'commands/input/accel_profile.c', | 16 | 'commands/input/accel_profile.c', |
16 | 'commands/input/click_method.c', | 17 | 'commands/input/click_method.c', |
17 | 'commands/input/drag_lock.c', | 18 | 'commands/input/drag_lock.c', |