tapdance.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /**
  2. * Tap Dance config and functions
  3. **/
  4. /* Copyright 2018 Corey Kump
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. enum {
  20. SINGLE_TAP = 1,
  21. SINGLE_HOLD = 2,
  22. DOUBLE_TAP = 3,
  23. DOUBLE_SINGLE_TAP = 4,
  24. UNKNOWN_TAPS = 5
  25. };
  26. typedef struct {
  27. bool is_press_action;
  28. int state;
  29. } tap;
  30. int cur_dance (qk_tap_dance_state_t *state) {
  31. if (state->count == 1) {
  32. if (state->interrupted || !state->pressed) {
  33. return SINGLE_TAP;
  34. } else {
  35. return SINGLE_HOLD;
  36. }
  37. }
  38. if (state->count == 2) {
  39. if (state->interrupted) {
  40. return DOUBLE_SINGLE_TAP;
  41. } else if (!state->pressed) {
  42. return DOUBLE_TAP;
  43. }
  44. }
  45. return UNKNOWN_TAPS;
  46. }
  47. /**
  48. * quote
  49. **/
  50. static tap quote_state = {
  51. .is_press_action = true,
  52. .state = 0
  53. };
  54. void quote_finished(qk_tap_dance_state_t *state, void *user_data) {
  55. quote_state.state = cur_dance(state);
  56. switch(quote_state.state) {
  57. case SINGLE_TAP: register_code(KC_QUOT); break;
  58. case SINGLE_HOLD: layer_on(_LEANDOWN); break;
  59. case DOUBLE_TAP: register_code(KC_MINS); break;
  60. case DOUBLE_SINGLE_TAP: register_code(KC_QUOT); unregister_code(KC_QUOT); register_code(KC_QUOT); break;
  61. }
  62. }
  63. void quote_reset(qk_tap_dance_state_t *state, void *user_data) {
  64. switch(quote_state.state) {
  65. case SINGLE_TAP: unregister_code(KC_QUOT); break;
  66. case SINGLE_HOLD: layer_off(_LEANDOWN); break;
  67. case DOUBLE_TAP: unregister_code(KC_MINS); break;
  68. case DOUBLE_SINGLE_TAP: unregister_code(KC_QUOT); break;
  69. }
  70. quote_state.state = 0;
  71. }
  72. /**
  73. * ralt / left bracket / left curly brace
  74. **/
  75. static tap ralt_state = {
  76. .is_press_action = true,
  77. .state = 0
  78. };
  79. void ralt_finished(qk_tap_dance_state_t *state, void *user_data) {
  80. ralt_state.state = cur_dance(state);
  81. switch(ralt_state.state) {
  82. case SINGLE_TAP: register_code(KC_LBRC); break;
  83. case SINGLE_HOLD: register_code(KC_RALT); break;
  84. case DOUBLE_TAP: register_code(KC_LSFT); register_code(KC_LBRC); break;
  85. // fallback to alt because it's the primary purpose of this key
  86. case DOUBLE_SINGLE_TAP: register_code(KC_RALT); break;
  87. }
  88. }
  89. void ralt_reset(qk_tap_dance_state_t *state, void *user_data) {
  90. switch(ralt_state.state) {
  91. case SINGLE_TAP: unregister_code(KC_LBRC); break;
  92. case SINGLE_HOLD: unregister_code(KC_RALT); break;
  93. case DOUBLE_TAP: unregister_code(KC_LBRC); unregister_code(KC_LSFT); break;
  94. case DOUBLE_SINGLE_TAP: unregister_code(KC_RALT); break;
  95. }
  96. ralt_state.state = 0;
  97. }
  98. /**
  99. * rgui / right bracket / right curly brace
  100. **/
  101. static tap rgui_state = {
  102. .is_press_action = true,
  103. .state = 0
  104. };
  105. void rgui_finished(qk_tap_dance_state_t *state, void *user_data) {
  106. rgui_state.state = cur_dance(state);
  107. switch(rgui_state.state) {
  108. case SINGLE_TAP: register_code(KC_RBRC); break;
  109. case SINGLE_HOLD: register_code(KC_RGUI); break;
  110. case DOUBLE_TAP: register_code(KC_LSFT); register_code(KC_RBRC); break;
  111. // fallback to alt because it's the primary purpose of this key
  112. case DOUBLE_SINGLE_TAP: register_code(KC_RGUI); break;
  113. }
  114. }
  115. void rgui_reset(qk_tap_dance_state_t *state, void *user_data) {
  116. switch(rgui_state.state) {
  117. case SINGLE_TAP: unregister_code(KC_RBRC); break;
  118. case SINGLE_HOLD: unregister_code(KC_RGUI); break;
  119. case DOUBLE_TAP: unregister_code(KC_RBRC); unregister_code(KC_LSFT); break;
  120. case DOUBLE_SINGLE_TAP: unregister_code(KC_RGUI); break;
  121. }
  122. rgui_state.state = 0;
  123. }
  124. /**
  125. * Define the available tap dance keys
  126. **/
  127. enum {
  128. TD_ALT_SHIFT = 0,
  129. TD_LQUT_MINS,
  130. TD_QUOT_LEAN_MINS,
  131. TD_LBRC_RALT_LCBR,
  132. TD_RBRC_RGUI_RCBR
  133. };
  134. qk_tap_dance_action_t tap_dance_actions[] = {
  135. // Tap once for Alt, twice for Shift
  136. [TD_ALT_SHIFT] = ACTION_TAP_DANCE_DOUBLE(KC_RALT, KC_RSFT),
  137. [TD_QUOT_LEAN_MINS] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, quote_finished, quote_reset),
  138. [TD_LBRC_RALT_LCBR] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, ralt_finished, ralt_reset),
  139. [TD_RBRC_RGUI_RCBR] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, rgui_finished, rgui_reset)
  140. };