Skip to content

Commit

Permalink
Merge pull request #11389 from keymanapp/refactor/android/update-sele…
Browse files Browse the repository at this point in the history
…ction

refactor(android/engine): Refactor updateSelection
  • Loading branch information
darcywong00 authored May 9, 2024
2 parents 58f169e + 4cd8a00 commit 298437e
Showing 1 changed file with 45 additions and 39 deletions.
84 changes: 45 additions & 39 deletions android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java
Original file line number Diff line number Diff line change
Expand Up @@ -170,57 +170,63 @@ protected boolean updateText(String text) {
return result;
}

/**
* Updates the selection range of the current context.
* Returns boolean - true if the selection range was updated successfully
*/
protected boolean updateSelectionRange() {
boolean result = false;

InputConnection ic = KMManager.getInputConnection(this.keyboardType);
if (ic != null) {
ExtractedText icText = ic.getExtractedText(new ExtractedTextRequest(), 0);
if (icText == null) {
return false;
}
if (ic == null) {
// Unable to get connection to the text
return false;
}

String rawText = icText.text.toString();
updateText(rawText.toString());
ExtractedText icText = ic.getExtractedText(new ExtractedTextRequest(), 0);
if (icText == null) {
// Failed to get text becausee either input connection became invalid or client is taking too long to respond
// https://developer.android.com/reference/android/view/inputmethod/InputConnection#getExtractedText(android.view.inputmethod.ExtractedTextRequest,%20int)
return false;
}

int selStart = icText.selectionStart;
int selEnd = icText.selectionEnd;
String rawText = icText.text.toString();
updateText(rawText.toString());

if (selStart < 0 || selEnd < 0) {
// There is no selection or cursor
// Reference https://developer.android.com/reference/android/text/Selection#getSelectionEnd(java.lang.CharSequence)
return false;
}
int selMin = icText.selectionStart, selMax = icText.selectionEnd;

int selMin = selStart, selMax = selEnd;
if (selStart > selEnd) {
// Selection is reversed so "swap"
selMin = selEnd;
selMax = selStart;
}
if (selMin < 0 || selMax < 0) {
// There is no selection or cursor
// Reference https://developer.android.com/reference/android/text/Selection#getSelectionEnd(java.lang.CharSequence)
return false;
}

/*
The values of selStart & selEnd provided by the system are in code units,
not code-points. We need to account for surrogate pairs here.
if (selMin > selMax) {
// Selection is reversed so "swap"
selMin = icText.selectionEnd;
selMax = icText.selectionStart;
}

Fortunately, it uses UCS-2 encoding... just like JS.
/*
The values of selStart & selEnd provided by the system are in code units,
not code-points. We need to account for surrogate pairs here.
References:
- https://stackoverflow.com/a/23980211
- https://android.googlesource.com/platform/frameworks/base/+/152944f/core/java/android/view/inputmethod/InputConnection.java#326
*/
Fortunately, it uses UCS-2 encoding... just like JS.
// Count the number of characters which are surrogate pairs.
int pairsAtStart = CharSequenceUtil.countSurrogatePairs(rawText.substring(0, selMin), rawText.length());
String selectedText = rawText.substring(selMin, selMax);
int pairsSelected = CharSequenceUtil.countSurrogatePairs(selectedText, selectedText.length());
References:
- https://stackoverflow.com/a/23980211
- https://android.googlesource.com/platform/frameworks/base/+/152944f/core/java/android/view/inputmethod/InputConnection.java#326
*/

selMin -= pairsAtStart;
selMax -= (pairsAtStart + pairsSelected);
this.loadJavascript(KMString.format("updateKMSelectionRange(%d,%d)", selMin, selMax));
}
result = true;
// Count the number of characters which are surrogate pairs.
int pairsAtStart = CharSequenceUtil.countSurrogatePairs(rawText.substring(0, selMin), rawText.length());
String selectedText = rawText.substring(selMin, selMax);
int pairsSelected = CharSequenceUtil.countSurrogatePairs(selectedText, selectedText.length());

return result;
selMin -= pairsAtStart;
selMax -= (pairsAtStart + pairsSelected);
this.loadJavascript(KMString.format("updateKMSelectionRange(%d,%d)", selMin, selMax));

return true;
}


Expand Down

0 comments on commit 298437e

Please sign in to comment.