tap_dances.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /*
  2. Copyright 2018 Eric Gebhart <e.a.gebhart@gmail.com>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. #ifdef TAP_DANCES_ENABLE
  15. #include "tap_dances.h"
  16. #include "action.h"
  17. #include "action_layer.h"
  18. #include "process_keycode/process_tap_dance.h"
  19. void tap_dance_mouse_btns (qk_tap_dance_state_t *state, void *user_data) {
  20. switch(state->count){
  21. case 1:
  22. register_code(KC_BTN1);
  23. break;
  24. case 2:
  25. register_code(KC_BTN2);
  26. break;
  27. case 3:
  28. register_code(KC_BTN3);
  29. break;
  30. case 4:
  31. register_code(KC_BTN4);
  32. break;
  33. case 5:
  34. register_code(KC_BTN5);
  35. break;
  36. default:
  37. break;
  38. }
  39. reset_tap_dance(state);
  40. }
  41. // counting on all the qwerty layers to be less than dvorak_on_bepo
  42. int on_qwerty(){
  43. uint8_t deflayer = (biton32(default_layer_state));
  44. switch(deflayer){
  45. case _DVORAK_BP:
  46. case _BEAKL_BP:
  47. case _BEPO:
  48. return (false);
  49. default:
  50. break;
  51. }
  52. return (true);
  53. }
  54. static void switch_default_layer(uint8_t layer) {
  55. default_layer_set(1UL<<layer);
  56. clear_keyboard();
  57. }
  58. // so the keyboard remembers which layer it's in after power disconnect.
  59. /*
  60. uint32_t default_layer_state_set_kb(uint32_t state) {
  61. eeconfig_update_default_layer(state);
  62. return state;
  63. }
  64. */
  65. void tap_dance_df_bepo_layers_switch (qk_tap_dance_state_t *state, void *user_data) {
  66. switch(state->count){
  67. case 1:
  68. switch_default_layer(_DVORAK_BP);
  69. break;
  70. case 2:
  71. switch_default_layer(_BEPO);
  72. break;
  73. case 3:
  74. layer_invert(_LAYERS);
  75. break;
  76. default:
  77. break;
  78. }
  79. reset_tap_dance(state);
  80. }
  81. void tap_dance_layer_switch (qk_tap_dance_state_t *state, void *user_data) {
  82. switch(state->count){
  83. case 1:
  84. if(on_qwerty())
  85. layer_invert(_SYMB);
  86. else
  87. layer_invert(_SYMB_BP);
  88. break;
  89. case 2:
  90. layer_invert(_NAV);
  91. break;
  92. case 3:
  93. layer_invert(_LAYERS);
  94. break;
  95. case 4:
  96. if(on_qwerty())
  97. layer_invert(_KEYPAD);
  98. else
  99. layer_invert(_KEYPAD_BP);
  100. break;
  101. default:
  102. break;
  103. }
  104. reset_tap_dance(state);
  105. }
  106. void tap_dance_default_layer_switch (qk_tap_dance_state_t *state, void *user_data) {
  107. switch(state->count){
  108. case 1:
  109. switch_default_layer(_DVORAK);
  110. break;
  111. case 2:
  112. switch_default_layer(_DVORAK_BP);
  113. break;
  114. case 3:
  115. switch_default_layer(_BEPO);
  116. break;
  117. default:
  118. break;
  119. }
  120. reset_tap_dance(state);
  121. }
  122. // switch the default layer to another qwerty based layer.
  123. void switch_default_layer_on_qwerty(int count) {
  124. switch(count){
  125. case 1:
  126. switch_default_layer(_DVORAK);
  127. break;
  128. case 2:
  129. switch_default_layer(_QWERTY);
  130. break;
  131. case 3:
  132. switch_default_layer(_COLEMAK);
  133. break;
  134. /* case 4: */
  135. /* switch_default_layer(_WORKMAN); */
  136. /* break; */
  137. /* case 5: */
  138. /* switch_default_layer(_NORMAN); */
  139. /* break; */
  140. default:
  141. switch_default_layer(_DVORAK);
  142. break;
  143. }
  144. }
  145. // switch the default layer to another bepo based layer.
  146. void switch_default_layer_on_bepo(int count) {
  147. switch(count){
  148. case 1:
  149. switch_default_layer(_DVORAK_BP);
  150. break;
  151. case 2:
  152. switch_default_layer(_BEPO);
  153. break;
  154. default:
  155. switch_default_layer(_DVORAK_BP);
  156. break;
  157. }
  158. }
  159. // tap to change the default layer. Distinguishes between layers that are based on
  160. // a qwerty software keyboard and a bepo software keyboard.
  161. // if shifted, choose layers based on the other software keyboard, otherwise choose only
  162. // layers that work on the current software keyboard.
  163. void tap_dance_default_os_layer_switch (qk_tap_dance_state_t *state, void *user_data) {
  164. //uint8_t shifted = (get_mods() & MOD_BIT(KC_LSFT|KC_RSFT));
  165. bool shifted = ( keyboard_report->mods & (MOD_BIT(KC_LSFT)|MOD_BIT(KC_RSFT)) );
  166. int qwerty = on_qwerty();
  167. // shifted, choose between layers on the other software keyboard
  168. if(shifted){
  169. if (qwerty)
  170. switch_default_layer_on_bepo(state->count);
  171. else
  172. switch_default_layer_on_qwerty(state->count);
  173. // not shifted, choose between layers on the same software keyboard
  174. } else {
  175. if (qwerty)
  176. switch_default_layer_on_qwerty(state->count);
  177. else
  178. switch_default_layer_on_bepo(state->count);
  179. }
  180. reset_tap_dance(state);
  181. }
  182. /* Return an integer that corresponds to what kind of tap dance should be executed.
  183. *
  184. * How to figure out tap dance state: interrupted and pressed.
  185. *
  186. * Interrupted: If the state of a dance dance is "interrupted", that means that another key has been hit
  187. * under the tapping term. This is typically indicitive that you are trying to "tap" the key.
  188. *
  189. * Pressed: Whether or not the key is still being pressed. If this value is true, that means the tapping term
  190. * has ended, but the key is still being pressed down. This generally means the key is being "held".
  191. *
  192. * One thing that is currenlty not possible with qmk software in regards to tap dance is to mimic the "permissive hold"
  193. * feature. In general, advanced tap dances do not work well if they are used with commonly typed letters.
  194. * For example "A". Tap dances are best used on non-letter keys that are not hit while typing letters.
  195. *
  196. * Good places to put an advanced tap dance:
  197. * z,q,x,j,k,v,b, any function key, home/end, comma, semi-colon
  198. *
  199. * Criteria for "good placement" of a tap dance key:
  200. * Not a key that is hit frequently in a sentence
  201. * Not a key that is used frequently to double tap, for example 'tab' is often double tapped in a terminal, or
  202. * in a web form. So 'tab' would be a poor choice for a tap dance.
  203. * Letters used in common words as a double. For example 'p' in 'pepper'. If a tap dance function existed on the
  204. * letter 'p', the word 'pepper' would be quite frustating to type.
  205. *
  206. * For the third point, there does exist the 'DOUBLE_SINGLE_TAP', however this is not fully tested
  207. *
  208. */
  209. int cur_dance (qk_tap_dance_state_t *state) {
  210. if (state->count == 1) {
  211. if (state->interrupted || !state->pressed) return SINGLE_TAP;
  212. //key has not been interrupted, but they key is still held. Means you want to send a 'HOLD'.
  213. else return SINGLE_HOLD;
  214. }
  215. else if (state->count == 2) {
  216. /*
  217. * DOUBLE_SINGLE_TAP is to distinguish between typing "pepper", and actually wanting a double tap
  218. * action when hitting 'pp'. Suggested use case for this return value is when you want to send two
  219. * keystrokes of the key, and not the 'double tap' action/macro.
  220. */
  221. if (state->interrupted) return DOUBLE_SINGLE_TAP;
  222. else if (state->pressed) return DOUBLE_HOLD;
  223. else return DOUBLE_TAP;
  224. }
  225. //Assumes no one is trying to type the same letter three times (at least not quickly).
  226. //If your tap dance key is 'KC_W', and you want to type "www." quickly - then you will need to add
  227. //an exception here to return a 'TRIPLE_SINGLE_TAP', and define that enum just like 'DOUBLE_SINGLE_TAP'
  228. if (state->count == 3) {
  229. if (state->interrupted || !state->pressed) return TRIPLE_TAP;
  230. else return TRIPLE_HOLD;
  231. }
  232. else return 8; //magic number. At some point this method will expand to work for more presses
  233. }
  234. //Tap Dance Definitions
  235. qk_tap_dance_action_t tap_dance_actions[] = {
  236. //Tap once for Esc, twice for Caps Lock
  237. [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS),
  238. [TD_TAB_BKTAB] = ACTION_TAP_DANCE_DOUBLE(KC_TAB, LSFT(KC_TAB)),
  239. [TD_RIGHT_TAB] = ACTION_TAP_DANCE_DOUBLE(KC_RIGHT, KC_TAB),
  240. [TD_LEFT_BACKTAB] = ACTION_TAP_DANCE_DOUBLE(KC_LEFT, LSFT(KC_TAB)),
  241. [TD_UP_HOME] = ACTION_TAP_DANCE_DOUBLE(KC_UP, KC_HOME),
  242. [TD_DOWN_END] = ACTION_TAP_DANCE_DOUBLE(KC_DOWN, KC_END),
  243. [TD_MDIA_SYMB] = ACTION_TAP_DANCE_FN(tap_dance_layer_switch),
  244. [TD_DVORAK_BEPO] = ACTION_TAP_DANCE_FN(tap_dance_df_bepo_layers_switch),
  245. [TD_DEF_LAYER_SW] = ACTION_TAP_DANCE_FN(tap_dance_default_layer_switch),
  246. [TD_DEF_OS_LAYER_SW] = ACTION_TAP_DANCE_FN(tap_dance_default_os_layer_switch),
  247. [TD_HOME_END] = ACTION_TAP_DANCE_DOUBLE(KC_HOME, KC_END),
  248. [TD_MOUSE_BTNS] = ACTION_TAP_DANCE_FN(tap_dance_mouse_btns)
  249. };
  250. #endif