mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-22 07:10:40 +01:00
Merge "[ion/device] Fix events generation"
This commit is contained in:
@@ -50,53 +50,54 @@ static bool sleepWithTimeout(int duration, int * timeout) {
|
||||
}
|
||||
}
|
||||
|
||||
// Debouncing, and change to get_key event.
|
||||
Event sLastEvent = Events::None;
|
||||
Keyboard::State sLastKeyboardState = 0;
|
||||
bool sEventIsRepeating = 0;
|
||||
constexpr int delayBeforeRepeat = 200;
|
||||
constexpr int delayBetweenRepeat = 50;
|
||||
|
||||
bool canRepeatEvent(Event e) {
|
||||
return (e == Events::Left || e == Events::Up || e == Events::Down || e == Events::Right || e == Events::Backspace);
|
||||
}
|
||||
|
||||
// FIXME: Timeout is ignored!
|
||||
|
||||
Event getEvent(int * timeout) {
|
||||
// Let's start by saving which keys we've seen up
|
||||
Keyboard::State keysSeenUp = ~Keyboard::scan();
|
||||
|
||||
/* We'll need to sleep to prevent keys from repeating too fast.
|
||||
* As a rule of thumb, we'll assume that the user cannot input more than 20
|
||||
* keys per second. That gives a 50ms minimum delay between events. */
|
||||
int sleepDelay = 50;
|
||||
|
||||
// The following two operations could be looped
|
||||
|
||||
// 1 - Wait a little to deal with establishing contacts (debouncing)
|
||||
if (sleepWithTimeout(sleepDelay, timeout)) {
|
||||
return Ion::Events::None;
|
||||
}
|
||||
|
||||
/* 2 - Let's discard the keys we previously saw up but which aren't anymore:
|
||||
* those were probably bouncing indeed. In terms of logic, that gives :
|
||||
* Initial keysSeenUp : 0001001
|
||||
* Current scan : 1111110
|
||||
* Updated keysSeenUp : 0000001
|
||||
* In other works, updated = initial "or not" scan.*/
|
||||
keysSeenUp |= ~Keyboard::scan();
|
||||
|
||||
|
||||
int time = 0;
|
||||
Keyboard::State keysSeenUp = 0;
|
||||
Keyboard::State keysSeenTransitionningFromUpToDown = 0;
|
||||
while (true) {
|
||||
Keyboard::State state = Keyboard::scan();
|
||||
/* We want to detect keys that are now down (1 in scan) and that were
|
||||
* previously up (1 in keysSeenUp). */
|
||||
Keyboard::State match = state & keysSeenUp;
|
||||
// Let's take this opportunity to update the keys we've seen up
|
||||
keysSeenUp |= ~state;
|
||||
if (match != 0) {
|
||||
keysSeenTransitionningFromUpToDown = keysSeenUp & state;
|
||||
|
||||
if (keysSeenTransitionningFromUpToDown != 0) {
|
||||
sEventIsRepeating = false;
|
||||
/* The key that triggered the event corresponds to the first non-zero bit
|
||||
* in "match". This is a rather simple logic operation for the which many
|
||||
* processors have an instruction (ARM thumb uses CLZ).
|
||||
* Unfortunately there's no way to express this in standard C, so we have
|
||||
* to resort to using a builtin function. */
|
||||
Keyboard::Key key = (Keyboard::Key)(63-__builtin_clzll(match));
|
||||
Event result(key, sIsShiftActive, sIsAlphaActive || sIsAlphaLocked);
|
||||
updateModifiersFromEvent(result);
|
||||
return result;
|
||||
Keyboard::Key key = (Keyboard::Key)(63-__builtin_clzll(keysSeenTransitionningFromUpToDown));
|
||||
Event event(key, sIsShiftActive, sIsAlphaActive || sIsAlphaLocked);
|
||||
updateModifiersFromEvent(event);
|
||||
sLastEvent = event;
|
||||
sLastKeyboardState = state;
|
||||
return event;
|
||||
}
|
||||
// Last but not least, sleep for a bit if we didn't find anything
|
||||
if (sleepWithTimeout(sleepDelay, timeout)) {
|
||||
return Ion::Events::None;
|
||||
|
||||
msleep(10);
|
||||
time += 10;
|
||||
|
||||
// At this point, we know that keysSeenTransitionningFromUpToDown has *always* been zero
|
||||
// In other words, no new key has been pressed
|
||||
if (canRepeatEvent(sLastEvent) && (state == sLastKeyboardState)) {
|
||||
int delay = (sEventIsRepeating ? delayBetweenRepeat : delayBeforeRepeat);
|
||||
if (time >= delay) {
|
||||
sEventIsRepeating = true;
|
||||
sLastKeyboardState = state;
|
||||
return sLastEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user