qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

layer_lock.c (3056B)


      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.
     20 layer_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
     24 uint32_t layer_lock_timer = 0;
     25 
     26 void 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 }
     32 void layer_lock_activity_trigger(void) {
     33     layer_lock_timer = timer_read32();
     34 }
     35 #    else
     36 void layer_lock_timeout_task(void) {}
     37 void layer_lock_activity_trigger(void) {}
     38 #    endif // LAYER_LOCK_IDLE_TIMEOUT > 0
     39 
     40 bool is_layer_locked(uint8_t layer) {
     41     return locked_layers & ((layer_state_t)1 << layer);
     42 }
     43 
     44 void 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.
     61 void layer_lock_on(uint8_t layer) {
     62     if (!is_layer_locked(layer)) {
     63         layer_lock_invert(layer);
     64     }
     65 }
     66 
     67 void layer_lock_off(uint8_t layer) {
     68     if (is_layer_locked(layer)) {
     69         layer_lock_invert(layer);
     70     }
     71 }
     72 
     73 void 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
     80 bool is_layer_locked(uint8_t layer) {
     81     return false;
     82 }
     83 void layer_lock_on(uint8_t layer) {}
     84 void layer_lock_off(uint8_t layer) {}
     85 void layer_lock_all_off(void) {}
     86 void layer_lock_invert(uint8_t layer) {}
     87 void layer_lock_timeout_task(void) {}
     88 void 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 
     98 void layer_lock_task(void) {
     99     layer_lock_timeout_task();
    100 }