Skip to content
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

feat: Allow layer behaviors to "lock" layers on #2717

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

nmunnich
Copy link
Contributor

@nmunnich nmunnich commented Dec 16, 2024

Adds a locking property to momentary, to, and toggle layer behaviors. Enabled by default for &to and &tog, a layer being "locked" prevents behaviors without the locking property from deactivating the layer.

Conditional layer activation and deactivation is always non-locking, which seems to interact nicely.

Common use case: with this PR you can place e.g. a &tog 1 or a &to 1 on layer 1, allowing you to "lock" it in place while it is active.

PR check-list

  • Branch has a clean commit history
  • Additional tests are included, if changing behaviors/core code that is testable.
  • Pre-commit used to check formatting of files, commit messages, etc.
  • Has any necessary documentation updates.

@nmunnich nmunnich requested a review from a team as a code owner December 16, 2024 16:15
@nmunnich nmunnich marked this pull request as draft December 16, 2024 18:06
@caksoylar
Copy link
Contributor

caksoylar commented Dec 16, 2024

Conditional layer activation and deactivation is always non-locking, which seems to interact nicely.

If you want to get the state of a conditionally activated then-layer, it seems useful to me to propagate the locked state from if-layers (i.e. it is locked if all of the if-layers are locked). This'd be necessary to replace the momentariness tracking I mentioned on Discord.

Can you lock on a then-layer using &tog? I would guess not, since it still needs all the if-layers to be active.

@nmunnich
Copy link
Contributor Author

If you want to get the state of a conditionally activated then-layer, it seems useful to me to propagate the locked state from if-layers (i.e. it is locked if all of the if-layers are locked). This'd be necessary to replace the momentariness tracking I mentioned on Discord.

Can you lock on a then-layer using &tog? I would guess not, since it still needs all the if-layers to be active.

I realised that tracking that is unnecessary for this to work as expected. Rather, if both if-layers are locked then the then-layer is semi-locked: If it is deactivated, then on the event triggered by the deactivation the then-layer immediately becomes reactivated.

This also has the effect of allowing the then-layer to be locked using &tog, as if one of the if-layers becomes inactive then the conditional layer effect will try but fail to deactivate the then-layer.

@caksoylar
Copy link
Contributor

I will rewind a bit: I have this momentariness tracking feature which is being used to filter layer change events that aren't "permanent". I am hoping to replace the tracking of momentariness by checking the "locked" state of the highest active layer instead. For that to work:

  • There'd need to be a function like bool zmk_keymap_layer_locked(zmk_keymap_layer_id_t layer) that'd return the state of a layer
  • Conditional layers would need to set the default locked status (check if all the if-layers are locked), before it might be locked directly by e.g. a &tog

@nmunnich
Copy link
Contributor Author

nmunnich commented Jan 5, 2025

I am hoping to replace the tracking of momentariness by checking the "locked" state of the highest active layer instead.

I've added what I believe are the necessary parts to get that to work with the locking system.

@nmunnich nmunnich marked this pull request as ready for review January 14, 2025 14:50
@nmunnich nmunnich requested a review from a team as a code owner January 14, 2025 14:50
@nmunnich nmunnich requested a review from caksoylar January 14, 2025 14:51
Copy link
Contributor

@caksoylar caksoylar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I haven't tested, implementation looks good to me. I left some clean up remarks and some suggestions to think about. While I like the new default behavior of &tog and &to, also worth considering that it will technically constitute a breaking change (alongside the API break in keymap.h).

Also need to update https://zmk.dev/docs/config/behaviors to add the new property.

Comment on lines +43 to +46
int zmk_keymap_layer_activate(zmk_keymap_layer_id_t layer, bool locking);
int zmk_keymap_layer_deactivate(zmk_keymap_layer_id_t layer, bool locking);
int zmk_keymap_layer_toggle(zmk_keymap_layer_id_t layer, bool locking);
int zmk_keymap_layer_to(zmk_keymap_layer_id_t layer, bool locking);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth thinking about adding single param variants as compatibility shims.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought about this for a bit. While it could be done, of the modules that I know of (aka those in the collection) the only one that is affected is auto-layer, which already has code in it to track momentariness. I think it should be ok to break API here, though @urob maybe can chime in?

Copy link
Contributor

@urob urob Feb 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for letting me know. Agree, breaking the API here shouldn't be a big issue for auto-layer. (I adapted the upstream versioning for the module releases. So as long as users keep them in sync, there shouldn't be any compatibility issues).

As an aside, it would be great if breaking API changes like this one could be flagged in the release notes, ideally detailing how the API changed. Otherwise it could get tricky to figure out why things break given how many commits the next ZMK release is going to have.

@nmunnich nmunnich force-pushed the layer-locking branch 2 times, most recently from 3e55050 to 1f890c6 Compare February 25, 2025 15:29
@nmunnich
Copy link
Contributor Author

nmunnich commented Mar 1, 2025

Just realised that this makes #1984 obsolete.

nmunnich and others added 2 commits March 11, 2025 07:54
Co-authored-by: Cem Aksoylar <caksoylar@users.noreply.github.com>
Co-authored-by: Cem Aksoylar <caksoylar@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants