javafxports/openjdk-jfx

TextInputControl in macOS environment cannot input Emoji

yososs opened this issue · 3 comments

This problem can be reproduced in the next test.

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class EmojiTextInputTest extends Application{
	
	static Font emojiFont = Font.font("Apple Color Emoji");
	
	@Override
	public void start(Stage stage) throws Exception {

		TextField textField = new TextField();
		TextArea textArea = new TextArea();
		WebView webView = new WebView();
		textField.setFont(emojiFont);
		textArea.setFont(emojiFont);
		
		VBox root = new VBox(8, new Label("TextField"),textField, new Label("TextArea"), textArea, new Label("WebView"), webView);
		Scene scene = new Scene(root, 400, 700);
		stage.setScene(scene);
		stage.show();

		webView.getEngine().loadContent("<html><input type=text style='font-family:Apple Color Emoji'><textarea style='font-family:Apple Color Emoji'></textarea></html>");

	}
	
	public static void main(String[] args) {
		Application.launch(args);
	}
}

Start the test and input an emoji (😄) from InputMethod.
The problem is not just correct Emoji input. After this operation, ASCII characters cannot be input.

スクリーンショット 2019-09-30 1 26 36

Solution

The problem is that NewStringUTF cannot handle emoji code correctly. You can fix it by using NewString instead.

static jstring convertNSStringToJString(id aString, int length)
{
GET_MAIN_JENV;
jstring jStr;
if ([aString isKindOfClass:[NSAttributedString class]]) {
NSData *data = [[aString string] dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
jchar *dataBytes = (jchar *)malloc(sizeof(jchar) * length);
if (dataBytes != NULL) {
[data getBytes:dataBytes length:length * 2];
jStr = (*env)->NewString(env, dataBytes, length);
free(dataBytes);
}
} else {
jStr = (*env)->NewStringUTF(env, [aString UTF8String]);
}
GLASS_CHECK_EXCEPTION(env);
return jStr;
}

The following is the source after rewriting.

 static jstring convertNSStringToJString(id aString, int length) 
 { 
     GET_MAIN_JENV; 
  
     jstring jStr; 
     if ([aString isKindOfClass:[NSAttributedString class]]) { 
         NSData *data = [[aString string] dataUsingEncoding:NSUTF16LittleEndianStringEncoding]; 
         jchar *dataBytes = (jchar *)malloc(sizeof(jchar) * length); 
         if (dataBytes != NULL) { 
             [data getBytes:dataBytes length:length * 2]; 
             jStr = (*env)->NewString(env, dataBytes, length); 
             free(dataBytes); 
         } 
     } else { 
        jsize buflen = [aString length];
        unichar buffer[buflen];
        [aString getCharacters:buffer];
        jStr = (*env)->NewString(env, (jchar *)buffer, buflen);
     } 
  
     GLASS_CHECK_EXCEPTION(env); 
  
     return jStr; 
 } 

This GitHub issue tracker is not actively tracked or managed. Please file a bug at bugreport.java.com.

ok.