Convert keymap cache to a representation of active keyboard state

This converts `Layer.live_composite_keymap_[]` from a simple cache to a
representation of the keyboard's current state, and transfers that cache to
`Runtime.active_keys_[]`. With the exception of plugin activity, an idle key
will have the value `Key_Transparent`, and a pressed key will have the value of
whatever key it's currently mapped to in the keymap. A value of `Key_NoKey` will
mask that key until it is released.

If a plugin returns `ABORT` from its `onKeyswitchEvent()` handler, that means
that the keymap cache should not be updated. It's especially important to have
this occur after plugins like OneShot and Qukeys, where the key can stay
active (or become active) after the physical keyswitch has been released.

Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
f/keymap-cache-redesign
Michael Richters 4 years ago committed by Jesse Vincent
parent 3b1500a526
commit 38c18cdcc7
No known key found for this signature in database
GPG Key ID: 122F5DF7108E4046

@ -21,6 +21,7 @@
namespace kaleidoscope {
uint32_t Runtime_::millis_at_cycle_start_;
Key Runtime_::active_keys_[kaleidoscope_internal::device.numKeys()];
Runtime_::Runtime_(void) {
}
@ -42,6 +43,11 @@ Runtime_::setup(void) {
device().setup();
// Clear the active keys array (all keys idle at start)
for (auto key_addr : KeyAddr::all()) {
updateActiveKey(key_addr, Key_Transparent);
}
Layer.setup();
}

@ -128,8 +128,16 @@ class Runtime_ {
return kaleidoscope::Hooks::onFocusEvent(command);
}
static Key activeKey(KeyAddr key_addr) {
return active_keys_[key_addr.toInt()];
}
static void updateActiveKey(KeyAddr key_addr, Key key) {
active_keys_[key_addr.toInt()] = key;
}
private:
static uint32_t millis_at_cycle_start_;
static Key active_keys_[kaleidoscope_internal::device.numKeys()];
};
extern kaleidoscope::Runtime_ Runtime;

@ -86,16 +86,6 @@ void handleKeyswitchEvent(Key mappedKey, KeyAddr key_addr, uint8_t keyState) {
*/
if (key_addr.isValid()) {
/* If a key had an on event, we update the live composite keymap. See
* layers.h for an explanation about the different caches we have. */
if (keyToggledOn(keyState)) {
if (mappedKey == Key_NoKey || keyState & EPHEMERAL) {
Layer.updateLiveCompositeKeymap(key_addr);
} else {
Layer.updateLiveCompositeKeymap(key_addr, mappedKey);
}
}
/* 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.
@ -111,23 +101,44 @@ void handleKeyswitchEvent(Key mappedKey, KeyAddr key_addr, uint8_t keyState) {
}
}
/* Convert key_addr to the correct mappedKey
* The condition here means that if mappedKey and key_addr are both valid,
* the mappedKey wins - we don't re-look-up the mappedKey
*/
// If the caller did not supply a `Key` value, get it from the keymap
// cache. If that value is transparent, look it up from the active layer for
// that key address.
if (mappedKey == Key_NoKey) {
// Note: If the next line returns `Key_NoKey`, that will effectively mask
// the key.
mappedKey = Layer.lookup(key_addr);
}
} // key_addr valid
// Keypresses with out-of-bounds key_addr start here in the processing chain
auto result = kaleidoscope::Hooks::onKeyswitchEvent(mappedKey, key_addr, keyState);
if (kaleidoscope::Hooks::onKeyswitchEvent(mappedKey, key_addr, keyState) != kaleidoscope::EventHandlerResult::OK)
// If any plugin returns `ABORT`, stop here and don't update the active keys
// cache entry.
if (result == kaleidoscope::EventHandlerResult::ABORT)
return;
mappedKey = Layer.eventHandler(mappedKey, key_addr, keyState);
if (mappedKey == Key_NoKey)
// Update the active keys cache if the key toggled on or off.
if (key_addr.isValid()) {
if (keyToggledOn(keyState)) {
Runtime.updateActiveKey(key_addr, mappedKey);
} else if (keyToggledOff(keyState)) {
Runtime.updateActiveKey(key_addr, Key_Transparent);
}
}
// Only continue if all plugin handlers returned `OK`.
if (result != kaleidoscope::EventHandlerResult::OK)
return;
// If the key has been masked (i.e. `Key_NoKey`), or it's a plugin-specific
// key (`RESERVED`), don't bother continuing.
if (mappedKey == Key_NoKey || (mappedKey.getFlags() & RESERVED) != 0)
return;
// Handle all built-in key types.
Layer.eventHandler(mappedKey, key_addr, keyState);
handleKeyswitchEventDefault(mappedKey, key_addr, keyState);
}

