From 2bccb387d81298ffd3b88a193deb3e32c0b6c494 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 9 Jun 2019 21:17:28 +0300 Subject: [PATCH] Add a new xkb_switch_layout command This allows users to programatically change the active layout. --- include/sway/commands.h | 1 + sway/commands/input.c | 4 +- sway/commands/input/xkb_switch_layout.c | 51 +++++++++++++++++++++++++ sway/meson.build | 1 + 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 sway/commands/input/xkb_switch_layout.c diff --git a/include/sway/commands.h b/include/sway/commands.h index 927296b0..e0cd94d1 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -260,6 +260,7 @@ 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_switch_layout; sway_cmd input_cmd_xkb_variant; sway_cmd output_cmd_background; diff --git a/sway/commands/input.c b/sway/commands/input.c index d95c4baf..08af3cb2 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -31,6 +31,7 @@ static struct cmd_handler input_handlers[] = { { "xkb_model", input_cmd_xkb_model }, { "xkb_options", input_cmd_xkb_options }, { "xkb_rules", input_cmd_xkb_rules }, + { "xkb_switch_layout", input_cmd_xkb_switch_layout }, { "xkb_variant", input_cmd_xkb_variant }, }; @@ -86,7 +87,8 @@ struct cmd_results *cmd_input(int argc, char **argv) { input_handlers, sizeof(input_handlers)); } - if (!res || res->status == CMD_SUCCESS) { + if ((!res || res->status == CMD_SUCCESS) && + strcmp(argv[1], "xkb_switch_layout") != 0) { char *error = NULL; struct input_config *ic = store_input_config(config->handler_context.input_config, &error); diff --git a/sway/commands/input/xkb_switch_layout.c b/sway/commands/input/xkb_switch_layout.c new file mode 100644 index 00000000..fdf21452 --- /dev/null +++ b/sway/commands/input/xkb_switch_layout.c @@ -0,0 +1,51 @@ +#define _POSIX_C_SOURCE 200809L +#include "sway/config.h" +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "log.h" + +static void switch_layout(struct wlr_keyboard *kbd, xkb_layout_index_t idx) { + xkb_layout_index_t num_layouts = xkb_keymap_num_layouts(kbd->keymap); + if (idx >= num_layouts) { + return; + } + wlr_keyboard_notify_modifiers(kbd, kbd->modifiers.depressed, + kbd->modifiers.latched, kbd->modifiers.locked, idx); +} + +struct cmd_results *input_cmd_xkb_switch_layout(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "xkb_switch_layout", EXPECTED_EQUAL_TO, 1))) { + return error; + } + struct input_config *ic = config->handler_context.input_config; + if (!ic) { + return cmd_results_new(CMD_FAILURE, "No input device defined."); + } + + if (config->reading || !config->active) { + return cmd_results_new(CMD_DEFER, NULL); + } + + const char *layout_str = argv[0]; + + char *end; + int layout = strtol(layout_str, &end, 10); + if (layout_str[0] == '\0' || end[0] != '\0' || layout < 0) { + return cmd_results_new(CMD_FAILURE, "Invalid layout index."); + } + + struct sway_input_device *dev; + wl_list_for_each(dev, &server.input->devices, link) { + if (strcmp(ic->identifier, "*") != 0 && + strcmp(ic->identifier, dev->identifier) != 0) { + continue; + } + if (dev->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) { + continue; + } + switch_layout(dev->wlr_device->keyboard, layout); + } + + return cmd_results_new(CMD_SUCCESS, NULL); +} diff --git a/sway/meson.build b/sway/meson.build index 262d7057..99dab7e7 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -164,6 +164,7 @@ sway_sources = files( 'commands/input/xkb_numlock.c', 'commands/input/xkb_options.c', 'commands/input/xkb_rules.c', + 'commands/input/xkb_switch_layout.c', 'commands/input/xkb_variant.c', 'commands/output/background.c',