You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
7.5 KiB

  1. /* Copyright 2021 @daliusd
  2. *
  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. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "print.h"
  17. #include "oneshot.h"
  18. void update_oneshot(
  19. oneshot_state *state,
  20. uint16_t mod,
  21. uint16_t trigger,
  22. uint16_t keycode,
  23. keyrecord_t *record
  24. ) {
  25. if (keycode == trigger) {
  26. if (record->event.pressed) {
  27. // Trigger keydown
  28. if (*state == os_up_unqueued) {
  29. register_code(mod);
  30. }
  31. *state = os_down_unused;
  32. dprintf("trigger down (on?), mod: %d, ? -> os_down_unused\n", mod);
  33. } else {
  34. // Trigger keyup
  35. switch (*state) {
  36. case os_down_unused:
  37. // If we didn't use the mod while trigger was held, queue it.
  38. *state = os_up_queued;
  39. dprintf("trigger up, mod: %d, os_down_unused -> os_up_queued\n", mod);
  40. break;
  41. case os_down_used:
  42. // If we did use the mod while trigger was held, unregister it.
  43. *state = os_up_unqueued;
  44. unregister_code(mod);
  45. dprintf("trigger up (off), mod: %d, os_down_used -> os_up_unqueued\n", mod);
  46. break;
  47. default:
  48. break;
  49. }
  50. }
  51. } else {
  52. if (record->event.pressed) {
  53. if (is_oneshot_cancel_key(keycode) && *state != os_up_unqueued) {
  54. // Cancel oneshot on designated cancel keydown.
  55. *state = os_up_unqueued;
  56. unregister_code(mod);
  57. dprintf("cancel (off), mod: %d, ? -> os_up_unqueued\n", mod);
  58. }
  59. if (!is_oneshot_ignored_key(keycode)) {
  60. switch (*state) {
  61. case os_up_queued:
  62. *state = os_up_queued_used;
  63. dprintf("key up (off), mod: %d, os_up_queued -> os_up_queued_used\n", mod);
  64. break;
  65. case os_up_queued_used:
  66. *state = os_up_unqueued;
  67. unregister_code(mod);
  68. dprintf("key up (off), mod: %d, os_up_queued_used -> os_up_unqueued\n", mod);
  69. break;
  70. default:
  71. break;
  72. }
  73. }
  74. } else {
  75. if (!is_oneshot_ignored_key(keycode)) {
  76. // On non-ignored keyup, consider the oneshot used.
  77. switch (*state) {
  78. case os_down_unused:
  79. *state = os_down_used;
  80. dprintf("key up, mod: %d, os_down_unused -> os_down_used\n", mod);
  81. break;
  82. case os_up_queued:
  83. *state = os_up_unqueued;
  84. unregister_code(mod);
  85. dprintf("key up (off), mod: %d, os_up_queued -> os_up_unqueued\n", mod);
  86. break;
  87. case os_up_queued_used:
  88. *state = os_up_unqueued;
  89. unregister_code(mod);
  90. dprintf("key up (off), mod: %d, os_up_queued_used -> os_up_unqueued\n", mod);
  91. break;
  92. default:
  93. break;
  94. }
  95. }
  96. }
  97. }
  98. }
  99. bool update_oneshot_layer(
  100. oneshot_state *state,
  101. uint16_t layer,
  102. uint16_t trigger,
  103. uint16_t keycode,
  104. keyrecord_t *record
  105. ) {
  106. if (keycode == trigger) {
  107. if (record->event.pressed) {
  108. // Trigger keydown
  109. if (*state == os_up_unqueued) {
  110. layer_on(layer);
  111. }
  112. *state = os_down_unused;
  113. dprintf("trigger down (on?), layer: %d, ? -> os_down_unused\n", layer);
  114. return false;
  115. } else {
  116. // Trigger keyup
  117. switch (*state) {
  118. case os_down_unused:
  119. // If we didn't use the layer while trigger was held, queue it.
  120. *state = os_up_queued;
  121. dprintf("trigger up, layer: %d, os_down_unused -> os_up_queued\n", layer);
  122. return false;
  123. case os_down_used:
  124. // If we did use the layer while trigger was held, turn off it.
  125. *state = os_up_unqueued;
  126. layer_off(layer);
  127. dprintf("trigger up (off), layer: %d, os_down_used -> os_up_unqueued\n", layer);
  128. return false;
  129. default:
  130. break;
  131. }
  132. }
  133. } else {
  134. if (record->event.pressed) {
  135. if (is_oneshot_layer_cancel_key(keycode) && *state != os_up_unqueued) {
  136. // Cancel oneshot layer on designated cancel keydown.
  137. *state = os_up_unqueued;
  138. layer_off(layer);
  139. dprintf("cancel (off), layer: %d, ? -> os_up_unqueued\n", layer);
  140. return false;
  141. }
  142. uint8_t key_layer = read_source_layers_cache(record->event.key);
  143. if (key_layer == layer) {
  144. // On non-ignored keyup, consider the oneshot used.
  145. switch (*state) {
  146. case os_down_unused:
  147. *state = os_down_used;
  148. dprintf("key down, layer: %d, os_down_unused -> os_down_used\n", layer);
  149. return true;
  150. case os_up_queued:
  151. if (is_oneshot_mod_key(keycode)) {
  152. *state = os_up_unqueued;
  153. layer_off(layer);
  154. dprintf("key down, layer: %d, os_up_queued -> os_up_unqueued\n", layer);
  155. return false;
  156. } else {
  157. *state = os_up_queued_used;
  158. dprintf("key down, layer: %d, os_up_queued -> os_up_queued_used\n", layer);
  159. }
  160. return true;
  161. case os_up_queued_used:
  162. *state = os_up_unqueued;
  163. layer_off(layer);
  164. dprintf("key down (off), layer: %d, os_up_queued_used -> os_up_unqueued\n", layer);
  165. return false;
  166. default:
  167. break;
  168. }
  169. }
  170. } else {
  171. // Ignore key ups from other layers
  172. uint8_t key_layer = read_source_layers_cache(record->event.key);
  173. if (key_layer == layer) {
  174. // On non-ignored keyup, consider the oneshot used.
  175. switch (*state) {
  176. case os_up_queued:
  177. *state = os_up_unqueued;
  178. layer_off(layer);
  179. dprintf("key up (off), layer: %d, os_up_queued -> os_up_unqueued\n", layer);
  180. return true;
  181. case os_up_queued_used:
  182. *state = os_up_unqueued;
  183. layer_off(layer);
  184. dprintf("key up (off), layer: %d, os_up_queued_used -> os_up_unqueued\n", layer);
  185. return true;
  186. default:
  187. break;
  188. }
  189. }
  190. }
  191. }
  192. return true;
  193. }