input: implement cycling through keyboard layout list

This commit is contained in:
Bor Grošelj Simić 2020-02-27 21:50:21 +01:00 committed by Simon Ser
parent 28e3187df1
commit 27d5cf1316
2 changed files with 48 additions and 9 deletions

View file

@ -1,4 +1,5 @@
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include "sway/config.h"
#include "sway/commands.h"
#include "sway/input/input-manager.h"
@ -13,6 +14,26 @@ static void switch_layout(struct wlr_keyboard *kbd, xkb_layout_index_t idx) {
kbd->modifiers.latched, kbd->modifiers.locked, idx);
}
static xkb_layout_index_t get_current_layout_index(struct wlr_keyboard *kbd) {
xkb_layout_index_t num_layouts = xkb_keymap_num_layouts(kbd->keymap);
assert(num_layouts > 0);
xkb_layout_index_t layout_idx;
for (layout_idx = 0; layout_idx < num_layouts; layout_idx++) {
if (xkb_state_layout_index_is_active(kbd->xkb_state,
layout_idx, XKB_STATE_LAYOUT_EFFECTIVE)) {
break;
}
}
return layout_idx;
}
static void switch_layout_relative(struct wlr_keyboard *kbd, int dir) {
xkb_layout_index_t num_layouts = xkb_keymap_num_layouts(kbd->keymap);
xkb_layout_index_t idx = get_current_layout_index(kbd);
switch_layout(kbd, (idx + num_layouts + dir) % num_layouts);
}
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))) {
@ -28,12 +49,22 @@ struct cmd_results *input_cmd_xkb_switch_layout(int argc, char **argv) {
}
const char *layout_str = argv[0];
int relative, layout;
if (strcmp(layout_str, "next") == 0) {
relative = 1;
} else if (strcmp(layout_str, "prev") == 0) {
relative = -1;
} else {
char *end;
int layout = strtol(layout_str, &end, 10);
if (layout_str[0] == '\0' || end[0] != '\0' || layout < 0) {
layout = strtol(layout_str, &end, 10);
if (layout_str[0] == '\0' || end[0] != '\0') {
return cmd_results_new(CMD_FAILURE, "Invalid argument.");
} else if (layout < 0) {
return cmd_results_new(CMD_FAILURE, "Invalid layout index.");
}
relative = 0;
}
struct sway_input_device *dev;
wl_list_for_each(dev, &server.input->devices, link) {
@ -45,8 +76,12 @@ struct cmd_results *input_cmd_xkb_switch_layout(int argc, char **argv) {
if (dev->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) {
continue;
}
if (relative) {
switch_layout_relative(dev->wlr_device->keyboard, relative);
} else {
switch_layout(dev->wlr_device->keyboard, layout);
}
}
return cmd_results_new(CMD_SUCCESS, NULL);
}

View file

@ -66,10 +66,14 @@ For more information on these xkb configuration options, see
*input* <identifier> xkb_rules <rules>
Sets files of rules to be used for keyboard mapping composition.
*input* <identifier> xkb_switch_layout <index>
Changes the active keyboard layout index. This can be used when multiple
layouts are configured with *xkb_layout*. A list of layouts you can switch
between can be obtained with *swaymsg -t get_inputs*.
*input* <identifier> xkb_switch_layout <index>|next|prev
Changes the active keyboard layout to <index> counting from zero or to
next or previous layout on the list. If there is no next or previous
layout, this command hops to the other end of the list.
This can be used when multiple layouts are configured with *xkb_layout*.
A list of layouts you can switch between can be obtained with
*swaymsg -t get_inputs*.
*input* <identifier> xkb_variant <variant>
Sets the variant of the keyboard like _dvorak_ or _colemak_.