summaryrefslogtreecommitdiff
path: root/quantum/process_keycode
diff options
context:
space:
mode:
authorPascal Getreuer <50221757+getreuer@users.noreply.github.com>2023-05-20 05:35:06 -0700
committerGitHub <noreply@github.com>2023-05-20 22:35:06 +1000
commit3993b15f054265071730cdb450f43457dcf4c64a (patch)
tree61c5b980ed14428bae3c0278c27937dbb5d33627 /quantum/process_keycode
parente1766df185869d8a591228d37f3f7b6d5b4049b4 (diff)
[Core] Add Repeat Key ("repeat last key") as a core feature. (#19700)
Co-authored-by: casuanoob <96005765+casuanoob@users.noreply.github.com> Co-authored-by: Sergey Vlasov <sigprof@gmail.com>
Diffstat (limited to 'quantum/process_keycode')
-rw-r--r--quantum/process_keycode/process_repeat_key.c109
-rw-r--r--quantum/process_keycode/process_repeat_key.h62
2 files changed, 171 insertions, 0 deletions
diff --git a/quantum/process_keycode/process_repeat_key.c b/quantum/process_keycode/process_repeat_key.c
new file mode 100644
index 0000000000..f819aa226e
--- /dev/null
+++ b/quantum/process_keycode/process_repeat_key.c
@@ -0,0 +1,109 @@
+// Copyright 2022-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.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "process_repeat_key.h"
+
+// Default implementation of remember_last_key_user().
+__attribute__((weak)) bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, uint8_t* remembered_mods) {
+ return true;
+}
+
+static bool remember_last_key(uint16_t keycode, keyrecord_t* record, uint8_t* remembered_mods) {
+ switch (keycode) {
+ // Ignore MO, TO, TG, TT, and TL layer switch keys.
+ case QK_MOMENTARY ... QK_MOMENTARY_MAX:
+ case QK_TO ... QK_TO_MAX:
+ case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX:
+ case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
+ // Ignore mod keys.
+ case KC_LCTL ... KC_RGUI:
+ case KC_HYPR:
+ case KC_MEH:
+#ifndef NO_ACTION_ONESHOT // Ignore one-shot keys.
+ case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX:
+ case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
+#endif // NO_ACTION_ONESHOT
+#ifdef TRI_LAYER_ENABLE // Ignore Tri Layer keys.
+ case QK_TRI_LAYER_LOWER:
+ case QK_TRI_LAYER_UPPER:
+#endif // TRI_LAYER_ENABLE
+ return false;
+
+ // Ignore hold events on tap-hold keys.
+#ifndef NO_ACTION_TAPPING
+ case QK_MOD_TAP ... QK_MOD_TAP_MAX:
+# ifndef NO_ACTION_LAYER
+ case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
+# endif // NO_ACTION_LAYER
+ if (record->tap.count == 0) {
+ return false;
+ }
+ break;
+#endif // NO_ACTION_TAPPING
+
+#ifdef SWAP_HANDS_ENABLE
+ case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
+ if (IS_SWAP_HANDS_KEYCODE(keycode) || record->tap.count == 0) {
+ return false;
+ }
+ break;
+#endif // SWAP_HANDS_ENABLE
+
+ case QK_REPEAT_KEY:
+#ifndef NO_ALT_REPEAT_KEY
+ case QK_ALT_REPEAT_KEY:
+#endif // NO_ALT_REPEAT_KEY
+ return false;
+ }
+
+ return remember_last_key_user(keycode, record, remembered_mods);
+}
+
+bool process_last_key(uint16_t keycode, keyrecord_t* record) {
+ if (get_repeat_key_count()) {
+ return true;
+ }
+
+ if (record->event.pressed) {
+ uint8_t remembered_mods = get_mods() | get_weak_mods();
+#ifndef NO_ACTION_ONESHOT
+ remembered_mods |= get_oneshot_mods();
+#endif // NO_ACTION_ONESHOT
+
+ if (remember_last_key(keycode, record, &remembered_mods)) {
+ set_last_record(keycode, record);
+ set_last_mods(remembered_mods);
+ }
+ }
+
+ return true;
+}
+
+bool process_repeat_key(uint16_t keycode, keyrecord_t* record) {
+ if (get_repeat_key_count()) {
+ return true;
+ }
+
+ if (keycode == QK_REPEAT_KEY) {
+ repeat_key_invoke(&record->event);
+ return false;
+#ifndef NO_ALT_REPEAT_KEY
+ } else if (keycode == QK_ALT_REPEAT_KEY) {
+ alt_repeat_key_invoke(&record->event);
+ return false;
+#endif // NO_ALT_REPEAT_KEY
+ }
+
+ return true;
+}
diff --git a/quantum/process_keycode/process_repeat_key.h b/quantum/process_keycode/process_repeat_key.h
new file mode 100644
index 0000000000..eddc50f254
--- /dev/null
+++ b/quantum/process_keycode/process_repeat_key.h
@@ -0,0 +1,62 @@
+// Copyright 2022-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.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include "quantum.h"
+
+/**
+ * @brief Process handler for remembering the last key.
+ *
+ * @param keycode Keycode registered by matrix press, per keymap
+ * @param record keyrecord_t structure
+ * @return true Continue processing keycodes, and send to host
+ * @return false Stop processing keycodes, and don't send to host
+ */
+bool process_last_key(uint16_t keycode, keyrecord_t* record);
+
+/**
+ * @brief Optional callback defining which keys are remembered.
+ *
+ * @param keycode Keycode that was just pressed
+ * @param record keyrecord_t structure
+ * @param remembered_mods Mods that will be remembered with this key
+ * @return true Key is remembered
+ * @return false Key is ignored
+ *
+ * Modifier and layer switch keys are always ignored. For all other keys, this
+ * callback is called on every key press. Returning true means that the key is
+ * remembered, false means it is ignored. By default, all non-modifier,
+ * non-layer switch keys are remembered.
+ *
+ * The `remembered_mods` arg represents the mods that will be remembered with
+ * this key. It can be modified to forget certain mods, for instance to forget
+ * capitalization when repeating shifted letters:
+ *
+ * // Forget Shift on letter keys.
+ * if (KC_A <= keycode && keycode <= KC_Z && (*remembered_mods & ~MOD_MASK_SHIFT) == 0) {
+ * *remembered_mods = 0;
+ * }
+ */
+bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, uint8_t* remembered_mods);
+
+/**
+ * @brief Process handler for Repeat Key feature.
+ *
+ * @param keycode Keycode registered by matrix press, per keymap
+ * @param record keyrecord_t structure
+ * @return true Continue processing keycodes, and send to host
+ * @return false Stop processing keycodes, and don't send to host
+ */
+bool process_repeat_key(uint16_t keycode, keyrecord_t* record);