Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Review fixes for layer lock feature #24627

Merged
merged 1 commit into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions quantum/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef OS_DETECTION_ENABLE
# include "os_detection.h"
#endif
#if defined(LAYER_LOCK_ENABLE) && LAYER_LOCK_IDLE_TIMEOUT > 0
#ifdef LAYER_LOCK_ENABLE
# include "layer_lock.h"
#endif // LAYER_LOCK_ENABLE
#endif

static uint32_t last_input_modification_time = 0;
uint32_t last_input_activity_time(void) {
Expand Down Expand Up @@ -659,7 +659,7 @@ void quantum_task(void) {
secure_task();
#endif

#if defined(LAYER_LOCK_ENABLE) && LAYER_LOCK_IDLE_TIMEOUT > 0
#ifdef LAYER_LOCK_ENABLE
layer_lock_task();
#endif
}
Expand Down
29 changes: 24 additions & 5 deletions quantum/layer_lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,18 @@ layer_state_t locked_layers = 0;
# if defined(LAYER_LOCK_IDLE_TIMEOUT) && LAYER_LOCK_IDLE_TIMEOUT > 0
uint32_t layer_lock_timer = 0;

void layer_lock_task(void) {
void layer_lock_timeout_task(void) {
if (locked_layers && timer_elapsed32(layer_lock_timer) > LAYER_LOCK_IDLE_TIMEOUT) {
layer_lock_all_off();
layer_lock_timer = timer_read32();
}
}
void layer_lock_activity_trigger(void) {
layer_lock_timer = timer_read32();
}
# else
void layer_lock_timeout_task(void) {}
void layer_lock_activity_trigger(void) {}
# endif // LAYER_LOCK_IDLE_TIMEOUT > 0

bool is_layer_locked(uint8_t layer) {
Expand All @@ -44,9 +50,7 @@ void layer_lock_invert(uint8_t layer) {
}
# 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
layer_lock_activity_trigger();
} else { // Layer is being unlocked.
layer_off(layer);
}
Expand All @@ -72,10 +76,25 @@ void layer_lock_all_off(void) {
layer_lock_set_kb(locked_layers);
}

#else // NO_ACTION_LAYER
bool is_layer_locked(uint8_t layer) {
return false;
}
void layer_lock_on(uint8_t layer) {}
void layer_lock_off(uint8_t layer) {}
void layer_lock_all_off(void) {}
void layer_lock_invert(uint8_t layer) {}
void layer_lock_timeout_task(void) {}
void layer_lock_activity_trigger(void) {}
#endif // NO_ACTION_LAYER

__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

void layer_lock_task(void) {
layer_lock_timeout_task();
}
45 changes: 4 additions & 41 deletions quantum/layer_lock.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,6 @@
*
* #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>
*/
Expand All @@ -67,24 +60,6 @@
#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);

Expand Down Expand Up @@ -116,20 +91,8 @@ void layer_lock_invert(uint8_t layer);
bool layer_lock_set_kb(layer_state_t locked_layers);
bool layer_lock_set_user(layer_state_t locked_layers);

/** Handle various background tasks */
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

/** Update any configured timeouts */
void layer_lock_activity_trigger(void);
17 changes: 2 additions & 15 deletions quantum/process_keycode/process_layer_lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.

/**
* @file layer_lock.c
* @brief Layer Lock implementation
*
* For full documentation, see
* <https://getreuer.info/posts/keyboards/layer-lock>
*/

#include "layer_lock.h"
#include "process_layer_lock.h"
#include "quantum_keycodes.h"
#include "action_util.h"

// The current lock state. The kth bit is on if layer k is locked.
extern layer_state_t locked_layers;
#if defined(LAYER_LOCK_IDLE_TIMEOUT) && LAYER_LOCK_IDLE_TIMEOUT > 0
extern uint32_t layer_lock_timer;
#endif

// Handles an event on an `MO` or `TT` layer switch key.
static bool handle_mo_or_tt(uint8_t layer, keyrecord_t* record) {
static inline bool handle_mo_or_tt(uint8_t layer, keyrecord_t* record) {
if (is_layer_locked(layer)) {
if (record->event.pressed) { // On press, unlock the layer.
layer_lock_invert(layer);
Expand All @@ -44,9 +33,7 @@ static bool handle_mo_or_tt(uint8_t layer, keyrecord_t* record) {

bool process_layer_lock(uint16_t keycode, keyrecord_t* record) {
#ifndef NO_ACTION_LAYER
# if defined(LAYER_LOCK_IDLE_TIMEOUT) && LAYER_LOCK_IDLE_TIMEOUT > 0
layer_lock_timer = timer_read32();
# endif // LAYER_LOCK_IDLE_TIMEOUT > 0
layer_lock_activity_trigger();

// The intention is that locked layers remain on. If something outside of
// this feature turned any locked layers off, unlock them.
Expand Down
48 changes: 0 additions & 48 deletions quantum/process_keycode/process_layer_lock.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,54 +12,6 @@
// 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>
Expand Down
2 changes: 1 addition & 1 deletion quantum/quantum.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@

#ifdef LAYER_LOCK_ENABLE
# include "process_layer_lock.h"
#endif // LAYER_LOCK_ENABLE
#endif

#ifdef AUDIO_ENABLE
# ifndef GOODBYE_SONG
Expand Down
2 changes: 1 addition & 1 deletion quantum/quantum.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ extern layer_state_t layer_state;

#ifdef LAYER_LOCK_ENABLE
# include "layer_lock.h"
#endif // LAYER_LOCK_ENABLE
#endif

void set_single_default_layer(uint8_t default_layer);
void set_single_persistent_default_layer(uint8_t default_layer);
Expand Down