Apostrophe Key Isn't Recognised

In one of my games, the apostrophe key cannot be detected, so I setup a test case to see if it was an issue generated by myself.

What I discovered was: using KEY_APOSTROPHE as a KeyTrigger doesn’t work, however using KEY_GRAVE does!

This means that whenever I press the grave key (also known as back tick) OR the apostrophe key, my test case cannot tell the difference.

In the code below, pressing ` or ' prints "GRAVE" to the console.


import com.jme3.app.SimpleApplication;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;

public class InputTest extends SimpleApplication {
    
    public static void main(String[] args) {
        InputTest app = new InputTest();
        app.start();
    }

    @Override
    public void simpleInitApp() {
        inputManager.addMapping("APOSTROPHE", new KeyTrigger(KeyInput.KEY_APOSTROPHE));
        inputManager.addMapping("GRAVE", new KeyTrigger(KeyInput.KEY_GRAVE));        
        
        inputManager.addListener(actionListener, "APOSTROPHE", "GRAVE");        
    }
    
    private final ActionListener actionListener = new ActionListener() {
        @Override
        public void onAction(String name, boolean isPressed, float tpf) {
            if (isPressed) {
                System.out.println(name);
            }
        }
        
    };
}

Could this be an issue with the version I’m using: JME3.2.1-stable-sdk3? I don’t think it’s a keyboard issue, because I have tried two USB keyboards, and one PS2 keyboard.

On the same computer?

This is an OS/Driver-level issue. I suspect that even if you tried regular Java Swing/AWT key events you’d have the same issue.

I’ve just done a test, using KeyEventDemo.java which is provided by oracle, and everything seems to work fine.

https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/uiswing/examples/events/KeyEventDemoProject/src/events/KeyEventDemo.java


Typing grave ` outputs:

KEY PRESSED: 
    key code = 192 (Back Quote)
    extended modifiers = 0 (no extended modifiers)
    action key? NO
    key location: standard
KEY TYPED: 
    key character = '`'
    extended modifiers = 0 (no extended modifiers)
    action key? NO
    key location: unknown
KEY RELEASED: 
    key code = 192 (Back Quote)
    extended modifiers = 0 (no extended modifiers)
    action key? NO
    key location: standard


Typing apostrophe ' outputs:

KEY PRESSED: 
    key code = 222 (Quote)
    extended modifiers = 0 (no extended modifiers)
    action key? NO
    key location: standard
KEY TYPED: 
    key character = '''
    extended modifiers = 0 (no extended modifiers)
    action key? NO
    key location: unknown
KEY RELEASED: 
    key code = 222 (Quote)
    extended modifiers = 0 (no extended modifiers)
    action key? NO
    key location: standard

I’m now not sure what the issue is.

Just for symmetry, you might try creating a similar demo using JME’s raw listener support.

https://javadoc.jmonkeyengine.org/com/jme3/input/InputManager.html#addRawInputListener-com.jme3.input.RawInputListener-

If that reports both keys as the same then it may be a bug in lwjgl.

This now outputs:

for ` :

Key(CODE=41, CHAR=`, PRESSED)
Key(CODE=41, RELEASED)

for ' :

Key(CODE=41, CHAR=', PRESSED)
Key(CODE=41, RELEASED)

They have the same key code of 41, so this isn’t JME’s fault because they are defined differently in KeyInput:

    /**
     * ' key.
     */
    public static final int KEY_APOSTROPHE = 0x28;         //0x28 = 40
    /**
     * ` key.
     */
    public static final int KEY_GRAVE = 0x29;             //0x29 = 41

import com.jme3.app.SimpleApplication;
import com.jme3.input.KeyInput;
import com.jme3.input.RawInputListener;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.event.JoyAxisEvent;
import com.jme3.input.event.JoyButtonEvent;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.input.event.MouseButtonEvent;
import com.jme3.input.event.MouseMotionEvent;
import com.jme3.input.event.TouchEvent;


public class InputTest extends SimpleApplication {
     
    public static void main(String[] args) {
        InputTest app = new InputTest();
        app.start();
    }

    @Override
    public void simpleInitApp() {
       inputManager.addRawInputListener(ril);        
    }
    
    private final RawInputListener ril = new RawInputListener() {
        @Override
        public void beginInput() {
            
        }

        @Override
        public void endInput() {
            
        }

        @Override
        public void onJoyAxisEvent(JoyAxisEvent evt) {
            
        }

        @Override
        public void onJoyButtonEvent(JoyButtonEvent evt) {
            
        }

        @Override
        public void onMouseMotionEvent(MouseMotionEvent evt) {
            
        }

        @Override
        public void onMouseButtonEvent(MouseButtonEvent evt) {
            
        }

        @Override
        public void onKeyEvent(KeyInputEvent evt) {
            System.out.print(evt);
        }

        @Override
        public void onTouchEvent(TouchEvent evt) {
            
        }
    };
    
}

Although the issue isn’t solved, I can at least use the RawInputListener now instead to tell the difference.


Also, forgot to mention that I have tested this on another computer, which runs a different version of windows.

In case it helps anyway, this is the code JME is using to get the events from lwjgl:

…and we don’t do any interpretation so it seems to be on lwjgl.

Unless you are using lwjgl3 and then JME does do some interpretation:

I’m using lwjgl-2.9.3.jar although in the org.lwjgl.input.LwjglKeyInput.java they are defined seperately:


    public static final int KEY_APOSTROPHE = 40;
    public static final int KEY_GRAVE = 41;

I’ll have to do some more digging…

tested on both lwjgl 2, 3 it works fine in both of them for me

with lwjgl 2 :

evt.isPressed() : Key(CODE=40, CHAR=', PRESSED)
evt.isPressed() : Key(CODE=41, CHAR=`, PRESSED)

with lwjgl 3:

evt.isPressed() : Key(CODE=40, PRESSED)
evt.isPressed() : Key(CODE=0, CHAR=', PRESSED)
evt.isPressed() : Key(CODE=41, PRESSED)
evt.isPressed() : Key(CODE=0, CHAR=`, PRESSED)

Note: I am using JME master branch (3.3)

Edit: and I am on Linux

I guess this is again the issue I was reporting with the difference between scan code / key position and mapping. Like for German Keyboards `’ is on the same key, for others it might not. And CHAR is different from CODE.
Just linking it here in case someone is digging into it: Keyboard Mapping inconsistency between lwjgl2 and 3 · Issue #942 · jMonkeyEngine/jmonkeyengine · GitHub

I updated the engine to 3.2.2-stable and still the problem persists, no idea what’s causing it, but I’ll modify my code to use the raw inputer listener instead, so I can at least get around it.

1 Like