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

Double tap & interrupt questions #411

Closed
algernon opened this issue Jun 15, 2016 · 17 comments
Closed

Double tap & interrupt questions #411

algernon opened this issue Jun 15, 2016 · 17 comments

Comments

@algernon
Copy link
Contributor

This is more of a question than an issue, if this is not the right place to ask these questions, please direct me to the right forum.

What I would like to achieve, is to have a number of double-use keys, that input one symbol when tapped once, and another when tapped twice. This works reasonably well when one of the keys is a modifier, but if I want one tap to be :, and double-tap to register ?, that's not really possible, not without ill side-effects.

If I make an Fn key out of it, that calls ACTION_MACRO_TAP(), then when I tap the key once, we hit both the pressed and the released events, then when I tap it a second time, we hit them again. So to be able to register ? only, I need to postpone registering : until the multi-tap is interrupted, or it times out. The timing out part is the easier case, but interruption does not work as I'd wish: if I tap : and a in quick succession, a may come out first.

What I'd want to do, is a simple way to say: I want : when tapped once, and only once. If I don't tap anything for the next TAPPING_TERM, register it. If I hit any other key, register : first, before the other key. If I hit the key again, and double-tap it, give me an ?. Preferably, I'd do this without having to add tons of boilerplate.

Is this reasonably possible right now? If so, what am I missing?

@eltang
Copy link
Contributor

eltang commented Jun 15, 2016

You can just delete the first character on the second tap.

@algernon
Copy link
Contributor Author

I have experimented with that, but that looks terrible on the screen, and does not work when I want to use it for a chord or as a key sequence. For example, Space : a is, in my Spacemacs config, very different from Space ; Backspace : a.

So deleting works for some cases, but for a number of things I'd want this for, it doesn't :(

@jackhumbert
Copy link
Member

This is the same sort of problem that I've encountered with implementing double taps on touchscreens, and I would imagine an implementation here would have similar frustrations - the time between taps is just too long, and makes regular input "laggy" to some degree. It's definitely possible to implement, and many mobile devices still do.

If you're only wanting the double-tap feature on some keys, you can enter a double-tap mode, which would basically record keypresses for the delay time, then sort out what to do with them (in order) once it's been established that it's a single or double tap (or even triple/whatever). There will always be a delay when using that key/the keys after it, but I would imagine it'd be something you could deal with. That sort of input lag (everything still processed and in order) is something I know I've gotten used to when my computer is working overtime :)

If you have a speaker on your keyboard, you could use that for quick feedback that you're double-tapping, so your know that your presses are being acknowledged. I would imagine feedback on the single tap would be a little more annoying, but maybe not!

Something else to consider here is a dedicated leader-type key that can be tapped more than once before a sequences begins. There's no delay associated with that since it's a dedicated key.

@algernon
Copy link
Contributor Author

The lag is, indeed, not an issue, as long as playback is in order. I'm very used to that, it happens all the time when I type through mosh and a flaky connection.

The leader-type key idea sounds interesting, but my sequences would me one or two keys, and with a leader-type solution, I'd either have to tap one more, or use two keys: a leader, and a sequence key. The goal is to have one single key.

Case in point, consider this layout:
base-layer

There is the :; key on the left side, easy to tap with my thumb, just need to move it towards my palm. However, to access ;, I need to hit shift, which is also hit by the same thumb, and then it has to move quite a lot. This is one of the reasons I am looking for a way to be able to just double-tap the :; key, and get a semi-colon only.

I did consider implementing a kind of recording, but for that, I'd need to reach into deeper levels of the firmware than I am familiar with, but I guess I'll have to... or find another way to input ;... like LEADER :, hmmm...

I suppose that should work too, and solves my immediate problem.

Thanks for providing some material I could spin my brain on! :)

@jackhumbert
Copy link
Member

Ah, I gotcha. If you're interested in implementing the recording thing, check out the leader key implementation here. It basically does what you'd need to do to capture the keypresses, except that you'd need to capture keyups as well, and store that information - the only other things you'd need to change are the conditionals that decide when things are recording, and the array's size. The final implementation would need to change as well - that could really be put anywhere, but probably makes the most sense as a macro like the LEADER_DICTIONARY, so you can customise it in the keymaps. That's defined in the quantum.h file.

@algernon
Copy link
Contributor Author

Will have a look at that, when I have more than a few minutes of keyboard-hacking time, thanks!

@eltang
Copy link
Contributor

eltang commented Jun 15, 2016

I don't believe that an entirely new feature has to be created. The current tapping code already has most of the pieces in place, and all that needs to be done is expand it.

@piotr-dobrogost
Copy link

@algernon

However, to access ;, I need to hit shift, which is also hit by the same thumb, and then it has to move quite a lot.

I think the best thing one can do with programmable keyboard is to place modifiers on home row; full set (alt, ctrl, shift, meta) on each side. This makes each shortcut accessible instantly. This single modification had the biggest impact on comfort in my case. Have you tried this?

@eltang
Copy link
Contributor

eltang commented Jun 15, 2016

@piotr-dobrogost I wholeheartedly agree. Modifiers on both sides are a must.

@jackhumbert
Copy link
Member

@piotr-dobrogost do you have your keymap up here anywhere?

@algernon
Copy link
Contributor Author

@piotr-dobrogost

I think the best thing one can do with programmable keyboard is to place modifiers on home row; full set (alt, ctrl, shift, meta) on each side. This makes each shortcut accessible instantly. This single modification had the biggest impact on comfort in my case. Have you tried this?

