From 561907db576a5216ae100a166c953cbacac5cc8e Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Thu, 23 Dec 2021 12:28:27 -0500 Subject: [PATCH 1/2] Add ShiftBlocker example plugin This mini plugin is an example of how to suppress a held `shift` key from a Macros sequence. In this case, it's to enable a macro that types an accented character using a dead key (where the dead key must be entered without the `shift` modifier held). Signed-off-by: Michael Richters --- .../Features/ShiftBlocker/ShiftBlocker.ino | 106 ++++++++++++++++++ examples/Features/ShiftBlocker/sketch.json | 6 + 2 files changed, 112 insertions(+) create mode 100644 examples/Features/ShiftBlocker/ShiftBlocker.ino create mode 100644 examples/Features/ShiftBlocker/sketch.json diff --git a/examples/Features/ShiftBlocker/ShiftBlocker.ino b/examples/Features/ShiftBlocker/ShiftBlocker.ino new file mode 100644 index 00000000..46770e8c --- /dev/null +++ b/examples/Features/ShiftBlocker/ShiftBlocker.ino @@ -0,0 +1,106 @@ +/* -*- mode: c++ -*- + * ShiftBlocker -- A Kaleidoscope Example + * Copyright (C) 2016-2022 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 "Kaleidoscope.h" +#include "Kaleidoscope-Macros.h" + +/* *INDENT-OFF* */ +KEYMAPS( + [0] = KEYMAP_STACKED + ( + Key_NoKey, Key_1, Key_2, Key_3, Key_4, Key_5, Key_NoKey, + Key_Backtick, Key_Q, Key_W, Key_E, Key_R, Key_T, Key_Tab, + Key_PageUp, Key_A, Key_S, Key_D, Key_F, Key_G, + Key_PageDown, Key_Z, Key_X, Key_C, Key_V, Key_B, Key_Escape, + + Key_LeftControl, Key_Backspace, Key_LeftGui, Key_LeftShift, + M(0), + + Key_skip, Key_6, Key_7, Key_8, Key_9, Key_0, Key_skip, + Key_Enter, Key_Y, Key_U, Key_I, Key_O, Key_P, Key_Equals, + Key_H, Key_J, Key_K, Key_L, Key_Semicolon, Key_Quote, + Key_skip, Key_N, Key_M, Key_Comma, Key_Period, Key_Slash, Key_Minus, + + Key_RightShift, Key_RightAlt, Key_Spacebar, Key_RightControl, + M(0) + ), +) +/* *INDENT-ON* */ + +namespace kaleidoscope { +namespace plugin { + +// When activated, this plugin will suppress any `Shift` key (including modifier +// combos with `Shift`) before it's added to the HID report. +class ShiftBlocker : public Plugin { + + public: + EventHandlerResult onAddToReport(Key key) { + if (active_ && key.isKeyboardShift()) + return EventHandlerResult::ABORT; + return EventHandlerResult::OK; + } + + void enable() { + active_ = true; + } + void disable() { + active_ = false; + } + + private: + bool active_{false}; + +}; + +} // namespace plugin +} // namespace kaleidoscope + +kaleidoscope::plugin::ShiftBlocker ShiftBlocker; + +const macro_t *macroAction(uint8_t macro_id, KeyEvent &event) { + if (keyToggledOn(event.state)) { + switch (macro_id) { + case 0: + // First, enable ShiftBlocker to suppress any held `Shift` key(s). + ShiftBlocker.enable(); + // Tap `AltGr` + `7` to activate the grave accent dead key. + Macros.tap(RALT(Key_7)); + // Disable ShiftBlocker so it won't affect the `E` event. + ShiftBlocker.disable(); + // Change the Macros key into a plain `E` key before its press event is + // processed. + event.key = Key_E; + break; + } + } + return MACRO_NONE; +} + +KALEIDOSCOPE_INIT_PLUGINS(Macros, + ShiftBlocker); + +void setup() { + Kaleidoscope.setup(); + // Uncomment to manually set the OS, as Kaleidoscope will not autodetect it. + // (Possible values are in HostOS.h.) + // HostOS.os(kaleidoscope::hostos::LINUX); +} + +void loop() { + Kaleidoscope.loop(); +} diff --git a/examples/Features/ShiftBlocker/sketch.json b/examples/Features/ShiftBlocker/sketch.json new file mode 100644 index 00000000..884ed009 --- /dev/null +++ b/examples/Features/ShiftBlocker/sketch.json @@ -0,0 +1,6 @@ +{ + "cpu": { + "fqbn": "keyboardio:avr:model01", + "port": "" + } +} From ebad8940fb799a5cf9d045856749904977cd9743 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Thu, 23 Dec 2021 12:27:42 -0500 Subject: [PATCH 2/2] Add testcases for ShiftBlocker example plugin Signed-off-by: Michael Richters --- .../Macros/shift-blocker/shift-blocker.ino | 99 +++++++++++++++++++ .../plugins/Macros/shift-blocker/sketch.json | 6 ++ tests/plugins/Macros/shift-blocker/test.ktest | 55 +++++++++++ 3 files changed, 160 insertions(+) create mode 100644 tests/plugins/Macros/shift-blocker/shift-blocker.ino create mode 100644 tests/plugins/Macros/shift-blocker/sketch.json create mode 100644 tests/plugins/Macros/shift-blocker/test.ktest diff --git a/tests/plugins/Macros/shift-blocker/shift-blocker.ino b/tests/plugins/Macros/shift-blocker/shift-blocker.ino new file mode 100644 index 00000000..bcc16998 --- /dev/null +++ b/tests/plugins/Macros/shift-blocker/shift-blocker.ino @@ -0,0 +1,99 @@ +/* -*- 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 + +// *INDENT-OFF* +KEYMAPS( + [0] = KEYMAP_STACKED + ( + M(0), ___, ___, ___, ___, ___, ___, + Key_LeftShift, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + + ___, ___, ___, ___, + ___, + + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + + ___, ___, ___, ___, + ___ + ), +) +// *INDENT-ON* + +// ShiftBlocker plugin +namespace kaleidoscope { +namespace plugin { + +// When activated, this plugin will suppress any `Shift` key (including modifier +// combos with `Shift`) before it's added to the HID report. +class ShiftBlocker : public Plugin { + public: + EventHandlerResult onAddToReport(Key key) { + if (active_ && key.isKeyboardShift()) + return EventHandlerResult::ABORT; + return EventHandlerResult::OK; + } + void enable() { + active_ = true; + } + void disable() { + active_ = false; + } + + private: + bool active_{false}; +}; + +} // namespace kaleidoscope +} // namespace plugin + +kaleidoscope::plugin::ShiftBlocker ShiftBlocker; + +const macro_t *macroAction(uint8_t macro_id, KeyEvent &event) { + if (keyToggledOn(event.state)) { + switch (macro_id) { + case 0: + // First, enable ShiftBlocker to suppress any held `Shift` key(s). + ShiftBlocker.enable(); + // Tap `AltGr` + `7` to activate the grave accent dead key. + Macros.tap(RALT(Key_7)); + // Disable ShiftBlocker so it won't affect the `E` event. + ShiftBlocker.disable(); + // Change the Macros key into a plain `E` key before its press event is + // processed. + event.key = Key_E; + break; + } + } + return MACRO_NONE; +} + +KALEIDOSCOPE_INIT_PLUGINS(Macros, ShiftBlocker); + +void setup() { + Kaleidoscope.setup(); +} + +void loop() { + Kaleidoscope.loop(); +} diff --git a/tests/plugins/Macros/shift-blocker/sketch.json b/tests/plugins/Macros/shift-blocker/sketch.json new file mode 100644 index 00000000..8cc86922 --- /dev/null +++ b/tests/plugins/Macros/shift-blocker/sketch.json @@ -0,0 +1,6 @@ +{ + "cpu": { + "fqbn": "keyboardio:virtual:model01", + "port": "" + } +} diff --git a/tests/plugins/Macros/shift-blocker/test.ktest b/tests/plugins/Macros/shift-blocker/test.ktest new file mode 100644 index 00000000..5ff46482 --- /dev/null +++ b/tests/plugins/Macros/shift-blocker/test.ktest @@ -0,0 +1,55 @@ +VERSION 1 + +KEYSWITCH M_0 0 0 +KEYSWITCH SHIFT 1 0 + +# ============================================================================== +NAME Macro without shift + +RUN 5 ms +PRESS M_0 +RUN 1 cycle +EXPECT keyboard-report Key_RightAlt # Report should contain only `AltGr` +EXPECT keyboard-report Key_RightAlt Key_7 # Report should contain `AltGr` & `7` +EXPECT keyboard-report Key_RightAlt # Report should contain only `AltGr` +EXPECT keyboard-report empty # Report should be empty +EXPECT keyboard-report Key_E # Report should contain only `E` + +RUN 5 ms +RELEASE M_0 +RUN 1 cycle +EXPECT keyboard-report empty # Report should be empty + +RUN 5 ms +EXPECT no keyboard-report + +# ============================================================================== +NAME Macro with shift + +RUN 5 ms +PRESS SHIFT +RUN 1 cycle +EXPECT keyboard-report Key_LeftShift # Report should contain `shift` + +RUN 5 ms +PRESS M_0 +RUN 1 cycle +EXPECT keyboard-report Key_RightAlt # Report should contain only `AltGr` +EXPECT keyboard-report Key_RightAlt Key_7 # Report should contain `AltGr` & `7` +EXPECT keyboard-report Key_RightAlt # Report should contain only `AltGr` +EXPECT keyboard-report empty # Report should be empty +EXPECT keyboard-report Key_LeftShift # Report should contain only `shift` +EXPECT keyboard-report Key_LeftShift Key_E # Report should contain `shift` & `E` + +RUN 5 ms +RELEASE M_0 +RUN 1 cycle +EXPECT keyboard-report Key_LeftShift # Report should contain only `shift` + +RUN 5 ms +RELEASE SHIFT +RUN 1 cycle +EXPECT keyboard-report empty # Report should be empty + +RUN 5 ms +EXPECT no keyboard-report