-
-
Notifications
You must be signed in to change notification settings - Fork 39.8k
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 the layer-dependent modifiers handling #182
Conversation
This fix quite deeply modifies the implementation of key releases, I wonder if it is really safe. It does not only affect the modifiers but actually all the keys are affected. In fact, I think the current behaviour is really intentional as ( Finally, I think this behaviour should thus at least be optional, independently of The documentation should also specify more clearly that (without this fix) the destination layer should contain the mods at the same place between layers – that is, if the user intends to switch layers while those mods are depressed. |
It's really an interesting patch that opens new possibilities, yes give it it proper symbol definition and not relate it to |
That's true and I'm eager to hear about the potential issues. I was using it for a few days and so far so good but we all know how these things tend to be.
Kind of. Calling clear_keyboard_but_mods() prevents most keys from being stuck while still allowing to combine the modifiers and keys from different layers. I think this specific behavior is a bug.
I'm aware of it. I considered storing a top-most layer number (uint8_t) for each key (taking the transparent keys into account of course) but I wanted to keep it simple for now. If the patch makes sense, I'll try to optimize it for memory.
Makes sense. Should I do these things or leave it for someone knowing the project's conventions? |
I've just noticed another benefit of my patch. Until now, when I used a DF() key placed on a layer to change the default layer, I needed to enable a layer it was on, press it, release it and then disable the layer. I could not release the layer before releasing the DF() key. Now the order of releasing the keys doesn't matter. |
As for updating the docs: Please just go ahead and update the main readme.md at the root directory as part of this PR. I may suggest tweaks but obviously since this is your code you know exactly the intent behind it. Reading this from the standpoint of a user, I'll try to summarize the rationale, please tell me if I got it. This patch addresses the following scenario:
Is this correct? With this patch, it would "remember" that I started out with Shift in that key, and treat the keyup event as "un-shift" in this case? If so, I am not sure I understand the side effects we should watch out for. @DidierLoiseau, any chance you could explain a bit more? What's the danger in this change, where would it be surprising? |
@ezuk Almost correct. This scenario works correctly if you release the layer modifier before releasing your Shift/R. If you release Shift/R before returning to Layer 0, well, then it becomes problematic (until you press and release Shift again). I've just modified readme. I've also added an optional macro enabling this feature. @Eric-L-T It depends on the user. For example it really bothered me and using such constructs for each key is quite syntax-heavy. Is it ok as an optional feature? |
@Eric-L-T I read a bit about the weak mods and tried your solution. Unfortunately it does not achieve the same result. My solution allows to hold a modifier, switch layer and press some key affected by the said modifier. Weak mods are cleared on layer switch. I've also encountered my first problem with my patch. I have a layer activated by holding two modifiers (link) and two macros allowing me to release either one and end up in one of the other layers (link). It no longer works because I am now releasing the original key. Any ideas for improvement and/or workaround? |
@vifon this is indeed the kind of issue I was thinking of. I intend to implement a similar behavior in my keymap but I wasn't sure exactly how this patch would affect it. The "workaround" I see would be to implement this kind of layer switching with macros only, and test in the macros which layers are active. But I find it a bit cumbersome… |
@DidierLoiseau I managed to solve it like this: vifon@3c04721 |
@vifon I see. What's a bit hidden now is that when you are in BTW in which case are you switching layouts while holding modifiers? If I had to cast a vote, I think this PR should be merged now that 8d55a12 has made it optional :-) |
@DidierLoiseau Yes, the macro on release depends on the order of enabled layers but both release actions are essentially the same. The state is consistent. I switch layers for example in the following scenario. On my keyboard layout (the software one in the OS) I input umlauts by pressing AltGr+[ and then a letter, for instance o. My AltGr is on the layer 0 but [ is on |
If one wants to temporarily disable the key cache (for example because it interferes with a macro), `disable_action_cache` must be set to `true`. `process_action_nocache` is a simple wrapper doing just that for a single call.
I've added a new Without it the release events were never intercepted by my recording keymap and were not recorded properly. |
I'm not actually sure where this PR stands. @vifon, @jackhumbert, @DidierLoiseau - any thoughts? Are we going to merge this? |
I still want to optimize the used memory, together with @Eric-L-T, but the functionality shouldn't change. I have some additional changes on my |
I think that'd be good, yes. Let's consolidate all related changes so we can discuss and review. As for the memory considerations: Assuming we're not hitting the Teensy's memory limit, what's the implication here? I mean, of course it's great to conserve memory, but:
Asking dumb questions so I can really understand what's at stake here -- whether we're talking aesthetics (which are important) or functionality (which is crucial obviously). |
I've added the rest of the commits. ad. 1) No, it's enabled in compile-time so it will change nothing unless enabled. ad. 2) If user's other features use considerable amount of RAM, they may have not enough after enabling this feature, that's all. For example my macro recording is quite memory-hungry so it was a concern for me. Anyway, the memory consumption is constant per keyboard (2 bytes per physical key). |
Given your answers to 1 and 2, I'd say from a pragmatic standpoint memory consumption is not a deal breaker here. We need to be sure to note in the docs that this is a memory-hungry feature, and perhaps optimize in time -- but it's nice that it simplifies layer management. @DidierLoiseau what are your thoughts? And @jackhumbert? |
…firmware into modifier-release-fix
- remove a superfluous parenthesis - wrap lines longer than 80 characters - add const specifiers where appropriate - remove unnecessary casts
958ab1c
to
4dce725
Compare
- new macro_mods bit field for mods applied by macros - weak_mods now only used for ACT_{L,R}MODS (i.e. LSFT, RSFT, LCTL etc.) - clear the _weak_ mods on every key *pressed* such that LSFT etc. can no more interfere with the next key
@vifon nice! Can't merge due to conflicts though, could you fix? And then let's ask @jackhumbert for feedback, and maybe @DidierLoiseau too |
…into modifier-release-fix
I've resolved the conflicts. @jackhumbert, @DidierLoiseau, could you take a look? |
I think this is a nice improvement and having it optional makes sure it won't impact anyone who doesn't use it. However I am not really convinced by the last optimisation that reduces the memory consumption to 5 bits per key (instead of 1 byte). The code has become hard to understand and maintain and I think the previous optimisation to only store the layer was already sufficient (down to 3.3% of the memory for an Ergodox). I think if we wanted to improve the memory consumption further, it would be better to switch to a simple array storing p.s.: I just figured I had overestimated the memory consumption in my first comment: it was actually around 6.6% instead of 10% for an Ergodox. |
I agree with @DidierLoiseau, and this sounds cool! Let's get this merged :) |
Just to be clear: It still stores only the layer number. The layer number is <32, so we need only 5 bits to store it. Conceptually it still does the same thing, only the encoding differs. In case you want to revert to the "1 byte per key" version, revert 8ef14d0, 4dce725 and 97cc44e. That should be enough. I've got my doubts about the maintainability of this version too, though I cannot deny its efficiency.
I don't get how it would be more memory efficient. Can you elaborate? @jackhumbert Is there anything else I need to do before you merge it? |
I've refactored the source layer cache code a bit and moved it to |
@vifon We could define a struct like typedef struct {
uint8_t row :5;
uint8_t col :5;
uint8_t layer :5;
uint8_t active :1;
} pressed_key_t; and store the pressed keys in an array defined as pressed_key_t pressed_keys[KEYBOARD_REPORT_SIZE]; (this could have preprocessor conditions to choose the appropriate size of each field) When a key is pressed, record the pressed key in the first entry that has I used NB.: I don't pretend to be a C expert so don't hesitate to correct me if I made mistakes. |
@DidierLoiseau NKRO allows only 16 keys? I didn't know that... Well, in that case it should be possible. |
- Idea form qmk/qmk_firmware#182 - Define NO_TRACK_KEY_PRESS to get old behaviour - This should resolve #105, #248, #397, #441 and FAQ entry: https://github.com/tmk/tmk_keyboard/wiki/FAQ-Keymap#modifierlayer-stuck
- Idea form qmk/qmk_firmware#182 - Define NO_TRACK_KEY_PRESS to get old behaviour - This should resolve tmk#105, tmk#248, tmk#397, tmk#441 and FAQ entry: https://github.com/tmk/tmk_keyboard/wiki/FAQ-Keymap#modifierlayer-stuck
- Idea form qmk/qmk_firmware#182 - Define NO_TRACK_KEY_PRESS to get old behaviour - This should resolve tmk#105, tmk#248, tmk#397, tmk#441 and FAQ entry: https://github.com/tmk/tmk_keyboard/wiki/FAQ-Keymap#modifierlayer-stuck
- Idea form qmk/qmk_firmware#182 - Define NO_TRACK_KEY_PRESS to get old behaviour - This should resolve #105, #248, #397, #441 and FAQ entry: https://github.com/tmk/tmk_keyboard/wiki/FAQ-Keymap#modifierlayer-stuck
* launchpad default keymap * change keymap name to avoid errors
Add vial support for Angler2
Closes #181.
I'm aware the function naming could be better. I'm open to suggestions.