Instead of syncing right after updating, sync at the end of the loop. This
allows hooks (both loop and event handler hooks) to override LED colors, without
cooperation from the active LED effect, and without flickering.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Because we have `raw`, `rawKey` was confusing. Rename it to `keyCode` instead,
which better conveys what the byte is for.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
We want the `Keyboardio` object to be a singleton. If it is static, then
each library that gets compiled separately, and uses it in one way or
the other, will have a copy of it.
Making it extern, we'll only have one copy, as it should be.
I don't think there were any bugs caused by it being static, but it was
certainly a tiny bit of wasted code and memory.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
With the Layer code not using the hooks anymore, the Arduino builder will tell
the linker to remove any unreferenced code. As we are using dot_a_linkage, that
means that the hook functions will be removed due to being unreferenced before
plugins had a chance to reference them.
Add a dummy call in Keyboardio_::setup() to prevent this case.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
The layer handling is a core functionality, it should be active at all times,
and should be at the very end, before the default event handler. Otherwise there
may be ordering issues, when a plugin wants to return layer keys from its own
event handler.
This also saves us a couple of bytes of both code and data, as an additional
bonus!
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
This allows to call make with `ARDUINO_PATH=/custom/install/loc make` to avoid
having to modify the Makefile when the arduino components are installed in non
standard installation paths.
Makes it obvious when one forgets to close the arguments with a sentinel, by
giving the compiler a hint.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
When trying to update the LEDs, do not unconditionally call `modes[mode]->init`
and `modes[mode]->update`: we may have no effects installed. This change stops
the firmware from crashing with an NPE if no LED effects are enabled.
Also sets mode and previousMode to zero in the constructor, so we start with a
deterministic state.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
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>
Some behaviour would benefit from knowing the last report, some would want a
clear report and a way to pre-fill the next one. For this reason, we need two
places to call loop hooks from: one after scanning the matrix and updating LEDs,
and another after sending and clearing the report.
To save space and sanity, we call the same hooks twice, but the second time, we
set the `postClear` flag, which is false the first time.
All users have been updated.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
This function registers the layer handler, move it up, before Keyboardio.use, so
it will have a chance to run before the other handlers.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
To make keymaps look nicer, easier to read, introduce the `___` and `XXX`
aliases. The former is an alias to `Key_Transparent`, the latter to `Key_NoKey`.
The `genetare_keymaps.pl` tool was updated to support these, too, with the
additional functionality, that all strings that are made up entirely of
underscore or Xes, and are two or more characters long, will be treated as
`___`/`XXX`, respectively. This makes it possible to space keys in a nicer way
in the source layout files.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
`keymapEntry.rawKey` contains the target layer, but offset by
`MOMENTARY_OFFSET`. That value must be subtracted from the value before
comparing it to anything, or switching to another layer.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
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>
The mousekey handler was way too eager, and captured events that were not meant
to be handled by it, like the `a` key. This has been fixed by removing the
`KEY_MOUSE_CENTER` bit, and replacing it with `KEY_MOUSE_BUTTON`. That way,
everything fits into the `IS_MOUSE_KEY` flag bit.
While there, also fixed the id of the right mouse button.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
The macro handler should only catch things that were meant to be its stuff, and
should only act on keypress, not all kinds of key events.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
We can't register hooks from constructors, because there is no guaranteed order
in which the objects will be created. So it may well happen that the Keyboardio
object gets created later, and zeroes out everything. Or it gets created first,
and registers the default handler as the first one, making all the others
pointless.
Instead, we create a KeyboardioPlugin class, that has a `begin` method. This is
responsible for setting up the hooks and whatnot. To make things simpler (for
some values of simple), a `Keyboardio.use` method is introduced, which, when
given a NULL-terminated list of plugin object pointers, will call the begin
method of each.
All LED effects and other plugins that used to register a static object now use
an extern, and had their initialization moved to the `begin` method.
The end result is not the nicest thing, but it works. We can try figuring out
something nicer later.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
If a key in the layout has parens, leave it there as-is. This makes it a
lot easier to have macros and whatnot in the layout: one can just use
M(0) and the like.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Wraps the value LCTRL & friends in parens, so that they can be easily passed on
to other macros without the compiler getting confused.
Also moved the definition up, just below the _HELD bits, so that these macros
can be used for other key definitions, such as `Key_Pipe`, and so on.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Add a number of helper macros that aid in constructing the Key code for
keys with modifiers held. These can, of course, be embedded in each
other, so to have a key on the keymap that has all currently supported
modifiers pressed, along with `X`, one would write:
`LCTRL(LALT(RALT(LSHIFT(LGUI(X)))))`
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Add a `MACRODOWN` convenience macro, that will only run the given macro
when the key toggled on. It assumes that it is called from a function
with a `keyState` argument. If the key is not pressed, the macro will
evaluate to `MACRO_NONE`.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
`Dr`, `Ur`, and `Tr` are similar to the already existing `D`, `U`, and
`T` helpers, but they do not prefix their argument with `Key_`. This
makes it a lot easier to create macros that use custom key codes.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Instead of calling loop hooks before anything else, including scanning
the matrix, call it after all that, at the end of `Keyboardio_::loop()`.
This is less surprising, and should not have any ill side-effects,
either.
(Based on a discussion with @obra on IRC.)
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Keys that have the IS_INTERNAL flag set can also have the same bit set as the
IS_MACRO bit, yet, we do not want to handle those as if they were macros. So
teach `handleMacroEvent` to skip keys with that bit set.
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>