From 2166dbe2e49fc5eeb345d744424db360ee63f508 Mon Sep 17 00:00:00 2001 From: ProgAndy Date: Sun, 22 Jul 2018 21:16:19 +0200 Subject: [PATCH 1/5] Implement setting NumLock and CapsLock status After setting the keymap, try to enable NumLock and disable CapsLock. This only works if sway has the xkb master state and controls the keyboard. Prepare configuration settings for later use as well. --- include/sway/config.h | 3 +++ sway/config/input.c | 8 ++++++++ sway/input/keyboard.c | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/include/sway/config.h b/include/sway/config.h index 4a6bb7802..0f74b4392 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -101,6 +101,9 @@ struct input_config { char *xkb_rules; char *xkb_variant; + int xkb_numlock; + int xkb_capslock; + struct input_config_mapped_from_region *mapped_from_region; char *mapped_to_output; diff --git a/sway/config/input.c b/sway/config/input.c index 8d687a6d0..9885e85c8 100644 --- a/sway/config/input.c +++ b/sway/config/input.c @@ -33,6 +33,8 @@ struct input_config *new_input_config(const char* identifier) { input->left_handed = INT_MIN; input->repeat_delay = INT_MIN; input->repeat_rate = INT_MIN; + input->xkb_numlock = INT_MIN; + input->xkb_capslock = INT_MIN; return input; } @@ -104,6 +106,12 @@ void merge_input_config(struct input_config *dst, struct input_config *src) { free(dst->xkb_variant); dst->xkb_variant = strdup(src->xkb_variant); } + if (src->xkb_numlock != INT_MIN) { + dst->xkb_numlock = src->xkb_numlock; + } + if (src->xkb_capslock != INT_MIN) { + dst->xkb_capslock = src->xkb_capslock; + } if (src->mapped_from_region) { free(dst->mapped_from_region); dst->mapped_from_region = diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 49241db84..36c5a064e 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "sway/commands.h" #include "sway/desktop/transaction.h" #include "sway/input/input-manager.h" @@ -385,6 +386,23 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { keyboard->keymap = keymap; wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); + xkb_mod_mask_t locked_mods = 0; + if (!input_config || input_config->xkb_numlock != 0) { + xkb_mod_index_t mod_index = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_NUM); + if (mod_index != XKB_MOD_INVALID) { + locked_mods |= (uint32_t)1 << mod_index; + } + } + if (input_config && input_config->xkb_capslock > 0) { + xkb_mod_index_t mod_index = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_CAPS); + if (mod_index != XKB_MOD_INVALID) { + locked_mods |= (uint32_t)1 << mod_index; + } + } + if (locked_mods) { + wlr_keyboard_notify_modifiers(wlr_device->keyboard, 0, 0, locked_mods, 0); + } + if (input_config && input_config->repeat_delay != INT_MIN && input_config->repeat_rate != INT_MIN) { wlr_keyboard_set_repeat_info(wlr_device->keyboard, From c7a3a03115aa672b8abd1155e7e93e6328512326 Mon Sep 17 00:00:00 2001 From: ProgAndy Date: Sun, 22 Jul 2018 22:22:16 +0200 Subject: [PATCH 2/5] Add xkb_numlock/xkb_capslock commands (#2311) --- include/sway/commands.h | 2 ++ sway/commands/input.c | 2 ++ sway/commands/input/xkb_capslock.c | 33 ++++++++++++++++++++++++++++++ sway/commands/input/xkb_numlock.c | 33 ++++++++++++++++++++++++++++++ sway/meson.build | 2 ++ 5 files changed, 72 insertions(+) create mode 100644 sway/commands/input/xkb_capslock.c create mode 100644 sway/commands/input/xkb_numlock.c diff --git a/include/sway/commands.h b/include/sway/commands.h index f53d335a3..41858ccca 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -213,8 +213,10 @@ sway_cmd input_cmd_scroll_button; sway_cmd input_cmd_scroll_method; sway_cmd input_cmd_tap; sway_cmd input_cmd_tap_button_map; +sway_cmd input_cmd_xkb_capslock; sway_cmd input_cmd_xkb_layout; sway_cmd input_cmd_xkb_model; +sway_cmd input_cmd_xkb_numlock; sway_cmd input_cmd_xkb_options; sway_cmd input_cmd_xkb_rules; sway_cmd input_cmd_xkb_variant; diff --git a/sway/commands/input.c b/sway/commands/input.c index 5b203ea06..7f9270735 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -24,8 +24,10 @@ static struct cmd_handler input_handlers[] = { { "scroll_method", input_cmd_scroll_method }, { "tap", input_cmd_tap }, { "tap_button_map", input_cmd_tap_button_map }, + { "xkb_capslock", input_cmd_xkb_capslock }, { "xkb_layout", input_cmd_xkb_layout }, { "xkb_model", input_cmd_xkb_model }, + { "xkb_numlock", input_cmd_xkb_numlock }, { "xkb_options", input_cmd_xkb_options }, { "xkb_rules", input_cmd_xkb_rules }, { "xkb_variant", input_cmd_xkb_variant }, diff --git a/sway/commands/input/xkb_capslock.c b/sway/commands/input/xkb_capslock.c new file mode 100644 index 000000000..5442c463b --- /dev/null +++ b/sway/commands/input/xkb_capslock.c @@ -0,0 +1,33 @@ +#include +#include +#include "sway/config.h" +#include "sway/commands.h" +#include "sway/input/input-manager.h" + +struct cmd_results *input_cmd_xkb_capslock(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "xkb_capslock", EXPECTED_AT_LEAST, 1))) { + return error; + } + struct input_config *current_input_config = + config->handler_context.input_config; + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "xkb_capslock", + "No input device defined."); + } + struct input_config *new_config = + new_input_config(current_input_config->identifier); + + if (strcasecmp(argv[0], "enabled") == 0) { + new_config->xkb_capslock = 1; + } else if (strcasecmp(argv[0], "disabled") == 0) { + new_config->xkb_capslock = 0; + } else { + free_input_config(new_config); + return cmd_results_new(CMD_INVALID, "xkb_capslock", + "Expected 'xkb_capslock '"); + } + + apply_input_config(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/input/xkb_numlock.c b/sway/commands/input/xkb_numlock.c new file mode 100644 index 000000000..396753660 --- /dev/null +++ b/sway/commands/input/xkb_numlock.c @@ -0,0 +1,33 @@ +#include +#include +#include "sway/config.h" +#include "sway/commands.h" +#include "sway/input/input-manager.h" + +struct cmd_results *input_cmd_xkb_numlock(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "xkb_numlock", EXPECTED_AT_LEAST, 1))) { + return error; + } + struct input_config *current_input_config = + config->handler_context.input_config; + if (!current_input_config) { + return cmd_results_new(CMD_FAILURE, "xkb_numlock", + "No input device defined."); + } + struct input_config *new_config = + new_input_config(current_input_config->identifier); + + if (strcasecmp(argv[0], "enabled") == 0) { + new_config->xkb_numlock = 1; + } else if (strcasecmp(argv[0], "disabled") == 0) { + new_config->xkb_numlock = 0; + } else { + free_input_config(new_config); + return cmd_results_new(CMD_INVALID, "xkb_numlock", + "Expected 'xkb_numlock '"); + } + + apply_input_config(new_config); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/meson.build b/sway/meson.build index 649a3ac22..d92bb9051 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -128,8 +128,10 @@ sway_sources = files( 'commands/input/scroll_method.c', 'commands/input/tap.c', 'commands/input/tap_button_map.c', + 'commands/input/xkb_capslock.c', 'commands/input/xkb_layout.c', 'commands/input/xkb_model.c', + 'commands/input/xkb_numlock.c', 'commands/input/xkb_options.c', 'commands/input/xkb_rules.c', 'commands/input/xkb_variant.c', From d07463d53b2677ba0662b2b91aad484f67fc6405 Mon Sep 17 00:00:00 2001 From: ProgAndy Date: Mon, 23 Jul 2018 14:41:11 +0200 Subject: [PATCH 3/5] Add documentation for xkb_capslock/xkb_numlock --- sway/sway-input.5.scd | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index b63914312..372ca6977 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 *input* xkb\_variant Sets the variant of the keyboard like _dvorak_ or _colemak_. +*input* xkb\_capslock enabled|disabled + Enables or disables CapsLock on sway startup, the default is disabled. + Only meaningful if sway controls the keyboard. + +*input* xkb\_numlock enabled|disabled + Enables or disables NumLock on sway startup, the default is enabled. + Only meaningful if sway controls the keyboard. + ## MAPPING CONFIGURATION *input* map\_to\_output From 0ba52458abb8fb0414319d2084e6d0d0214ae304 Mon Sep 17 00:00:00 2001 From: ProgAndy Date: Wed, 25 Jul 2018 17:08:47 +0200 Subject: [PATCH 4/5] Restrict CapsLock and NumLock commands to the configuration file --- sway/commands/input.c | 23 ++++++++++++++++++++--- sway/sway-input.5.scd | 8 ++++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/sway/commands/input.c b/sway/commands/input.c index 7f9270735..84888fbb7 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -24,15 +24,19 @@ static struct cmd_handler input_handlers[] = { { "scroll_method", input_cmd_scroll_method }, { "tap", input_cmd_tap }, { "tap_button_map", input_cmd_tap_button_map }, - { "xkb_capslock", input_cmd_xkb_capslock }, { "xkb_layout", input_cmd_xkb_layout }, { "xkb_model", input_cmd_xkb_model }, - { "xkb_numlock", input_cmd_xkb_numlock }, { "xkb_options", input_cmd_xkb_options }, { "xkb_rules", input_cmd_xkb_rules }, { "xkb_variant", input_cmd_xkb_variant }, }; +// must be in order for the bsearch +static struct cmd_handler input_config_handlers[] = { + { "xkb_capslock", input_cmd_xkb_capslock }, + { "xkb_numlock", input_cmd_xkb_numlock }, +}; + struct cmd_results *cmd_input(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 2))) { @@ -46,8 +50,21 @@ struct cmd_results *cmd_input(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config"); } - struct cmd_results *res = config_subcommand(argv + 1, argc - 1, + struct cmd_results *res; + + if (find_handler(argv[1], input_config_handlers, + sizeof(input_config_handlers))) { + if (config->reading) { + res = config_subcommand(argv + 1, argc - 1, + input_config_handlers, sizeof(input_config_handlers)); + } else { + res = cmd_results_new(CMD_FAILURE, "input", + "Can only be used in config file."); + } + } else { + res = config_subcommand(argv + 1, argc - 1, input_handlers, sizeof(input_handlers)); + } free_input_config(config->handler_context.input_config); config->handler_context.input_config = NULL; diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index 372ca6977..fa3119713 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -33,13 +33,13 @@ For more information on these xkb configuration options, see *input* xkb\_variant Sets the variant of the keyboard like _dvorak_ or _colemak_. +The following commands may only be used in the configuration file. + *input* xkb\_capslock enabled|disabled - Enables or disables CapsLock on sway startup, the default is disabled. - Only meaningful if sway controls the keyboard. + Initially enables or disables CapsLock, the default is disabled. *input* xkb\_numlock enabled|disabled - Enables or disables NumLock on sway startup, the default is enabled. - Only meaningful if sway controls the keyboard. + Initially enables or disables NumLock, the default is enabled. ## MAPPING CONFIGURATION From 76ece5788bffe27b32c85968886f3738d244abf9 Mon Sep 17 00:00:00 2001 From: ProgAndy Date: Wed, 25 Jul 2018 17:09:34 +0200 Subject: [PATCH 5/5] Fix LEDs for configured modifier states --- sway/input/keyboard.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 36c5a064e..643ff510c 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -401,6 +401,14 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { } if (locked_mods) { wlr_keyboard_notify_modifiers(wlr_device->keyboard, 0, 0, locked_mods, 0); + uint32_t leds = 0; + for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { + if (xkb_state_led_index_is_active(wlr_device->keyboard->xkb_state, + wlr_device->keyboard->led_indexes[i])) { + leds |= (1 << i); + } + } + wlr_keyboard_led_update(wlr_device->keyboard, leds); } if (input_config && input_config->repeat_delay != INT_MIN