-
-
Notifications
You must be signed in to change notification settings - Fork 845
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
core: Key input overhaul #19616
core: Key input overhaul #19616
Conversation
return Some(KeyCode::from_code(char.to_ascii_uppercase() as u32)); | ||
fn alpha_to_logical(ch: &str) -> LogicalKey { | ||
// TODO What if we get multiple chars? | ||
if let Some(ch) = ch.chars().last() { |
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.
Didn't we use the first character before?
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.
We weren't consistent:
I think getting the last char makes more sense in case of dead keys until we start supporting them properly.
f7d47e2
to
fa35648
Compare
"F23" => KeyCode::F23, | ||
"F24" => KeyCode::F24, | ||
_ => KeyCode::UNKNOWN, | ||
"Backquote" => PhysicalKey::Backquote, |
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.
Just curious: I tried to figure out where this order comes from and I think it's based on the code in e.g. https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values#code_values_on_windows. So why is the first not Escape?
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.
Oh I had no reason to use Windows-specific docs :D The order is based on the spec: https://w3c.github.io/uievents-code/#code-value-tables
First it's categorized by section, then by the key's physical location, the order should be the same as in the PhysicalKey
enum (you can see the sections there).
It is probably interesting to mention that this adds not yet used support for mapping physical keys to Flash's virtual key code. |
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.
Great work.
I feel like If we we also used winit as an abstraction for key handling on the web we could probably unify a lot of the code between desktop and web.
That is very true. Web and winit have compatible interfaces (winit basically uses the web interface in Rust), but as long as we don't use winit on web, we have to duplicate this interface :/ |
01e5c5e
to
c16dea4
Compare
c16dea4
to
2a15cdf
Compare
The main goal of this refactor is to unify key input across all platforms and move all Flash Player related behaviors to core in order to get rid of differences across platforms and minimize bugs. Instead of providing KeyCodes in PlayerEvents, frontends now provide KeyDescriptors, which describe the pressed key on a high level. Then, Ruffle core does all necessary mappings to KeyCodes (and key location in the future). This also adds (not yet used) physical key mapping in Ruffle.
This test verifies key input mapping on an 80% keyboard.
This test verifies key input mapping on a numpad.
This test verifies the behavior of keyLocation in key events.
2a15cdf
to
b593080
Compare
#[derive(Debug, Clone, Copy)] | ||
pub struct KeyDescriptor { | ||
pub physical_key: PhysicalKey, | ||
pub logical_key: LogicalKey, | ||
pub key_location: KeyLocation, | ||
} |
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.
Any suggestions on how to jam the contents of this neat struct (especially LogicalKey
) all the way across this pipeline? 😵💫
https://github.com/ruffle-rs/ruffle-android/blob/main/app/src/main/res/layout/keyboard.xml#L121-L127
https://github.com/ruffle-rs/ruffle-android/blob/main/app/src/main/java/rs/ruffle/PlayerActivity.kt#L179-L188
https://github.com/ruffle-rs/ruffle-android/blob/main/app/src/main/java/rs/ruffle/PlayerActivity.kt#L97-L98
https://github.com/ruffle-rs/ruffle-android/blob/main/src/lib.rs#L487-L523
https://github.com/ruffle-rs/ruffle-android/blob/main/src/lib.rs#L400-L421
Or maybe I should leave all the XML/Kotlin parts operating on "softkeyboard scancodes" of a made-up layout, and translate it all in the Rust part? But that creates an uncomfy tie (or gap, depending on how you look at it) between how and where the layout is defined (including the button text), and what it "means" for the Ruffle player...
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.
IMO when it comes to a simple, custom keyboard, you should use an approach similar to one used in tests, where each key has an identifier and is mapped into PhysicalKey
/LogicalKey
/KeyLocation
. For more advanced keyboards I would expect all 3 fields to come from the virtual keyboard.
Maybe we can explore the idea of using the system keyboard on Android?
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.
Maybe we can explore the idea of using the system keyboard on Android?
I don't think we can get separate down/up events from that, nor can it handle pressing multiple keys at the same time...
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.
For pure text entry, sure, it would be great, but not for playing games, and such.
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 same mechanisms could/should trigger hiding our handmade keyboard and bringing up the system one as currently used for the same purpose on web IMO.)
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.
Bur yeah, making each key have a proper identifier in its tag
attribute, and carrying that string all the way into Rust, then dispatching on it there (turning it into a KeyIdentifier
) sounds doable. But passing strings through the JNI FFI boundary is just so much more inconvenient than simple scalar values IIRC... 😩 Sure it's not impossible, just less nice...
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 can always map it in Java and pass numerical values down. Not sure if that would require code duplication or not
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.
Yeah but that would just require more messing around with encoding different (sometimes optional) info about all the keys into numbers and then those into Rust enumerants... This way it would be in one place at least.
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, it would still require separating the methods to pass in the key events coming from our handmade virtual keyboard (with the string identifiers), and those coming from an actual physical keyboard connected say via Bluetooth (or USB or adb/scrcpy or whatever), in the form of an Android KeyEvent
. Oh well, this isn't a big deal either I guess...
The main goal of this refactor is to unify key input across all platforms and move all Flash Player related behaviors to core in order to get rid of differences across platforms and minimize bugs.
Instead of providing
KeyCode
s inPlayerEvent
s, frontends now provideKeyDescriptor
s, which describe the pressed key on a high level. Then, Ruffle core does all necessary mappings toKeyCode
s (and key location).Additionally, this PR implements support for
KeyboardEvent.keyLocation
.CC @evilpie