From d3cdc5915f3ee81af1443896c3366ec65cdc4d25 Mon Sep 17 00:00:00 2001
From: Nick Conway <nick@conway.dev>
Date: Mon, 15 Apr 2024 15:27:04 -0400
Subject: [PATCH] Update for 3.5 and refactor

---
 app/include/zmk/leader.h                |  1 -
 app/include/zmk/virtual_key_position.h  |  5 +++
 app/src/behaviors/behavior_leader_key.c |  4 +-
 app/src/leader.c                        | 54 ++++++++++++++-----------
 docs/sidebars.js                        |  2 +
 5 files changed, 39 insertions(+), 27 deletions(-)

diff --git a/app/include/zmk/leader.h b/app/include/zmk/leader.h
index 6e28daa8..e0ea5b0d 100644
--- a/app/include/zmk/leader.h
+++ b/app/include/zmk/leader.h
@@ -8,4 +8,3 @@
 
 void zmk_leader_activate(int32_t timeout, bool timeout_on_activation, uint32_t position);
 void zmk_leader_deactivate();
-bool zmk_leader_get_status();
diff --git a/app/include/zmk/virtual_key_position.h b/app/include/zmk/virtual_key_position.h
index b8f20683..27a020b3 100644
--- a/app/include/zmk/virtual_key_position.h
+++ b/app/include/zmk/virtual_key_position.h
@@ -23,3 +23,8 @@
  * Gets the virtual key position to use for the combo with the given index.
  */
 #define ZMK_VIRTUAL_KEY_POSITION_COMBO(index) (ZMK_KEYMAP_LEN + ZMK_KEYMAP_SENSORS_LEN + (index))
+
+/**
+ * Gets the virtual key position to use for the leader sequence with the given index.
+ */
+#define ZMK_VIRTUAL_KEY_POSITION_LEADER(index) (ZMK_KEYMAP_LEN + ZMK_KEYMAP_SENSORS_LEN + (index))
diff --git a/app/src/behaviors/behavior_leader_key.c b/app/src/behaviors/behavior_leader_key.c
index b8624947..6ca63b34 100644
--- a/app/src/behaviors/behavior_leader_key.c
+++ b/app/src/behaviors/behavior_leader_key.c
@@ -47,8 +47,8 @@ static const struct behavior_driver_api behavior_leader_key_driver_api = {
 #define LEAD_INST(n)                                                                               \
     static struct behavior_leader_key_config behavior_leader_key_config_##n = {                    \
         .timerless = DT_INST_PROP(n, timerless), .timeout_ms = DT_INST_PROP(n, timeout_ms)};       \
