Skip to content

Commit

Permalink
Achordion: unregister eager mods in settle_as_hold
Browse files Browse the repository at this point in the history
Fixes #17

Currently, mods can get stuck if the mod is both eager and using the
one-shot mod-tap trick described here:
https://getreuer.info/posts/keyboards/achordion/index.html#one-shot-mod-tap-key
This commit fixes that.

Outline of how the stuck mod happened:

1. On press, the eager mod is registered.
2. Suppose the key continues to be held without other keys pressed. On
   timeout, `settle_as_hold()` is called to settle the key as held.
3. The default effect of holding a mod-tap key is (of course) to apply
   the mod. For this reason when the mod is eager, the current mod
   simply leaves the mod in effect, but sets `eager_mods = 0`.
4. In `process_record_user()`, the one-shot mod-tap handling code
   intercepts the hold press event, applying the one-shot behavior.
5. When the key is released, Achordion does *not* unregister the eager
   mod, since the key was settled.
6. In `process_record_user()`, the one-shot mod-tap handling code does
   nothing on release.

The one-shot mod is released, as it should, but the regular mod is still
stuck, since the eager mod was never cleared.

The fix is to unregister the mod in step 3.

Thanks to @jasonkena for reporting this.
  • Loading branch information
getreuer committed Aug 27, 2022
1 parent 95bdddf commit 393fa0b
Showing 1 changed file with 7 additions and 7 deletions.
14 changes: 7 additions & 7 deletions features/achordion.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,19 @@ static void recursively_process_record(keyrecord_t* record, uint8_t state) {
achordion_state = state;
}

// Sends hold press event and settles the active tap-hold key as held.
static void settle_as_hold(void) {
eager_mods = 0;
// Create hold press event.
recursively_process_record(&tap_hold_record, STATE_HOLDING);
}

// Clears eagerly-applied mods.
static void clear_eager_mods(void) {
unregister_mods(eager_mods);
eager_mods = 0;
}

// Sends hold press event and settles the active tap-hold key as held.
static void settle_as_hold(void) {
clear_eager_mods();
// Create hold press event.
recursively_process_record(&tap_hold_record, STATE_HOLDING);
}

bool process_achordion(uint16_t keycode, keyrecord_t* record) {
// Don't process events that Achordion generated.
if (achordion_state == STATE_RECURSING) { return true; }
Expand Down

0 comments on commit 393fa0b

Please sign in to comment.