From f0b3ad2b14dc02092c901800cced5227116b1d93 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Sun, 30 Jul 2017 10:54:22 +0200 Subject: [PATCH 1/2] Implement key masking for momentary layer keys The goal is to ignore key events from still-held keys in a situation where we just turned a layer off. Thus, if one holds a momentary layer key, then presses and holds another key, releases the layer key, we want to ignore the other held keys until they are released. This is accomplished by masking all held keys when a momentary layer has been turned off, and ignoring all masked key events in `handleKeyswitchEvent` until they are released, when we unmask them. This should address #150, but requires keyboardio/Kaleidoscope-Hardware-Model01#9. Signed-off-by: Gergely Nagy --- src/key_events.cpp | 8 ++++++++ src/layers.cpp | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/key_events.cpp b/src/key_events.cpp index 85f01679..7639cf5b 100644 --- a/src/key_events.cpp +++ b/src/key_events.cpp @@ -47,6 +47,14 @@ void handleKeyswitchEvent(Key mappedKey, byte row, byte col, uint8_t keyState) { if (!(keyState & INJECTED)) { mappedKey = Layer.lookup(row, col); } + + if (KeyboardHardware.isKeyMasked(row, col)) { + if (keyToggledOff(keyState)) { + KeyboardHardware.unMaskKey(row, col); + } + return; + } + for (byte i = 0; Kaleidoscope.eventHandlers[i] != NULL && i < HOOK_MAX; i++) { Kaleidoscope_::eventHandlerHook handler = Kaleidoscope.eventHandlers[i]; mappedKey = (*handler)(mappedKey, row, col, keyState); diff --git a/src/layers.cpp b/src/layers.cpp index cd48ed46..2d693175 100644 --- a/src/layers.cpp +++ b/src/layers.cpp @@ -28,6 +28,8 @@ static void handleKeymapKeyswitchEvent(Key keymapEntry, uint8_t keyState) { } else { Layer.off(target); } + + KeyboardHardware.maskHeldKeys(); } // switch keymap and stay there From ca8f586b2e925bf617648550557da8ac9bda9099 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Thu, 3 Aug 2017 12:22:17 +0200 Subject: [PATCH 2/2] Document the use of key masking a bit Signed-off-by: Gergely Nagy --- src/key_events.cpp | 7 +++++++ src/layers.cpp | 15 +++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/key_events.cpp b/src/key_events.cpp index 7639cf5b..f2d28b89 100644 --- a/src/key_events.cpp +++ b/src/key_events.cpp @@ -48,6 +48,13 @@ void handleKeyswitchEvent(Key mappedKey, byte row, byte col, uint8_t keyState) { mappedKey = Layer.lookup(row, col); } + /* If the key we are dealing with is masked, ignore it until it is released. + * When releasing it, clear the mask, so future key events can be handled + * appropriately. + * + * See layers.cpp for an example that masks keys, and the reason why it does + * so. + */ if (KeyboardHardware.isKeyMasked(row, col)) { if (keyToggledOff(keyState)) { KeyboardHardware.unMaskKey(row, col); diff --git a/src/layers.cpp b/src/layers.cpp index 2d693175..340936c4 100644 --- a/src/layers.cpp +++ b/src/layers.cpp @@ -29,6 +29,21 @@ static void handleKeymapKeyswitchEvent(Key keymapEntry, uint8_t keyState) { Layer.off(target); } + /* + * When toggling a layer off, we mask all keys still held. Masked keys + * will be ignored until released and pressed again (see + * `handleKeyswitchEvent` in key_events.cpp). + * + * We do this because when holding a momentary layer switch key, then + * pressing and holding some others, they will fire as keys on the + * momentary layer. But if we release the momentary layer switch key + * before releasing the others, they will continue firing, but from + * another layer. When typing fast, it may easily happen that we end up in + * a situation where the layer key releases first (in the same scan cycle, + * but handled first), and it will emit a key from the wrong layer. So we + * ignore held keys after releasing a layer key, until they are pressed + * again, to avoid the aforementioned issue. + */ KeyboardHardware.maskHeldKeys(); }