|
|
@ -20,12 +20,14 @@
|
|
|
|
#include "kaleidoscope/keyswitch_state.h"
|
|
|
|
#include "kaleidoscope/keyswitch_state.h"
|
|
|
|
#include "kaleidoscope/keyswitch_state.h"
|
|
|
|
#include "kaleidoscope/keyswitch_state.h"
|
|
|
|
#include "kaleidoscope/key_events.h"
|
|
|
|
#include "kaleidoscope/key_events.h"
|
|
|
|
|
|
|
|
#include "kaleidoscope/KeyEventTracker.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace kaleidoscope {
|
|
|
|
namespace kaleidoscope {
|
|
|
|
namespace plugin {
|
|
|
|
namespace plugin {
|
|
|
|
|
|
|
|
|
|
|
|
// --- state ---
|
|
|
|
// --- state ---
|
|
|
|
Key Leader::sequence_[LEADER_MAX_SEQUENCE_LENGTH + 1];
|
|
|
|
Key Leader::sequence_[LEADER_MAX_SEQUENCE_LENGTH + 1];
|
|
|
|
|
|
|
|
KeyEventTracker Leader::event_tracker_;
|
|
|
|
uint8_t Leader::sequence_pos_;
|
|
|
|
uint8_t Leader::sequence_pos_;
|
|
|
|
uint16_t Leader::start_time_ = 0;
|
|
|
|
uint16_t Leader::start_time_ = 0;
|
|
|
|
uint16_t Leader::time_out = 1000;
|
|
|
|
uint16_t Leader::time_out = 1000;
|
|
|
@ -81,8 +83,9 @@ void Leader::reset(void) {
|
|
|
|
sequence_[0] = Key_NoKey;
|
|
|
|
sequence_[0] = Key_NoKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// DEPRECATED
|
|
|
|
void Leader::inject(Key key, uint8_t key_state) {
|
|
|
|
void Leader::inject(Key key, uint8_t key_state) {
|
|
|
|
onKeyswitchEvent(key, UnknownKeyswitchLocation, key_state);
|
|
|
|
Runtime.handleKeyEvent(KeyEvent(KeyAddr::none(), key_state | INJECTED, key));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// --- hooks ---
|
|
|
|
// --- hooks ---
|
|
|
@ -90,61 +93,49 @@ EventHandlerResult Leader::onNameQuery() {
|
|
|
|
return ::Focus.sendName(F("Leader"));
|
|
|
|
return ::Focus.sendName(F("Leader"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EventHandlerResult Leader::onKeyswitchEvent(Key &mapped_key, KeyAddr key_addr, uint8_t keyState) {
|
|
|
|
EventHandlerResult Leader::onKeyswitchEvent(KeyEvent &event) {
|
|
|
|
if (keyState & INJECTED)
|
|
|
|
// If the plugin has already processed and released this event, ignore it.
|
|
|
|
|
|
|
|
// There's no need to update the event tracker explicitly.
|
|
|
|
|
|
|
|
if (event_tracker_.shouldIgnore(event))
|
|
|
|
return EventHandlerResult::OK;
|
|
|
|
return EventHandlerResult::OK;
|
|
|
|
|
|
|
|
|
|
|
|
if (!isActive() && !isLeader(mapped_key))
|
|
|
|
if (keyToggledOff(event.state) || event.state & INJECTED)
|
|
|
|
return EventHandlerResult::OK;
|
|
|
|
return EventHandlerResult::OK;
|
|
|
|
|
|
|
|
|
|
|
|
if (!isActive()) {
|
|
|
|
if (!isActive()) {
|
|
|
|
// Must be a leader key!
|
|
|
|
if (!isLeader(event.key))
|
|
|
|
|
|
|
|
return EventHandlerResult::OK;
|
|
|
|
|
|
|
|
|
|
|
|
if (keyToggledOff(keyState)) {
|
|
|
|
|
|
|
|
// not active, but a leader key = start the sequence on key release!
|
|
|
|
|
|
|
|
start_time_ = Runtime.millisAtCycleStart();
|
|
|
|
start_time_ = Runtime.millisAtCycleStart();
|
|
|
|
sequence_pos_ = 0;
|
|
|
|
sequence_pos_ = 0;
|
|
|
|
sequence_[sequence_pos_] = mapped_key;
|
|
|
|
sequence_[sequence_pos_] = event.key;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If the sequence was not active yet, ignore the key.
|
|
|
|
return EventHandlerResult::ABORT;
|
|
|
|
return EventHandlerResult::EVENT_CONSUMED;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// active
|
|
|
|
++sequence_pos_;
|
|
|
|
int8_t action_index = lookup();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (keyToggledOn(keyState)) {
|
|
|
|
|
|
|
|
sequence_pos_++;
|
|
|
|
|
|
|
|
if (sequence_pos_ > LEADER_MAX_SEQUENCE_LENGTH) {
|
|
|
|
if (sequence_pos_ > LEADER_MAX_SEQUENCE_LENGTH) {
|
|
|
|
reset();
|
|
|
|
reset();
|
|
|
|
return EventHandlerResult::OK;
|
|
|
|
return EventHandlerResult::OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
start_time_ = Runtime.millisAtCycleStart();
|
|
|
|
start_time_ = Runtime.millisAtCycleStart();
|
|
|
|
sequence_[sequence_pos_] = mapped_key;
|
|
|
|
sequence_[sequence_pos_] = event.key;
|
|
|
|
action_index = lookup();
|
|
|
|
int8_t action_index = lookup();
|
|
|
|
|
|
|
|
|
|
|
|
if (action_index >= 0) {
|
|
|
|
|
|
|
|
return EventHandlerResult::EVENT_CONSUMED;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (keyIsPressed(keyState)) {
|
|
|
|
|
|
|
|
// held, no need for anything here.
|
|
|
|
|
|
|
|
return EventHandlerResult::EVENT_CONSUMED;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (action_index == NO_MATCH) {
|
|
|
|
if (action_index == NO_MATCH) {
|
|
|
|
reset();
|
|
|
|
reset();
|
|
|
|
return EventHandlerResult::OK;
|
|
|
|
return EventHandlerResult::OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (action_index == PARTIAL_MATCH) {
|
|
|
|
if (action_index == PARTIAL_MATCH) {
|
|
|
|
return EventHandlerResult::EVENT_CONSUMED;
|
|
|
|
return EventHandlerResult::ABORT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
action_t leaderAction = (action_t) pgm_read_ptr((void const **) & (dictionary[action_index].action));
|
|
|
|
action_t leaderAction = (action_t) pgm_read_ptr((void const **) & (dictionary[action_index].action));
|
|
|
|
(*leaderAction)(action_index);
|
|
|
|
(*leaderAction)(action_index);
|
|
|
|
|
|
|
|
reset();
|
|
|
|
|
|
|
|
|
|
|
|
return EventHandlerResult::EVENT_CONSUMED;
|
|
|
|
return EventHandlerResult::ABORT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EventHandlerResult Leader::afterEachCycle() {
|
|
|
|
EventHandlerResult Leader::afterEachCycle() {
|
|
|
|