diff --git a/include/sway/config.h b/include/sway/config.h index 7ee2ec71..6610f009 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -536,7 +536,7 @@ struct seat_attachment_config *seat_attachment_config_new(void); struct seat_attachment_config *seat_config_get_attachment( struct seat_config *seat_config, char *identifier); -void apply_seat_config(struct seat_config *seat); +struct seat_config *store_seat_config(struct seat_config *seat); int output_name_cmp(const void *item, const void *data); diff --git a/sway/commands.c b/sway/commands.c index eda29c65..51bfe13a 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -42,21 +42,6 @@ struct cmd_results *checkarg(int argc, const char *name, enum expected_args type : NULL; } -void apply_seat_config(struct seat_config *seat_config) { - int i = list_seq_find(config->seat_configs, seat_name_cmp, seat_config->name); - if (i >= 0) { - // merge existing config - struct seat_config *sc = config->seat_configs->items[i]; - merge_seat_config(sc, seat_config); - free_seat_config(seat_config); - seat_config = sc; - } else { - list_add(config->seat_configs, seat_config); - } - - input_manager_apply_seat_config(seat_config); -} - /* Keep alphabetized */ static struct cmd_handler handlers[] = { { "assign", cmd_assign }, diff --git a/sway/commands/seat.c b/sway/commands/seat.c index 5abb19b0..56acd204 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c @@ -26,9 +26,16 @@ struct cmd_results *cmd_seat(int argc, char **argv) { struct cmd_results *res = config_subcommand(argv + 1, argc - 1, seat_handlers, sizeof(seat_handlers)); + if (res && res->status != CMD_SUCCESS) { + free_seat_config(config->handler_context.seat_config); + config->handler_context.seat_config = NULL; + return res; + } - free_seat_config(config->handler_context.seat_config); - config->handler_context.seat_config = NULL; + struct seat_config *sc = + store_seat_config(config->handler_context.seat_config); + input_manager_apply_seat_config(sc); - return res; + config->handler_context.seat_config = NULL; + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/seat/attach.c b/sway/commands/seat/attach.c index 8d646c2d..0fb17f1d 100644 --- a/sway/commands/seat/attach.c +++ b/sway/commands/seat/attach.c @@ -1,10 +1,7 @@ #define _POSIX_C_SOURCE 200809L #include -#include -#include "sway/input/input-manager.h" #include "sway/commands.h" #include "sway/config.h" -#include "log.h" #include "stringop.h" struct cmd_results *seat_cmd_attach(int argc, char **argv) { @@ -12,19 +9,17 @@ struct cmd_results *seat_cmd_attach(int argc, char **argv) { if ((error = checkarg(argc, "attach", EXPECTED_AT_LEAST, 1))) { return error; } - struct seat_config *current_seat_config = - config->handler_context.seat_config; - if (!current_seat_config) { + if (!config->handler_context.seat_config) { return cmd_results_new(CMD_FAILURE, "attach", "No seat defined"); } - struct seat_config *new_config = new_seat_config(current_seat_config->name); - struct seat_attachment_config *new_attachment = seat_attachment_config_new(); - new_attachment->identifier = strdup(argv[0]); - list_add(new_config->attachments, new_attachment); - - if (!config->validating) { - apply_seat_config(new_config); + struct seat_attachment_config *attachment = seat_attachment_config_new(); + if (!attachment) { + return cmd_results_new(CMD_FAILURE, "attach", + "Failed to allocate seat attachment config"); } + attachment->identifier = strdup(argv[0]); + list_add(config->handler_context.seat_config->attachments, attachment); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/seat/fallback.c b/sway/commands/seat/fallback.c index a0ddf3ef..8f1ab12c 100644 --- a/sway/commands/seat/fallback.c +++ b/sway/commands/seat/fallback.c @@ -1,27 +1,18 @@ -#include -#include #include "sway/config.h" #include "sway/commands.h" -#include "sway/input/input-manager.h" #include "util.h" struct cmd_results *seat_cmd_fallback(int argc, char **argv) { struct cmd_results *error = NULL; - if ((error = checkarg(argc, "fallback", EXPECTED_AT_LEAST, 1))) { + if ((error = checkarg(argc, "fallback", EXPECTED_EQUAL_TO, 1))) { return error; } - struct seat_config *current_seat_config = - config->handler_context.seat_config; - if (!current_seat_config) { + if (!config->handler_context.seat_config) { return cmd_results_new(CMD_FAILURE, "fallback", "No seat defined"); } - struct seat_config *new_config = - new_seat_config(current_seat_config->name); - - new_config->fallback = parse_boolean(argv[0], false); - if (!config->validating) { - apply_seat_config(new_config); - } + config->handler_context.seat_config->fallback = + parse_boolean(argv[0], false); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/config/seat.c b/sway/config/seat.c index 1cb4c363..c248990a 100644 --- a/sway/config/seat.c +++ b/sway/config/seat.c @@ -11,7 +11,6 @@ struct seat_config *new_seat_config(const char* name) { return NULL; } - wlr_log(WLR_DEBUG, "new_seat_config(%s)", name); seat->name = strdup(name); if (!sway_assert(seat->name, "could not allocate name for seat")) { free(seat); @@ -30,6 +29,52 @@ struct seat_config *new_seat_config(const char* name) { return seat; } +static void merge_wildcard_on_all(struct seat_config *wildcard) { + for (int i = 0; i < config->seat_configs->length; i++) { + struct seat_config *sc = config->seat_configs->items[i]; + if (strcmp(wildcard->name, sc->name) != 0) { + wlr_log(WLR_DEBUG, "Merging seat * config on %s", sc->name); + merge_seat_config(sc, wildcard); + } + } +} + +struct seat_config *store_seat_config(struct seat_config *sc) { + bool wildcard = strcmp(sc->name, "*") == 0; + if (wildcard) { + merge_wildcard_on_all(sc); + } + + int i = list_seq_find(config->seat_configs, seat_name_cmp, sc->name); + if (i >= 0) { + wlr_log(WLR_DEBUG, "Merging on top of existing seat config"); + struct seat_config *current = config->seat_configs->items[i]; + merge_seat_config(current, sc); + free_seat_config(sc); + sc = current; + } else if (!wildcard) { + wlr_log(WLR_DEBUG, "Adding non-wildcard seat config"); + i = list_seq_find(config->seat_configs, seat_name_cmp, "*"); + if (i >= 0) { + wlr_log(WLR_DEBUG, "Merging on top of seat * config"); + struct seat_config *current = new_seat_config(sc->name); + merge_seat_config(current, config->seat_configs->items[i]); + merge_seat_config(current, sc); + free_seat_config(sc); + sc = current; + } + list_add(config->seat_configs, sc); + } else { + // New wildcard config. Just add it + wlr_log(WLR_DEBUG, "Adding seat * config"); + list_add(config->seat_configs, sc); + } + + wlr_log(WLR_DEBUG, "Config stored for seat %s", sc->name); + + return sc; +} + struct seat_attachment_config *seat_attachment_config_new(void) { struct seat_attachment_config *attachment = calloc(1, sizeof(struct seat_attachment_config)); @@ -65,11 +110,6 @@ static void merge_seat_attachment_config(struct seat_attachment_config *dest, } void merge_seat_config(struct seat_config *dest, struct seat_config *source) { - if (source->name) { - free(dest->name); - dest->name = strdup(source->name); - } - if (source->fallback != -1) { dest->fallback = source->fallback; } diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 89146d5b..055f6752 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -82,11 +82,12 @@ static struct sway_input_device *input_sway_device_from_wlr( return NULL; } -static bool input_has_seat_configuration(void) { +static bool input_has_seat_fallback_configuration(void) { struct sway_seat *seat = NULL; wl_list_for_each(seat, &server.input->seats, link) { struct seat_config *seat_config = seat_get_config(seat); - if (seat_config) { + if (seat_config && strcmp(seat_config->name, "*") != 0 + && seat_config->fallback != -1) { return true; } } @@ -296,11 +297,12 @@ static void handle_new_input(struct wl_listener *listener, void *data) { input_device->device_destroy.notify = handle_device_destroy; struct sway_seat *seat = NULL; - if (!input_has_seat_configuration()) { - wlr_log(WLR_DEBUG, "no seat configuration, using default seat"); + if (!input_has_seat_fallback_configuration()) { + wlr_log(WLR_DEBUG, "no seat config - creating default seat config"); seat = input_manager_get_default_seat(); - seat_add_device(seat, input_device); - return; + struct seat_config *sc = new_seat_config(seat->wlr_seat->name); + sc->fallback = true; + store_seat_config(sc); } bool added = false; @@ -459,15 +461,26 @@ void input_manager_apply_input_config(struct input_config *input_config) { } void input_manager_apply_seat_config(struct seat_config *seat_config) { - wlr_log(WLR_DEBUG, "applying new seat config for seat %s", - seat_config->name); - struct sway_seat *seat = input_manager_get_seat(seat_config->name); - if (!seat) { - return; + wlr_log(WLR_DEBUG, "applying seat config for seat %s", seat_config->name); + if (strcmp(seat_config->name, "*") == 0) { + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &server.input->seats, link) { + // Only apply the wildcard config directly if there is no seat + // specific config + struct seat_config *sc = seat_get_config(seat); + if (!sc) { + sc = seat_config; + } + seat_apply_config(seat, sc); + } + } else { + struct sway_seat *seat = input_manager_get_seat(seat_config->name); + if (!seat) { + return; + } + seat_apply_config(seat, seat_config); } - seat_apply_config(seat, seat_config); - // for every device, try to add it to a seat and if no seat has it // attached, add it to the fallback seats. struct sway_input_device *input_device = NULL;