-    DEVICE_DT_INST_DEFINE(n, behavior_leader_key_init, NULL, NULL,                                 \
-                          &behavior_leader_key_config_##n, APPLICATION,                            \
+    BEHAVIOR_DT_INST_DEFINE(n, behavior_leader_key_init, NULL, NULL,                               \
+                          &behavior_leader_key_config_##n, POST_KERNEL,                            \
                           CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_leader_key_driver_api);
 
 DT_INST_FOREACH_STATUS_OKAY(LEAD_INST)
diff --git a/app/src/leader.c b/app/src/leader.c
index ed7e5493..9fc2b42e 100644
--- a/app/src/leader.c
+++ b/app/src/leader.c
@@ -7,33 +7,37 @@
 #define DT_DRV_COMPAT zmk_leader_sequences
 
 #include <zephyr/device.h>
-#include <drivers/behavior.h>
 #include <zephyr/logging/log.h>
 #include <zephyr/sys/dlist.h>
 #include <zephyr/kernel.h>
 
+#include <drivers/behavior.h>
+
 #include <zmk/behavior.h>
 #include <zmk/event_manager.h>
 #include <zmk/events/position_state_changed.h>
 #include <zmk/hid.h>
 #include <zmk/matrix.h>
 #include <zmk/keymap.h>
+#include <zmk/virtual_key_position.h>
 #include <zmk/leader.h>
 
 LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
 
-bool leader_status;
-int32_t press_count;
-int32_t release_count;
-int32_t timeout_ms;
-int32_t active_leader_position;
-int8_t layer;
-bool first_release;
-struct k_work_delayable release_timer;
-int64_t release_at;
-bool timer_started;
-bool timer_cancelled;
-bool timerless;
+#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
+
+static bool leader_status;
+static int32_t press_count;
+static int32_t release_count;
+static int32_t timeout_ms;
+static int32_t active_leader_position;
+static int8_t layer;
+static bool first_release;
+static struct k_work_delayable release_timer;
+static int64_t release_at;
+// static bool timer_started;
+static bool timer_cancelled;
+static bool timerless;
 
 struct leader_seq_cfg {
     int32_t key_positions[CONFIG_ZMK_LEADER_MAX_KEYS_PER_SEQUENCE];
@@ -52,17 +56,17 @@ struct leader_seq_cfg {
 // leader_pressed_keys is filled with an event when a key is pressed.
 // The keys are removed from this array when they are released.
 // Once this array is empty, the behavior is released.
-const struct zmk_position_state_changed
+static const struct zmk_position_state_changed
     *leader_pressed_keys[CONFIG_ZMK_LEADER_MAX_KEYS_PER_SEQUENCE] = {NULL};
 
-uint32_t current_sequence[CONFIG_ZMK_LEADER_MAX_KEYS_PER_SEQUENCE] = {-1};
+static uint32_t current_sequence[CONFIG_ZMK_LEADER_MAX_KEYS_PER_SEQUENCE] = {-1};
 // the set of candidate leader based on the currently leader_pressed_keys
-int num_candidates;
-struct leader_seq_cfg *sequence_candidates[CONFIG_ZMK_LEADER_MAX_SEQUENCES_PER_KEY];
-int num_comp_candidates;
-struct leader_seq_cfg *completed_sequence_candidates[CONFIG_ZMK_LEADER_MAX_SEQUENCES_PER_KEY];
+static int num_candidates;
+static struct leader_seq_cfg *sequence_candidates[CONFIG_ZMK_LEADER_MAX_SEQUENCES_PER_KEY];
+static int num_comp_candidates;
+static struct leader_seq_cfg *completed_sequence_candidates[CONFIG_ZMK_LEADER_MAX_SEQUENCES_PER_KEY];
 // a lookup dict that maps a key position to all sequences on that position
-struct leader_seq_cfg *sequence_lookup[ZMK_KEYMAP_LEN][CONFIG_ZMK_LEADER_MAX_SEQUENCES_PER_KEY] = {
+static struct leader_seq_cfg *sequence_lookup[ZMK_KEYMAP_LEN][CONFIG_ZMK_LEADER_MAX_SEQUENCES_PER_KEY] = {
     NULL};
 
 // Store the leader key pointer in the leader array, one pointer for each key position
@@ -339,7 +343,7 @@ ZMK_SUBSCRIPTION(leader, zmk_position_state_changed);
 
 #define LEADER_INST(n)                                                                             \
     static struct leader_seq_cfg sequence_config_##n = {                                           \
-        .virtual_key_position = ZMK_KEYMAP_LEN + __COUNTER__,                                      \
+        .virtual_key_position = ZMK_VIRTUAL_KEY_POSITION_LEADER(__COUNTER__),                      \
         .immediate_trigger = DT_PROP(n, immediate_trigger),                                        \
         .is_pressed = false,                                                                       \
         .key_positions = DT_PROP(n, key_positions),                                                \
@@ -349,14 +353,16 @@ ZMK_SUBSCRIPTION(leader, zmk_position_state_changed);
         .layers_len = DT_PROP_LEN(n, layers),                                                      \
     };
 
-DT_INST_FOREACH_CHILD(0, LEADER_INST)
-
 #define INTITIALIAZE_LEADER_SEQUENCES(n) intitialiaze_leader_sequences(&sequence_config_##n);
 
-static int leader_init() {
+DT_INST_FOREACH_CHILD(0, LEADER_INST)
+
+static int leader_init(void) {
     k_work_init_delayable(&release_timer, behavior_leader_key_timer_handler);
     DT_INST_FOREACH_CHILD(0, INTITIALIAZE_LEADER_SEQUENCES);
     return 0;
 }
 
 SYS_INIT(leader_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
+
+#endif
diff --git a/docs/sidebars.js b/docs/sidebars.js
index d4c398b4..3411a4dd 100644
--- a/docs/sidebars.js
+++ b/docs/sidebars.js
@@ -35,6 +35,7 @@ module.exports = {
         "features/bluetooth",
         "features/split-keyboards",
         "features/combos",
+        "features/leader",
         "features/conditional-layers",
         "features/debouncing",
         "features/displays",
@@ -62,6 +63,7 @@ module.exports = {
         "behaviors/mod-tap",
         "behaviors/mod-morph",
         "behaviors/macros",
+        "behaviors/leader-key",
         "behaviors/key-toggle",
         "behaviors/sticky-key",
         "behaviors/sticky-layer",