process_key_override.h (8573B)
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 <stdint.h> 22 #include "action.h" 23 #include "action_layer.h" 24 25 /** 26 * Key overrides allow you to send a different key-modifier combination or perform a custom action when a certain modifier-key combination is pressed. 27 * 28 * 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. 29 * 30 * See the documentation and examples here: https://docs.qmk.fm/#/feature_key_overrides 31 */ 32 33 /** Bitfield with various options controlling the behavior of a key override. */ 34 typedef enum { 35 /** Allow activating when the trigger key is pressed down. */ 36 ko_option_activation_trigger_down = (1 << 0), 37 /** Allow activating when a necessary modifier is pressed down. */ 38 ko_option_activation_required_mod_down = (1 << 1), 39 /** Allow activating when a negative modifier is released. */ 40 ko_option_activation_negative_mod_up = (1 << 2), 41 42 ko_options_all_activations = ko_option_activation_negative_mod_up | ko_option_activation_required_mod_down | ko_option_activation_trigger_down, 43 44 /** 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). */ 45 ko_option_one_mod = (1 << 3), 46 47 /** If set, the trigger key will never be registered again after the override is deactivated. */ 48 ko_option_no_reregister_trigger = (1 << 4), 49 50 /** If set, the override will not deactivate when another key is pressed down. Use only if you really know you need this. */ 51 ko_option_no_unregister_on_other_key_down = (1 << 5), 52 53 /** The default options used by the ko_make_xxx functions. */ 54 ko_options_default = ko_options_all_activations, 55 } ko_option_t; 56 57 /** Defines a single key override */ 58 typedef struct key_override_t { 59 // 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. 60 uint16_t trigger; 61 62 // 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. 63 uint8_t trigger_mods; 64 65 // This is a BITMASK (!), defining which layers this override applies to. To use this override on layer i set the ith bit (1 << i). 66 layer_state_t layers; 67 68 // 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. 69 uint8_t negative_mod_mask; 70 71 // 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. 72 uint8_t suppressed_mods; 73 74 // 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. 75 uint16_t replacement; 76 77 // Options controlling the behavior of the override, such as what actions are allowed to activate the override. 78 ko_option_t options; 79 80 // 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. 81 bool (*custom_action)(bool activated, void *context); 82 83 // A context that will be passed to the custom action function. 84 void *context; 85 86 // If this points to false this override will not be used. Set to NULL to always have this override enabled. 87 bool *enabled; 88 } key_override_t; 89 90 /** Turns key overrides on */ 91 void key_override_on(void); 92 93 /** Turns key overrides off */ 94 void key_override_off(void); 95 96 /** Toggles key overrides on */ 97 void key_override_toggle(void); 98 99 /** Returns whether key overrides are enabled */ 100 bool key_override_is_enabled(void); 101 102 /** Handling of key overrides and its implemented keycodes */ 103 bool process_key_override(const uint16_t keycode, const keyrecord_t *const record); 104 105 /** Perform any deferred keys */ 106 void key_override_task(void); 107 108 /** 109 * 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. 110 */ 111 112 // clang-format off 113 114 /** 115 * Convenience initializer to create a basic key override. Activates the override on all layers. 116 */ 117 #define ko_make_basic(trigger_mods, trigger_key, replacement_key) \ 118 ko_make_with_layers(trigger_mods, trigger_key, replacement_key, ~0) 119 120 /** 121 * 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. 122 */ 123 #define ko_make_with_layers(trigger_mods, trigger_key, replacement_key, layers) \ 124 ko_make_with_layers_and_negmods(trigger_mods, trigger_key, replacement_key, layers, 0) 125 126 /** 127 * 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. 128 */ 129 #define ko_make_with_layers_and_negmods(trigger_mods, trigger_key, replacement_key, layers, negative_mask) \ 130 ko_make_with_layers_negmods_and_options(trigger_mods, trigger_key, replacement_key, layers, negative_mask, ko_options_default) 131 132 /** 133 * 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. 134 */ 135 #define ko_make_with_layers_negmods_and_options(trigger_mods_, trigger_key, replacement_key, layer_mask, negative_mask, options_) \ 136 ((const key_override_t){ \ 137 .trigger_mods = (trigger_mods_), \ 138 .layers = (layer_mask), \ 139 .suppressed_mods = (trigger_mods_), \ 140 .options = (options_), \ 141 .negative_mod_mask = (negative_mask), \ 142 .custom_action = NULL, \ 143 .context = NULL, \ 144 .trigger = (trigger_key), \ 145 .replacement = (replacement_key), \ 146 .enabled = NULL \ 147 }) 148 149 // clang-format on