mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-04-26 09:36:50 +00:00
fix 9713c4a25a
not working when word ends with two equal codepoints
This commit is contained in:
parent
c78e729daa
commit
8fbb0ce0c7
2 changed files with 52 additions and 40 deletions
|
@ -699,7 +699,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
|
||||||
* @return a range containing the text surrounding the cursor
|
* @return a range containing the text surrounding the cursor
|
||||||
*/
|
*/
|
||||||
public TextRange getWordRangeAtCursor(final SpacingAndPunctuations spacingAndPunctuations,
|
public TextRange getWordRangeAtCursor(final SpacingAndPunctuations spacingAndPunctuations,
|
||||||
final int scriptId) {
|
final int scriptId, final boolean justDeleted) {
|
||||||
mIC = mParent.getCurrentInputConnection();
|
mIC = mParent.getCurrentInputConnection();
|
||||||
if (!isConnected()) {
|
if (!isConnected()) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -718,43 +718,24 @@ public final class RichInputConnection implements PrivateCommandPerformer {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// issue:
|
// we need text before, and text after is either empty or a separator or similar
|
||||||
// type 2 words and space, press delete twice -> remaining word and space before are selected
|
if (justDeleted && before.length() > 0 &&
|
||||||
// now on next key press, the space before the word is removed
|
(after.length() == 0
|
||||||
// or complete a word by choosing a suggestion than press backspace -> same thing
|
|| !isPartOfCompositionForScript(Character.codePointAt(after, 0), spacingAndPunctuations, scriptId)
|
||||||
// what is sometimes happening (depending on app, or maybe input field attributes):
|
)
|
||||||
// we just pressed delete, and getTextBeforeCursor gets the correct text,
|
) {
|
||||||
// but getTextBeforeCursorAndDetectLaggyConnection returns the old word, before the deletion (not sure why)
|
// issue:
|
||||||
// -> we try to detect this difference, and then try to fix it
|
// type 2 words and space, press delete twice -> remaining word and space before are selected
|
||||||
// interestingly, getTextBeforeCursor seems to only get the correct text because it uses
|
// now on next key press, the space before the word is removed
|
||||||
// mCommittedTextBeforeComposingText where the text is cached
|
// or complete a word by choosing a suggestion, then press backspace -> same thing
|
||||||
// what could be actually going on? we probably need to fetch the text because we want updated styles if any
|
// what is sometimes happening (depending on app, or maybe input field attributes):
|
||||||
|
// we just pressed delete, and getTextBeforeCursor gets the correct text,
|
||||||
// we need text before, and text after is always empty or a separator or similar
|
// but getTextBeforeCursorAndDetectLaggyConnection returns the old word, before the deletion (not sure why)
|
||||||
if (before.length() > 0 && (after.length() == 0 || !isPartOfCompositionForScript(Character.codePointAt(after, 0), spacingAndPunctuations, scriptId))) {
|
// -> we try to detect this difference, and then try to fix it
|
||||||
final int lastBeforeCodePoint = Character.codePointBefore(before, before.length());
|
// interestingly, getTextBeforeCursor seems to only get the correct text because it uses
|
||||||
// check whether before ends with the same codepoint as getTextBeforeCursor
|
// mCommittedTextBeforeComposingText, where the text is cached
|
||||||
int lastBeforeLength = Character.charCount(lastBeforeCodePoint);
|
// what could be actually going on? we probably need to fetch the text, because we want updated styles (if any)
|
||||||
CharSequence codePointBeforeCursor = getTextBeforeCursor(lastBeforeLength, 0);
|
before = fixIncorrectLength(before);
|
||||||
if (codePointBeforeCursor.length() != 0 && Character.codePointAt(codePointBeforeCursor, 0) != lastBeforeCodePoint) {
|
|
||||||
// they are different, as is expected from the issue
|
|
||||||
// now check whether they are the same if the last codepoint of before is removed
|
|
||||||
final CharSequence beforeWithoutLast = before.subSequence(0, before.length() - lastBeforeLength);
|
|
||||||
final CharSequence beforeCursor = getTextBeforeCursor(beforeWithoutLast.length(), 0);
|
|
||||||
if (beforeCursor.length() == beforeWithoutLast.length()) {
|
|
||||||
boolean same = true;
|
|
||||||
// CharSequence has undefined equals, so we need to compare characters
|
|
||||||
for (int i = 0; i < beforeCursor.length(); i++) {
|
|
||||||
if (beforeCursor.charAt(i) != beforeWithoutLast.charAt(i)) {
|
|
||||||
same = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (same) {
|
|
||||||
before = beforeWithoutLast;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Going backward, find the first breaking point (separator)
|
// Going backward, find the first breaking point (separator)
|
||||||
|
@ -794,6 +775,37 @@ public final class RichInputConnection implements PrivateCommandPerformer {
|
||||||
hasUrlSpans);
|
hasUrlSpans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mostly fixes an issue where the space before the word is selected after deleting a codepoint,
|
||||||
|
// because the text length is not yet updated in the field (i.e. trying to select "word length"
|
||||||
|
// before cursor, but the last letter has just been deleted and thus the space before is also selected)
|
||||||
|
private CharSequence fixIncorrectLength(final CharSequence before) {
|
||||||
|
// don't use codepoints, just do the simple thing...
|
||||||
|
int initialCheckLength = Math.min(3, before.length());
|
||||||
|
// this should have been checked before calling this method, but better be safe
|
||||||
|
if (initialCheckLength == 0) return before;
|
||||||
|
final CharSequence lastCharsInBefore = before.subSequence(before.length() - initialCheckLength, before.length());
|
||||||
|
final CharSequence lastCharsBeforeCursor = getTextBeforeCursor(initialCheckLength, 0);
|
||||||
|
// if the last 3 chars are equal, we can be relatively sure to not have this bug (can still be e.g. rrrr, which is not detected)
|
||||||
|
// (we could also check everything though, it's just a little slower)
|
||||||
|
if (TextUtils.equals(lastCharsInBefore, lastCharsBeforeCursor)) return before;
|
||||||
|
|
||||||
|
// delete will hopefully have deleted a codepoint, not only a char
|
||||||
|
// we want to compare whether the text before the cursor is the same as "before" without
|
||||||
|
// the last codepoint. if yes, return "before" without the last codepoint
|
||||||
|
final int lastBeforeCodePoint = Character.codePointBefore(before, before.length());
|
||||||
|
int lastBeforeLength = Character.charCount(lastBeforeCodePoint);
|
||||||
|
final CharSequence codePointBeforeCursor = getTextBeforeCursor(lastBeforeLength, 0);
|
||||||
|
if (codePointBeforeCursor.length() == 0) return before;
|
||||||
|
|
||||||
|
// now check whether they are the same if the last codepoint of before is removed
|
||||||
|
final CharSequence beforeWithoutLast = before.subSequence(0, before.length() - lastBeforeLength);
|
||||||
|
final CharSequence beforeCursor = getTextBeforeCursor(beforeWithoutLast.length(), 0);
|
||||||
|
if (beforeCursor.length() != beforeWithoutLast.length()) return before;
|
||||||
|
if (TextUtils.equals(beforeCursor, beforeWithoutLast))
|
||||||
|
return beforeWithoutLast;
|
||||||
|
return before;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isCursorTouchingWord(final SpacingAndPunctuations spacingAndPunctuations,
|
public boolean isCursorTouchingWord(final SpacingAndPunctuations spacingAndPunctuations,
|
||||||
boolean checkTextAfter) {
|
boolean checkTextAfter) {
|
||||||
if (checkTextAfter && isCursorFollowedByWordCharacter(spacingAndPunctuations)) {
|
if (checkTextAfter && isCursorFollowedByWordCharacter(spacingAndPunctuations)) {
|
||||||
|
|
|
@ -1255,7 +1255,7 @@ public final class InputLogic {
|
||||||
&& settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces) {
|
&& settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces) {
|
||||||
final TextRange range = mConnection.getWordRangeAtCursor(
|
final TextRange range = mConnection.getWordRangeAtCursor(
|
||||||
settingsValues.mSpacingAndPunctuations,
|
settingsValues.mSpacingAndPunctuations,
|
||||||
currentKeyboardScriptId);
|
currentKeyboardScriptId, false);
|
||||||
if (range != null) {
|
if (range != null) {
|
||||||
return range.mWord.toString();
|
return range.mWord.toString();
|
||||||
}
|
}
|
||||||
|
@ -1603,7 +1603,7 @@ public final class InputLogic {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final TextRange range = mConnection.getWordRangeAtCursor(
|
final TextRange range = mConnection.getWordRangeAtCursor(
|
||||||
settingsValues.mSpacingAndPunctuations, currentKeyboardScriptId);
|
settingsValues.mSpacingAndPunctuations, currentKeyboardScriptId, true);
|
||||||
if (null == range) return; // Happens if we don't have an input connection at all
|
if (null == range) return; // Happens if we don't have an input connection at all
|
||||||
if (range.length() <= 0) {
|
if (range.length() <= 0) {
|
||||||
// Race condition, or touching a word in a non-supported script.
|
// Race condition, or touching a word in a non-supported script.
|
||||||
|
|
Loading…
Add table
Reference in a new issue