-
-
Notifications
You must be signed in to change notification settings - Fork 899
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
feat: Added HardwareKeyboardDetector #2257
Conversation
That's fine, but I think it works both ways and maaaaybe the Focus could be better. You can use the keys from |
This is still a draft, meaning that there are still things to iron out API-wise. Comments/suggestions welcome. Focus or not?The
So, it appears that using this approach is actually recommended by the Flutter team. Of course, it might be useful to think carefully about the pros/cons here:
KeyboardHandler componentsCurrently the keyboard-handler mixin propagates the key events to all components in the tree. This is probably suboptimal: normally there would be only one component listening to key events. So, we could introduce the concept of "focus component" which would be the receiver of all key events from the mixin. A KeyboardHandler component would then add itself into the This would allow, for example, an opaque route to prevent the components underneath from receiving key events -- by putting itself on top of the onKeysPressed eventHonestly, I'm not very sure whether we even need this one. It just seems too trivial -- a user can always override the |
Is |
The Now, it's possible that this may not be "fast enough" for some games. The user may press and release a key within say 20ms, and they may want to get exactly 20ms worth of movement -- not 16ms or 32ms. The solution to that (assuming |
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 had a similar approach in the past, we used RawKeyboard to provide the events instead of the Focus stuff.
But we moved out of that approach because by using the RawKeyboard there was no way of preventing that annoying bell sound that MacOS makes.
So, I do like this approach and the proposed API, but we need to make sure that we won't be bringing back that issue
I think it is a great idea and I love the implementation. One only point: I would make lots of noise in the user console if they add this AND any kind of mixing/class/component in the game that relies on focus. For starters, I would add a check on every callback, if "this is KeyboardDetector" and yell in the console if true. Edit: made it less harsh |
I would also name every method and field in this mixing with "raw" to be explicit that the person using this knows the rabbit hole there are going into. |
/// The list of keys that are currently being pressed on the keyboard (or a | ||
/// keyboard-like device). The keys are listed in the order in which they | ||
/// were pressed, except for the modifier keys which may be listed | ||
/// out-of-order on some systems. | ||
List<PhysicalKeyboardKey> physicalKeysPressed = []; | ||
|
||
/// The set of logical keys that are currently being pressed on the keyboard. | ||
/// This set corresponds to the [physicalKeysPressed] list, and can be used | ||
/// to search for keys in a keyboard-layout-independent way. | ||
Set<LogicalKeyboardKey> logicalKeysPressed = {}; |
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.
Given this issue flutter/flutter#99330 I would not duplicate this info that is already present and accessible on RawKeyboard.
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 field is copied from the RawKeyboard
on every key event:
logicalKeysPressed = RawKeyboard.instance.keysPressed;
Thus, it is always kept in sync with the information available in RawKeyboard. The reason I decided to have this copy is because in RawKeyboard
this field is defined as follows:
Set<LogicalKeyboardKey> get keysPressed => _keysPressed.values.toSet();
That is, they return a copy of the internal state on every access. This is good for safety, but not so much for efficiency: if your code needs to check whether a number of certain keys are pressed, there will be a new set created on every check. Even such simple methods as isShiftPressed
/isControlPressed
/isAltPressed
each create two new copies of this set.
So I thought that a good solution to this is to simply keep a local copy of the set of logical keys, and make sure it is always kept up-to-date with RawKeyboard
.
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.
As for physicalKeysPressed
-- I believe it's important to know not only which keys are currently being pressed, but also in what order they were pressed. This information is currently missing in RawKeyboard
, they return physical keys as an orderless set, and keep it internally as a dictionary.
The reason why the order may be important is a scenario like this: suppose the user presses [Left Arrow], holds it, and then presses [Right Arrow]. Now two arrows are pressed simultaneously, and the game needs to decide how to respond to this. One possible choice is to make the player character stand still; another choice is to make the player character go right, since the right arrow was pressed last. By keeping the physical keys in a list instead of a set, we give the game an opportunity to choose which behavior to implement (my personal preference is for the latter).
Done. |
Was it? |
I've created an example, and it seems to be working quite well; and there are no extraneous bell sounds on a Mac. |
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.
Lgtm, is this still a draft?
Still need tests and docs |
Oh LOL:
|
Here's what I'm wondering: should this even be a This could have a few potential advantages:
|
Sounds nice, a bit inconsistent with how we have other things though? |
Description
This creates a new component
HardwareKeyboardDetector
, which is a more advanced version of theKeyboardEvents
mixin:HardwareKeyboardDetector
is a component instead of a mixin, which means it can be added/removed by the user at any point;HardwareKeyboard
interface, bypassing the need for a Focus widget;keyEventsPaused
property.Checklist
docs
and added dartdoc comments with///
.examples
ordocs
.Breaking Change?
Related Issues
Closes #2245