diff --git a/tests/features/events/keyboard-state/release-cleared/common.h b/tests/features/events/keyboard-state/release-cleared/common.h new file mode 100644 index 00000000..3ab385ca --- /dev/null +++ b/tests/features/events/keyboard-state/release-cleared/common.h @@ -0,0 +1,27 @@ +// -*- mode: c++ -*- + +/* Kaleidoscope - Firmware for computer input devices + * Copyright (C) 2021 Keyboard.io, Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once + +#include + +namespace kaleidoscope { +namespace testing { + +} // namespace testing +} // namespace kaleidoscope diff --git a/tests/features/events/keyboard-state/release-cleared/release-cleared.ino b/tests/features/events/keyboard-state/release-cleared/release-cleared.ino new file mode 100644 index 00000000..b3d4c0c5 --- /dev/null +++ b/tests/features/events/keyboard-state/release-cleared/release-cleared.ino @@ -0,0 +1,104 @@ +/* -*- mode: c++ -*- + * Copyright (C) 2021 Keyboard.io, Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include + +#include "./common.h" + +#undef min +#undef max +#include + +// *INDENT-OFF* +KEYMAPS( + [0] = KEYMAP_STACKED + ( + Key_A, ___, ___, ___, ___, ___, ___, + ShiftToLayer(1), ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, + ___, + + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, + ___ + ), + [1] = KEYMAP_STACKED + ( + Key_X, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, + ___, + + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, + ___ + ), +) +// *INDENT-ON* + +namespace kaleidoscope { +namespace plugin { + +class ConvertXtoY : public kaleidoscope::Plugin { + public: + EventHandlerResult onKeyswitchEvent(Key &key, KeyAddr key_addr, uint8_t key_state) { + if (keyToggledOn(key_state)) { + if (key == Key_X) + key = Key_Y; + } + // It should be impossible to get a `Key_X` at this point, because the + // previous block changes any `Key_X` to `Key_Y`, which results in the + // active keys cache storing that value. On subsequent cycles (while the key + // is still pressed), the `key` value should be `Key_Y`. + if (keyIsPressed(key_state) && key == Key_X) { + std::cerr << "t=" << Runtime.millisAtCycleStart() << ": " + << "Error: we shouldn't see a key with value `X`" << std::endl; + } + // When `Key_Y` toggles off, return `EVENT_CONSUMED`. Despite this, the + // active keys cache entry should be cleared. If it's not, then a subsequent + // press of the same key without the layer shift in effect will still result + // in `Key_Y` instead of `Key_A`. + if (keyToggledOff(key_state) && (key == Key_Y)) { + return EventHandlerResult::EVENT_CONSUMED; + } + return EventHandlerResult::OK; + } +}; + +} // namespace plugin +} // namespace kaleidoscope + +kaleidoscope::plugin::ConvertXtoY ConvertXtoY; + +KALEIDOSCOPE_INIT_PLUGINS(ConvertXtoY); + +void setup() { + Kaleidoscope.setup(); +} + +void loop() { + Kaleidoscope.loop(); +} diff --git a/tests/features/events/keyboard-state/release-cleared/sketch.json b/tests/features/events/keyboard-state/release-cleared/sketch.json new file mode 100644 index 00000000..43dc4c7e --- /dev/null +++ b/tests/features/events/keyboard-state/release-cleared/sketch.json @@ -0,0 +1,6 @@ +{ + "cpu": { + "fqbn": "keyboardio:virtual:model01", + "port": "" + } +} \ No newline at end of file diff --git a/tests/features/events/keyboard-state/release-cleared/test.ktest b/tests/features/events/keyboard-state/release-cleared/test.ktest new file mode 100644 index 00000000..d44f6d4c --- /dev/null +++ b/tests/features/events/keyboard-state/release-cleared/test.ktest @@ -0,0 +1,59 @@ +VERSION 1 + +KEYSWITCH A 0 0 +KEYSWITCH LAYER_SHIFT 1 0 + +# ============================================================================== +# Keyboard state array +NAME Keyboard state cleared + +RUN 10 ms + +PRESS A +RUN 1 cycle +EXPECT keyboard-report Key_A # Report should contain only `A` + +RUN 5 ms + +RELEASE A +RUN 1 cycle +EXPECT keyboard-report empty # Report should be empty + +RUN 5 ms + +# Press and hold `ShiftToLayer(1)`, changing the `A` key to `X` +PRESS LAYER_SHIFT +RUN 5 ms + +# Press `X`, which gets converted to `Y` by the `ConvertXtoY` plugin defined in +# the sketch. The plugin simply changes the value of the key, which causes it to +# get set to `Key_Y` in the keyboard state array. +PRESS A +RUN 1 cycle +EXPECT keyboard-report Key_Y # Report should contain only `Y` + +RUN 5 ms + +# Release the `X` key (on Layer 1), which has become a `Y` key in the keyboard +# state array. This should clear its entry. +RELEASE A +RUN 1 cycle +EXPECT keyboard-report empty # Report should be empty + +RUN 5 ms + +# Release `ShiftToLayer(1)`. This should restore the `A` key to its base layer +# value on subsequent presses, unless the Macros key gets "stuck" in the +# keyboard state array because it returns `EVENT_CONSUMED`. +RELEASE LAYER_SHIFT +RUN 5 ms + +PRESS A +RUN 1 cycle +EXPECT keyboard-report Key_A # Report should contain only `A` + +RUN 5 ms + +RELEASE A +RUN 1 cycle +EXPECT keyboard-report empty # Report should be empty