aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);