-
Notifications
You must be signed in to change notification settings - Fork 79
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
Implement successions of keys #10
Comments
that would be cool. |
Frankly I'm surprised it doesn't already have this feature! Add me to the list of folks that want this primarily so I can have the keyboard send unicode characters (e.g. |
That's not implemented because I didn't need this feature, and, for now, only me has implemented new features in keyberon ;-) @riskable That's a bit more complicated than planned, but the feature request is noted. I don't think I'll do that short term. If any of you is interested to do it, I can guide you in the code to do the feature. |
If you give me some tips I'll do my best and hopefully submit a PR! I never intended to, but I've become quite familiar with the way Keyberon works developing my hall effect firmware =) |
First, let's design the interface. Do you have any idea? |
Well let me state that I wrote a tool (https://github.com/liftoff/HumanInput) for JavaScript that takes strings as input and converts them to keystrokes (that it listens for--as opposed to executing them) and its interface is super easy to use: For sending keystrokes we need to be able to program separate keydown and keyup events and possibly specify how long each lasts. So a naive approach might be an underlying array of arrays of unicode characters (u32) might work. Here's how we might execute
...where each array in the array represents a keydown event. However, this doesn't specify how long each key gets held down for. So for something like that we may need an array of array of a custom struct or something like that. I'm still new to Rust so I'm not sure how it would work but maybe something like |
Almost forgot: If possible, we also need a way to serialize the macro format as well so we can store it in a config somewhere (e.g. EEPROM). Not sure if we need to take that into consideration when designing the interface. |
But you can't model your Unicode typing example like this. |
How about something that accumulates? Like: event_delay = 10; // ms between keydown/keypress/keyrelease
ke = KeyEvent::new(event_delay);
ke.add_keydown(LCtrl);
ke.add_keydown(LShift);
ke.add_keydown(U);
ke.add_keypress(Kb1);
ke.add_keypress(F);
ke.add_keypress(Kb4);
ke.add_keypress(A);
ke.add_keypress(F);
ke.add_keyrelease(LCtrl); // Or maybe just add_keyrelease() with no args to release all keydowns at once
ke.add_keyrelease(LShift);
ke.add_keyrelease(U); |
Just realized a better way would be to just chain the calls: ke = KeyEvent::new()
.keydown(LCtrl)
.keydown(LShift)
.keydown(U)
.keypress(Kb2)
.keypress(Kb6)
.keypress(Kb3)
.keypress(A)
.keyrelease(); |
You can't really have such a builder pattern as we don't have allocation, but we can have something like: use KeyAction::*; // I don't like this name
const HUNDRED_POINTS = Action::Succession {
delay: 10,
succession: &[
Press(LCtrl),
Press(LShift),
Press(U),
Tap(Kb1),
Tap(F),
Tap(Kb4),
Tap(A),
Tap(F),
Release(LCtrl),
Release(LShift),
Release(U),
],
}; We might add in the implementation a "release everything at the end". |
That'll work! For a mod name how about, "KeyMacro" since that's basically what it is? |
I started trying to implement this myself but I've run into an issue: The way the keydown The Any recommendations as to how to proceed without refactoring a ton of code in layout.rs (and potentially action.rs)? |
You don't have to care of WaitingState, in fact, the only thing you care is You have to add an enum to manage a KeyMacro (name seems fine). You also have a bit of refactoring to change the signature of Then, let's just handle Press and Release event. We can easily add some simple macro to transform Hope it's clear. |
Your hints are definitely helpful. I've never written a Rust macro before but it doesn't look like rocket science (more like "dollar sign science" hehe) but I'll try to figure it out. Thanks. The plan is to get you a PR that doesn't make you do more work than you would have if you implemented this on your own 👍 . Reasoning about the code without an allocator is definitely a challenge for my brain (that was free-range raised on dynamic, interpreted language feed). |
I don't care if it takes more of my time than if I implement it myself. I don't need it for the moment, so I'm not so motivated to do it. But mentoring is important to me. Don't be afraid of PR with lots of comments ;-) |
That's great, actually. If you're taking the time to get me up-to-speed I'll do my best to make it worth your while 💯 |
I've got it working! I wasn't able to figure out how to get it working with just const MACROTEST: Action = Sequence {
delay: 10, // Currently unused
actions: &[
SequenceEvent::Press(LCtrl), SequenceEvent::Press(LShift), SequenceEvent::Press(U), // Long form
tap(Kb1), tap(F), tap(Kb4), tap(A), tap(F), // Short form
kr(LCtrl), kr(LShift), kr(U), // Couldn't figure out how to get ReleaseAll() working--need some help there
],
}; I also made a short video demonstrating a I'll be submitting a PR for review in a moment. It'll probably require changes 😄 |
Implement an action that correspond to a succession of key, i.e. one keypress to write a sentence.
The text was updated successfully, but these errors were encountered: