Awt Robot key press delay

2.9k views Asked by At

I work on a small tool for a game something like hotkey which handle a combination of user key press event and simulate with Awt Robot a couple of key press. The problem is that called method ghostWalk() work as expected only first time when registered combination is pressed, second time when I press the same combination and the same method are called only the last key is simulated which is after "robot.delay". pls read more from code comment.

import com.melloware.jintellitype.HotkeyListener;
import com.melloware.jintellitype.JIntellitype;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

public class L {
int i = 160;

public static void main(String args[]){
    L l = new L();
    l.k();
}
public void k(){
    // Register keys combination
    JIntellitype.getInstance();
    JIntellitype.getInstance().registerHotKey(1, JIntellitype.MOD_ALT, (int)'D');
    JIntellitype.getInstance().registerHotKey(2, JIntellitype.MOD_ALT, (int)'J');
    JIntellitype.getInstance().registerHotKey(3, JIntellitype.MOD_ALT, (int)'K');
    JIntellitype.getInstance().addHotKeyListener(new HotkeyListener() {
        public void onHotKey(int aIdentifier) {
            // First indentifier Alt + D
            if (aIdentifier == 1) {
                System.out.println("Alt+D hotkey pressed");
                // Start new thread
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        L gh = new L();
                        gh.ghostWalk();
                    }
                }).start();
            }
            // Second indetifier
            else if(aIdentifier == 2){
                i += 10;
                System.out.println(i);
            }
            // Third
            else if(aIdentifier == 3){
                i -= 10;
                System.out.println(i);
            }
        }
    });
}
// Method called to simulate key press
/* So, first time when i press Alt + D in game after program runs
all work good, the keys are simulated  as expected but if I press again and again
the combination only key "d" are simulated which is after "delay(i), i = 160"
If program is restarted all again is the same, only first time when i press registered
combinations the program work as expected.
Second and others times program work only if there is delay "robot = new Robot();
                                                             robot.delay(100);"
 on 100 delay program work well on 40ms need to press very fast the combination
 so the program work as expected. How to fix it ? to simulate key press without
 delay like first time when program is run.
 P.s no matter in which window(game, notepad) you press combination to simulate key press
 still work good only first time.
Example of output when i press two times combinations in game
first time: qqwewwd
second time: d
 */
public void ghostWalk(){
    Robot robot = null;
    try {
        robot = new Robot();
        //robot.delay(100);
        robot.keyPress(KeyEvent.VK_Q);
        robot.keyRelease(KeyEvent.VK_Q);
        robot.keyPress(KeyEvent.VK_Q);
        robot.keyRelease(KeyEvent.VK_Q);
        robot.keyPress(KeyEvent.VK_W);
        robot.keyRelease(KeyEvent.VK_W);
        robot.keyPress(KeyEvent.VK_R);
        robot.keyRelease(KeyEvent.VK_R);
        robot.keyPress(KeyEvent.VK_W);
        robot.keyRelease(KeyEvent.VK_W);
        robot.keyPress(KeyEvent.VK_W);
        robot.keyRelease(KeyEvent.VK_W);
        robot.delay(i);
        robot.keyPress(KeyEvent.VK_D);
        robot.keyRelease(KeyEvent.VK_D);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

Edit: I can't understand what changes are made after first calling ghostWalk method that I should to use delay so my program work as expected.

Edit2: In my case code start to work when setAutoWaitForIdle was set to true and delay = 5 (delay before start to simulate keypress) also if between keypress is a delay like in my case delay(i), i = 160 then start delay should be 60~. (if start delay is 40~ then not always work good, need very fast to press registered keys combination idk why, also if start delay is less than 40-60 in my case is simulated only last keypress "D" which is after delay(i).)

If to delete robot.setAutoWaitForIdle(true) and robot.delay(60) on first registered hotkey event the tool will work as expected, on second, third etc times - not. After first JIntellitype event work only this code.

public void ghostWalk(){
    Robot robot = null;
    try {
        robot = new Robot();
        robot.setAutoWaitForIdle(true);
        robot.delay(60);
        robot.keyPress(KeyEvent.VK_Q);
        robot.keyRelease(KeyEvent.VK_Q);
        robot.keyPress(KeyEvent.VK_Q);
        robot.keyRelease(KeyEvent.VK_Q);
        robot.keyPress(KeyEvent.VK_W);
        robot.keyRelease(KeyEvent.VK_W);
        robot.keyPress(KeyEvent.VK_R);
        robot.keyRelease(KeyEvent.VK_R);;
        robot.delay(i);
        robot.keyPress(KeyEvent.VK_D);
        robot.keyRelease(KeyEvent.VK_D);

    } catch (Exception e) {
        e.printStackTrace();
    }
}
1

There are 1 answers

7
TT. On BEST ANSWER

You should consider setting an auto-delay using setAutoDelay.

It's quite possible your OS has problems handling input events if they're posted without delay. Try with 50 ms or 25ms delay, see what happens.

Another thing you can try is add waitForIdle() before each key press.


EDIT: For sports I tried the JIntelliType library out, and the following snippet works relatively well. I tested pressing the hotkey out in Notepad++ (ctrl-Q) and it consistently prints out tt rocks. However I had to release the hotkey fast, otherwise Notepad++ started interpreting the hotkey as something else (ctrl-Q is already a shortcut for something else in Notepad++).

Using a robot is not exact science. I had to delay the robot for 150 ms and then waitForIdle before letting the robot press keys. Otherwise things got screwed up. Setting auto delay was not necessary.

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import com.melloware.jintellitype.HotkeyListener;
import com.melloware.jintellitype.JIntellitype;

public class TestKeys {
    private HotkeyListener listener = new HotkeyListener() {
        @Override
        public void onHotKey(final int hotKeyId) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    JIntellitype.getInstance().removeHotKeyListener(listener);
                    handleHotKey(hotKeyId);
                    JIntellitype.getInstance().addHotKeyListener(listener);
                }
            }).start();
        }
    };

    public void registerHotKeys() {
        JIntellitype instance = JIntellitype.getInstance();
        instance.registerHotKey(1, JIntellitype.MOD_CONTROL, 'Q');
        instance.registerHotKey(2, JIntellitype.MOD_CONTROL, 'J');
        instance.addHotKeyListener(listener);
        System.out.println("Hotkeys registered");
    }

    private static void handleHotKey(int hotKeyId) {
        switch(hotKeyId) {
            case 1:
                System.out.println("Pressing some keys now!");
                pressSomeKeys();
                break;
            case 2:
                System.out.println("Bailing out, cya!");
                System.exit(0);
                break;
        }
    }

    private static void pressSomeKeys() {
        Robot r;
        try {
            r = new Robot();
        } 
        catch (AWTException e) {
            System.out.println("Creating robot failed");
            System.exit(2);
            return;
        }
        r.setAutoWaitForIdle(true);
        r.delay(150);
        r.waitForIdle();
        r.keyPress(KeyEvent.VK_T); r.keyRelease(KeyEvent.VK_T);
        r.keyPress(KeyEvent.VK_T); r.keyRelease(KeyEvent.VK_T);
        r.keyPress(KeyEvent.VK_SPACE); r.keyRelease(KeyEvent.VK_SPACE);
        r.keyPress(KeyEvent.VK_R); r.keyRelease(KeyEvent.VK_R);
        r.keyPress(KeyEvent.VK_O); r.keyRelease(KeyEvent.VK_O);
        r.keyPress(KeyEvent.VK_C); r.keyRelease(KeyEvent.VK_C);
        r.keyPress(KeyEvent.VK_K); r.keyRelease(KeyEvent.VK_K);
        r.keyPress(KeyEvent.VK_S); r.keyRelease(KeyEvent.VK_S);
    }

    public static synchronized void main(String[] args) {
        System.out.println("TestKeys started");
        TestKeys k = new TestKeys();
        k.registerHotKeys();
        try { 
            TestKeys.class.wait();
        } 
        catch (InterruptedException e) {
        }
    }
}