Merge pull request #982 from gedankenexperimenter/f/core.key-utils

Add common utility methods for `Key` & `KeyAddr` classes
pull/988/head
Jesse Vincent 4 years ago committed by GitHub
commit d2e9a113fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -26,6 +26,52 @@
#include "kaleidoscope/key_defs_aliases.h" #include "kaleidoscope/key_defs_aliases.h"
// -----------------------------------------------------------------------------
// Constant keycode values
#define HID_FIRST_KEY HID_KEYBOARD_NO_EVENT
#define HID_LAST_KEY HID_KEYPAD_HEXADECIMAL
#define HID_KEYBOARD_FIRST_MODIFIER HID_KEYBOARD_LEFT_CONTROL
#define HID_KEYBOARD_LAST_MODIFIER HID_KEYBOARD_RIGHT_GUI
// -----------------------------------------------------------------------------
// Constant flags values
#define KEY_FLAGS B00000000
#define CTRL_HELD B00000001
#define LALT_HELD B00000010
#define RALT_HELD B00000100
#define SHIFT_HELD B00001000
#define GUI_HELD B00010000
#define SYNTHETIC B01000000
#define RESERVED B10000000
// we assert that synthetic keys can never have keys held, so we reuse the _HELD bits
#define IS_SYSCTL B00000001
#define IS_INTERNAL B00000010
#define SWITCH_TO_KEYMAP B00000100
#define IS_CONSUMER B00001000
// HID Usage Types: Because these constants, like the ones above, are
// used in the flags byte of the Key class, they can't overlap any of
// the above bits. Nor can we use `SYNTHETIC` and `RESERVED` to encode
// the HID usage type of a keycode, which leaves us with only two
// bits. Since we don't currently do anything different based on HID
// usage type, these are currently all set to zeroes.
#define HID_TYPE_CA B00000000
#define HID_TYPE_CL B00000000
#define HID_TYPE_LC B00000000
#define HID_TYPE_MC B00000000
#define HID_TYPE_NARY B00000000
#define HID_TYPE_OOC B00000000
#define HID_TYPE_OSC B00000000
#define HID_TYPE_RTC B00000000
#define HID_TYPE_SEL B00000000
#define HID_TYPE_SV B00000000
// Mask defining the allowed usage type flag bits:
#define HID_TYPE_MASK B00110000
// =============================================================================
namespace kaleidoscope { namespace kaleidoscope {
class Key { class Key {
@ -121,10 +167,84 @@ class Key {
pgm_read_byte(&(this->getFlags()))}; pgm_read_byte(&(this->getFlags()))};
} }
// ---------------------------------------------------------------------------
// Builtin Key variant test functions
//
// The following functions return `true` if the `key` parameter is of the
// corresponding HID type (Keyboard, Consumer Control, or System Control).
constexpr bool isKeyboardKey() {
return ((flags_ & (RESERVED | SYNTHETIC)) == 0);
}
constexpr bool isSystemControlKey() {
return ((flags_ & system_control_mask_) == (SYNTHETIC | IS_SYSCTL));
}
constexpr bool isConsumerControlKey() {
return ((flags_ & consumer_control_mask_) == (SYNTHETIC | IS_CONSUMER));
}
// Not a HID type, but also a builtin `Key` variant.
constexpr bool isLayerKey() {
return (flags_ == (SYNTHETIC | SWITCH_TO_KEYMAP));
}
// ---------------------------------------------------------------------------
// Additional utility functions for builtin `Key` variants
//
// An "intentional" Keyboard modifier is any HID Keyboard key that has a
// keycode byte corresponding to a modifier. This includes combination
// modifier keys like `LSHIFT(Key_RightAlt)` and `Key_Meh`. It will not match
// a key with only modifier flags (e.g. `LCTRL(RALT(Key_NoKey))`); this is an
// intentional feature so that plugins can distinguish between the two.
constexpr bool isKeyboardModifier() {
return (isKeyboardKey() &&
(keyCode_ >= HID_KEYBOARD_FIRST_MODIFIER &&
keyCode_ <= HID_KEYBOARD_LAST_MODIFIER));
}
// It's important to distinguish between "intentional" modifiers and
// "incidental" modifiers (non-modifier keys with a modifier flag). The
// following test matches any Keyboard modifier key that includes a `shift`
// keycode either in its keycode byte or in its flags. In this way, we treat
// all of the modifiers in a combination modifier key the same. There should
// be no difference between `LSHIFT(Key_RightAlt)` and `RALT(Key_LeftShift)`.
//
// The `shift` modifiers are special even among the Keyboard modifier keys
// (and several plugins single them out for this reason), because they are
// used in a conceptually different way: to get a different symbol in the
// output. We don't normally think "type `shift`+`1`"; we think "type `!`".
constexpr bool isKeyboardShift() {
return (isKeyboardModifier() &&
((keyCode_ == HID_KEYBOARD_LEFT_SHIFT ||
keyCode_ == HID_KEYBOARD_RIGHT_SHIFT) ||
((flags_ & SHIFT_HELD) != 0)));
}
// Layer shift keys are conceptually similar to Keyboard modifier keys in that
// they are used chorded to change the result of typing those other
// keys. They're even more similar to `shift` keys. For both reasons, it's
// worth singling them out.
constexpr bool isLayerShift() {
return (isLayerKey() &&
(keyCode_ >= LAYER_SHIFT_OFFSET));
}
private: private:
uint8_t keyCode_; uint8_t keyCode_;
uint8_t flags_; uint8_t flags_;
// -----------------------------------------------------------------------------
// Useful constants for the `Key` object's `flags` byte.
// There are two bits available for Consumer Control & System Control keys to
// use for storing information about the HID Usage Type. These bits are ones
// in the following mask.
static constexpr uint8_t hid_type_mask_ = HID_TYPE_MASK;
// The bits that must match exactly when checking if a `Key` value corresponds
// to a System Control keycode.
static constexpr uint8_t system_control_mask_ = ~hid_type_mask_;
// The bits that must match exactly when checking if a `Key` value corresponds
// to a Consumer Control keycode.
static constexpr uint8_t consumer_control_mask_ = (RESERVED | SYNTHETIC | IS_CONSUMER);
}; };
static_assert(sizeof(Key) == 2, "sizeof(Key) changed"); static_assert(sizeof(Key) == 2, "sizeof(Key) changed");
@ -154,82 +274,18 @@ constexpr Key addFlags(Key k, uint8_t add_flags) {
typedef kaleidoscope::Key Key; typedef kaleidoscope::Key Key;
typedef kaleidoscope::Key Key_; typedef kaleidoscope::Key Key_;
#define KEY_FLAGS B00000000
#define CTRL_HELD B00000001
#define LALT_HELD B00000010
#define RALT_HELD B00000100
#define SHIFT_HELD B00001000
#define GUI_HELD B00010000
#define SYNTHETIC B01000000
#define RESERVED B10000000
#define LCTRL(k) kaleidoscope::addFlags(CONVERT_TO_KEY(k), CTRL_HELD) #define LCTRL(k) kaleidoscope::addFlags(CONVERT_TO_KEY(k), CTRL_HELD)
#define LALT(k) kaleidoscope::addFlags(CONVERT_TO_KEY(k), LALT_HELD) #define LALT(k) kaleidoscope::addFlags(CONVERT_TO_KEY(k), LALT_HELD)
#define RALT(k) kaleidoscope::addFlags(CONVERT_TO_KEY(k), RALT_HELD) #define RALT(k) kaleidoscope::addFlags(CONVERT_TO_KEY(k), RALT_HELD)
#define LSHIFT(k) kaleidoscope::addFlags(CONVERT_TO_KEY(k), SHIFT_HELD) #define LSHIFT(k) kaleidoscope::addFlags(CONVERT_TO_KEY(k), SHIFT_HELD)
#define LGUI(k) kaleidoscope::addFlags(CONVERT_TO_KEY(k), GUI_HELD) #define LGUI(k) kaleidoscope::addFlags(CONVERT_TO_KEY(k), GUI_HELD)
// we assert that synthetic keys can never have keys held, so we reuse the _HELD bits
#define IS_SYSCTL B00000001
#define IS_INTERNAL B00000010
#define SWITCH_TO_KEYMAP B00000100
#define IS_CONSUMER B00001000
// HID Usage Types: Because these constants, like the ones above, are
// used in the flags byte of the Key class, they can't overlap any of
// the above bits. Nor can we use `SYNTHETIC` and `RESERVED` to encode
// the HID usage type of a keycode, which leaves us with only two
// bits. Since we don't currently do anything different based on HID
// usage type, these are currently all set to zeroes.
#define HID_TYPE_CA B00000000
#define HID_TYPE_CL B00000000
#define HID_TYPE_LC B00000000
#define HID_TYPE_MC B00000000
#define HID_TYPE_NARY B00000000
#define HID_TYPE_OOC B00000000
#define HID_TYPE_OSC B00000000
#define HID_TYPE_RTC B00000000
#define HID_TYPE_SEL B00000000
#define HID_TYPE_SV B00000000
// Mask defining the allowed usage type flag bits:
#define HID_TYPE_MASK B00110000
#define Key_NoKey Key(0, KEY_FLAGS) #define Key_NoKey Key(0, KEY_FLAGS)
#define Key_skip Key(0, KEY_FLAGS) #define Key_skip Key(0, KEY_FLAGS)
#define Key_Transparent Key(0xffff) #define Key_Transparent Key(0xffff)
#define ___ Key_Transparent #define ___ Key_Transparent
#define XXX Key_NoKey #define XXX Key_NoKey
// -----------------------------------------------------------------------------
// Constant keycode values
#define HID_FIRST_KEY HID_KEYBOARD_NO_EVENT
#define HID_LAST_KEY HID_KEYPAD_HEXADECIMAL
#define HID_KEYBOARD_FIRST_MODIFIER HID_KEYBOARD_LEFT_CONTROL
#define HID_KEYBOARD_LAST_MODIFIER HID_KEYBOARD_RIGHT_GUI
namespace kaleidoscope {
namespace key_flags {
// -----------------------------------------------------------------------------
// Useful constants for the `Key` object's `flags` byte.
// There are two bits available for Consumer Control & System Control keys to
// use for storing information about the HID Usage Type. These bits are ones in
// the following mask.
constexpr uint8_t hid_type_mask = HID_TYPE_MASK;
// The bits that must match exactly when checking if a `Key` value corresponds
// to a System Control keycode.
constexpr uint8_t system_control_mask = ~hid_type_mask;
// The bits that must match exactly when checking if a `Key` value corresponds
// to a Consumer Control keycode.
constexpr uint8_t consumer_control_mask = (RESERVED | SYNTHETIC | IS_CONSUMER);
} // namespace key_flags
} // namespace kaleidoscope
#define KEY_BACKLIGHT_DOWN 0xf1 #define KEY_BACKLIGHT_DOWN 0xf1
#define KEY_BACKLIGHT_UP 0xf2 #define KEY_BACKLIGHT_UP 0xf2
#define Key_BacklightDown Key(KEY_BACKLIGHT_DOWN, KEY_FLAGS) #define Key_BacklightDown Key(KEY_BACKLIGHT_DOWN, KEY_FLAGS)

@ -418,24 +418,11 @@ bool Qukeys::isKeyAddrInQueueBeforeIndex(KeyAddr k, uint8_t index) const {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// This function could get lifted into Kaleidoscope proper, since it might be // This function is here to provide the test for a SpaceCadet-type qukey, which
// more generally useful. It's here to provide the test for a SpaceCadet-type // is any Qukey that has a modifier (including layer shifts) as its primary
// qukey, which is any Qukey that has a modifier (including layer shifts) as its // value.
// primary value.
bool isModifierKey(Key key) { bool isModifierKey(Key key) {
// If it's a plain keyboard key, return true if its base keycode is a return (key.isKeyboardModifier() || key.isLayerShift());
// modifier, otherwise return false:
if ((key.getFlags() & (SYNTHETIC | RESERVED)) == 0) {
return (key.getKeyCode() >= HID_KEYBOARD_FIRST_MODIFIER &&
key.getKeyCode() <= HID_KEYBOARD_LAST_MODIFIER);
}
// If it's a layer shift key, return true:
if (key.getFlags() == (SYNTHETIC | SWITCH_TO_KEYMAP) &&
key.getKeyCode() >= LAYER_SHIFT_OFFSET) {
return true;
}
// In all other cases, return false:
return false;
} }
} // namespace plugin { } // namespace plugin {

Loading…
Cancel
Save