forked from qmk/qmk_firmware
-
Notifications
You must be signed in to change notification settings - Fork 387
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
417 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"keycodes": { | ||
"0x7C7B": { | ||
"group": "quantum", | ||
"key": "QK_LAYER_LOCK", | ||
"aliases": [ | ||
"QK_LLCK" | ||
] | ||
} | ||
} | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// Copyright 2022-2023 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#include "layer_lock.h" | ||
#include "quantum_keycodes.h" | ||
|
||
#ifndef NO_ACTION_LAYER | ||
// The current lock state. The kth bit is on if layer k is locked. | ||
layer_state_t locked_layers = 0; | ||
|
||
// Layer Lock timer to disable layer lock after X seconds inactivity | ||
# if defined(LAYER_LOCK_IDLE_TIMEOUT) && LAYER_LOCK_IDLE_TIMEOUT > 0 | ||
uint32_t layer_lock_timer = 0; | ||
|
||
void layer_lock_task(void) { | ||
if (locked_layers && timer_elapsed32(layer_lock_timer) > LAYER_LOCK_IDLE_TIMEOUT) { | ||
layer_lock_all_off(); | ||
layer_lock_timer = timer_read32(); | ||
} | ||
} | ||
# endif // LAYER_LOCK_IDLE_TIMEOUT > 0 | ||
|
||
bool is_layer_locked(uint8_t layer) { | ||
return locked_layers & ((layer_state_t)1 << layer); | ||
} | ||
|
||
void layer_lock_invert(uint8_t layer) { | ||
const layer_state_t mask = (layer_state_t)1 << layer; | ||
if ((locked_layers & mask) == 0) { // Layer is being locked. | ||
# ifndef NO_ACTION_ONESHOT | ||
if (layer == get_oneshot_layer()) { | ||
reset_oneshot_layer(); // Reset so that OSL doesn't turn layer off. | ||
} | ||
# endif // NO_ACTION_ONESHOT | ||
layer_on(layer); | ||
# if defined(LAYER_LOCK_IDLE_TIMEOUT) && LAYER_LOCK_IDLE_TIMEOUT > 0 | ||
layer_lock_timer = timer_read32(); | ||
# endif // LAYER_LOCK_IDLE_TIMEOUT > 0 | ||
} else { // Layer is being unlocked. | ||
layer_off(layer); | ||
} | ||
layer_lock_set_user(locked_layers ^= mask); | ||
} | ||
|
||
// Implement layer_lock_on/off by deferring to layer_lock_invert. | ||
void layer_lock_on(uint8_t layer) { | ||
if (!is_layer_locked(layer)) { | ||
layer_lock_invert(layer); | ||
} | ||
} | ||
|
||
void layer_lock_off(uint8_t layer) { | ||
if (is_layer_locked(layer)) { | ||
layer_lock_invert(layer); | ||
} | ||
} | ||
|
||
void layer_lock_all_off(void) { | ||
layer_and(~locked_layers); | ||
locked_layers = 0; | ||
layer_lock_set_user(locked_layers); | ||
} | ||
|
||
__attribute__((weak)) bool layer_lock_set_kb(layer_state_t locked_layers) { | ||
return layer_lock_set_user(locked_layers); | ||
} | ||
__attribute__((weak)) bool layer_lock_set_user(layer_state_t locked_layers) { | ||
return true; | ||
} | ||
#endif // NO_ACTION_LAYER |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// Copyright 2022-2023 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
/** | ||
* @file layer_lock.h | ||
* @brief Layer Lock, a key to stay in the current layer. | ||
* | ||
* Overview | ||
* -------- | ||
* | ||
* Layers are often accessed by holding a button, e.g. with a momentary layer | ||
* switch `MO(layer)` or layer tap `LT(layer, key)` key. But you may sometimes | ||
* want to "lock" or "toggle" the layer so that it stays on without having to | ||
* hold down a button. One way to do that is with a tap-toggle `TT` layer key, | ||
* but here is an alternative. | ||
* | ||
* This library implements a "Layer Lock key". When tapped, it "locks" the | ||
* highest layer to stay active, assuming the layer was activated by one of the | ||
* following keys: | ||
* | ||
* * `MO(layer)` momentary layer switch | ||
* * `LT(layer, key)` layer tap | ||
* * `OSL(layer)` one-shot layer | ||
* * `TT(layer)` layer tap toggle | ||
* * `LM(layer, mod)` layer-mod key (the layer is locked, but not the mods) | ||
* | ||
* Tapping the Layer Lock key again unlocks and turns off the layer. | ||
* | ||
* @note When a layer is "locked", other layer keys such as `TO(layer)` or | ||
* manually calling `layer_off(layer)` will override and unlock the layer. | ||
* | ||
* Configuration | ||
* ------------- | ||
* | ||
* Optionally, a timeout may be defined so that Layer Lock disables | ||
* automatically if not keys are pressed for `LAYER_LOCK_IDLE_TIMEOUT` | ||
* milliseconds. Define `LAYER_LOCK_IDLE_TIMEOUT` in your config.h, for instance | ||
* | ||
* #define LAYER_LOCK_IDLE_TIMEOUT 60000 // Turn off after 60 seconds. | ||
* | ||
* and call `layer_lock_task()` from your `matrix_scan_user()` in keymap.c: | ||
* | ||
* void matrix_scan_user(void) { | ||
* layer_lock_task(); | ||
* // Other tasks... | ||
* } | ||
* | ||
* For full documentation, see | ||
* <https://getreuer.info/posts/keyboards/layer-lock> | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <stdint.h> | ||
#include <stdbool.h> | ||
#include "action_layer.h" | ||
#include "action_util.h" | ||
|
||
/** | ||
* Handler function for Layer Lock. | ||
* | ||
* In your keymap, define a custom keycode to use for Layer Lock. Then handle | ||
* Layer Lock from your `process_record_user` function by calling | ||
* `process_layer_lock`, passing your custom keycode for the `lock_keycode` arg: | ||
* | ||
* #include "features/layer_lock.h" | ||
* | ||
* bool process_record_user(uint16_t keycode, keyrecord_t* record) { | ||
* if (!process_layer_lock(keycode, record, LLOCK)) { return false; } | ||
* // Your macros ... | ||
* | ||
* return true; | ||
* } | ||
*/ | ||
|
||
#ifndef NO_ACTION_LAYER | ||
/** Returns true if `layer` is currently locked. */ | ||
bool is_layer_locked(uint8_t layer); | ||
|
||
/** Locks and turns on `layer`. */ | ||
void layer_lock_on(uint8_t layer); | ||
|
||
/** Unlocks and turns off `layer`. */ | ||
void layer_lock_off(uint8_t layer); | ||
|
||
/** Unlocks and turns off all locked layers. */ | ||
void layer_lock_all_off(void); | ||
|
||
/** Toggles whether `layer` is locked. */ | ||
void layer_lock_invert(uint8_t layer); | ||
|
||
/** | ||
* Optional callback that gets called when a layer is locked or unlocked. | ||
* | ||
* This is useful to represent the current lock state, e.g. by setting an LED or | ||
* playing a sound. In your keymap, define | ||
* | ||
* void layer_lock_set_user(layer_state_t locked_layers) { | ||
* // Do something like `set_led(is_layer_locked(NAV));` | ||
* } | ||
* | ||
* @param locked_layers Bitfield in which the kth bit represents whether the | ||
* kth layer is on. | ||
*/ | ||
bool layer_lock_set_kb(layer_state_t locked_layers); | ||
bool layer_lock_set_user(layer_state_t locked_layers); | ||
|
||
void layer_lock_task(void); | ||
#else // NO_ACTION_LAYER | ||
static inline bool is_layer_locked(uint8_t layer) { return false; } | ||
static inline void layer_lock_on(uint8_t layer) {} | ||
static inline void layer_lock_off(uint8_t layer) {} | ||
static inline void layer_lock_all_off(void) {} | ||
static inline void layer_lock_invert(uint8_t layer) {} | ||
static inline bool layer_lock_set_kb(layer_state_t locked_layers) { return true; } | ||
static inline bool layer_lock_set_user(layer_state_t locked_layers) { return true; } | ||
static inline void layer_lock_task(void) {} | ||
#endif // NO_ACTION_LAYER |
Oops, something went wrong.