|
|
|
#include "Kaleidoscope.h"
|
|
|
|
|
|
|
|
static bool handle_synthetic_keyswitch_event(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) {
|
Support for holding Consumer/SystemControl keys
Instead of calling the `.write` method of `ConsumerControl`/`SystemControl`,
which registers the key, sends a report, then unregisters, and reports again,
just `.press` it when the key is pressed, as we did before.
However, since `.press` always sends a report, and so does `.releaseAll`, we
can't have it the same way we do for `Keyboard`. We need to explicitly release
the consumer/system key, when the triggering key is released too. Not doing so
makes the key stuck, as we never release it, and that will upset the operating
system very much.
With this patch, we do an explicit release when the key toggles off, and thus,
we support both holding the key, and allowing the OS to trigger repeat, and, the
key won't be stuck, either!
Fixes #120.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
8 years ago
|
|
|
if (key_is_pressed(keyState))
|
|
|
|
ConsumerControl.press(mappedKey.keyCode);
|
|
|
|
else if (key_was_pressed(keyState))
|
|
|
|
ConsumerControl.release(mappedKey.keyCode);
|
|
|
|
} else if (mappedKey.flags & IS_SYSCTL) {
|
Support for holding Consumer/SystemControl keys
Instead of calling the `.write` method of `ConsumerControl`/`SystemControl`,
which registers the key, sends a report, then unregisters, and reports again,
just `.press` it when the key is pressed, as we did before.
However, since `.press` always sends a report, and so does `.releaseAll`, we
can't have it the same way we do for `Keyboard`. We need to explicitly release
the consumer/system key, when the triggering key is released too. Not doing so
makes the key stuck, as we never release it, and that will upset the operating
system very much.
With this patch, we do an explicit release when the key toggles off, and thus,
we support both holding the key, and allowing the OS to trigger repeat, and, the
key won't be stuck, either!
Fixes #120.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
8 years ago
|
|
|
if (key_is_pressed(keyState))
|
|
|
|
SystemControl.press(mappedKey.keyCode);
|
|
|
|
else if (key_was_pressed(keyState))
|
|
|
|
SystemControl.release();
|
|
|
|
} 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 handle_keyswitch_event_default(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) {
|
|
|
|
handle_synthetic_keyswitch_event( mappedKey, keyState);
|
|
|
|
} else if (key_is_pressed(keyState)) {
|
|
|
|
press_key(mappedKey);
|
|
|
|
} else if (key_toggled_off(keyState) && (keyState & INJECTED)) {
|
|
|
|
release_key(mappedKey);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void press_key(Key mappedKey) {
|
|
|
|
if (mappedKey.flags & SHIFT_HELD) {
|
|
|
|
Keyboard.press(Key_LeftShift.keyCode);
|
|
|
|
}
|
|
|
|
if (mappedKey.flags & CTRL_HELD) {
|
|
|
|
Keyboard.press(Key_LeftControl.keyCode);
|
|
|
|
}
|
|
|
|
if (mappedKey.flags & LALT_HELD) {
|
|
|
|
Keyboard.press(Key_LeftAlt.keyCode);
|
|
|
|
}
|
|
|
|
if (mappedKey.flags & RALT_HELD) {
|
|
|
|
Keyboard.press(Key_RightAlt.keyCode);
|
|
|
|
}
|
|
|
|
if (mappedKey.flags & GUI_HELD) {
|
|
|
|
Keyboard.press(Key_LeftGui.keyCode);
|
|
|
|
}
|
|
|
|
Keyboard.press(mappedKey.keyCode);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void release_key(Key mappedKey) {
|
|
|
|
if (mappedKey.flags & SHIFT_HELD) {
|
|
|
|
Keyboard.release(Key_LeftShift.keyCode);
|
|
|
|
}
|
|
|
|
if (mappedKey.flags & CTRL_HELD) {
|
|
|
|
Keyboard.release(Key_LeftControl.keyCode);
|
|
|
|
}
|
|
|
|
if (mappedKey.flags & LALT_HELD) {
|
|
|
|
Keyboard.release(Key_LeftAlt.keyCode);
|
|
|
|
}
|
|
|
|
if (mappedKey.flags & RALT_HELD) {
|
|
|
|
Keyboard.release(Key_RightAlt.keyCode);
|
|
|
|
}
|
|
|
|
if (mappedKey.flags & GUI_HELD) {
|
|
|
|
Keyboard.release(Key_LeftGui.keyCode);
|
|
|
|
}
|
|
|
|
Keyboard.release(mappedKey.keyCode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handle_keyswitch_event(Key mappedKey, byte row, byte col, uint8_t keyState) {
|
|
|
|
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];
|
Event hooks reworked, again
Instead of returning a bool, to signal whether further processing should be
done, return a Key. Reason being, if we want to replace a key with another, for
subsequent handlers, it is a lot easier if we can modify what gets passed along,
than it is to inject a key, and try to avoid loops and infinite recursion.
Nevertheless, injecting keys is still possible.
This is not immediately useful for the core firmware, but makes it trivially
easy to upgrade keys from their normal behaviour to something special: for
example, a one-shot handler can auto-promote modifiers to one-shot, simply by
scheduling a promoter handler before the real one.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
8 years ago
|
|
|
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;
|
|
|
|
handle_keyswitch_event_default(mappedKey, row, col, keyState);
|
|
|
|
}
|