diff --git a/examples/Features/AppSwitcher/AppSwitcher.cpp b/examples/Features/AppSwitcher/AppSwitcher.cpp new file mode 100644 index 00000000..e75c94bf --- /dev/null +++ b/examples/Features/AppSwitcher/AppSwitcher.cpp @@ -0,0 +1,79 @@ +/* -*- mode: c++ -*- + * AppSwitcher -- A Kaleidoscope Example + * Copyright (C) 2021 Keyboardio, 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 . + */ + +#define KALEIDOSCOPE_HOSTOS_GUESSER 1 + +#include + +#include "AppSwitcher.h" + +namespace kaleidoscope { +namespace plugin { + +EventHandlerResult AppSwitcher::onKeyEvent(KeyEvent &event) { + // Ignore all key releases + if (keyToggledOff(event.state)) + return EventHandlerResult::OK; + + if (event.key == AppSwitcher_Next || event.key == AppSwitcher_Prev) { + bool add_shift_flag = false; + if (event.key == AppSwitcher_Prev) { + add_shift_flag = true; + } + + // For good measure: + event.state |= INJECTED; + + // If AppSwitcher was not already active, hold its modifier first. + if (!active_addr_.isValid()) { + if (::HostOS.os() == hostos::OSX) { + event.key = Key_LeftGui; + } else { + event.key = Key_LeftAlt; + } + Runtime.handleKeyEvent(event); + } + + // Clear the event's key address so we don't clobber the modifier. + event.addr.clear(); + event.key = Key_Tab; + if (add_shift_flag) + event.key.setFlags(SHIFT_HELD); + // Press tab + Runtime.handleKeyEvent(event); + // Change state to release; this will get processed when we return OK below. + event.state = WAS_PRESSED | INJECTED; + } else if (active_addr_.isValid()) { + // If any non-AppSwitcher key is pressed while AppSwitcher is active, that + // will close AppSwitcher instead of processing that keypress. We mask the + // address of the key that closed AppSwitcher so that its release doesn't + // have any effect. Then we turn the event for that key's press into an + // event for the release of the AppSwitcher's modifier key. + live_keys.mask(event.addr); + event.addr = active_addr_; + event.state = WAS_PRESSED | INJECTED; + event.key = live_keys[event.addr]; + // Turn off AppSwitcher: + active_addr_.clear(); + } + return EventHandlerResult::OK; +} + +} // namespace plugin +} // namespace kaleidoscope + +kaleidoscope::plugin::AppSwitcher AppSwitcher; diff --git a/examples/Features/AppSwitcher/Macros.h b/examples/Features/AppSwitcher/AppSwitcher.h similarity index 53% rename from examples/Features/AppSwitcher/Macros.h rename to examples/Features/AppSwitcher/AppSwitcher.h index 1099bb03..00de27a6 100644 --- a/examples/Features/AppSwitcher/Macros.h +++ b/examples/Features/AppSwitcher/AppSwitcher.h @@ -1,6 +1,6 @@ /* -*- mode: c++ -*- * AppSwitcher -- A Kaleidoscope Example - * Copyright (C) 2016-2018 Keyboardio, Inc. + * Copyright (C) 2021 Keyboardio, 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 @@ -17,13 +17,27 @@ #pragma once -#include +#include +#include "Kaleidoscope-Ranges.h" + +constexpr Key AppSwitcher_Next{kaleidoscope::ranges::SAFE_START}; +constexpr uint16_t _prev_val = AppSwitcher_Next.getRaw() + 1; +constexpr Key AppSwitcher_Prev{_prev_val}; + +namespace kaleidoscope { +namespace plugin { + +class AppSwitcher : public kaleidoscope::Plugin { + + public: + EventHandlerResult onKeyEvent(KeyEvent &event); + + private: + KeyAddr active_addr_ = KeyAddr::none(); -enum { - M_APPSWITCH, - M_APPCANCEL, }; -const macro_t *macroAppSwitch(uint8_t keyState); -const macro_t *macroAppCancel(uint8_t keyState); -void macroAppSwitchLoop(); +} // namespace plugin +} // namespace kaleidoscope + +extern kaleidoscope::plugin::AppSwitcher AppSwitcher; diff --git a/examples/Features/AppSwitcher/AppSwitcher.ino b/examples/Features/AppSwitcher/AppSwitcher.ino index ad46fefc..56f3c0ac 100644 --- a/examples/Features/AppSwitcher/AppSwitcher.ino +++ b/examples/Features/AppSwitcher/AppSwitcher.ino @@ -17,10 +17,10 @@ #include "Kaleidoscope.h" #include "Kaleidoscope-EEPROM-Settings.h" -#include "Kaleidoscope-Macros.h" #include "Kaleidoscope-HostOS.h" +#include "Kaleidoscope-Ranges.h" -#include "Macros.h" +#include "AppSwitcher.h" /* *INDENT-OFF* */ KEYMAPS( @@ -32,7 +32,7 @@ KEYMAPS( Key_PageDown, Key_Z, Key_X, Key_C, Key_V, Key_B, Key_Escape, Key_LeftControl, Key_Backspace, Key_LeftGui, Key_LeftShift, - M(M_APPSWITCH), + AppSwitcher_Next, 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, @@ -40,24 +40,13 @@ KEYMAPS( Key_skip, Key_N, Key_M, Key_Comma, Key_Period, Key_Slash, Key_Minus, Key_RightShift, Key_RightAlt, Key_Spacebar, Key_RightControl, - M(M_APPCANCEL) + AppSwitcher_Prev ), ) /* *INDENT-ON* */ -const macro_t *macroAction(uint8_t macroIndex, uint8_t keyState) { - switch (macroIndex) { - case M_APPSWITCH: - return macroAppSwitch(keyState); - case M_APPCANCEL: - return macroAppCancel(keyState); - } - return MACRO_NONE; -} - -KALEIDOSCOPE_INIT_PLUGINS(EEPROMSettings, - HostOS, - Macros); +KALEIDOSCOPE_INIT_PLUGINS(HostOS, + AppSwitcher); void setup() { Kaleidoscope.setup(); @@ -67,6 +56,5 @@ void setup() { } void loop() { - macroAppSwitchLoop(); Kaleidoscope.loop(); } diff --git a/examples/Features/AppSwitcher/Macros.cpp b/examples/Features/AppSwitcher/Macros.cpp deleted file mode 100644 index 9baaafa2..00000000 --- a/examples/Features/AppSwitcher/Macros.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- mode: c++ -*- - * AppSwitcher -- A Kaleidoscope Example - * Copyright (C) 2016-2018 Keyboardio, 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 . - */ - -#define KALEIDOSCOPE_HOSTOS_GUESSER 1 - -#include - -#include "Macros.h" - -namespace H = kaleidoscope::hostos; - -static bool appSwitchActive = false; - -const macro_t *macroAppSwitch(uint8_t keyState) { - appSwitchActive = true; - - // Key was just pressed, or is being held - if (keyIsPressed(keyState)) { - if (HostOS.os() == H::OSX) - return MACRO(Dr(Key_LeftGui), D(Tab)); - else - return MACRO(Dr(Key_LeftAlt), D(Tab)); - } - // Key was just released - if (keyToggledOff(keyState)) { - if (HostOS.os() == H::OSX) - return MACRO(U(Tab), Dr(Key_LeftGui)); - else - return MACRO(U(Tab), Dr(Key_LeftAlt)); - } - // otherwise we do nothing - return MACRO_NONE; -} - -const macro_t *macroAppCancel(uint8_t keyState) { - if (keyToggledOn(keyState)) - appSwitchActive = false; - return MACRO_NONE; -} - -void macroAppSwitchLoop() { - Key mod = Key_LeftAlt; - - if (HostOS.os() == H::OSX) - mod = Key_LeftGui; - - // if appSwitchActive is true, we continue holding Alt. - if (appSwitchActive) { - handleKeyswitchEvent(mod, UnknownKeyswitchLocation, IS_PRESSED); - } -}