diff options
Diffstat (limited to 'sway/config/input.c')
-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 @@ | |||
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); |