Skip to content

feat: add one-shot sticky modifiers#720

Merged
HaoboGu merged 1 commit intoHaoboGu:mainfrom
braindefender:ossm
Mar 20, 2026
Merged

feat: add one-shot sticky modifiers#720
HaoboGu merged 1 commit intoHaoboGu:mainfrom
braindefender:ossm

Conversation

@braindefender
Copy link
Contributor

Added One-Shot Sticky Modifiers functionality
Moved OSM/OSL logic into oneshot.rs file

Added two boolean config variables:

  • activate_on_keypress: Should modifiers be active from keypress (sticky modifiers)
  • send_on_second_press: Should the second keypress send modifiers and unstick them

Updated behavior.md docs to correspond with the new config structure:

[behavior.one_shot_modifiers]
  timeout = "1s"
  activate_on_keypress = false
  send_on_second_press = false

[behavior.one_shot_layers]
  timeout = "1s"

@github-actions
Copy link

github-actions bot commented Feb 2, 2026

Binary Size Report

use_config/nrf52832_ble

   text	   data	    bss	    dec	    hex	filename
 315708	   5104	  33736	 354548	  568f4	rmk-nrf52832
Diff
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +5.47Ki  [ = ]       0    .debug_str
  +0.1% +2.30Ki  [ = ]       0    .debug_info
  +0.1%    +701  [ = ]       0    .debug_loc
  +0.2%    +566  [ = ]       0    .debug_line
  +0.1%    +400  +0.1%    +400    .text
  +0.1%    +267  [ = ]       0    .strtab
  +0.1%    +208  [ = ]       0    .debug_ranges
  +0.2%    +192  [ = ]       0    .symtab
  +0.2%     +92  [ = ]       0    .debug_frame
  +0.2%     +72  +0.2%     +72    .rodata
  +0.1%     +40  [ = ]       0    .debug_aranges
  +7.9%      +5  [ = ]       0    [Unmapped]
  +0.2% +10.3Ki  +0.1%    +472    TOTAL

use_config/nrf52840_ble

   text	   data	    bss	    dec	    hex	filename
 352208	   5104	  47704	 405016	  62e18	rmk-nrf52840
Diff
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +5.55Ki  [ = ]       0    .debug_str
  +0.2% +3.35Ki  [ = ]       0    .debug_info
  +0.1%    +824  [ = ]       0    .debug_loc
  +0.2%    +568  [ = ]       0    .debug_line
  +0.1%    +420  +0.1%    +420    .text
  +0.1%    +239  [ = ]       0    .strtab
  +0.1%    +232  [ = ]       0    .debug_ranges
  +0.1%    +160  [ = ]       0    .symtab
  +0.9%     +76  [ = ]       0    .debug_abbrev
  +0.2%     +76  [ = ]       0    .debug_frame
  +0.2%     +72  +0.2%     +72    .rodata
  +0.1%     +32  [ = ]       0    .debug_aranges
 -23.4%     -15  [ = ]       0    [Unmapped]
  +0.2% +11.5Ki  +0.1%    +492    TOTAL

use_config/nrf52840_ble_split

   text	   data	    bss	    dec	    hex	filename
 430840	   6428	  45624	 482892	  75e4c	central

   text	   data	    bss	    dec	    hex	filename
 276432	   5792	  26696	 308920	  4b6b8	peripheral
Diff

Central Diff

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +5.92Ki  [ = ]       0    .debug_str
  +0.1% +1.99Ki  [ = ]       0    .debug_info
  +0.1%    +851  [ = ]       0    .debug_loc
  +0.2%    +548  [ = ]       0    .debug_line
  +0.1%    +432  +0.1%    +432    .text
  +0.1%    +228  [ = ]       0    .strtab
  +0.1%    +160  [ = ]       0    .symtab
  +0.1%    +152  [ = ]       0    .debug_ranges
  +0.2%     +76  [ = ]       0    .debug_frame
  +0.2%     +72  +0.2%     +72    .rodata
  +0.1%     +32  [ = ]       0    .debug_aranges
   +14%      +7  [ = ]       0    [Unmapped]
  +0.1% +10.4Ki  +0.1%    +504    TOTAL

