Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Registering Multi-Key Presses with JNativeHook

Tags:

java

I have looked at examples, and also tried to search on Google for a few hours, but it seems I can't quite find a question that covers what I am asking.

If I wanted to do something like

W + A at the same time, and register that as a separate key event and not just as W and A separately, how would I go about doing that using JNativeHook? Is it because I missed a class somewhere that covers this, or is there some sort of workaround to only reading a single key?

I am trying to do it in a console (hence I use this library and not Swing).

I took their example, and wanted to try and modify it:

import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;

public class GlobalKeyListener implements NativeKeyListener {

    @Override
    public void nativeKeyPressed(NativeKeyEvent e) {
        System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));

        if (e.getKeyCode() == NativeKeyEvent.VC_ESCAPE) {
            GlobalScreen.unregisterNativeHook();
        }
    }

    @Override
    public void nativeKeyReleased(NativeKeyEvent e) {
        System.out.println("Key Released: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
    }

    @Override
    public void nativeKeyTyped(NativeKeyEvent e) {
        System.out.println("Key Typed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
    }

    public static void main(String[] args) {
        try {
            GlobalScreen.registerNativeHook();
        } catch (NativeHookException ex) {
            System.err.println("There was a problem registering the native hook.");
            System.err.println(ex.getMessage());

            System.exit(1);
        }

        //Construct the example object and initialze native hook.
        GlobalScreen.getInstance().addNativeKeyListener(new GlobalKeyListener());
    }
}
like image 878
OmniOwl Avatar asked Oct 06 '14 13:10

OmniOwl


2 Answers

You need to listen for each individual key push and release event for the combination required and set some kind of flag as each of the keys is depressed. If after 1 of the desired keys is pressed, and the flag condition is met, then you can do whatever you need to do when those keys are pressed together. There is no way to get a single event for two keys without creating a custom keyboard driver. If you goal is to suppress the W and A key events until both are press, look at the unsupported consuming events section of the docs. Note that event suppression is only available on Windows and OS X targets and the suppressed events will not be delivered to other applications.

Its not the prettiest example, but it should do what you are look for.

private short hotKeyFlag = 0x00;
private static final short MASK_A = 1 << 0;
private static final short MASK_W = 1 << 1;

...
@Override
public void nativeKeyPressed(NativeKeyEvent e) {
    if (e.getKeyCode() == NativeKeyEvent.VC_ESCAPE) {
        GlobalScreen.unregisterNativeHook();
    }
    else if (e.getKeyCode() == NativeKeyEvent.VK_A) {
        hotKeyFlag &= MASK_A;
    }
    else if (e.getKeyCode() == NativeKeyEvent.VK_W) {
        hotKeyFlag &= MASK_W;
    }

    // Check the mask and do work.
    if (hotKeyFlag == MASK_A & MASK_W) {
        // Fire Shortcut.
    }
}

@Override
public void nativeKeyReleased(NativeKeyEvent e) {
    if (e.getKeyCode() == NativeKeyEvent.VK_A) {
        hotKeyFlag ^= MASK_A;
    }
    else if (e.getKeyCode() == NativeKeyEvent.VK_W) {
        hotKeyFlag ^= MASK_W;
    }
}
like image 130
Alex Barker Avatar answered Nov 17 '22 22:11

Alex Barker


This is my answer:-

private boolean a = false, w = false;

@Override
public void nativeKeyPressed(NativeKeyEvent e) {
    if (e.getKeyCode() == NativeKeyEvent.VC_A) {
        a = true;
        if (w) {
            System.out.println("W+A");
        } else {//remove this else only for testing
            System.out.println("Only A");
        }
    } else if (e.getKeyCode() == NativeKeyEvent.VC_W) {
        w = true;
        if (a) {
            System.out.println("A+W");
        } else {//remove this else only for testing
            System.out.println("Only W");
        }
    }
}

@Override
public void nativeKeyReleased(NativeKeyEvent e) {
    if (e.getKeyCode() == NativeKeyEvent.VC_A) {
        a = false;
    } else if (e.getKeyCode() == NativeKeyEvent.VC_W) {
        w = false;
    }
}

@Override
public void nativeKeyTyped(NativeKeyEvent e) {
    //System.out.println("Key Typed: " + e.getKeyText(e.getKeyCode()));
}
like image 5
Isuru Dilshan Avatar answered Nov 17 '22 22:11

Isuru Dilshan