I'm trying to create a sample that calls JNA's KeyboardUtils
class to check key states on Windows (similar to Win32's GetAsyncKeyState()
).
Here's my code:
package com.foo;
import com.sun.jna.platform.KeyboardUtils;
import java.awt.event.KeyEvent;
public class Main {
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
System.out.println("Watching for Left/Right/Up/Down or WASD. Press Shift+Q to quit");
while (true) {
try
{
Thread.sleep(10);
if (KeyboardUtils.isPressed(KeyEvent.VK_DOWN) || KeyboardUtils.isPressed(KeyEvent.VK_S) )
{
System.out.println("Down");
}
if (KeyboardUtils.isPressed(KeyEvent.VK_UP) || KeyboardUtils.isPressed(KeyEvent.VK_W) )
{
System.out.println("Up");
}
if (KeyboardUtils.isPressed(KeyEvent.VK_LEFT) || KeyboardUtils.isPressed(KeyEvent.VK_A) )
{
System.out.println("Left");
}
if (KeyboardUtils.isPressed(KeyEvent.VK_RIGHT) || KeyboardUtils.isPressed(KeyEvent.VK_D) )
{
System.out.println("Right");
}
if (KeyboardUtils.isPressed(KeyEvent.VK_Q) && KeyboardUtils.isPressed(KeyEvent.VK_SHIFT) )
{
break;
}
}
catch(Exception e)
{ }
}
System.exit(0);
}
}.start();
}
}
This works fine and detects WASD keys, as well as Shift+Q. However, the arrow keys Left/Right/Up/Down are never detected.
Converting the code to C++ and calling Win32 GetAsyncKeyState()
does work with the arrow keys.
According to the web, the value of KeyEvent.VK_DOWN
matches the Win32 definition (40).
Any idea why JNA isn't correctly detecting the arrow keys?
According to the KeyboardUtils
source code, KeyboardUtils
does not support arrow keys at all, on any platform.
KeyboardUtils
is implemented for only 3 keyboard platforms - Windows, Mac, and Linux.
On Mac, isPressed()
is not implemented at all and returns false for all key codes, and an UnsupportedOperationException
is thrown when KeyboardUtils
is initialized.
On Windows and Linux, KeyboardUtils
supports the following keys:
VK_A
- VK_Z
VK_0
- VK_9
VK_SHIFT
VK_CONTROL
VK_ALT
VK_META
(Linux only)On Windows, KeyboardUtils.isPressed()
translates KeyEvent
key codes into Win32 virtual key codes (in W32KeyboardUtils.toNative()
) and passes them to GetAsyncKeyState()
(in W32KeyboardUtils.isPressed()
). But arrow keys are not handled and get translated to virtual key code 0, which is not a valid key code.
Similar with Linux key codes.
So, to detect arrow keys on Windows, you will have to call GetAsyncKeyState()
yourself, as you have already discovered.