-
-
Notifications
You must be signed in to change notification settings - Fork 150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
keyboard: add the ability to load layout from file #870
Conversation
I am still curious what issue this solves, since custom xkbcommon layouts are already possible, provided you use the canonical path to put your layout file ( |
@Leon-Plickat Oh, I just replied to you in the issue. I couldn't get that to work (quite possibly due to something I'm missing because of the lacking documentation, as my layout file doesn't seem to be completely valid, for example it does not work under XWayland, probably because I'm not using four character long key identifiers or something like that), but also, even if I could've, I prefer keeping my home directory as clean as possible and store these kinds of things somewhere else. (In this case, under Anyway, having the flexibility to load a file from anywhere doesn't hurt in my opinion. To stop the bifurcation of this conversation, I'll reply to your last comment on the issue here:
I had issues with overriding certain parts of built-in layouts when I tried extending those, so that's not really a direction that I'd like to invest more time into, but I might try finding what's missing from my layout file. |
The reason you could not get it to work is because your custom layout does not have a name. If you add your layout file to one of the canonical locations, xkb-common adds it to its database of layouts. Yes, even if you have a local config file, all global configuration is still loaded. Since it has no name, you can't access it. The name is not automatically inferred from the filename. The name is a quoted string between |
I just tried adding a name there, but I'm still getting |
Probably. I suspect xkbcommon compiles its layout list on library init. |
Sorry for the delay, I have been away from home last week, but so far I still haven't managed to get my layout loaded through the currently available command. |
I am not opposed to this, I merely remain unconvinced this is necessary.
My custom layout works find as is and I don't see why yours shouldn't.
|
I have converted your layout file into the canonical form. You can find it here. Place those directories into You can check if it compiles with xkbcli compile-keymap --layout vortex --rules vortex For |
river/command/keyboard.zig
Outdated
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | ||
defer _ = gpa.deinit(); | ||
|
||
var file = std.fs.cwd().openFile(args[1], .{}) catch return error.CannotOpenFile; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it really make sense to have two different errors for being unable to open the file and being unable to read the file? I'd combine them.
river/command/keyboard.zig
Outdated
var file = std.fs.cwd().openFile(args[1], .{}) catch return error.CannotOpenFile; | ||
defer file.close(); | ||
|
||
var file_bytes = file.readToEndAlloc(gpa.allocator(), 512 * 4096) catch return error.CannotReadFile; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I think you are leaking this buffer.
I would like to be convinced that this feature is necessary before reviewing/merging it. |
I don't think it's strictly necessary, however it is arguably more convenient than splitting combined keymap files into separate files to make xkbcommon happy. So I think it might be interesting to know how common it is to have these combined keymap files. Are they typical for weird / unusual keyboards? If yes, this feature might be nice sugar. Otherwise, if this is not common and just used by people DIYing their own layouts, I think it's fine to ask them to do it the Right Way™ instead. |
@Leon-Plickat RE: #870 (comment) Thank you once again for taking your time with this!
I would think that this issue is orthogonal to the current one though, since as far as I know P.S. Thank you for reviewing the code as well, I'll go through your comments tomorrow and make adjustments accordingly. This was my first time writing |
On Mon Aug 21, 2023 at 8:54 PM CEST, István Donkó wrote:
Thank you once again for taking your time with this!
I have followed your instructions by cloning the contents of the
linked repository to `~/.xkb`, but I still get `error: invalid value`
when I try to load the layout.
I believe xkbcommon caches layouts, so river needs to be restarted.
If you can compile the vortex layout with xkbcli, it should work in
river. Otherwise track down the errors xkcli shows you.
|
Would the dedicated keymap-file command work around this caching? That would be another point in favor of adding it. Restarting river to tweak configuration isn't fun. |
Ah, I forgot about the caching since I brought it up last time (#870 (comment)), and voilà, after restarting For example none of the alphanumeric keys got properly assigned, they just show up as Also, iterating on this was pretty painful due to having to restart Another point could be the fact that this feature is present in other major window managers (such as Sway and Hyprland), so if it's missing from |
I think it would. IIRC the part of xkbcommon that applies a keymap is separate from the part that compiles a keymap from the various files and caches them. |
I guess that this wasn't entirely clear from my previous message, but as far as I understand, there could technically be no caching issue with my approach, since Anyway, I did test it before I wrote my previous reply, and |
@Leon-Plickat I have pushed a (I had to explicitly return |
river/command/keyboard.zig
Outdated
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | ||
const allocator = gpa.allocator(); | ||
defer _ = gpa.deinit(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't you use gpa
from util.zig
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The answer if very simple, because I didn't know that it existed. 😃
Thanks for the review, I'll include this into the fixup
!
river/command/keyboard.zig
Outdated
var file = std.fs.cwd().openFile(args[1], .{}) catch return error.CannotReadFile; | ||
defer file.close(); | ||
|
||
var file_bytes = file.readToEndAlloc(util.gpa, 512 * 4096) catch |err| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a fan of uncommented magic numbers in code, TBH.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I stole that one from here:
https://github.com/ifreund/zig-wayland/blob/7f528883e057b282b1cb51db2899f9183b2e5a3b/src/scanner.zig#L191
It's a huge overkill for this purpose, but I don't know what's the best way to come up with a reasonable estimated upper limit for the size of XKB files. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The size isn't the issue, just that it is arbitrary. readToEndAlloc()
will only allocate as much as is needed to store the contents of the file. As such, I'd use math.maxInt(usize)
.
And one more thing I forgot on the first review round: readToEndAlloc()
can return error.FileTooBig
, which should make your function return error.OutOfMemory
.
@@ -112,6 +113,8 @@ pub const Error = error{ | |||
InvalidOrientation, | |||
InvalidRgba, | |||
InvalidValue, | |||
CannotReadFile, | |||
CannotParseFile, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CannotParseFile, |
@@ -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", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error.CannotParseFile => "cannot parse file", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that providing a separate read error and parse error has meaningful difference, for example, providing a wrong path leads to a read error, while providing a path to a file with contents that XKB cannot compile leads to a parse error.
I think that with b41f1f8 I have now addressed all the reviews except for removing |
@Leon-Plickat @ifreund Sorry for the ping, but it has now been a week since the last response. Do you think that there is anything else to be done before this can be merged? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello, thanks for your patience!
Here's my proper in-depth review. When these comments are addressed this should be good to go.
@ifreund Thanks for the review, I'm a bit overwhelmed by work right now, but I'll make sure to finish this properly when I have the capacity to do so! |
No worries at all, take your time! |
7d044c7
to
34089d2
Compare
Finally getting around to cleaning this up! I have rebased my previous changes and updated the fixup commit with the requested changes from the review. Thanks again for the great piece of software, thorough review and patience! I have had some more ideas in the last few weeks of using River, so I will try to find more time for contributions either here, or in the form of smaller utilities or layout generators! :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the patch! I did a bit more cleanup myself and added a link to the best documentation I could find on the XKB keymap file format.
As per the discussion on IRC that followed my issue (#869) I have added a separate
riverctl keyboard-layout-file
command with the file path as its single parameter.The loading mechanism reads the file and passes the buffer to
xkbcommon
instead of the descriptor / handle to avoid dealing with the problem mentioned in #869.