Skip to content

feat: add configurable one-shot modifier behaviors#796

Open
ldsands wants to merge 4 commits intoHaoboGu:mainfrom
ldsands:feat/osm-enhanced-behavior
Open

feat: add configurable one-shot modifier behaviors#796
ldsands wants to merge 4 commits intoHaoboGu:mainfrom
ldsands:feat/osm-enhanced-behavior

Conversation

@ldsands
Copy link
Copy Markdown
Contributor

@ldsands ldsands commented Apr 10, 2026

Again, I'm trying to replicate all the features I was using previously on KMK. I've only got one more after this. I think I tested this fairly extensively on my own keyboard, and almost everything worked perfectly. I add this so that it is much easier to send a bare one-shot key to the OS than it was before. This allows you to double tap a one-shot key to immediately send that one-shot key to the os with no other keys. It also allows for sending the one-shot key once after tapping it when the timeout is reached. This is useful for using the gui (start) key which I couldn't use on its own to get to the start menu (on Windows and similar on Linux) while keeping the one-shot functionality. Thanks again.

Add three new configuration options for one-shot modifiers (OSM) and fix OSM interaction with mouse keys.

New OSM configuration options

All options default to false, preserving existing behavior for current users.

Re-press behavior — what happens when you press the same OSM key again while one-shot is active:

  • tap_on_double_press — send a bare modifier tap to the host and consume the one-shot state. Useful for intentionally firing the modifier by itself (e.g., tapping LGui twice to open the Start menu).
  • retap_cancel — cancel the one-shot silently without sending anything. Takes priority over tap_on_double_press if both are enabled.

Timeout behavior:

  • tap_on_timeout — when the one-shot timeout expires with no follow-up key, send a bare modifier tap instead of silently cancelling. Useful for triggering OS actions tied to a lone modifier press.
[behavior.one_shot_modifiers]
tap_on_timeout = true
tap_on_double_press = true

Behavior change: unconditional unstick-on-repress removed

The main branch (post-v0.8.2) added unconditional logic in process_action_osm() where re-pressing the same OSM key always removed the matching modifier bits and sent a report pair. This PR replaces that unconditional behavior with the explicit tap_on_double_press and retap_cancel options above.

Since the unstick behavior was added after v0.8.2 and has not been in a published release, this should not affect any released users. Users who adopted the behavior from main can restore it by adding tap_on_double_press = true to their config.

Bug fixes

OSM + mouse click: Mouse HID reports don't carry keyboard modifier bits. When an OSM modifier was active and a mouse button was pressed, the host received the click without modifier context, so combinations like Ctrl+Click didn't work. Fixed by sending a keyboard report with resolved OSM modifiers before the mouse report in process_action_mouse.

Select race in OSM timeout: Guard against the select race where the timer wins even though a key event arrived at the subscriber simultaneously. Now checks try_next_message_pure() before treating a timeout as genuine.

update_osm timing: Clear Single state on any key event (press or release), not just release. Since resolve_modifiers runs before update_osm, the modifier is already included in the HID report by the time update_osm executes, so clearing on press prevents the state from lingering between key press and release.

Tests

Four new tests covering the configurable behaviors:

  • test_osm_tap_on_timeout — bare modifier tap on timeout expiry
  • test_osm_tap_on_double_press — bare modifier tap on re-press
  • test_osm_retap_cancel — silent cancellation on re-press
  • test_osm_double_press_different_modifier_still_stacks — stacking different OSM modifiers still works with tap_on_double_press enabled

Context

I'm using a Sofle V2 split keyboard with sticky modifier keys (OSM) and needed these behaviors to match what I had in KMK firmware (KC.SK with retap_cancel=True and timeout tap). The mouse fix was discovered during daily use — Ctrl+Click for opening links in new tabs wasn't working with OSM-Ctrl.

Changes

  • rmk/src/keyboard/oneshot.rs — core OSM state machine changes
  • rmk/src/keyboard.rs — mouse + OSM modifier fix
  • rmk/src/config/behavior.rs — new config struct fields
  • rmk-config/src/lib.rs — TOML deserialization
  • rmk-config/src/resolved/behavior.rs — resolved config
  • rmk-macro/src/codegen/behavior.rs — proc macro codegen
  • rmk/tests/keyboard_one_shot_test.rs — 4 new tests
  • docs/docs/main/docs/configuration/behavior.md — user-facing docs
  • docs/docs/main/docs/configuration/appendix.md — full config reference

