summary refs log tree commit diff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-rw-r--r--quantum/action_layer.c10
-rw-r--r--quantum/action_layer.h21
-rw-r--r--quantum/keycodes.h6
-rw-r--r--quantum/process_keycode/process_tri_layer.c30
-rw-r--r--quantum/process_keycode/process_tri_layer.h16
-rw-r--r--quantum/quantum.c13
-rw-r--r--quantum/quantum.h7
-rw-r--r--quantum/tri_layer.c39
-rw-r--r--quantum/tri_layer.h59
9 files changed, 187 insertions, 14 deletions
diff --git a/quantum/action_layer.c b/quantum/action_layer.c
index 74e8137920..35f494df8f 100644
--- a/quantum/action_layer.c
+++ b/quantum/action_layer.c
@@ -349,3 +349,13 @@ uint8_t layer_switch_get_layer(keypos_t key) {
 action_t layer_switch_get_action(keypos_t key) {
     return action_for_key(layer_switch_get_layer(key), key);
 }
+
+layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3) {
+    layer_state_t mask12 = ((layer_state_t)1 << layer1) | ((layer_state_t)1 << layer2);
+    layer_state_t mask3  = (layer_state_t)1 << layer3;
+    return (state & mask12) == mask12 ? (state | mask3) : (state & ~mask3);
+}
+
+void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
+    layer_state_set(update_tri_layer_state(layer_state, layer1, layer2, layer3));
+}
diff --git a/quantum/action_layer.h b/quantum/action_layer.h
index 3fe2726529..ff783bb3e7 100644
--- a/quantum/action_layer.h
+++ b/quantum/action_layer.h
@@ -113,6 +113,25 @@ void          layer_and(layer_state_t state);
 void          layer_xor(layer_state_t state);
 layer_state_t layer_state_set_user(layer_state_t state);
 layer_state_t layer_state_set_kb(layer_state_t state);
+
+/**
+ * @brief Applies the tri layer to global layer state. Not be used in layer_state_set_(kb|user) functions.
+ *
+ * @param layer1 First layer to check for tri layer
+ * @param layer2 Second layer to check for tri layer
+ * @param layer3 Layer to activate if both other layers are enabled
+ */
+void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3);
+/**
+ * @brief Applies the tri layer behavior to supplied layer bitmask, without using layer functions.
+ *
+ * @param state Original layer bitmask to check and modify
+ * @param layer1 First layer to check for tri layer
+ * @param layer2 Second layer to check for tri layer
+ * @param layer3 Layer to activate if both other layers are enabled
+ * @return layer_state_t returns a modified layer bitmask with tri layer modifications applied
+ */
+layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3);
 #else
 #    define layer_state 0
 
@@ -131,6 +150,8 @@ layer_state_t layer_state_set_kb(layer_state_t state);
 #    define layer_xor(state) (void)state
 #    define layer_state_set_kb(state) (void)state
 #    define layer_state_set_user(state) (void)state
+#    define update_tri_layer(layer1, layer2, layer3)
+#    define update_tri_layer_state(state, layer1, layer2, layer3) (void)state
 #endif
 
 /* pressed actions cache */
