Parent directory

process_layer_lock.c

3123 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 "process_layer_lock.h"
17#include "quantum_keycodes.h"
18#include "action_util.h"
19
20// The current lock state. The kth bit is on if layer k is locked.
21extern layer_state_t locked_layers;
22
23// Handles an event on an `MO` or `TT` layer switch key.
24static inline bool handle_mo_or_tt(uint8_t layer, keyrecord_t* record) {
25    if (is_layer_locked(layer)) {
26        if (record->event.pressed) { // On press, unlock the layer.
27            layer_lock_invert(layer);
28        }
29        return false; // Skip default handling.
30    }
31    return true;
32}
33
34bool process_layer_lock(uint16_t keycode, keyrecord_t* record) {
35#ifndef NO_ACTION_LAYER
36    layer_lock_activity_trigger();
37
38    // The intention is that locked layers remain on. If something outside of
39    // this feature turned any locked layers off, unlock them.
40    if ((locked_layers & ~layer_state) != 0) {
41        layer_lock_set_kb(locked_layers &= layer_state);
42    }
43
44    if (keycode == QK_LAYER_LOCK) {
45        if (record->event.pressed) { // The layer lock key was pressed.
46            layer_lock_invert(get_highest_layer(layer_state));
47        }
48        return false;
49    }
50
51    switch (keycode) {
52        case QK_MOMENTARY ... QK_MOMENTARY_MAX: // `MO(layer)` keys.
53            return handle_mo_or_tt(QK_MOMENTARY_GET_LAYER(keycode), record);
54
55        case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX: // `TT(layer)`.
56            return handle_mo_or_tt(QK_LAYER_TAP_TOGGLE_GET_LAYER(keycode), record);
57
58        case QK_LAYER_MOD ... QK_LAYER_MOD_MAX: { // `LM(layer, mod)`.
59            uint8_t layer = QK_LAYER_MOD_GET_LAYER(keycode);
60            if (is_layer_locked(layer)) {
61                if (record->event.pressed) { // On press, unlock the layer.
62                    layer_lock_invert(layer);
63                } else { // On release, clear the mods.
64                    clear_mods();
65                    send_keyboard_report();
66                }
67                return false; // Skip default handling.
68            }
69        } break;
70
71#    ifndef NO_ACTION_TAPPING
72        case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: // `LT(layer, key)` keys.
73            if (record->tap.count == 0 && !record->event.pressed && is_layer_locked(QK_LAYER_TAP_GET_LAYER(keycode))) {
74                // Release event on a held layer-tap key where the layer is locked.
75                return false; // Skip default handling so that layer stays on.
76            }
77            break;
78#    endif // NO_ACTION_TAPPING
79    }
80#endif // NO_ACTION_LAYER
81    return true;
82}