aboutsummaryrefslogtreecommitdiffstats
path: root/sway
diff options
context:
space:
mode:
authorLibravatar Tony Crisci <tony@dubstepdish.com>2017-12-14 11:11:56 -0500
committerLibravatar Tony Crisci <tony@dubstepdish.com>2017-12-14 11:11:56 -0500
commit92fef27eaa0b52c9d37bdabff14ae21cd6660f46 (patch)
tree7a923bbbc233079006597d82721117bae88b6ac6 /sway
parentseat configuration (diff)
downloadsway-92fef27eaa0b52c9d37bdabff14ae21cd6660f46.tar.gz
sway-92fef27eaa0b52c9d37bdabff14ae21cd6660f46.tar.zst
sway-92fef27eaa0b52c9d37bdabff14ae21cd6660f46.zip
basic configuration
Diffstat (limited to 'sway')
-rw-r--r--sway/commands.c32
-rw-r--r--sway/commands/input/seat.c28
-rw-r--r--sway/commands/seat.c35
-rw-r--r--sway/commands/seat/attach.c26
-rw-r--r--sway/config.c144
-rw-r--r--sway/input/cursor.c8
-rw-r--r--sway/input/input-manager.c139
-rw-r--r--sway/input/keyboard.c51
-rw-r--r--sway/input/seat.c163
-rw-r--r--sway/meson.build3
10 files changed, 475 insertions, 154 deletions
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
77void 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
120static int handler_compare(const void *_a, const void *_b) { 138static 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
160static struct cmd_handler seat_handlers[] = {
161 { "attach", seat_cmd_attach },
162};
163
142static struct cmd_handler *find_handler(char *line, enum cmd_status block) { 164static 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
8struct 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
7struct 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
10struct 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
259void merge_input_config(struct input_config *dst, struct input_config *src) { 260void 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
311struct 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
333struct 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
343static void seat_attachment_config_free(
344 struct seat_attachment_config *attachment) {
345 free(attachment->identifier);
346 free(attachment);
347 return;
348}
349
350static 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
362static 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
367void 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
398void 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
414int 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
420struct 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
313bool load_main_config(const char *file, bool is_active) { 433bool 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
25static void cursor_send_pointer_motion(struct sway_cursor *cursor, 25static 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";
18struct sway_input_manager *input_manager; 18struct sway_input_manager *input_manager;
19 19
20struct input_config *current_input_config = NULL; 20struct input_config *current_input_config = NULL;
21struct seat_config *current_seat_config = NULL;
21 22
22static struct sway_seat *input_manager_get_seat( 23static 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
61static struct sway_input_device *input_sway_device_from_wlr(struct sway_input_manager *input, 62static 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
72static struct sway_input_device *input_sway_device_from_config(struct sway_input_manager *input, 73static 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
84static 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
95static 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
83static void input_add_notify(struct wl_listener *listener, void *data) { 106static 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
113static void input_remove_notify(struct wl_listener *listener, void *data) { 146static 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
135struct sway_input_manager *sway_input_manager_create( 168struct 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
180void sway_input_manager_apply_config(struct sway_input_manager *input, 212void 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
227void 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
198void sway_input_manager_configure_xcursor(struct sway_input_manager *input) { 261void 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 @@
5static void handle_keyboard_key(struct wl_listener *listener, void *data) { 5static 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
14static void handle_keyboard_modifiers(struct wl_listener *listener, 18static 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
22struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, 30struct 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
47void 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
61void sway_keyboard_destroy(struct sway_keyboard *keyboard) { 79void 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
12static 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
12struct sway_seat *sway_seat_create(struct sway_input_manager *input, 24struct 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
46static void seat_add_pointer(struct sway_seat *seat, 58static 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
53static void seat_add_keyboard(struct sway_seat *seat, 65static 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
60bool sway_seat_has_device(struct sway_seat *seat, 73static 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
65void sway_seat_add_device(struct sway_seat *seat, 85void 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
89static void seat_remove_keyboard(struct sway_seat *seat, 115void 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
96static 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
101void sway_seat_remove_device(struct sway_seat *seat, 135void 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
130void sway_seat_configure_xcursor(struct sway_seat *seat) { 148void 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
218void 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',