diff --git a/quantum/keycodes.h b/quantum/keycodes.h
index f24ccf01b8..4fa4306ed6 100644
--- a/quantum/keycodes.h
+++ b/quantum/keycodes.h
@@ -717,6 +717,8 @@ enum qk_keycode_defines {
     QK_AUTOCORRECT_ON = 0x7C74,
     QK_AUTOCORRECT_OFF = 0x7C75,
     QK_AUTOCORRECT_TOGGLE = 0x7C76,
+    QK_TRI_LAYER_LOWER = 0x7C77,
+    QK_TRI_LAYER_UPPER = 0x7C78,
     SAFE_RANGE = 0x7E00,
 
 // Alias
@@ -1282,6 +1284,8 @@ enum qk_keycode_defines {
     AC_ON      = QK_AUTOCORRECT_ON,
     AC_OFF     = QK_AUTOCORRECT_OFF,
     AC_TOGG    = QK_AUTOCORRECT_TOGGLE,
+    TL_LOWR    = QK_TRI_LAYER_LOWER,
+    TL_UPPR    = QK_TRI_LAYER_UPPER,
 };
 
 // Range Helpers
@@ -1333,4 +1337,4 @@ enum qk_keycode_defines {
 #define IS_MACRO_KEYCODE(code) ((code) >= QK_MACRO_0 && (code) <= QK_MACRO_31)
 #define IS_BACKLIGHT_KEYCODE(code) ((code) >= QK_BACKLIGHT_ON && (code) <= QK_BACKLIGHT_TOGGLE_BREATHING)
 #define IS_RGB_KEYCODE(code) ((code) >= RGB_TOG && (code) <= RGB_MODE_TWINKLE)
-#define IS_QUANTUM_KEYCODE(code) ((code) >= QK_BOOTLOADER && (code) <= QK_AUTOCORRECT_TOGGLE)
+#define IS_QUANTUM_KEYCODE(code) ((code) >= QK_BOOTLOADER && (code) <= QK_TRI_LAYER_UPPER)
diff --git a/quantum/process_keycode/process_tri_layer.c b/quantum/process_keycode/process_tri_layer.c
new file mode 100644
index 0000000000..1e681b9a1c
--- /dev/null
+++ b/quantum/process_keycode/process_tri_layer.c
@@ -0,0 +1,30 @@
+// Copyright 2023 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "process_tri_layer.h"
+#include "tri_layer.h"
+#include "action_layer.h"
+
+bool process_tri_layer(uint16_t keycode, keyrecord_t *record) {
+    switch (keycode) {
+        case QK_TRI_LAYER_LOWER:
+            if (record->event.pressed) {
+                layer_on(get_tri_layer_lower_layer());
+                update_tri_layer(get_tri_layer_lower_layer(), get_tri_layer_upper_layer(), get_tri_layer_adjust_layer());
+            } else {
+                layer_off(get_tri_layer_lower_layer());
+                update_tri_layer(get_tri_layer_lower_layer(), get_tri_layer_upper_layer(), get_tri_layer_adjust_layer());
+            }
+            return false;
+        case QK_TRI_LAYER_UPPER:
+            if (record->event.pressed) {
+                layer_on(get_tri_layer_upper_layer());
+                update_tri_layer(get_tri_layer_lower_layer(), get_tri_layer_upper_layer(), get_tri_layer_adjust_layer());
+            } else {
+                layer_off(get_tri_layer_upper_layer());
+                update_tri_layer(get_tri_layer_lower_layer(), get_tri_layer_upper_layer(), get_tri_layer_adjust_layer());
+            }
+            return false;
+    }
+    return true;
+}
diff --git a/quantum/process_keycode/process_tri_layer.h b/quantum/process_keycode/process_tri_layer.h
new file mode 100644
index 0000000000..9c4e3df1c2
--- /dev/null
+++ b/quantum/process_keycode/process_tri_layer.h
@@ -0,0 +1,16 @@
+// Copyright 2023 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "action.h"
+
+/**
+ * @brief Handles tri layer behavior
+ *
+ * @param keycode the keycode
+ * @param record the key record structure
+ * @return true continue handling keycodes
+ * @return false stop handling keycodes
+ */
+bool process_tri_layer(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 5554ecab32..0587f215fe 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -343,6 +343,9 @@ bool process_record_quantum(keyrecord_t *record) {
 #ifdef AUTOCORRECT_ENABLE
             process_autocorrect(keycode, record) &&
 #endif
+#ifdef TRI_LAYER_ENABLE
+            process_tri_layer(keycode, record) &&
+#endif
             true)) {
         return false;
     }
@@ -443,16 +446,6 @@ void set_single_persistent_default_layer(uint8_t default_layer) {
     default_layer_set((layer_state_t)1 << default_layer);
 }
 
-layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3) {
-    layer_state_t mask12 = ((layer_state_t)1 << layer1) | ((layer_state_t)1 << layer2);
-    layer_state_t mask3  = (layer_state_t)1 << layer3;
-    return (state & mask12) == mask12 ? (state | mask3) : (state & ~mask3);
-}
-
-void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
-    layer_state_set(update_tri_layer_state(layer_state, layer1, layer2, layer3));
-}
-
 //------------------------------------------------------------------------------
 // Override these functions in your keymap file to play different tunes on
 // different events such as startup and bootloader jump
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 615ec2382c..708d325a32 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -240,9 +240,10 @@ extern layer_state_t layer_state;
 #    include "process_autocorrect.h"
 #endif
 
