diff options
-rw-r--r-- | include/sway/commands.h | 2 | ||||
-rw-r--r-- | include/sway/config.h | 3 | ||||
-rw-r--r-- | sway/commands/input.c | 21 | ||||
-rw-r--r-- | sway/commands/input/xkb_capslock.c | 33 | ||||
-rw-r--r-- | sway/commands/input/xkb_numlock.c | 33 | ||||
-rw-r--r-- | sway/config/input.c | 8 | ||||
-rw-r--r-- | sway/input/keyboard.c | 26 | ||||
-rw-r--r-- | sway/meson.build | 2 | ||||
-rw-r--r-- | sway/sway-input.5.scd | 8 |
9 files changed, 135 insertions, 1 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index f53d335a..41858ccc 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -213,8 +213,10 @@ sway_cmd input_cmd_scroll_button; | |||
213 | sway_cmd input_cmd_scroll_method; | 213 | sway_cmd input_cmd_scroll_method; |
214 | sway_cmd input_cmd_tap; | 214 | sway_cmd input_cmd_tap; |
215 | sway_cmd input_cmd_tap_button_map; | 215 | sway_cmd input_cmd_tap_button_map; |
216 | sway_cmd input_cmd_xkb_capslock; | ||
216 | sway_cmd input_cmd_xkb_layout; | 217 | sway_cmd input_cmd_xkb_layout; |
217 | sway_cmd input_cmd_xkb_model; | 218 | sway_cmd input_cmd_xkb_model; |
219 | sway_cmd input_cmd_xkb_numlock; | ||
218 | sway_cmd input_cmd_xkb_options; | 220 | sway_cmd input_cmd_xkb_options; |
219 | sway_cmd input_cmd_xkb_rules; | 221 | sway_cmd input_cmd_xkb_rules; |
220 | sway_cmd input_cmd_xkb_variant; | 222 | sway_cmd input_cmd_xkb_variant; |
diff --git a/include/sway/config.h b/include/sway/config.h index 4a6bb780..0f74b439 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -101,6 +101,9 @@ struct input_config { | |||
101 | char *xkb_rules; | 101 | char *xkb_rules; |
102 | char *xkb_variant; | 102 | char *xkb_variant; |
103 | 103 | ||
104 | int xkb_numlock; | ||
105 | int xkb_capslock; | ||
106 | |||
104 | struct input_config_mapped_from_region *mapped_from_region; | 107 | struct input_config_mapped_from_region *mapped_from_region; |
105 | char *mapped_to_output; | 108 | char *mapped_to_output; |
106 | 109 | ||
diff --git a/sway/commands/input.c b/sway/commands/input.c index 5b203ea0..84888fbb 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c | |||
@@ -31,6 +31,12 @@ static struct cmd_handler input_handlers[] = { | |||
31 | { "xkb_variant", input_cmd_xkb_variant }, | 31 | { "xkb_variant", input_cmd_xkb_variant }, |
32 | }; | 32 | }; |
33 | 33 | ||
34 | // must be in order for the bsearch | ||
35 | static struct cmd_handler input_config_handlers[] = { | ||
36 | { "xkb_capslock", input_cmd_xkb_capslock }, | ||
37 | { "xkb_numlock", input_cmd_xkb_numlock }, | ||
38 | }; | ||
39 | |||
34 | struct cmd_results *cmd_input(int argc, char **argv) { | 40 | struct cmd_results *cmd_input(int argc, char **argv) { |
35 | struct cmd_results *error = NULL; | 41 | struct cmd_results *error = NULL; |
36 | if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 2))) { | 42 | if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 2))) { |
@@ -44,8 +50,21 @@ struct cmd_results *cmd_input(int argc, char **argv) { | |||
44 | return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config"); | 50 | return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config"); |
45 | } | 51 | } |
46 | 52 | ||
47 | struct cmd_results *res = config_subcommand(argv + 1, argc - 1, | 53 | struct cmd_results *res; |
54 | |||
55 | if (find_handler(argv[1], input_config_handlers, | ||
56 | sizeof(input_config_handlers))) { | ||
57 | if (config->reading) { | ||
58 | res = config_subcommand(argv + 1, argc - 1, | ||
59 | input_config_handlers, sizeof(input_config_handlers)); | ||
60 | } else { | ||
61 | res = cmd_results_new(CMD_FAILURE, "input", | ||
62 | "Can only be used in config file."); | ||
63 | } | ||
64 | } else { | ||
65 | res = config_subcommand(argv + 1, argc - 1, | ||
48 | input_handlers, sizeof(input_handlers)); | 66 | input_handlers, sizeof(input_handlers)); |
67 | } | ||
49 | 68 | ||
50 | free_input_config(config->handler_context.input_config); | 69 | free_input_config(config->handler_context.input_config); |
51 | config->handler_context.input_config = NULL; | 70 | config->handler_context.input_config = NULL; |
diff --git a/sway/commands/input/xkb_capslock.c b/sway/commands/input/xkb_capslock.c new file mode 100644 index 00000000..5442c463 --- /dev/null +++ b/sway/commands/input/xkb_capslock.c | |||
@@ -0,0 +1,33 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/config.h" | ||
4 | #include "sway/commands.h" | ||
5 | #include "sway/input/input-manager.h" | ||
6 | |||
7 | struct cmd_results *input_cmd_xkb_capslock(int argc, char **argv) { | ||
8 | struct cmd_results *error = NULL; | ||
9 | if ((error = checkarg(argc, "xkb_capslock", EXPECTED_AT_LEAST, 1))) { | ||
10 | return error; | ||
11 | } | ||
12 | struct input_config *current_input_config = | ||
13 | config->handler_context.input_config; | ||
14 | if (!current_input_config) { | ||
15 | return cmd_results_new(CMD_FAILURE, "xkb_capslock", | ||
16 | "No input device defined."); | ||
17 | } | ||
18 | struct input_config *new_config = | ||
19 | new_input_config(current_input_config->identifier); | ||
20 | |||
21 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
22 | new_config->xkb_capslock = 1; | ||
23 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
24 | new_config->xkb_capslock = 0; | ||
25 | } else { | ||
26 | free_input_config(new_config); | ||
27 | return cmd_results_new(CMD_INVALID, "xkb_capslock", | ||
28 | "Expected 'xkb_capslock <enabled|disabled>'"); | ||
29 | } | ||
30 | |||
31 | apply_input_config(new_config); | ||
32 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
33 | } | ||
diff --git a/sway/commands/input/xkb_numlock.c b/sway/commands/input/xkb_numlock.c new file mode 100644 index 00000000..39675366 --- /dev/null +++ b/sway/commands/input/xkb_numlock.c | |||
@@ -0,0 +1,33 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/config.h" | ||
4 | #include "sway/commands.h" | ||
5 | #include "sway/input/input-manager.h" | ||
6 | |||
7 | struct cmd_results *input_cmd_xkb_numlock(int argc, char **argv) { | ||
8 | struct cmd_results *error = NULL; | ||
9 | if ((error = checkarg(argc, "xkb_numlock", EXPECTED_AT_LEAST, 1))) { | ||
10 | return error; | ||
11 | } | ||
12 | struct input_config *current_input_config = | ||
13 | config->handler_context.input_config; | ||
14 | if (!current_input_config) { | ||
15 | return cmd_results_new(CMD_FAILURE, "xkb_numlock", | ||
16 | "No input device defined."); | ||
17 | } | ||
18 | struct input_config *new_config = | ||
19 | new_input_config(current_input_config->identifier); | ||
20 | |||
21 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
22 | new_config->xkb_numlock = 1; | ||
23 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
24 | new_config->xkb_numlock = 0; | ||
25 | } else { | ||
26 | free_input_config(new_config); | ||
27 | return cmd_results_new(CMD_INVALID, "xkb_numlock", | ||
28 | "Expected 'xkb_numlock <enabled|disabled>'"); | ||
29 | } | ||
30 | |||
31 | apply_input_config(new_config); | ||
32 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
33 | } | ||
diff --git a/sway/config/input.c b/sway/config/input.c index 8d687a6d..9885e85c 100644 --- a/sway/config/input.c +++ b/sway/config/input.c | |||
@@ -33,6 +33,8 @@ struct input_config *new_input_config(const char* identifier) { | |||
33 | input->left_handed = INT_MIN; | 33 | input->left_handed = INT_MIN; |
34 | input->repeat_delay = INT_MIN; | 34 | input->repeat_delay = INT_MIN; |
35 | input->repeat_rate = INT_MIN; | 35 | input->repeat_rate = INT_MIN; |
36 | input->xkb_numlock = INT_MIN; | ||
37 | input->xkb_capslock = INT_MIN; | ||
36 | 38 | ||
37 | return input; | 39 | return input; |
38 | } | 40 | } |
@@ -104,6 +106,12 @@ void merge_input_config(struct input_config *dst, struct input_config *src) { | |||
104 | free(dst->xkb_variant); | 106 | free(dst->xkb_variant); |
105 | dst->xkb_variant = strdup(src->xkb_variant); | 107 | dst->xkb_variant = strdup(src->xkb_variant); |
106 | } | 108 | } |
109 | if (src->xkb_numlock != INT_MIN) { | ||
110 | dst->xkb_numlock = src->xkb_numlock; | ||
111 | } | ||
112 | if (src->xkb_capslock != INT_MIN) { | ||
113 | dst->xkb_capslock = src->xkb_capslock; | ||
114 | } | ||
107 | if (src->mapped_from_region) { | 115 | if (src->mapped_from_region) { |
108 | free(dst->mapped_from_region); | 116 | free(dst->mapped_from_region); |
109 | dst->mapped_from_region = | 117 | dst->mapped_from_region = |
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 49241db8..643ff510 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <wlr/backend/multi.h> | 3 | #include <wlr/backend/multi.h> |
4 | #include <wlr/backend/session.h> | 4 | #include <wlr/backend/session.h> |
5 | #include <wlr/types/wlr_idle.h> | 5 | #include <wlr/types/wlr_idle.h> |
6 | #include <wlr/interfaces/wlr_keyboard.h> | ||
6 | #include "sway/commands.h" | 7 | #include "sway/commands.h" |
7 | #include "sway/desktop/transaction.h" | 8 | #include "sway/desktop/transaction.h" |
8 | #include "sway/input/input-manager.h" | 9 | #include "sway/input/input-manager.h" |
@@ -385,6 +386,31 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { | |||
385 | keyboard->keymap = keymap; | 386 | keyboard->keymap = keymap; |
386 | wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); | 387 | wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); |
387 | 388 | ||
389 | xkb_mod_mask_t locked_mods = 0; | ||
390 | if (!input_config || input_config->xkb_numlock != 0) { | ||
391 | xkb_mod_index_t mod_index = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_NUM); | ||
392 | if (mod_index != XKB_MOD_INVALID) { | ||
393 | locked_mods |= (uint32_t)1 << mod_index; | ||
394 | } | ||
395 | } | ||
396 | if (input_config && input_config->xkb_capslock > 0) { | ||
397 | xkb_mod_index_t mod_index = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_CAPS); | ||
398 | if (mod_index != XKB_MOD_INVALID) { | ||
399 | locked_mods |= (uint32_t)1 << mod_index; | ||
400 | } | ||
401 | } | ||
402 | if (locked_mods) { | ||
403 | wlr_keyboard_notify_modifiers(wlr_device->keyboard, 0, 0, locked_mods, 0); | ||
404 | uint32_t leds = 0; | ||
405 | for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { | ||
406 | if (xkb_state_led_index_is_active(wlr_device->keyboard->xkb_state, | ||
407 | wlr_device->keyboard->led_indexes[i])) { | ||
408 | leds |= (1 << i); | ||
409 | } | ||
410 | } | ||
411 | wlr_keyboard_led_update(wlr_device->keyboard, leds); | ||
412 | } | ||
413 | |||
388 | if (input_config && input_config->repeat_delay != INT_MIN | 414 | if (input_config && input_config->repeat_delay != INT_MIN |
389 | && input_config->repeat_rate != INT_MIN) { | 415 | && input_config->repeat_rate != INT_MIN) { |
390 | wlr_keyboard_set_repeat_info(wlr_device->keyboard, | 416 | wlr_keyboard_set_repeat_info(wlr_device->keyboard, |
diff --git a/sway/meson.build b/sway/meson.build index 649a3ac2..d92bb905 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -128,8 +128,10 @@ sway_sources = files( | |||
128 | 'commands/input/scroll_method.c', | 128 | 'commands/input/scroll_method.c', |
129 | 'commands/input/tap.c', | 129 | 'commands/input/tap.c', |
130 | 'commands/input/tap_button_map.c', | 130 | 'commands/input/tap_button_map.c', |
131 | 'commands/input/xkb_capslock.c', | ||
131 | 'commands/input/xkb_layout.c', | 132 | 'commands/input/xkb_layout.c', |
132 | 'commands/input/xkb_model.c', | 133 | 'commands/input/xkb_model.c', |
134 | 'commands/input/xkb_numlock.c', | ||
133 | 'commands/input/xkb_options.c', | 135 | 'commands/input/xkb_options.c', |
134 | 'commands/input/xkb_rules.c', | 136 | 'commands/input/xkb_rules.c', |
135 | 'commands/input/xkb_variant.c', | 137 | 'commands/input/xkb_variant.c', |
diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index b6391431..fa311971 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd | |||
@@ -33,6 +33,14 @@ For more information on these xkb configuration options, see | |||
33 | *input* <identifier> xkb\_variant <variant> | 33 | *input* <identifier> xkb\_variant <variant> |
34 | Sets the variant of the keyboard like _dvorak_ or _colemak_. | 34 | Sets the variant of the keyboard like _dvorak_ or _colemak_. |
35 | 35 | ||
36 | The following commands may only be used in the configuration file. | ||
37 | |||
38 | *input* <identifier> xkb\_capslock enabled|disabled | ||
39 | Initially enables or disables CapsLock, the default is disabled. | ||
40 | |||
41 | *input* <identifier> xkb\_numlock enabled|disabled | ||
42 | Initially enables or disables NumLock, the default is enabled. | ||
43 | |||
36 | ## MAPPING CONFIGURATION | 44 | ## MAPPING CONFIGURATION |
37 | 45 | ||
38 | *input* <identifier> map\_to\_output <identifier> | 46 | *input* <identifier> map\_to\_output <identifier> |