@ -42,7 +42,6 @@ uint32_t Layer_::layer_state_;
uint8_t Layer_::active_layer_count_ = 1;
int8_t Layer_::active_layers_[31];
Key Layer_::live_composite_keymap_[Runtime.device().numKeys()];
uint8_t Layer_::active_layer_keymap_[Runtime.device().numKeys()];
Layer_::GetKeyFunction Layer_::getKey = &Layer_::getKeyFromPROGMEM;
@ -50,11 +49,8 @@ void Layer_::setup() {
// Explicitly set layer 0's state to 1
bitSet(layer_state_, 0);
// Update the keymap cache, so we start with a non-empty state.
// Update the active layer cache (every entry will be `0` to start)
Layer.updateActiveLayers();
for (auto key_addr : KeyAddr::all()) {
Layer.updateLiveCompositeKeymap(key_addr);
}
}
void Layer_::handleKeymapKeyswitchEvent(Key keymapEntry, uint8_t keyState) {
@ -113,20 +109,24 @@ void Layer_::handleKeymapKeyswitchEvent(Key keymapEntry, uint8_t keyState) {
}
Key Layer_::eventHandler(Key mappedKey, KeyAddr key_addr, uint8_t keyState) {
if (mappedKey.getFlags() != (SYNTHETIC | SWITCH_TO_KEYMAP))
return mappedKey;
handleKeymapKeyswitchEvent(mappedKey, keyState);
return Key_NoKey;
if (mappedKey.getFlags() == (SYNTHETIC | SWITCH_TO_KEYMAP))
handleKeymapKeyswitchEvent(mappedKey, keyState);
return mappedKey;
}
Key Layer_::getKeyFromPROGMEM(uint8_t layer, KeyAddr key_addr) {
return keyFromKeymap(layer, key_addr);
}
// Deprecated
void Layer_::updateLiveCompositeKeymap(KeyAddr key_addr) {
int8_t layer = active_layer_keymap_[key_addr.toInt()];
live_composite_keymap_[key_addr.toInt()] = (*getKey)(layer, key_addr);
// We could update the active keys cache here (as commented below), but I
// think that's unlikely to serve whatever purpose the caller had in
// mind. `Layer.lookup()` will still give the correct result, and without a
// `Key` value is specified, this function no longer serves a purpose.
// int8_t layer = active_layer_keymap_[key_addr.toInt()];
// Runtime.updateActiveKey(key_addr, (*getKey)(layer, key_addr));
}
void Layer_::updateActiveLayers(void) {

@ -20,6 +20,7 @@
#include "kaleidoscope/key_defs.h"
#include "kaleidoscope/keymaps.h"
#include "kaleidoscope/device/device.h"
#include "kaleidoscope/Runtime.h"
#include "kaleidoscope_internal/device.h"
#include "kaleidoscope_internal/sketch_exploration/sketch_exploration.h"
#include "kaleidoscope_internal/shortname.h"
@ -83,7 +84,13 @@ class Layer_ {
* `lookupOnActiveLayer`.
*/
static Key lookup(KeyAddr key_addr) {
return live_composite_keymap_[key_addr.toInt()];
// First check the active keys array
Key key = Runtime.activeKey(key_addr);
// If that entry is clear, look up the entry from the active keymap layers
if (key == Key_Transparent) {
key = lookupOnActiveLayer(key_addr);
}
return key;
}
static Key lookupOnActiveLayer(KeyAddr key_addr) {
uint8_t layer = active_layer_keymap_[key_addr.toInt()];
@ -121,9 +128,11 @@ class Layer_ {
static Key getKeyFromPROGMEM(uint8_t layer, KeyAddr key_addr);
DEPRECATED(LAYER_UPDATELIVECOMPOSITEKEYMAP)
static void updateLiveCompositeKeymap(KeyAddr key_addr, Key mappedKey) {
live_composite_keymap_[key_addr.toInt()] = mappedKey;
Runtime.updateActiveKey(key_addr, mappedKey);
}
DEPRECATED(LAYER_UPDATELIVECOMPOSITEKEYMAP)
static void updateLiveCompositeKeymap(KeyAddr key_addr);
static void updateActiveLayers(void);
@ -137,7 +146,6 @@ class Layer_ {
static uint32_t layer_state_;
static uint8_t active_layer_count_;
static int8_t active_layers_[31];
static Key live_composite_keymap_[kaleidoscope_internal::device.numKeys()];
static uint8_t active_layer_keymap_[kaleidoscope_internal::device.numKeys()];
static void handleKeymapKeyswitchEvent(Key keymapEntry, uint8_t keyState);

@ -46,3 +46,10 @@
"Layers are now in activation-order, please use" __NL__ \
"`Layer.forEachActiveLayer()` instead."
#define _DEPRECATED_MESSAGE_LAYER_UPDATELIVECOMPOSITEKEYMAP __NL__ \
"`Layer.updateLiveCompositeKeymap()` is deprecated.\n" __NL__ \
"The 'live composite keymap' cache has been replaced with the\n" __NL__ \
"'active keys' cache, which now represents the state of the active\n" __NL__ \
"keys at any given time. It is probably not necessary to directly\n" __NL__ \
"update that cache from a plugin, but if you need to, please use\n" __NL__ \
"the `Runtime.updateActiveKey(key_addr, key)` function instead."

Loading…
Cancel
Save