* Enhance tap-hold docs.
* Minor edits.
* Move note on Quick Tap to a sub bullet for visibility.
Co-authored-by: Drashna Jaelre <drashna@live.com>
---------
Co-authored-by: Drashna Jaelre <drashna@live.com>
* Flow Tap bug fix.
As reported by @amarz45 and @mwpardue, there is a bug where if two
tap-hold keys are pressed in distinct taps back to back, then Flow Tap
is not applied on the second tap-hold key, but it should be.
In a related bug reported by @NikGovorov, if a tap-hold key is held
followed by a tap of a tap-hold key, then Flow Tap updates its timer on
the release of the held tap-hold key, but it should be ignored.
The problem common to both these bugs is that I incorrectly assumed
`tapping_key` is cleared to noevent once it is released, when actually
`tapping_key` is still maintained for `TAPPING_TERM` ms after release
(for Quick Tap). This commit fixes that. Thanks to @amarz45, @mwpardue,
and @NikGovorov for reporting!
Details:
* Logic for converting the current tap-hold event to a tap is extracted
to `flow_tap_key_if_within_term()`, which is now invoked also in the
post-release "interfered with other tap key" case. This fixes the
distinct taps bug.
* The Flow Tap timer is now updated at the beginning of each call to
`process_record()`, provided that there is no unsettled tap-hold key
at that time and that the record is not for a mod or layer switch key.
By moving this update logic to `process_record()`, it is conceptually
simpler and more robust.
* Unit tests extended to cover the reported scenarios.
* Fix formatting.
* Revision to fix @NikGovorov's scenario.
The issue is that when another key is pressed while a layer-tap hasn't
been settled yet, the `prev_keycode` remembers the keycode from before
the layer switched. This can then enable Flow Tap for the following key
when it shouldn't, or vice versa.
Thanks to @NikGovorov for reporting!
This commit revises Flow Tap in the following ways:
* The previous key and timer are both updated from `process_record()`.
This is slightly later in the sequence of processing than before, and
by this point, a just-settled layer-tap should have taken effect so
that the keycode from the correct layer is remembered.
* The Flow Tap previous key and timer are updated now also on key
release events, except for releases of modifiers and held layer
switches.
* The Flow Tap previous key and timer are now updated together, for
simplicity. This makes the logic easier to think about.
* A few additional unit tests, including @NikGovorov's scenario as
"layer_tap_ignored_with_disabled_key_complex."
* keycode_string(): Format keycodes as strings.
This adds the `keycode_string()` function described in
https://getreuer.info/posts/keyboards/keycode-string/index.html
as a core feature.
* Fix formatting.
* keycode_string review revisions.
* Rename keycode_string() -> get_keycode_string() for consistency with
existing string utils like get_u8_str().
* Revise custom keycode names with separate _user and _kb tables.
* Correct indent in builddefs/generic_features.mk.
Co-authored-by: Ryan <fauxpark@gmail.com>
* Add KC_NUHS, KC_NUBS, and KC_CAPS.
* Fix linking error with custom names.
* Attempt at simplifying interface.
* Formatting fix.
* Several fixes and revisions.
* Don't use PSTR in KEYCODE_STRING_NAME, since this fails to build on
AVR. Store custom names in RAM.
* Revise the internal table of common keycode names to use its own
storage representation, still in PROGMEM, and now more efficiently
stored flat in 8 bytes per entry.
* Support Swap Hands keycodes and a few other keycodes.
* Revert "Formatting fix."
This reverts commit 2a2771068c.
* Revert "Attempt at simplifying interface."
This reverts commit 8eaf67de76.
* Simplify custom names API by sigprof's suggestion.
* Support more keycodes.
* Add QK_LOCK keycode.
* Add Secure keycodes.
* Add Joystick keycodes.
* Add Programmable Button keycodes.
* Add macro MC_ keycodes.
* For remaining keys in known code ranges, stringify them as
"QK_<feature>+<number>". For instance, "QK_MIDI+7".
* Bug fix and a few improvements.
* Fix missing right-hand bit when displaying 5-bit mods numerically.
* Support KC_HYPR, KC_MEH, HYPR_T(kc), MEH_T(kc).
* Exclude one-shot keycodes when NO_ACTION_ONESHOT is defined.
---------
Co-authored-by: Ryan <fauxpark@gmail.com>
* Chordal Hold: restrict what chords settle as hold
* Chordal Hold: docs and further improvements
* Fix formatting.
* Doc rewording and minor edit.
* Support Chordal Hold of multiple tap-hold keys.
* Fix formatting.
* Simplification and additional test.
* Fix formatting.
* Tighten tests.
* Add test two_mod_taps_same_hand_hold_til_timeout.
* Revise handing of pairs of tap-hold keys.
* Generate a default chordal_hold_layout.
* Document chordal_hold_handedness().
* Add license notice to new and branched files in PR.
* Add `tapping.chordal_hold` property for info.json.
* Update docs/reference_info_json.md
* Revise "hand" jsonschema.
* Chordal Hold: Improved layout handedness heuristic.
This commit improves the heuristic used in generate-keyboard-c for
inferring key handedness from keyboard.json geometry data.
Heuristic summary:
1. If the layout is symmetric (e.g. most split keyboards), guess the
handedness based on the sign of (x - layout_x_midpoint).
2. Otherwise, if the layout has a key of >=6u width, it is probably the
spacebar. Form a dividing line through the spacebar, nearly vertical
but with a slight angle to follow typical row stagger.
3. Otherwise, assume handedness based on the widest horizontal
separation.
I have tested this strategy on a couple dozen keyboards and found it to
work reliably.
* Use Optional instead of `| None`.
* Refactor to avoid lambdas.
* Remove trailing comma in chordal_hold_layout.
* Minor docs edits.
* Revise to allow combining multiple same-hand mods.
This commit revises Chordal Hold as described in discussion in
https://github.com/qmk/qmk_firmware/pull/24560#discussion_r1894655238
1. In "RCTL_T(KC_A)↓, RSFT_T(KC_C)↓, RCTL_T(KC_A)↑" before the tapping
term, RCTL_T(KC_A) is settled as tapped.
2. In "RCTL_T(KC_A)↓, RSFT_T(KC_C)↓, RSFT_T(KC_C)↑", both RCTL_T(KC_A)
and RSFT_T(KC_C) are settled as tapped.
3. In "RCTL_T(KC_A)↓, RSFT_T(KC_C)↓, KC_U↓" (all keys on the same side),
both RCTL_T(KC_A) and RSFT_T(KC_C) are settled as tapped.
4. In "RCTL_T(KC_A)↓, RSFT_T(KC_C)↓, LSFT_T(KC_T)↓", with the third key
on the other side, we allow Permissive Hold or Hold On Other Keypress
to decide how/when to settle the keys.
5. In "RCTL_T(KC_A)↓, RSFT_T(KC_C)↓" held until the tapping term, the
keys are settled as held.
1–3 provide same-hand roll protection. 4–5 are for combining multiple
same-hand modifiers.
I've updated the unit tests and have been running it on my keyboard, for
a few hours so far, and all seems good. I really like this scheme. It
allows combining same-side mods, yet it also has roll protection on
streaks. For me, this feels like Achordion, but clearly better streak
handling and improved responsiveness.
* Fix formatting.
* Add a couple tests with LT keys.
* Remove stale use of CHORDAL_HOLD_LAYOUT.
* Fix misspelling lastest -> latest
* Handling tweak for LTs and tests.
* Fix formatting.
* More tests with LT keys.
* Fix formatting.
* Fix Caps Word to treat mod-taps more consistently.
Previously, holding any mod-tap key while Caps Word is active stops Caps
Word, and this happens regardless of `caps_word_press_user()`. Yet for
regular mod keys, AltGr (KC_RALT) is ignored, Shift keys are passed to
`caps_word_press_user()` to determine whether to continue, and
similarly, a key `RSFT(KC_RALT)` representing Right Shift + Alt is
passed to `caps_word_press_user()` to determine whether to continue.
This commit makes held mod-tap keys consistent with regular mod keys:
* Holding a `RALT_T` mod-tap is ignored.
* When holding a shift mod-tap key, `KC_LSFT` or `KC_RSFT` is passed to
`caps_word_press_user()` to determine whether to continue.
* When holding a Right Shift + Alt (`RSA_T`) mod-tap, `RSFT(KC_RALT)` is
passed to `caps_word_press_user()`.
Particularly, with this fix a user may choose to continue Caps Word when
a shift mod-tap key is held by adding `KC_LSFT` and `KC_RSFT` cases in
`caps_word_press_user()`. For instance as
```
bool caps_word_press_user(uint16_t keycode) {
switch (keycode) {
// Keycodes that continue Caps Word, with shift applied.
case KC_A ... KC_Z:
case KC_MINS:
add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to the next key.
return true;
// Keycodes that continue Caps Word, without shifting.
case KC_1 ... KC_0:
case KC_BSPC:
case KC_DEL:
case KC_UNDS:
case KC_LSFT: // <<< Added here.
case KC_RSFT:
return true;
default:
return false; // Deactivate Caps Word.
}
}
```
* Fix Caps Word to treat mod-taps more consistently.
Previously, holding any mod-tap key while Caps Word is active stops Caps
Word, and this happens regardless of `caps_word_press_user()`. Yet for
regular mod keys, AltGr (KC_RALT) is ignored, Shift keys are passed to
`caps_word_press_user()` to determine whether to continue, and
similarly, a key `RSFT(KC_RALT)` representing Right Shift + Alt is
passed to `caps_word_press_user()` to determine whether to continue.
This commit makes held mod-tap keys consistent with regular mod keys:
* Holding a `RALT_T` mod-tap is ignored.
* When holding a shift mod-tap key, `KC_LSFT` or `KC_RSFT` is passed to
`caps_word_press_user()` to determine whether to continue.
* When holding a Right Shift + Alt (`RSA_T`) mod-tap, `RSFT(KC_RALT)` is
passed to `caps_word_press_user()`.
Particularly, with this fix a user may choose to continue Caps Word when
a shift mod-tap key is held by adding `KC_LSFT` and `KC_RSFT` cases in
`caps_word_press_user()`. For instance as
```
bool caps_word_press_user(uint16_t keycode) {
switch (keycode) {
// Keycodes that continue Caps Word, with shift applied.
case KC_A ... KC_Z:
case KC_MINS:
add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to the next key.
return true;
// Keycodes that continue Caps Word, without shifting.
case KC_1 ... KC_0:
case KC_BSPC:
case KC_DEL:
case KC_UNDS:
case KC_LSFT: // <<< Added here.
case KC_RSFT:
return true;
default:
return false; // Deactivate Caps Word.
}
}
```
* Update quantum/process_keycode/process_caps_word.c
Co-authored-by: Joel Challis <git@zvecr.com>
* Fix Caps Word and Unicode Map
* Tests for Caps Word + Auto Shift and Unicode Map.
* Fix formatting
* Add additional keyboard report expectation macros
This commit defines five test utilities, EXPECT_REPORT, EXPECT_UNICODE,
EXPECT_EMPTY_REPORT, EXPECT_ANY_REPORT and EXPECT_NO_REPORT for use with
TestDriver.
EXPECT_REPORT sets a gmock expectation that a given keyboard report will
be sent. For instance,
EXPECT_REPORT(driver, (KC_LSFT, KC_A));
is shorthand for
EXPECT_CALL(driver,
send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A)));
EXPECT_UNICODE sets a gmock expectation that a given Unicode code point
will be sent using UC_LNX input mode. For instance for U+2013,
EXPECT_UNICODE(driver, 0x2013);
expects the sequence of keys:
"Ctrl+Shift+U, 2, 0, 1, 3, space".
EXPECT_EMPTY_REPORT sets a gmock expectation that a given keyboard
report will be sent. For instance
EXPECT_EMPTY_REPORT(driver);
expects a single report without keypresses or modifiers.
EXPECT_ANY_REPORT sets a gmock expectation that a arbitrary keyboard
report will be sent, without matching its contents. For instance
EXPECT_ANY_REPORT(driver).Times(1);
expects a single arbitrary keyboard report will be sent.
EXPECT_NO_REPORT sets a gmock expectation that no keyboard report will
be sent at all.
* Add tap_key() and tap_keys() to TestFixture.
This commit adds a `tap_key(key)` method to TestFixture that taps a
given KeymapKey, optionally with a specified delay between press and
release.
Similarly, the method `tap_keys(key_a, key_b, key_c)` taps a sequence of
KeymapKeys.
* Use EXPECT_REPORT, tap_keys, etc. in most tests.
This commit uses EXPECT_REPORT, EXPECT_UNICODE, EXPECT_EMPTY_REPORT,
EXPECT_NO_REPORT, tap_key() and tap_keys() test utilities from the
previous two commits in most tests. Particularly the EXPECT_REPORT
macro is frequently useful and makes a nice reduction in boilerplate
needed to express many tests.
Co-authored-by: David Kosorin <david@kosorin.net>
This is a minor bug fix for Caps Word. Currently, Caps Word turns off
whenever a non-shift mod becomes active. This is done to avoid
interfering with hotkeys.
This commit makes an exception to continue Caps Word when AltGr (right
Alt) is held. Outside the US, the AltGr key is used to type additional
symbols (https://en.wikipedia.org/wiki/AltGr_key). Depending on the
language, these may include symbols used within words like accented
letters where it would be desirable to continue Caps Word.