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

no tricks with modifiers? #215

Closed
hontvari opened this issue May 16, 2015 · 16 comments
Closed

no tricks with modifiers? #215

hontvari opened this issue May 16, 2015 · 16 comments

Comments

@hontvari
Copy link

I would like to use base row keys as modifiers.

First I tried to map modifiers to base row keys using the tap feature. As it turned out, this does not work, because I frequently press the next key before I (or the spring) release the first key. For example:

  • Press F key. It is defined as a SHIFT modifier if it is held down, and as F if tapped.
  • Press O. It is a normal key.
  • Release F
  • Release O

The intention here is clearly to type "fo". But it is registered as an upper case "O". The solution does not seem to be easy:
-If a tapping modifier is held down, key presses for any other keys must no be registered at the moment of the key press. The key press of the second key can be registered when:
-the tapping modifier key (F) is released. Register "fo".
-the normal key (O) is released. Register "O".
-neither is released, but a timeout occurs. Register key presses SHIFT, O.

Second I tried layers. This means that I have to press a very easily accessible momentary layer switch, a modifier key defined on that layer on the base row, and finally the printable key. This attempt was also failed. The problem here is that the order of the modifiers does count. For example:

  • press and hold the layer switch (which is a redefined thumb key)
  • press and hold CTRL (which is the physically labelled as the V key)
  • press and release S (the document is saved, so far so good).
  • release the layer switch
  • release CTRL (the key labelled as V)
    It seems as success, but the CTRL key is stuck in.

The solution, again, is not simple. When a layer is switched off, all keys which is pressed at that time, and which has a different keycode on the new layer must be noted. For all of such keys a release event must be sent immediately (in which order?). Further, when these keys are actually released, the release event must be swallowed.

All in all, I do not see a way to define a dual-function key which is a modifier in at least one of its roles. Modifiers must be left alone, the maximum which is feasible is to move them around, but a modifier key must be the same modifier key on all layers and it must not have any other function via tapping.

Background:
It has been always a pain that I cannot press modifier combinations during touch typing. I also have to use 9 accented characters which results in a crammed layout. Then I saw the picture of the Space Cadet keyboard and immediately became enlightened. Modifier combinations could be touch typed effortlessly, as well as national characters... 30 years ago... on a proper keyboard. So I want to create something similar using an Ergodox. For this I need many modifier keys, especially because they since started to combine level keys (SHIFT) with bucky bit keys (CTRL) (which is a really bad idea, but without proper keyboards it is understandable).

This report is partially a request for comment/confirmation, partially a documentation of my experiences, which may be useful for others.

@tmk
Copy link
Owner

tmk commented May 16, 2015

I didn't experience your first problem, I think it should register 'fo' as long as you release 'f' key within TAPPING_TERM. TouchCursor has very clever and concise implementation of dual role key, you can refer its code if you want to look into more deep, while TMK tapping code is mess.
http://touchcursor.sourceforge.net/

Some issues about tapping are filed, they may be related.
#85
#49

The second problem is not related to tapping, it is a limitation of TMK keymap system. Yes, you must place same modifier on a key of all layers. In other words you cannnot change modifier key to other key with layer switch at the moment at least. Unfortunately TMK doesn't support what you want here.

@hontvari
Copy link
Author

Thanks for the reply. I reinstalled the first firmware for testing. I can easily reproduce the issue. I very-very quickly press F and O after each other (much faster than during real typing), but I make sure that O follows F. In almost 100% it results in an "O" and not an "fo".

While I typed the above sentences I also experienced the issue several times. I am using cubuanic's Ergodox fork, and it is a bit older. But I have already read the changelog here and I do not see any commit which could be related to this. I have no idea how you could reproduce the issue.

This is the line which defines the tapping F key:

    #define KC_F_Sh                                KC_FN7
    [7] =   ACTION_MODS_TAP_KEY(MOD_LSFT, KC_F),

@hontvari
Copy link
Author

@tmk
Copy link
Owner

tmk commented May 16, 2015

Are you sure that you release 'f' key first?
You will get 'O' if you release 'o' key before releasing 'f' key. If you are sure I think it is a bug, I'll try your setting and look into Tapping code. If your type are fast enough and the situation can be occured you will need change TMK Tapping code.

TMK Tapping function was implemented for my type fingering and speed in heuristic and adhoc way, so it is not enough configurable to cover every situations for people.

And right, I also think cubuanic's is not old for Tapping.

@hontvari
Copy link
Author

I am pretty sure that I release first, but the spring and the hardware scan process can also have an effect. Also I really-really do not want to take your time with a false report, so I would like to give you some evidence instead of relying on my feeling. I started xev here is the result:

KeyPress event, serial 37, synthetic NO, window 0x4c00001,
    root 0xbb, subw 0x0, time 179948790, (391,952), root:(2376,1004),
    state 0x0, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyPress event, serial 37, synthetic NO, window 0x4c00001,
    root 0xbb, subw 0x0, time 179948974, (391,952), root:(2376,1004),
    state 0x1, keycode 32 (keysym 0x4f, O), same_screen YES,
    XLookupString gives 1 bytes: (4f) "O"
    XmbLookupString gives 1 bytes: (4f) "O"
    XFilterEvent returns: False

