Allow deactivation of base layer

Instead of safeguarding against an unrecoverable blank layer state by
guaranteeing that layer 0 is always active (and therefore always at the bottom
of the layer stack), we safeguard by a move to layer 0 if the only active layer
is deactivated.

Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
pull/1013/head
Michael Richters 4 years ago
parent 4f9afcfdb9
commit 08f45ba6a9
No known key found for this signature in database
GPG Key ID: 1288FD13E4EEF0C0

@ -104,8 +104,9 @@ void Layer_::handleKeymapKeyswitchEvent(Key keymapEntry, uint8_t keyState) {
break; break;
} }
} else if (keyToggledOn(keyState)) { } else if (keyToggledOn(keyState)) {
uint8_t target = keymapEntry.getKeyCode();
// switch keymap and stay there // switch keymap and stay there
if (Layer.isActive(keymapEntry.getKeyCode()) && keymapEntry.getKeyCode()) if (Layer.isActive(target))
deactivate(keymapEntry.getKeyCode()); deactivate(keymapEntry.getKeyCode());
else else
activate(keymapEntry.getKeyCode()); activate(keymapEntry.getKeyCode());
@ -130,22 +131,28 @@ void Layer_::updateLiveCompositeKeymap(KeyAddr key_addr) {
} }
void Layer_::updateActiveLayers(void) { void Layer_::updateActiveLayers(void) {
// First, set every entry in the active layer keymap to point to the default
// layer (layer 0).
memset(active_layer_keymap_, 0, Runtime.device().numKeys()); memset(active_layer_keymap_, 0, Runtime.device().numKeys());
// For each key address, set its entry in the active layer keymap to the value
// of the top active layer that has a non-transparent entry for that address.
for (auto key_addr : KeyAddr::all()) { for (auto key_addr : KeyAddr::all()) {
int8_t layer_index = active_layer_count_; for (uint8_t i = active_layer_count_; i > 0; --i) {
while (layer_index > 0) { uint8_t layer = active_layers_[i - 1];
uint8_t layer = active_layers_[layer_index - 1]; Key key = (*getKey)(layer, key_addr);
if (Layer.isActive(layer)) {
Key mappedKey = (*getKey)(layer, key_addr); if (key != Key_Transparent) {
active_layer_keymap_[key_addr.toInt()] = layer;
if (mappedKey != Key_Transparent) { break;
active_layer_keymap_[key_addr.toInt()] = layer;
break;
}
} }
layer_index--;
} }
} }
// Even if there are no active layers (a situation that should be prevented by
// `deactivate()`), each key will be mapped from the base layer (layer
// 0). Likewise, for any address where all active layers have a transparent
// entry, that key will be mapped from the base layer, even if the base layer
// has been deactivated.
} }
void Layer_::move(uint8_t layer) { void Layer_::move(uint8_t layer) {
@ -177,7 +184,8 @@ void Layer_::activate(uint8_t layer) {
if (isActive(layer)) if (isActive(layer))
return; return;
// Otherwise, turn on its bit in layer_state_ // Otherwise, turn on its bit in layer_state_, and push it onto the active
// layer stack
bitSet(layer_state_, layer); bitSet(layer_state_, layer);
active_layers_[active_layer_count_++] = layer; active_layers_[active_layer_count_++] = layer;
@ -191,22 +199,28 @@ void Layer_::activate(uint8_t layer) {
// Deactivate a given layer // Deactivate a given layer
void Layer_::deactivate(uint8_t layer) { void Layer_::deactivate(uint8_t layer) {
// If the target layer was already off, return // If the target layer was already off, return
if (!bitRead(layer_state_, layer)) if (!isActive(layer))
return; return;
// If the sole active layer is being deactivated, turn on the base layer and
// return so we always have at least one layer active.
if (active_layer_count_ <= 1) {
move(0);
return;
}
// Turn off its bit in layer_state_ // Turn off its bit in layer_state_
bitClear(layer_state_, layer); bitClear(layer_state_, layer);
// Rearrange the activation order array... // Remove the target layer from the active layer stack, and shift any layers
uint8_t idx = 0; // above it down to fill in the gap
for (uint8_t i = active_layer_count_; i > 0; i--) { for (uint8_t i = 0; i < active_layer_count_; ++i) {
if (active_layers_[i] == layer) { if (active_layers_[i] == layer) {
idx = i; memmove(&active_layers_[i], &active_layers_[i + 1], active_layer_count_ - i);
--active_layer_count_;
break; break;
} }
} }
memmove(&active_layers_[idx], &active_layers_[idx + 1], active_layer_count_ - idx);
active_layer_count_--;
// Update the keymap cache (but not live_composite_keymap_; that gets // Update the keymap cache (but not live_composite_keymap_; that gets
// updated separately, when keys toggle on or off. See layers.h) // updated separately, when keys toggle on or off. See layers.h)

Loading…
Cancel
Save