-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Fix mod-morph #1412
Fix mod-morph #1412
Conversation
Quick ping @petejohanson: I think this is ready for review if you get the chance. Below a quick summary of the technical implementation to, hopefully, facilitate the review process. At its core, the PR does a bit of refactoring of how mods are handled in Any change in modifiers; i.e., any call to one of the following functions:
updates the corresponding state variable and then calls
Using the refactored hid functions, |
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.
Code changes all seem reasonable, just the one point of discussion around the default behavior being changed by this PR.
@@ -88,6 +93,8 @@ static int behavior_mod_morph_init(const struct device *dev) { return 0; } | |||
.normal_binding = _TRANSFORM_ENTRY(0, n), \ | |||
.morph_binding = _TRANSFORM_ENTRY(1, n), \ | |||
.mods = DT_INST_PROP(n, mods), \ | |||
.masked_mods = COND_CODE_0(DT_INST_NODE_HAS_PROP(n, masked_mods), (DT_INST_PROP(n, mods)), \ |
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 fallback makes sense, in theory, but changes existing default mod morph behavior....
docs/docs/behaviors/mod-morph.md
Outdated
|
||
`masked-mods` | ||
|
||
When a modifier specified in `mods` is being held, it won't be sent along with the morphed keycode if it is also part of `masked-mods`. To sent all modifiers along with the morphed keycode, set `masked-mods` to `<0>`. By default, `masked-mods` equals `mods`. |
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.
Doesn't this mean the default behavior for mod morph is changed as part of this PR?
Do we think there's any reason to be concerned by that?
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.
My reading was that most considered the old default a bug (see #683). Personally, I could go either way. But I thought that the proposed default may simplify life for the typical use-case of mod-morph?
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.
Plenty of voices there that would seem to suggest a new default behavior is fine... Wonder how many folks use it today is as and it works well?
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, one can always enforce that a mod gets sent along by adding it to the binding as implicit mod. Hopefully that'll be intuitive enough so that most people won't even need to adjust the masked-mods property?
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.
Yeah, I am leaning towards this being an "in the greater good" breaking change in behavior, given the fact the original versions sending along the mods was "odd" in the first place.
@joelspadin @Nicell @okke-formsma Thoughts?
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.
Re: masked-mods vs keep-mods, there's a minor restriction associated with the latter in that one wouldn't be able to mask any mods other than the ones triggering the mod-morph. Not sure how much that's a restriction in practice, but it may limit some creative uses?
That's a good call out. I think potentially useful to support that for cases we're not imaging yet for this.
I hadn't thought that far.
My issue was that masked-mods
looked like an implementation detail leaking into the API for no good reason.
"Future use-cases" could be reason enough to go with it; and with the with the new default I assume it wouldn't show up in the vast majority of cases anyway.
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.
I agree with snoyer, in addition if we are changing the default then it's also fair to break not-yet-imagined use cases that masked-mods
might allow. Making it more intuitive for users should take priority here IMO.
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.
Thinking about this more... I think I'm now leaning towards keep-mods
for this. If we really need to filter other mods not specified in the morph later, we can solve that another way.
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.
The main use I could imagine is to set up a "dummy-mod-morph" which doesn't actually do anything other than masking mods. Currently, this is the only way to access the backend hid-functions zmk_hid_masked_modifiers_set
and zmk_hid_masked_modifiers_clear
from the user side. But I agree that if there is demand for that, it would probably better to create a new "negative-mods" behavior that more directly exposes the masked_mods functionality.
I just pushed a new commit that switches from masked-mods to keep-mods. I tried out a couple of edge cases and it all works well on my side.
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.
Having a behavior to set/clear masked mods would also be useful for sending strings, as you could lock out mods before sending the string and restore them after. That said, if the string is too long and it overflows the behavior queue, the restore behavior would never be sent and you wouldn't be able to use those mods anymore, so that wouldn't be great. Maybe instead we could add an optional mask property to specific behaviors, so for example you could add a &kp
variant that masks mods and use that instead of &kp
when sending strings.
lgtm |
Co-authored-by: Cem Aksoylar <caksoylar@users.noreply.github.com>
No modifiers will be preserved could be misunderstood as no modifier, including those that aren't part of `mods` will be preserved.
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.
Looks good to me from a docs perspective.
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 for all the work on this!
This is an updated version of #1114. It builds on @aumuell's masked-mods fix 241f82e. Notable differences with respect to #1114 are:
masked-mods
to be overwritten by implicit modsmasked-mods
)Important change: the config option has been changed from
masked_mods
tokeep-mods