|
|
@ -1,5 +1,5 @@
|
|
|
|
/* DynamicMacros - Dynamic macro support for Kaleidoscope.
|
|
|
|
/* DynamicMacros - Dynamic macro support for Kaleidoscope.
|
|
|
|
* Copyright (C) 2019, 2021 Keyboard.io, Inc.
|
|
|
|
* Copyright (C) 2019-2022 Keyboard.io, Inc.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify it under
|
|
|
|
* This program is free software: you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU General Public License as published by the Free Software
|
|
|
|
* the terms of the GNU General Public License as published by the Free Software
|
|
|
@ -37,6 +37,7 @@ namespace plugin {
|
|
|
|
uint16_t DynamicMacros::storage_base_;
|
|
|
|
uint16_t DynamicMacros::storage_base_;
|
|
|
|
uint16_t DynamicMacros::storage_size_;
|
|
|
|
uint16_t DynamicMacros::storage_size_;
|
|
|
|
uint16_t DynamicMacros::map_[];
|
|
|
|
uint16_t DynamicMacros::map_[];
|
|
|
|
|
|
|
|
uint8_t DynamicMacros::macro_count_;
|
|
|
|
Key DynamicMacros::active_macro_keys_[];
|
|
|
|
Key DynamicMacros::active_macro_keys_[];
|
|
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
// =============================================================================
|
|
|
@ -65,11 +66,10 @@ void DynamicMacros::tap(Key key) {
|
|
|
|
Runtime.handleKeyEvent(KeyEvent(KeyAddr::none(), WAS_PRESSED | INJECTED, key));
|
|
|
|
Runtime.handleKeyEvent(KeyEvent(KeyAddr::none(), WAS_PRESSED | INJECTED, key));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DynamicMacros::updateDynamicMacroCache() {
|
|
|
|
uint8_t DynamicMacros::updateDynamicMacroCache() {
|
|
|
|
uint16_t pos = storage_base_;
|
|
|
|
uint16_t pos = storage_base_;
|
|
|
|
uint8_t current_id = 0;
|
|
|
|
uint8_t current_id = 0;
|
|
|
|
macro_t macro = MACRO_ACTION_END;
|
|
|
|
macro_t macro = MACRO_ACTION_END;
|
|
|
|
bool previous_macro_ended = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map_[0] = 0;
|
|
|
|
map_[0] = 0;
|
|
|
|
|
|
|
|
|
|
|
@ -79,7 +79,6 @@ void DynamicMacros::updateDynamicMacroCache() {
|
|
|
|
case MACRO_ACTION_STEP_EXPLICIT_REPORT:
|
|
|
|
case MACRO_ACTION_STEP_EXPLICIT_REPORT:
|
|
|
|
case MACRO_ACTION_STEP_IMPLICIT_REPORT:
|
|
|
|
case MACRO_ACTION_STEP_IMPLICIT_REPORT:
|
|
|
|
case MACRO_ACTION_STEP_SEND_REPORT:
|
|
|
|
case MACRO_ACTION_STEP_SEND_REPORT:
|
|
|
|
previous_macro_ended = false;
|
|
|
|
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case MACRO_ACTION_STEP_INTERVAL:
|
|
|
|
case MACRO_ACTION_STEP_INTERVAL:
|
|
|
@ -87,19 +86,16 @@ void DynamicMacros::updateDynamicMacroCache() {
|
|
|
|
case MACRO_ACTION_STEP_KEYCODEDOWN:
|
|
|
|
case MACRO_ACTION_STEP_KEYCODEDOWN:
|
|
|
|
case MACRO_ACTION_STEP_KEYCODEUP:
|
|
|
|
case MACRO_ACTION_STEP_KEYCODEUP:
|
|
|
|
case MACRO_ACTION_STEP_TAPCODE:
|
|
|
|
case MACRO_ACTION_STEP_TAPCODE:
|
|
|
|
previous_macro_ended = false;
|
|
|
|
|
|
|
|
pos++;
|
|
|
|
pos++;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case MACRO_ACTION_STEP_KEYDOWN:
|
|
|
|
case MACRO_ACTION_STEP_KEYDOWN:
|
|
|
|
case MACRO_ACTION_STEP_KEYUP:
|
|
|
|
case MACRO_ACTION_STEP_KEYUP:
|
|
|
|
case MACRO_ACTION_STEP_TAP:
|
|
|
|
case MACRO_ACTION_STEP_TAP:
|
|
|
|
previous_macro_ended = false;
|
|
|
|
|
|
|
|
pos += 2;
|
|
|
|
pos += 2;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case MACRO_ACTION_STEP_TAP_SEQUENCE: {
|
|
|
|
case MACRO_ACTION_STEP_TAP_SEQUENCE: {
|
|
|
|
previous_macro_ended = false;
|
|
|
|
|
|
|
|
uint8_t keyCode, flags;
|
|
|
|
uint8_t keyCode, flags;
|
|
|
|
do {
|
|
|
|
do {
|
|
|
|
flags = Runtime.storage().read(pos++);
|
|
|
|
flags = Runtime.storage().read(pos++);
|
|
|
@ -109,7 +105,6 @@ void DynamicMacros::updateDynamicMacroCache() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
case MACRO_ACTION_STEP_TAP_CODE_SEQUENCE: {
|
|
|
|
case MACRO_ACTION_STEP_TAP_CODE_SEQUENCE: {
|
|
|
|
previous_macro_ended = false;
|
|
|
|
|
|
|
|
uint8_t keyCode, flags;
|
|
|
|
uint8_t keyCode, flags;
|
|
|
|
do {
|
|
|
|
do {
|
|
|
|
keyCode = Runtime.storage().read(pos++);
|
|
|
|
keyCode = Runtime.storage().read(pos++);
|
|
|
@ -119,14 +114,17 @@ void DynamicMacros::updateDynamicMacroCache() {
|
|
|
|
|
|
|
|
|
|
|
|
case MACRO_ACTION_END:
|
|
|
|
case MACRO_ACTION_END:
|
|
|
|
map_[++current_id] = pos - storage_base_;
|
|
|
|
map_[++current_id] = pos - storage_base_;
|
|
|
|
|
|
|
|
|
|
|
|
if (previous_macro_ended)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
previous_macro_ended = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
// When we encounter an unknown step type, stop processing. Whatever we
|
|
|
|
|
|
|
|
// encounter after is unknown, and there's no guarantee we can parse it
|
|
|
|
|
|
|
|
// properly.
|
|
|
|
|
|
|
|
return current_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return current_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// public
|
|
|
|
// public
|
|
|
@ -136,9 +134,14 @@ void DynamicMacros::play(uint8_t macro_id) {
|
|
|
|
uint16_t pos;
|
|
|
|
uint16_t pos;
|
|
|
|
Key key;
|
|
|
|
Key key;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If the requested ID is higher than the number of macros we found during the
|
|
|
|
|
|
|
|
// cache update, bail out. Our map beyond `macro_count_` is unreliable.
|
|
|
|
|
|
|
|
if (macro_id >= macro_count_)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
pos = storage_base_ + map_[macro_id];
|
|
|
|
pos = storage_base_ + map_[macro_id];
|
|
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
while (pos < storage_base_ + storage_size_) {
|
|
|
|
switch (macro = Runtime.storage().read(pos++)) {
|
|
|
|
switch (macro = Runtime.storage().read(pos++)) {
|
|
|
|
case MACRO_ACTION_STEP_EXPLICIT_REPORT:
|
|
|
|
case MACRO_ACTION_STEP_EXPLICIT_REPORT:
|
|
|
|
case MACRO_ACTION_STEP_IMPLICIT_REPORT:
|
|
|
|
case MACRO_ACTION_STEP_IMPLICIT_REPORT:
|
|
|
@ -272,14 +275,14 @@ EventHandlerResult DynamicMacros::onFocusEvent(const char *command) {
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
uint16_t pos = 0;
|
|
|
|
uint16_t pos = 0;
|
|
|
|
|
|
|
|
|
|
|
|
while (!::Focus.isEOL()) {
|
|
|
|
while (!::Focus.isEOL() && pos < storage_size_) {
|
|
|
|
uint8_t b;
|
|
|
|
uint8_t b;
|
|
|
|
::Focus.read(b);
|
|
|
|
::Focus.read(b);
|
|
|
|
|
|
|
|
|
|
|
|
Runtime.storage().update(storage_base_ + pos++, b);
|
|
|
|
Runtime.storage().update(storage_base_ + pos++, b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Runtime.storage().commit();
|
|
|
|
Runtime.storage().commit();
|
|
|
|
updateDynamicMacroCache();
|
|
|
|
macro_count_ = updateDynamicMacroCache();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -296,7 +299,7 @@ EventHandlerResult DynamicMacros::onFocusEvent(const char *command) {
|
|
|
|
void DynamicMacros::reserve_storage(uint16_t size) {
|
|
|
|
void DynamicMacros::reserve_storage(uint16_t size) {
|
|
|
|
storage_base_ = ::EEPROMSettings.requestSlice(size);
|
|
|
|
storage_base_ = ::EEPROMSettings.requestSlice(size);
|
|
|
|
storage_size_ = size;
|
|
|
|
storage_size_ = size;
|
|
|
|
updateDynamicMacroCache();
|
|
|
|
macro_count_ = updateDynamicMacroCache();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace plugin
|
|
|
|
} // namespace plugin
|
|
|
|