diff options
Diffstat (limited to 'sway/config')
-rw-r--r-- | sway/config/input.c | 134 |
1 files changed, 105 insertions, 29 deletions
diff --git a/sway/config/input.c b/sway/config/input.c index 9c533e71..c4f64eb8 100644 --- a/sway/config/input.c +++ b/sway/config/input.c @@ -3,6 +3,7 @@ #include <limits.h> #include <float.h> #include "sway/config.h" +#include "sway/input/keyboard.h" #include "log.h" struct input_config *new_input_config(const char* identifier) { @@ -133,22 +134,82 @@ void merge_input_config(struct input_config *dst, struct input_config *src) { } } -static void merge_wildcard_on_all(struct input_config *wildcard) { +static bool validate_xkb_merge(struct input_config *dest, + struct input_config *src, char **xkb_error) { + struct input_config *temp = new_input_config("temp"); + if (dest) { + merge_input_config(temp, dest); + } + merge_input_config(temp, src); + + struct xkb_keymap *keymap = sway_keyboard_compile_keymap(temp, xkb_error); + free_input_config(temp); + if (!keymap) { + return false; + } + + xkb_keymap_unref(keymap); + return true; +} + +static bool validate_wildcard_on_all(struct input_config *wildcard, + char **error) { for (int i = 0; i < config->input_configs->length; i++) { struct input_config *ic = config->input_configs->items[i]; if (strcmp(wildcard->identifier, ic->identifier) != 0) { - sway_log(SWAY_DEBUG, "Merging input * config on %s", ic->identifier); - merge_input_config(ic, wildcard); + sway_log(SWAY_DEBUG, "Validating xkb merge of * on %s", + ic->identifier); + if (!validate_xkb_merge(ic, wildcard, error)) { + return false; + } } } for (int i = 0; i < config->input_type_configs->length; i++) { struct input_config *ic = config->input_type_configs->items[i]; + sway_log(SWAY_DEBUG, "Validating xkb merge of * config on %s", + ic->identifier); + if (!validate_xkb_merge(ic, wildcard, error)) { + return false; + } + } + + return true; +} + +static void merge_wildcard_on_all(struct input_config *wildcard) { + for (int i = 0; i < config->input_configs->length; i++) { + struct input_config *ic = config->input_configs->items[i]; if (strcmp(wildcard->identifier, ic->identifier) != 0) { sway_log(SWAY_DEBUG, "Merging input * config on %s", ic->identifier); merge_input_config(ic, wildcard); } } + + for (int i = 0; i < config->input_type_configs->length; i++) { + struct input_config *ic = config->input_type_configs->items[i]; + sway_log(SWAY_DEBUG, "Merging input * config on %s", ic->identifier); + merge_input_config(ic, wildcard); + } +} + +static bool validate_type_on_existing(struct input_config *type_wildcard, + char **error) { + for (int i = 0; i < config->input_configs->length; i++) { + struct input_config *ic = config->input_configs->items[i]; + if (ic->input_type == NULL) { + continue; + } + + if (strcmp(ic->input_type, type_wildcard->identifier + 5) == 0) { + sway_log(SWAY_DEBUG, "Validating merge of %s on %s", + type_wildcard->identifier, ic->identifier); + if (!validate_xkb_merge(ic, type_wildcard, error)) { + return false; + } + } + } + return true; } static void merge_type_on_existing(struct input_config *type_wildcard) { @@ -167,44 +228,59 @@ static void merge_type_on_existing(struct input_config *type_wildcard) { } } -struct input_config *store_input_config(struct input_config *ic) { +struct input_config *store_input_config(struct input_config *ic, + char **error) { bool wildcard = strcmp(ic->identifier, "*") == 0; + if (wildcard && error && !validate_wildcard_on_all(ic, error)) { + return NULL; + } + + bool type = strncmp(ic->identifier, "type:", strlen("type:")) == 0; + if (type && error && !validate_type_on_existing(ic, error)) { + return NULL; + } + + list_t *config_list = type ? config->input_type_configs + : config->input_configs; + + struct input_config *current = NULL; + bool new_current = false; + + int i = list_seq_find(config_list, input_identifier_cmp, ic->identifier); + if (i >= 0) { + current = config_list->items[i]; + } + + i = list_seq_find(config->input_configs, input_identifier_cmp, "*"); + if (!current && i >= 0) { + current = new_input_config(ic->identifier); + merge_input_config(current, config->input_configs->items[i]); + new_current = true; + } + + if (error && !validate_xkb_merge(current, ic, error)) { + if (new_current) { + free_input_config(current); + } + return NULL; + } + if (wildcard) { merge_wildcard_on_all(ic); } - list_t *config_list = NULL; - if (strncmp(ic->identifier, "type:", 5) == 0) { - config_list = config->input_type_configs; + if (type) { merge_type_on_existing(ic); - } else { - config_list = config->input_configs; } - int i = list_seq_find(config_list, input_identifier_cmp, - ic->identifier); - if (i >= 0) { - sway_log(SWAY_DEBUG, "Merging on top of existing input config"); - struct input_config *current = config_list->items[i]; + if (current) { merge_input_config(current, ic); free_input_config(ic); ic = current; - } else if (!wildcard) { - sway_log(SWAY_DEBUG, "Adding non-wildcard input config"); - i = list_seq_find(config->input_configs, input_identifier_cmp, "*"); - if (i >= 0) { - sway_log(SWAY_DEBUG, "Merging on top of input * config"); - struct input_config *current = new_input_config(ic->identifier); - merge_input_config(current, config->input_configs->items[i]); - merge_input_config(current, ic); - free_input_config(ic); - ic = current; - } + } + + if (!current || new_current) { list_add(config_list, ic); - } else { - // New wildcard config. Just add it - sway_log(SWAY_DEBUG, "Adding input * config"); - list_add(config->input_configs, ic); } sway_log(SWAY_DEBUG, "Config stored for input %s", ic->identifier); |