diff options
-rw-r--r-- | include/sway/config.h | 2 | ||||
-rw-r--r-- | sway/commands/input.c | 11 | ||||
-rw-r--r-- | sway/commands/input/events.c | 2 | ||||
-rw-r--r-- | sway/config/input.c | 134 |
4 files changed, 111 insertions, 38 deletions
diff --git a/include/sway/config.h b/include/sway/config.h index 311adb16..57ae3c63 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -581,7 +581,7 @@ struct input_config *new_input_config(const char* identifier); | |||
581 | 581 | ||
582 | void merge_input_config(struct input_config *dst, struct input_config *src); | 582 | void merge_input_config(struct input_config *dst, struct input_config *src); |
583 | 583 | ||
584 | struct input_config *store_input_config(struct input_config *ic); | 584 | struct input_config *store_input_config(struct input_config *ic, char **error); |
585 | 585 | ||
586 | void input_config_fill_rule_names(struct input_config *ic, | 586 | void input_config_fill_rule_names(struct input_config *ic, |
587 | struct xkb_rule_names *rules); | 587 | struct xkb_rule_names *rules); |
diff --git a/sway/commands/input.c b/sway/commands/input.c index 23a6644f..d95c4baf 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c | |||
@@ -88,9 +88,10 @@ struct cmd_results *cmd_input(int argc, char **argv) { | |||
88 | 88 | ||
89 | if (!res || res->status == CMD_SUCCESS) { | 89 | if (!res || res->status == CMD_SUCCESS) { |
90 | char *error = NULL; | 90 | char *error = NULL; |
91 | struct xkb_keymap *keymap = sway_keyboard_compile_keymap( | 91 | struct input_config *ic = |
92 | config->handler_context.input_config, &error); | 92 | store_input_config(config->handler_context.input_config, &error); |
93 | if (!keymap) { | 93 | if (!ic) { |
94 | free_input_config(config->handler_context.input_config); | ||
94 | if (res) { | 95 | if (res) { |
95 | free_cmd_results(res); | 96 | free_cmd_results(res); |
96 | } | 97 | } |
@@ -99,10 +100,6 @@ struct cmd_results *cmd_input(int argc, char **argv) { | |||
99 | free(error); | 100 | free(error); |
100 | return res; | 101 | return res; |
101 | } | 102 | } |
102 | xkb_keymap_unref(keymap); | ||
103 | |||
104 | struct input_config *ic = | ||
105 | store_input_config(config->handler_context.input_config); | ||
106 | 103 | ||
107 | input_manager_apply_input_config(ic); | 104 | input_manager_apply_input_config(ic); |
108 | retranslate_keysyms(ic); | 105 | retranslate_keysyms(ic); |
diff --git a/sway/commands/input/events.c b/sway/commands/input/events.c index 44bc9e74..cd2985ee 100644 --- a/sway/commands/input/events.c +++ b/sway/commands/input/events.c | |||
@@ -101,7 +101,7 @@ static void toggle_wildcard_send_events(int argc, char **argv) { | |||
101 | } else { | 101 | } else { |
102 | toggle_supported_send_events_for_device(ic, input_device); | 102 | toggle_supported_send_events_for_device(ic, input_device); |
103 | } | 103 | } |
104 | store_input_config(ic); | 104 | store_input_config(ic, NULL); |
105 | } | 105 | } |
106 | } | 106 | } |
107 | 107 | ||
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 @@ | |||
3 | #include <limits.h> | 3 | #include <limits.h> |
4 | #include <float.h> | 4 | #include <float.h> |
5 | #include "sway/config.h" | 5 | #include "sway/config.h" |
6 | #include "sway/input/keyboard.h" | ||
6 | #include "log.h" | 7 | #include "log.h" |
7 | 8 | ||
8 | struct input_config *new_input_config(const char* identifier) { | 9 | 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) { | |||
133 | } | 134 | } |
134 | } | 135 | } |
135 | 136 | ||
136 | static void merge_wildcard_on_all(struct input_config *wildcard) { | 137 | static bool validate_xkb_merge(struct input_config *dest, |
138 | struct input_config *src, char **xkb_error) { | ||
139 | struct input_config *temp = new_input_config("temp"); | ||
140 | if (dest) { | ||
141 | merge_input_config(temp, dest); | ||
142 | } | ||
143 | merge_input_config(temp, src); | ||
144 | |||
145 | struct xkb_keymap *keymap = sway_keyboard_compile_keymap(temp, xkb_error); | ||
146 | free_input_config(temp); | ||
147 | if (!keymap) { | ||
148 | return false; | ||
149 | } | ||
150 | |||
151 | xkb_keymap_unref(keymap); | ||
152 | return true; | ||
153 | } | ||
154 | |||
155 | static bool validate_wildcard_on_all(struct input_config *wildcard, | ||
156 | char **error) { | ||
137 | for (int i = 0; i < config->input_configs->length; i++) { | 157 | for (int i = 0; i < config->input_configs->length; i++) { |
138 | struct input_config *ic = config->input_configs->items[i]; | 158 | struct input_config *ic = config->input_configs->items[i]; |
139 | if (strcmp(wildcard->identifier, ic->identifier) != 0) { | 159 | if (strcmp(wildcard->identifier, ic->identifier) != 0) { |
140 | sway_log(SWAY_DEBUG, "Merging input * config on %s", ic->identifier); | 160 | sway_log(SWAY_DEBUG, "Validating xkb merge of * on %s", |
141 | merge_input_config(ic, wildcard); | 161 | ic->identifier); |
162 | if (!validate_xkb_merge(ic, wildcard, error)) { | ||
163 | return false; | ||
164 | } | ||
142 | } | 165 | } |
143 | } | 166 | } |
144 | 167 | ||
145 | for (int i = 0; i < config->input_type_configs->length; i++) { | 168 | for (int i = 0; i < config->input_type_configs->length; i++) { |
146 | struct input_config *ic = config->input_type_configs->items[i]; | 169 | struct input_config *ic = config->input_type_configs->items[i]; |
170 | sway_log(SWAY_DEBUG, "Validating xkb merge of * config on %s", | ||
171 | ic->identifier); | ||
172 | if (!validate_xkb_merge(ic, wildcard, error)) { | ||
173 | return false; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | return true; | ||
178 | } | ||
179 | |||
180 | static void merge_wildcard_on_all(struct input_config *wildcard) { | ||
181 | for (int i = 0; i < config->input_configs->length; i++) { | ||
182 | struct input_config *ic = config->input_configs->items[i]; | ||
147 | if (strcmp(wildcard->identifier, ic->identifier) != 0) { | 183 | if (strcmp(wildcard->identifier, ic->identifier) != 0) { |
148 | sway_log(SWAY_DEBUG, "Merging input * config on %s", ic->identifier); | 184 | sway_log(SWAY_DEBUG, "Merging input * config on %s", ic->identifier); |
149 | merge_input_config(ic, wildcard); | 185 | merge_input_config(ic, wildcard); |
150 | } | 186 | } |
151 | } | 187 | } |
188 | |||
189 | for (int i = 0; i < config->input_type_configs->length; i++) { | ||
190 | struct input_config *ic = config->input_type_configs->items[i]; | ||
191 | sway_log(SWAY_DEBUG, "Merging input * config on %s", ic->identifier); | ||
192 | merge_input_config(ic, wildcard); | ||
193 | } | ||
194 | } | ||
195 | |||
196 | static bool validate_type_on_existing(struct input_config *type_wildcard, | ||
197 | char **error) { | ||
198 | for (int i = 0; i < config->input_configs->length; i++) { | ||
199 | struct input_config *ic = config->input_configs->items[i]; | ||
200 | if (ic->input_type == NULL) { | ||
201 | continue; | ||
202 | } | ||
203 | |||
204 | if (strcmp(ic->input_type, type_wildcard->identifier + 5) == 0) { | ||
205 | sway_log(SWAY_DEBUG, "Validating merge of %s on %s", | ||
206 | type_wildcard->identifier, ic->identifier); | ||
207 | if (!validate_xkb_merge(ic, type_wildcard, error)) { | ||
208 | return false; | ||
209 | } | ||
210 | } | ||
211 | } | ||
212 | return true; | ||
152 | } | 213 | } |
153 | 214 | ||
154 | static void merge_type_on_existing(struct input_config *type_wildcard) { | 215 | 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) { | |||
167 | } | 228 | } |
168 | } | 229 | } |
169 | 230 | ||
170 | struct input_config *store_input_config(struct input_config *ic) { | 231 | struct input_config *store_input_config(struct input_config *ic, |
232 | char **error) { | ||
171 | bool wildcard = strcmp(ic->identifier, "*") == 0; | 233 | bool wildcard = strcmp(ic->identifier, "*") == 0; |
234 | if (wildcard && error && !validate_wildcard_on_all(ic, error)) { | ||
235 | return NULL; | ||
236 | } | ||
237 | |||
238 | bool type = strncmp(ic->identifier, "type:", strlen("type:")) == 0; | ||
239 | if (type && error && !validate_type_on_existing(ic, error)) { | ||
240 | return NULL; | ||
241 | } | ||
242 | |||
243 | list_t *config_list = type ? config->input_type_configs | ||
244 | : config->input_configs; | ||
245 | |||
246 | struct input_config *current = NULL; | ||
247 | bool new_current = false; | ||
248 | |||
249 | int i = list_seq_find(config_list, input_identifier_cmp, ic->identifier); | ||
250 | if (i >= 0) { | ||
251 | current = config_list->items[i]; | ||
252 | } | ||
253 | |||
254 | i = list_seq_find(config->input_configs, input_identifier_cmp, "*"); | ||
255 | if (!current && i >= 0) { | ||
256 | current = new_input_config(ic->identifier); | ||
257 | merge_input_config(current, config->input_configs->items[i]); | ||
258 | new_current = true; | ||
259 | } | ||
260 | |||
261 | if (error && !validate_xkb_merge(current, ic, error)) { | ||
262 | if (new_current) { | ||
263 | free_input_config(current); | ||
264 | } | ||
265 | return NULL; | ||
266 | } | ||
267 | |||
172 | if (wildcard) { | 268 | if (wildcard) { |
173 | merge_wildcard_on_all(ic); | 269 | merge_wildcard_on_all(ic); |
174 | } | 270 | } |
175 | 271 | ||
176 | list_t *config_list = NULL; | 272 | if (type) { |
177 | if (strncmp(ic->identifier, "type:", 5) == 0) { | ||
178 | config_list = config->input_type_configs; | ||
179 | merge_type_on_existing(ic); | 273 | merge_type_on_existing(ic); |
180 | } else { | ||
181 | config_list = config->input_configs; | ||
182 | } | 274 | } |
183 | 275 | ||
184 | int i = list_seq_find(config_list, input_identifier_cmp, | 276 | if (current) { |
185 | ic->identifier); | ||
186 | if (i >= 0) { | ||
187 | sway_log(SWAY_DEBUG, "Merging on top of existing input config"); | ||
188 | struct input_config *current = config_list->items[i]; | ||
189 | merge_input_config(current, ic); | 277 | merge_input_config(current, ic); |
190 | free_input_config(ic); | 278 | free_input_config(ic); |
191 | ic = current; | 279 | ic = current; |
192 | } else if (!wildcard) { | 280 | } |
193 | sway_log(SWAY_DEBUG, "Adding non-wildcard input config"); | 281 | |
194 | i = list_seq_find(config->input_configs, input_identifier_cmp, "*"); | 282 | if (!current || new_current) { |
195 | if (i >= 0) { | ||
196 | sway_log(SWAY_DEBUG, "Merging on top of input * config"); | ||
197 | struct input_config *current = new_input_config(ic->identifier); | ||
198 | merge_input_config(current, config->input_configs->items[i]); | ||
199 | merge_input_config(current, ic); | ||
200 | free_input_config(ic); | ||
201 | ic = current; | ||
202 | } | ||
203 | list_add(config_list, ic); | 283 | list_add(config_list, ic); |
204 | } else { | ||
205 | // New wildcard config. Just add it | ||
206 | sway_log(SWAY_DEBUG, "Adding input * config"); | ||
207 | list_add(config->input_configs, ic); | ||
208 | } | 284 | } |
209 | 285 | ||
210 | sway_log(SWAY_DEBUG, "Config stored for input %s", ic->identifier); | 286 | sway_log(SWAY_DEBUG, "Config stored for input %s", ic->identifier); |