aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIstván Donkó <istvan.donko@gmail.com>2023-08-12 21:30:55 +0200
committerIsaac Freund <mail@isaacfreund.com>2023-11-09 13:23:07 +0100
commit927dceb071f4d068ea271a3d97c3ece9db0da3b4 (patch)
tree9104f07c167fed4fbe6d8e1db81af28dac045470
parent04dea1edee9545dd3bb936cb1b51f1ebab4a5e54 (diff)
downloadriver-927dceb071f4d068ea271a3d97c3ece9db0da3b4.tar.gz
river-927dceb071f4d068ea271a3d97c3ece9db0da3b4.tar.xz
keyboard: add the ability to load layout from file
-rw-r--r--completions/bash/riverctl1
-rw-r--r--completions/fish/riverctl.fish1
-rw-r--r--completions/zsh/_riverctl1
-rw-r--r--doc/riverctl.1.scd6
-rw-r--r--river/command.zig5
-rw-r--r--river/command/keyboard.zig36
6 files changed, 50 insertions, 0 deletions
diff --git a/completions/bash/riverctl b/completions/bash/riverctl
index c756321..ccee6a0 100644
--- a/completions/bash/riverctl
+++ b/completions/bash/riverctl
@@ -9,6 +9,7 @@ function __riverctl_completion ()
keyboard-group-add \
keyboard-group-remove \
keyboard-layout \
+ keyboard-layout-file \
exit \
focus-output \
focus-view \
diff --git a/completions/fish/riverctl.fish b/completions/fish/riverctl.fish
index 9b321f3..7accc4d 100644
--- a/completions/fish/riverctl.fish
+++ b/completions/fish/riverctl.fish
@@ -77,6 +77,7 @@ complete -c riverctl -n '__fish_riverctl_complete_arg 1' -a 'keyboard-group-dest
complete -c riverctl -n '__fish_riverctl_complete_arg 1' -a 'keyboard-group-add' -d 'Add a keyboard to a keyboard group'
complete -c riverctl -n '__fish_riverctl_complete_arg 1' -a 'keyboard-group-remove' -d 'Remove a keyboard from a keyboard group'
complete -c riverctl -n '__fish_riverctl_complete_arg 1' -a 'keyboard-layout' -d 'Set the keyboard layout'
+complete -c riverctl -n '__fish_riverctl_complete_arg 1' -a 'keyboard-layout-file' -d 'Set the keyboard layout from a file.'
# Subcommands
complete -c riverctl -n '__fish_seen_subcommand_from focus-output send-to-output' -n '__fish_riverctl_complete_arg 2' -a 'next previous'
diff --git a/completions/zsh/_riverctl b/completions/zsh/_riverctl
index 6467fbc..0c90bf9 100644
--- a/completions/zsh/_riverctl
+++ b/completions/zsh/_riverctl
@@ -67,6 +67,7 @@ _riverctl_commands()
'keyboard-group-add:Add a keyboard to a keyboard group'
'keyboard-group-remove:Remove a keyboard from a keyboard group'
'keyboard-layout:Set the keyboard layout'
+ 'keyboard-layout-file:Set the keyboard layout from a file'
# Input
'input:Configure input devices'
'list-inputs:List all input devices'
diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd
index b43678b..5553306 100644
--- a/doc/riverctl.1.scd
+++ b/doc/riverctl.1.scd
@@ -424,6 +424,12 @@ matches everything while _\*\*_ and the empty string are invalid.
"grp:ctrl_space_toggle"). See *xkeyboard-config*(7) for possible values and
more information.
+*keyboard-layout-file* _path_
+ Set the XKB layout for all keyboards from an XKB keymap file at the provided
+ path. Documentation for the XKB keymap file format can be found at the
+ following URL:
+ https://xkbcommon.org/doc/current/keymap-text-format-v1.html
+
*keyboard-group-create* _group_name_
Create a keyboard group. A keyboard group collects multiple keyboards in
a single logical keyboard. This means that all state, like the active
diff --git a/river/command.zig b/river/command.zig
index dfebe9b..4a2a647 100644
--- a/river/command.zig
+++ b/river/command.zig
@@ -62,6 +62,7 @@ const command_impls = std.ComptimeStringMap(
.{ "keyboard-group-destroy", @import("command/keyboard_group.zig").keyboardGroupDestroy },
.{ "keyboard-group-remove", @import("command/keyboard_group.zig").keyboardGroupRemove },
.{ "keyboard-layout", @import("command/keyboard.zig").keyboardLayout },
+ .{ "keyboard-layout-file", @import("command/keyboard.zig").keyboardLayoutFile },
.{ "list-input-configs", @import("command/input.zig").listInputConfigs},
.{ "list-inputs", @import("command/input.zig").listInputs },
.{ "list-rules", @import("command/rule.zig").listRules},
@@ -112,6 +113,8 @@ pub const Error = error{
InvalidOrientation,
InvalidRgba,
InvalidValue,
+ CannotReadFile,
+ CannotParseFile,
UnknownOption,
ConflictingOptions,
OutOfMemory,
@@ -155,6 +158,8 @@ pub fn errToMsg(err: Error) [:0]const u8 {
Error.InvalidOrientation => "invalid orientation. Must be 'horizontal', or 'vertical'",
Error.InvalidRgba => "invalid color format, must be hexadecimal 0xRRGGBB or 0xRRGGBBAA",
Error.InvalidValue => "invalid value",
+ Error.CannotReadFile => "cannot read file",
+ Error.CannotParseFile => "cannot parse file",
Error.OutOfMemory => "out of memory",
Error.Other => unreachable,
};
diff --git a/river/command/keyboard.zig b/river/command/keyboard.zig
index 93f5cb9..c09db1f 100644
--- a/river/command/keyboard.zig
+++ b/river/command/keyboard.zig
@@ -58,6 +58,42 @@ pub fn keyboardLayout(
) orelse return error.InvalidValue;
defer new_keymap.unref();
+ applyLayout(new_keymap);
+}
+
+pub fn keyboardLayoutFile(
+ _: *Seat,
+ args: []const [:0]const u8,
+ _: *?[]const u8,
+) Error!void {
+ if (args.len < 2) return Error.NotEnoughArguments;
+ if (args.len > 2) return Error.TooManyArguments;
+
+ const file = std.fs.cwd().openFile(args[1], .{}) catch return error.CannotReadFile;
+ defer file.close();
+
+ // 1 GiB is arbitrarily chosen as an exceedingly large but not infinite upper bound.
+ const file_bytes = file.readToEndAlloc(util.gpa, 1024 * 1024 * 1024) catch |err| {
+ switch (err) {
+ error.FileTooBig, error.OutOfMemory => return error.OutOfMemory,
+ else => return error.CannotReadFile,
+ }
+ };
+ defer util.gpa.free(file_bytes);
+
+ const new_keymap = xkb.Keymap.newFromBuffer(
+ server.config.xkb_context,
+ file_bytes.ptr,
+ file_bytes.len,
+ .text_v1,
+ .no_flags,
+ ) orelse return error.CannotParseFile;
+ defer new_keymap.unref();
+
+ applyLayout(new_keymap);
+}
+
+fn applyLayout(new_keymap: *xkb.Keymap) void {
server.config.keymap.unref();
server.config.keymap = new_keymap.ref();