From 27f984771352c84d7c6d77743f31cf4e65bd8a5c Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 31 Mar 2017 10:37:48 +0200 Subject: [PATCH] [ion/device] Fix events generation We now repeat some events (arrow, backspace) Change-Id: I5f8e09b5f29ea4edbc709b94aae8674d7112a7b3 --- ion/src/shared/events_keyboard.cpp | 75 +++++++++++++++--------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/ion/src/shared/events_keyboard.cpp b/ion/src/shared/events_keyboard.cpp index 2d2455b4e..f02e8b2f0 100644 --- a/ion/src/shared/events_keyboard.cpp +++ b/ion/src/shared/events_keyboard.cpp @@ -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; + } } } }