at master 277 lines 9.8 kB view raw
1// Copyright 2021-2022 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#include "process_caps_word.h" 16#include "process_auto_shift.h" 17#include "process_space_cadet.h" 18#include "caps_word.h" 19#include "keycodes.h" 20#include "quantum_keycodes.h" 21#include "modifiers.h" 22#include "timer.h" 23#include "action_tapping.h" 24#include "action_util.h" 25 26#ifdef CAPS_WORD_INVERT_ON_SHIFT 27static uint8_t held_mods = 0; 28 29static bool handle_shift(uint16_t keycode, keyrecord_t* record) { 30 switch (keycode) { 31 case OSM(MOD_LSFT): 32 keycode = KC_LSFT; 33 break; 34 case OSM(MOD_RSFT): 35 keycode = KC_RSFT; 36 break; 37 38# ifndef NO_ACTION_TAPPING 39 case QK_MOD_TAP ... QK_MOD_TAP_MAX: 40 if (record->tap.count == 0) { // Mod-tap key is held. 41 switch (QK_MOD_TAP_GET_MODS(keycode)) { 42 case MOD_LSFT: 43 keycode = KC_LSFT; 44 break; 45 case MOD_RSFT: 46 keycode = KC_RSFT; 47 break; 48 } 49 } 50# endif // NO_ACTION_TAPPING 51 } 52 53 if (keycode == KC_LSFT || keycode == KC_RSFT) { 54 const uint8_t mod = MOD_BIT(keycode); 55 56 if (is_caps_word_on()) { 57 if (record->event.pressed) { 58 held_mods |= mod; 59 } else { 60 held_mods &= ~mod; 61 } 62 return false; 63 } else if ((held_mods & mod) != 0) { 64 held_mods &= ~mod; 65 del_mods(mod); 66 return record->event.pressed; 67 } 68 } 69 70 return true; 71} 72#endif // CAPS_WORD_INVERT_ON_SHIFT 73 74bool process_caps_word(uint16_t keycode, keyrecord_t* record) { 75 if (keycode == QK_CAPS_WORD_TOGGLE) { 76 if (record->event.pressed) { 77 caps_word_toggle(); 78 } 79 return false; 80 } 81#ifdef CAPS_WORD_INVERT_ON_SHIFT 82 if (!handle_shift(keycode, record)) { 83 return false; 84 } 85#endif // CAPS_WORD_INVERT_ON_SHIFT 86 87#ifndef NO_ACTION_ONESHOT 88 const uint8_t mods = get_mods() | get_oneshot_mods(); 89#else 90 const uint8_t mods = get_mods(); 91#endif // NO_ACTION_ONESHOT 92 93 if (!is_caps_word_on()) { 94 // The following optionally turns on Caps Word by holding left and 95 // right shifts or by double tapping left shift. This way Caps Word 96 // may be used without needing a dedicated key and also without 97 // needing combos or tap dance. 98 99#ifdef BOTH_SHIFTS_TURNS_ON_CAPS_WORD 100 // Many keyboards enable the Command feature by default, which also 101 // uses left+right shift. It can be configured to use a different 102 // key combination by defining IS_COMMAND(). We make a non-fatal 103 // warning if Command is enabled but IS_COMMAND() is *not* defined. 104# if defined(COMMAND_ENABLE) && !defined(IS_COMMAND) 105# pragma message "BOTH_SHIFTS_TURNS_ON_CAPS_WORD and Command should not be enabled at the same time, since both use the Left Shift + Right Shift key combination. Please disable Command, or ensure that `IS_COMMAND` is not set to (get_mods() == MOD_MASK_SHIFT)." 106# else 107 if (mods == MOD_MASK_SHIFT 108# ifdef COMMAND_ENABLE 109 // Don't activate Caps Word at the same time as Command. 110 && !(IS_COMMAND()) 111# endif // COMMAND_ENABLE 112 ) { 113 caps_word_on(); 114# ifdef SPACE_CADET_ENABLE 115 reset_space_cadet(); 116# endif // SPACE_CADET_ENABLE 117 } 118# endif // defined(COMMAND_ENABLE) && !defined(IS_COMMAND) 119#endif // BOTH_SHIFTS_TURNS_ON_CAPS_WORD 120 121#ifdef DOUBLE_TAP_SHIFT_TURNS_ON_CAPS_WORD 122 // Double tapping left shift turns on Caps Word. 123 // 124 // NOTE: This works with KC_LSFT and one-shot left shift. It 125 // wouldn't make sense with mod-tap or Space Cadet shift since 126 // double tapping would of course trigger the tapping action. 127 if (record->event.pressed) { 128 static bool tapped = false; 129 static uint16_t timer = 0; 130 if (keycode == KC_LSFT || keycode == OSM(MOD_LSFT)) { 131 if (tapped && !timer_expired(record->event.time, timer)) { 132 // Left shift was double tapped, activate Caps Word. 133 caps_word_on(); 134 } 135 tapped = true; 136 timer = record->event.time + GET_TAPPING_TERM(keycode, record); 137 } else { 138 tapped = false; // Reset when any other key is pressed. 139 } 140 } 141#endif // DOUBLE_TAP_SHIFT_TURNS_ON_CAPS_WORD 142 143 return true; 144 } 145 146#if CAPS_WORD_IDLE_TIMEOUT > 0 147 caps_word_reset_idle_timer(); 148#endif // CAPS_WORD_IDLE_TIMEOUT > 0 149 150 // From here on, we only take action on press events. 151 if (!record->event.pressed) { 152 return true; 153 } 154 155 if (!(mods & ~(MOD_MASK_SHIFT | MOD_BIT(KC_RALT)))) { 156 switch (keycode) { 157 // Ignore MO, TO, TG, TT, and OSL layer switch keys. 158 case QK_MOMENTARY ... QK_MOMENTARY_MAX: 159 case QK_TO ... QK_TO_MAX: 160 case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX: 161 case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX: 162 case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX: 163#ifdef TRI_LAYER_ENABLE // Ignore Tri Layer keys. 164 case QK_TRI_LAYER_LOWER ... QK_TRI_LAYER_UPPER: 165#endif // TRI_LAYER_ENABLE 166#ifdef LAYER_LOCK_ENABLE // Ignore Layer Lock key. 167 case QK_LAYER_LOCK: 168#endif // LAYER_LOCK_ENABLE 169 // Ignore AltGr. 170 case KC_RALT: 171 case OSM(MOD_RALT): 172 return true; 173 174#ifndef NO_ACTION_TAPPING 175 // Corresponding to mod keys above, a held mod-tap is handled as: 176 // * For shift mods, pass KC_LSFT or KC_RSFT to 177 // caps_word_press_user() to determine whether to continue. 178 // * For Shift + AltGr (MOD_RSFT | MOD_RALT), pass RSFT(KC_RALT). 179 // * AltGr (MOD_RALT) is ignored. 180 // * Otherwise stop Caps Word. 181 case QK_MOD_TAP ... QK_MOD_TAP_MAX: 182 if (record->tap.count == 0) { // Mod-tap key is held. 183 const uint8_t mods = QK_MOD_TAP_GET_MODS(keycode); 184 switch (mods) { 185# ifndef CAPS_WORD_INVERT_ON_SHIFT 186 case MOD_LSFT: 187 keycode = KC_LSFT; 188 break; 189 case MOD_RSFT: 190 keycode = KC_RSFT; 191 break; 192# endif // CAPS_WORD_INVERT_ON_SHIFT 193 case MOD_RSFT | MOD_RALT: 194 keycode = RSFT(KC_RALT); 195 break; 196 case MOD_RALT: 197 return true; 198 default: 199 caps_word_off(); 200# ifdef CAPS_WORD_INVERT_ON_SHIFT 201 add_mods(held_mods); 202# endif // CAPS_WORD_INVERT_ON_SHIFT 203 return true; 204 } 205 } else { 206 keycode = QK_MOD_TAP_GET_TAP_KEYCODE(keycode); 207 } 208 break; 209 210# ifndef NO_ACTION_LAYER 211 case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: 212# endif // NO_ACTION_LAYER 213 if (record->tap.count == 0) { 214 return true; 215 } 216 keycode = QK_LAYER_TAP_GET_TAP_KEYCODE(keycode); 217 break; 218#endif // NO_ACTION_TAPPING 219 220#ifdef SWAP_HANDS_ENABLE 221 case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX: 222 // Note: IS_SWAP_HANDS_KEYCODE() actually tests for the special action keycodes like SH_TOGG, SH_TT, ..., 223 // which currently overlap the SH_T(kc) range. 224 if (IS_SWAP_HANDS_KEYCODE(keycode) 225# ifndef NO_ACTION_TAPPING 226 || record->tap.count == 0 227# endif // NO_ACTION_TAPPING 228 ) { 229 return true; 230 } 231 keycode = QK_SWAP_HANDS_GET_TAP_KEYCODE(keycode); 232 break; 233#endif // SWAP_HANDS_ENABLE 234 } 235 236#ifdef AUTO_SHIFT_ENABLE 237 del_weak_mods(get_autoshift_state() ? ~MOD_BIT(KC_LSFT) : 0xff); 238#else 239 clear_weak_mods(); 240#endif // AUTO_SHIFT_ENABLE 241 if (caps_word_press_user(keycode)) { 242#ifdef CAPS_WORD_INVERT_ON_SHIFT 243 if (held_mods) { 244 set_weak_mods(get_weak_mods() ^ MOD_BIT(KC_LSFT)); 245 } 246#endif // CAPS_WORD_INVERT_ON_SHIFT 247 send_keyboard_report(); 248 return true; 249 } 250 } 251 252 caps_word_off(); 253#ifdef CAPS_WORD_INVERT_ON_SHIFT 254 add_mods(held_mods); 255#endif // CAPS_WORD_INVERT_ON_SHIFT 256 return true; 257} 258 259__attribute__((weak)) bool caps_word_press_user(uint16_t keycode) { 260 switch (keycode) { 261 // Keycodes that continue Caps Word, with shift applied. 262 case KC_A ... KC_Z: 263 case KC_MINS: 264 add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to next key. 265 return true; 266 267 // Keycodes that continue Caps Word, without shifting. 268 case KC_1 ... KC_0: 269 case KC_BSPC: 270 case KC_DEL: 271 case KC_UNDS: 272 return true; 273 274 default: 275 return false; // Deactivate Caps Word. 276 } 277}