Peripheral Diff

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +74  [ = ]       0    .debug_str
  +0.0%     +44  [ = ]       0    .debug_info
  +0.0%     +11  [ = ]       0    .strtab
  +0.0%      +4  +0.0%      +4    .text
  +0.0%      +1  [ = ]       0    .debug_line
  -8.6%      -6  [ = ]       0    [Unmapped]
  -0.0%      -8  [ = ]       0    .debug_ranges
  +0.0%    +120  +0.0%      +4    TOTAL

use_rust/nrf52840_ble_split

   text	   data	    bss	    dec	    hex	filename
 433708	   6428	  51336	 491472	  77fd0	central

   text	   data	    bss	    dec	    hex	filename
 274368	   5232	  25440	 305040	  4a790	peripheral
Diff

Central Diff

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +5.39Ki  [ = ]       0    .debug_str
  +0.1% +2.08Ki  [ = ]       0    .debug_info
  +0.1%    +851  [ = ]       0    .debug_loc
  +0.2%    +582  [ = ]       0    .debug_line
  +0.1%    +432  +0.1%    +432    .text
  +0.1%    +248  [ = ]       0    .strtab
  +0.1%    +160  [ = ]       0    .debug_ranges
  +0.1%    +160  [ = ]       0    .symtab
  +0.2%     +92  [ = ]       0    .debug_frame
  +0.2%     +72  +0.2%     +72    .rodata
  +0.1%     +40  [ = ]       0    .debug_aranges
  +0.3%     +24  [ = ]       0    .debug_abbrev
 -32.8%     -20  [ = ]       0    [Unmapped]
  +0.1% +10.1Ki  +0.1%    +504    TOTAL

Peripheral Diff

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +74  [ = ]       0    .debug_str
  +0.0%     +44  [ = ]       0    .debug_info
   +91%     +32  [ = ]       0    [Unmapped]
  +0.0%     +19  [ = ]       0    .debug_line
  +0.0%     +11  [ = ]       0    .strtab
  +0.0%      +4  +0.0%      +4    .text
  +0.0%    +184  +0.0%      +4    TOTAL

use_config/pi_pico_w_ble

   text	   data	    bss	    dec	    hex	filename
 597568	      0	  54712	 652280	  9f3f8	rmk-pi-pico-w
Diff
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +5.08Ki  [ = ]       0    .debug_str
  +0.1% +2.36Ki  [ = ]       0    .debug_info
  +0.1%    +904  [ = ]       0    .debug_loc
  +0.2%    +760  [ = ]       0    .debug_line
  +0.2%    +524  +0.2%    +524    .text
  +0.1%    +176  [ = ]       0    .debug_ranges
  +0.1%    +158  [ = ]       0    .strtab
  +0.2%    +128  [ = ]       0    .symtab
  +0.0%     +72  +0.0%     +72    .rodata
  +0.1%     +28  [ = ]       0    .debug_frame
  +0.0%      +8  [ = ]       0    .debug_aranges
 -32.4%     -22  [ = ]       0    [Unmapped]
  +0.1% +10.1Ki  +0.1%    +596    TOTAL

use_config/pi_pico_w_ble_split

   text	   data	    bss	    dec	    hex	filename
 629120	      0	  61240	 690360	  a88b8	central

   text	   data	    bss	    dec	    hex	filename
 493276	      0	  41924	 535200	  82aa0	peripheral
Diff

Central Diff

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +5.36Ki  [ = ]       0    .debug_str
  +0.1% +2.16Ki  [ = ]       0    .debug_info
  +0.1% +1.06Ki  [ = ]       0    .debug_loc
  +0.1%    +452  [ = ]       0    .debug_line
  +0.1%    +424  +0.1%    +424    .text
  +0.1%    +208  [ = ]       0    .debug_ranges
  +0.2%    +192  [ = ]       0    .symtab
  +0.1%    +158  [ = ]       0    .strtab
  +0.0%     +72  +0.0%     +72    .rodata
  +0.1%     +28  [ = ]       0    .debug_frame
  +0.0%      +8  [ = ]       0    .debug_aranges
 -22.2%     -14  [ = ]       0    [Unmapped]
  +0.1% +10.1Ki  +0.1%    +496    TOTAL

Peripheral Diff

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +48  [ = ]       0    .debug_str
  +0.0%     +44  [ = ]       0    .debug_info
  +0.0%     +21  [ = ]       0    .debug_loc
  +0.0%     +15  [ = ]       0    .debug_line
  +0.0%      +4  +0.0%      +4    .text
 -12.3%      -7  [ = ]       0    [Unmapped]
  -0.0%     -13  [ = ]       0    .strtab
  +0.0%    +112  +0.0%      +4    TOTAL

