Changed how key caching & lookup works

This changes how key caching & lookup works: instead of updating the whole key
cache whenever we change the layer state, we update each key before they are
pressed or released. This allows us to have two different ways in which layers
can work:

- Keys still held when releasing the layer key will be masked out until they are
  released. (This is the current behaviour)
- Keys held will repeat the keycode they had when they toggled on, even if the
  layer key gets released prior to this other key, while other keys will not be
  affected.

One can toggle between the two modes by setting
`Kaleidoscope.repeat_first_press` to `true` (second behaviour) or `false` (first
behaviour).

For now, the default behaviour is left unchanged.

Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
pull/159/head
Gergely Nagy 7 years ago
parent 283b96ae2e
commit e3f1172244

@ -44,9 +44,8 @@ static bool handleKeyswitchEventDefault(Key mappedKey, byte row, byte col, uint8
} }
void handleKeyswitchEvent(Key mappedKey, byte row, byte col, uint8_t keyState) { void handleKeyswitchEvent(Key mappedKey, byte row, byte col, uint8_t keyState) {
if (!(keyState & INJECTED)) { if (keyToggledOn(keyState) || keyToggledOff(keyState))
mappedKey = Layer.lookup(row, col); Layer.updateKeyCache(row, col);
}
/* If the key we are dealing with is masked, ignore it until it is released. /* 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 * When releasing it, clear the mask, so future key events can be handled
@ -63,6 +62,10 @@ void handleKeyswitchEvent(Key mappedKey, byte row, byte col, uint8_t keyState) {
} }
} }
if (!(keyState & INJECTED)) {
mappedKey = Layer.lookup(row, col);
}
for (byte i = 0; Kaleidoscope.eventHandlers[i] != NULL && i < HOOK_MAX; i++) { for (byte i = 0; Kaleidoscope.eventHandlers[i] != NULL && i < HOOK_MAX; i++) {
Kaleidoscope_::eventHandlerHook handler = Kaleidoscope.eventHandlers[i]; Kaleidoscope_::eventHandlerHook handler = Kaleidoscope.eventHandlers[i];
mappedKey = (*handler)(mappedKey, row, col, keyState); mappedKey = (*handler)(mappedKey, row, col, keyState);

@ -6,6 +6,7 @@ static uint32_t LayerState;
uint8_t Layer_::highestLayer; uint8_t Layer_::highestLayer;
uint8_t Layer_::keyMap[ROWS][COLS]; uint8_t Layer_::keyMap[ROWS][COLS];
Key(*Layer_::getKey)(uint8_t layer, byte row, byte col) = Layer.getKeyFromPROGMEM; Key(*Layer_::getKey)(uint8_t layer, byte row, byte col) = Layer.getKeyFromPROGMEM;
bool Layer_::repeat_first_press = false;
static void handleKeymapKeyswitchEvent(Key keymapEntry, uint8_t keyState) { static void handleKeymapKeyswitchEvent(Key keymapEntry, uint8_t keyState) {
if (keymapEntry.keyCode >= MOMENTARY_OFFSET) { if (keymapEntry.keyCode >= MOMENTARY_OFFSET) {
@ -44,6 +45,7 @@ static void handleKeymapKeyswitchEvent(Key keymapEntry, uint8_t keyState) {
* ignore held keys after releasing a layer key, until they are pressed * ignore held keys after releasing a layer key, until they are pressed
* again, to avoid the aforementioned issue. * again, to avoid the aforementioned issue.
*/ */
if (!Layer.repeat_first_press)
KeyboardHardware.maskHeldKeys(); KeyboardHardware.maskHeldKeys();
} }
@ -79,29 +81,18 @@ Layer_::getKeyFromPROGMEM(uint8_t layer, byte row, byte col) {
} }
void void
Layer_::mergeLayers(void) { Layer_::updateKeyCache(byte row, byte col) {
memset(keyMap, DefaultLayer, ROWS * COLS);
if (LayerState == (uint32_t)(1 << DefaultLayer))
return;
for (uint8_t r = 0; r < ROWS; r++) {
for (uint8_t c = 0; c < COLS; c++) {
int8_t layer = highestLayer; int8_t layer = highestLayer;
while (layer > DefaultLayer) { for (layer = highestLayer; layer >= DefaultLayer; layer--) {
if (Layer.isOn(layer)) { if (Layer.isOn(layer)) {
Key mappedKey = (*getKey)(layer, r, c); Key mappedKey = (*getKey)(layer, row, col);
if (mappedKey != Key_Transparent) { if (mappedKey != Key_Transparent) {
keyMap[r][c] = layer; keyMap[row][col] = layer;
break; break;
} }
} }
layer--;
}
}
} }
} }
@ -128,14 +119,12 @@ void Layer_::on(uint8_t layer) {
bitSet(LayerState, layer); bitSet(LayerState, layer);
if (layer > highestLayer) if (layer > highestLayer)
highestLayer = layer; highestLayer = layer;
mergeLayers();
} }
void Layer_::off(uint8_t layer) { void Layer_::off(uint8_t layer) {
bitClear(LayerState, layer); bitClear(LayerState, layer);
if (layer == highestLayer) if (layer == highestLayer)
highestLayer = top(); highestLayer = top();
mergeLayers();
} }
boolean Layer_::isOn(uint8_t layer) { boolean Layer_::isOn(uint8_t layer) {

@ -30,11 +30,13 @@ class Layer_ {
static Key getKeyFromPROGMEM(uint8_t layer, byte row, byte col); static Key getKeyFromPROGMEM(uint8_t layer, byte row, byte col);
static void updateKeyCache(byte row, byte col);
static bool repeat_first_press;
private: private:
static uint8_t highestLayer; static uint8_t highestLayer;
static uint8_t keyMap[ROWS][COLS]; static uint8_t keyMap[ROWS][COLS];
static void mergeLayers(void);
}; };
Key layer_getKey(uint8_t layer, uint8_t r, uint8_t c); Key layer_getKey(uint8_t layer, uint8_t r, uint8_t c);

Loading…
Cancel
Save