feat(behaviors): Swapper implementation#1366
feat(behaviors): Swapper implementation#1366nickconway wants to merge 6 commits intozmkfirmware:mainfrom
Conversation
|
I have been testing the window swapper implementation as in the example for the last day and it is working well so far. It neatly fixes #997 using a combination of first and second approaches proposed in there. |
petejohanson
left a comment
There was a problem hiding this comment.
Thanks for this! Love the idea, and the general approach.
A few thoughts on implementation details/changes added here.
As far as naming.... Let me ponder. "Smart Interrupt" certainly feels better than "Swapper", but I'm curious if anyone has any other ideas for a better name. I also think "smart" is superfluous... A lot of what ZMK does is "smart", so it feels odd to include it in the naming for just this one behavior.
- "Three Phase Behavior"
- *Tri-Phase Behavior"
- "Start/Continue/End Behavior"
- "Tri-State Behavior"
Just a few that come to mind as food for thought.
| struct zmk_behavior_binding *behaviors; | ||
| int32_t shared_layers[32]; | ||
| int32_t timeout_ms; | ||
| int32_t shared_key_positions[]; |
There was a problem hiding this comment.
Ditto, could be a bitmask instead of this "sparse" array.
There was a problem hiding this comment.
From the discussion on discord this is a bit tricky since the keymap can be any length. I've changed it to 8-bit ints for now but will keep working on a better solution.
93e215c to
69a3948
Compare
|
About the "tri-state" naming: It might be confusable with the "tri-layer" ( |
Maybe three-phase would be better, or would 'triplex' or 'treble' work here? Start/Continue/End Behavior gets the point across, but I feel like it's a bit too specific. |
|
I like the "bookend"/"sandwich" suggestions from @petejohanson personally, since it is like the repeatable "continue" behavior is bookended by special start and end events. Three-phase also sounds good. |
There was a problem hiding this comment.
An implementation comment... And then a bump again on naming... I'm on the fence on tri-state. @nickconway I didn't see you're thought on "bookend" concept for the name?
| behavior_keymap_binding_pressed((struct zmk_behavior_binding *)&cfg->start_behavior, event); | ||
| behavior_keymap_binding_released((struct zmk_behavior_binding *)&cfg->start_behavior, | ||
| event); |
There was a problem hiding this comment.
I know we do this for hold taps right now, but any reason not to use the behavior queue here?
| event); | ||
| tri_state->first_press = false; | ||
| } | ||
| behavior_keymap_binding_pressed((struct zmk_behavior_binding *)&cfg->continue_behavior, event); |
| behavior_keymap_binding_released( | ||
| (struct zmk_behavior_binding *)&tri_state->config->continue_behavior, event); | ||
| } | ||
| behavior_keymap_binding_pressed( | ||
| (struct zmk_behavior_binding *)&tri_state->config->end_behavior, event); | ||
| behavior_keymap_binding_released( | ||
| (struct zmk_behavior_binding *)&tri_state->config->end_behavior, event); |
|
@petejohanson Apologies for the delay. I think the bookend name is much better. As for the behavior queue, my understanding was that the keymap_* functions would be used here since we want the action taken immediately? |
There was a problem hiding this comment.
I've tried to compile zmk with the latest main and zephyr 3.5 with this behaviour, and had a few compilation errors.
for anyone interested, there are a few changes that made it work for me (you can find a complete patch in lttb@2b856c5)
| } | ||
|
|
||
| void behavior_tri_state_timer_handler(struct k_work *item) { | ||
| struct active_tri_state *tri_state = CONTAINER_OF(item, struct active_tri_state, release_timer); |
There was a problem hiding this comment.
from Zephyr v3.5.0 Migration Guide
CONTAINER_OF now performs type checking, this was very commonly misused to obtain user structure from k_work pointers without passing from k_work_delayable. This would now result in a build error and have to be done correctly using k_work_delayable_from_work().
| struct active_tri_state *tri_state = CONTAINER_OF(item, struct active_tri_state, release_timer); | |
| struct k_work_delayable *ditem = k_work_delayable_from_work(item); | |
| struct active_tri_state *tri_state = CONTAINER_OF(ditem, struct active_tri_state, release_timer); |
|
|
||
| #define _TRANSFORM_ENTRY(idx, node) \ | ||
| { \ | ||
| .behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(node, bindings, idx)), \ |
There was a problem hiding this comment.
- in Zephyr 3.2 Upgrade #1499,
DT_LABELwas migrated toDT_PROP - and then in refactor!: Remove deprecated label property #2028,
DT_PROPwas migrated toDEVICE_DT_NAME
| .behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(node, bindings, idx)), \ | |
| .behavior_dev = DEVICE_DT_NAME(DT_INST_PHANDLE_BY_IDX(node, bindings, idx)), \ |
| .start_behavior = _TRANSFORM_ENTRY(0, n), \ | ||
| .continue_behavior = _TRANSFORM_ENTRY(1, n), \ | ||
| .end_behavior = _TRANSFORM_ENTRY(2, n)}; \ | ||
| DEVICE_DT_INST_DEFINE(n, behavior_tri_state_init, NULL, NULL, &behavior_tri_state_config_##n, \ |
There was a problem hiding this comment.
in #2028 DEVICE_DT_INST_DEFINE was migrated to BEHAVIOR_DT_INST_DEFINE in behaviours
| DEVICE_DT_INST_DEFINE(n, behavior_tri_state_init, NULL, NULL, &behavior_tri_state_config_##n, \ | |
| BEHAVIOR_DT_INST_DEFINE(n, behavior_tri_state_init, NULL, NULL, &behavior_tri_state_config_##n, \ |
|
Thank you very much for all the effort. I gave it a try. Works when added directly to the keymap. When I add it via a combo though, it doesn't work. Does anybody have the same problem or a workaround? |
You have to include the combo locations in the ignore-positions. See #1366 (comment) |
|
@urob thank you very much!!! I just noticed my mistake. For others that want to use it with zmk-nodefree-config, here's how it works. |
54a2252 to
0876cbc
Compare
6afccca to
fb95060
Compare
Extracted from zmkfirmware#1366
fb95060 to
1f72789
Compare
d1a69a4 to
6ae088c
Compare
Extracted from zmkfirmware#1366
Extracted from zmkfirmware#1366
Implementation of #997. Smart interrupt is probably not the name we should use, but I was out of ideas, help wanted!