KeyRelease event, serial 37, synthetic NO, window 0x4c00001,
    root 0xbb, subw 0x0, time 179948982, (391,952), root:(2376,1004),
    state 0x1, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyRelease event, serial 37, synthetic NO, window 0x4c00001,
    root 0xbb, subw 0x0, time 179948990, (391,952), root:(2376,1004),
    state 0x0, keycode 32 (keysym 0x6f, o), same_screen YES,
    XLookupString gives 1 bytes: (6f) "o"
    XFilterEvent returns: False

Does this help?
(It says Shift_L, but I press the physical F key of course, i.e. the the forth key in the base row)

@adamgordonbell
Copy link

@hontvari I've gone with layers for modifiers in the home row, its a bit hacky but you can see some of it in action in my comment on #85 . I found it works way better than the tap keys, but you have to have the key in the layer you fall to be empty, if that makes sense, or you never pop up out of layer.

I have a ctrl layer, alt layer, and so on. I problem I have found is that I need more than 32 function keys at each layer.

I'm not sure how layer tap is handled differently then mod tap, but I really wish there was a way to make mod tap work the same as layer tap and then I wouldn't need all these hacks.

@tmk tmk added the TODO label May 22, 2015
@tmk
Copy link
Owner

tmk commented May 22, 2015

hm, I tried ACTION_MODS_TAP_KEY and I also found it doesn't work, as you said.
I'll look into this some later.

@adamgordonbell
Copy link

@tmk That would be some great if you could figure it out. Having my various home row keys also be modifier keys when held is really great! I think with this firmware I'm pretty close to not needing a dedicated CTRL, ALT or FN key. Right now, just having to use layers for it, and running out of function keys is my only issue. If ACTION_MODS_TAP_KEY could work as a home row key, it would be awesome.

@tmk
Copy link
Owner

tmk commented May 22, 2015

Current implementation of ACTION_MODS_TAP_KEY works like 'modifier key' rather than 'alpha key'. (I don't remember this was my intention or not, though :D)

Try this patch, it works like more 'alpha key'.

--- a/tmk_core/common/action.c
+++ b/tmk_core/common/action.c
@@ -142,15 +142,17 @@ void process_action(keyrecord_t *record)
                     default:
                         if (event.pressed) {
                             if (tap_count > 0) {
+/*
                                 if (record->tap.interrupted) {
                                     dprint("MODS_TAP: Tap: Cancel: add_mods\n");
                                     // ad hoc: set 0 to cancel tap
                                     record->tap.count = 0;
                                     register_mods(mods);
                                 } else {
+*/
                                     dprint("MODS_TAP: Tap: register_code\n");
                                     register_code(action.key.code);
-                                }
+//                                }
                             } else {
                                 dprint("MODS_TAP: No tap: add_mods\n");
                                 register_mods(mods);

As @AGBell referred, this shares root of the problem with issue #85 essentially.

@adamgordonbell
Copy link

@tmk This works! I am going to test is some more, but it seems like a fix for #85, except for the repeat issue.

@Zutatensuppe
Copy link

The patch is working great, any reason why it is not included into the repository? Or is it otherwise "fixed" already?

@tmk tmk added the KEYMAP label May 30, 2017
@tmk
Copy link
Owner

tmk commented May 30, 2017

Second problem was fixed at ba2883f

@adamgordonbell
Copy link

@Zutatensuppe It was included in qmk under the flag IGNORE_MOD_TAP_INTERRUPT, I believe.

I also have an open PR for a flag called PERMISSIVE_HOLD, in QMK, which tweaks the hold logic a bit more in the direction that worked for me. qmk/qmk_firmware#1359

@tmk tmk added NOTE and removed TODO labels Jun 3, 2017
@tmk
Copy link
Owner

tmk commented Jun 3, 2017

Thanks for letting us know.
It is nice to have options for tapping configuration.

For future refernece, QMK has build option IGNORE_MOD_TAP_INTERRUPT to change ACTION_MODS_TAP_KEY behaviour as discussed here.
https://github.com/qmk/qmk_firmware/blob/732a115b32a9c6aa529c53ef52a9689b5901411d/tmk_core/common/action.c

Use #85 for further discussion.

@tmk tmk closed this as completed Jun 3, 2017
@adamgordonbell
Copy link

Thanks for all your great work on this firmware @tmk. I don't know the code base like you, but I had an idea I thought I would throw out. Would it be possible to represent the idea of a key being currently held, as a first class value in tmk. So, instead of needing timers since key down, you could always read the state of what keys are being held down at time of key press. It might not be possible but seems like it would simplify things.

@tmk
Copy link
Owner

tmk commented Jun 4, 2017

I'm not sure what your idea is but dual-role key can be implemented without timer, I think Touchcusor does like that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants