zmkfirmware / zmk

ZMK Firmware Repository
https://zmk.dev/
MIT License
2.77k stars 2.81k forks source link

Feature: "Shifted Keycodes", e.g. assigning `!` to a key press or mod-tap behavior. #86

Closed petejohanson closed 3 years ago

petejohanson commented 4 years ago

Potential fix/idea:

BrainWart commented 4 years ago

For people who can't wait for a better solution, brainwart/zmk@e09246a8e664c2e873a21cd8d4903f445156c51d

This does not add new keycodes. It just applies two keys one after another. Usage: &mkp LSFT NUM_7

okke-formsma commented 4 years ago

I have an implementation proposal for this in https://github.com/okke-formsma/zmk/tree/modifiers / https://github.com/zmkfirmware/zmk/pull/153

It brings the following changes:

The mods are implemented as flags in the third byte of the keycode. This overloads the keycodes a bit, but I feel that's warranted in this case.

There has been some discussion about this on discord: https://discordapp.com/channels/719497620560543766/719544230497878116/751160749203652649

okke-formsma commented 4 years ago

We had a chat on discord about not adding shifted keycodes to the default codes, as they are locale-dependent. (e.g. shifted keycodes result in a different character being typed depending on Dutch/Belgian/French/German/..., UK or US setting.)

By forcing users to use &lsft NUM_3 or &kp (NUM_3 | LSFT), we make them aware of what is happening.

innovaker commented 4 years ago

Would this syntax (using MACROs) be more robust in terms of future implementation refactoring? LCTRL(LSFT(A))

It looks uglier, but it could be eased with composite convenience MACROs such as: LS() LCS() LSC() LCSA() etc.

This would hide some of the implementation detail (bit masks) on primarily user-facing code, potentially easing localized refactors?

tominabox1 commented 4 years ago

I like the idea of concatenating mods like this fwiw

I would love to not use pipe's in my code because I don't know where I put them on my keyboards haha

innovaker commented 4 years ago

This syntax would probably also transfer better into whatever supersedes DT/DDM for keymaps/bindings/behaviours, in the future.

okke-formsma commented 4 years ago

discussed on discord https://discordapp.com/channels/719497620560543766/719544230497878116/770359370814586950

#define LS(keycode) (MOD_LSFT << 24) & keycode)

okke-formsma commented 4 years ago

The modifiers branch now includes "implicit" and "explicit" modifiers. An modifier is "explicit" when it's called like &kp LEFT_CONTROL. A modifier is "implicit" when it's added to another key; &kp LC(A).

Explicit modifiers are held until their key is released.

Implicit modifiers are held until their key is released or another key is pressed. This makes rolling over modified keys possible; pressing LS(A) and then B, and then releasing LS(A) and B should output "Ab" (and not AB).

There is one known issue in the current implementation. Implicit modifiers are also released when other keys are released. namely that implicit modthat's not supported: A down, LS(B) down, A up, (wait) LS(B) up. The expected output would be aBBBBBBBBBBBBBB but the actual output is aBbbbbbbbbbb because the shift modifier is released when the A key is released.