Unicode input

jME3 uses LWJGL as a backend. To further explain, in pure LWJGL code, there’s this following problem…


char c = Keyboard.getEventCharacter();
System.out.println((int)c); // if this is a unicode character, it will keep printing 63 (which means ?)

char c = (char)29233; // Chinese letter "爱"
System.out.println((int)c); // in this case, it prints 29233 (which is correct).

Apparently, this problem duplicates itself in jME3. Even if you use RawInputListener, to get raw events.

So, I research a little bit. I’ve found out that this is a bug in java. Microsoft’s input method would just return ? for unicode characters. It even happens for TWL. Only pure Java… AWT or Swing input methods will work consistently for unicode input. The only solution is to use AWT or Swing with LWJGL.

Back to jME3, it seems I can’t receive events from an attached KeyListener to a canvas to receive its input.


class MyApp extends Application implements KeyListener
...
JmeCanvasContext ctx = (JmeCanvasContext) getContext();
Canvas canvas = ctx.getCanvas();
canvas.addKeyListener(this);
...
// keyPressed, keyReleased and keyTyped events aren't called-back.

Then, I decided to have JTextFields overlay the OpenGL canvas to provide text input, but I found out that it creates more problems. Thus, I abandoned it, in favour of a text field directly in OpenGL instead. I really need unicode textual input as my target application definitely requires handling of East Asian scripts (especially Chinese).

How do unicode games (especially those with chatting consoles) get Unicode Input?

  • How do you receive a KeyListener event from an OpenGL canvas?
  • Is there a better way to do this?

Thanks for the help! =D

SOLVED! I definitely needed to use KeyListener or AwtKeyInput, and not LwjglKeyInput in jME3, because LwjglKeyInput did not receive unicode characters properly. So it was a matter of why did KeyListener not receive input.

I found AwtKeyInput in jME3 sources, but it also did not receive input because window and component focus was not set properly. I realised that since it works the same way as using KeyListener, why not, just use KeyListener with LwjglKeyInput.

Therefore, I have a boolean that tells me if my application is in text mode, thus, received KeyListener events instead of LWJGL events. I added a FocusListener. So, if my application is in text mode, the focus is immediately set to the KeyListener implementation class. Otherwise, I cleared focus.


JmeCanvasContext ctx = (JmeCanvasContext) context;
ctx.setSystemListener(this);

canvas = ctx.getCanvas();
canvas.addFocusListener(this);

frame.addKeyListener(this);
frame.addFocusListener(this);

void focusGained() {
	if(textMode) {
		frame.requestFocus();
		frame.requestFocusInWindow();
	}
	else {
		KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
	}
}

void focusLost() {
	if(textMode) {
		frame.requestFocus();
		frame.requestFocusInWindow();
	}
	else {
		KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
	}
}

Maybe casting was not a good idea… :stuck_out_tongue: What about the methods char provide, such as getNumericValue()?