use_rust/pi_pico_w_ble_split

   text	   data	    bss	    dec	    hex	filename
 629676	      0	  61560	 691236	  a8c24	central

   text	   data	    bss	    dec	    hex	filename
 493764	      0	  41924	 535688	  82c88	peripheral
Diff

Central Diff

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +5.36Ki  [ = ]       0    .debug_str
  +0.1% +2.29Ki  [ = ]       0    .debug_info
  +0.1% +1.06Ki  [ = ]       0    .debug_loc
  +0.1%    +451  [ = ]       0    .debug_line
  +0.1%    +424  +0.1%    +424    .text
  +0.1%    +208  [ = ]       0    .debug_ranges
  +0.2%    +192  [ = ]       0    .symtab
  +0.1%    +158  [ = ]       0    .strtab
  +0.0%     +64  +0.0%     +64    .rodata
  +0.1%     +28  [ = ]       0    .debug_frame
   +59%     +26  [ = ]       0    [Unmapped]
  +0.0%      +8  [ = ]       0    .debug_aranges
  +0.1% +10.2Ki  +0.1%    +488    TOTAL

Peripheral Diff

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +48  [ = ]       0    .debug_str
  +0.0%     +44  [ = ]       0    .debug_info
  +0.0%     +12  [ = ]       0    .debug_line
   +13%      +5  [ = ]       0    [Unmapped]
  -0.0%      -4  -0.0%      -4    .text
  -0.0%     -13  [ = ]       0    .strtab
  +0.0%     +92  -0.0%      -4    TOTAL

use_config/rp2040

   text	   data	    bss	    dec	    hex	filename
 135584	      0	  15836	 151420	  24f7c	rmk-rp2040
Diff
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.4% +5.30Ki  [ = ]       0    .debug_str
  +0.2% +2.02Ki  [ = ]       0    .debug_info
  +0.3%    +900  [ = ]       0    .debug_loc
  +0.5%    +785  [ = ]       0    .debug_line
  +0.5%    +536  +0.5%    +536    .text
  +0.3%    +264  [ = ]       0    .debug_ranges
  +0.2%    +155  [ = ]       0    .strtab
  +0.3%     +96  [ = ]       0    .symtab
  +0.4%     +68  +0.4%     +68    .rodata
  +0.2%     +28  [ = ]       0    .debug_frame
  +0.1%      +8  [ = ]       0    .debug_aranges
   +12%      +5  [ = ]       0    [Unmapped]
  +0.3% +10.1Ki  +0.4%    +604    TOTAL

use_config/rp2040_split

   text	   data	    bss	    dec	    hex	filename
 147108	      0	  16864	 163972	  28084	central

   text	   data	    bss	    dec	    hex	filename
  23572	     56	   2492	  26120	   6608	peripheral
Diff

Central Diff

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.4% +5.77Ki  [ = ]       0    .debug_str
  +0.2% +2.35Ki  [ = ]       0    .debug_info
  +0.2%    +779  [ = ]       0    .debug_loc
  +0.4%    +683  [ = ]       0    .debug_line
  +0.4%    +548  +0.4%    +548    .text
  +0.2%    +216  [ = ]       0    .debug_ranges
  +0.1%    +140  [ = ]       0    .strtab
  +0.4%     +68  +0.4%     +68    .rodata
  +0.2%     +64  [ = ]       0    .symtab
  +0.1%     +28  [ = ]       0    .debug_frame
  +0.0%      +8  [ = ]       0    .debug_aranges
 -13.7%      -7  [ = ]       0    [Unmapped]
  +0.3% +10.6Ki  +0.4%    +616    TOTAL

Peripheral Diff

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +14  [ = ]       0    .debug_line
  +0.0%     +10  [ = ]       0    .debug_info
   +15%      +5  [ = ]       0    [Unmapped]
  +0.0%      +2  [ = ]       0    .debug_str
  +0.0%      +1  [ = ]       0    .strtab
  +0.0%     +32  [ = ]       0    TOTAL

use_rust/rp2040_split

   text	   data	    bss	    dec	    hex	filename
 145772	      0	  16468	 162240	  279c0	central

   text	   data	    bss	    dec	    hex	filename
  24300	     56	   2756	  27112	   69e8	peripheral
