From 265988ee25bc7d62e99d354116b4bd574b51b33b Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Mon, 12 Dec 2016 20:14:09 +0100 Subject: [PATCH] Better key state tracking We need to store the previous state of the keys, to figure out when a specific key is released, as opposed to simply not being pressed. This is required for layer keys such as `Mod` and `Fn` to work properly when there are more than one of them on the keymap. Without being able to tell when a key is released, we would not be able to turn a layer off only when no layer key is held. Not easily, anyway: we'd have to track the state of all layer keys... but then it is easier to just track them all. Thankfully, the memcpy at the end is fast, as it only needs to copy 70 bytes. Signed-off-by: Gergely Nagy --- right/src/keyboard_layout.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/right/src/keyboard_layout.c b/right/src/keyboard_layout.c index c2aa002..0f56a5e 100644 --- a/right/src/keyboard_layout.c +++ b/right/src/keyboard_layout.c @@ -4,6 +4,9 @@ static uint8_t keyMasks[SLOT_COUNT][MAX_KEY_COUNT_PER_MODULE]; static uint8_t modifierState = 0; +static uint8_t prevLeftKeyStates[KEY_STATE_COUNT]; +static uint8_t prevRightKeyStates[KEY_STATE_COUNT]; + static inline __attribute__((always_inline)) uhk_key_t getKeycode(KEYBOARD_LAYOUT(layout), uint8_t slotId, uint8_t keyId) { if (keyId < MAX_KEY_COUNT_PER_MODULE) { @@ -15,7 +18,7 @@ static inline __attribute__((always_inline)) uhk_key_t getKeycode(KEYBOARD_LAYOU uhk_key_t k = layout[modifierState][slotId][keyId]; keyMasks[slotId][keyId] = modifierState; - if (k.raw == 0) { + if (k.type == UHK_KEY_TRANSPARENT) { k = layout[0][slotId][keyId]; } @@ -67,18 +70,32 @@ bool layerOff(uhk_key_t key) { return false; } -bool handleKey(uhk_key_t key, int scancodeIdx, usb_keyboard_report_t *report, uint8_t keyState) { +bool key_toggled_on (const uint8_t *prevKeyStates, const uint8_t *currKeyStates, uint8_t keyId) { + return (!prevKeyStates[keyId]) && currKeyStates[keyId]; +} + +bool key_is_pressed (const uint8_t *prevKeyStates, const uint8_t *currKeyStates, uint8_t keyId) { + return currKeyStates[keyId]; +} + +bool key_toggled_off (const uint8_t *prevKeyStates, const uint8_t *currKeyStates, uint8_t keyId) { + return (!currKeyStates[keyId]) && prevKeyStates[keyId]; +} + +bool handleKey(uhk_key_t key, int scancodeIdx, usb_keyboard_report_t *report, const uint8_t *prevKeyStates, const uint8_t *currKeyStates, uint8_t keyId) { switch (key.type) { case UHK_KEY_SIMPLE: - if (keyState) { + if (key_is_pressed (prevKeyStates, currKeyStates, keyId)) { return pressKey (key, scancodeIdx, report); } break; case UHK_KEY_LAYER: - if (keyState) { - return layerOn(key); + if (key_toggled_on (prevKeyStates, currKeyStates, keyId)) { + return layerOn (key); + } + if (key_toggled_off (prevKeyStates, currKeyStates, keyId)) { + return layerOff (key); } - return layerOff(key); break; default: break; @@ -98,7 +115,7 @@ void fillKeyboardReport(usb_keyboard_report_t *report, const uint8_t *leftKeySta uhk_key_t code = getKeycode(layout, SLOT_ID_RIGHT_KEYBOARD_HALF, keyId); - if (handleKey(code, scancodeIdx, report, rightKeyStates[keyId])) { + if (handleKey(code, scancodeIdx, report, prevRightKeyStates, rightKeyStates, keyId)) { scancodeIdx++; } } @@ -110,8 +127,11 @@ void fillKeyboardReport(usb_keyboard_report_t *report, const uint8_t *leftKeySta uhk_key_t code = getKeycode(layout, SLOT_ID_LEFT_KEYBOARD_HALF, keyId); - if (handleKey(code, scancodeIdx, report, leftKeyStates[keyId])) { + if (handleKey(code, scancodeIdx, report, prevLeftKeyStates, leftKeyStates, keyId)) { scancodeIdx++; } } + + memcpy (prevLeftKeyStates, leftKeyStates, KEY_STATE_COUNT); + memcpy (prevRightKeyStates, rightKeyStates, KEY_STATE_COUNT); }