|
|
|
/* Kaleidoscope - Firmware for computer input devices
|
|
|
|
* Copyright (C) 2013-2018 Keyboard.io, Inc.
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU General Public License as published by the Free Software
|
|
|
|
* Foundation, version 3.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
Major redesign of the plugin and hooking interface
With this redesign, we introduce a new way to create plugins, which is easier to
extend with new hook points, provides a better interface, uses less memory, less
program space, and is a tiny bit faster too.
It all begins with `kaleidoscope::Plugin` being the base class, which provides
the hook methods plugins can implement. Plugins should be declared with
`KALEIDOSCOPE_INIT_PLUGINS` instead of `Kaleidoscope.use()`. Behind this macro
is a bit of magic (see the in-code documentation) that allows us to unroll the
hook method calls, avoid vtables, and so on. It creates an override for
`kaleidoscope::Hooks::*` methods, each of which will call the respective methods
of each initialized plugin.
With the new API come new names: all of the methods plugins can implement
received new, more descriptive names that all follow a similar pattern.
The old (dubbed V1) API still remains in place, although deprecated. One can
turn it off by setting the `KALEIDOSCOPE_ENABLE_V1_PLUGIN_API` define to zero,
while compiling the firmware.
This work is based on #276, written by @noseglasses. @obra and @algernon did
some cleaning up and applied a little naming treatment.
Signed-off-by: noseglasses <shinynoseglasses@gmail.com>
Signed-off-by: Jesse Vincent <jesse@keyboard.io>
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
7 years ago
|
|
|
/*
|
|
|
|
* This file contains pre-processor macros, which are not namespaced, the
|
|
|
|
* vast majority of code these macros generate will live under the
|
|
|
|
* kaleidoscope_internal namespace. That is why this header is here.
|
|
|
|
*
|
|
|
|
* The only exception to this is the _KALEIDOSCOPE_INIT_PLUGINS macro, which
|
|
|
|
* also places a few symbols under the kaleidoscope namespace. But that code is
|
|
|
|
* tightly coupled with the other parts, which are in kaleidoscope_internal.
|
|
|
|
*
|
|
|
|
* The reason we use an entirely separate namespace is that
|
|
|
|
* Some plugins' classes are in the kaleidoscope namespace, and the instances
|
|
|
|
* of those classes have the same names as the classes, but in the global
|
|
|
|
* namespace. In these cases, the macros herein would resolve to the classes,
|
|
|
|
* when we want them to resolve to instances. To avoid this, we put the
|
|
|
|
* generated code in an entirely different namespace.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "kaleidoscope/macro_helpers.h"
|
|
|
|
#include "kaleidoscope/plugin.h"
|
Major redesign of the plugin and hooking interface
With this redesign, we introduce a new way to create plugins, which is easier to
extend with new hook points, provides a better interface, uses less memory, less
program space, and is a tiny bit faster too.
It all begins with `kaleidoscope::Plugin` being the base class, which provides
the hook methods plugins can implement. Plugins should be declared with
`KALEIDOSCOPE_INIT_PLUGINS` instead of `Kaleidoscope.use()`. Behind this macro
is a bit of magic (see the in-code documentation) that allows us to unroll the
hook method calls, avoid vtables, and so on. It creates an override for
`kaleidoscope::Hooks::*` methods, each of which will call the respective methods
of each initialized plugin.
With the new API come new names: all of the methods plugins can implement
received new, more descriptive names that all follow a similar pattern.
The old (dubbed V1) API still remains in place, although deprecated. One can
turn it off by setting the `KALEIDOSCOPE_ENABLE_V1_PLUGIN_API` define to zero,
while compiling the firmware.
This work is based on #276, written by @noseglasses. @obra and @algernon did
some cleaning up and applied a little naming treatment.
Signed-off-by: noseglasses <shinynoseglasses@gmail.com>
Signed-off-by: Jesse Vincent <jesse@keyboard.io>
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
7 years ago
|
|
|
#include "kaleidoscope/hooks.h"
|
|
|
|
#include "kaleidoscope_internal/eventhandler_signature_check.h"
|
|
|
|
#include "kaleidoscope/event_handlers.h"
|
Major redesign of the plugin and hooking interface
With this redesign, we introduce a new way to create plugins, which is easier to
extend with new hook points, provides a better interface, uses less memory, less
program space, and is a tiny bit faster too.
It all begins with `kaleidoscope::Plugin` being the base class, which provides
the hook methods plugins can implement. Plugins should be declared with
`KALEIDOSCOPE_INIT_PLUGINS` instead of `Kaleidoscope.use()`. Behind this macro
is a bit of magic (see the in-code documentation) that allows us to unroll the
hook method calls, avoid vtables, and so on. It creates an override for
`kaleidoscope::Hooks::*` methods, each of which will call the respective methods
of each initialized plugin.
With the new API come new names: all of the methods plugins can implement
received new, more descriptive names that all follow a similar pattern.
The old (dubbed V1) API still remains in place, although deprecated. One can
turn it off by setting the `KALEIDOSCOPE_ENABLE_V1_PLUGIN_API` define to zero,
while compiling the firmware.
This work is based on #276, written by @noseglasses. @obra and @algernon did
some cleaning up and applied a little naming treatment.
Signed-off-by: noseglasses <shinynoseglasses@gmail.com>
Signed-off-by: Jesse Vincent <jesse@keyboard.io>
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
7 years ago
|
|
|
|
|
|
|
// Some words about the design of hook routing:
|
|
|
|
//
|
|
|
|
// The EventDispatcher class implements a compile-time loop over all plugins, which
|
|
|
|
// calls an event handler on each plugin.
|
|
|
|
//
|
|
|
|
// Each hook called by the firmware core compiles down to only a single
|
|
|
|
// static function call (in class Hooks), rather than one for each plugin.
|
|
|
|
//
|
|
|
|
// This approach is better than using virtual event handlers in classes
|
|
|
|
// derived from kaleidoscope::Plugin because it results in significantly fewer
|
|
|
|
// virtual function calls and virtual function tables (vtables).
|
|
|
|
//
|
|
|
|
// The call to event handlers through kaleidoscope::Hooks and
|
|
|
|
// kaleidoscope_internal::EventDispatcher is templated to allow for compile time
|
|
|
|
// static polymorphisms (plugins' EventHandlers aren't virtual).
|
|
|
|
//
|
|
|
|
// Technically, plugins don't need to be derived from kaleidoscope::Plugin, but
|
|
|
|
// only need to implement a set of event handlers whose call signature match the
|
|
|
|
// API definition. This approach is similar to duck typing in scripting languages:
|
|
|
|
// The compiler only cares that a method's signature matches, not that the plugin
|
|
|
|
// is derived from kaleidoscope::Plugin.
|
|
|
|
//
|
|
|
|
// Static hook functions inside the Hooks class each use the EventDispatcher
|
|
|
|
// helper class to cast an associated EventHandler on each plugin instance.
|
|
|
|
|
|
|
|
|
|
|
|
// This defines an auxiliary class 'EventHandler_Foo' for each hook 'Foo'.
|
|
|
|
// Kaleidoscope::Hooks calls the EventDispatcher class, which in turn invokes
|
|
|
|
// the event handler method 'Foo' of each registered plugin with a given
|
|
|
|
// set of arguments.
|
|
|
|
|
Event handler versioning, deprecation and extended signature checks
Recently a proposed change to the firmware required a change to one of
the event handlers'/hooks' signatures.
Up to now, we only supported a single overload/implementation of a
event handler of a specific type. This means that changing handler signatures
was only possible by adding a handler method with a similar name and
a different signature like
EventHandlerResult
onKeyswitchEvent(Key &mappedKey, byte row, byte col, uint8_t keyState);
and
EventHandlerResult
onKeyswitchEvent2(Key &mappedKey, KeyAddr key_addr, uint8_t keyState);
As this was regarded as unacceptable confusion of the users of our
programming interface, this commit introduces some changes to the
event handler management.
Important changes:
* handlers can now be overloaded,
* handler signatures can be versioned,
* individual versions can be declared as deprecated,
* we now abort the compile if a handler reimplementation with a bad signature
is found,
* or if two or more handlers with correct signatures are detected that
are furtheron considered as ambiguous.
Impact on resources:
The proposed changes only affect the way things are handled at compile time.
No changes in terms of PROGMEM or RAM are to be expected.
Signed-off-by: Florian Fleissner <fleissner@inpartik.de>
6 years ago
|
|
|
// The following macros help to generate type or instance names
|
|
|
|
// by concatenating macro parameter tokens.
|
|
|
|
//
|
|
|
|
#define _NAME3(A, B, C) A##B##C
|
|
|
|
#define _NAME4(A, B, C, D) A##B##C##D
|
|
|
|
#define _NAME5(A, B, C, D, E) A##B##C##D##E
|
|
|
|
|
Major redesign of the plugin and hooking interface
With this redesign, we introduce a new way to create plugins, which is easier to
extend with new hook points, provides a better interface, uses less memory, less
program space, and is a tiny bit faster too.
It all begins with `kaleidoscope::Plugin` being the base class, which provides
the hook methods plugins can implement. Plugins should be declared with
`KALEIDOSCOPE_INIT_PLUGINS` instead of `Kaleidoscope.use()`. Behind this macro
is a bit of magic (see the in-code documentation) that allows us to unroll the
hook method calls, avoid vtables, and so on. It creates an override for
`kaleidoscope::Hooks::*` methods, each of which will call the respective methods
of each initialized plugin.
With the new API come new names: all of the methods plugins can implement
received new, more descriptive names that all follow a similar pattern.
The old (dubbed V1) API still remains in place, although deprecated. One can
turn it off by setting the `KALEIDOSCOPE_ENABLE_V1_PLUGIN_API` define to zero,
while compiling the firmware.
This work is based on #276, written by @noseglasses. @obra and @algernon did
some cleaning up and applied a little naming treatment.
Signed-off-by: noseglasses <shinynoseglasses@gmail.com>
Signed-off-by: Jesse Vincent <jesse@keyboard.io>
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
7 years ago
|
|
|
#define _REGISTER_EVENT_HANDLER( \
|
Event handler versioning, deprecation and extended signature checks
Recently a proposed change to the firmware required a change to one of
the event handlers'/hooks' signatures.
Up to now, we only supported a single overload/implementation of a
event handler of a specific type. This means that changing handler signatures
was only possible by adding a handler method with a similar name and
a different signature like
EventHandlerResult
onKeyswitchEvent(Key &mappedKey, byte row, byte col, uint8_t keyState);
and
EventHandlerResult
onKeyswitchEvent2(Key &mappedKey, KeyAddr key_addr, uint8_t keyState);
As this was regarded as unacceptable confusion of the users of our
programming interface, this commit introduces some changes to the
event handler management.
Important changes:
* handlers can now be overloaded,
* handler signatures can be versioned,
* individual versions can be declared as deprecated,
* we now abort the compile if a handler reimplementation with a bad signature
is found,
* or if two or more handlers with correct signatures are detected that
are furtheron considered as ambiguous.
Impact on resources:
The proposed changes only affect the way things are handled at compile time.
No changes in terms of PROGMEM or RAM are to be expected.
Signed-off-by: Florian Fleissner <fleissner@inpartik.de>
6 years ago
|
|
|
HOOK_NAME, HOOK_VERSION, DEPRECATION_TAG, \
|
|
|
|
SHOULD_ABORT_ON_CONSUMED_EVENT, SIGNATURE, ARGS_LIST) \
|
Major redesign of the plugin and hooking interface
With this redesign, we introduce a new way to create plugins, which is easier to
extend with new hook points, provides a better interface, uses less memory, less
program space, and is a tiny bit faster too.
It all begins with `kaleidoscope::Plugin` being the base class, which provides
the hook methods plugins can implement. Plugins should be declared with
`KALEIDOSCOPE_INIT_PLUGINS` instead of `Kaleidoscope.use()`. Behind this macro
is a bit of magic (see the in-code documentation) that allows us to unroll the
hook method calls, avoid vtables, and so on. It creates an override for
`kaleidoscope::Hooks::*` methods, each of which will call the respective methods
of each initialized plugin.
With the new API come new names: all of the methods plugins can implement
received new, more descriptive names that all follow a similar pattern.
The old (dubbed V1) API still remains in place, although deprecated. One can
turn it off by setting the `KALEIDOSCOPE_ENABLE_V1_PLUGIN_API` define to zero,
while compiling the firmware.
This work is based on #276, written by @noseglasses. @obra and @algernon did
some cleaning up and applied a little naming treatment.
Signed-off-by: noseglasses <shinynoseglasses@gmail.com>
Signed-off-by: Jesse Vincent <jesse@keyboard.io>
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
7 years ago
|
|
|
__NL__ \
|
|
|
|
namespace kaleidoscope_internal { __NL__ \
|
|
|
|
__NL__ \
|
Event handler versioning, deprecation and extended signature checks
Recently a proposed change to the firmware required a change to one of
the event handlers'/hooks' signatures.
Up to now, we only supported a single overload/implementation of a
event handler of a specific type. This means that changing handler signatures
was only possible by adding a handler method with a similar name and
a different signature like
EventHandlerResult
onKeyswitchEvent(Key &mappedKey, byte row, byte col, uint8_t keyState);
and
EventHandlerResult
onKeyswitchEvent2(Key &mappedKey, KeyAddr key_addr, uint8_t keyState);
As this was regarded as unacceptable confusion of the users of our
programming interface, this commit introduces some changes to the
event handler management.
Important changes:
* handlers can now be overloaded,
* handler signatures can be versioned,
* individual versions can be declared as deprecated,
* we now abort the compile if a handler reimplementation with a bad signature
is found,
* or if two or more handlers with correct signatures are detected that
are furtheron considered as ambiguous.
Impact on resources:
The proposed changes only affect the way things are handled at compile time.
No changes in terms of PROGMEM or RAM are to be expected.
Signed-off-by: Florian Fleissner <fleissner@inpartik.de>
6 years ago
|
|
|
template<bool hook_is_implemented__, __NL__ \
|
|
|
|
typename Plugin__, __NL__ \
|
|
|
|
typename... Args__> __NL__ \
|
|
|
|
struct _NAME5(EventHandler_, HOOK_NAME, _v, HOOK_VERSION, _caller) { __NL__ \
|
|
|
|
static DEPRECATION_TAG kaleidoscope::EventHandlerResult __NL__ \
|
|
|
|
call(Plugin__ &plugin, Args__&&... hook_args) { __NL__ \
|
|
|
|
return plugin.HOOK_NAME(hook_args...); __NL__ \
|
|
|
|
} __NL__ \
|
|
|
|
}; __NL__ \
|
|
|
|
__NL__ \
|
|
|
|
/* This specialization is used for those hooks that a plugin does not __NL__ \
|
|
|
|
* implement. __NL__ \
|
|
|
|
*/ __NL__ \
|
|
|
|
template<typename Plugin__, __NL__ \
|
|
|
|
typename... Args__> __NL__ \
|
|
|
|
struct _NAME5(EventHandler_, HOOK_NAME, _v, HOOK_VERSION, _caller) __NL__ \
|
|
|
|
<false, Plugin__, Args__...> { __NL__ \
|
|
|
|
static kaleidoscope::EventHandlerResult __NL__ \
|
|
|
|
call(Plugin__ &/*plugin*/, Args__&&... /*hook_args*/) { __NL__ \
|
|
|
|
return kaleidoscope::EventHandlerResult::OK; __NL__ \
|
|
|
|
} __NL__ \
|
|
|
|
}; __NL__ \
|
|
|
|
__NL__ \
|
|
|
|
struct _NAME4(EventHandler_, HOOK_NAME, _v, HOOK_VERSION) { __NL__ \
|
Major redesign of the plugin and hooking interface
With this redesign, we introduce a new way to create plugins, which is easier to
extend with new hook points, provides a better interface, uses less memory, less
program space, and is a tiny bit faster too.
It all begins with `kaleidoscope::Plugin` being the base class, which provides
the hook methods plugins can implement. Plugins should be declared with
`KALEIDOSCOPE_INIT_PLUGINS` instead of `Kaleidoscope.use()`. Behind this macro
is a bit of magic (see the in-code documentation) that allows us to unroll the
hook method calls, avoid vtables, and so on. It creates an override for
`kaleidoscope::Hooks::*` methods, each of which will call the respective methods
of each initialized plugin.
With the new API come new names: all of the methods plugins can implement
received new, more descriptive names that all follow a similar pattern.
The old (dubbed V1) API still remains in place, although deprecated. One can
turn it off by setting the `KALEIDOSCOPE_ENABLE_V1_PLUGIN_API` define to zero,
while compiling the firmware.
This work is based on #276, written by @noseglasses. @obra and @algernon did
some cleaning up and applied a little naming treatment.
Signed-off-by: noseglasses <shinynoseglasses@gmail.com>
Signed-off-by: Jesse Vincent <jesse@keyboard.io>
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
7 years ago
|
|
|
__NL__ \
|
|
|
|
static bool shouldAbortOnConsumedEvent() { __NL__ \
|
|
|
|
return SHOULD_ABORT_ON_CONSUMED_EVENT; __NL__ \
|
|
|
|
} __NL__ \
|
|
|
|
__NL__ \
|
|
|
|
template<typename Plugin__, typename... Args__> __NL__ \
|
|
|
|
static kaleidoscope::EventHandlerResult __NL__ \
|
|
|
|
call(Plugin__ &plugin, Args__&&... hook_args) { __NL__ \
|
Event handler versioning, deprecation and extended signature checks
Recently a proposed change to the firmware required a change to one of
the event handlers'/hooks' signatures.
Up to now, we only supported a single overload/implementation of a
event handler of a specific type. This means that changing handler signatures
was only possible by adding a handler method with a similar name and
a different signature like
EventHandlerResult
onKeyswitchEvent(Key &mappedKey, byte row, byte col, uint8_t keyState);
and
EventHandlerResult
onKeyswitchEvent2(Key &mappedKey, KeyAddr key_addr, uint8_t keyState);
As this was regarded as unacceptable confusion of the users of our
programming interface, this commit introduces some changes to the
event handler management.
Important changes:
* handlers can now be overloaded,
* handler signatures can be versioned,
* individual versions can be declared as deprecated,
* we now abort the compile if a handler reimplementation with a bad signature
is found,
* or if two or more handlers with correct signatures are detected that
are furtheron considered as ambiguous.
Impact on resources:
The proposed changes only affect the way things are handled at compile time.
No changes in terms of PROGMEM or RAM are to be expected.
Signed-off-by: Florian Fleissner <fleissner@inpartik.de>
6 years ago
|
|
|
__NL__ \
|
Major redesign of the plugin and hooking interface
With this redesign, we introduce a new way to create plugins, which is easier to
extend with new hook points, provides a better interface, uses less memory, less
program space, and is a tiny bit faster too.
It all begins with `kaleidoscope::Plugin` being the base class, which provides
the hook methods plugins can implement. Plugins should be declared with
`KALEIDOSCOPE_INIT_PLUGINS` instead of `Kaleidoscope.use()`. Behind this macro
is a bit of magic (see the in-code documentation) that allows us to unroll the
hook method calls, avoid vtables, and so on. It creates an override for
`kaleidoscope::Hooks::*` methods, each of which will call the respective methods
of each initialized plugin.
With the new API come new names: all of the methods plugins can implement
received new, more descriptive names that all follow a similar pattern.
The old (dubbed V1) API still remains in place, although deprecated. One can
turn it off by setting the `KALEIDOSCOPE_ENABLE_V1_PLUGIN_API` define to zero,
while compiling the firmware.
This work is based on #276, written by @noseglasses. @obra and @algernon did
some cleaning up and applied a little naming treatment.
Signed-off-by: noseglasses <shinynoseglasses@gmail.com>
Signed-off-by: Jesse Vincent <jesse@keyboard.io>
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
7 years ago
|
|
|
_VALIDATE_EVENT_HANDLER_SIGNATURE(HOOK_NAME, Plugin__) __NL__ \
|
Event handler versioning, deprecation and extended signature checks
Recently a proposed change to the firmware required a change to one of
the event handlers'/hooks' signatures.
Up to now, we only supported a single overload/implementation of a
event handler of a specific type. This means that changing handler signatures
was only possible by adding a handler method with a similar name and
a different signature like
EventHandlerResult
onKeyswitchEvent(Key &mappedKey, byte row, byte col, uint8_t keyState);
and
EventHandlerResult
onKeyswitchEvent2(Key &mappedKey, KeyAddr key_addr, uint8_t keyState);
As this was regarded as unacceptable confusion of the users of our
programming interface, this commit introduces some changes to the
event handler management.
Important changes:
* handlers can now be overloaded,
* handler signatures can be versioned,
* individual versions can be declared as deprecated,
* we now abort the compile if a handler reimplementation with a bad signature
is found,
* or if two or more handlers with correct signatures are detected that
are furtheron considered as ambiguous.
Impact on resources:
The proposed changes only affect the way things are handled at compile time.
No changes in terms of PROGMEM or RAM are to be expected.
Signed-off-by: Florian Fleissner <fleissner@inpartik.de>
6 years ago
|
|
|
__NL__ \
|
|
|
|
static constexpr bool derived_implements_hook __NL__ \
|
|
|
|
= HookVersionImplemented_##HOOK_NAME< __NL__ \
|
|
|
|
Plugin__, HOOK_VERSION>::value; __NL__ \
|
|
|
|
__NL__ \
|
|
|
|
/* The caller type adds another level of indirection that __NL__ \
|
|
|
|
* is required to enable some hooks not to be implemented __NL__ \
|
|
|
|
* by plugins. __NL__ \
|
|
|
|
*/ __NL__ \
|
|
|
|
typedef _NAME5(EventHandler_, HOOK_NAME, _v, HOOK_VERSION, _caller) __NL__ \
|
|
|
|
< __NL__ \
|
|
|
|
derived_implements_hook, __NL__ \
|
|
|
|
Plugin__, __NL__ \
|
|
|
|
Args__... __NL__ \
|
|
|
|
> Caller; __NL__ \
|
|
|
|
__NL__ \
|
|
|
|
return Caller::call(plugin, hook_args...); __NL__ \
|
Major redesign of the plugin and hooking interface
With this redesign, we introduce a new way to create plugins, which is easier to
extend with new hook points, provides a better interface, uses less memory, less
program space, and is a tiny bit faster too.
It all begins with `kaleidoscope::Plugin` being the base class, which provides
the hook methods plugins can implement. Plugins should be declared with
`KALEIDOSCOPE_INIT_PLUGINS` instead of `Kaleidoscope.use()`. Behind this macro
is a bit of magic (see the in-code documentation) that allows us to unroll the
hook method calls, avoid vtables, and so on. It creates an override for
`kaleidoscope::Hooks::*` methods, each of which will call the respective methods
of each initialized plugin.
With the new API come new names: all of the methods plugins can implement
received new, more descriptive names that all follow a similar pattern.
The old (dubbed V1) API still remains in place, although deprecated. One can
turn it off by setting the `KALEIDOSCOPE_ENABLE_V1_PLUGIN_API` define to zero,
while compiling the firmware.
This work is based on #276, written by @noseglasses. @obra and @algernon did
some cleaning up and applied a little naming treatment.
Signed-off-by: noseglasses <shinynoseglasses@gmail.com>
Signed-off-by: Jesse Vincent <jesse@keyboard.io>
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
7 years ago
|
|
|
} __NL__ \
|
|
|
|
}; __NL__ \
|
|
|
|
__NL__ \
|
|
|
|
} __NL__ \
|
|
|
|
__NL__ \
|
|
|
|
namespace kaleidoscope { __NL__ \
|
|
|
|
__NL__ \
|
|
|
|
EventHandlerResult Hooks::HOOK_NAME SIGNATURE { __NL__ \
|
|
|
|
return kaleidoscope_internal::EventDispatcher::template __NL__ \
|
Event handler versioning, deprecation and extended signature checks
Recently a proposed change to the firmware required a change to one of
the event handlers'/hooks' signatures.
Up to now, we only supported a single overload/implementation of a
event handler of a specific type. This means that changing handler signatures
was only possible by adding a handler method with a similar name and
a different signature like
EventHandlerResult
onKeyswitchEvent(Key &mappedKey, byte row, byte col, uint8_t keyState);
and
EventHandlerResult
onKeyswitchEvent2(Key &mappedKey, KeyAddr key_addr, uint8_t keyState);
As this was regarded as unacceptable confusion of the users of our
programming interface, this commit introduces some changes to the
event handler management.
Important changes:
* handlers can now be overloaded,
* handler signatures can be versioned,
* individual versions can be declared as deprecated,
* we now abort the compile if a handler reimplementation with a bad signature
is found,
* or if two or more handlers with correct signatures are detected that
are furtheron considered as ambiguous.
Impact on resources:
The proposed changes only affect the way things are handled at compile time.
No changes in terms of PROGMEM or RAM are to be expected.
Signed-off-by: Florian Fleissner <fleissner@inpartik.de>
6 years ago
|
|
|
apply<kaleidoscope_internal __NL__ \
|
|
|
|
::_NAME4(EventHandler_, HOOK_NAME, _v, HOOK_VERSION)> __NL__ \
|
Major redesign of the plugin and hooking interface
With this redesign, we introduce a new way to create plugins, which is easier to
extend with new hook points, provides a better interface, uses less memory, less
program space, and is a tiny bit faster too.
It all begins with `kaleidoscope::Plugin` being the base class, which provides
the hook methods plugins can implement. Plugins should be declared with
`KALEIDOSCOPE_INIT_PLUGINS` instead of `Kaleidoscope.use()`. Behind this macro
is a bit of magic (see the in-code documentation) that allows us to unroll the
hook method calls, avoid vtables, and so on. It creates an override for
`kaleidoscope::Hooks::*` methods, each of which will call the respective methods
of each initialized plugin.
With the new API come new names: all of the methods plugins can implement
received new, more descriptive names that all follow a similar pattern.
The old (dubbed V1) API still remains in place, although deprecated. One can
turn it off by setting the `KALEIDOSCOPE_ENABLE_V1_PLUGIN_API` define to zero,
while compiling the firmware.
This work is based on #276, written by @noseglasses. @obra and @algernon did
some cleaning up and applied a little naming treatment.
Signed-off-by: noseglasses <shinynoseglasses@gmail.com>
Signed-off-by: Jesse Vincent <jesse@keyboard.io>
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
7 years ago
|
|
|
ARGS_LIST; __NL__ \
|
|
|
|
} __NL__ \
|
|
|
|
__NL__ \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define _INLINE_EVENT_HANDLER_FOR_PLUGIN(PLUGIN) \
|
|
|
|
__NL__ \
|
|
|
|
result = EventHandler__::call(PLUGIN, hook_args...); __NL__ \
|
|
|
|
__NL__ \
|
|
|
|
if (EventHandler__::shouldAbortOnConsumedEvent() && __NL__ \
|
|
|
|
result == kaleidoscope::EventHandlerResult::EVENT_CONSUMED) { __NL__ \
|
|
|
|
return result; __NL__ \
|
|
|
|
} __NL__
|
|
|
|
|
|
|
|
// _KALEIDOSCOPE_INIT_PLUGINS builds the loops that execute the plugins'
|
|
|
|
// implementations of the various event handlers.
|
|
|
|
//
|
|
|
|
// Its arguments are a list of references to plugin instances that have been
|
|
|
|
// instantiated in the global scope.
|
|
|
|
|
|
|
|
// EventDispatcher::apply() implements a compile time for-each loop over all
|
|
|
|
// plugins. The compiler automatically optimizes away calls to any plugin that
|
|
|
|
// doesn't implement an EventHandler for a given hook.
|
|
|
|
|
|
|
|
#define _KALEIDOSCOPE_INIT_PLUGINS(...) __NL__ \
|
|
|
|
namespace kaleidoscope_internal { __NL__ \
|
|
|
|
struct EventDispatcher { __NL__ \
|
|
|
|
__NL__ \
|
|
|
|
/* Iterate through plugins, calling each one's event handler with */ __NL__ \
|
|
|
|
/* the arguments passed to the hook */ __NL__ \
|
|
|
|
template<typename EventHandler__, typename... Args__ > __NL__ \
|
|
|
|
static kaleidoscope::EventHandlerResult apply(Args__&&... hook_args) { __NL__ \
|
|
|
|
__NL__ \
|
|
|
|
kaleidoscope::EventHandlerResult result; __NL__ \
|
|
|
|
MAP(_INLINE_EVENT_HANDLER_FOR_PLUGIN, __VA_ARGS__) __NL__ \
|
|
|
|
__NL__ \
|
|
|
|
return result; __NL__ \
|
|
|
|
} __NL__ \
|
|
|
|
}; __NL__ \
|
|
|
|
__NL__ \
|
|
|
|
} __NL__ \
|
|
|
|
/* We register event handlers here - which is not technically related */ __NL__ \
|
|
|
|
/* to initialization, nor is it in the same namespace - to support the */ __NL__ \
|
|
|
|
/* transition from the old APIs. When the user sketch does not use */ __NL__ \
|
|
|
|
/* KALEIDOSCOPE_INIT_PLUGINS(), the event handlers will not exist */ __NL__ \
|
|
|
|
/* either, thus wrapping them would produce a compile error. For this */ __NL__ \
|
|
|
|
/* reason, we do the wrapping here, tied to _KALEIDOSCOPE_INIT_PLUGINS. */ __NL__ \
|
|
|
|
/* */ __NL__ \
|
|
|
|
/* TODO(anyone): Move this somewhere else, outside of _internal, once */ __NL__ \
|
|
|
|
/* the V1 API is removed. */ __NL__ \
|
Event handler versioning, deprecation and extended signature checks
Recently a proposed change to the firmware required a change to one of
the event handlers'/hooks' signatures.
Up to now, we only supported a single overload/implementation of a
event handler of a specific type. This means that changing handler signatures
was only possible by adding a handler method with a similar name and
a different signature like
EventHandlerResult
onKeyswitchEvent(Key &mappedKey, byte row, byte col, uint8_t keyState);
and
EventHandlerResult
onKeyswitchEvent2(Key &mappedKey, KeyAddr key_addr, uint8_t keyState);
As this was regarded as unacceptable confusion of the users of our
programming interface, this commit introduces some changes to the
event handler management.
Important changes:
* handlers can now be overloaded,
* handler signatures can be versioned,
* individual versions can be declared as deprecated,
* we now abort the compile if a handler reimplementation with a bad signature
is found,
* or if two or more handlers with correct signatures are detected that
are furtheron considered as ambiguous.
Impact on resources:
The proposed changes only affect the way things are handled at compile time.
No changes in terms of PROGMEM or RAM are to be expected.
Signed-off-by: Florian Fleissner <fleissner@inpartik.de>
6 years ago
|
|
|
__NL__ \
|
|
|
|
_PREPARE_EVENT_HANDLER_SIGNATURE_CHECK __NL__ \
|
|
|
|
__NL__ \
|
Major redesign of the plugin and hooking interface
With this redesign, we introduce a new way to create plugins, which is easier to
extend with new hook points, provides a better interface, uses less memory, less
program space, and is a tiny bit faster too.
It all begins with `kaleidoscope::Plugin` being the base class, which provides
the hook methods plugins can implement. Plugins should be declared with
`KALEIDOSCOPE_INIT_PLUGINS` instead of `Kaleidoscope.use()`. Behind this macro
is a bit of magic (see the in-code documentation) that allows us to unroll the
hook method calls, avoid vtables, and so on. It creates an override for
`kaleidoscope::Hooks::*` methods, each of which will call the respective methods
of each initialized plugin.
With the new API come new names: all of the methods plugins can implement
received new, more descriptive names that all follow a similar pattern.
The old (dubbed V1) API still remains in place, although deprecated. One can
turn it off by setting the `KALEIDOSCOPE_ENABLE_V1_PLUGIN_API` define to zero,
while compiling the firmware.
This work is based on #276, written by @noseglasses. @obra and @algernon did
some cleaning up and applied a little naming treatment.
Signed-off-by: noseglasses <shinynoseglasses@gmail.com>
Signed-off-by: Jesse Vincent <jesse@keyboard.io>
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
7 years ago
|
|
|
_FOR_EACH_EVENT_HANDLER(_REGISTER_EVENT_HANDLER)
|