Instead of having a primary and a temporary layer, store the state of at
most 32 layers in a bitfield. These can be individually turned on and
off, and key lookup starts from the top, and goes downwards until the
default layer to find a non-transparent key.
This allows one to reuse a partially transparent layer: set the default,
and the transparent parts will be reused. The numpad layer was updated
accordingly.
Having an interface to the layer switching things also makes it easier
to build other behaviour on top of these.
As part of the rework, layer handling was moved to a separate file, and into its
own, full-blown handler. Furthermore, we now use a single bit for all keymap
events.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Instead of registering the default handler late, always call it at the end if no
other handler took care of the event. This makes it less of an issue to order
`Keyboardio.use()` and `Keyboardio.setup()`.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Introduces the RESERVED bit, a bit reserved for plugins. If it is set, the core
handlers will not handle the event.
Also rearranges the SYNTHETIC bits, to make slightly more sense. In practice,
this means that LED_TOGGLE was promoted to a flag bit, under IS_INTERNAL.
The handler that deals with synthetic events was updated to look at the flag
bits in an order that does not cause confusion, and preparations were also made
to turn it into an independent handler on its own (but that step has not been
taken yet).
This is just groundwork to clean things up, and make the event flow easier to
follow.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Since macros and other injected keys do not clear the report, we need a way to
release keys. The new `release_key` function does just that, similar to how
`press_key` does it for key presses. It is called by the default event handler
when the `keyState` toggles off, and has the `INJECTED` bit set.
The reason behind this is that keys that will need this special treatment will
always be injected keys. And those injected keys that do not need this
treatment, can be handled by an event handler prior to the default.
This should fix the macros not releasing keys issue.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Instead of hardcoding the macro actions into the core firmware, use a
`macroAction` function that is marked weak. This makes it possible to override
the function from Sketches, and implement the handlers there.
While there, also made sure that the `macroAction` is always called, with
`keyState` argument appropriately set. With this, macro actions can trigger on
keyup, or while held, or anytime the implementor wants, not just on keypress.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Instead of having a previousState and a currentState, of which at most
two bits are used, use a single byte. This saves us a lot of code space,
and makes a number of things easier, too.
The helpers were redone as macros, since they are just bit checks now.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Instead of abusing `Key_NoKey`, use the new `INJECTED` flag in
`handle_key_event` and `handle_key_event_default` to check if the event
is an original, or an injected one.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
The primary reason for the move is to be able to disable mouse keys
completely, and not even compile them in. For this to work, it needs to
be in a separate library, otherwise it will always be included, even if
not active.
So, this patch turns mouse-keys into a simple plugin, included with the
core firmware! This makes the default event handler a bit simpler, the
code marginally smaller, and the feature completely optional.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Do the mappedKey lookup earlier, in handle_key_event, so that if any of
our handlers need to look at the mapped key, they do not have to look it
up themselves. This simplifies plugged hooks considerably, as they can
always assume that the mapped key they receive is correct. They still
receive enough information to do the lookup themselves, though, if they
ever need that.
Additionally, in handle_key_event_default, baseKey is only looked up if
mappedKey was NoKey. This is so that hooks can defer to this function,
via handle_key_event, setting their own mappedKey, without having to
worry about setting a row/col that would map to a special key on the
base layer.
Fixes#39.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
To make replacing work sanely, we first NULL out both the eventHandlers
and loopHooks arrays in the Keyboardio_ constructor. This allows the
replace functions to just run through the whole array, and either see
hook pointers there, or NULL. So they don't need to be afraid of garbage
being there.
This makes the replacing very easy: run through the array, and replace
the first occurrence of the old hook with the new. This further
simplifies addition: the old hook we pass in, will be NULL. If we run
out of space, it silently fails, like before.
Replacing hooks is important for cases where one wants to build features
that can be toggled off, or their behaviour otherwise changed at
run-time. In this case, the most efficent way is to replace the hook,
which is what these new helpers allow us to do.
This closes#36.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
There are scenarios where one would want to inject a keycode into the
event handler chain, restart the processing from scratch, but with a
keycode different than what the lookup would normally yield. For
example, with one-shot modifiers, a feature one may wish is to be able
to turn the one-shotness off, and have them act as normal modifiers.
This is easily done, if we can remove the one-shot markup, and let the
event handler process the resulting code as-is.
This makes that possible: in a custom event handler, just call
handle_key_event() with the first argument set to the desired code, and
the rest left unchanged. This makes it possible to inject events: not
just register keycodes with the HID, but inject synthetic events,
something much more powerful.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
This moves the layouts to the sketch directory, so that other sketches
can easily use a different keymap. In the process, not much had to be
changed, and a number of things still remain in the core that assume the
default keymap (such as the NUMPAD_KEYMAP thing in LEDControl.cpp), but
this is a first step.
The downside is that the keymap is no longer static, because that would
conflict with the extern declaration, and the NUMPAD_KEYMAP is a byte,
instead of a compile-time define.
Alltogether, the difference is small enough to be acceptable.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Having the default handler in the list by default prevents other things
to hook up before it. Add it in Keyboardio_::setup instead, so that
others have a chance to add themselves first.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Moved the library sources into src/, and the sketch into examples/. This
makes it easier to use the project as a library, and the default
firmware sketch shows up in Arduino IDE's Files/Examples menu. This in
turn, has a very neat side effect: an end user can start from this
example, and when they save it, it will be saved to their Sketchbook,
and the library can be updated independently, without having to worry
about conflicts.
Having the Sketch separate from the sources also paves the way for
moving the keymap there.
As far as Arduino IDE dependencies go: this requires Arduino IDE 1.6.7+,
the same minimum version required previously.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>