I tried that, and hated it. I could only put them under my pinky, and that wasn't good - it's ok on something small like the TypeMatrix I used before, but on an ErgoDox, that stretch is not comfortable for me. Besides, Shift is one of my most used keys, not going to put such a frequent key under the pinky. On the thumb cluster, as a one-shot modifier, it's much more practical for me. I also don't need two of them, because I never hold it, so reaching the next key is easy, unless the next one's a thumb key too - and then, only when the other key is on the same side.

I'd rather have the modifiers on one thumb cluster (Alt and Ctrl I rarely use anyway, GUI sees more use in my daily workflow), and use the wide keys on the sides for something else. You see, I live in Emacs. Ctrl-c and the rest of the common shortcuts do not apply to me. My shortcuts either start with a Space, or one of the alphanumeric keys, modifiers are used only for rare stuff.

This works for me, I did pretty extensive tests to see what layout works best, and this layout of modifiers is what I'm sticking with.

As for the feature - I have not looked at the leader key code at all yet. If it can be extended, instead of a whole new feature built, rest assured I will extend. I'm a lazy person, not going to do needless work if I can avoid it :)

@piotr-dobrogost
Copy link

@algernon

I could only put them under my pinky, and that wasn't good - it's ok on something small like the
TypeMatrix I used before, but on an ErgoDox, that stretch is not comfortable for me.

I'm confused. One types on home row keys using all fingers but thumbs. Why pinky only, what stretch do you have in mind? Could you elaborate?

Besides, Shift is one of my most used keys, not going to put such a frequent key under the pinky.

I have pinky -> meta, ring -> shift, middle -> ctrl and index -> alt on both sides. You can avoid pinky by using some key outside of home row but within comfortable reach (like "e" or "i") – see the strain map at http://www.workmanlayout.com/blog/#design.

I'd rather have the modifiers on one thumb cluster (…)

Placing modifiers on thumb clusters generally do not work as you can't press combos easily then. Besides thumb clusters on ErgoDox are so bad…

Alt and Ctrl I rarely use anyway (…)

Well, I guess this is rather uncommon and surely leads to rather unique layout.

My shortcuts either start with a Space, or one of the alphanumeric keys (…)

How is this even possible?

@jackhumbert

Not yet :)

@algernon
Copy link
Contributor Author

I'm confused. One types on home row keys using all fingers but thumbs. Why pinky only, what stretch do you have in mind? Could you elaborate?

On my ErgoDox, I can reasonably put modifiers to the following places:

  • On either side, onto the wide buttons, which are to be hit by the pinky. My pinky is short, to reach any of those wider keys (save the one on the home row), I'd either have to move my hand slightly, or strecth my pinky. Neither is something I want to do when reaching for modifiers.
  • On the bottom row, which is something I rarely use, because I find it uncomfortable to reach, unless I move my hands, which I'd like to avoid.
  • On the tall keys at the inner side of each half, but I have brackets there now, which I use often, and would miss it dearly, if I had to move them elsewhere.
  • On the thumb cluster.

I went with the thumb cluster, because all of my modifiers are one-shot, I never hold them. So I just smash them with my left thumb, and the next key is pressed by whatever finger is needed for it. This puts some good work on the thumbs, my strongest fingers.

See the picture above, with my layout.

I have pinky -> meta, ring -> shift, middle -> ctrl and index -> alt on both sides. You can avoid pinky by using some key outside of home row but within comfortable reach (like "e" or "i") – see the strain map at http://www.workmanlayout.com/blog/#design.

This assumes a traditional keyboard - my TypeMatrix is like that, and I have no problem reaching the sides with my pinky, the keyboard is compact. With the ErgoDox, it's different.

Placing modifiers on thumb clusters generally do not work as you can't press combos easily then. Besides thumb clusters on ErgoDox are so bad…

As I said, I do not press combos. I have one-shot modifiers, I tap them, and press another key. This makes it very convenient to have them on the thumb cluster, no finger-jamming or twisted finger positions involved.

I find the thumb cluster reasonably ok - it could be better, but I can hit 3 keys easily, and that's enough to give my thumbs a reasonable amount of work, and I can use the rest for less used keys, because moving my hand to reach them is okay, once in a while. I only want to avoid hand movement when done regurarly.

How is this even possible?

Spacemacs & modal editing :)

@eltang
Copy link
Contributor

eltang commented Jun 15, 2016

@algernon Just so we're clear, I'm talking about the code in action_tapping.c, not the code in quantum.c.

@algernon
Copy link
Contributor Author

@eltang Yup, got it.

@algernon
Copy link
Contributor Author

Turns out this was easier than I imagined. All I had to do was to have a custom code I can process with process_user_record, do some tap counting there, and set a timer I can check in matrix_scan_user. While my current solution is not generic, and is a tad ugly too, it does work.

See here for the interesting bits of how it can be done.

The way it works is as follows: I count the number of times the key was pressed, and don't do anything until either another key is pressed, or the timer fires (this latter I check in matrix_scan_user). If either happens, depending on the counter, I register : or ;.

Thus, my immediate issue is fixed, this can be done on a per-keymap basis, and isn't terribly hard, either. As such, I am closing the issue. If I get around to implement this in a more generic way, I'll open a pull request. If you think this should be kept open nevertheless, please reopen it.

Thanks for the help here, and in other issues like #303 where I borrowed the idea from!

@jackhumbert
Copy link
Member

Awesome :)

BlueTufa pushed a commit to BlueTufa/qmk_firmware that referenced this issue Aug 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants