|
|
|
@ -18,49 +18,47 @@
|
|
|
|
|
|
|
|
|
|
#include <Kaleidoscope-OneShot.h>
|
|
|
|
|
|
|
|
|
|
using namespace KaleidoscopePlugins::Ranges;
|
|
|
|
|
namespace kaleidoscope {
|
|
|
|
|
|
|
|
|
|
namespace KaleidoscopePlugins {
|
|
|
|
|
// ---- state ---------
|
|
|
|
|
|
|
|
|
|
uint32_t OneShot::startTime = 0;
|
|
|
|
|
uint16_t OneShot::timeOut = 2500;
|
|
|
|
|
uint16_t OneShot::holdTimeOut = 250;
|
|
|
|
|
OneShot::state_t OneShot::State;
|
|
|
|
|
OneShot::state_t OneShot::stickyState;
|
|
|
|
|
OneShot::state_t OneShot::pressedState;
|
|
|
|
|
uint32_t OneShot::leftMask;
|
|
|
|
|
uint32_t OneShot::rightMask;
|
|
|
|
|
Key OneShot::prevKey;
|
|
|
|
|
bool OneShot::shouldCancel = false;
|
|
|
|
|
bool OneShot::shouldCancelStickies = false;
|
|
|
|
|
uint32_t OneShot::start_time_ = 0;
|
|
|
|
|
uint16_t OneShot::time_out = 2500;
|
|
|
|
|
uint16_t OneShot::hold_time_out = 250;
|
|
|
|
|
OneShot::state_t OneShot::state_;
|
|
|
|
|
OneShot::state_t OneShot::sticky_state_;
|
|
|
|
|
OneShot::state_t OneShot::pressed_state_;
|
|
|
|
|
uint32_t OneShot::left_mask_;
|
|
|
|
|
uint32_t OneShot::right_mask_;
|
|
|
|
|
Key OneShot::prev_key_;
|
|
|
|
|
bool OneShot::should_cancel_ = false;
|
|
|
|
|
bool OneShot::should_cancel_stickies_ = false;
|
|
|
|
|
|
|
|
|
|
// --- helper macros ------
|
|
|
|
|
|
|
|
|
|
#define isOS(key) (key.raw >= OS_FIRST && key.raw <= OS_LAST)
|
|
|
|
|
#define isOS(key) (key.raw >= ranges::OS_FIRST && key.raw <= ranges::OS_LAST)
|
|
|
|
|
#define isModifier(key) (key.raw >= Key_LeftControl.raw && key.raw <= Key_RightGui.raw)
|
|
|
|
|
#define isLayerKey(key) (key.flags == (KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP) && key.keyCode >= MOMENTARY_OFFSET && key.keyCode <= MOMENTARY_OFFSET + 23)
|
|
|
|
|
|
|
|
|
|
#define isOneShot(idx) (bitRead (State.all, (idx)))
|
|
|
|
|
#define setOneShot(idx) (bitWrite (State.all, idx, 1))
|
|
|
|
|
#define clearOneShot(idx) (bitWrite (State.all, idx, 0))
|
|
|
|
|
#define isOneShot(idx) (bitRead (state_.all, (idx)))
|
|
|
|
|
#define setOneShot(idx) (bitWrite (state_.all, idx, 1))
|
|
|
|
|
#define clearOneShot(idx) (bitWrite (state_.all, idx, 0))
|
|
|
|
|
|
|
|
|
|
#define isSticky(idx) (bitRead (stickyState.all, idx))
|
|
|
|
|
#define setSticky(idx) (bitWrite (stickyState.all, idx, 1))
|
|
|
|
|
#define clearSticky(idx) bitWrite (stickyState.all, idx, 0)
|
|
|
|
|
#define isSticky(idx) (bitRead (sticky_state_.all, idx))
|
|
|
|
|
#define setSticky(idx) (bitWrite (sticky_state_.all, idx, 1))
|
|
|
|
|
#define clearSticky(idx) bitWrite (sticky_state_.all, idx, 0)
|
|
|
|
|
|
|
|
|
|
#define setPressed(idx) bitWrite(pressedState.all, idx, 1)
|
|
|
|
|
#define clearPressed(idx) bitWrite(pressedState.all, idx, 0)
|
|
|
|
|
#define isPressed(idx) bitRead (pressedState.all, idx)
|
|
|
|
|
#define setPressed(idx) bitWrite(pressed_state_.all, idx, 1)
|
|
|
|
|
#define clearPressed(idx) bitWrite(pressed_state_.all, idx, 0)
|
|
|
|
|
#define isPressed(idx) bitRead (pressed_state_.all, idx)
|
|
|
|
|
|
|
|
|
|
#define isSameAsPrevious(key) (key.raw == prevKey.raw)
|
|
|
|
|
#define saveAsPrevious(key) prevKey.raw = key.raw
|
|
|
|
|
#define isSameAsPrevious(key) (key.raw == prev_key_.raw)
|
|
|
|
|
#define saveAsPrevious(key) prev_key_.raw = key.raw
|
|
|
|
|
|
|
|
|
|
#define hasTimedOut() (millis () - startTime >= timeOut)
|
|
|
|
|
#define hasTimedOut() (millis () - start_time_ >= time_out)
|
|
|
|
|
|
|
|
|
|
// ---- OneShot stuff ----
|
|
|
|
|
void
|
|
|
|
|
OneShot::injectNormalKey(uint8_t idx, uint8_t keyState) {
|
|
|
|
|
void OneShot::injectNormalKey(uint8_t idx, uint8_t key_state) {
|
|
|
|
|
Key key;
|
|
|
|
|
|
|
|
|
|
if (idx < 8) {
|
|
|
|
@ -71,85 +69,79 @@ OneShot::injectNormalKey(uint8_t idx, uint8_t keyState) {
|
|
|
|
|
key.keyCode = MOMENTARY_OFFSET + idx - 8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handle_keyswitch_event(key, UNKNOWN_KEYSWITCH_LOCATION, keyState | INJECTED);
|
|
|
|
|
handle_keyswitch_event(key, UNKNOWN_KEYSWITCH_LOCATION, key_state | INJECTED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
OneShot::activateOneShot(uint8_t idx) {
|
|
|
|
|
void OneShot::activateOneShot(uint8_t idx) {
|
|
|
|
|
injectNormalKey(idx, IS_PRESSED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
OneShot::cancelOneShot(uint8_t idx) {
|
|
|
|
|
void OneShot::cancelOneShot(uint8_t idx) {
|
|
|
|
|
clearOneShot(idx);
|
|
|
|
|
injectNormalKey(idx, WAS_PRESSED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
OneShot::mask(byte row, byte col) {
|
|
|
|
|
void OneShot::mask(byte row, byte col) {
|
|
|
|
|
if (row >= ROWS || col >= COLS)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (col >= 8) {
|
|
|
|
|
col = col - 8;
|
|
|
|
|
rightMask |= SCANBIT(row, col);
|
|
|
|
|
right_mask_ |= SCANBIT(row, col);
|
|
|
|
|
} else {
|
|
|
|
|
leftMask |= SCANBIT(row, col);
|
|
|
|
|
left_mask_ |= SCANBIT(row, col);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
OneShot::unmask(byte row, byte col) {
|
|
|
|
|
void OneShot::unmask(byte row, byte col) {
|
|
|
|
|
if (row >= ROWS || col >= COLS)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (col >= 8) {
|
|
|
|
|
col = col - 8;
|
|
|
|
|
rightMask &= ~(SCANBIT(row, col));
|
|
|
|
|
right_mask_ &= ~(SCANBIT(row, col));
|
|
|
|
|
} else {
|
|
|
|
|
leftMask &= ~(SCANBIT(row, col));
|
|
|
|
|
left_mask_ &= ~(SCANBIT(row, col));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
OneShot::isMasked(byte row, byte col) {
|
|
|
|
|
bool OneShot::isMasked(byte row, byte col) {
|
|
|
|
|
if (row >= ROWS || col >= COLS)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (col >= 8) {
|
|
|
|
|
col = col - 8;
|
|
|
|
|
return rightMask & SCANBIT(row, col);
|
|
|
|
|
return right_mask_ & SCANBIT(row, col);
|
|
|
|
|
} else {
|
|
|
|
|
return leftMask & SCANBIT(row, col);
|
|
|
|
|
return left_mask_ & SCANBIT(row, col);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Key
|
|
|
|
|
OneShot::eventHandlerHook(Key mappedKey, byte row, byte col, uint8_t keyState) {
|
|
|
|
|
Key OneShot::eventHandlerHook(Key mapped_key, byte row, byte col, uint8_t key_state) {
|
|
|
|
|
uint8_t idx;
|
|
|
|
|
|
|
|
|
|
if (keyState & INJECTED)
|
|
|
|
|
return mappedKey;
|
|
|
|
|
if (key_state & INJECTED)
|
|
|
|
|
return mapped_key;
|
|
|
|
|
|
|
|
|
|
if (!State.all) {
|
|
|
|
|
if (!isOS(mappedKey)) {
|
|
|
|
|
if (!state_.all) {
|
|
|
|
|
if (!isOS(mapped_key)) {
|
|
|
|
|
if (isMasked(row, col)) {
|
|
|
|
|
if (key_toggled_off(keyState))
|
|
|
|
|
if (key_toggled_off(key_state))
|
|
|
|
|
unmask(row, col);
|
|
|
|
|
return Key_NoKey;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mappedKey;
|
|
|
|
|
return mapped_key;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
idx = mappedKey.raw - OS_FIRST;
|
|
|
|
|
if (key_toggled_off(keyState)) {
|
|
|
|
|
idx = mapped_key.raw - ranges::OS_FIRST;
|
|
|
|
|
if (key_toggled_off(key_state)) {
|
|
|
|
|
clearPressed(idx);
|
|
|
|
|
} else if (key_toggled_on(keyState)) {
|
|
|
|
|
startTime = millis();
|
|
|
|
|
} else if (key_toggled_on(key_state)) {
|
|
|
|
|
start_time_ = millis();
|
|
|
|
|
setPressed(idx);
|
|
|
|
|
setOneShot(idx);
|
|
|
|
|
saveAsPrevious(mappedKey);
|
|
|
|
|
saveAsPrevious(mapped_key);
|
|
|
|
|
|
|
|
|
|
activateOneShot(idx);
|
|
|
|
|
}
|
|
|
|
@ -157,37 +149,37 @@ OneShot::eventHandlerHook(Key mappedKey, byte row, byte col, uint8_t keyState) {
|
|
|
|
|
return Key_NoKey;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!key_is_pressed(keyState) && !key_was_pressed(keyState))
|
|
|
|
|
return mappedKey;
|
|
|
|
|
if (!key_is_pressed(key_state) && !key_was_pressed(key_state))
|
|
|
|
|
return mapped_key;
|
|
|
|
|
|
|
|
|
|
if (isOS(mappedKey)) {
|
|
|
|
|
idx = mappedKey.raw - OS_FIRST;
|
|
|
|
|
if (isOS(mapped_key)) {
|
|
|
|
|
idx = mapped_key.raw - ranges::OS_FIRST;
|
|
|
|
|
|
|
|
|
|
if (isSticky(idx)) {
|
|
|
|
|
if (key_toggled_on(keyState)) { // maybe on _off instead?
|
|
|
|
|
saveAsPrevious(mappedKey);
|
|
|
|
|
if (key_toggled_on(key_state)) { // maybe on _off instead?
|
|
|
|
|
saveAsPrevious(mapped_key);
|
|
|
|
|
clearSticky(idx);
|
|
|
|
|
cancelOneShot(idx);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (key_toggled_off(keyState)) {
|
|
|
|
|
if (key_toggled_off(key_state)) {
|
|
|
|
|
clearPressed(idx);
|
|
|
|
|
if ((millis() - startTime) >= holdTimeOut) {
|
|
|
|
|
if ((millis() - start_time_) >= hold_time_out) {
|
|
|
|
|
cancelOneShot(idx);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (key_toggled_on(keyState)) {
|
|
|
|
|
if (key_toggled_on(key_state)) {
|
|
|
|
|
setPressed(idx);
|
|
|
|
|
if (isSameAsPrevious(mappedKey)) {
|
|
|
|
|
if (isSameAsPrevious(mapped_key)) {
|
|
|
|
|
setSticky(idx);
|
|
|
|
|
|
|
|
|
|
saveAsPrevious(mappedKey);
|
|
|
|
|
saveAsPrevious(mapped_key);
|
|
|
|
|
} else {
|
|
|
|
|
startTime = millis();
|
|
|
|
|
start_time_ = millis();
|
|
|
|
|
|
|
|
|
|
setOneShot(idx);
|
|
|
|
|
saveAsPrevious(mappedKey);
|
|
|
|
|
saveAsPrevious(mapped_key);
|
|
|
|
|
|
|
|
|
|
activateOneShot(idx);
|
|
|
|
|
}
|
|
|
|
@ -199,28 +191,27 @@ OneShot::eventHandlerHook(Key mappedKey, byte row, byte col, uint8_t keyState) {
|
|
|
|
|
|
|
|
|
|
// ordinary key here, with some event
|
|
|
|
|
|
|
|
|
|
if (key_is_pressed(keyState)) {
|
|
|
|
|
if (key_is_pressed(key_state)) {
|
|
|
|
|
mask(row, col);
|
|
|
|
|
saveAsPrevious(mappedKey);
|
|
|
|
|
shouldCancel = true;
|
|
|
|
|
saveAsPrevious(mapped_key);
|
|
|
|
|
should_cancel_ = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mappedKey;
|
|
|
|
|
return mapped_key;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
OneShot::loopHook(bool postClear) {
|
|
|
|
|
if (!State.all)
|
|
|
|
|
void OneShot::loopHook(bool is_post_clear) {
|
|
|
|
|
if (!state_.all)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (postClear) {
|
|
|
|
|
if (is_post_clear) {
|
|
|
|
|
if (hasTimedOut())
|
|
|
|
|
cancel();
|
|
|
|
|
|
|
|
|
|
for (uint8_t i = 0; i < 32; i++) {
|
|
|
|
|
if (shouldCancel) {
|
|
|
|
|
if (should_cancel_) {
|
|
|
|
|
if (isSticky(i)) {
|
|
|
|
|
if (shouldCancelStickies) {
|
|
|
|
|
if (should_cancel_stickies_) {
|
|
|
|
|
clearSticky(i);
|
|
|
|
|
}
|
|
|
|
|
} else if (isOneShot(i) && !isPressed(i)) {
|
|
|
|
@ -229,9 +220,9 @@ OneShot::loopHook(bool postClear) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (shouldCancel) {
|
|
|
|
|
shouldCancel = false;
|
|
|
|
|
shouldCancelStickies = false;
|
|
|
|
|
if (should_cancel_) {
|
|
|
|
|
should_cancel_ = false;
|
|
|
|
|
should_cancel_stickies_ = false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (uint8_t i = 0; i < 8; i++) {
|
|
|
|
@ -247,36 +238,31 @@ OneShot::loopHook(bool postClear) {
|
|
|
|
|
OneShot::OneShot(void) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
OneShot::begin(void) {
|
|
|
|
|
void OneShot::begin(void) {
|
|
|
|
|
event_handler_hook_use(eventHandlerHook);
|
|
|
|
|
loop_hook_use(loopHook);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
OneShot::isActive(void) {
|
|
|
|
|
return (State.all && !hasTimedOut());
|
|
|
|
|
bool OneShot::isActive(void) {
|
|
|
|
|
return (state_.all && !hasTimedOut());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
OneShot::isModifierActive(Key key) {
|
|
|
|
|
bool OneShot::isModifierActive(Key key) {
|
|
|
|
|
if (key.raw < Key_LeftControl.raw || key.raw > Key_RightGui.raw)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return isOneShot(key.keyCode - Key_LeftControl.keyCode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
OneShot::cancel(bool withStickies) {
|
|
|
|
|
shouldCancel = true;
|
|
|
|
|
shouldCancelStickies = withStickies;
|
|
|
|
|
void OneShot::cancel(bool with_stickies) {
|
|
|
|
|
should_cancel_ = true;
|
|
|
|
|
should_cancel_stickies_ = with_stickies;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
OneShot::inject(Key key, uint8_t keyState) {
|
|
|
|
|
eventHandlerHook(key, 255, 255, keyState);
|
|
|
|
|
void OneShot::inject(Key key, uint8_t key_state) {
|
|
|
|
|
eventHandlerHook(key, UNKNOWN_KEYSWITCH_LOCATION, key_state);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
KaleidoscopePlugins::OneShot OneShot;
|
|
|
|
|
kaleidoscope::OneShot OneShot;
|
|
|
|
|