-
Notifications
You must be signed in to change notification settings - Fork 903
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
New keyboard API for Linux #1932
New keyboard API for Linux #1932
Conversation
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 skimmed through the X11 implementation. Here are the things that caught my eye.
For the record: I updated |
How could I test this, as an outsider that isn't familiar with winit and its APIs? Is there something ready-made I can run (example or something) or something I could code up easily, to play around with this and see if I encounter bugs or other feedback to give? |
You can use this program I made in order to test any of the keyboard rework PRs. |
@maroider Can you also test it out with multi-pointer x (I believe wayland also supports this) while working on this? In the demo, can also add a "seat" details there. https://wiki.archlinux.org/title/Multi-pointer_X#xinput_utility provides some instructions on how to do it. |
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.
Sorry for my late comment.
I tested in my local x11 env, but couldn't get ReceivedImeText
event.
Is there a particular reason you can't test this yourself, @pickfire? I have no experience with "multi-pointer X", and the wiki page you linked doesn't list i3 (my X11 WM) as compatible with it. |
Oh, I forgot to mention that multi-pointer X is only useful for window manager. I don't think it will be useful for application, I don't think I am aware of any rust window manager that I can try out with this patch, it needs to have support from both the window manager and xinit for it to work. |
Changing the keyboard layout should now work under native X11, but the details aren't pretty. In any case, I think I'll be able to push through with the other TODOs now that this sort of works on X11, as it has been the biggest mental roadblock to getting anything done on this PR. I don't recall if I thanked you on the discord call, @ArturKovacs, so here you go: Thank you! You helped a bunch. |
I went through the TODOs in your list and I believe that the only item that's blocking this from getting merged is
Can you elaborate on what those edge cases are and how can one reproduce them? And the other thing that I believe is blocking this is the missing implementation for |
I have forgotten, and I'm annoyed at myself for not writing it down. I recall writing that with the intention of re-visiting it within a couple of days. Needless to say, that didn't happen 😅. As for when I can get on with wrapping this PR up: I've admittedly been distracted by other PRs a bit (as well as the start of a new school year, as well as moving to a new place for said school), but I have some measure of confidence that I'll get around to doing the things you mentioned either today or next week. I also have an implementation for |
That sounds great Markus! Let me know if you need help with anything. I'm eager to get these improvements out to the public. |
Ok, I have done the things now. |
I've had another brief look over things, and I believe the PR should be in a state where nothing should change too much from further review (other than that one horrible hack that we don't talk about, shhh). I'd like those who know how to use an IME to check if this PR introduces any regressions at this point. I'm also waiting on a response from @garasubo. |
7d59987
to
ba8023a
Compare
b37656e
to
0676c39
Compare
Turns out I was an idiot when initially working on this. Don't listen to XkbMapNotify This event appears to be subsumed by XkbNewKeyboardNotify when we start listening to XkbNewKeyboardNotify, although the documentation feels a little unclear on the matter.
This commit retains the old code-path for doing this tracking in order to test for regressions introduced by this change. It appears that we manage to avoid any visible regressions due to having already removed the long since deprecated `modifiers` field from keyboard events, which hides the fact that using XkbStateNotify makes ModifiersChanged events arrive _after_ the WindowEvent for the keypress instead of between the DeviceEvent and the WindowEvent.
0676c39
to
6c7820e
Compare
In particular, this removes the X11_EVPROC_NEXT_COMPOSE hack now that our IME event code-path seems to ignore compose sequences.
Ok, I'm fairly certain the current keyboard layout change handling should work for most people now (and without the horrible hack that was previously used). I also went ahead and moved us over to using So as of this point, I don't think there's anything I'd consider a "hard blocker" to merging this (after some review, of course). |
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.
Looks good to me!
/// X11-style keycodes are offset by 8 from the keycodes the Linux kernel uses. | ||
pub fn raw_keycode_to_keycode(keycode: u32) -> KeyCode { | ||
let rawkey = keycode - 8; | ||
// The keycode values are taken from linux/include/uapi/linux/input-event-codes.h, as |
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.
According to this, in most cases it should map 1/1 in most cases.
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.
So that means it'll (hopefully) work just fine on FreeBSD?
Hi! I chanced upon this PR when I was trying to figure out why my application wasn't receiving
I'm supportive of this, but if it is ultimately not implemented, I suggest adding a line or two to the docs for clarification. |
This got a LGTM about a month ago; could a maintainer merge this? This may affect one of my projects. |
While I did ask @notgull to have a look over this PR (and am glad he did), I still want a review from @kchibisov (which I've asked for, but other things have taken priority), since he's our Wayland maintainer. Don't get me wrong, I'd love nothing more than to merge this, but I can't exactly merge major work on a backend without sign-off from the maintainer of said backend. |
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 haven't looked that much into semantics of XKB handling and X11 backend.
); | ||
|
||
if keymap.is_null() { | ||
panic!("Received invalid keymap from compositor."); |
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.
Do we really need to crash here? Though I guess we can't do much at this point...
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 chose to panic here because it was less work than bubbling the error up to the user somehow, although it's not obvious to me how we'd do that and still let the user use their window(s) in this degraded state. Another option would've been to log the error and move on with keyboard events remaining non-functional, but that makes the error one you have to dig through logs to find. I also don't think this will come up often in practice, but that's just a guess.
@@ -0,0 +1,882 @@ | |||
//! Convert Wayland keys to winit keys. |
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 sure why Wayland
is here given that it's a common thing?
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'm not sure why that's like that either (it's been a while since I wrote this, haha). "X11-style" is what I'd go with (since it existed first), but as you mention, it's the same both on X11 and Wayland.
/// Map the raw X11-style keycode to the `KeyCode` enum. | ||
/// | ||
/// X11-style keycodes are offset by 8 from the keycodes the Linux kernel uses. |
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.
And here we talk about x11
?
|
||
pub(crate) struct KbState { | ||
#[cfg(feature = "x11")] | ||
xcb_connection: *mut xcb_connection_t, |
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.
Do we need to use xcb
given that winit
is xlib
based? I'm pretty sure there's an xkb
X11 extension.
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.
libxkbcommon
wants a *mut xcb_connection_t
in some of the functions we want to use, and the *mut xcb_connection_t
we use is derived from the xlib
connection.
/// libxkbcommon is not available | ||
XKBNotFound, | ||
/// Provided RMLVO specified a keymap that would not be loaded | ||
#[cfg(feature = "wayland")] |
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 don't think that feature gating enum variants is a good idea.
fn register( | ||
&mut self, | ||
poll: &mut calloop::Poll, | ||
token_factory: &mut calloop::TokenFactory, | ||
) -> std::io::Result<()> { | ||
self.timer.register(poll, token_factory) | ||
} | ||
|
||
fn reregister( | ||
&mut self, | ||
poll: &mut calloop::Poll, | ||
token_factory: &mut calloop::TokenFactory, | ||
) -> std::io::Result<()> { | ||
self.timer.reregister(poll, token_factory) | ||
} | ||
|
||
fn unregister(&mut self, poll: &mut calloop::Poll) -> std::io::Result<()> { | ||
self.timer.unregister(poll) | ||
} |
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.
Could you recheck latest SCTK release wrt that code, it was changed iirc given that calloop updated, but maybe that's a new version of it?
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.
This is all based off of a 5 months old version of Winit, so maybe that'll be an issue once we rebase.
{ | ||
if let Some(ref mut repeat) = self.repeat { | ||
repeat.stop_all_repeat(); | ||
} | ||
} |
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.
You don't need extra scope for that.
#[inline] | ||
pub fn transparent(&self) -> bool { | ||
self.window.transparent | ||
} |
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.
Seems like a strange rebase.
@@ -202,6 +201,27 @@ impl<T: 'static> EventLoop<T> { | |||
ext | |||
}; | |||
|
|||
let xkbext = { |
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.
Could you put unsafe
here?
@maroider given that you really want to work on such thing. Could we have a branch against latest winit with the following structure. 1 commit - Core API So at least we'd have a reviewable thing and the thing that could actually be used? Right now I find it insanely hard to review any of those branches since I have 0 clue what is going on, which API is the final one and so on. So having everything in a single branch with suggest commit structure could help me a lot to move this forward given that I don't have time to do that myself at all. The single branch against master could help me port something like alacritty and test it, since it's a client using all sorts of keyboard input in the current winit. |
closing as we have mono branch. |
cargo fmt
has been run on this branchcargo doc
builds successfullyCHANGELOG.md
if knowledge of this change could be valuable to usersCreated or updated an example program if it would help users understand this functionalityThis implements #753 for Linux (I know that issue number by heart now, lol). Much like #1888, this PR is lacking in some areas, but unlike the aforementioned PR, this PR should be usable enough to get some useful feedback and testing done.
TODOs
keymap.rs
, as there are things there I suspect can be mapped, and some things that may have been mapped incorrectly.gnome-terminal
agrees, butkonsole
disagrees. Should it be configurable instead?TODO
comments in the code.src/platform_impl/linux/common/keymap.rs
src/platform_impl/linux/common/xkb_state.rs
src/platform_impl/linux/x11/event_processor.rs
cc @garasubo @jamadazi