-
-
Notifications
You must be signed in to change notification settings - Fork 39.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update store_or_get_action to cache keycode on key press, return cached keycode on key release #24517
base: develop
Are you sure you want to change the base?
Update store_or_get_action to cache keycode on key press, return cached keycode on key release #24517
Conversation
lint formatting Co-authored-by: Drashna Jaelre <[email protected]>
quantum/dynamic_keymap.c
Outdated
// Big endian, so we can read/write EEPROM directly from host if we want | ||
eeprom_update_byte(address, (uint8_t)(keycode >> 8)); | ||
eeprom_update_byte(address + 1, (uint8_t)(keycode & 0xFF)); | ||
unregister_code(prev_keycode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed on discord, this wont correctly handle keycode that are non-basic, and changing it to unregister_code16
would then only handle basic+modded. Using clear_keyboard()
covers more scenarios but still does not cover any side effects of quantum keycodes.
Im also not a fan of coupling storage directly to its eventual use, wherever in the tmk action code. I agree updating via.c
to be responsible would be error prone for other eventual uses of dynamic_keymap_set_keycode
, but it still feels like the cleaner workaround till a better solution is implemented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A reason I handled things in here was to cover the scenario of:
- key pressed
- dynamic keymap set
- dynamic keymap set (again)
- key released
Is changing unregister_code
to handle non-basic keycodes an option?
Or creating a new, all-encompassing function to handle unregistering any code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, when you suggest to have via.c
be responsible, would having the same logic but instead immediately before and after the call to dynamic_keymap_set_keycode
within the id_dynamic_keymap_set_keycode
case suffice? Or would there be more to having this happen in via.c
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolving since I made via.c
responsible to handle this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unresolving as its still using unregister_code
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unresolving as its still using
unregister_code
.
Hey mate, if you have time and still have interest, I think my new implementation is ready for further review
I made some heavy changes following a suggestion from the discussion on discord when this was first brought up. I modified the logic of what I know there is some overlap with the introduction of this implementation but I don't know what all depends on the source layers cache, so I focused solely on what |
This may need to be opt-in, given the added RAM requirement. A TKL would use somewhere of the order of 400-500 extra bytes, and not everyone has that free. |
quantum/action_layer.c
Outdated
uint16_t keycode_map[((MATRIX_ROWS * MATRIX_COLS) + (CHAR_BIT)-1) / (CHAR_BIT)][16] = {{KC_NO}}; | ||
# ifdef ENCODER_MAP_ENABLE | ||
uint16_t encoder_keycode_map[(NUM_ENCODERS + (CHAR_BIT)-1) / (CHAR_BIT)][16] = {{KC_NO}}; | ||
# endif // ENCODER_MAP_ENABLE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks overcomplicated. The source layer cache code uses such tricks to avoid allocating a whole byte for each entry that needs just 2 bits in the most common case (4 layers); if you are storing the whole 16-bit keycode, you may just use
static uint16_t keycode_map[MATRIX_ROWS][MATRIX_COLS];
and
static uint16_t encoder_keycode_map[NUM_ENCODERS][NUM_DIRECTIONS];
(Actually the encoder code might not need such handling at all, because the press and release events are emitted without running the rest of main loop code in between, therefore keymap updates should not happen.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a ton for the feedback, I cleaned up the overcomplicated keycode_map and also removed the encoder handling
quantum/action_layer.c
Outdated
else if (key.row == KEYLOC_ENCODER_CW || key.row == KEYLOC_ENCODER_CCW) { | ||
const uint16_t entry_number = key.col; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general you may need to consider key.row
too (so that entries for different rotation direction don't overwrite each other); maybe it's simple to just do that instead of thinking why that should not happen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since I removed the encoder handling code, is this safe to not consider?
@@ -287,6 +287,31 @@ uint8_t read_source_layers_cache(keypos_t key) { | |||
# endif // ENCODER_MAP_ENABLE | |||
return 0; | |||
} | |||
|
|||
# ifdef KEYCODE_CACHE_ENABLE | |||
static uint16_t keycode_map[MATRIX_ROWS][MATRIX_COLS] = {{KC_NO}}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps keeping an array of, say, 10 of:
typedef struct historical_keycode_t {
uint8_t row;
uint8_t col;
uint16_t keycode;
} historical_keycode_t;
...should significantly decrease the RAM requirements at the cost of a slightly more complicated algorithm.
Description
Changes behavior of
store_or_get_action
to cache a keycode for a pressed key and then return the cached keycode when releasing a key.I would not exactly call this a "bugfix" but it does prevent keys from getting "stuck" when editing layouts through VIA hotswapping, for example.
This semi-replaces the source layers cache implementation to cache the entire keycode for a key location.
Feature must be opted into with
#define KEYCODE_CACHE_ENABLE
.Types of Changes
Issues Fixed or Closed by This PR
Checklist