keyboard: add the ability to load layout from file

This commit is contained in:
István Donkó 2023-08-12 21:30:55 +02:00 committed by Isaac Freund
parent 04dea1edee
commit 927dceb071
No known key found for this signature in database
GPG Key ID: 86DED400DDFD7A11
6 changed files with 50 additions and 0 deletions

View File

@ -9,6 +9,7 @@ function __riverctl_completion ()
keyboard-group-add \
keyboard-group-remove \
keyboard-layout \
keyboard-layout-file \
exit \
focus-output \
focus-view \

View File

@ -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'

View File

@ -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'

View File

@ -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

View File

@ -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,
};

View File

@ -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();