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..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 @@ -23,12 +26,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)` @@ -36,13 +62,48 @@ configuration method: > (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)` + +> 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.cpp b/plugins/Kaleidoscope-Escape-OneShot/src/kaleidoscope/plugin/Escape-OneShot.cpp index c9708cbf..832664d3 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,25 @@ 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_ && + // + // `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 90e8511b..b39c436c 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 @@ -20,24 +20,62 @@ #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 { + 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; + } + + friend class EscapeOneShotConfig; private: - static Key cancel_oneshot_key_; + struct Settings { + bool disabled; + Key cancel_oneshot_key; + }; + 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;