|
|
|
#include "Kaleidoscope.h"
|
|
|
|
|
|
|
|
|
|
|
|
static bool handleSyntheticKeyswitchEvent(Key mappedKey, uint8_t keyState) {
|
|
|
|
if (mappedKey.flags & RESERVED)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(mappedKey.flags & SYNTHETIC))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (mappedKey.flags & IS_INTERNAL) {
|
|
|
|
return false;
|
|
|
|
} else if (mappedKey.flags & IS_CONSUMER) {
|
|
|
|
if (keyIsPressed(keyState)) {
|
|
|
|
} else if (keyWasPressed(keyState)) {
|
|
|
|
kaleidoscope::hid::pressConsumerControl(mappedKey);
|
|
|
|
kaleidoscope::hid::releaseConsumerControl(mappedKey);
|
|
|
|
}
|
|
|
|
} else if (mappedKey.flags & IS_SYSCTL) {
|
|
|
|
if (keyIsPressed(keyState)) {
|
|
|
|
} else if (keyWasPressed(keyState)) {
|
|
|
|
kaleidoscope::hid::pressSystemControl(mappedKey);
|
|
|
|
kaleidoscope::hid::releaseSystemControl(mappedKey);
|
|
|
|
}
|
|
|
|
} else if (mappedKey.flags & SWITCH_TO_KEYMAP) {
|
|
|
|
// Should not happen, handled elsewhere.
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
key_events: A way to hook into the event handling
This adds a new `handle_user_key_event` function, that will get called
before anything else, and can override what happens. If it returns true,
the event will not be processed further by the firmware. By default,
this function returns false, and is a no-op.
It is defined with a `weak` attribute, to let the linker know that any
other function with the same name should override his one. This makes it
possible to have another version of this function in a firmware Sketch,
and override the behaviour, to extend the event handling.
This is the foundation that allows it to use external libraries, and tap
into the firmware's event handler, to add new stuff. (We can already
hook into the main loop by changing the top `loop` function in the
Sketch)
This addresses #21 for the most part.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
8 years ago
|
|
|
|
|
|
|
static bool handleKeyswitchEventDefault(Key mappedKey, byte row, byte col, uint8_t keyState) {
|
|
|
|
//for every newly pressed button, figure out what logical key it is and send a key down event
|
|
|
|
// for every newly released button, figure out what logical key it is and send a key up event
|
|
|
|
|
|
|
|
if (mappedKey.flags & SYNTHETIC) {
|
|
|
|
handleSyntheticKeyswitchEvent(mappedKey, keyState);
|
|
|
|
} else if (keyIsPressed(keyState)) {
|
|
|
|
kaleidoscope::hid::pressKey(mappedKey);
|
|
|
|
} else if (keyToggledOff(keyState) && (keyState & INJECTED)) {
|
|
|
|
kaleidoscope::hid::releaseKey(mappedKey);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleKeyswitchEvent(Key mappedKey, byte row, byte col, uint8_t keyState) {
|
layers: Implement a two-stage cache
With the new implementation, there are two lookup functions, because we have two
caches, and different parts of the firmware will want to use either this or
that (or perhaps both, in rare cases).
First of all, we use caches because looking up a key through all the layers
is costy, and the cost increases dramatically the more layers we have.
Then, we have the `effectiveKeymapCache`, because to have layer behaviours
we want, that is, if you hold a key on a layer, release the layer key but
continue holding the other, we want for the layered keycode to continue
repeating. At the same time, we want other keys to not be affected by the
now-turned-off layer. So we update the keycode in the cache on-demand, when
the key is pressed or released. (see the top of `handleKeyswitchEvent`).
On the other hand, we also have plugins that scan the whole keymap, and do
things based on that information, such as highlighting keys that changed
between layers. These need to be able to look at a state of where the
keymap *should* be, not necessarily where it is. The `effectiveKeymapCache`
is not useful here. So we use a `keymapCache` which we update whenever
layers change (see `Layer.on` and `Layer.off`), and it updates the cache to
show how the keymap should look, without the `effectiveKeymapCache`-induced
behaviour.
Thus, if we are curious about what a given key will do, use `lookup`. If we
are curious what the active layer state describes the key as, use
`lookupUncached`.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
7 years ago
|
|
|
/* If a key had an on or off event, we update the effective keymap cache. See
|
|
|
|
* layers.h for an explanation about the different caches we have. */
|
|
|
|
if (keyToggledOn(keyState) || keyToggledOff(keyState))
|
layers: Implement a two-stage cache
With the new implementation, there are two lookup functions, because we have two
caches, and different parts of the firmware will want to use either this or
that (or perhaps both, in rare cases).
First of all, we use caches because looking up a key through all the layers
is costy, and the cost increases dramatically the more layers we have.
Then, we have the `effectiveKeymapCache`, because to have layer behaviours
we want, that is, if you hold a key on a layer, release the layer key but
continue holding the other, we want for the layered keycode to continue
repeating. At the same time, we want other keys to not be affected by the
now-turned-off layer. So we update the keycode in the cache on-demand, when
the key is pressed or released. (see the top of `handleKeyswitchEvent`).
On the other hand, we also have plugins that scan the whole keymap, and do
things based on that information, such as highlighting keys that changed
between layers. These need to be able to look at a state of where the
keymap *should* be, not necessarily where it is. The `effectiveKeymapCache`
is not useful here. So we use a `keymapCache` which we update whenever
layers change (see `Layer.on` and `Layer.off`), and it updates the cache to
show how the keymap should look, without the `effectiveKeymapCache`-induced
behaviour.
Thus, if we are curious about what a given key will do, use `lookup`. If we
are curious what the active layer state describes the key as, use
`lookupUncached`.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
7 years ago
|
|
|
Layer.updateEffectiveKeymapCache(row, col);
|
|
|
|
|
|
|
|
/* If the key we are dealing with is masked, ignore it until it is released.
|
|
|
|
* When releasing it, clear the mask, so future key events can be handled
|
|
|
|
* appropriately.
|
|
|
|
*
|
|
|
|
* See layers.cpp for an example that masks keys, and the reason why it does
|
|
|
|
* so.
|
|
|
|
*/
|
|
|
|
if (KeyboardHardware.isKeyMasked(row, col)) {
|
|
|
|
if (keyToggledOff(keyState)) {
|
|
|
|
KeyboardHardware.unMaskKey(row, col);
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(keyState & INJECTED)) {
|
|
|
|
mappedKey = Layer.lookup(row, col);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (byte i = 0; Kaleidoscope.eventHandlers[i] != NULL && i < HOOK_MAX; i++) {
|
|
|
|
Kaleidoscope_::eventHandlerHook handler = Kaleidoscope.eventHandlers[i];
|
|
|
|
mappedKey = (*handler)(mappedKey, row, col, keyState);
|
|
|
|
if (mappedKey.raw == Key_NoKey.raw)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mappedKey = Layer.eventHandler(mappedKey, row, col, keyState);
|
|
|
|
if (mappedKey.raw == Key_NoKey.raw)
|
|
|
|
return;
|
|
|
|
handleKeyswitchEventDefault(mappedKey, row, col, keyState);
|
|
|
|
}
|