3

I am struggling to find a solution that detects the simultaneous pressing of f and j so that if only f or j is pressed, the current application also receives an f or an j but when I press f and (within a short time period) j simultaneously that the current application receives neither key.

I understand that I somehow have to wait for the short time period (of possibly 0.2 seconds) after an f or j is detected in order to determine if I should use send to give the pressed f or j to the current application or if I have to "swallow" both and to go on with my macro. Yet, how I should to that, I have no idea.

René Nyffenegger
  • 39,402
  • 33
  • 158
  • 293
  • Yes that is right, for that to work it will need to wait some time when you press this key. But that means you will not be able to type text reliably. Say, you'll type "ja" quickly and it will give you "aj" because "a" will be received immediately. So I am not sure if the whole idea is good, I mean if you still need those keys involved in typing or other commands. – Mikhail V May 31 '19 at 10:32
  • What are you planning to do with this F&J combo? mikhail makes a good point, anything like this is going to end up messing with the expected behavior of your normal keys – J. G. May 31 '19 at 16:33
  • Since the keys `f` and `j` are located beneath the index fingers, they lend themselves for a shortcut. I'd be hard pressed to find a word where f and j occur adjacently (except for *fjord*). If I want to type "*ja*", I don't mind if I don't see the *j* right after pressing it. But of course, when I type the *a*, the script then knows that I didn't press *fj* and can insert the *j* and then the *a*. And even in the case of *fjord*, I thinks is very unlikely that I press the *f* and the *j* simultaneously. – René Nyffenegger Jun 01 '19 at 07:14
  • _"But of course, when I type the a, the script then knows that I didn't press fj and can insert the j and then the a."_ If the solution is by overriding "j" and "f" key behavior - then no, regardless of "fj" combo, you will surely get "aj" instead of "ja" if "a" will be pressed earlier than "j" keywait is over (or "j" key is released, if you'll rely on that instead of timeout). And that stands for all keys - so any words you type fast that have "j" or "f" will have these letters shifted. Unless of course you redefine the behavior for all keys, or tweak the whole input system. – Mikhail V Jun 02 '19 at 02:35
  • There is one possible workaround - detect the combo without blocking these keys, and then send `backspace` 2 times - this will delete 2 last typed character "fj" or "jf", then run you desired command. It might actually work, though it only makes sense if you have focus on some input box, so there can be other issues as well. – Mikhail V Jun 02 '19 at 02:35
  • You can try [RapidHotkey](https://autohotkey.com/board/topic/35566-rapidhotkey/) – user3419297 Jun 02 '19 at 08:43

1 Answers1

2

Relatively simple solution is to detect the combo directly without blocking the input for these two keys. Once it detects that both keys are pressed, delete the input results by sending backspace key 2 times, and then run the desired command. This has the benefit that you can still type text without any issues.
OTOH it will work correctly only for the case where current focus is on the text input application/widget and where backspace means delete last char. In other cases you might get some surprises, e.g. activating random commands.
Here is an example, I used x and c keys here. The place where the command fires is the line send {O}.

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.

dt := 30            ;  milliseconds sleep
k1name := "x"       ;  key 1
k2name := "c"       ;  key 2

loop 
{
    sleep %dt%                              ; sleep to reduce CPU usage
    k1 := getkeystate(k1name, "P")          ; get key 1 state
    k2 := getkeystate(k2name, "P")          ; get key 2 state

    if ( ! ( getkeystate("Ctrl", "P") || getkeystate("Alt", "P") || getkeystate("Shift", "P") ) ) {
        if ( k1 && k2 && !trig ) {
            send {backspace 2}
            send {O}        ; send some command 
            trig := 1       ; set flag to avoid repetition
        }
        if ( !k1 || !k2 ) {
            trig := 0
        }
    }
}

There can be also solutions with overriding the behavior of those keys, but that will be more complicated and has the issues already mentioned in the comments. I personally would tend to stick to the above solution because of its simplicity.

Mikhail V
  • 1,416
  • 1
  • 14
  • 23