mabe02 / lanterna

Java library for creating text-based GUIs
GNU Lesser General Public License v3.0
2.27k stars 242 forks source link

CJK/Input Method Editor support for terminal emulator #439

Closed reibitto closed 4 years ago

reibitto commented 4 years ago

I tried inputting Japanese and Korean text into the Swing terminal and neither worked correctly. It looks like input coming from IMEs is not supported currently.

I investigated this and supporting it seems doable using InputMethodListener. The idea is basically to simulate CJK key presses when text is committed with the IME.

This might need a little bit of trickery if you need a JTextComponent to receive these events properly. Such as adding a JTextComponent to the terminal emulator frame but not styling it so that it remains invisible. I did confirm though that the events still come through even if you use setEditable(false), so at least there's that.

@mabe02 Does this sound reasonable? If so, I wouldn't mind giving this a shot.

Other ideas are welcome too. I'm unable to see any other alternatives though.

reibitto commented 4 years ago

The JTextComponent hack I mentioned looks to be unnecessary. The events come through on a plain JFrame when using InputMethodRequests.

mabe02 commented 4 years ago

I haven't actually looked into this. Would be good to support this! Did you get it actually reading CJK characters?

reibitto commented 4 years ago

I haven't looked further into this yet (but will definitely need to soon), but the fact that the CJK text is coming through properly in the event means this should definitely be doable. I just haven't looked into the lanterna internals yet to see where I would take that CJK text and insert it. I just vaguely remember that key presses were being translated somewhere which is where the "simulate a CJK key press" idea came from. As if the user has a keyboard where each key is a single Chinese character... 😅 Because I'm assuming it only makes sense to do this after the user commits the text (which will be a string, not necessarily a single character) rather than while the user is composing CJK text.

mabe02 commented 4 years ago

Yeah, that probably makes sense. Once the text has been committed by the input layer, we should take it character by character and insert them as if they were punched in one by one. Not sure how well Java integrated with the platform IME though, for example, how does the OS know where to but the IME composer? But as long as it works somewhat, that's a lot better than what we have now.

reibitto commented 4 years ago

So basically you would implement the InputMethodRequests interface and then in your implementation for getTextLocation you would calculate where the composition box should appear. I imagine it's just a matter of finding where the frame is in relation to the screen + offsetting where the text cursor appears within the JFrame. I don't know if there's a helper method for that latter part already, but if not I think you can calculate it from Font + Graphics?

https://docs.oracle.com/javase/8/docs/api/java/awt/im/InputMethodRequests.html#getTextLocation-java.awt.font.TextHitInfo-

reibitto commented 4 years ago

Alright, I have this working. I just have to position the composition box. I think I should be able to create the PR tomorrow.

mabe02 commented 4 years ago

Great, thanks!

mabe02 commented 4 years ago

Nice! bild