diff --git a/docs/feature_swap_hands.md b/docs/feature_swap_hands.md index 35131884e15..4d0d5540931 100644 --- a/docs/feature_swap_hands.md +++ b/docs/feature_swap_hands.md @@ -44,3 +44,9 @@ As an example, if a split keyboard has a single encoder per side, you can swap t const uint8_t PROGMEM encoder_hand_swap_config[NUM_ENCODERS] = { 1, 0 }; #endif ``` + +### Functions :id=functions + +| Function | Description | +|----------------------|---------------------------------------------| +| `is_swap_hands_on()` | Returns true if Swap-Hands is currently on. | diff --git a/quantum/action.c b/quantum/action.c index ee412db393a..d2e54bf8ec6 100644 --- a/quantum/action.c +++ b/quantum/action.c @@ -161,6 +161,10 @@ void set_swap_hands_state(size_t index, uint8_t *swap_state, bool on) { } } +bool is_swap_hands_on(void) { + return swap_hands; +} + /** \brief Process Hand Swap * * FIXME: Needs documentation. diff --git a/quantum/action.h b/quantum/action.h index e4d28ba9475..8ef6db6781a 100644 --- a/quantum/action.h +++ b/quantum/action.h @@ -84,6 +84,13 @@ typedef uint32_t swap_state_row_t; # error "MATRIX_COLS: invalid value" # endif +/** + * @brief Get the swap hands enable state + * + * @return true + * @return false + */ +bool is_swap_hands_on(void); void process_hand_swap(keyevent_t *record); #endif diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index f4982e82916..b4feb397392 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -128,7 +128,7 @@ action_t action_for_keycode(uint16_t keycode) { case QK_LAYER_MOD ... QK_LAYER_MOD_MAX: mod = mod_config(QK_LAYER_MOD_GET_MODS(keycode)); action_layer = QK_LAYER_MOD_GET_LAYER(keycode); - action.code = ACTION_LAYER_MODS(action_layer, mod); + action.code = ACTION_LAYER_MODS(action_layer, (mod & 0x10) ? mod << 4 : mod); break; #endif #ifndef NO_ACTION_TAPPING diff --git a/tests/basic/test_action_layer.cpp b/tests/basic/test_action_layer.cpp index 883d99b4040..b7ecfa52ef8 100644 --- a/tests/basic/test_action_layer.cpp +++ b/tests/basic/test_action_layer.cpp @@ -19,6 +19,7 @@ #include "test_common.hpp" using testing::_; +using testing::AnyNumber; using testing::InSequence; class ActionLayer : public TestFixture {}; @@ -399,3 +400,65 @@ TEST_F(ActionLayer, LayerTapReleasedBeforeKeypressReleaseWithModifiers) { EXPECT_TRUE(layer_state_is(0)); VERIFY_AND_CLEAR(driver); } + +TEST_F(ActionLayer, LayerModWithKeypress) { + TestDriver driver; + KeymapKey layer_key = KeymapKey{0, 0, 0, LM(1, MOD_RALT)}; + KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A}; + set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}}); + + // Allow any number of reports with no keys or only KC_RALT. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_RALT)))) + .Times(AnyNumber()); + // clang-format on + EXPECT_REPORT(driver, (KC_RALT, KC_B)).Times(1); + + layer_key.press(); + run_one_scan_loop(); + EXPECT_TRUE(layer_state_is(1)); + EXPECT_EQ(get_mods(), MOD_BIT(KC_RALT)); + + tap_key(regular_key); + + layer_key.release(); + run_one_scan_loop(); + EXPECT_TRUE(layer_state_is(0)); + EXPECT_EQ(get_mods(), 0); + + VERIFY_AND_CLEAR(driver); +} + +TEST_F(ActionLayer, LayerModHonorsModConfig) { + TestDriver driver; + KeymapKey layer_key = KeymapKey{0, 0, 0, LM(1, MOD_RALT)}; + KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A}; + set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}}); + + // Allow any number of reports with no keys or only KC_RALT. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_RGUI)))) + .Times(AnyNumber()); + // clang-format on + EXPECT_REPORT(driver, (KC_RGUI, KC_B)).Times(1); + + keymap_config.swap_ralt_rgui = true; + + layer_key.press(); + run_one_scan_loop(); + EXPECT_TRUE(layer_state_is(1)); + EXPECT_EQ(get_mods(), MOD_BIT(KC_RGUI)); + + tap_key(regular_key); + + layer_key.release(); + run_one_scan_loop(); + EXPECT_TRUE(layer_state_is(0)); + EXPECT_EQ(get_mods(), 0); + + VERIFY_AND_CLEAR(driver); +}