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

Feature request: toggle() with timeout #671

Open
lobre opened this issue Feb 23, 2024 · 6 comments
Open

Feature request: toggle() with timeout #671

lobre opened this issue Feb 23, 2024 · 6 comments

Comments

@lobre
Copy link

lobre commented Feb 23, 2024

In the following issue, there was a discussion about adding a timeout to a oneshot.

#277

I find it really useful. One of the principles that I follow when configuring keyboards and layers is that I should always know where I am (on which layer), and if this is not the case I should have a straight path to my base layer.

Ben Vallack talks about this "getting home" principle on his Ferris keyboard in the following video:

https://www.youtube.com/watch?v=8wZ8FRwOzhU&t=330s

He uses layer locks, so he can easily let the keyboard in a layer away from home. To remedy that, he creates a combination of keys that will always go back to the base layer, whatever the current layer.

Toggled layers do have the same problems as those layer locks. The keyboard can stay locked without you knowing. Apart from setting up a combination to go home, another solution could be a timeout.

I find it even simpler, you just have to be patient to go back to the base layer.

Let’s take the example of having shift+shift locking the shift layer:

[shift]
shift = toggle(shift)

I suggest adding a global option named toggle_timeout that would cancel the current toggle operation if no keys are pressed during <timeout>ms of time.

For my example, let’s say I have 2000ms for this setting. This way, I could shift+shift, and then before the expiration of the timeout, I can start typing uppercase. As long as I type letters, the timeout gets reset. If I stop typing and those 2000ms elapse, I would be turned back to the base layer.

What do you think? Is there a way to achieve this behavior without adding this feature?

@nsbgn
Copy link
Collaborator

nsbgn commented Feb 25, 2024

I can imagine the use of a layer that stays on for as long as you keep typing, though I'm not sure that globally attaching that behaviour to toggle is the way to go (I imagine that it's something to decide on a per-layer basis).

I believe that your example can currently be achieved by chaining oneshotms and using the global oneshot_timeout to handle the expiry. That is:

[global]
oneshot_timeout = 2000

[shift]
shift = oneshot(pshift)

[pshift:S]
a = oneshotm(pshift, A)
b = oneshotm(pshift, B)
# etcetera

This does have some drawbacks - feel free to argue :P

@lobre
Copy link
Author

lobre commented Feb 26, 2024

I imagine that it's something to decide on a per-layer basis.

I did not think about it this way, but you are right, this might be a better perspective on the problem.

Thanks for providing a solution. Not sure I like it, as I need to redefine the whole layer though for such a "simple" usecase. I was expecting my keyd config to stay relatively small and understandable ^^.

@rvaiya
Copy link
Owner

rvaiya commented Mar 7, 2024

One of the principles that I follow when configuring keyboards and layers is that I should always know where I am (on which layer), and if this is not the case I should have a straight path to my base layer.

I agree that this is desirable property of a layout. My own solution to it is to minimize layer depth (I am only ever one layer deep) and to define a key which consistently clears all auxiliary layers (capslock in my case, which also functions as control/escape in my main layer).

All of my toggleable layers thus have :

capslock = clear()

inside of them.

So I can be sure that tapping capslock will restore me to a sane state in the event that my layout stack is borked (which rarely happens since I am in the habit of pressing escape anyway).

I suggest adding a global option named toggle_timeout that would cancel the current toggle operation if no keys are pressed during ms of time.

I am not opposed to this.

I can imagine the use of a layer that stays on for as long as you keep typing, though I'm not sure that globally attaching that behaviour to toggle

Agreed, it should be probably be an action like togglet. I have considered adding something like this previously, as it can be quite useful for things like window manager bindings (tmux does this for window switching if you hit your prefix and then use the arrow keys). There were some other novel use cases I thought of, but they escape me at the moment.

I believe that your example can currently be achieved by chaining oneshotm
[...]
Not sure I like it, as I need to redefine the whole layer though for such a "simple" usecase. I was expecting my keyd config to stay relatively small and understandable ^^.

FWIW, I do something similar with my shift layer:

[main]
shift = oneshot(shift)

[shift]
shift = toggle(shift2)

[shift2:S]
space = togglem(shift2, space)
enter = togglem(shift2, enter)
, = togglem(shift2, comma)
capslock = togglem(shift2, esc)

Which allows me to double tab shift and then type symbol names without having to worry about explicitly deactivating it (since I almost always type space or enter after a capitalized word/symbol). This covers the majority of my non-roid induced use cases quite nicely.

@lobre
Copy link
Author

lobre commented Mar 7, 2024

Thanks for your response! It enlarges the spectrum as I search for a good way to enter capitalized words, whether in code or prose.

This behavior of automatically disabling the "capslock" mode on words seems appealing!

While searching for this, I came across this mode in QMK, which does exactly what I was looking for.

https://github.com/qmk/qmk_firmware/blob/master/docs/feature_caps_word.md

It would be nice if we could get close to that in keyd. Apparently, they think with the opposite mindset. They state that the mode is disabled when the key is not a number, letter, dash, underscore, delete or backspace. I am not sure we can have this negated mechanism in keyd, as we should instead declare which key will disable the mode. Maybe you have an idea to get closer to this QMK word mode?

Caps Word automatically disables itself at the end of the word. That is, it stops by default once a space or any key other than KC_A--KC_Z, KC_0--KC_9, KC_MINS, KC_UNDS, KC_DELETE, or KC_BACKSPACE is pressed.

Though, I think the initial proposition still holds valid. On top of this word mode, having a way to disable a toggle after some time of inactivity is still interesting. By the way, this QMK word mode also has this behavior included.

Caps Word also disables itself if the keyboard is idle for 5 seconds. This is configurable, see below.

@lobre
Copy link
Author

lobre commented Mar 7, 2024

Sorry for the double post, but I thought posting the actual implementation of QMK could be interesting to bring context (it is further down the doc page that I posted also).

bool caps_word_press_user(uint16_t keycode) {
    switch (keycode) {
        // Keycodes that continue Caps Word, with shift applied.
        case KC_A ... KC_Z:
        case KC_MINS:
            add_weak_mods(MOD_BIT(KC_LSFT));  // Apply shift to next key.
            return true;

        // Keycodes that continue Caps Word, without shifting.
        case KC_1 ... KC_0:
        case KC_BSPC:
        case KC_DEL:
        case KC_UNDS:
            return true;

        default:
            return false;  // Deactivate Caps Word.
    }
}

So in this mode, a key will either apply its shifted version, its normal/unshifted version or deactivate the mode.

@lobre lobre mentioned this issue Apr 4, 2024
@lobre
Copy link
Author

lobre commented Apr 4, 2024

I realize by re-reading this that the word-mode is a topic on its own. I have created an issue for this: #711

And so this issue could stay focused on the inactivity timeout that could be attached to a layer (begin a toggle layer or any other kind of layer).

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

3 participants