From cbabc8dbe6a8476d3082e8bc649d330f87e7b904 Mon Sep 17 00:00:00 2001 From: Albert Y <76888457+filterpaper@users.noreply.github.com> Date: Mon, 12 Dec 2022 23:52:22 +0800 Subject: [Core] Replace Tapping Force Hold feature with Quick Tap Term (#17007) * Replace Tapping Force Hold feature with Quick Tap Term * Replace keyboard level TAPPING_FORCE_HOLD with QUICK_TAP_TERM 0 * Deprecate force hold in info_config.json * Before and after quick tap term unit tests * Quick tap unit tests iteration * Keymap config.h correction * Remove TAPPING_FORCE_HOLD_PER_KEY macros that were missed * Add two more test cases for quick tap * Replace TAPPING_FORCE_HOLD with QUICK_TAP_TERM in configs #2 * Replace TAPPING_FORCE_HOLD_PER_KEY with QUICK_TAP_TERM_PER_KEY in configs #2 * Add function declaration for get_quick_tap_term Co-authored-by: Stefan Kerkmann --- tests/tap_hold_configurations/quick_tap/config.h | 21 ++ tests/tap_hold_configurations/quick_tap/test.mk | 18 ++ .../quick_tap/test_action_layer.cpp | 82 ++++++ .../quick_tap/test_quick_tap.cpp | 291 +++++++++++++++++++++ 4 files changed, 412 insertions(+) create mode 100644 tests/tap_hold_configurations/quick_tap/config.h create mode 100644 tests/tap_hold_configurations/quick_tap/test.mk create mode 100644 tests/tap_hold_configurations/quick_tap/test_action_layer.cpp create mode 100644 tests/tap_hold_configurations/quick_tap/test_quick_tap.cpp (limited to 'tests/tap_hold_configurations/quick_tap') diff --git a/tests/tap_hold_configurations/quick_tap/config.h b/tests/tap_hold_configurations/quick_tap/config.h new file mode 100644 index 0000000000..cd82d3b5a5 --- /dev/null +++ b/tests/tap_hold_configurations/quick_tap/config.h @@ -0,0 +1,21 @@ +/* Copyright 2021 Stefan Kerkmann + * + * 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" + +#define QUICK_TAP_TERM 100 diff --git a/tests/tap_hold_configurations/quick_tap/test.mk b/tests/tap_hold_configurations/quick_tap/test.mk new file mode 100644 index 0000000000..efecca2c22 --- /dev/null +++ b/tests/tap_hold_configurations/quick_tap/test.mk @@ -0,0 +1,18 @@ +# Copyright 2021 Stefan Kerkmann +# +# 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 +# -------------------------------------------------------------------------------- diff --git a/tests/tap_hold_configurations/quick_tap/test_action_layer.cpp b/tests/tap_hold_configurations/quick_tap/test_action_layer.cpp new file mode 100644 index 0000000000..9c3b38050a --- /dev/null +++ b/tests/tap_hold_configurations/quick_tap/test_action_layer.cpp @@ -0,0 +1,82 @@ +/* Copyright 2021 Stefan Kerkmann + * + * 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 "test_common.hpp" + +using testing::_; +using testing::InSequence; + +class ActionLayer : public TestFixture {}; + +TEST_F(ActionLayer, LayerTapToggleWithToggleWithKeypress) { + TestDriver driver; + KeymapKey layer_key = KeymapKey{0, 0, 0, TT(1)}; + + /* These keys must have the same position in the matrix, only the layer is different. */ + KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A}; + set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}}); + + /* Tap TT five times . */ + /* TODO: Tapping Force Hold breaks TT */ + EXPECT_NO_REPORT(driver); + + layer_key.press(); + run_one_scan_loop(); + layer_key.release(); + run_one_scan_loop(); + expect_layer_state(0); + + idle_for(QUICK_TAP_TERM + 10); + + layer_key.press(); + run_one_scan_loop(); + layer_key.release(); + run_one_scan_loop(); + expect_layer_state(0); + + layer_key.press(); + run_one_scan_loop(); + layer_key.release(); + run_one_scan_loop(); + expect_layer_state(0); + + layer_key.press(); + run_one_scan_loop(); + layer_key.release(); + run_one_scan_loop(); + expect_layer_state(0); + + layer_key.press(); + run_one_scan_loop(); + layer_key.release(); + run_one_scan_loop(); + expect_layer_state(0); + + testing::Mock::VerifyAndClearExpectations(&driver); + + EXPECT_REPORT(driver, (KC_A)).Times(1); + regular_key.press(); + run_one_scan_loop(); + expect_layer_state(0); + testing::Mock::VerifyAndClearExpectations(&driver); + + EXPECT_EMPTY_REPORT(driver).Times(1); + regular_key.release(); + run_one_scan_loop(); + expect_layer_state(0); + testing::Mock::VerifyAndClearExpectations(&driver); +} diff --git a/tests/tap_hold_configurations/quick_tap/test_quick_tap.cpp b/tests/tap_hold_configurations/quick_tap/test_quick_tap.cpp new file mode 100644 index 0000000000..be43f8e6c4 --- /dev/null +++ b/tests/tap_hold_configurations/quick_tap/test_quick_tap.cpp @@ -0,0 +1,291 @@ +/* Copyright 2021 Stefan Kerkmann + * + * 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 "config.h" +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "action_tapping.h" +#include "test_fixture.hpp" +#include "test_keymap_key.hpp" + +using testing::_; +using testing::InSequence; + +class QuickTap : public TestFixture {}; + +TEST_F(QuickTap, tap_regular_key_while_mod_tap_key_is_held) { + TestDriver driver; + InSequence s; + auto mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); + auto regular_key = KeymapKey(0, 2, 0, KC_A); + + set_keymap({mod_tap_key, regular_key}); + + /* Press mod-tap key. */ + EXPECT_NO_REPORT(driver); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Press regular key. */ + EXPECT_NO_REPORT(driver); + regular_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release regular key. */ + EXPECT_NO_REPORT(driver); + regular_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_REPORT(driver, (KC_LSFT)); + mod_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Idle for tapping term of mod tap hold key. */ + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_EMPTY_REPORT(driver); + idle_for(TAPPING_TERM - 3); + testing::Mock::VerifyAndClearExpectations(&driver); +} + +TEST_F(QuickTap, tap_mod_tap_key_while_mod_tap_key_is_held) { + TestDriver driver; + InSequence s; + auto first_mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); + auto second_mod_tap_key = KeymapKey(0, 2, 0, RSFT_T(KC_A)); + + set_keymap({first_mod_tap_key, second_mod_tap_key}); + + /* Press first mod-tap key */ + EXPECT_NO_REPORT(driver); + first_mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Press second mod-tap key */ + EXPECT_NO_REPORT(driver); + second_mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release second tap-hold key */ + EXPECT_NO_REPORT(driver); + second_mod_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release first mod-tap key */ + EXPECT_REPORT(driver, (KC_LSFT)); + first_mod_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Idle for tapping term of first mod-tap key. */ + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_EMPTY_REPORT(driver); + idle_for(TAPPING_TERM - 3); + testing::Mock::VerifyAndClearExpectations(&driver); +} + +TEST_F(QuickTap, tap_regular_key_while_layer_tap_key_is_held) { + TestDriver driver; + InSequence s; + auto layer_tap_key = KeymapKey(0, 1, 0, LT(1, KC_P)); + auto regular_key = KeymapKey(0, 2, 0, KC_A); + auto layer_key = KeymapKey(1, 2, 0, KC_B); + + set_keymap({layer_tap_key, regular_key, layer_key}); + + /* Press layer-tap key */ + EXPECT_NO_REPORT(driver); + layer_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Press regular key */ + EXPECT_NO_REPORT(driver); + regular_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release regular key */ + EXPECT_NO_REPORT(driver); + regular_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release layer-tap key */ + EXPECT_REPORT(driver, (KC_P)); + EXPECT_REPORT(driver, (KC_A, KC_P)); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + layer_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); +} + +TEST_F(QuickTap, tap_key_and_tap_again_before_quick_tap_term) { + TestDriver driver; + InSequence s; + auto mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); + + set_keymap({mod_tap_key}); + + /* Press mod-tap key. */ + EXPECT_NO_REPORT(driver); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + idle_for(QUICK_TAP_TERM - 10); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Press and tap mod-tap key again. */ + EXPECT_REPORT(driver, (KC_P)); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); +} + +TEST_F(QuickTap, tap_key_and_hold_again_before_quick_tap_term) { + TestDriver driver; + InSequence s; + auto mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); + + set_keymap({mod_tap_key}); + + /* Press mod-tap key. */ + EXPECT_NO_REPORT(driver); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + idle_for(QUICK_TAP_TERM - 10); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Press and hold mod-tap key again. */ + EXPECT_REPORT(driver, (KC_P)); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Wait until tapping term expired */ + EXPECT_NO_REPORT(driver); + idle_for(TAPPING_TERM); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); +} + + +TEST_F(QuickTap, tap_key_and_tap_again_after_quick_tap_term) { + TestDriver driver; + InSequence s; + auto mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); + + set_keymap({mod_tap_key}); + + /* Press mod-tap key. */ + EXPECT_NO_REPORT(driver); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + idle_for(QUICK_TAP_TERM + 10); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Press mod-tap key again. */ + EXPECT_NO_REPORT(driver); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); +} + +TEST_F(QuickTap, tap_key_and_hold_again_after_quick_tap_term) { + TestDriver driver; + InSequence s; + auto mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); + + set_keymap({mod_tap_key}); + + /* Press mod-tap key. */ + EXPECT_NO_REPORT(driver); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + idle_for(QUICK_TAP_TERM + 10); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Press and hold mod-tap key again. */ + EXPECT_NO_REPORT(driver); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Wait until tapping term expired */ + EXPECT_REPORT(driver, (KC_LSFT)); + idle_for(TAPPING_TERM); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); +} -- cgit v1.2.3