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

After a combo should we resuspend keys (even if they had already been exerted on output)? #31

Open
joshgoebel opened this issue Jun 14, 2022 · 2 comments
Assignees

Comments

@joshgoebel
Copy link
Owner

joshgoebel commented Jun 14, 2022

Please also read issue #9 for the full context here.


Look at this test:

async def test_after_combo_should_lift_exerted_keys():
    keymap("Firefox",{
        K("Ctrl-j"): K("Alt-TAB"),
    })

    boot_config()

    press(Key.LEFT_CTRL)
    await asyncio.sleep(2)
    press(Key.J)
    release(Key.J)
    release(Key.LEFT_CTRL)

    assert _out.keys() == [
        (PRESS, Key.LEFT_CTRL),
        # beginning of combo will release left ctrl since it's not part of combo
        (RELEASE, Key.LEFT_CTRL),
        (PRESS, Key.LEFT_ALT),
        (PRESS, Key.TAB),
        (RELEASE, Key.TAB),
        (RELEASE, Key.LEFT_ALT),
        # but now we reassert left ctrl
        (PRESS, Key.LEFT_CTRL),
        # and finally we release it
        (RELEASE, Key.LEFT_CTRL),
    ]

We hold CTRL a long time, so long that we have to push it to the output... then finally we end up using it in a combo (that it's not part of)... this means we have to temporarily lift it from the output (to send the combo)... then after the combo is sent we immediately re-exert Ctrl on output since it's still held down.

That is the current behavior... but since we just "spent" the modifier on the combo... should we instead decide to suspend it after the combo has completed? IE, put it back in the "we don't know what to do with it yet, lets wait and see" queue... until the timeout again fires and we have to resume output...

If we did this then the above test would change such that you never saw the last two events (assuming Ctrl was released after the combo)...

@joshgoebel
Copy link
Owner Author

joshgoebel commented Jun 14, 2022

And does it matter whether this matches the "already held, part of combo" behavior... ie, this test:

async def test_sticky_combo_with_sticky_inkey_in_output_combo():
    keymap("Firefox",{
        K("C-j"): [bind, K("Alt-C-TAB")],
    })

    boot_config()

    press(Key.LEFT_CTRL)
    await asyncio.sleep(2)
    press(Key.J)
    release(Key.J)
    release(Key.LEFT_CTRL)

    assert _out.keys() == [
        (PRESS, Key.LEFT_CTRL),
        # we never lift left control (that was held)
        # because it's part of the output combo
        (PRESS, Key.LEFT_ALT),
        (PRESS, Key.TAB),
        (RELEASE, Key.TAB),
        (RELEASE, Key.LEFT_ALT),
        (RELEASE, Key.LEFT_CTRL),
    ]

Here we smartly realize that our long hold of Ctrl happens to be part of the finally triggered combo, so we just keep holding Ctrl on the output (and add the other keys for the combo)... if we kept holding it, (after the combo) then it would just stay down on the output. This currently matches the former in that once a key is resumed (and sent to output) we try to continue asserting it on output as much as possible (other than incompatible combos)... this seems more important in this case though since we're actually doing a better job of matching input with output.

But one could argue here that we aren't holding down alt (on the output), we haven't requested sticky/bind... so perhaps Left Ctrl should also be immediately released from the output and resuspended (until we know what a users wants to do next) - ie that all combos (non-sticky/bound) should be momentary.

Yes, this is all very nuanced.

@joshgoebel
Copy link
Owner Author

joshgoebel commented Jun 14, 2022

I lean slightly towards the re-suspend behavior... because otherwise (in the case of one-of combos, which most combos are) the result is a LOT of wasted/false keypresses of the original keys immediately following a combo, before they can be released. IE, if we don't re-suspend this will be a pattern that happens commonly:

  • real keys input (and held past the suspend timeout)
  • real keys pressed on output
  • real keys released on output (to make way for the combo)
  • actual combo sent to output
  • real keys pressed on output
  • real keys released on output

As always the problem is that we don't know what to do with the real keys before/after a combo without the ability to see into the future.

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

1 participant