Closed adamgordonbell closed 7 years ago
Yep, I'm currently wanting to do the same thing for my layout, just with '#' instead of '{'. I've had a bit of a look into this and found the cause of the issue.
In QMK keys are stored in 16bits (hence the uint16_t in all the keymap definitions), when are then mapped into actions for the TMK core to process.
For the MT (mod - tap) keytypes 4 of these bits identify the keycode as being a MT keycode, 4 identify the modifiers to act as when held, and 8bits indentify the raw keycode to send when tapped. This allows for a great deal of flexibility - it can hold down any combination of the four left hand modifiers, however as it only stores the raw keycode in 8bits, the original modifier information is lost.
Unfortunately there doesn't seem to be an easy way to allow for any combination of the four left hand modifiers to be active when held, and then any combination of the four left hand modifiers + a raw key to be active when tapped. This would take up 4bits for each modifier set, and 8 bits for the keycode, using up the entire 16bit QMK keycode space.
However, in this case just a single modifier + keycode for tap, and a single modifier when held, would suffice. If we only allow for the 4 left hand modifiers to be use in both cases, we use 2bits for tap and 2bits for hold - 4 bits in total. We can also store the raw keycode in 7bits, as you would not use a modifier when pressing any of the upper 128 keys - a modifier wouldn't change them, and they would generally not be used in keyboard shortcuts.
This allows all the data to be stored in 13bits total, allowing it to fit in the (currently free) range 0x5800 - 0x5FFF in the QMK key codes. It can also be implemented as a TMK action with the currently reserved 0b0111 action_kind.
I'll name this type MTM - Mod Tab Mod, and will try to implement it with the encodings as follows:
QMK key
0101 | 1tth | hkkk | kkkk
TMK action
0111 | 0tth | hkkk | kkkk
t = modifier when tapped
h = modifier when held
k = raw keycode when tapped
Although this allows shifted keys when tapped, as well as basic keyboard shortcuts, there might be a usecase in the future for AltGr international keys. Dunno how that would work...
Edit: I've found a better approach, see below.
Interesting, I'm not totally up on how qmk encodes things. However, I had this working in tmk. You can see how I did it for LCTL_LPAREN. It is super verbose though, and I was porting my keyboard to qmk to get a more concise, clean, keymap. https://github.com/agbell/tmk_keyboard/blob/cub_layout/keyboard/ergodox/keymap_adam.h
Ok. I got it working through a similar hack - not through the native QMK keycodes as I was planning before.
I've made it instead be a 'tapped' macro, and then sent out a different macro depending on whether the key was tapped or held down. The benefit here being that the macros are a lot less verbose than the multiple lines of C code you had.
See here for basic approach: https://gist.github.com/LukeSilva/4662de28caba161b8823d8727559b309
The benefit of having macros here is that you can simply do a whole lot more - tap for AltGr symbols, tap for _, hold for a different layer, although it is a little verbose. To clean this approach up a little, I created a C macro which expands to do all the checking and return the appropriate macro.
See here for cleaner code: https://gist.github.com/LukeSilva/e76815d978d7d09ef01421ee4ff8d9e5
If this is going to be properly fixed, I think we should try to take care of handling all combinations of modifiers, not only left hand side ones.
That has been reporter at least here #524 and #968.
@LukeSilva Your work around will work for me for now, Thanks! It is more concise than what I had.
https://github.com/agbell/qmk_firmware/blob/master/keyboards/ergodox/keymaps/adam/keymap.c
Yes, For the moment I believe that the workaround with macros is better than adding new QMK and TMK keycodes and actions. The macro approach is a lot more flexible, and is still relatively clean.
Pull request #1046 serves to bring a set of C defines into the core code, to make this approach relatively easy.
I've been able to achieve this functionality using the tap dance process. https://gist.github.com/SjB/1071122648256b849ea5ab8e732cc0c5
I am trying to map a key to Alt when held and { when tapped, but it does not seem to work. I get '[' with ALT_T(S(KC_LBRC)) and with ALT_T(KC_LCBR).