aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Ed Younis <edyounis123@gmail.com>2019-07-12 19:04:29 -0700
committerLibravatar Brian Ashworth <bosrsf04@gmail.com>2019-07-17 19:26:58 -0400
commiteb770e88b7396e892898d6a71867d2a603e707ff (patch)
treeb4f04a7316b1c25286daabee57025fb1e7307919
parentAdd missing description for focus_on_window_activation command in docs. (diff)
downloadsway-eb770e88b7396e892898d6a71867d2a603e707ff.tar.gz
sway-eb770e88b7396e892898d6a71867d2a603e707ff.tar.zst
sway-eb770e88b7396e892898d6a71867d2a603e707ff.zip
Implement input_cmd_xkb_file (#3999)
Adds a new commend "xkb_file", which constructs the internal xkb_keymap from a xkb file rather than an RMLVO configuration. This allows greater flexibility when specifying xkb configurations. An xkb file can be dumped with the xkbcomp program.
-rw-r--r--include/sway/commands.h1
-rw-r--r--include/sway/config.h3
-rw-r--r--sway/commands/input.c5
-rw-r--r--sway/commands/input/xkb_file.c28
-rw-r--r--sway/config/input.c9
-rw-r--r--sway/input/keyboard.c47
-rw-r--r--sway/meson.build1
-rw-r--r--sway/sway-input.5.scd5
8 files changed, 90 insertions, 9 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index ddee2994..7ff3b651 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -257,6 +257,7 @@ sway_cmd input_cmd_scroll_method;
257sway_cmd input_cmd_tap; 257sway_cmd input_cmd_tap;
258sway_cmd input_cmd_tap_button_map; 258sway_cmd input_cmd_tap_button_map;
259sway_cmd input_cmd_xkb_capslock; 259sway_cmd input_cmd_xkb_capslock;
260sway_cmd input_cmd_xkb_file;
260sway_cmd input_cmd_xkb_layout; 261sway_cmd input_cmd_xkb_layout;
261sway_cmd input_cmd_xkb_model; 262sway_cmd input_cmd_xkb_model;
262sway_cmd input_cmd_xkb_numlock; 263sway_cmd input_cmd_xkb_numlock;
diff --git a/include/sway/config.h b/include/sway/config.h
index c5558c0d..f1426453 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -138,6 +138,9 @@ struct input_config {
138 char *xkb_options; 138 char *xkb_options;
139 char *xkb_rules; 139 char *xkb_rules;
140 char *xkb_variant; 140 char *xkb_variant;
141 char *xkb_file;
142
143 bool xkb_file_is_set;
141 144
142 int xkb_numlock; 145 int xkb_numlock;
143 int xkb_capslock; 146 int xkb_capslock;
diff --git a/sway/commands/input.c b/sway/commands/input.c
index 588ef2d5..2289ede5 100644
--- a/sway/commands/input.c
+++ b/sway/commands/input.c
@@ -28,6 +28,7 @@ static struct cmd_handler input_handlers[] = {
28 { "scroll_method", input_cmd_scroll_method }, 28 { "scroll_method", input_cmd_scroll_method },
29 { "tap", input_cmd_tap }, 29 { "tap", input_cmd_tap },
30 { "tap_button_map", input_cmd_tap_button_map }, 30 { "tap_button_map", input_cmd_tap_button_map },
31 { "xkb_file", input_cmd_xkb_file },
31 { "xkb_layout", input_cmd_xkb_layout }, 32 { "xkb_layout", input_cmd_xkb_layout },
32 { "xkb_model", input_cmd_xkb_model }, 33 { "xkb_model", input_cmd_xkb_model },
33 { "xkb_options", input_cmd_xkb_options }, 34 { "xkb_options", input_cmd_xkb_options },
@@ -48,8 +49,8 @@ static struct cmd_handler input_config_handlers[] = {
48static void retranslate_keysyms(struct input_config *input_config) { 49static void retranslate_keysyms(struct input_config *input_config) {
49 for (int i = 0; i < config->input_configs->length; ++i) { 50 for (int i = 0; i < config->input_configs->length; ++i) {
50 struct input_config *ic = config->input_configs->items[i]; 51 struct input_config *ic = config->input_configs->items[i];
51 if (ic->xkb_layout) { 52 if (ic->xkb_layout || ic->xkb_file) {
52 // this is the first config with xkb_layout 53 // this is the first config with xkb_layout or xkb_file
53 if (ic->identifier == input_config->identifier) { 54 if (ic->identifier == input_config->identifier) {
54 translate_keysyms(ic); 55 translate_keysyms(ic);
55 } 56 }
diff --git a/sway/commands/input/xkb_file.c b/sway/commands/input/xkb_file.c
new file mode 100644
index 00000000..063f544d
--- /dev/null
+++ b/sway/commands/input/xkb_file.c
@@ -0,0 +1,28 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/config.h"
3#include "sway/commands.h"
4#include "sway/input/input-manager.h"
5#include "log.h"
6
7struct cmd_results *input_cmd_xkb_file(int argc, char **argv) {
8 struct cmd_results *error = NULL;
9 if ((error = checkarg(argc, "xkb_file", EXPECTED_EQUAL_TO, 1))) {
10 return error;
11 }
12 struct input_config *ic = config->handler_context.input_config;
13 if (!ic) {
14 return cmd_results_new(CMD_FAILURE, "No input device defined.");
15 }
16
17 if (strcmp(argv[0], "-") == 0) {
18 free(ic->xkb_file);
19 ic->xkb_file = NULL;
20 } else {
21 ic->xkb_file = strdup(argv[0]);
22 }
23 ic->xkb_file_is_set = true;
24
25 sway_log(SWAY_DEBUG, "set-xkb_file for config: %s file: %s",
26 ic->identifier, ic->xkb_file);
27 return cmd_results_new(CMD_SUCCESS, NULL);
28}
diff --git a/sway/config/input.c b/sway/config/input.c
index b5be4f26..ad4a64ee 100644
--- a/sway/config/input.c
+++ b/sway/config/input.c
@@ -39,6 +39,7 @@ struct input_config *new_input_config(const char* identifier) {
39 input->repeat_rate = INT_MIN; 39 input->repeat_rate = INT_MIN;
40 input->xkb_numlock = INT_MIN; 40 input->xkb_numlock = INT_MIN;
41 input->xkb_capslock = INT_MIN; 41 input->xkb_capslock = INT_MIN;
42 input->xkb_file_is_set = false;
42 43
43 return input; 44 return input;
44} 45}
@@ -95,6 +96,11 @@ void merge_input_config(struct input_config *dst, struct input_config *src) {
95 if (src->tap_button_map != INT_MIN) { 96 if (src->tap_button_map != INT_MIN) {
96 dst->tap_button_map = src->tap_button_map; 97 dst->tap_button_map = src->tap_button_map;
97 } 98 }
99 if (src->xkb_file_is_set) {
100 free(dst->xkb_file);
101 dst->xkb_file = src->xkb_file ? strdup(src->xkb_file) : NULL;
102 dst->xkb_file_is_set = dst->xkb_file != NULL;
103 }
98 if (src->xkb_layout) { 104 if (src->xkb_layout) {
99 free(dst->xkb_layout); 105 free(dst->xkb_layout);
100 dst->xkb_layout = strdup(src->xkb_layout); 106 dst->xkb_layout = strdup(src->xkb_layout);
@@ -284,6 +290,8 @@ struct input_config *store_input_config(struct input_config *ic,
284 ic = current; 290 ic = current;
285 } 291 }
286 292
293 ic->xkb_file_is_set = ic->xkb_file != NULL;
294
287 if (!current || new_current) { 295 if (!current || new_current) {
288 list_add(config_list, ic); 296 list_add(config_list, ic);
289 } 297 }
@@ -307,6 +315,7 @@ void free_input_config(struct input_config *ic) {
307 return; 315 return;
308 } 316 }
309 free(ic->identifier); 317 free(ic->identifier);
318 free(ic->xkb_file);
310 free(ic->xkb_layout); 319 free(ic->xkb_layout);
311 free(ic->xkb_model); 320 free(ic->xkb_model);
312 free(ic->xkb_options); 321 free(ic->xkb_options);
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c
index ef20a3cf..1f7ed849 100644
--- a/sway/input/keyboard.c
+++ b/sway/input/keyboard.c
@@ -534,11 +534,6 @@ static void handle_xkb_context_log(struct xkb_context *context,
534 534
535struct xkb_keymap *sway_keyboard_compile_keymap(struct input_config *ic, 535struct xkb_keymap *sway_keyboard_compile_keymap(struct input_config *ic,
536 char **error) { 536 char **error) {
537 struct xkb_rule_names rules = {0};
538 if (ic) {
539 input_config_fill_rule_names(ic, &rules);
540 }
541
542 struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); 537 struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
543 if (!sway_assert(context, "cannot create XKB context")) { 538 if (!sway_assert(context, "cannot create XKB context")) {
544 return NULL; 539 return NULL;
@@ -546,8 +541,46 @@ struct xkb_keymap *sway_keyboard_compile_keymap(struct input_config *ic,
546 xkb_context_set_user_data(context, error); 541 xkb_context_set_user_data(context, error);
547 xkb_context_set_log_fn(context, handle_xkb_context_log); 542 xkb_context_set_log_fn(context, handle_xkb_context_log);
548 543
549 struct xkb_keymap *keymap = 544 struct xkb_keymap *keymap = NULL;
550 xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); 545
546 if (ic && ic->xkb_file) {
547 FILE *keymap_file = fopen(ic->xkb_file, "r");
548 if (!keymap_file) {
549 if (error) {
550 size_t len = snprintf(NULL, 0, "cannot read XKB file %s: %s",
551 ic->xkb_file, strerror(errno)) + 1;
552 *error = malloc(len);
553 if (*error) {
554 snprintf(*error, len, "cannot read XKB file %s: %s",
555 ic->xkb_file, strerror(errno));
556 } else {
557 sway_log_errno(SWAY_ERROR, "cannot read XKB file %s: %s",
558 ic->xkb_file, strerror(errno));
559 }
560 } else {
561 sway_log_errno(SWAY_ERROR, "cannot read XKB file %s: %s",
562 ic->xkb_file, strerror(errno));
563 }
564 goto cleanup;
565 }
566
567 keymap = xkb_keymap_new_from_file(context, keymap_file,
568 XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
569
570 if (!fclose(keymap_file)) {
571 sway_log_errno(SWAY_ERROR, "cannot close XKB file %s: %s",
572 ic->xkb_file, strerror(errno));
573 }
574 } else {
575 struct xkb_rule_names rules = {0};
576 if (ic) {
577 input_config_fill_rule_names(ic, &rules);
578 }
579 keymap = xkb_keymap_new_from_names(context, &rules,
580 XKB_KEYMAP_COMPILE_NO_FLAGS);
581 }
582
583cleanup:
551 xkb_context_set_user_data(context, NULL); 584 xkb_context_set_user_data(context, NULL);
552 xkb_context_unref(context); 585 xkb_context_unref(context);
553 return keymap; 586 return keymap;
diff --git a/sway/meson.build b/sway/meson.build
index c60be008..934dbe68 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -160,6 +160,7 @@ sway_sources = files(
160 'commands/input/tap.c', 160 'commands/input/tap.c',
161 'commands/input/tap_button_map.c', 161 'commands/input/tap_button_map.c',
162 'commands/input/xkb_capslock.c', 162 'commands/input/xkb_capslock.c',
163 'commands/input/xkb_file.c',
163 'commands/input/xkb_layout.c', 164 'commands/input/xkb_layout.c',
164 'commands/input/xkb_model.c', 165 'commands/input/xkb_model.c',
165 'commands/input/xkb_numlock.c', 166 'commands/input/xkb_numlock.c',
diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd
index 4fb14fd2..9a9c5c4c 100644
--- a/sway/sway-input.5.scd
+++ b/sway/sway-input.5.scd
@@ -44,6 +44,11 @@ on top of the existing device configurations.
44For more information on these xkb configuration options, see 44For more information on these xkb configuration options, see
45*xkeyboard-config*(7). 45*xkeyboard-config*(7).
46 46
47*input* <identifier> xkb_file <file_name>
48 Sets all xkb configurations from a complete .xkb file. This file can be
49 dumped from _xkbcomp $DISPLAY keymap.xkb_. This setting overrides
50 xkb_layout, xkb_model, xkb_options, xkb_rules, and xkb_variant settings.
51
47*input* <identifier> xkb_layout <layout_name> 52*input* <identifier> xkb_layout <layout_name>
48 Sets the layout of the keyboard like _us_ or _de_. 53 Sets the layout of the keyboard like _us_ or _de_.
49 54