aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorDrashna Jaelre <[email protected]>2024-11-20 22:31:54 -0800
committerGitHub <[email protected]>2024-11-21 17:31:54 +1100
commit36b5559b997cedd14a352aa70891558936b8b3a3 (patch)
treebf4d30ba2d31b69d659c53a225e4a5b9a7299f7a /tests
parent39161b9ee793f4c62836b209ec877acda457b88d (diff)
downloadqmk_firmware-36b5559b997cedd14a352aa70891558936b8b3a3.tar.gz
qmk_firmware-36b5559b997cedd14a352aa70891558936b8b3a3.zip
[Core] Add Layer Lock feature (#23430)
Co-authored-by: Daniel <[email protected]> Co-authored-by: Pascal Getreuer <[email protected]> Co-authored-by: Pascal Getreuer <[email protected]>
Diffstat (limited to 'tests')
-rw-r--r--tests/layer_lock/config.h8
-rw-r--r--tests/layer_lock/test.mk8
-rw-r--r--tests/layer_lock/test_layer_lock.cpp284
-rw-r--r--tests/test_common/keycode_table.cpp1
4 files changed, 301 insertions, 0 deletions
diff --git a/tests/layer_lock/config.h b/tests/layer_lock/config.h
new file mode 100644
index 0000000000..25d0b20c0e
--- /dev/null
+++ b/tests/layer_lock/config.h
@@ -0,0 +1,8 @@
+// Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) <[email protected]>
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "test_common.h"
+
+#define LAYER_LOCK_IDLE_TIMEOUT 1000
diff --git a/tests/layer_lock/test.mk b/tests/layer_lock/test.mk
new file mode 100644
index 0000000000..05771e4dbf
--- /dev/null
+++ b/tests/layer_lock/test.mk
@@ -0,0 +1,8 @@
+# Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) <[email protected]>
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
+
+LAYER_LOCK_ENABLE = yes
diff --git a/tests/layer_lock/test_layer_lock.cpp b/tests/layer_lock/test_layer_lock.cpp
new file mode 100644
index 0000000000..00742c3b43
--- /dev/null
+++ b/tests/layer_lock/test_layer_lock.cpp
@@ -0,0 +1,284 @@
+// Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) <[email protected]>
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "keycodes.h"
+#include "test_common.hpp"
+
+using testing::_;
+
+class LayerLock : public TestFixture {};
+
+TEST_F(LayerLock, LayerLockState) {
+ TestDriver driver;
+ KeymapKey key_a = KeymapKey(0, 0, 0, KC_A);
+ KeymapKey key_b = KeymapKey(1, 0, 0, KC_B);
+ KeymapKey key_c = KeymapKey(2, 0, 0, KC_C);
+ KeymapKey key_d = KeymapKey(3, 0, 0, KC_C);
+
+ set_keymap({key_a, key_b, key_c, key_d});
+
+ EXPECT_FALSE(is_layer_locked(1));
+ EXPECT_FALSE(is_layer_locked(2));
+ EXPECT_FALSE(is_layer_locked(3));
+
+ layer_lock_invert(1); // Layer 1: unlocked -> locked
+ layer_lock_on(2); // Layer 2: unlocked -> locked
+ layer_lock_off(3); // Layer 3: stays unlocked
+
+ // Layers 1 and 2 are now on.
+ EXPECT_TRUE(layer_state_is(1));
+ EXPECT_TRUE(layer_state_is(2));
+ // Layers 1 and 2 are now locked.
+ EXPECT_TRUE(is_layer_locked(1));
+ EXPECT_TRUE(is_layer_locked(2));
+ EXPECT_FALSE(is_layer_locked(3));
+
+ layer_lock_invert(1); // Layer 1: locked -> unlocked
+ layer_lock_on(2); // Layer 2: stays locked
+ layer_lock_on(3); // Layer 3: unlocked -> locked
+
+ EXPECT_FALSE(layer_state_is(1));
+ EXPECT_TRUE(layer_state_is(2));
+ EXPECT_TRUE(layer_state_is(3));
+ EXPECT_FALSE(is_layer_locked(1));
+ EXPECT_TRUE(is_layer_locked(2));
+ EXPECT_TRUE(is_layer_locked(3));
+
+ layer_lock_invert(1); // Layer 1: unlocked -> locked
+ layer_lock_off(2); // Layer 2: locked -> unlocked
+
+ EXPECT_TRUE(layer_state_is(1));
+ EXPECT_FALSE(layer_state_is(2));
+ EXPECT_TRUE(layer_state_is(3));
+ EXPECT_TRUE(is_layer_locked(1));
+ EXPECT_FALSE(is_layer_locked(2));
+ EXPECT_TRUE(is_layer_locked(3));
+
+ layer_lock_all_off(); // Layers 1 and 3: locked -> unlocked
+
+ EXPECT_FALSE(layer_state_is(1));
+ EXPECT_FALSE(layer_state_is(2));
+ EXPECT_FALSE(layer_state_is(3));
+ EXPECT_FALSE(is_layer_locked(1));
+ EXPECT_FALSE(is_layer_locked(2));
+ EXPECT_FALSE(is_layer_locked(3));
+}
+
+TEST_F(LayerLock, LayerLockMomentaryTest) {
+ TestDriver driver;
+ KeymapKey key_layer = KeymapKey(0, 0, 0, MO(1));
+ KeymapKey key_a = KeymapKey(0, 1, 0, KC_A);
+ KeymapKey key_trns = KeymapKey(1, 0, 0, KC_TRNS);
+ KeymapKey key_ll = KeymapKey(1, 1, 0, QK_LAYER_LOCK);
+
+ set_keymap({key_layer, key_a, key_trns, key_ll});
+
+ EXPECT_NO_REPORT(driver);
+ key_layer.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ EXPECT_FALSE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ tap_key(key_ll);
+ EXPECT_TRUE(layer_state_is(1));
+ EXPECT_TRUE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ key_layer.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ EXPECT_TRUE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+
+ // Pressing Layer Lock again unlocks the lock.
+ EXPECT_NO_REPORT(driver);
+ key_ll.press();
+ run_one_scan_loop();
+ EXPECT_FALSE(layer_state_is(1));
+ EXPECT_FALSE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(LayerLock, LayerLockLayerTapTest) {
+ TestDriver driver;
+ KeymapKey key_layer = KeymapKey(0, 0, 0, LT(1, KC_B));
+ KeymapKey key_a = KeymapKey(0, 1, 0, KC_A);
+ KeymapKey key_trns = KeymapKey(1, 0, 0, KC_TRNS);
+ KeymapKey key_ll = KeymapKey(1, 1, 0, QK_LAYER_LOCK);
+
+ set_keymap({key_layer, key_a, key_trns, key_ll});
+
+ EXPECT_NO_REPORT(driver);
+ key_layer.press();
+ idle_for(TAPPING_TERM);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ tap_key(key_ll);
+ EXPECT_TRUE(layer_state_is(1));
+ EXPECT_TRUE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+
+ // Pressing Layer Lock again unlocks the lock.
+ EXPECT_NO_REPORT(driver);
+ key_ll.press();
+ run_one_scan_loop();
+ EXPECT_FALSE(layer_state_is(1));
+ EXPECT_FALSE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(LayerLock, LayerLockOneshotTapTest) {
+ TestDriver driver;
+ KeymapKey key_layer = KeymapKey(0, 0, 0, OSL(1));
+ KeymapKey key_a = KeymapKey(0, 1, 0, KC_A);
+ KeymapKey key_trns = KeymapKey(1, 0, 0, KC_TRNS);
+ KeymapKey key_ll = KeymapKey(1, 1, 0, QK_LAYER_LOCK);
+
+ set_keymap({key_layer, key_a, key_trns, key_ll});
+
+ EXPECT_NO_REPORT(driver);
+ tap_key(key_layer);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ tap_key(key_ll);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ EXPECT_TRUE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+
+ // Pressing Layer Lock again unlocks the lock.
+ EXPECT_NO_REPORT(driver);
+ key_ll.press();
+ run_one_scan_loop();
+ EXPECT_FALSE(layer_state_is(1));
+ EXPECT_FALSE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(LayerLock, LayerLockOneshotHoldTest) {
+ TestDriver driver;
+ KeymapKey key_layer = KeymapKey(0, 0, 0, OSL(1));
+ KeymapKey key_a = KeymapKey(0, 1, 0, KC_A);
+ KeymapKey key_trns = KeymapKey(1, 0, 0, KC_TRNS);
+ KeymapKey key_ll = KeymapKey(1, 1, 0, QK_LAYER_LOCK);
+
+ set_keymap({key_layer, key_a, key_trns, key_ll});
+
+ EXPECT_NO_REPORT(driver);
+ key_layer.press();
+ idle_for(TAPPING_TERM);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ tap_key(key_ll);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ key_layer.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ EXPECT_TRUE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+
+ // Pressing Layer Lock again unlocks the lock.
+ EXPECT_NO_REPORT(driver);
+ key_ll.press();
+ run_one_scan_loop();
+ EXPECT_FALSE(layer_state_is(1));
+ EXPECT_FALSE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(LayerLock, LayerLockTimeoutTest) {
+ TestDriver driver;
+ KeymapKey key_layer = KeymapKey(0, 0, 0, MO(1));
+ KeymapKey key_a = KeymapKey(0, 1, 0, KC_A);
+ KeymapKey key_trns = KeymapKey(1, 0, 0, KC_TRNS);
+ KeymapKey key_ll = KeymapKey(1, 1, 0, QK_LAYER_LOCK);
+
+ set_keymap({key_layer, key_a, key_trns, key_ll});
+
+ EXPECT_NO_REPORT(driver);
+ key_layer.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ tap_key(key_ll);
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ key_layer.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ EXPECT_TRUE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ idle_for(LAYER_LOCK_IDLE_TIMEOUT);
+ run_one_scan_loop();
+ EXPECT_FALSE(layer_state_is(1));
+ EXPECT_FALSE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(LayerLock, ToKeyOverridesLayerLock) {
+ TestDriver driver;
+ KeymapKey key_layer = KeymapKey(0, 0, 0, MO(1));
+ KeymapKey key_to0 = KeymapKey(1, 0, 0, TO(0));
+ KeymapKey key_ll = KeymapKey(1, 1, 0, QK_LAYER_LOCK);
+
+ set_keymap({key_layer, key_to0, key_ll});
+
+ EXPECT_NO_REPORT(driver);
+ layer_lock_on(1);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ EXPECT_TRUE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ tap_key(key_to0); // TO(0) overrides Layer Lock and unlocks layer 1.
+ EXPECT_FALSE(layer_state_is(1));
+ EXPECT_FALSE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(LayerLock, LayerClearOverridesLayerLock) {
+ TestDriver driver;
+ KeymapKey key_layer = KeymapKey(0, 0, 0, MO(1));
+ KeymapKey key_a = KeymapKey(0, 1, 0, KC_A);
+ KeymapKey key_ll = KeymapKey(1, 1, 0, QK_LAYER_LOCK);
+
+ set_keymap({key_layer, key_a, key_ll});
+
+ EXPECT_NO_REPORT(driver);
+ layer_lock_on(1);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ EXPECT_TRUE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_A));
+ layer_clear(); // layer_clear() overrides Layer Lock and unlocks layer 1.
+ key_a.press();
+ run_one_scan_loop();
+ EXPECT_FALSE(layer_state_is(1));
+ EXPECT_FALSE(is_layer_locked(1));
+ VERIFY_AND_CLEAR(driver);
+}
diff --git a/tests/test_common/keycode_table.cpp b/tests/test_common/keycode_table.cpp
index a520dd3f2b..ae1a9edcd0 100644
--- a/tests/test_common/keycode_table.cpp
+++ b/tests/test_common/keycode_table.cpp
@@ -699,6 +699,7 @@ std::map<uint16_t, std::string> KEYCODE_ID_TABLE = {
{QK_TRI_LAYER_UPPER, "QK_TRI_LAYER_UPPER"},
{QK_REPEAT_KEY, "QK_REPEAT_KEY"},
{QK_ALT_REPEAT_KEY, "QK_ALT_REPEAT_KEY"},
+ {QK_LAYER_LOCK, "QK_LAYER_LOCK"},
{QK_KB_0, "QK_KB_0"},
{QK_KB_1, "QK_KB_1"},
{QK_KB_2, "QK_KB_2"},