Skip to content

Instantly share code, notes, and snippets.

@gedankenexperimenter
Last active July 5, 2022 13:20
Show Gist options
  • Save gedankenexperimenter/db1150160524726c936c1e658ae1ddbd to your computer and use it in GitHub Desktop.
Save gedankenexperimenter/db1150160524726c936c1e658ae1ddbd to your computer and use it in GitHub Desktop.
Custom Kaleidoscope Plugin for `alt`+`A` to switch apps (on macOS), corrected
namespace kaleidoscope {
namespace plugin {
class AppSwitcher : public kaleidoscope::Plugin {
public:
static constexpr KeyAddr invalid_addr{KeyAddr::invalid_state};
AppSwitcher() {}
EventHandlerResult onKeyswitchEvent(Key &key,
KeyAddr key_addr,
uint8_t key_state) {
// When `alt` toggles off, reset.
if (keyToggledOff(key_state) && key_addr == alt_key_addr_) {
alt_key_addr_ = invalid_addr;
alt_is_cmd_ = false;
return EventHandlerResult::OK;
}
// When `alt` is pressed, record its address so we'll know to replace `A`
// with `tab` if that key is pressed while `alt` is still held.
if (keyToggledOn(key_state) && key == Key_LeftAlt) {
alt_key_addr_ = key_addr;
return EventHandlerResult::OK;
}
// If `alt` is held while `A` is pressed, change `alt` to `cmd`, and change
// `A` to `tab`.
if (key == Key_A && alt_key_addr_ != invalid_addr) {
// If this is the first time `A` has been pressed during this hold of
// `alt`, we need to change `alt` to `cmd`.
if (!alt_is_cmd_) {
// Temporarily store the address of the `alt` key, because it's about to
// get clobbered.
KeyAddr cmd_key_addr_ = alt_key_addr_;
// Call the key event handler as a courtesy to other plugins, so they'll
// know that the `alt` key was released. We don't need to bother
// specifying its key value; that gets populated automatically from the
// keymap cache entry. During the call to `handleKeyswitchEvent()`, this
// `onKeyswitchEvent()` will also get called, clearing `alt_key_addr_`.
handleKeyswitchEvent(Key_NoKey, cmd_key_addr_, WAS_PRESSED);
// Next, we send the information that a `cmd` (GUI) key toggled
// on. Again, this is mainly a courtesy, so other plugins won't miss an
// event and get confused. This time, we specify the key value,
// overriding the keymap, and causing that value to get cached for as
// long as the key is held.
handleKeyswitchEvent(Key_LeftGui, cmd_key_addr_, IS_PRESSED);
// Restore the saved address.
alt_key_addr_ = cmd_key_addr_;
// Store the fact that `alt` has now become `cmd` so we only execute
// this block at most once per press of the `alt` key.
alt_is_cmd_ = true;
}
// Change `A` to `tab`. We could call handleKeyswitchEvent() again here,
// so that plugins before this one would know which keycode would result,
// but it doesn't matter nearly as much for non-modifiers. This can be
// done in the same cycle as switching the modifier above because
// Kaleidoscope sends an extra report with just the modifier change before
// adding the `tab` character.
key = Key_Tab;
}
return EventHandlerResult::OK;
}
private:
KeyAddr alt_key_addr_;
bool alt_is_cmd_{false};
};
} // namespace plugin
} // namespace kaleidoscope
kaleidoscope::plugin::AppSwitcher AppSwitcher;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment