Although I can understand the desire to have a small, fast app to provide this functionality, it's fairly easy to do with AHK, and I don't find AHK that much of a system hog anyway. Using AHK also has the advantage that you can do plenty of other things besides sending alternative keystrokes, if you need to.
I've just added a simple double tap feature to my default AHK script (which runs at startup and provides most of my global hotkeys). One nice thing about this is that it's one less tray icon to worry about, and also minimises the overhead of running multiple hotkey processes.
The code for this is pretty simple. Near the top of my script, I have the following function:
DoubleKey(key, timeout, sendKeys)
{
global
if(tapped%key% and (A_TickCount - tapTime%key% < timeout))
{
Send, %sendKeys%
tapped%key% = 0
}
else
{
tapped%key% = 1
tapTime%key% := A_TickCount
}
}
And then to use it, I just create a hotkey which calls this function. For example, my FARR double tap hotkey is as follows:
Ctrl:: DoubleKey("ctrl", 500, "^!k")
The "^!k" is the CTRL+ALT+K key sequence I use to bring up FARR normally, and the 500 is the time allowed between the two taps in milliseconds - if you wait any longer before pressing CTRL again, it resets and you have to tap twice again.
The "crtl" is used by the function to distinguish between different double tap keys. For example, if I also set up a hotkey for a double tap of SHIFT, it's probably better if the state of the double tap is kept separate from the state of any CTRL double tap, so the "ctrl" is used as part of the state variable names. The SHIFT hotkey would use "shift" (or anything else, so long as it's different from "ctrl"). If you don't do this, then SHIFT followed quickly by CTRL would fire the CTRL sequence, as if CTRL had been pressed twice.
Interestingly, it might be possible to make use of this kind of sequence, e.g. SHIFT then CTRL could fire a different sequence from CTRL-CTRL or SHIFT-SHIFT, as could CTRL-SHIFT. My current script can't do this, but it should be possible.
The only thing I haven't managed to solve yet is using the left and right SHIFT/CONTROL keys separately. If you use the LCtrl/RCtrl/LShift/RShift hotkeys in AHK, there seems to be some sort of repetition happening, which causes the sequence to fire any time you hold those particular keys down. I'll see if I can fix that when I have more time, but the current code seems to work very well for the Ctrl, Shift and Alt hotkeys.
If you feel it's ahk's fault, post ait at the ahk forum. I'm sure they'll be able to provide a solution or if there is no solution, they'll solve it on the next release. At least, that's how it's happened with me ;)
-jgpaiva
I just tried a search there and found a solution, as well as a better way to do what I was trying to do. :)
It turns out that AHK provides useful built-in variables for the previous and current hotkey, as well as the time since the last hotkey. Using them, DoubleKey() turns into:
DoubleKey(sendKeys, timeout)
{
if(A_PriorHotKey = A_ThisHotKey and A_TimeSincePriorHotkey < timeout)
Send, %sendKeys%
}
Pretty nifty. In fact, there's not really much benefit to my nice, neat function any more. ;)
The problem with using separate left/right Ctrl/Alt/Shift can be solved by doing two things.
First, the "repeating key when held down" issue is strangely solved by making the hotkey respond to key-up events instead of key-down events - you can do this by putting " Up" in the hotkey name. This also seems to solve a problem I noticed when you make the timeout quite short (200ms or less), where the trigger sometimes wouldn't work - this seems to be related to which key you are using.
The other issue that was happening was that the LCtrl/RCtrl versions weren't allowing normal CTRL+key presses to get through to other apps. This is fixed by using the "~" modifier, which tells AHK to pass the hotkey to the underlying app rather than swallowing it completely. This shouldn't be necessary, since CTRL+key is a different key to CTRL on its own, and isn't for the non-left-right versions, but it seems to be necessary for the left-right variants.
So my hotkey for running FARR is now:
~RCtrl Up:: DoubleKey("^!k", 200)
One other thing I noticed (while typing this actually), is that setting SHIFT as a double tap key can be slightly problematic depending on how fast you type. For me, quoted strings seem to involve a quick shift to make the " and then a quick shift to make the capital letter or symbol following it. It seems that I quite often do this sequence in less than 500ms, so I've got my timeout set at 200ms now. It's amazing the things you find out about yourself sometimes. :)