Added a configurable release delay on qukey release

When releasing a qukey, allow a short timeout in case a subsequent key was released
effectively simultaneously, treating that near-simultaneous release as intended to use the
alternate (i.e. modifier) keycode.
pull/389/head
Michael Richters 7 years ago
parent 26c5bd7162
commit 32a8537c28

@ -85,11 +85,14 @@ uint8_t Qukeys::qukeys_count = 0;
bool Qukeys::active_ = true; bool Qukeys::active_ = true;
uint16_t Qukeys::time_limit_ = 250; uint16_t Qukeys::time_limit_ = 250;
uint8_t Qukeys::release_delay_ = 0;
QueueItem Qukeys::key_queue_[] = {}; QueueItem Qukeys::key_queue_[] = {};
uint8_t Qukeys::key_queue_length_ = 0; uint8_t Qukeys::key_queue_length_ = 0;
byte Qukeys::qukey_state_[] = {}; byte Qukeys::qukey_state_[] = {};
bool Qukeys::flushing_queue_ = false; bool Qukeys::flushing_queue_ = false;
constexpr uint16_t QUKEYS_RELEASE_DELAY_OFFSET = 4096;
// Empty constructor; nothing is stored at the instance level // Empty constructor; nothing is stored at the instance level
Qukeys::Qukeys(void) {} Qukeys::Qukeys(void) {}
@ -116,7 +119,7 @@ void Qukeys::enqueue(uint8_t key_addr) {
flushQueue(); flushQueue();
} }
key_queue_[key_queue_length_].addr = key_addr; key_queue_[key_queue_length_].addr = key_addr;
key_queue_[key_queue_length_].start_time = (uint16_t)millis(); key_queue_[key_queue_length_].start_time = millis();
key_queue_length_++; key_queue_length_++;
addr::mask(key_addr); addr::mask(key_addr);
} }
@ -175,7 +178,7 @@ void Qukeys::flushKey(bool qukey_state, uint8_t keyswitch_state) {
memcpy(Keyboard.keyReport.allkeys, hid_report.allkeys, sizeof(hid_report)); memcpy(Keyboard.keyReport.allkeys, hid_report.allkeys, sizeof(hid_report));
// Last, if the key is still down, add its code back in // Last, if the key is still down, add its code back in
if (keyswitch_state | IS_PRESSED) if (keyswitch_state & IS_PRESSED)
handleKeyswitchEvent(keycode, row, col, IS_PRESSED | WAS_PRESSED); handleKeyswitchEvent(keycode, row, col, IS_PRESSED | WAS_PRESSED);
// Now that we're done sending the report(s), Qukeys can process events again: // Now that we're done sending the report(s), Qukeys can process events again:
@ -197,22 +200,29 @@ void Qukeys::flushQueue(int8_t index) {
return; return;
for (int8_t i = 0; i < index; i++) { for (int8_t i = 0; i < index; i++) {
if (key_queue_length_ == 0) if (key_queue_length_ == 0)
break; return;
flushKey(QUKEY_STATE_ALTERNATE, IS_PRESSED | WAS_PRESSED); flushKey(QUKEY_STATE_ALTERNATE, IS_PRESSED | WAS_PRESSED);
} }
flushKey(QUKEY_STATE_PRIMARY, WAS_PRESSED); if (isQukey(key_queue_[0].addr)) {
flushKey(QUKEY_STATE_PRIMARY, IS_PRESSED | WAS_PRESSED);
} else {
flushKey(QUKEY_STATE_PRIMARY, WAS_PRESSED);
}
} }
// Flush all the non-qukey keys from the front of the queue // Flush all the non-qukey keys from the front of the queue
void Qukeys::flushQueue() { void Qukeys::flushQueue() {
// flush keys until we find a qukey: // flush keys until we find a qukey:
while (key_queue_length_ > 0 && while (key_queue_length_ > 0 && !isQukey(key_queue_[0].addr)) {
! isDualUse(key_queue_[0].addr) &&
lookupQukey(key_queue_[0].addr) == QUKEY_NOT_FOUND) {
flushKey(QUKEY_STATE_PRIMARY, IS_PRESSED | WAS_PRESSED); flushKey(QUKEY_STATE_PRIMARY, IS_PRESSED | WAS_PRESSED);
} }
} }
inline
bool Qukeys::isQukey(uint8_t addr) {
return (isDualUse(addr) || lookupQukey(addr) != QUKEY_NOT_FOUND);
}
Key Qukeys::keyScanHook(Key mapped_key, byte row, byte col, uint8_t key_state) { Key Qukeys::keyScanHook(Key mapped_key, byte row, byte col, uint8_t key_state) {
// If key_addr is not a physical key, ignore it; some other plugin injected it // If key_addr is not a physical key, ignore it; some other plugin injected it
@ -279,6 +289,14 @@ Key Qukeys::keyScanHook(Key mapped_key, byte row, byte col, uint8_t key_state) {
} }
return mapped_key; return mapped_key;
} }
// If there's a release delay in effect, the released key is a qukey, and there's at
// least one key after it in the queue, delay this key's release event:
if (release_delay_ > 0 &&
isQukey(key_addr) &&
queue_index < (key_queue_length_ - 1)) {
key_queue_[queue_index].start_time = millis() + QUKEYS_RELEASE_DELAY_OFFSET;
return Key_NoKey;
}
flushQueue(queue_index); flushQueue(queue_index);
flushQueue(); flushQueue();
return Key_NoKey; return Key_NoKey;
@ -314,10 +332,23 @@ Key Qukeys::keyScanHook(Key mapped_key, byte row, byte col, uint8_t key_state) {
} }
void Qukeys::preReportHook(void) { void Qukeys::preReportHook(void) {
uint16_t current_time = millis();
if (release_delay_ > 0) {
int16_t diff_time = key_queue_[0].start_time - current_time;
if (diff_time > 0) {
int16_t delay_window = QUKEYS_RELEASE_DELAY_OFFSET - release_delay_;
if (diff_time < delay_window) {
flushKey(QUKEY_STATE_ALTERNATE, WAS_PRESSED);
flushQueue();
}
}
}
// If the qukey has been held longer than the time limit, set its // If the qukey has been held longer than the time limit, set its
// state to the alternate keycode and add it to the report // state to the alternate keycode and add it to the report
while (key_queue_length_ > 0) { while (key_queue_length_ > 0) {
uint16_t current_time = millis();
if ((current_time - key_queue_[0].start_time) > time_limit_) { if ((current_time - key_queue_[0].start_time) > time_limit_) {
flushKey(QUKEY_STATE_ALTERNATE, IS_PRESSED | WAS_PRESSED); flushKey(QUKEY_STATE_ALTERNATE, IS_PRESSED | WAS_PRESSED);
flushQueue(); flushQueue();

@ -94,6 +94,9 @@ class Qukeys : public KaleidoscopePlugin {
static void setTimeout(uint16_t time_limit) { static void setTimeout(uint16_t time_limit) {
time_limit_ = time_limit; time_limit_ = time_limit;
} }
static void setReleaseDelay(uint8_t release_delay) {
release_delay_ = release_delay;
}
static Qukey * qukeys; static Qukey * qukeys;
static uint8_t qukeys_count; static uint8_t qukeys_count;
@ -101,6 +104,7 @@ class Qukeys : public KaleidoscopePlugin {
private: private:
static bool active_; static bool active_;
static uint16_t time_limit_; static uint16_t time_limit_;
static uint8_t release_delay_;
static QueueItem key_queue_[QUKEYS_QUEUE_MAX]; static QueueItem key_queue_[QUKEYS_QUEUE_MAX];
static uint8_t key_queue_length_; static uint8_t key_queue_length_;
static bool flushing_queue_; static bool flushing_queue_;
@ -120,6 +124,7 @@ class Qukeys : public KaleidoscopePlugin {
static void flushKey(bool qukey_state, uint8_t keyswitch_state); static void flushKey(bool qukey_state, uint8_t keyswitch_state);
static void flushQueue(int8_t index); static void flushQueue(int8_t index);
static void flushQueue(void); static void flushQueue(void);
static bool isQukey(uint8_t addr);
static Key keyScanHook(Key mapped_key, byte row, byte col, uint8_t key_state); static Key keyScanHook(Key mapped_key, byte row, byte col, uint8_t key_state);
static void preReportHook(void); static void preReportHook(void);

Loading…
Cancel
Save