Karabiner-Elements: __BlockUntilKeyUp__ functionality

I’d like to implement a “SpaceFN” layer (ie. while space is held down, activate another layer).

Here’s a small example showing how to map Space+J to “left”:

{
    "description": "Space + J = LEFT",
    "from": {
        "key_code": "j",
        "modifiers": {
            "mandatory": [
                "fn"
            ]
        }
    },
    "to": [
        {
            "key_code": "left_arrow"
        }
    ],
    "type": "basic"
},
{
    "description": "Space as fn",
    "from": {
        "key_code": "spacebar"
    },
    "to": [
        {
            "key_code": "fn"
        }
    ],
    "to_if_alone": [
        {
            "key_code": "spacebar"
        }
    ],
    "type": "basic"
},

The problem is, space is pressed very often during normal typing, so it is all too easy for this kind of set-up to produce unwanted “fn” presses instead of spacebar presses when typing fast.

With the old Karabiner, __BlockUntilKeyUp__ took care of this quite nicely, or at least, I think it did if I understand its purpose. It basically meant, I think, that it wouldn’t fire one of the layer events unless Space were pressed before another key, and released after the other key:

# This triggers a layer event (ie. LEFT)
Space down ---> J down ---> J up ---> Space up

# This normal roll-over does not trigger a layer event, just SPACE then J:
Space down ---> J down ---> Space up ---> J up

Here’s the full version of the old Karabiner config: https://github.com/wincent/wincent/blob/c250a81d235bef574d3a7cf2f2bb7a585bcd9686/roles/keyboard/files/spacefn.xml

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 6
  • Comments: 23 (2 by maintainers)

Commits related to this issue

Most upvoted comments

@michelkoga: That’s much better. Thanks.

However, I still think I need an equivalent for __BlockUntilKeyUp__. Without this, configurations like the above don’t handle rollover well. I am going to keep playing around and see if I can come up with something in terms of variables and to_if_alone_timeout_milliseconds perhaps, but ultimately I think I need something else.

The new to_if_held_down property allows us to get pretty close to what we would need here, but it is not quite there; given this config:

                        "description": "SpaceFN layer",
                        "manipulators": [
                            {
                                "from": {
                                    "key_code": "spacebar",
                                    "modifiers": {
                                        "optional": [
                                            "any"
                                        ]
                                    }
                                },
                                "to_if_held_down": [
                                    {
                                        "set_variable": {
                                            "name": "SpaceFN",
                                            "value": 1
                                        }
                                    }
                                ],
                                "to_after_key_up": [
                                    {
                                        "set_variable": {
                                            "name": "SpaceFN",
                                            "value": 0
                                        }
                                    }
                                ],
                                "to": [
                                  {
                                    "key_code": "spacebar",
                                    "repeat":  false
                                  }
                                ],
                                "type": "basic"
                            },

We can prevent the SpaceFN layer from kicking in until the key is pressed for a while, and we can still enjoy normal rollover while typing fast. The only gotcha is that initial press of the space bar causes an immediate key-down/key-up to be sent, even if you end up just pressing and holding (ie. your intention is to enter SpaceFN mode). This is very close to being usable now, but I think we still need something like __BlockUntilKeyUp__.

Should this issue be reopened? Seems like it is only resolved for @wincent, but everyone else is still waiting for a fix before spacefn is usable 😃

Let me throw in here the set if heuristics that I’m using in my Linux implementation (in the Xorg input driver): http://www.ljosa.com/~ljosa/software/spacefn-xorg/

I found that simple timeouts were not enough, and that I needed to buffer other keypresses (not just space) until their intention became clear.

I’d second sven’s request. It would have saved me a fair few hours of banging my head against the wall!

The SpaceFN configuration listed here should be updated with the fix by @wincent.