diff --git a/src/KeyboardioFirmware.cpp b/src/KeyboardioFirmware.cpp index fb942301..44fb8e6d 100644 --- a/src/KeyboardioFirmware.cpp +++ b/src/KeyboardioFirmware.cpp @@ -14,8 +14,8 @@ Keyboardio_::setup(const byte keymap_count) { KeyboardHardware.setup(); LEDControl.setup(); - event_handler_hook_add (NULL); - loop_hook_add (NULL); + event_handler_hook_use (NULL); + loop_hook_use (NULL); Layer.defaultLayer (Storage.load_primary_keymap (keymap_count)); } diff --git a/src/hooks.cpp b/src/hooks.cpp index ed638e76..c4fa9a08 100644 --- a/src/hooks.cpp +++ b/src/hooks.cpp @@ -11,10 +11,24 @@ event_handler_hook_replace (custom_handler_t oldHook, custom_handler_t newHook) } void -event_handler_hook_add (custom_handler_t hook) { +event_handler_hook_append (custom_handler_t hook) { event_handler_hook_replace ((custom_handler_t)NULL, hook); } +void +event_handler_hook_use (custom_handler_t hook) { + for (byte i = 0; i < HOOK_MAX; i++) { + if (eventHandlers[i] == hook) + return; + } + event_handler_hook_append (hook); +} + +void +event_handler_hook_add (custom_handler_t hook) { + event_handler_hook_use (hook); +} + void loop_hook_replace (custom_loop_t oldHook, custom_loop_t newHook) { for (byte i = 0; i < HOOK_MAX; i++) { @@ -26,6 +40,20 @@ loop_hook_replace (custom_loop_t oldHook, custom_loop_t newHook) { } void -loop_hook_add (custom_loop_t hook) { +loop_hook_append (custom_loop_t hook) { loop_hook_replace ((custom_loop_t)NULL, hook); } + +void +loop_hook_use (custom_loop_t hook) { + for (byte i = 0; i < HOOK_MAX; i++) { + if (loopHooks[i] == hook) + return; + } + loop_hook_append (hook); +} + +void +loop_hook_add (custom_loop_t hook) { + loop_hook_use (hook); +} diff --git a/src/hooks.h b/src/hooks.h index 615156da..b8084092 100644 --- a/src/hooks.h +++ b/src/hooks.h @@ -8,11 +8,33 @@ typedef Key (*custom_handler_t)(Key mappedKey, byte row, byte col, uint8_t keyState); extern custom_handler_t eventHandlers[HOOK_MAX]; -void event_handler_hook_add (custom_handler_t hook); +/* + * In most cases, one only wants a single copy of a hook. On the other hand, + * plugins that depend on other plugins, may want to make it easier for the + * end-user to use the plugin, and call the setup function of the dependent + * plugins too. In case the end-user calls the same setup function, we'd end up + * with hooks registered multiple times. + * + * To avoid this, protection against double-registration has been introduced. + * The `event_handler_hook_use` and `loop_hook_use` functions will only allow + * one copy of the hook. The `event_handler_hook_append` and `loop_hook_append` + * functions will, on the other hand, just append the hooks, and not care about + * protection. + * + * The `event_handler_hook_add` and `loop_hook_add` functions are deprecated, + * but for the time being, they are aliases to the `_use` functions, until all + * plugins have been updated, and the aliases can be removed. + */ + +void event_handler_hook_use (custom_handler_t hook); +void event_handler_hook_append (custom_handler_t hook); +void event_handler_hook_add (custom_handler_t hook) __attribute__((deprecated)); void event_handler_hook_replace (custom_handler_t oldHook, custom_handler_t newHook); typedef void (*custom_loop_t)(bool postClear); extern custom_loop_t loopHooks[HOOK_MAX]; -void loop_hook_add (custom_loop_t hook); +void loop_hook_use (custom_loop_t hook); +void loop_hook_append (custom_loop_t hook); +void loop_hook_add (custom_loop_t hook) __attribute__((deprecated)); void loop_hook_replace (custom_loop_t oldHook, custom_loop_t newHook);