diff --git a/plugins/Kaleidoscope-TopsyTurvy/src/kaleidoscope/plugin/TopsyTurvy.cpp b/plugins/Kaleidoscope-TopsyTurvy/src/kaleidoscope/plugin/TopsyTurvy.cpp index 774ae7f2..e587c7d2 100644 --- a/plugins/Kaleidoscope-TopsyTurvy/src/kaleidoscope/plugin/TopsyTurvy.cpp +++ b/plugins/Kaleidoscope-TopsyTurvy/src/kaleidoscope/plugin/TopsyTurvy.cpp @@ -21,53 +21,61 @@ namespace kaleidoscope { namespace plugin { -uint8_t TopsyTurvy::last_pressed_position_; -bool TopsyTurvy::is_shifted_; -bool TopsyTurvy::is_active_; +KeyAddr TopsyTurvy::tt_addr_ = KeyAddr::none(); +bool TopsyTurvy::shift_detected_ = false; -EventHandlerResult TopsyTurvy::onKeyswitchEvent(Key &mapped_key, KeyAddr key_addr, uint8_t key_state) { - - if (mapped_key == Key_LeftShift || - mapped_key == Key_RightShift) { - is_shifted_ = keyIsPressed(key_state); - if (is_active_) - return EventHandlerResult::EVENT_CONSUMED; - } - - if (mapped_key < ranges::TT_FIRST || mapped_key > ranges::TT_LAST) { - if (keyToggledOn(key_state) && (mapped_key < Key_LeftControl || mapped_key > Key_RightGui)) { - last_pressed_position_ = key_addr.toInt(); - } +EventHandlerResult TopsyTurvy::beforeEachCycle() { + // Clear the shift detection state before each scan cycle. + shift_detected_ = false; + return EventHandlerResult::OK; +} +EventHandlerResult TopsyTurvy::beforeReportingState() { + // If no TopsyTurvy key is active, there's nothing to do. + if (! tt_addr_.isValid()) return EventHandlerResult::OK; - } - is_active_ = keyIsPressed(key_state); - - if (keyToggledOn(key_state)) { - last_pressed_position_ = key_addr.toInt(); + // A TopsyTurvy key is active. That means we need to reverse the shift state, + // whether it was on or off. + if (shift_detected_) { + kaleidoscope::Runtime.hid().keyboard().releaseKey(Key_LeftShift); + kaleidoscope::Runtime.hid().keyboard().releaseKey(Key_RightShift); } else { - if (last_pressed_position_ != key_addr.toInt()) { - return EventHandlerResult::EVENT_CONSUMED; - } + kaleidoscope::Runtime.hid().keyboard().pressKey(Key_LeftShift); } + return EventHandlerResult::OK; +} - mapped_key.setRaw(mapped_key.getRaw() - ranges::TT_FIRST); - - // invert the shift state - if (!is_shifted_) { - mapped_key.setFlags(mapped_key.getFlags() | SHIFT_HELD); +EventHandlerResult TopsyTurvy::onKeyswitchEvent(Key &key, + KeyAddr key_addr, + uint8_t key_state) { + // If a modifer key (including combo modifiers, but not non-modifier keys with + // mod flags) is active, and it includes `shift` (either from its keycode or a + // mod flag), record that we detected an "intentional shift". + if (key.isKeyboardShift() && keyIsPressed(key_state)) + shift_detected_ = true; + + // If the active TopsyTurvy key toggles off, clear the stored address to + // record that. + if (keyToggledOff(key_state)) { + if (key_addr == tt_addr_) { + tt_addr_.clear(); + } return EventHandlerResult::OK; } - if (keyIsPressed(key_state)) { - kaleidoscope::Runtime.hid().keyboard().releaseKey(Key_LeftShift); - kaleidoscope::Runtime.hid().keyboard().releaseKey(Key_RightShift); - - return EventHandlerResult::OK; + if (keyToggledOn(key_state)) { + if (isTopsyTurvyKey(key)) { + // If a TopsyTurvy key toggles on, store its address to indicate that it's + // active, and decode its key value to store in the active keys cache. + tt_addr_ = key_addr; + key = Key(key.getRaw() - ranges::TT_FIRST); + } else { + // If any other key toggles on, clear the active TopsyTurvy address. + tt_addr_.clear(); + } } - - return EventHandlerResult::EVENT_CONSUMED; + return EventHandlerResult::OK; } } diff --git a/plugins/Kaleidoscope-TopsyTurvy/src/kaleidoscope/plugin/TopsyTurvy.h b/plugins/Kaleidoscope-TopsyTurvy/src/kaleidoscope/plugin/TopsyTurvy.h index bfd77c24..a1903615 100644 --- a/plugins/Kaleidoscope-TopsyTurvy/src/kaleidoscope/plugin/TopsyTurvy.h +++ b/plugins/Kaleidoscope-TopsyTurvy/src/kaleidoscope/plugin/TopsyTurvy.h @@ -29,12 +29,18 @@ class TopsyTurvy: public kaleidoscope::Plugin { public: TopsyTurvy(void) {} - EventHandlerResult onKeyswitchEvent(Key &mapped_key, KeyAddr key_addr, uint8_t key_state); + EventHandlerResult beforeEachCycle(); + EventHandlerResult beforeReportingState(); + EventHandlerResult onKeyswitchEvent(Key &key, KeyAddr key_addr, uint8_t key_state); + + static bool isTopsyTurvyKey(Key key) { + return (key >= ranges::TT_FIRST && + key <= ranges::TT_LAST); + } private: - static uint8_t last_pressed_position_; - static bool is_shifted_; - static bool is_active_; + static KeyAddr tt_addr_; + static bool shift_detected_; }; } }