From 050fa9062f6a62ee2adefde17e6634edd79d92fc Mon Sep 17 00:00:00 2001
From: Jouke Witteveen
Date: Thu, 16 Jun 2022 08:05:27 +0200
Subject: tap-dance: Rename tests so that tap_dance is used consistently
(#17396)
---
tests/tap_dance/config.h | 19 +++
tests/tap_dance/examples.c | 199 ++++++++++++++++++++++++
tests/tap_dance/examples.h | 33 ++++
tests/tap_dance/test.mk | 22 +++
tests/tap_dance/test_examples.cpp | 319 ++++++++++++++++++++++++++++++++++++++
tests/tapdance/config.h | 19 ---
tests/tapdance/examples.c | 199 ------------------------
tests/tapdance/examples.h | 33 ----
tests/tapdance/test.mk | 22 ---
tests/tapdance/test_examples.cpp | 319 --------------------------------------
10 files changed, 592 insertions(+), 592 deletions(-)
create mode 100644 tests/tap_dance/config.h
create mode 100644 tests/tap_dance/examples.c
create mode 100644 tests/tap_dance/examples.h
create mode 100644 tests/tap_dance/test.mk
create mode 100644 tests/tap_dance/test_examples.cpp
delete mode 100644 tests/tapdance/config.h
delete mode 100644 tests/tapdance/examples.c
delete mode 100644 tests/tapdance/examples.h
delete mode 100644 tests/tapdance/test.mk
delete mode 100644 tests/tapdance/test_examples.cpp
diff --git a/tests/tap_dance/config.h b/tests/tap_dance/config.h
new file mode 100644
index 0000000000..6aada3efd3
--- /dev/null
+++ b/tests/tap_dance/config.h
@@ -0,0 +1,19 @@
+/* Copyright 2022 Jouke Witteveen
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+#include "test_common.h"
diff --git a/tests/tap_dance/examples.c b/tests/tap_dance/examples.c
new file mode 100644
index 0000000000..4a5be41b08
--- /dev/null
+++ b/tests/tap_dance/examples.c
@@ -0,0 +1,199 @@
+/* Copyright 2022 Jouke Witteveen
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "quantum.h"
+#include "examples.h"
+
+// Example code from the tap dance documentation, adapted for testing
+
+// clang-format off
+
+// Example 1
+
+void dance_egg(qk_tap_dance_state_t *state, void *user_data) {
+ if (state->count >= 100) {
+ // SEND_STRING("Safety dance!");
+ tap_code(KC_C);
+ reset_tap_dance(state);
+ }
+}
+
+
+// Example 2
+
+void dance_flsh_each(qk_tap_dance_state_t *state, void *user_data) {
+ switch (state->count) {
+ case 1:
+ register_code(KC_3);
+ break;
+ case 2:
+ register_code(KC_2);
+ break;
+ case 3:
+ register_code(KC_1);
+ break;
+ case 4:
+ unregister_code(KC_3);
+ // wait_ms(50);
+ unregister_code(KC_2);
+ // wait_ms(50);
+ unregister_code(KC_1);
+ }
+}
+
+void dance_flsh_finished(qk_tap_dance_state_t *state, void *user_data) {
+ if (state->count >= 4) {
+ // reset_keyboard();
+ tap_code(KC_R);
+ }
+}
+
+void dance_flsh_reset(qk_tap_dance_state_t *state, void *user_data) {
+ unregister_code(KC_1);
+ // wait_ms(50);
+ unregister_code(KC_2);
+ // wait_ms(50);
+ unregister_code(KC_3);
+}
+
+
+// Example 3
+
+typedef struct {
+ uint16_t tap;
+ uint16_t hold;
+ uint16_t held;
+} tap_dance_tap_hold_t;
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ qk_tap_dance_action_t *action;
+
+ switch (keycode) {
+ case TD(CT_CLN):
+ action = &tap_dance_actions[TD_INDEX(keycode)];
+ if (!record->event.pressed && action->state.count && !action->state.finished) {
+ tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data;
+ tap_code16(tap_hold->tap);
+ }
+ }
+ return true;
+}
+
+void tap_dance_tap_hold_finished(qk_tap_dance_state_t *state, void *user_data) {
+ tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
+
+ if (state->pressed) {
+ if (state->count == 1
+#ifndef PERMISSIVE_HOLD
+ && !state->interrupted
+#endif
+ ) {
+ register_code16(tap_hold->hold);
+ tap_hold->held = tap_hold->hold;
+ } else {
+ register_code16(tap_hold->tap);
+ tap_hold->held = tap_hold->tap;
+ }
+ }
+}
+
+void tap_dance_tap_hold_reset(qk_tap_dance_state_t *state, void *user_data) {
+ tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
+
+ if (tap_hold->held) {
+ unregister_code16(tap_hold->held);
+ tap_hold->held = 0;
+ }
+}
+
+#define ACTION_TAP_DANCE_TAP_HOLD(tap, hold) \
+ { .fn = {NULL, tap_dance_tap_hold_finished, tap_dance_tap_hold_reset}, .user_data = (void *)&((tap_dance_tap_hold_t){tap, hold, 0}), }
+
+
+// Example 4
+
+typedef enum {
+ TD_NONE,
+ TD_UNKNOWN,
+ TD_SINGLE_TAP,
+ TD_SINGLE_HOLD,
+ TD_DOUBLE_TAP,
+ TD_DOUBLE_HOLD,
+ TD_DOUBLE_SINGLE_TAP,
+ TD_TRIPLE_TAP,
+ TD_TRIPLE_HOLD
+} td_state_t;
+
+typedef struct {
+ bool is_press_action;
+ td_state_t state;
+} td_tap_t;
+
+td_state_t cur_dance(qk_tap_dance_state_t *state) {
+ if (state->count == 1) {
+ if (state->interrupted || !state->pressed) return TD_SINGLE_TAP;
+ else return TD_SINGLE_HOLD;
+ } else if (state->count == 2) {
+ if (state->interrupted) return TD_DOUBLE_SINGLE_TAP;
+ else if (state->pressed) return TD_DOUBLE_HOLD;
+ else return TD_DOUBLE_TAP;
+ }
+
+ if (state->count == 3) {
+ if (state->interrupted || !state->pressed) return TD_TRIPLE_TAP;
+ else return TD_TRIPLE_HOLD;
+ } else return TD_UNKNOWN;
+}
+
+static td_tap_t xtap_state = {
+ .is_press_action = true,
+ .state = TD_NONE
+};
+
+void x_finished(qk_tap_dance_state_t *state, void *user_data) {
+ xtap_state.state = cur_dance(state);
+ switch (xtap_state.state) {
+ case TD_SINGLE_TAP: register_code(KC_X); break;
+ case TD_SINGLE_HOLD: register_code(KC_LCTL); break;
+ case TD_DOUBLE_TAP: register_code(KC_ESC); break;
+ case TD_DOUBLE_HOLD: register_code(KC_LALT); break;
+ case TD_DOUBLE_SINGLE_TAP: tap_code(KC_X); register_code(KC_X);
+ default: break; // Not present in documentation
+ }
+}
+
+void x_reset(qk_tap_dance_state_t *state, void *user_data) {
+ switch (xtap_state.state) {
+ case TD_SINGLE_TAP: unregister_code(KC_X); break;
+ case TD_SINGLE_HOLD: unregister_code(KC_LCTL); break;
+ case TD_DOUBLE_TAP: unregister_code(KC_ESC); break;
+ case TD_DOUBLE_HOLD: unregister_code(KC_LALT);
+ case TD_DOUBLE_SINGLE_TAP: unregister_code(KC_X);
+ default: break; // Not present in documentation
+ }
+ xtap_state.state = TD_NONE;
+}
+
+
+qk_tap_dance_action_t tap_dance_actions[] = {
+ [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS),
+ [CT_EGG] = ACTION_TAP_DANCE_FN(dance_egg),
+ [CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED(dance_flsh_each, dance_flsh_finished, dance_flsh_reset),
+ [CT_CLN] = ACTION_TAP_DANCE_TAP_HOLD(KC_COLN, KC_SCLN),
+ [X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset)
+};
+
+// clang-format on
diff --git a/tests/tap_dance/examples.h b/tests/tap_dance/examples.h
new file mode 100644
index 0000000000..2622af6b2f
--- /dev/null
+++ b/tests/tap_dance/examples.h
@@ -0,0 +1,33 @@
+/* Copyright 2022 Jouke Witteveen
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ TD_ESC_CAPS,
+ CT_EGG,
+ CT_FLSH,
+ CT_CLN,
+ X_CTL,
+};
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/tests/tap_dance/test.mk b/tests/tap_dance/test.mk
new file mode 100644
index 0000000000..041d9b4dc9
--- /dev/null
+++ b/tests/tap_dance/test.mk
@@ -0,0 +1,22 @@
+# Copyright 2022 Jouke Witteveen
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
+
+TAP_DANCE_ENABLE = yes
+
+SRC += examples.c
diff --git a/tests/tap_dance/test_examples.cpp b/tests/tap_dance/test_examples.cpp
new file mode 100644
index 0000000000..e67e6cb907
--- /dev/null
+++ b/tests/tap_dance/test_examples.cpp
@@ -0,0 +1,319 @@
+/* Copyright 2022 Jouke Witteveen
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
+#include "test_common.hpp"
+#include "action_tapping.h"
+#include "test_keymap_key.hpp"
+#include "examples.h"
+
+using testing::_;
+using testing::InSequence;
+
+class TapDance : public TestFixture {};
+
+TEST_F(TapDance, DoubleTap) {
+ TestDriver driver;
+ InSequence s;
+ auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)};
+
+ set_keymap({key_esc_caps});
+
+ /* The tap dance key does nothing on the first press */
+ key_esc_caps.press();
+ run_one_scan_loop();
+ key_esc_caps.release();
+ EXPECT_NO_REPORT(driver);
+
+ /* We get the key press and the release on timeout */
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_ESC));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Double tap gets us the second key */
+ tap_key(key_esc_caps);
+ EXPECT_NO_REPORT(driver);
+ key_esc_caps.press();
+ EXPECT_REPORT(driver, (KC_CAPS));
+ run_one_scan_loop();
+ key_esc_caps.release();
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+}
+
+TEST_F(TapDance, DoubleTapWithMod) {
+ TestDriver driver;
+ InSequence s;
+ auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)};
+ auto key_shift = KeymapKey{0, 2, 0, KC_LSFT};
+
+ set_keymap({key_esc_caps, key_shift});
+
+ /* The tap dance key does nothing on the first press */
+ key_shift.press();
+ EXPECT_REPORT(driver, (KC_LSFT));
+ run_one_scan_loop();
+ key_esc_caps.press();
+ run_one_scan_loop();
+
+ key_esc_caps.release();
+ key_shift.release();
+ EXPECT_EMPTY_REPORT(driver);
+
+ /* We get the key press and the release */
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_LSFT));
+ EXPECT_REPORT(driver, (KC_LSFT, KC_ESC));
+ EXPECT_REPORT(driver, (KC_LSFT));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Double tap gets us the second key */
+ key_shift.press();
+ EXPECT_REPORT(driver, (KC_LSFT));
+ run_one_scan_loop();
+ tap_key(key_esc_caps);
+ EXPECT_NO_REPORT(driver);
+ key_shift.release();
+ key_esc_caps.press();
+ EXPECT_REPORT(driver, (KC_LSFT, KC_CAPS));
+ run_one_scan_loop();
+ key_esc_caps.release();
+ EXPECT_REPORT(driver, (KC_LSFT));
+ run_one_scan_loop();
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+}
+
+TEST_F(TapDance, DoubleTapInterrupted) {
+ TestDriver driver;
+ InSequence s;
+ auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)};
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+
+ set_keymap({key_esc_caps, regular_key});
+
+ /* Interrupted double tap */
+ tap_key(key_esc_caps);
+ regular_key.press();
+ /* Immediate tap of the first key */
+ EXPECT_REPORT(driver, (KC_ESC));
+ EXPECT_EMPTY_REPORT(driver);
+ /* Followed by the interrupting key */
+ EXPECT_REPORT(driver, (KC_A));
+ run_one_scan_loop();
+ regular_key.release();
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Second tap after being interrupted acts as a single tap */
+ key_esc_caps.press();
+ run_one_scan_loop();
+ key_esc_caps.release();
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_ESC));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+}
+
+TEST_F(TapDance, DanceFn) {
+ TestDriver driver;
+ InSequence s;
+ auto key_egg = KeymapKey(0, 1, 0, TD(CT_EGG));
+
+ set_keymap({key_egg});
+
+ /* 99 taps do nothing */
+ for (int i = 0; i < 99; i++) {
+ run_one_scan_loop();
+ key_egg.press();
+ run_one_scan_loop();
+ key_egg.release();
+ }
+ idle_for(TAPPING_TERM);
+ EXPECT_NO_REPORT(driver);
+ run_one_scan_loop();
+
+ /* 100 taps trigger the action */
+ for (int i = 0; i < 100; i++) {
+ run_one_scan_loop();
+ key_egg.press();
+ run_one_scan_loop();
+ key_egg.release();
+ }
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_C));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* 250 taps act the same as 100 taps */
+ /* Taps are counted in an uint8_t, so the count overflows after 255 taps */
+ for (int i = 0; i < 250; i++) {
+ run_one_scan_loop();
+ key_egg.press();
+ run_one_scan_loop();
+ key_egg.release();
+ }
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_C));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+}
+
+TEST_F(TapDance, DanceFnAdvanced) {
+ TestDriver driver;
+ InSequence s;
+ auto key_flsh = KeymapKey(0, 1, 0, TD(CT_FLSH));
+
+ set_keymap({key_flsh});
+
+ /* Three taps don't trigger a reset */
+ EXPECT_REPORT(driver, (KC_3));
+ EXPECT_REPORT(driver, (KC_3, KC_2));
+ EXPECT_REPORT(driver, (KC_3, KC_2, KC_1));
+ for (int i = 0; i < 3; i++) {
+ run_one_scan_loop();
+ key_flsh.press();
+ run_one_scan_loop();
+ key_flsh.release();
+ }
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_3, KC_2));
+ EXPECT_REPORT(driver, (KC_3));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Four taps trigger a reset */
+ EXPECT_REPORT(driver, (KC_3));
+ EXPECT_REPORT(driver, (KC_3, KC_2));
+ EXPECT_REPORT(driver, (KC_3, KC_2, KC_1));
+ EXPECT_REPORT(driver, (KC_2, KC_1));
+ EXPECT_REPORT(driver, (KC_1));
+ EXPECT_EMPTY_REPORT(driver);
+ for (int i = 0; i < 4; i++) {
+ run_one_scan_loop();
+ key_flsh.press();
+ run_one_scan_loop();
+ key_flsh.release();
+ }
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_R));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+}
+
+TEST_F(TapDance, TapHold) {
+ TestDriver driver;
+ InSequence s;
+ auto key_cln = KeymapKey{0, 1, 0, TD(CT_CLN)};
+
+ set_keymap({key_cln});
+
+ /* Short taps fire on release */
+ key_cln.press();
+ run_one_scan_loop();
+ key_cln.release();
+ EXPECT_REPORT(driver, (KC_LSFT));
+ EXPECT_REPORT(driver, (KC_LSFT, KC_SCLN));
+ EXPECT_REPORT(driver, (KC_LSFT));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Holds immediate following a tap apply to the tap key */
+ key_cln.press();
+ EXPECT_REPORT(driver, (KC_LSFT));
+ EXPECT_REPORT(driver, (KC_LSFT, KC_SCLN));
+ idle_for(TAPPING_TERM * 2);
+ key_cln.release();
+ EXPECT_REPORT(driver, (KC_LSFT));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Holds trigger the hold key */
+ key_cln.press();
+ idle_for(TAPPING_TERM);
+ run_one_scan_loop();
+ EXPECT_REPORT(driver, (KC_SCLN));
+ run_one_scan_loop();
+ key_cln.release();
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+}
+
+TEST_F(TapDance, QuadFunction) {
+ TestDriver driver;
+ InSequence s;
+ auto key_quad = KeymapKey{0, 1, 0, TD(X_CTL)};
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+
+ set_keymap({key_quad, regular_key});
+
+ /* Single tap */
+ key_quad.press();
+ run_one_scan_loop();
+ key_quad.release();
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_X));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Single hold */
+ key_quad.press();
+ run_one_scan_loop();
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_LCTL));
+ run_one_scan_loop();
+ key_quad.release();
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Double tap */
+ tap_key(key_quad);
+ key_quad.press();
+ run_one_scan_loop();
+ key_quad.release();
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_ESC));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Double tap and hold */
+ tap_key(key_quad);
+ key_quad.press();
+ run_one_scan_loop();
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_LALT));
+ run_one_scan_loop();
+ key_quad.release();
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Double single tap */
+ tap_key(key_quad);
+ tap_key(key_quad);
+ regular_key.press();
+ EXPECT_REPORT(driver, (KC_X));
+ EXPECT_EMPTY_REPORT(driver);
+ EXPECT_REPORT(driver, (KC_X));
+ EXPECT_EMPTY_REPORT(driver);
+ EXPECT_REPORT(driver, (KC_A));
+ run_one_scan_loop();
+ regular_key.release();
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+}
diff --git a/tests/tapdance/config.h b/tests/tapdance/config.h
deleted file mode 100644
index 6aada3efd3..0000000000
--- a/tests/tapdance/config.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright 2022 Jouke Witteveen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#pragma once
-
-#include "test_common.h"
diff --git a/tests/tapdance/examples.c b/tests/tapdance/examples.c
deleted file mode 100644
index 4a5be41b08..0000000000
--- a/tests/tapdance/examples.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/* Copyright 2022 Jouke Witteveen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include "quantum.h"
-#include "examples.h"
-
-// Example code from the tap dance documentation, adapted for testing
-
-// clang-format off
-
-// Example 1
-
-void dance_egg(qk_tap_dance_state_t *state, void *user_data) {
- if (state->count >= 100) {
- // SEND_STRING("Safety dance!");
- tap_code(KC_C);
- reset_tap_dance(state);
- }
-}
-
-
-// Example 2
-
-void dance_flsh_each(qk_tap_dance_state_t *state, void *user_data) {
- switch (state->count) {
- case 1:
- register_code(KC_3);
- break;
- case 2:
- register_code(KC_2);
- break;
- case 3:
- register_code(KC_1);
- break;
- case 4:
- unregister_code(KC_3);
- // wait_ms(50);
- unregister_code(KC_2);
- // wait_ms(50);
- unregister_code(KC_1);
- }
-}
-
-void dance_flsh_finished(qk_tap_dance_state_t *state, void *user_data) {
- if (state->count >= 4) {
- // reset_keyboard();
- tap_code(KC_R);
- }
-}
-
-void dance_flsh_reset(qk_tap_dance_state_t *state, void *user_data) {
- unregister_code(KC_1);
- // wait_ms(50);
- unregister_code(KC_2);
- // wait_ms(50);
- unregister_code(KC_3);
-}
-
-
-// Example 3
-
-typedef struct {
- uint16_t tap;
- uint16_t hold;
- uint16_t held;
-} tap_dance_tap_hold_t;
-
-bool process_record_user(uint16_t keycode, keyrecord_t *record) {
- qk_tap_dance_action_t *action;
-
- switch (keycode) {
- case TD(CT_CLN):
- action = &tap_dance_actions[TD_INDEX(keycode)];
- if (!record->event.pressed && action->state.count && !action->state.finished) {
- tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data;
- tap_code16(tap_hold->tap);
- }
- }
- return true;
-}
-
-void tap_dance_tap_hold_finished(qk_tap_dance_state_t *state, void *user_data) {
- tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
-
- if (state->pressed) {
- if (state->count == 1
-#ifndef PERMISSIVE_HOLD
- && !state->interrupted
-#endif
- ) {
- register_code16(tap_hold->hold);
- tap_hold->held = tap_hold->hold;
- } else {
- register_code16(tap_hold->tap);
- tap_hold->held = tap_hold->tap;
- }
- }
-}
-
-void tap_dance_tap_hold_reset(qk_tap_dance_state_t *state, void *user_data) {
- tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
-
- if (tap_hold->held) {
- unregister_code16(tap_hold->held);
- tap_hold->held = 0;
- }
-}
-
-#define ACTION_TAP_DANCE_TAP_HOLD(tap, hold) \
- { .fn = {NULL, tap_dance_tap_hold_finished, tap_dance_tap_hold_reset}, .user_data = (void *)&((tap_dance_tap_hold_t){tap, hold, 0}), }
-
-
-// Example 4
-
-typedef enum {
- TD_NONE,
- TD_UNKNOWN,
- TD_SINGLE_TAP,
- TD_SINGLE_HOLD,
- TD_DOUBLE_TAP,
- TD_DOUBLE_HOLD,
- TD_DOUBLE_SINGLE_TAP,
- TD_TRIPLE_TAP,
- TD_TRIPLE_HOLD
-} td_state_t;
-
-typedef struct {
- bool is_press_action;
- td_state_t state;
-} td_tap_t;
-
-td_state_t cur_dance(qk_tap_dance_state_t *state) {
- if (state->count == 1) {
- if (state->interrupted || !state->pressed) return TD_SINGLE_TAP;
- else return TD_SINGLE_HOLD;
- } else if (state->count == 2) {
- if (state->interrupted) return TD_DOUBLE_SINGLE_TAP;
- else if (state->pressed) return TD_DOUBLE_HOLD;
- else return TD_DOUBLE_TAP;
- }
-
- if (state->count == 3) {
- if (state->interrupted || !state->pressed) return TD_TRIPLE_TAP;
- else return TD_TRIPLE_HOLD;
- } else return TD_UNKNOWN;
-}
-
-static td_tap_t xtap_state = {
- .is_press_action = true,
- .state = TD_NONE
-};
-
-void x_finished(qk_tap_dance_state_t *state, void *user_data) {
- xtap_state.state = cur_dance(state);
- switch (xtap_state.state) {
- case TD_SINGLE_TAP: register_code(KC_X); break;
- case TD_SINGLE_HOLD: register_code(KC_LCTL); break;
- case TD_DOUBLE_TAP: register_code(KC_ESC); break;
- case TD_DOUBLE_HOLD: register_code(KC_LALT); break;
- case TD_DOUBLE_SINGLE_TAP: tap_code(KC_X); register_code(KC_X);
- default: break; // Not present in documentation
- }
-}
-
-void x_reset(qk_tap_dance_state_t *state, void *user_data) {
- switch (xtap_state.state) {
- case TD_SINGLE_TAP: unregister_code(KC_X); break;
- case TD_SINGLE_HOLD: unregister_code(KC_LCTL); break;
- case TD_DOUBLE_TAP: unregister_code(KC_ESC); break;
- case TD_DOUBLE_HOLD: unregister_code(KC_LALT);
- case TD_DOUBLE_SINGLE_TAP: unregister_code(KC_X);
- default: break; // Not present in documentation
- }
- xtap_state.state = TD_NONE;
-}
-
-
-qk_tap_dance_action_t tap_dance_actions[] = {
- [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS),
- [CT_EGG] = ACTION_TAP_DANCE_FN(dance_egg),
- [CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED(dance_flsh_each, dance_flsh_finished, dance_flsh_reset),
- [CT_CLN] = ACTION_TAP_DANCE_TAP_HOLD(KC_COLN, KC_SCLN),
- [X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset)
-};
-
-// clang-format on
diff --git a/tests/tapdance/examples.h b/tests/tapdance/examples.h
deleted file mode 100644
index 2622af6b2f..0000000000
--- a/tests/tapdance/examples.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Copyright 2022 Jouke Witteveen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum {
- TD_ESC_CAPS,
- CT_EGG,
- CT_FLSH,
- CT_CLN,
- X_CTL,
-};
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/tests/tapdance/test.mk b/tests/tapdance/test.mk
deleted file mode 100644
index 041d9b4dc9..0000000000
--- a/tests/tapdance/test.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2022 Jouke Witteveen
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-# --------------------------------------------------------------------------------
-# Keep this file, even if it is empty, as a marker that this folder contains tests
-# --------------------------------------------------------------------------------
-
-TAP_DANCE_ENABLE = yes
-
-SRC += examples.c
diff --git a/tests/tapdance/test_examples.cpp b/tests/tapdance/test_examples.cpp
deleted file mode 100644
index e67e6cb907..0000000000
--- a/tests/tapdance/test_examples.cpp
+++ /dev/null
@@ -1,319 +0,0 @@
-/* Copyright 2022 Jouke Witteveen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include "keyboard_report_util.hpp"
-#include "keycode.h"
-#include "test_common.hpp"
-#include "action_tapping.h"
-#include "test_keymap_key.hpp"
-#include "examples.h"
-
-using testing::_;
-using testing::InSequence;
-
-class TapDance : public TestFixture {};
-
-TEST_F(TapDance, DoubleTap) {
- TestDriver driver;
- InSequence s;
- auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)};
-
- set_keymap({key_esc_caps});
-
- /* The tap dance key does nothing on the first press */
- key_esc_caps.press();
- run_one_scan_loop();
- key_esc_caps.release();
- EXPECT_NO_REPORT(driver);
-
- /* We get the key press and the release on timeout */
- idle_for(TAPPING_TERM);
- EXPECT_REPORT(driver, (KC_ESC));
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-
- /* Double tap gets us the second key */
- tap_key(key_esc_caps);
- EXPECT_NO_REPORT(driver);
- key_esc_caps.press();
- EXPECT_REPORT(driver, (KC_CAPS));
- run_one_scan_loop();
- key_esc_caps.release();
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-}
-
-TEST_F(TapDance, DoubleTapWithMod) {
- TestDriver driver;
- InSequence s;
- auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)};
- auto key_shift = KeymapKey{0, 2, 0, KC_LSFT};
-
- set_keymap({key_esc_caps, key_shift});
-
- /* The tap dance key does nothing on the first press */
- key_shift.press();
- EXPECT_REPORT(driver, (KC_LSFT));
- run_one_scan_loop();
- key_esc_caps.press();
- run_one_scan_loop();
-
- key_esc_caps.release();
- key_shift.release();
- EXPECT_EMPTY_REPORT(driver);
-
- /* We get the key press and the release */
- idle_for(TAPPING_TERM);
- EXPECT_REPORT(driver, (KC_LSFT));
- EXPECT_REPORT(driver, (KC_LSFT, KC_ESC));
- EXPECT_REPORT(driver, (KC_LSFT));
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-
- /* Double tap gets us the second key */
- key_shift.press();
- EXPECT_REPORT(driver, (KC_LSFT));
- run_one_scan_loop();
- tap_key(key_esc_caps);
- EXPECT_NO_REPORT(driver);
- key_shift.release();
- key_esc_caps.press();
- EXPECT_REPORT(driver, (KC_LSFT, KC_CAPS));
- run_one_scan_loop();
- key_esc_caps.release();
- EXPECT_REPORT(driver, (KC_LSFT));
- run_one_scan_loop();
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-}
-
-TEST_F(TapDance, DoubleTapInterrupted) {
- TestDriver driver;
- InSequence s;
- auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)};
- auto regular_key = KeymapKey(0, 2, 0, KC_A);
-
- set_keymap({key_esc_caps, regular_key});
-
- /* Interrupted double tap */
- tap_key(key_esc_caps);
- regular_key.press();
- /* Immediate tap of the first key */
- EXPECT_REPORT(driver, (KC_ESC));
- EXPECT_EMPTY_REPORT(driver);
- /* Followed by the interrupting key */
- EXPECT_REPORT(driver, (KC_A));
- run_one_scan_loop();
- regular_key.release();
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-
- /* Second tap after being interrupted acts as a single tap */
- key_esc_caps.press();
- run_one_scan_loop();
- key_esc_caps.release();
- idle_for(TAPPING_TERM);
- EXPECT_REPORT(driver, (KC_ESC));
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-}
-
-TEST_F(TapDance, DanceFn) {
- TestDriver driver;
- InSequence s;
- auto key_egg = KeymapKey(0, 1, 0, TD(CT_EGG));
-
- set_keymap({key_egg});
-
- /* 99 taps do nothing */
- for (int i = 0; i < 99; i++) {
- run_one_scan_loop();
- key_egg.press();
- run_one_scan_loop();
- key_egg.release();
- }
- idle_for(TAPPING_TERM);
- EXPECT_NO_REPORT(driver);
- run_one_scan_loop();
-
- /* 100 taps trigger the action */
- for (int i = 0; i < 100; i++) {
- run_one_scan_loop();
- key_egg.press();
- run_one_scan_loop();
- key_egg.release();
- }
- idle_for(TAPPING_TERM);
- EXPECT_REPORT(driver, (KC_C));
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-
- /* 250 taps act the same as 100 taps */
- /* Taps are counted in an uint8_t, so the count overflows after 255 taps */
- for (int i = 0; i < 250; i++) {
- run_one_scan_loop();
- key_egg.press();
- run_one_scan_loop();
- key_egg.release();
- }
- idle_for(TAPPING_TERM);
- EXPECT_REPORT(driver, (KC_C));
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-}
-
-TEST_F(TapDance, DanceFnAdvanced) {
- TestDriver driver;
- InSequence s;
- auto key_flsh = KeymapKey(0, 1, 0, TD(CT_FLSH));
-
- set_keymap({key_flsh});
-
- /* Three taps don't trigger a reset */
- EXPECT_REPORT(driver, (KC_3));
- EXPECT_REPORT(driver, (KC_3, KC_2));
- EXPECT_REPORT(driver, (KC_3, KC_2, KC_1));
- for (int i = 0; i < 3; i++) {
- run_one_scan_loop();
- key_flsh.press();
- run_one_scan_loop();
- key_flsh.release();
- }
- idle_for(TAPPING_TERM);
- EXPECT_REPORT(driver, (KC_3, KC_2));
- EXPECT_REPORT(driver, (KC_3));
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-
- /* Four taps trigger a reset */
- EXPECT_REPORT(driver, (KC_3));
- EXPECT_REPORT(driver, (KC_3, KC_2));
- EXPECT_REPORT(driver, (KC_3, KC_2, KC_1));
- EXPECT_REPORT(driver, (KC_2, KC_1));
- EXPECT_REPORT(driver, (KC_1));
- EXPECT_EMPTY_REPORT(driver);
- for (int i = 0; i < 4; i++) {
- run_one_scan_loop();
- key_flsh.press();
- run_one_scan_loop();
- key_flsh.release();
- }
- idle_for(TAPPING_TERM);
- EXPECT_REPORT(driver, (KC_R));
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-}
-
-TEST_F(TapDance, TapHold) {
- TestDriver driver;
- InSequence s;
- auto key_cln = KeymapKey{0, 1, 0, TD(CT_CLN)};
-
- set_keymap({key_cln});
-
- /* Short taps fire on release */
- key_cln.press();
- run_one_scan_loop();
- key_cln.release();
- EXPECT_REPORT(driver, (KC_LSFT));
- EXPECT_REPORT(driver, (KC_LSFT, KC_SCLN));
- EXPECT_REPORT(driver, (KC_LSFT));
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-
- /* Holds immediate following a tap apply to the tap key */
- key_cln.press();
- EXPECT_REPORT(driver, (KC_LSFT));
- EXPECT_REPORT(driver, (KC_LSFT, KC_SCLN));
- idle_for(TAPPING_TERM * 2);
- key_cln.release();
- EXPECT_REPORT(driver, (KC_LSFT));
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-
- /* Holds trigger the hold key */
- key_cln.press();
- idle_for(TAPPING_TERM);
- run_one_scan_loop();
- EXPECT_REPORT(driver, (KC_SCLN));
- run_one_scan_loop();
- key_cln.release();
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-}
-
-TEST_F(TapDance, QuadFunction) {
- TestDriver driver;
- InSequence s;
- auto key_quad = KeymapKey{0, 1, 0, TD(X_CTL)};
- auto regular_key = KeymapKey(0, 2, 0, KC_A);
-
- set_keymap({key_quad, regular_key});
-
- /* Single tap */
- key_quad.press();
- run_one_scan_loop();
- key_quad.release();
- idle_for(TAPPING_TERM);
- EXPECT_REPORT(driver, (KC_X));
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-
- /* Single hold */
- key_quad.press();
- run_one_scan_loop();
- idle_for(TAPPING_TERM);
- EXPECT_REPORT(driver, (KC_LCTL));
- run_one_scan_loop();
- key_quad.release();
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-
- /* Double tap */
- tap_key(key_quad);
- key_quad.press();
- run_one_scan_loop();
- key_quad.release();
- idle_for(TAPPING_TERM);
- EXPECT_REPORT(driver, (KC_ESC));
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-
- /* Double tap and hold */
- tap_key(key_quad);
- key_quad.press();
- run_one_scan_loop();
- idle_for(TAPPING_TERM);
- EXPECT_REPORT(driver, (KC_LALT));
- run_one_scan_loop();
- key_quad.release();
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-
- /* Double single tap */
- tap_key(key_quad);
- tap_key(key_quad);
- regular_key.press();
- EXPECT_REPORT(driver, (KC_X));
- EXPECT_EMPTY_REPORT(driver);
- EXPECT_REPORT(driver, (KC_X));
- EXPECT_EMPTY_REPORT(driver);
- EXPECT_REPORT(driver, (KC_A));
- run_one_scan_loop();
- regular_key.release();
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
-}
--
cgit v1.2.3