diff options
Diffstat (limited to 'quantum/process_keycode/process_key_override.h')
| -rw-r--r-- | quantum/process_keycode/process_key_override.h | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/quantum/process_keycode/process_key_override.h b/quantum/process_keycode/process_key_override.h new file mode 100644 index 000000000..9ba59e4e9 --- /dev/null +++ b/quantum/process_keycode/process_key_override.h | |||
| @@ -0,0 +1,147 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2021 Jonas Gessner | ||
| 3 | * | ||
| 4 | * This program is free software: you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation, either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #pragma once | ||
| 19 | |||
| 20 | #include <stdbool.h> | ||
| 21 | #include <stddef.h> | ||
| 22 | #include <stdint.h> | ||
| 23 | |||
| 24 | #include "action_layer.h" | ||
| 25 | |||
| 26 | /** | ||
| 27 | * Key overrides allow you to send a different key-modifier combination or perform a custom action when a certain modifier-key combination is pressed. | ||
| 28 | * | ||
| 29 | * For example, you may configure a key override to send the delete key when shift + backspace are pressed together, or that your volume keys become screen brightness keys when holding ctrl. The possibilities are quite vast and the documentation contains a few examples for inspiration. | ||
| 30 | * | ||
| 31 | * See the documentation and examples here: https://docs.qmk.fm/#/feature_key_overrides | ||
| 32 | */ | ||
| 33 | |||
| 34 | /** Bitfield with various options controlling the behavior of a key override. */ | ||
| 35 | typedef enum { | ||
| 36 | /** Allow activating when the trigger key is pressed down. */ | ||
| 37 | ko_option_activation_trigger_down = (1 << 0), | ||
| 38 | /** Allow activating when a necessary modifier is pressed down. */ | ||
| 39 | ko_option_activation_required_mod_down = (1 << 1), | ||
| 40 | /** Allow activating when a negative modifier is released. */ | ||
| 41 | ko_option_activation_negative_mod_up = (1 << 2), | ||
| 42 | |||
| 43 | ko_options_all_activations = ko_option_activation_negative_mod_up | ko_option_activation_required_mod_down | ko_option_activation_trigger_down, | ||
| 44 | |||
| 45 | /** If set, any of the modifiers in trigger_mods will be enough to activate the override (logical OR of modifiers). If not set, all the modifiers in trigger_mods have to be pressed (logical AND of modifiers). */ | ||
| 46 | ko_option_one_mod = (1 << 3), | ||
| 47 | |||
| 48 | /** If set, the trigger key will never be registered again after the override is deactivated. */ | ||
| 49 | ko_option_no_reregister_trigger = (1 << 4), | ||
| 50 | |||
| 51 | /** If set, the override will not deactivate when another key is pressed down. Use only if you really know you need this. */ | ||
| 52 | ko_option_no_unregister_on_other_key_down = (1 << 5), | ||
| 53 | |||
| 54 | /** The default options used by the ko_make_xxx functions. */ | ||
| 55 | ko_options_default = ko_options_all_activations, | ||
| 56 | } ko_option_t; | ||
| 57 | |||
| 58 | /** Defines a single key override */ | ||
| 59 | typedef struct { | ||
| 60 | // The non-modifier keycode that triggers the override. This keycode, and the necessary modifiers (trigger_mods) must be pressed to activate this override. Set this to the keycode of the key that should activate the override. Set to KC_NO to require only the necessary modifiers to be pressed and no non-modifier. | ||
| 61 | uint16_t trigger; | ||
| 62 | |||
| 63 | // Which mods need to be down for activation. If both sides of a modifier are set (e.g. left ctrl and right ctrl) then only one is required to be pressed (e.g. left ctrl suffices). Use the MOD_MASK_XXX and MOD_BIT() macros for this. | ||
| 64 | uint8_t trigger_mods; | ||
| 65 | |||
| 66 | // This is a BITMASK (!), defining which layers this override applies to. To use this override on layer i set the ith bit (1 << i). | ||
| 67 | layer_state_t layers; | ||
| 68 | |||
| 69 | // Which modifiers cannot be down. It must hold that (active_mods & negative_mod_mask) == 0, otherwise the key override will not be activated. An active override will be deactivated once this is no longer true. | ||
| 70 | uint8_t negative_mod_mask; | ||
| 71 | |||
| 72 | // Modifiers to 'suppress' while the override is active. To suppress a modifier means that even though the modifier key is held down, the host OS sees the modifier as not pressed. Can be used to suppress the trigger modifiers, as a trivial example. | ||
| 73 | uint8_t suppressed_mods; | ||
| 74 | |||
| 75 | // The complex keycode to send as replacement when this override is triggered. This can be a simple keycode, a key-modifier combination (e.g. C(KC_A)), or KC_NO (to register no replacement keycode). Use in combination with suppressed_mods to get the correct modifiers to be sent. | ||
| 76 | uint16_t replacement; | ||
| 77 | |||
| 78 | // Options controlling the behavior of the override, such as what actions are allowed to activate the override. | ||
| 79 | ko_option_t options; | ||
| 80 | |||
| 81 | // If not NULL, this function will be called right before the replacement key is registered, along with the provided context and a flag indicating whether the override was activated or deactivated. This function allows you to run some custom actions for specific key overrides. If you return `false`, the replacement key is not registered/unregistered as it would normally. Return `true` to register and unregister the override normally. | ||
| 82 | bool (*custom_action)(bool activated, void *context); | ||
| 83 | |||
| 84 | // A context that will be passed to the custom action function. | ||
| 85 | void *context; | ||
| 86 | |||
| 87 | // If this points to false this override will not be used. Set to NULL to always have this override enabled. | ||
| 88 | bool *enabled; | ||
| 89 | } key_override_t; | ||
| 90 | |||
| 91 | /** Define this as a null-terminated array of pointers to key overrides. These key overrides will be used by qmk. */ | ||
| 92 | extern const key_override_t **key_overrides; | ||
| 93 | |||
| 94 | /** Turns key overrides on */ | ||
| 95 | extern void key_override_on(void); | ||
| 96 | |||
| 97 | /** Turns key overrides off */ | ||
| 98 | extern void key_override_off(void); | ||
| 99 | |||
| 100 | /** Toggles key overrides on */ | ||
| 101 | extern void key_override_toggle(void); | ||
| 102 | |||
| 103 | /** Returns whether key overrides are enabled */ | ||
| 104 | extern bool key_override_is_enabled(void); | ||
| 105 | |||
| 106 | /** | ||
| 107 | * Preferrably use these macros to create key overrides. They fix many of the options to a standard setting that should satisfy most basic use-cases. Only directly create a key_override_t struct when you really need to. | ||
| 108 | */ | ||
| 109 | |||
| 110 | // clang-format off | ||
| 111 | |||
| 112 | /** | ||
| 113 | * Convenience initializer to create a basic key override. Activates the override on all layers. | ||
| 114 | */ | ||
| 115 | #define ko_make_basic(trigger_mods, trigger_key, replacement_key) \ | ||
| 116 | ko_make_with_layers(trigger_mods, trigger_key, replacement_key, ~0) | ||
| 117 | |||
| 118 | /** | ||
| 119 | * Convenience initializer to create a basic key override. Provide a bitmap (of type layer_state_t) with the bits set for each layer on which the override should activate. | ||
| 120 | */ | ||
| 121 | #define ko_make_with_layers(trigger_mods, trigger_key, replacement_key, layers) \ | ||
| 122 | ko_make_with_layers_and_negmods(trigger_mods, trigger_key, replacement_key, layers, 0) | ||
| 123 | |||
| 124 | /** | ||
| 125 | * Convenience initializer to create a basic key override. Provide a bitmap with the bits set for each layer on which the override should activate. Also provide a negative modifier mask, that is used to define which modifiers may not be pressed. | ||
| 126 | */ | ||
| 127 | #define ko_make_with_layers_and_negmods(trigger_mods, trigger_key, replacement_key, layers, negative_mask) \ | ||
| 128 | ko_make_with_layers_negmods_and_options(trigger_mods, trigger_key, replacement_key, layers, negative_mask, ko_options_default) | ||
| 129 | |||
| 130 | /** | ||
| 131 | * Convenience initializer to create a basic key override. Provide a bitmap with the bits set for each layer on which the override should activate. Also provide a negative modifier mask, that is used to define which modifiers may not be pressed. Provide options for additional control of the behavior of the override. | ||
| 132 | */ | ||
| 133 | #define ko_make_with_layers_negmods_and_options(trigger_mods_, trigger_key, replacement_key, layer_mask, negative_mask, options_) \ | ||
| 134 | ((const key_override_t){ \ | ||
| 135 | .trigger_mods = (trigger_mods_), \ | ||
| 136 | .layers = (layer_mask), \ | ||
| 137 | .suppressed_mods = (trigger_mods_), \ | ||
| 138 | .options = (options_), \ | ||
| 139 | .negative_mod_mask = (negative_mask), \ | ||
| 140 | .custom_action = NULL, \ | ||
| 141 | .context = NULL, \ | ||
| 142 | .trigger = (trigger_key), \ | ||
| 143 | .replacement = (replacement_key), \ | ||
| 144 | .enabled = NULL \ | ||
| 145 | }) | ||
| 146 | |||
| 147 | // clang-format on | ||
