Parent directory

layer_lock.c

3056 bytes
  1// Copyright 2022-2023 Google LLC
  2//
  3// Licensed under the Apache License, Version 2.0 (the "License");
  4// you may not use this file except in compliance with the License.
  5// You may obtain a copy of the License at
  6//
  7//     https://www.apache.org/licenses/LICENSE-2.0
  8//
  9// Unless required by applicable law or agreed to in writing, software
 10// distributed under the License is distributed on an "AS IS" BASIS,
 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12// See the License for the specific language governing permissions and
 13// limitations under the License.
 14
 15#include "layer_lock.h"
 16#include "quantum_keycodes.h"
 17
 18#ifndef NO_ACTION_LAYER
 19// The current lock state. The kth bit is on if layer k is locked.
 20layer_state_t locked_layers = 0;
 21
 22// Layer Lock timer to disable layer lock after X seconds inactivity
 23#    if defined(LAYER_LOCK_IDLE_TIMEOUT) && LAYER_LOCK_IDLE_TIMEOUT > 0
 24uint32_t layer_lock_timer = 0;
 25
 26void layer_lock_timeout_task(void) {
 27    if (locked_layers && timer_elapsed32(layer_lock_timer) > LAYER_LOCK_IDLE_TIMEOUT) {
 28        layer_lock_all_off();
 29        layer_lock_timer = timer_read32();
 30    }
 31}
 32void layer_lock_activity_trigger(void) {
 33    layer_lock_timer = timer_read32();
 34}
 35#    else
 36void layer_lock_timeout_task(void) {}
 37void layer_lock_activity_trigger(void) {}
 38#    endif // LAYER_LOCK_IDLE_TIMEOUT > 0
 39
 40bool is_layer_locked(uint8_t layer) {
 41    return locked_layers & ((layer_state_t)1 << layer);
 42}
 43
 44void layer_lock_invert(uint8_t layer) {
 45    const layer_state_t mask = (layer_state_t)1 << layer;
 46    if ((locked_layers & mask) == 0) { // Layer is being locked.
 47#    ifndef NO_ACTION_ONESHOT
 48        if (layer == get_oneshot_layer()) {
 49            reset_oneshot_layer(); // Reset so that OSL doesn't turn layer off.
 50        }
 51#    endif // NO_ACTION_ONESHOT
 52        layer_on(layer);
 53        layer_lock_activity_trigger();
 54    } else { // Layer is being unlocked.
 55        layer_off(layer);
 56    }
 57    layer_lock_set_kb(locked_layers ^= mask);
 58}
 59
 60// Implement layer_lock_on/off by deferring to layer_lock_invert.
 61void layer_lock_on(uint8_t layer) {
 62    if (!is_layer_locked(layer)) {
 63        layer_lock_invert(layer);
 64    }
 65}
 66
 67void layer_lock_off(uint8_t layer) {
 68    if (is_layer_locked(layer)) {
 69        layer_lock_invert(layer);
 70    }
 71}
 72
 73void layer_lock_all_off(void) {
 74    layer_and(~locked_layers);
 75    locked_layers = 0;
 76    layer_lock_set_kb(locked_layers);
 77}
 78
 79#else  // NO_ACTION_LAYER
 80bool is_layer_locked(uint8_t layer) {
 81    return false;
 82}
 83void layer_lock_on(uint8_t layer) {}
 84void layer_lock_off(uint8_t layer) {}
 85void layer_lock_all_off(void) {}
 86void layer_lock_invert(uint8_t layer) {}
 87void layer_lock_timeout_task(void) {}
 88void layer_lock_activity_trigger(void) {}
 89#endif // NO_ACTION_LAYER
 90
 91__attribute__((weak)) bool layer_lock_set_kb(layer_state_t locked_layers) {
 92    return layer_lock_set_user(locked_layers);
 93}
 94__attribute__((weak)) bool layer_lock_set_user(layer_state_t locked_layers) {
 95    return true;
 96}
 97
 98void layer_lock_task(void) {
 99    layer_lock_timeout_task();
100}