Skip to content

Commit

Permalink
Select Word: Revise to avoid possible edge cases.
Browse files Browse the repository at this point in the history
Motivated by #26,
this commit makes a few tweaks to avoid what look like bugs in certain
edge case situations. Thanks to @windhausen for reporting this:

* On initial press, always clear the non-Shift mods.
* Change uses of `register_code()` on mod keys to `register_mods()`.
* Change uses of `SEND_STRING` to `tap_code()` calls, since the former
  is not supported on non-Latin layouts.
* Mac, don't use the Ctrl+A / Crtl+E , since KC_A and KC_E might be
  remapped to other meanings if the OS is set to a non-US QWERTY layout.
  Instead use GUI+Left / GUI+Right.
* Streamline to eliminate sending a unnecessary keyboard reports around
  setting and clearing mods.
  • Loading branch information
getreuer committed Jan 29, 2023
1 parent 2abf74d commit b9b7d28
Showing 1 changed file with 25 additions and 18 deletions.
43 changes: 25 additions & 18 deletions features/select_word.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2021-2022 Google LLC
// Copyright 2021-2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -38,32 +38,40 @@ bool process_select_word(uint16_t keycode, keyrecord_t* record,
if (keycode == sel_keycode && record->event.pressed) { // On key press.
const uint8_t mods = get_mods();
#ifndef NO_ACTION_ONESHOT
const uint8_t all_mods = mods | get_oneshot_mods();
const bool shifted = (mods | get_oneshot_mods()) & MOD_MASK_SHIFT;
clear_oneshot_mods();
#else
const uint8_t all_mods = mods;
const bool shifted = mods & MOD_MASK_SHIFT;
#endif // NO_ACTION_ONESHOT
if ((all_mods & MOD_MASK_SHIFT) == 0) { // Select word.

if (!shifted) { // Select word.
#ifdef MAC_HOTKEYS
register_code(KC_LALT);
set_mods(MOD_BIT(KC_LALT));
#else
register_code(KC_LCTL);
set_mods(MOD_BIT(KC_LCTL));
#endif // MAC_HOTKEYS
if (state == STATE_NONE) {
SEND_STRING(SS_TAP(X_RGHT) SS_TAP(X_LEFT));
send_keyboard_report();
tap_code(KC_RGHT);
tap_code(KC_LEFT);
}
register_code(KC_LSFT);
register_mods(MOD_BIT(KC_LSFT));
register_code(KC_RGHT);
state = STATE_WORD;
} else { // Select line.
if (state == STATE_NONE) {
clear_mods();
#ifndef NO_ACTION_ONESHOT
clear_oneshot_mods();
#endif // NO_ACTION_ONESHOT
#ifdef MAC_HOTKEYS
SEND_STRING(SS_LCTL("a" SS_LSFT("e")));
set_mods(MOD_BIT(KC_LGUI));
send_keyboard_report();
tap_code(KC_LEFT);
register_mods(MOD_BIT(KC_LSFT));
tap_code(KC_RGHT);
#else
SEND_STRING(SS_TAP(X_HOME) SS_LSFT(SS_TAP(X_END)));
clear_mods();
send_keyboard_report();
tap_code(KC_HOME);
register_mods(MOD_BIT(KC_LSFT));
tap_code(KC_END);
#endif // MAC_HOTKEYS
set_mods(mods);
state = STATE_FIRST_LINE;
Expand All @@ -79,11 +87,10 @@ bool process_select_word(uint16_t keycode, keyrecord_t* record,
switch (state) {
case STATE_WORD:
unregister_code(KC_RGHT);
unregister_code(KC_LSFT);
#ifdef MAC_HOTKEYS
unregister_code(KC_LALT);
unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_LALT));
#else
unregister_code(KC_LCTL);
unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_LCTL));
#endif // MAC_HOTKEYS
state = STATE_SELECTED;
break;
Expand All @@ -103,7 +110,7 @@ bool process_select_word(uint16_t keycode, keyrecord_t* record,
state = STATE_NONE;
return false;
}
// Fallthrough.
// Fallthrough intended.
default:
state = STATE_NONE;
}
Expand Down

0 comments on commit b9b7d28

Please sign in to comment.