summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--quantum/action.c8
-rw-r--r--quantum/action_tapping.c10
-rw-r--r--quantum/process_keycode/process_combo.c1
-rw-r--r--tests/combo/config.h8
-rw-r--r--tests/combo/test.mk4
-rw-r--r--tests/combo/test_combo.cpp72
6 files changed, 97 insertions, 6 deletions
diff --git a/quantum/action.c b/quantum/action.c
index 9a6bbcca11..41c204f689 100644
--- a/quantum/action.c
+++ b/quantum/action.c
@@ -187,7 +187,7 @@ bool is_swap_hands_on(void) {
187 */ 187 */
188void process_hand_swap(keyevent_t *event) { 188void process_hand_swap(keyevent_t *event) {
189 keypos_t pos = event->key; 189 keypos_t pos = event->key;
190 if (pos.row < MATRIX_ROWS && pos.col < MATRIX_COLS) { 190 if (IS_KEYEVENT(*event) && pos.row < MATRIX_ROWS && pos.col < MATRIX_COLS) {
191 static uint8_t matrix_swap_state[((MATRIX_ROWS * MATRIX_COLS) + (CHAR_BIT)-1) / (CHAR_BIT)]; 191 static uint8_t matrix_swap_state[((MATRIX_ROWS * MATRIX_COLS) + (CHAR_BIT)-1) / (CHAR_BIT)];
192 size_t index = (size_t)(pos.row * MATRIX_COLS) + pos.col; 192 size_t index = (size_t)(pos.row * MATRIX_COLS) + pos.col;
193 bool do_swap = should_swap_hands(index, matrix_swap_state, event->pressed); 193 bool do_swap = should_swap_hands(index, matrix_swap_state, event->pressed);
@@ -200,7 +200,7 @@ void process_hand_swap(keyevent_t *event) {
200 } 200 }
201 } 201 }
202# ifdef ENCODER_MAP_ENABLE 202# ifdef ENCODER_MAP_ENABLE
203 else if (pos.row == KEYLOC_ENCODER_CW || pos.row == KEYLOC_ENCODER_CCW) { 203 else if (IS_ENCODEREVENT(*event) && pos.row == KEYLOC_ENCODER_CW || pos.row == KEYLOC_ENCODER_CCW) {
204 static uint8_t encoder_swap_state[((NUM_ENCODERS) + (CHAR_BIT)-1) / (CHAR_BIT)]; 204 static uint8_t encoder_swap_state[((NUM_ENCODERS) + (CHAR_BIT)-1) / (CHAR_BIT)];
205 size_t index = pos.col; 205 size_t index = pos.col;
206 bool do_swap = should_swap_hands(index, encoder_swap_state, event->pressed); 206 bool do_swap = should_swap_hands(index, encoder_swap_state, event->pressed);
@@ -242,6 +242,10 @@ __attribute__((weak)) void post_process_record_quantum(keyrecord_t *record) {}
242 * FIXME: Needs documentation. 242 * FIXME: Needs documentation.
243 */ 243 */
244void process_record_tap_hint(keyrecord_t *record) { 244void process_record_tap_hint(keyrecord_t *record) {
245 if (!IS_KEYEVENT(record->event)) {
246 return;
247 }
248
245 action_t action = layer_switch_get_action(record->event.key); 249 action_t action = layer_switch_get_action(record->event.key);
246 250
247 switch (action.kind.id) { 251 switch (action.kind.id) {
diff --git a/quantum/action_tapping.c b/quantum/action_tapping.c
index 362b15105c..f94e5e6f69 100644
--- a/quantum/action_tapping.c
+++ b/quantum/action_tapping.c
@@ -167,8 +167,10 @@ bool process_tapping(keyrecord_t *keyp) {
167 167
168 // state machine is in the "reset" state, no tapping key is to be 168 // state machine is in the "reset" state, no tapping key is to be
169 // processed 169 // processed
170 if (IS_NOEVENT(tapping_key.event) && IS_EVENT(event)) { 170 if (IS_NOEVENT(tapping_key.event)) {
171 if (event.pressed && is_tap_record(keyp)) { 171 if (!IS_EVENT(event)) {
172 // early return for tick events
173 } else if (event.pressed && is_tap_record(keyp)) {
172 // the currently pressed key is a tapping key, therefore transition 174 // the currently pressed key is a tapping key, therefore transition
173 // into the "pressed" tapping key state 175 // into the "pressed" tapping key state
174 ac_dprintf("Tapping: Start(Press tap key).\n"); 176 ac_dprintf("Tapping: Start(Press tap key).\n");
@@ -176,13 +178,13 @@ bool process_tapping(keyrecord_t *keyp) {
176 process_record_tap_hint(&tapping_key); 178 process_record_tap_hint(&tapping_key);
177 waiting_buffer_scan_tap(); 179 waiting_buffer_scan_tap();
178 debug_tapping_key(); 180 debug_tapping_key();
179 return true;
180 } else { 181 } else {
181 // the current key is just a regular key, pass it on for regular 182 // the current key is just a regular key, pass it on for regular
182 // processing 183 // processing
183 process_record(keyp); 184 process_record(keyp);
184 return true;
185 } 185 }
186
187 return true;
186 } 188 }
187 189
188 TAP_DEFINE_KEYCODE; 190 TAP_DEFINE_KEYCODE;
diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c
index b1b49d3019..2670ccabed 100644
--- a/quantum/process_keycode/process_combo.c
+++ b/quantum/process_keycode/process_combo.c
@@ -335,6 +335,7 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
335 // this in the end executes the combo when the key_buffer is dumped. 335 // this in the end executes the combo when the key_buffer is dumped.
336 record->keycode = combo->keycode; 336 record->keycode = combo->keycode;
337 record->event.type = COMBO_EVENT; 337 record->event.type = COMBO_EVENT;
338 record->event.key = MAKE_KEYPOS(0, 0);
338 339
339 qrecord->combo_index = combo_index; 340 qrecord->combo_index = combo_index;
340 ACTIVATE_COMBO(combo); 341 ACTIVATE_COMBO(combo);
diff --git a/tests/combo/config.h b/tests/combo/config.h
new file mode 100644
index 0000000000..8052932634
--- /dev/null
+++ b/tests/combo/config.h
@@ -0,0 +1,8 @@
1// Copyright 2023 Stefan Kerkmann (@KarlK90)
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "test_common.h"
7
8#define TAPPING_TERM 200
diff --git a/tests/combo/test.mk b/tests/combo/test.mk
new file mode 100644
index 0000000000..ce6f9fc2b0
--- /dev/null
+++ b/tests/combo/test.mk
@@ -0,0 +1,4 @@
1# Copyright 2023 Stefan Kerkmann (@KarlK90)
2# SPDX-License-Identifier: GPL-2.0-or-later
3
4COMBO_ENABLE = yes
diff --git a/tests/combo/test_combo.cpp b/tests/combo/test_combo.cpp
new file mode 100644
index 0000000000..b7aea27f4c
--- /dev/null
+++ b/tests/combo/test_combo.cpp
@@ -0,0 +1,72 @@
1// Copyright 2023 Stefan Kerkmann (@KarlK90)
2// Copyright 2023 @filterpaper
3// SPDX-License-Identifier: GPL-2.0-or-later
4
5#include "keyboard_report_util.hpp"
6#include "quantum.h"
7#include "keycode.h"
8#include "test_common.h"
9#include "test_driver.hpp"
10#include "test_fixture.hpp"
11#include "test_keymap_key.hpp"
12
13extern "C" {
14enum combos { modtest, osmshift, COMBO_LENGTH };
15uint16_t COMBO_LEN = COMBO_LENGTH;
16
17uint16_t const modtest_combo[] = {KC_Y, KC_U, COMBO_END};
18uint16_t const osmshift_combo[] = {KC_Z, KC_X, COMBO_END};
19
20// clang-format off
21combo_t key_combos[] = {
22 [modtest] = COMBO(modtest_combo, RSFT_T(KC_SPACE)),
23 [osmshift] = COMBO(osmshift_combo, OSM(MOD_LSFT))
24};
25// clang-format on
26}
27
28using testing::_;
29using testing::InSequence;
30
31class Combo : public TestFixture {};
32
33TEST_F(Combo, combo_modtest_tapped) {
34 TestDriver driver;
35 KeymapKey key_y(0, 0, 1, KC_Y);
36 KeymapKey key_u(0, 0, 2, KC_U);
37 set_keymap({key_y, key_u});
38
39 EXPECT_REPORT(driver, (KC_SPACE));
40 EXPECT_EMPTY_REPORT(driver);
41 tap_combo({key_y, key_u});
42 VERIFY_AND_CLEAR(driver);
43}
44
45TEST_F(Combo, combo_modtest_held_longer_than_tapping_term) {
46 TestDriver driver;
47 KeymapKey key_y(0, 0, 1, KC_Y);
48 KeymapKey key_u(0, 0, 2, KC_U);
49 set_keymap({key_y, key_u});
50
51 EXPECT_REPORT(driver, (KC_RIGHT_SHIFT));
52 EXPECT_EMPTY_REPORT(driver);
53 tap_combo({key_y, key_u}, TAPPING_TERM + 1);
54 VERIFY_AND_CLEAR(driver);
55}
56
57TEST_F(Combo, combo_osmshift_tapped) {
58 TestDriver driver;
59 KeymapKey key_z(0, 0, 1, KC_Z);
60 KeymapKey key_x(0, 0, 2, KC_X);
61 KeymapKey key_i(0, 0, 3, KC_I);
62 set_keymap({key_z, key_x, key_i});
63
64 EXPECT_NO_REPORT(driver);
65 tap_combo({key_z, key_x});
66 VERIFY_AND_CLEAR(driver);
67
68 EXPECT_REPORT(driver, (KC_I, KC_LEFT_SHIFT));
69 EXPECT_EMPTY_REPORT(driver);
70 tap_key(key_i);
71 VERIFY_AND_CLEAR(driver);
72}