Diff

Central Diff

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.4% +5.38Ki  [ = ]       0    .debug_str
  +0.2% +2.35Ki  [ = ]       0    .debug_info
  +0.2%    +779  [ = ]       0    .debug_loc
  +0.4%    +679  [ = ]       0    .debug_line
  +0.4%    +556  +0.4%    +556    .text
  +0.2%    +216  [ = ]       0    .debug_ranges
  +0.1%    +140  [ = ]       0    .strtab
  +0.4%     +72  +0.4%     +72    .rodata
  +0.2%     +64  [ = ]       0    .symtab
  +0.2%     +28  [ = ]       0    .debug_frame
  +0.0%      +8  [ = ]       0    .debug_aranges
 -35.8%     -19  [ = ]       0    [Unmapped]
  +0.3% +10.2Ki  +0.4%    +628    TOTAL

Peripheral Diff

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +14  [ = ]       0    .debug_line
  +0.0%     +10  [ = ]       0    .debug_info
  +0.0%      +2  [ = ]       0    .debug_str
  +0.0%      +1  [ = ]       0    .strtab
  +2.2%      +1  [ = ]       0    [Unmapped]
  +0.0%     +28  [ = ]       0    TOTAL

use_config/stm32f1

   text	   data	    bss	    dec	    hex	filename
  57288	     24	   8072	  65384	   ff68	rmk-stm32f1
Diff
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.8% +5.58Ki  [ = ]       0    .debug_str
  +0.4% +2.18Ki  [ = ]       0    .debug_info
  +0.6%    +749  [ = ]       0    .debug_loc
  +0.6%    +543  [ = ]       0    .debug_line
  +0.7%    +396  +0.7%    +396    .text
  +0.7%    +312  [ = ]       0    .debug_ranges
  +0.5%    +174  [ = ]       0    .strtab
  +0.3%     +64  [ = ]       0    .symtab
  +0.3%     +44  [ = ]       0    .debug_frame
  +0.2%     +16  [ = ]       0    .debug_aranges
  +0.2%     +14  [ = ]       0    .debug_abbrev
 -22.4%     -13  [ = ]       0    [Unmapped]
  +0.6% +10.0Ki  +0.6%    +396    TOTAL

use_config/stm32f4

   text	   data	    bss	    dec	    hex	filename
 135984	    320	  16556	 152860	  2551c	rmk-stm32f4
Diff
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.3% +5.34Ki  [ = ]       0    .debug_str
  +0.2% +2.31Ki  [ = ]       0    .debug_info
  +0.3%    +736  [ = ]       0    .debug_loc
  +0.3%    +545  [ = ]       0    .debug_line
  +0.4%    +412  +0.4%    +412    .text
  +0.2%    +249  [ = ]       0    .strtab
  +0.5%    +192  [ = ]       0    .symtab
  +0.2%    +168  [ = ]       0    .debug_ranges
  +0.4%     +92  [ = ]       0    .debug_frame
  +0.4%     +72  +0.4%     +72    .rodata
  +0.2%     +40  [ = ]       0    .debug_aranges
   +78%     +29  [ = ]       0    [Unmapped]
  +0.3% +10.1Ki  +0.3%    +484    TOTAL

use_config/stm32h7

   text	   data	    bss	    dec	    hex	filename
  98280	    264	  10684	 109228	  1aaac	rmk-stm32h7
Diff
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.3% +5.67Ki  [ = ]       0    .debug_str
  +0.3% +2.47Ki  [ = ]       0    .debug_info
  +0.5%    +898  [ = ]       0    .debug_loc
  +0.4%    +561  [ = ]       0    .debug_line
  +0.5%    +400  +0.5%    +400    .text
  +0.4%    +205  [ = ]       0    .strtab
  +0.3%    +200  [ = ]       0    .debug_ranges
  +0.5%    +128  [ = ]       0    .symtab
  +0.5%     +72  +0.5%     +72    .rodata
  +0.4%     +60  [ = ]       0    .debug_frame
  +0.1%     +24  [ = ]       0    .debug_aranges
   +16%      +9  [ = ]       0    [Unmapped]
  +0.3% +10.6Ki  +0.4%    +472    TOTAL

@braindefender braindefender force-pushed the ossm branch 3 times, most recently from de53682 to 3f613b6 Compare February 4, 2026 03:35
@braindefender braindefender force-pushed the ossm branch 2 times, most recently from ce8b966 to f3a9186 Compare February 8, 2026 14:02
@braindefender
Copy link
Contributor Author

