From 4d1e59e769a0ffcb86611664d1e641a6fb482fb1 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Thu, 18 Nov 2021 12:27:52 +0100 Subject: [PATCH 1/3] EscapeOneShot: Make it possible to disable the plugin at run-time We want to make it possible to have the plugin in firmwares shipped by Chrysalis, but still have the functionality optional. To achieve this, we need to be able to toggle it on and off at will. We move both the existing `cancel_oneshot_key_` property, and the new toggle into a struct, which we will later make use of in the upcoming configuration plugin. Signed-off-by: Gergely Nagy --- .../kaleidoscope/plugin/Escape-OneShot.cpp | 13 ++++++-- .../src/kaleidoscope/plugin/Escape-OneShot.h | 30 ++++++++++++++++--- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.cpp b/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.cpp index c9708cbf..b1a53fb6 100644 --- a/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.cpp +++ b/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.cpp @@ -1,6 +1,6 @@ /* -*- mode: c++ -*- * Kaleidoscope-Escape-OneShot -- Turn ESC into a key that cancels OneShots, if active. - * Copyright (C) 2016-2020 Keyboard.io, Inc + * Copyright (C) 2016-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 @@ -24,14 +24,21 @@ namespace kaleidoscope { namespace plugin { -Key EscapeOneShot::cancel_oneshot_key_{Key_Escape}; +EscapeOneShot::Settings EscapeOneShot::settings_ = { + .disabled = false, + .cancel_oneshot_key = Key_Escape +}; EventHandlerResult EscapeOneShot::onKeyEvent(KeyEvent &event) { + // If we're disabled, just pass through. + if (settings_.disabled) + return EventHandlerResult::OK; + // We only act on an escape key (or `cancel_oneshot_key_`, if that has been // set) that has just been pressed, and not generated by some other // plugin. Also, only if at least one OneShot key is active and/or // sticky. Last, only if there are no OneShot keys currently being held. - if (event.key == cancel_oneshot_key_ && + if (event.key == settings_.cancel_oneshot_key && keyToggledOn(event.state) && !keyIsInjected(event.state) && ::OneShot.isActive()) { diff --git a/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.h b/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.h index 90e8511b..d94111db 100644 --- a/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.h +++ b/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.h @@ -1,6 +1,6 @@ /* -*- mode: c++ -*- * Kaleidoscope-Escape-OneShot -- Turn ESC into a key that cancels OneShots, if active. - * Copyright (C) 2016-2020 Keyboard.io, Inc + * Copyright (C) 2016-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 @@ -24,19 +24,41 @@ constexpr Key OneShotCancelKey {kaleidoscope::ranges::OS_CANCEL}; namespace kaleidoscope { namespace plugin { + class EscapeOneShot : public kaleidoscope::Plugin { public: EscapeOneShot(void) {} EventHandlerResult onKeyEvent(KeyEvent &event); - void setCancelKey(Key cancel_key) { - cancel_oneshot_key_ = cancel_key; + static void setCancelKey(Key cancel_key) { + settings_.cancel_oneshot_key = cancel_key; + } + static Key getCancelKey() { + return settings_.cancel_oneshot_key; + } + static void enable() { + settings_.disabled = false; + } + static void disable() { + settings_.disabled = true; + } + static void toggle() { + settings_.disabled = !settings_.disabled; + } + static bool isEnabled() { + return !settings_.disabled; } private: - static Key cancel_oneshot_key_; + struct Settings { + bool disabled; + Key cancel_oneshot_key; + }; + static Settings settings_; }; +}; + } } From f3604d3317a4edb017cafd9bddb1ac1d9c409294 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Thu, 18 Nov 2021 12:51:34 +0100 Subject: [PATCH 2/3] plugin/EscapeOneShot: Add an optional Config plugin The new plugin - EscapeOneShotConfig - allows one to configure the main EscapeOneShot plugin via Focus. To make this functionality optional, it is a separate plugin, still contained in the same library for ease of us. Documentation and example updated accordingly. Signed-off-by: Gergely Nagy --- .../Escape-OneShot/Escape-OneShot.ino | 11 +- plugins/Kaleidoscope-Escape-OneShot/README.md | 62 +++++++++- .../plugin/Escape-OneShot-Config.cpp | 107 ++++++++++++++++++ .../src/kaleidoscope/plugin/Escape-OneShot.h | 13 +++ 4 files changed, 188 insertions(+), 5 deletions(-) create mode 100644 plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot-Config.cpp diff --git a/examples/Keystrokes/Escape-OneShot/Escape-OneShot.ino b/examples/Keystrokes/Escape-OneShot/Escape-OneShot.ino index 5f6689ca..921d4d92 100644 --- a/examples/Keystrokes/Escape-OneShot/Escape-OneShot.ino +++ b/examples/Keystrokes/Escape-OneShot/Escape-OneShot.ino @@ -1,6 +1,6 @@ /* -*- mode: c++ -*- * Kaleidoscope-Escape-OneShot -- Turn ESC into a key that cancels OneShots, if active. - * Copyright (C) 2016, 2017, 2018 Keyboard.io, Inc + * Copyright (C) 2016-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 @@ -16,8 +16,10 @@ */ #include +#include #include #include +#include // *INDENT-OFF* KEYMAPS( @@ -61,8 +63,11 @@ KEYMAPS( ) // *INDENT-ON* -KALEIDOSCOPE_INIT_PLUGINS(OneShot, - EscapeOneShot); +KALEIDOSCOPE_INIT_PLUGINS(EEPROMSettings, + Focus, + OneShot, + EscapeOneShot, + EscapeOneShotConfig); void setup() { Kaleidoscope.setup(); diff --git a/plugins/Kaleidoscope-Escape-OneShot/README.md b/plugins/Kaleidoscope-Escape-OneShot/README.md index 8ce762f0..8debee44 100644 --- a/plugins/Kaleidoscope-Escape-OneShot/README.md +++ b/plugins/Kaleidoscope-Escape-OneShot/README.md @@ -23,12 +23,35 @@ void setup () { } ``` +If one wishes to configure the plugin at run-time via [Focus][plugin:focus], the +optional `EscapeOneShotConfig` plugin must also be enabled: + + [plugin:focus]: Kaleidoscope-FocusSerial.md + +```c++ +#include +#include +#include +#include +#include + +KALEIDOSCOPE_INIT_PLUGINS(EEPROMSettings, + Focus, + OneShot, + EscapeOneShot, + EscapeOneShotConfig); + +void setup () { + Kaleidoscope.setup (); +} +``` + The plugin only makes sense when using one-shot keys. ## Plugin methods -The plugin provides the `EscapeOneShot` object, which has one public -configuration method: +The plugin provides the `EscapeOneShot` object, which has the following public +configuration methods: ### `.setCancelKey(key)` @@ -39,10 +62,45 @@ configuration method: > modifiers), there is the special `OneShotCancelKey`, which will not > have any side effects. +### `.getCancelKey(key)` + +> Returns the `Key` value that will trigger deactivation of one-shot (including +> sticky) keys. + +### `.enable()`, `.disable()`, `.toggle()`, and `.isEnabled()` + +> Enables, disables, toggles, and returns the enabled state of the plugin, +> respectively. +> +> By default, the plugin starts enabled. + +## Focus commands + +The plugin provides two Focus commands: `escape_oneshot.enabled`, and +`escape_oneshot.cancel_key`. + +### `escape_oneshot.enabled [0|1]` + +> Without arguments, returns whether the plugin is enabled or not. +> +> With an argument, enables or disables it. + +### `escape_oneshot.cancel_key [keycode]` + +> Without an argument, returns the raw 16-bit keycode of the cancel key set. +> +> With an argument - a raw 16-bit keycode -, sets the cancel key to the one +> corresponding to the given code. + ## Dependencies * [Kaleidoscope-OneShot](Kaleidoscope-OneShot.md) +### Optional dependencies + +* [Kaleidoscope-EEPROM-Settings](Kaleidoscope-EEPROM-Settings.md) +* [Kaleidoscope-FocusSerial](Kaleidoscope-FocusSerial.md) + ## Further reading Starting from the [example][plugin:example] is the recommended way of getting diff --git a/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot-Config.cpp b/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot-Config.cpp new file mode 100644 index 00000000..422a9b2f --- /dev/null +++ b/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot-Config.cpp @@ -0,0 +1,107 @@ +/* -*- mode: c++ -*- + * Kaleidoscope-Escape-OneShot -- Turn ESC into a key that cancels OneShots, if active. + * Copyright (C) 2016-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 "kaleidoscope/plugin/Escape-OneShot.h" + +#include +#include + +#include "kaleidoscope/Runtime.h" + +namespace kaleidoscope { +namespace plugin { + +uint16_t EscapeOneShotConfig::settings_base_; + +EventHandlerResult EscapeOneShotConfig::onSetup() { + settings_base_ = ::EEPROMSettings.requestSlice(sizeof(EscapeOneShot::settings_)); + struct { + uint8_t b; + uint16_t w; + } checker; + + Runtime.storage().get(settings_base_, checker); + + // Check if we have an empty eeprom... + if (checker.b == 0xff && checker.w == 0xffff) { + // ...if the eeprom was empty, store the default settings. + Runtime.storage().put(settings_base_, EscapeOneShot::settings_); + Runtime.storage().commit(); + } + + Runtime.storage().get(settings_base_, EscapeOneShot::settings_); + return EventHandlerResult::OK; +} + +EventHandlerResult EscapeOneShotConfig::onNameQuery() { + return ::Focus.sendName(F("EscapeOneShot")); +} + +EventHandlerResult EscapeOneShotConfig::onFocusEvent(const char *command) { + enum { + ENABLED, + CANCEL_KEY + } subCommand; + + if (::Focus.handleHelp(command, PSTR("escape_oneshot.enabled\n" + "escape_oneshot.cancel_key"))) + return EventHandlerResult::OK; + + if (strncmp_P(command, PSTR("escape_oneshot."), 15) != 0) + return EventHandlerResult::OK; + if (strcmp_P(command + 15, PSTR("enabled")) == 0) + subCommand = ENABLED; + else if (strcmp_P(command + 15, PSTR("cancel_key")) == 0) + subCommand = CANCEL_KEY; + else + return EventHandlerResult::OK; + + switch (subCommand) { + case ENABLED: + if (::Focus.isEOL()) { + ::Focus.send(::EscapeOneShot.isEnabled()); + } else { + uint8_t v; + ::Focus.read(v); + if (v != 0) { + ::EscapeOneShot.enable(); + } else { + ::EscapeOneShot.disable(); + } + } + break; + + case CANCEL_KEY: + if (::Focus.isEOL()) { + ::Focus.send(::EscapeOneShot.getCancelKey()); + } else { + Key k; + ::Focus.read(k); + ::EscapeOneShot.setCancelKey(k); + } + break; + } + + Runtime.storage().put(settings_base_, EscapeOneShot::settings_); + Runtime.storage().commit(); + return EventHandlerResult::EVENT_CONSUMED; +} + +} // namespace plugin +} // namespace kaleidoscope + +kaleidoscope::plugin::EscapeOneShotConfig EscapeOneShotConfig; diff --git a/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.h b/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.h index d94111db..bd14ff21 100644 --- a/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.h +++ b/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.h @@ -50,6 +50,8 @@ class EscapeOneShot : public kaleidoscope::Plugin { return !settings_.disabled; } + friend class EscapeOneShotConfig; + private: struct Settings { bool disabled; @@ -57,9 +59,20 @@ class EscapeOneShot : public kaleidoscope::Plugin { }; static Settings settings_; }; + +class EscapeOneShotConfig : public Plugin { + public: + EventHandlerResult onSetup(); + EventHandlerResult onFocusEvent(const char *command); + EventHandlerResult onNameQuery(); + + + private: + static uint16_t settings_base_; }; } } extern kaleidoscope::plugin::EscapeOneShot EscapeOneShot; +extern kaleidoscope::plugin::EscapeOneShotConfig EscapeOneShotConfig; From ddad1305e27a52e801ad9e9632c1b8bf6fd17296 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Thu, 18 Nov 2021 18:57:55 +0100 Subject: [PATCH 3/3] EscapeOneShot: Always treat `Key_OneShotCancel` as cancel key To make it easier to use a dedicated cancel key, always treat it as a cancel key if seen, without having to set it via `setCancelKey()` on top. The key has no use apart from this one task, lets make it easier to use. Signed-off-by: Gergely Nagy --- plugins/Kaleidoscope-Escape-OneShot/README.md | 5 ++++- .../src/kaleidoscope/plugin/Escape-OneShot.cpp | 6 +++++- .../src/kaleidoscope/plugin/Escape-OneShot.h | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/plugins/Kaleidoscope-Escape-OneShot/README.md b/plugins/Kaleidoscope-Escape-OneShot/README.md index 8debee44..ce223255 100644 --- a/plugins/Kaleidoscope-Escape-OneShot/README.md +++ b/plugins/Kaleidoscope-Escape-OneShot/README.md @@ -5,6 +5,9 @@ effect - or act as the normal `Esc` key if none are active, or if any of them are still held. For those times when one accidentally presses a one-shot key, or change their minds. +Additionally, the special `Key_OneShotCancel` key will also count as a oneshot +cancel key, would one want a dedicated key for the purpose. + ## Using the plugin To use the plugin, one needs to include the header, and activate it. No further @@ -59,7 +62,7 @@ configuration methods: > (including sticky) keys. The default is to use `Key_Escape` (the > normal `Esc` key), but if you would rather have a dedicated key (so > that you can use `Key_Escape` in combination with one-shot -> modifiers), there is the special `OneShotCancelKey`, which will not +> modifiers), there is the special `Key_OneShotCancel`, which will not > have any side effects. ### `.getCancelKey(key)` diff --git a/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.cpp b/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.cpp index b1a53fb6..832664d3 100644 --- a/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.cpp +++ b/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.cpp @@ -38,7 +38,11 @@ EventHandlerResult EscapeOneShot::onKeyEvent(KeyEvent &event) { // set) that has just been pressed, and not generated by some other // plugin. Also, only if at least one OneShot key is active and/or // sticky. Last, only if there are no OneShot keys currently being held. - if (event.key == settings_.cancel_oneshot_key && + // + // `Key_OneShotCancel` will always count as an escape key, even if not + // explicitly set so. + if ((event.key == settings_.cancel_oneshot_key || + event.key == Key_OneShotCancel) && keyToggledOn(event.state) && !keyIsInjected(event.state) && ::OneShot.isActive()) { diff --git a/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.h b/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.h index bd14ff21..b39c436c 100644 --- a/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.h +++ b/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.h @@ -20,7 +20,10 @@ #include "kaleidoscope/Runtime.h" #include +// DEPRECATED: `OneShotCancelKey` doesn't match our normal naming, and should +// eventually be removed. constexpr Key OneShotCancelKey {kaleidoscope::ranges::OS_CANCEL}; +constexpr Key Key_OneShotCancel {kaleidoscope::ranges::OS_CANCEL}; namespace kaleidoscope { namespace plugin {