From 59bc052301be6ce395e2ceea11604071b99aed9f Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Wed, 25 Jan 2017 15:31:23 +0100 Subject: [PATCH] Mask out interruptors When a key interrupts the one-shot, mask the position out until a key release. This is needed, because even a short tap usually results in a short hold, which in turn - without the mask - handles the key. Instead, we now mask the position out until it is released, so no such problems arise. Fixes #4. Signed-off-by: Gergely Nagy --- src/Akela/OneShot.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++- src/Akela/OneShot.h | 6 ++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/Akela/OneShot.cpp b/src/Akela/OneShot.cpp index 241a4e54..28ca16fe 100644 --- a/src/Akela/OneShot.cpp +++ b/src/Akela/OneShot.cpp @@ -28,6 +28,8 @@ namespace Akela { uint32_t OneShot::State = 0; uint32_t OneShot::stickyState = 0; uint32_t OneShot::pressedState = 0; + uint32_t OneShot::leftMask; + uint32_t OneShot::rightMask; Key OneShot::prevKey; bool OneShot::shouldCancel = false; bool OneShot::shouldCancelStickies = false; @@ -127,6 +129,42 @@ namespace Akela { injectNormalKey (idx, WAS_PRESSED); } + void + OneShot::mask (byte row, byte col) { + if (row >= ROWS || col >= COLS) + return; + + if (col >= 8) { + col = col - 8; + rightMask |= SCANBIT (row, col); + } else + leftMask |= SCANBIT (row, col); + } + + void + OneShot::unmask (byte row, byte col) { + if (row >= ROWS || col >= COLS) + return; + + if (col >= 8) { + col = col - 8; + rightMask &= ~(SCANBIT (row, col)); + } else + leftMask &= ~(SCANBIT (row, col)); + } + + bool + OneShot::isMasked (byte row, byte col) { + if (row >= ROWS || col >= COLS) + return false; + + if (col >= 8) { + col = col - 8; + return rightMask & SCANBIT (row, col); + } else + return leftMask & SCANBIT (row, col); + } + Key OneShot::eventHandlerHook (Key mappedKey, byte row, byte col, uint8_t keyState) { uint8_t idx; @@ -135,8 +173,15 @@ namespace Akela { return mappedKey; if (!State) { - if (!isOS (mappedKey)) + if (!isOS (mappedKey)) { + if (isMasked (row, col)) { + if (key_toggled_off (keyState)) + unmask (row, col); + return Key_NoKey; + } + return mappedKey; + } idx = mappedKey.raw - OS_FIRST; if (key_toggled_off (keyState)) { @@ -196,6 +241,7 @@ namespace Akela { // ordinary key here, with some event if (key_is_pressed (keyState)) { + mask (row, col); saveAsPrevious (mappedKey); shouldCancel = true; } diff --git a/src/Akela/OneShot.h b/src/Akela/OneShot.h index 2db14f48..4902c0c0 100644 --- a/src/Akela/OneShot.h +++ b/src/Akela/OneShot.h @@ -47,6 +47,8 @@ namespace Akela { static uint32_t State; static uint32_t stickyState; static uint32_t pressedState; + static uint32_t leftMask; + static uint32_t rightMask; static Key prevKey; static bool shouldCancel; static bool shouldCancelStickies; @@ -55,6 +57,10 @@ namespace Akela { static void activateOneShot (uint8_t idx); static void cancelOneShot (uint8_t idx); + static void mask (byte row, byte col); + static void unmask (byte row, byte col); + static bool isMasked (byte row, byte col); + static Key eventHandlerPassthroughHook (Key mappedKey, byte row, byte col, uint8_t keyState); static void loopNoOpHook (bool postClear);