qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

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