summaryrefslogtreecommitdiffstats
path: root/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java')
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java47
1 files changed, 47 insertions, 0 deletions
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java
index 5426adb501..2e8f2e55d7 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java
@@ -655,6 +655,53 @@ import org.mozilla.gecko.util.ThreadUtils;
return replaceComposingSpanWithSelection()
&& mKeyInputConnection.commitText(text, newCursorPosition);
}
+
+ // Bug 1818268 - Unexpected crash on Galaxy J7
+ if (InputMethods.dontOverrideCommitText()) {
+ return super.commitText(text, newCursorPosition);
+ }
+
+ // Default implementation is
+ // 1. Set selection
+ // 2. Call Editable.replace
+ // 3. Set selection in Editable.replace
+ //
+ // However, this results in additional IPC in Gecko and unexpected selection before replacing
+ // text.
+ // When changing text in Gecko, the selection will be updated, so the default implementation is
+ // not compatible with Gecko's text handling.
+ // Therefore, we set the selection after replacing the text. However, if there is a composition,
+ // the selection may be an IME cursor, not a standard selection. In such cases, this step is not
+ // necessary.
+ final Editable content = getEditable();
+ if (content != null) {
+ final int compositionStart = getComposingSpanStart(content);
+ final int compositionEnd = getComposingSpanEnd(content);
+
+ if (compositionStart < 0 || compositionEnd < 0) {
+ // No composition
+ int selStart = Math.max(Selection.getSelectionStart(content), 0);
+ int selEnd = Math.max(Selection.getSelectionEnd(content), 0);
+ if (selStart > selEnd) {
+ final int tmp = selEnd;
+ selEnd = selStart;
+ selStart = tmp;
+ }
+
+ beginBatchEdit();
+ content.replace(selStart, selEnd, text);
+
+ int cursorPosition =
+ newCursorPosition > 0
+ ? selStart + text.length() + newCursorPosition - 1
+ : selStart + newCursorPosition;
+ cursorPosition = Math.min(Math.max(0, cursorPosition), content.length());
+ Selection.setSelection(content, cursorPosition);
+ endBatchEdit();
+ return true;
+ }
+ }
+
return super.commitText(text, newCursorPosition);
}