This (hopefully) makes layer changes more intuitive for users, and more
straightforward to explain and reason about. I believe this is a natural
extension of the activation-order layer stack, and away from the fixed-order
stack of old.
Specifically, it changes things so that layer lock keys will deactivate the
target layer if it is at the top of the active layer stack, but otherwise it
will bring the target layer to the top of the stack, regardless of whether or
not it was previously active. This ought to provide less surprising behaviour
in the case where a layer was active, but hidden (possibly for long enough that
the user can't recall its status). Pressing the layer lock key is now
guaranteed to produce a user-visible change (unless the target layer is 100%
transparent).
Layer shift behaviour is also changed, but not quite in the same way. A layer
shift key will now activate the target layer, as before, but pressing a second
layer shift key for the same target layer won't bring the target layer to the
top of the stack. The idea is that pressing a second identical layer shift
should be interpreted as a continuation of the already-active shift, probably so
that the user can change hands. A user could still forget about a shifted
layer, but it would have to be a sticky OneShot layer shift, so I think this is
reasonable.
The major change is that locked and shifted layers are now tracked separately on
the layer stack (using an offset), which means that locking a layer, then
pressing and releasing a layer shift key for that layer will not result in the
layer being unlocked.
Closes#1009
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
There was a call to `memmove()` call that shifted one extra byte of memory
whenever a layer was deactivated. I don't think that `memmove()` would actually
overwrite the source byte, so it shouldn't have any visible effect, but this is
more correct.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
A number of devices declared the bootloader in their device properties as
`BootLoader`, while the base class, and anything using it, was looking for
`Bootloader`. This resulted in these devices using the default, dummy
bootloader, rather than the one we intended to set.
This patch corrects that, and everything's using `Bootloader` now, including the
documentation.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
`kaleidoscope::driver::storage::AVREEPROM` wasn't implementing its own
`isSliceUninitialized()` method, and relied on the Base class to do so. However,
since we're not using `virtual` methods, the base class was using
`Base::read()` (which always returns 0) rather than `AVREEPROM::read()`, so
`isSliceUninitialized()` always returned false.
To fix this, we implement the function in `AVREEPROM`, and let the default
implementation in Base always return false.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
The `::isSliceUninitialized()` method is required by the Base flash driver
class, but `GD32Flash` did not implement it. While the Base class does so,
`GD32Flash` is subclassing `EEPROMClass`, rather than `storage::Base`, for
historical and technical reasons. As such, we need to implement this method
ourselves.
We could probably use multiple inheritance, but I feel that would be more
trouble than its worth.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
The `TEST()` macro defined in `macro_helpers.h` shared a name with a critical
macro used by gtest code in the simulator, making simulator code very sensitive
to the order of header includes, with rather unhelpful error messages when it
failed. This change renames the offending macro, and a related one, for good
measure. Neither renamed macro was directly used by any Kaleidoscope code, so
this doesn't affect any APIs.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
This is the result of running the `include-what-you-use` wrapper, followed by
the `clang-format` wrapper on the Kaleidoscope codebase. It is now safe to use
both without needed any manual corrections after the fact, but it's still
necessary to run clang-format after IWYU, because the two differ in the way they
indent comments after header files.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
The class we're deriving from - `FlashAsEEPROM`'s `EEPROMClass` - already has a
`commit()` method, we do not need our own in the child class, especially not
when all it does is call the parent.
We previously added this call because in the original implementation of the
driver, we had an empty `commit()`. The correct fix is to remove the override,
rather than reimplement the inheritance.
Spotted by @obra, thanks!
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Before doing anything else, initialize the device, so that whatever the rest of
the hooks we'll call do, they'll be able to rely on an initialized device.
Thanks to @obra for catching this, and proposing the patch!
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
There are a number of places in our code where clang-format tries too hard, and
destroys human readability, so I protected them with `clang-format off`
directives.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
First, we add an `uinitialized_byte` prop to `BaseProps`, so implementations
that don't use `0xff` as default can set it to whatever they use. Do keep in
mind that plenty of code still assumes `0xff` is the uninitialized byte, but
this way we have a starting point.
Then, we add an `isSliceUninitialized()` function, which checks whether a given
slice is completely made up from uninitialized bytes or not.
Fixes#1145.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This standardizes namespace closing brackets for namespace blocks. Each one is
on its own line, with a comment clearly marking which namespace it closes.
Consecutive lines closing namespace blocks have no whitespace between them, but
there is one blank line before and after a set of namespace block closing lines.
To generate the namespace comments, I used clang-format, with
`FixNamespaceComments: true`. But since clang-format can't exactly duplicate
our astyle formatting, it made lots of other changes, too. To isolate the
namespace comments from the other formatting changes, I first ran clang-format
with `FixNamespaceComments: false`, committed those changes, then ran it again
to generate the namespace comments. Then I stashed the namespace comments,
reset `HEAD` to remove the other changes, applied the stashed namespace
comments, and committed the results (after examining them and making a few minor
adjustments by hand).
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
I ran `include-what-you-use` wherever possible, and made a number of manual
changes required to get things working with the new header organization.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
By specifying the type of the `EventHandlerResult` enum as `uint8_t`, it only
takes up one byte instead of two, saving a significant amout of PROGMEM.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
This removes the pre-`KeyEvent` handler hooks for `onKeyswitchEvent()` and
`beforeReportingState()`. Any third-party plugins that still use either should
be updated to use the new handlers instead.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
This removes all the core code that called the pre-`KeyEvent` hook functions
`onKeyswitchEvent(key, addr, state)` and `beforeReportingState()`. Any plugins
that were still using these functions should use the newer equivalents instead:
`onKeyEvent(event)` & `beforeReportingState(event)`.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
This removes the `key_events.*` files that once contained the main
`handleKeyswitchEvent()` function, and all references to it. Because
`key_events.h` was included in the main `Kaleidoscope.h` header file,
`key_defs.h` and `keyswitch_state.h` were added to that header so that other
code that relies on those things being included via `Kaleidoscope.h` will
continue to work.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
This function was mainly intended for internal use by Kaleidoscope's event
handling functions. The logic that it used to provide is now handled by
`Runtime.handleKeyEvent()`, and it is not generally necessary or recommended for
plugin or sketch code to directly modify HID reports any longer.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
This removes several vestigial functions from the `Layer` class:
- `.handleKeymapKeyswitchEvent()` & `.eventHandler()`, which have been replaced
with the `.handleLayerKeyEvent()` function that operates on `KeyEvent` objects.
- `.lookup()`, which has been replaced by either `Runtime.lookupKey()` or
`Layer.lookupOnActiveLayer()`, depending on the specific purpose.
- `.updateLiveCompositeKeymap()`, which referred to a structure that has been
replaced. `live_keys.activate()` serves a similar purpose, but in most cases
shouldn't be called directly by user code.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
Storage must be page aligned and must span full pages. Adjust the default
storage size accordingly, so it is a multiple of 4096.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
The commit method of the GD32Flash storage driver was accidentally left empty,
disabling the functionality. Call the parent's commit method to restore it.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This change prevents `KeyAddrEventQueue::remove()` from shifting values in
memory out of bounds of its arrays if `shift()` is called on an empty queue. It
also adds a check to be sure that the entry removed is in the queue.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>