-// For tri-layer
-void          update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3);
-layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3);
+#ifdef TRI_LAYER_ENABLE
+#    include "tri_layer.h"
+#    include "process_tri_layer.h"
+#endif
 
 void set_single_persistent_default_layer(uint8_t default_layer);
 
diff --git a/quantum/tri_layer.c b/quantum/tri_layer.c
new file mode 100644
index 0000000000..a5e3f8cb47
--- /dev/null
+++ b/quantum/tri_layer.c
@@ -0,0 +1,39 @@
+// Copyright 2023 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "tri_layer.h"
+#include <stdint.h>
+
+static uint8_t tri_layer_lower_layer  = TRI_LAYER_LOWER_LAYER;
+static uint8_t tri_layer_upper_layer  = TRI_LAYER_UPPER_LAYER;
+static uint8_t tri_layer_adjust_layer = TRI_LAYER_ADJUST_LAYER;
+
+void set_tri_layer_lower_layer(uint8_t layer) {
+    tri_layer_lower_layer = layer;
+}
+
+void set_tri_layer_upper_layer(uint8_t layer) {
+    tri_layer_upper_layer = layer;
+}
+
+void set_tri_layer_adjust_layer(uint8_t layer) {
+    tri_layer_adjust_layer = layer;
+}
+
+void set_tri_layer_layers(uint8_t lower, uint8_t raise, uint8_t adjust) {
+    tri_layer_lower_layer  = lower;
+    tri_layer_upper_layer  = raise;
+    tri_layer_adjust_layer = adjust;
+}
+
+uint8_t get_tri_layer_lower_layer(void) {
+    return tri_layer_lower_layer;
+}
+
+uint8_t get_tri_layer_upper_layer(void) {
+    return tri_layer_upper_layer;
+}
+
+uint8_t get_tri_layer_adjust_layer(void) {
+    return tri_layer_adjust_layer;
+}
diff --git a/quantum/tri_layer.h b/quantum/tri_layer.h
new file mode 100644
index 0000000000..3341ebffb2
--- /dev/null
+++ b/quantum/tri_layer.h
@@ -0,0 +1,59 @@
+// Copyright 2023 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <stdint.h>
+
+#ifndef TRI_LAYER_LOWER_LAYER
+#    define TRI_LAYER_LOWER_LAYER 1
+#endif
+#ifndef TRI_LAYER_UPPER_LAYER
+#    define TRI_LAYER_UPPER_LAYER 2
+#endif
+#ifndef TRI_LAYER_ADJUST_LAYER
+#    define TRI_LAYER_ADJUST_LAYER 3
+#endif
+
+/**
+ * @brief Set the tri layer lower layer index
+ *
+ * @param layer
+ */
+void set_tri_layer_lower_layer(uint8_t layer);
+/**
+ * @brief Set the tri layer upper layer index
+ *
+ * @param layer
+ */
+void set_tri_layer_upper_layer(uint8_t layer);
+/**
+ * @brief Set the tri layer adjust layer index
+ *
+ * @param layer
+ */
+void set_tri_layer_adjust_layer(uint8_t layer);
+/**
+ * @brief Set the tri layer indices
+ *
+ * @param lower
+ * @param upper
+ * @param adjust
+ */
+void set_tri_layer_layers(uint8_t lower, uint8_t upper, uint8_t adjust);
+/**
+ * @brief Get the tri layer lower layer index
+ *
+ * @return uint8_t
+ */
+uint8_t get_tri_layer_lower_layer(void);
+/**
+ * @brief Get the tri layer upper layer index
+ *
+ * @return uint8_t
+ */
+uint8_t get_tri_layer_upper_layer(void);
+/**
+ * @brief Get the tri layer adjust layer index
+ *
+ * @return uint8_t
+ */
+uint8_t get_tri_layer_adjust_layer(void);