Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle input method events #370

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
53 changes: 52 additions & 1 deletion rta/src/main/java/com/gluonhq/richtextarea/RichTextAreaSkin.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.InputMethodEvent;
import javafx.scene.input.InputMethodRequests;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.input.KeyEvent;
Expand Down Expand Up @@ -450,6 +452,9 @@ protected void invalidated() {
private final ChangeListener<Boolean> tableAllowedListener;
private final ChangeListener<EmojiSkinTone> skinToneChangeListener;

private final EventHandler<InputMethodEvent> inputMethodTextChangedHandler = this::handleInputMethodEvent;
private final InputMethodRequests inputMethodRequests = createIMRequests();

private final ResourceBundle resources;

private class RichVirtualFlow extends VirtualFlow<ListCell<Paragraph>> {
Expand Down Expand Up @@ -703,6 +708,8 @@ public void dispose() {
getSkinnable().tableAllowedProperty().removeListener(tableAllowedListener);
getSkinnable().setOnKeyPressed(null);
getSkinnable().setOnKeyTyped(null);
getSkinnable().setInputMethodRequests(null);
getSkinnable().setOnInputMethodTextChanged(null);
getSkinnable().widthProperty().removeListener(controlPrefWidthListener);
getSkinnable().focusedProperty().removeListener(focusListener);
getSkinnable().removeEventHandler(DragEvent.ANY, dndHandler);
Expand Down Expand Up @@ -750,6 +757,9 @@ private void setup(Document document) {
viewModel.setTableAllowed(getSkinnable().isTableAllowed());
getSkinnable().setOnKeyPressed(this::keyPressedListener);
getSkinnable().setOnKeyTyped(this::keyTypedListener);
// Note both setOnInputMethodTextChanged() and setInputMethodRequests() are required for IME to work
getSkinnable().setOnInputMethodTextChanged(inputMethodTextChangedHandler);
getSkinnable().setInputMethodRequests(inputMethodRequests);
getSkinnable().widthProperty().addListener(controlPrefWidthListener);
getSkinnable().focusedProperty().addListener(focusListener);
getSkinnable().addEventHandler(DragEvent.ANY, dndHandler);
Expand Down Expand Up @@ -813,7 +823,11 @@ private void refreshTextFlow() {
requestLayout();
nonTextNodesCount = nonTextNodes.get();
}
getSkinnable().requestFocus();
if (getSkinnable().getScene() != null && getSkinnable().getScene().getWindow() != null &&
getSkinnable().getScene().getFocusOwner() != null) {
// don't request focus if scene doesn't have a focus owner yet,
getSkinnable().requestFocus();
}
} finally {
objectsCacheEvictionTimer.start();
}
Expand Down Expand Up @@ -938,6 +952,43 @@ private void keyTypedListener(KeyEvent e) {
}
}

private InputMethodRequests createIMRequests() {
// dummy implementation for now
return new InputMethodRequests() {
@Override
public Point2D getTextLocation(int offset) {
return Point2D.ZERO;
}

@Override
public String getSelectedText() {
return null;
}

@Override
public int getLocationOffset(int x, int y) {
return 0;
}

@Override
public void cancelLatestCommittedText() {
}
};
}

private void handleInputMethodEvent(InputMethodEvent event) {
final RichTextArea control = getSkinnable();
if (control.isEditable() && !control.isDisabled()) {
// Insert committed text
String committed = event.getCommitted();
if (!committed.isEmpty()) {
control.setOnInputMethodTextChanged(null);
execute(ACTION_CMD_FACTORY.insertText(committed));
control.setOnInputMethodTextChanged(inputMethodTextChangedHandler);
}
}
}

private void populateContextMenu(boolean isEditable) {
if (isEditable && editableContextMenuItems == null) {
editableContextMenuItems = FXCollections.observableArrayList(
Expand Down
Loading