Minor Issue with Windows

The one "issue" is something that I'm pretty sure is an OS issue (with Windows gui+arrow keys) anyway. It works normally but when tapping (once) the one-shot gui key then layer key (MO) then tap an arrow key with another tap. It sends the correct combination but it also sends the gui key (seemingly independently). I realized that my KMK firmware also acted weird when doing this as well. This does not occur with any other key as far as I can tell (e.g. I tried using the exact same sequence but with the a key and it worked perfectly).

So again the only reason I came across it was due to trying to be comprehensive in my testing so it doesn't effect me but I figured I would be transparent. I tired to fix it for a while but couldn't figure out anything that worked. If anyone wants to take a stab at it feel free.

@ldsands ldsands marked this pull request as draft April 10, 2026 23:15
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 11, 2026

Size Report

Example main PR Diff .text .data .bss
use_config/nrf52832_ble 354.7 KiB 355.4 KiB +0.19% ⬆️ +716 0 +8
use_config/nrf52840_ble 405.5 KiB 406.0 KiB +0.12% ⬆️ +508 0 +8
use_config/nrf52840_ble_split (central) 482.8 KiB 483.3 KiB +0.11% ⬆️ +540 0 +8
use_config/nrf52840_ble_split (peripheral) 305.2 KiB 305.2 KiB +0.00% 0 0 0
use_config/pi_pico_w_ble 645.1 KiB 645.7 KiB +0.09% ⬆️ +600 0 +8
use_config/rp2040 146.2 KiB 146.8 KiB +0.40% ⬆️ +592 0 +8
use_config/rp2040_split (central) 157.2 KiB 157.7 KiB +0.36% ⬆️ +576 0 +8
use_config/rp2040_split (peripheral) 26.0 KiB 26.0 KiB +0.01% ⬆️ +4 0 0
use_config/stm32f1 63.5 KiB 64.1 KiB +0.87% ⬆️ +560 0 +8
use_config/stm32h7 100.4 KiB 101.0 KiB +0.51% ⬆️ +520 0 +8
use_rust/nrf52832_ble 343.9 KiB 344.2 KiB +0.08% ⬆️ +304 0 +8
use_rust/nrf52840_ble 402.7 KiB 403.3 KiB +0.12% ⬆️ +520 0 +8
use_rust/nrf52840_ble_split (central) 492.1 KiB 492.8 KiB +0.13% ⬆️ +652 0 +8
use_rust/nrf52840_ble_split (peripheral) 302.0 KiB 302.0 KiB +0.00% ⬆️ +8 0 0
use_rust/pi_pico_w_ble 645.3 KiB 646.0 KiB +0.10% ⬆️ +680 0 +8
use_rust/rp2040 146.5 KiB 147.2 KiB +0.48% ⬆️ +712 0 +8
use_rust/rp2040_split (central) 156.5 KiB 157.0 KiB +0.36% ⬆️ +572 0 +8
use_rust/rp2040_split (peripheral) 26.6 KiB 26.6 KiB +0.00% 0 0 0
use_rust/stm32f1 63.3 KiB 63.9 KiB +0.97% ⬆️ +624 0 +8
use_rust/stm32h7 119.5 KiB 120.2 KiB +0.58% ⬆️ +708 0 +8
use_config/nrf52832_ble — 354.7 KiB → 355.4 KiB (+0.19% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 324168	   5104	  34672	 363944	  58da8	rmk-nrf52832

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 323452	   5104	  34664	 363220	  58ad4	rmk-nrf52832

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +4.34Ki  [ = ]       0    .debug_str
  +0.1% +1.60Ki  [ = ]       0    .debug_info
  +0.2%    +716  +0.2%    +716    .text
  +0.2%    +534  [ = ]       0    .strtab
  +0.1%    +428  [ = ]       0    .debug_line
  +0.3%    +320  [ = ]       0    .symtab
  +0.4%    +164  [ = ]       0    .debug_frame
  +0.2%     +72  [ = ]       0    .debug_aranges
  +0.0%     +24  [ = ]       0    .debug_ranges
   +65%     +22  [ = ]       0    [Unmapped]
  [ = ]       0  +0.0%      +8    .bss
  +0.0%      +2  [ = ]       0    .debug_loc
  +0.1% +8.17Ki  +0.2%    +724    TOTAL
use_config/nrf52840_ble — 405.5 KiB → 406.0 KiB (+0.12% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 361916	   5104	  48760	 415780	  65824	rmk-nrf52840

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 361408	   5104	  48752	 415264	  65620	rmk-nrf52840

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +4.08Ki  [ = ]       0    .debug_str
  +0.1% +2.17Ki  [ = ]       0    .debug_info
  +0.1%    +949  [ = ]       0    .debug_loc
  +0.2%    +628  [ = ]       0    .debug_line
  +0.2%    +508  +0.2%    +508    .text
  +0.2%    +497  [ = ]       0    .strtab
  +0.2%    +256  [ = ]       0    .symtab
  +0.1%    +144  [ = ]       0    .debug_ranges
  +0.3%    +132  [ = ]       0    .debug_frame
  +0.1%     +56  [ = ]       0    .debug_aranges
  [ = ]       0  +0.0%      +8    .bss
  +0.9%      +8  [ = ]       0    .defmt
 -44.8%     -30  [ = ]       0    [Unmapped]
  +0.1% +9.33Ki  +0.1%    +516    TOTAL
use_config/nrf52840_ble_split (central) — 482.8 KiB → 483.3 KiB (+0.11% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 441592	   6428	  46872	 494892	  78d2c	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 441052	   6428	  46864	 494344	  78b08	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +3.23Ki  [ = ]       0    .debug_str
  +0.1% +1.82Ki  [ = ]       0    .debug_info
  +0.2% +1.10Ki  [ = ]       0    .debug_loc
  +0.2%    +560  [ = ]       0    .strtab
  +0.1%    +540  +0.1%    +540    .text
  +0.2%    +352  [ = ]       0    .symtab
  +0.1%    +328  [ = ]       0    .debug_line
  +0.3%    +164  [ = ]       0    .debug_frame
  +0.2%     +72  [ = ]       0    .debug_aranges
  +0.2%     +14  [ = ]       0    .debug_abbrev
  [ = ]       0  +0.0%      +8    .bss
   +13%      +7  [ = ]       0    [Unmapped]
  -0.0%     -88  [ = ]       0    .debug_ranges
  +0.1% +8.06Ki  +0.1%    +548    TOTAL
use_config/nrf52840_ble_split (peripheral) — 305.2 KiB → 305.2 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 280180	   5792	  26520	 312492	  4c4ac	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 280180	   5792	  26520	 312492	  4c4ac	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +11  [ = ]       0    .strtab
  +0.0%      +8  [ = ]       0    .debug_aranges
  -8.1%      -5  [ = ]       0    [Unmapped]
  -0.0%     -32  [ = ]       0    .debug_loc
  -0.0%    -257  [ = ]       0    .debug_info
  -0.1% -1.48Ki  [ = ]       0    .debug_str
  -0.0% -1.75Ki  [ = ]       0    TOTAL
use_config/pi_pico_w_ble — 645.1 KiB → 645.7 KiB (+0.09% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 605400	      0	  55800	 661200	  a16d0	rmk-pi-pico-w

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 604800	      0	  55792	 660592	  a1470	rmk-pi-pico-w

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +3.36Ki  [ = ]       0    .debug_str
  +0.1% +2.89Ki  [ = ]       0    .debug_info
  +0.2% +1.34Ki  [ = ]       0    .debug_loc
  +0.3%    +980  [ = ]       0    .debug_line
  +0.2%    +600  +0.2%    +600    .text
  +0.1%    +390  [ = ]       0    .strtab
  +0.2%    +192  [ = ]       0    .symtab
  +0.1%    +112  [ = ]       0    .debug_ranges
  +0.2%     +72  [ = ]       0    .debug_frame
  +0.1%     +24  [ = ]       0    .debug_aranges
   +21%     +10  [ = ]       0    [Unmapped]
  [ = ]       0  +0.0%      +8    .bss
  +0.1% +9.91Ki  +0.1%    +608    TOTAL
use_config/rp2040 — 146.2 KiB → 146.8 KiB (+0.40% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 134644	      0	  15672	 150316	  24b2c	rmk-rp2040

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 134052	      0	  15664	 149716	  248d4	rmk-rp2040

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.3% +3.89Ki  [ = ]       0    .debug_str
  +0.2% +2.09Ki  [ = ]       0    .debug_info
  +0.6% +1.66Ki  [ = ]       0    .debug_loc
  +0.4%    +638  [ = ]       0    .debug_line
  +0.5%    +592  +0.5%    +592    .text
  +0.4%    +391  [ = ]       0    .strtab
  +0.3%    +200  [ = ]       0    .debug_ranges
  +0.5%    +160  [ = ]       0    .symtab
  +0.4%     +72  [ = ]       0    .debug_frame
  +0.2%     +24  [ = ]       0    .debug_aranges
   +26%     +12  [ = ]       0    [Unmapped]
  [ = ]       0  +0.1%      +8    .bss
  +0.3% +9.68Ki  +0.4%    +600    TOTAL
use_config/rp2040_split (central) — 157.2 KiB → 157.7 KiB (+0.36% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 145088	      0	  16436	 161524	  276f4	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 144512	      0	  16428	 160940	  274ac	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +3.50Ki  [ = ]       0    .debug_str
  +0.2% +2.62Ki  [ = ]       0    .debug_info
  +0.3%    +887  [ = ]       0    .debug_loc
  +0.5%    +834  [ = ]       0    .debug_line
  +0.5%    +576  +0.5%    +576    .text
  +0.4%    +398  [ = ]       0    .strtab
  +0.4%    +160  [ = ]       0    .symtab
  +0.4%     +72  [ = ]       0    .debug_frame
  +0.1%     +24  [ = ]       0    .debug_aranges
  [ = ]       0  +0.1%      +8    .bss
  -0.0%     -16  [ = ]       0    .debug_ranges
  +0.3% +8.99Ki  +0.4%    +584    TOTAL
use_config/rp2040_split (peripheral) — 26.0 KiB → 26.0 KiB (+0.01% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  24144	     56	   2412	  26612	   67f4	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  24140	     56	   2412	  26608	   67f0	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +168  [ = ]       0    .debug_str
  +0.0%     +23  [ = ]       0    .debug_info
  +0.1%      +8  [ = ]       0    .debug_aranges
  +0.1%      +4  +0.1%      +4    .rodata
  -0.0%      -1  [ = ]       0    .strtab
  -4.4%      -2  [ = ]       0    [Unmapped]
  +0.0%    +200  +0.0%      +4    TOTAL
use_config/stm32f1 — 63.5 KiB → 64.1 KiB (+0.87% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  57540	     24	   8056	  65620	  10054	rmk-stm32f1

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  56980	     24	   8048	  65052	   fe1c	rmk-stm32f1

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.5% +3.89Ki  [ = ]       0    .debug_str
  +0.3% +1.71Ki  [ = ]       0    .debug_info
  +0.6%    +772  [ = ]       0    .debug_loc
  +1.0%    +560  +1.0%    +560    .text
  +0.6%    +518  [ = ]       0    .debug_line
  +1.2%    +410  [ = ]       0    .strtab
  +1.6%    +320  [ = ]       0    .symtab
  +1.4%    +180  [ = ]       0    .debug_frame
  +1.1%     +72  [ = ]       0    .debug_aranges
   +41%     +16  [ = ]       0    [Unmapped]
  [ = ]       0  +0.1%      +8    .bss
  -0.1%     -48  [ = ]       0    .debug_ranges
  +0.5% +8.33Ki  +0.9%    +568    TOTAL
use_config/stm32h7 — 100.4 KiB → 101.0 KiB (+0.51% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  92648	    264	  10464	 103376	  193d0	rmk-stm32h7

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  92128	    264	  10456	 102848	  191c0	rmk-stm32h7

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +3.54Ki  [ = ]       0    .debug_str
  +0.1% +1.14Ki  [ = ]       0    .debug_info
  +0.6% +1.06Ki  [ = ]       0    .debug_loc
  +0.5%    +577  [ = ]       0    .debug_line
  +0.7%    +520  +0.7%    +520    .text
  +0.7%    +413  [ = ]       0    .strtab
  +1.2%    +336  [ = ]       0    .symtab
  +1.2%    +180  [ = ]       0    .debug_frame
  +0.2%    +144  [ = ]       0    .debug_ranges
  +0.2%     +72  [ = ]       0    .debug_aranges
   +68%     +27  [ = ]       0    [Unmapped]
  [ = ]       0  +0.1%      +8    .bss
  +0.1%      +8  [ = ]       0    .debug_abbrev
  +0.2% +7.96Ki  +0.5%    +528    TOTAL
use_rust/nrf52832_ble — 343.9 KiB → 344.2 KiB (+0.08% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 313692	   5104	  33656	 352452	  560c4	rmk-nrf52832

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 313388	   5104	  33648	 352140	  55f8c	rmk-nrf52832

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +3.69Ki  [ = ]       0    .debug_str
  +0.1% +1.35Ki  [ = ]       0    .debug_info
  +0.1%    +795  [ = ]       0    .debug_loc
  +0.3%    +540  [ = ]       0    .strtab
  +0.5%    +528  [ = ]       0    .symtab
  +0.1%    +371  [ = ]       0    .debug_line
  +0.2%    +304  [ = ]       0    .debug_ranges
  +0.1%    +304  +0.1%    +304    .text
  +0.7%    +260  [ = ]       0    .debug_frame
  +0.3%    +112  [ = ]       0    .debug_aranges
  [ = ]       0  +0.0%      +8    .bss
  -0.2%     -16  [ = ]       0    .debug_abbrev
 -36.5%     -19  [ = ]       0    [Unmapped]
  +0.1% +8.15Ki  +0.1%    +312    TOTAL
use_rust/nrf52840_ble — 402.7 KiB → 403.3 KiB (+0.12% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 361272	   5104	  46560	 412936	  64d08	rmk-nrf52840

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 360752	   5104	  46552	 412408	  64af8	rmk-nrf52840

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +4.84Ki  [ = ]       0    .debug_str
  +0.1% +2.67Ki  [ = ]       0    .debug_info
  +0.2% +1.05Ki  [ = ]       0    .debug_loc
  +0.2%    +592  [ = ]       0    .strtab
  +0.2%    +520  +0.2%    +520    .text
  +0.1%    +465  [ = ]       0    .debug_line
  +0.3%    +384  [ = ]       0    .symtab
  +0.4%    +196  [ = ]       0    .debug_frame
  +0.2%     +88  [ = ]       0    .debug_aranges
  [ = ]       0  +0.0%      +8    .bss
 -22.9%     -11  [ = ]       0    [Unmapped]
  -0.1%    -160  [ = ]       0    .debug_ranges
  +0.1% +10.6Ki  +0.1%    +528    TOTAL
use_rust/nrf52840_ble_split (central) — 492.1 KiB → 492.8 KiB (+0.13% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 445580	   6428	  52608	 504616	  7b328	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 444928	   6428	  52600	 503956	  7b094	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +4.61Ki  [ = ]       0    .debug_str
  +0.1% +2.46Ki  [ = ]       0    .debug_info
  +0.1%    +861  [ = ]       0    .debug_loc
  +0.2%    +652  +0.2%    +652    .text
  +0.2%    +636  [ = ]       0    .strtab
  +0.1%    +480  [ = ]       0    .debug_line
  +0.3%    +448  [ = ]       0    .symtab
  +0.4%    +212  [ = ]       0    .debug_frame
  +0.2%     +96  [ = ]       0    .debug_aranges
  [ = ]       0  +0.0%      +8    .bss
 -22.9%     -11  [ = ]       0    [Unmapped]
  -0.1%    -192  [ = ]       0    .debug_ranges
  +0.1% +10.2Ki  +0.1%    +660    TOTAL
use_rust/nrf52840_ble_split (peripheral) — 302.0 KiB → 302.0 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 278720	   5232	  25288	 309240	  4b7f8	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 278712	   5232	  25288	 309232	  4b7f0	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +304  [ = ]       0    .debug_info
  +0.1%    +119  [ = ]       0    .debug_line
   +45%     +20  [ = ]       0    [Unmapped]
  +0.0%     +11  [ = ]       0    .strtab
  +0.0%      +8  [ = ]       0    .debug_aranges
  +0.0%      +8  +0.0%      +8    .text
  -0.0%      -1  [ = ]       0    .debug_loc
  -0.0%     -85  [ = ]       0    .debug_str
  +0.0%    +384  +0.0%      +8    TOTAL
use_rust/pi_pico_w_ble — 645.3 KiB → 646.0 KiB (+0.10% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 605716	      0	  55808	 661524	  a1814	rmk-pi-pico-w

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 605036	      0	  55800	 660836	  a1564	rmk-pi-pico-w

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +4.21Ki  [ = ]       0    .debug_str
  +0.1% +2.93Ki  [ = ]       0    .debug_info
  +0.3% +2.48Ki  [ = ]       0    .debug_loc
  +0.2%    +913  [ = ]       0    .debug_line
  +0.2%    +680  +0.2%    +680    .text
  +0.1%    +384  [ = ]       0    .strtab
  +0.1%    +200  [ = ]       0    .debug_ranges
  +0.2%    +160  [ = ]       0    .symtab
  +0.2%     +72  [ = ]       0    .debug_frame
  +0.1%     +24  [ = ]       0    .debug_aranges
  [ = ]       0  +0.0%      +8    .bss
 -11.6%      -8  [ = ]       0    [Unmapped]
  +0.1% +12.0Ki  +0.1%    +688    TOTAL
use_rust/rp2040 — 146.5 KiB → 147.2 KiB (+0.48% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 135032	      0	  15680	 150712	  24cb8	rmk-rp2040

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 134320	      0	  15672	 149992	  249e8	rmk-rp2040

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.4% +4.82Ki  [ = ]       0    .debug_str
  +0.9% +2.61Ki  [ = ]       0    .debug_loc
  +0.3% +2.44Ki  [ = ]       0    .debug_info
  +0.6%    +712  +0.6%    +712    .text
  +0.4%    +600  [ = ]       0    .debug_line
  +0.4%    +409  [ = ]       0    .strtab
  +0.5%    +352  [ = ]       0    .debug_ranges
  +0.8%    +256  [ = ]       0    .symtab
  +0.4%     +72  [ = ]       0    .debug_frame
  +0.2%     +24  [ = ]       0    .debug_aranges
  [ = ]       0  +0.1%      +8    .bss
 -13.4%      -9  [ = ]       0    [Unmapped]
  +0.4% +12.2Ki  +0.5%    +720    TOTAL
use_rust/rp2040_split (central) — 156.5 KiB → 157.0 KiB (+0.36% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 144468	      0	  16344	 160812	  2742c	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 143896	      0	  16336	 160232	  271e8	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +3.55Ki  [ = ]       0    .debug_str
  +0.3% +2.74Ki  [ = ]       0    .debug_info
  +0.4% +1.46Ki  [ = ]       0    .debug_loc
  +0.6% +1.02Ki  [ = ]       0    .debug_line
  +0.5%    +572  +0.5%    +572    .text
  +0.4%    +398  [ = ]       0    .strtab
  +0.5%    +160  [ = ]       0    .symtab
  +0.1%    +112  [ = ]       0    .debug_ranges
  +0.4%     +72  [ = ]       0    .debug_frame
  +0.1%     +24  [ = ]       0    .debug_aranges
  [ = ]       0  +0.1%      +8    .bss
   +15%      +8  [ = ]       0    [Unmapped]
  +0.3% +10.1Ki  +0.4%    +580    TOTAL
use_rust/rp2040_split (peripheral) — 26.6 KiB → 26.6 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  24472	     56	   2676	  27204	   6a44	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  24472	     56	   2676	  27204	   6a44	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +165  [ = ]       0    .debug_str
  +0.0%     +23  [ = ]       0    .debug_info
  +0.1%      +8  [ = ]       0    .debug_aranges
  +1.6%      +1  [ = ]       0    [Unmapped]
  -0.0%      -1  [ = ]       0    .strtab
  +0.0%    +196  [ = ]       0    TOTAL
use_rust/stm32f1 — 63.3 KiB → 63.9 KiB (+0.97% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  57324	     24	   8056	  65404	   ff7c	rmk-stm32f1

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  56700	     24	   8048	  64772	   fd04	rmk-stm32f1

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.5% +3.62Ki  [ = ]       0    .debug_str
  +0.3% +1.54Ki  [ = ]       0    .debug_info
  +0.6%    +780  [ = ]       0    .debug_loc
  +0.8%    +671  [ = ]       0    .debug_line
  +1.1%    +624  +1.1%    +624    .text
  +1.7%    +541  [ = ]       0    .strtab
  +2.6%    +512  [ = ]       0    .symtab
  +2.0%    +260  [ = ]       0    .debug_frame
  +2.3%    +112  [ = ]       0    .debug_aranges
  [ = ]       0  +0.1%      +8    .bss
 -29.5%     -18  [ = ]       0    [Unmapped]
  -0.1%     -40  [ = ]       0    .debug_ranges
  +0.5% +8.53Ki  +1.0%    +632    TOTAL
use_rust/stm32h7 — 119.5 KiB → 120.2 KiB (+0.58% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 106680	    320	  16088	 123088	  1e0d0	rmk-stm32h7

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 105972	    320	  16080	 122372	  1de04	rmk-stm32h7

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +2.91Ki  [ = ]       0    .debug_str
  +0.1% +1.21Ki  [ = ]       0    .debug_info
  +0.5% +1.07Ki  [ = ]       0    .debug_loc
  +0.5%    +807  [ = ]       0    .debug_line
  +0.7%    +708  +0.7%    +708    .text
  +0.7%    +520  [ = ]       0    .debug_ranges
  +0.4%    +333  [ = ]       0    .strtab
  +0.6%    +224  [ = ]       0    .symtab
  +0.7%    +132  [ = ]       0    .debug_frame
  +0.1%     +48  [ = ]       0    .debug_aranges
  [ = ]       0  +0.1%      +8    .bss
  -8.1%      -5  [ = ]       0    [Unmapped]
  +0.2% +7.89Ki  +0.6%    +716    TOTAL

@ldsands ldsands marked this pull request as ready for review April 11, 2026 00:35
@ldsands
Copy link
Copy Markdown
Contributor Author

ldsands commented Apr 11, 2026

Oops I accidentally pushed my other feature I've been working on into this pull request i'll remove it from here to make it simpler then make that a separate pr

@ldsands ldsands marked this pull request as draft April 11, 2026 18:36
@ldsands ldsands force-pushed the feat/osm-enhanced-behavior branch from c14518d to e30dc68 Compare April 11, 2026 18:42
ldsands added 4 commits April 11, 2026 14:27
Add three new configuration options for one-shot modifiers (OSM):

- `tap_on_timeout` (default: false) — when the one-shot timeout expires
  with no follow-up key, send a bare modifier tap to the host instead of
  silently cancelling. Useful for triggering OS actions tied to a lone
  modifier press (e.g., tapping LGui to open Start menu).

- `tap_on_double_press` (default: false) — when the same OSM key is
  pressed again while one-shot is active, send a bare modifier tap and
  consume the one-shot state. Provides a quick way to intentionally fire
  the modifier by itself.

- `retap_cancel` (default: false) — when the same OSM key is pressed
  again while one-shot is active, cancel the one-shot silently without
  sending anything. When both `tap_on_double_press` and `retap_cancel`
  are enabled, `retap_cancel` takes priority.

These replace the previous unconditional "unstick on re-press" behavior
(added after v0.8.2) with explicit, opt-in configuration. Users who
relied on the unstick behavior can restore it by setting
`tap_on_double_press = true`.

Also includes:
- Fix for select race condition in OSM timeout: guard against the timer
  winning the select even though a key event arrived simultaneously, by
  checking try_next_message_pure() before treating a timeout as genuine.
- Fix for update_osm: clear Single state on any key event (not just
  release), since resolve_modifiers already included the modifier in the
  HID report before update_osm runs.
- Tests for tap_on_timeout, tap_on_double_press, retap_cancel, and
  stacking different OSM modifiers with tap_on_double_press enabled.

Configuration example:
```toml
[behavior.one_shot_modifiers]
tap_on_timeout = true
tap_on_double_press = true
```
Mouse HID reports don't carry keyboard modifier bits. When an OSM
modifier is active and a mouse button is pressed, the host receives the
mouse click without any modifier context, so combinations like
Ctrl+Click don't work.

Send a keyboard report with the resolved OSM modifiers before the mouse
report in process_action_mouse, so the host applies the modifier to the
click.
Add documentation for tap_on_timeout, tap_on_double_press, and
retap_cancel in the behavior configuration guide and appendix reference.
@ldsands ldsands force-pushed the feat/osm-enhanced-behavior branch from e30dc68 to 413f63c Compare April 11, 2026 19:27
@ldsands ldsands marked this pull request as ready for review April 11, 2026 19:53
@ldsands
Copy link
Copy Markdown
Contributor Author

ldsands commented Apr 11, 2026

Okay now this is ready for review. Sorry about that branch mix up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant