aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2019-06-05 14:16:37 -0400
committerLibravatar Simon Ser <contact@emersion.fr>2019-06-09 20:13:22 +0300
commit5b1a8d62b9c8fa7c25b70e01910abd761fae9855 (patch)
tree173ef18191acf9dfb84b3bb76c43ee8108f4cd89
parentcommands/input: perform basic keymap validation (diff)
downloadsway-5b1a8d62b9c8fa7c25b70e01910abd761fae9855.tar.gz
sway-5b1a8d62b9c8fa7c25b70e01910abd761fae9855.tar.zst
sway-5b1a8d62b9c8fa7c25b70e01910abd761fae9855.zip
config/input: validate xkb keymap before storing
This allows for an optional validation stage when storing an input config. Currently, only the xkb keymap is validated. If storing the delta input config will result in any invalid xkb keymaps, the input config will not be stored and error will be populated with the first line of the xkbcommon log.
-rw-r--r--include/sway/config.h2
-rw-r--r--sway/commands/input.c11
-rw-r--r--sway/commands/input/events.c2
-rw-r--r--sway/config/input.c134
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
582void merge_input_config(struct input_config *dst, struct input_config *src); 582void merge_input_config(struct input_config *dst, struct input_config *src);
583 583
584struct input_config *store_input_config(struct input_config *ic); 584struct input_config *store_input_config(struct input_config *ic, char **error);
585 585
586void input_config_fill_rule_names(struct input_config *ic, 586void 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
8struct input_config *new_input_config(const char* identifier) { 9struct 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
136static void merge_wildcard_on_all(struct input_config *wildcard) { 137static 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
155static 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
180static 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
196static 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
154static void merge_type_on_existing(struct input_config *type_wildcard) { 215static 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
170struct input_config *store_input_config(struct input_config *ic) { 231struct 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);