Skip to content

[Bug] RETRO_TAPPING drops active Mod-Tap modifier due to shared global state #26126

@bilzard

Description

@bilzard

qmk_console.log

Describe the Bug

The root cause of this issue is that quantum/action.c manages the RETRO_TAPPING modifier state using a single global variable (retro_tap_curr_mods).

When a Layer-Tap key is tapped while a Mod-Tap key is being held, the unregister_mods(retro_tap_curr_mods); function at the end of the Retro Tapping process for the second key unintentionally clears the global modifier state. This results in the "killing" of the modifier for the first key, even though it is still physically held down.

Steps to Reproduce:

  1. Enable #define RETRO_TAPPING.
  2. Hold a Mod-Tap key (e.g., LSFT_T(KC_SPC)) -> Shift is registered.
  3. While holding it, tap a Layer-Tap key (e.g., LT(_LAYER, KC_MINS)) -> Shifted minus is output correctly via Retro Tapping.
  4. Type a third normal key (e.g., KC_A) while still holding the first Mod-Tap key.
  5. Expected: A (Shifted)
  6. Actual: a (Unshifted - the modifier was cleared by the previous Retro Tapping process).

Evidence

I have attached the QMK console log. The log clearly shows a discrepancy between the physical switch state (matrix) and the HID report.

  1. Row 09 (Thumb Shift) remains active (10000000) in the matrix scan throughout the session.
  2. However, after the second key (Layer-Tap) is released, the HID report for modifiers drops from 20 (Shift) to 00 (None) at line 39.
  3. This is because the RETRO_TAPPING logic in action_tapping.c unconditionally calls unregister_mods(), effectively "killing" the physically held modifier.

Log Highlight:

> 09: 10000000
> keyboard_report: 20 | 00 00 00 00 00 00 # Thumb Shift hold confirmed
...
> keyboard_report: 20 | 2D 00 00 00 00 00 # Shift + Minus (Layer-Tap)
> keyboard_report: 20 | 00 00 00 00 00 00 # Minus released
> keyboard_report: 00 | 00 00 00 00 00 00 # <-- BUG: Shift is forcibly reset to 0x00 while Row 09 is still 10000000
> 09: 10000000                          # Row 09 is still physically held!

Keyboard Used

salicylic_acid3/7skb

Link to product page (if applicable)

No response

Operating System

macOS Tahoe 26.31 (a)

qmk doctor Output

❯ qmk doctor
Ψ QMK Doctor is checking your environment.
Ψ Python version: 3.13.3
Ψ CLI version: 1.1.8
Ψ QMK home: /Users/bilzard/.go/src/github.com/qmk/qmk_firmware
Ψ Detected macOS 26.3.1 (Apple Silicon).
Ψ Testing userspace candidate: /Users/bilzard/.go/src/github.com/bilzard/qmk_userspace -- Valid `qmk.json`
Ψ QMK userspace: /Users/bilzard/.go/src/github.com/bilzard/qmk_userspace
Ψ Userspace enabled: True
Ψ Git branch: master
⚠ The official repository does not seem to be configured as git remote "upstream".
Ψ CLI installed in virtualenv.
Ψ All dependencies are installed.
Ψ Found arm-none-eabi-gcc version 15.2.0
☒ Failed to compile a simple program with arm-none-eabi-gcc, return code 1
☒ Command: arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mno-thumb-interwork --specs=nosys.specs --specs=nano.specs -x c -o /var/folders/1x/gbcc0yx16s18r3yrbxn3sc4w0000gn/T/tmpa6f5_9_9/test.elf /var/folders/1x/gbcc0yx16s18r3yrbxn3sc4w0000gn/T/tmpa6f5_9_9/test.c
Ψ Found avr-gcc version 9.5.0
Ψ Successfully compiled using avr-gcc
Ψ Successfully tested avr-binutils using avr-size
Ψ Found avrdude version 8.
Ψ Found dfu-programmer version 1.1.0
Ψ Found dfu-util version 0.11
Ψ Found diff version Apple diff (based on FreeBSD diff)
Ψ Found dos2unix version 7.5.4
Ψ Found git version 2.48.1
Ψ Found gmake version 4.4.1
Ψ Submodules are up to date.
Ψ Submodule status:
Ψ - lib/chibios: 2025-05-15 08:25:11 +0000 --  (8bd61b804)
Ψ - lib/chibios-contrib: 2025-10-03 18:22:15 +0200 --  (8d863d9e)
Ψ - lib/googletest: 2021-06-11 06:37:43 -0700 --  (e2239ee6)
Ψ - lib/lufa: 2022-08-26 12:09:55 +1000 --  (549b97320)
Ψ - lib/vusb: 2022-06-13 09:18:17 +1000 --  (819dbc1)
Ψ - lib/printf: 2022-06-29 23:59:58 +0300 --  (c2e3b4e)
Ψ - lib/pico-sdk: 2025-04-20 21:24:29 +1000 --  (d0c5cac)
Ψ - lib/lvgl: 2022-04-11 04:44:53 -0600 --  (e19410f8)
Ψ Major problems detected, please fix these problems before proceeding.
Ψ If you're missing dependencies, try following the instructions on: https://docs.qmk.fm/newbs_getting_started
Ψ Additionally, check out the FAQ (https://docs.qmk.fm/#/faq_build) or join the QMK Discord (https://discord.gg/qmk) for help.


**Note on Doctor Output:** Please ignore the `arm-none-eabi-gcc` error. I am using an AVR-based board (ATmega32U4), and the firmware compiles/flashes successfully using `avr-gcc`.

Is AutoHotKey / Karabiner installed

  • AutoHotKey (Windows)
  • Karabiner (macOS)

Other keyboard-related software installed

No response

Additional Context

I have identified the problematic code in quantum/action.c:

// Inside process_action() for RETRO_TAPPING
register_mods(retro_tap_curr_mods);
wait_ms(TAP_CODE_DELAY);
tap_code(action.layer_tap.code);
wait_ms(TAP_CODE_DELAY);
unregister_mods(retro_tap_curr_mods); // <--- THIS LINE IS THE CAUSE

source:

unregister_mods(retro_tap_curr_mods);

This unregister_mods call does not check if other dual-role keys are still being held. It forcibly clears the mods, breaking the state for the overlapping Mod-Tap key.

I also observed this behavior in the HID Console logs. When the Layer-Tap key is released, a keyboard_report of 00 | 00 00... is sent despite the thumb key (Row 9) still being physically active (10000000).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions