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 }