Updated the docs, squashed all WIP commits.
Now, I think, it's ready for review.
@HaoboGu

@braindefender braindefender force-pushed the ossm branch 2 times, most recently from 360291e to 010c139 Compare February 16, 2026 04:32
@braindefender
Copy link
Contributor Author

@HaoboGu Some tests failed, but I can't figure out why. Is main branch ok?

@HaoboGu
Copy link
Owner

HaoboGu commented Feb 16, 2026

I've fixed the test

@HaoboGu
Copy link
Owner

HaoboGu commented Feb 22, 2026

When send_on_second_press is enabled, pressing OSM(Shift), releasing it, then pressing and holding OSM(Shift) again while typing A sends an unshifted A, this feels like incorrect.

If the second tap of the same OSM cancels(releases) itself, when activate_on_keypress is enabled, the double-tap already works without send_on_second_press, right?

@braindefender
Copy link
Contributor Author

When send_on_second_press is enabled, pressing OSM(Shift), releasing it, then pressing and holding OSM(Shift) again while typing A sends an unshifted A, this feels like incorrect.

Why? send_on_second_press has fired modifier release on second press (not on press+release) as stated. So it won't already be active while you press A.

If the second tap of the same OSM cancels(releases) itself, when activate_on_keypress is enabled, the double-tap already works without send_on_second_press, right?

No, this is not quite right. When send_on_second_press is false, any consecutive taps on same OSM should do nothing. activate_on_keypress just holds it from the initial keypress.

@HaoboGu
Copy link
Owner

HaoboGu commented Feb 23, 2026

No, this is not quite right. When send_on_second_press is false, any consecutive taps on same OSM should do nothing. activate_on_keypress just holds it from the initial keypress.

Fair enough.

The only thing I'm thinking about now is:

Is send_on_second_press really needed except the "double-tap" case. For the double-tap case, I prefer to make

"Tap the same OSSM key for the second time within the timeout time: cancel current OSSM"

default behavior when activate_on_keypress = true. In this case, only one option(activate_on_keypress) is needed, and the second send in this comment can be eliminated.

But if there are other cases which need send_on_second_press, the current design is fine.

@braindefender
Copy link
Contributor Author

default behavior when activate_on_keypress = true. In this case, only one option(activate_on_keypress) is needed, and the second send in this comment can be eliminated.

But if there are other cases which need send_on_second_press, the current design is fine.

On the one hand, we need send_on_second_press for compatibility with the default QMK/ZMK behavior. Cause the user can just misclick when trying to combine mods and send_on_second_press will be unwanted in that case.

On the other hand, making this behavior default will make this behavior "smarter". But I don't think that the code simplicity wins against better configurability. So, it's up to you to decide which way it should be (:

@HaoboGu
Copy link
Owner

HaoboGu commented Mar 2, 2026

On the one hand, we need send_on_second_press for compatibility with the default QMK/ZMK behavior. Cause the user can just misclick when trying to combine mods and send_on_second_press will be unwanted in that case.

On the other hand, making this behavior default will make this behavior "smarter". But I don't think that the code simplicity wins against better configurability. So, it's up to you to decide which way it should be (:

I’d like to keep the configuration simple. For now, the activate_on_keypress option should be sufficient for most users. If we get more requests later, we can always add send_on_second_press. Let's remove it for the time being. Thank you a lot for the hard work, I really appreciate it

@braindefender braindefender force-pushed the ossm branch 3 times, most recently from 5092e31 to 6d04815 Compare March 19, 2026 10:38
@braindefender
Copy link
Contributor Author

@HaoboGu

Synced with the upstream and removed send_on_second_press making that behavior true by default.

Please, check that everything is okay.

Copy link
Owner

@HaoboGu HaoboGu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks nice now, only a minor import fix here

@braindefender
Copy link
Contributor Author

It looks nice now, only a minor import fix here

Fixed. Ready to merge?

@HaoboGu
Copy link
Owner

HaoboGu commented Mar 20, 2026

It looks nice now, only a minor import fix here

Fixed. Ready to merge?

Yes! Thanks a lot for your effort!

@HaoboGu HaoboGu merged commit 2776c2e into HaoboGu:main Mar 20, 2026
118 checks passed
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.

2 participants