Skip to content

Commit e300be9

Browse files
author
Gilles Debunne
committed
IOOB is Suggestions
Bug 5555929 This problem only happens when in landscape extracted text mode. A suggestion pick from the popup window replaces the text in the ExtractedText, when it should do it in the underlying source EditText instead. When the replacement text is longer than the replaced text and is at the end of the text, an IOOB occurs because the ExtractedText was not modified (we now correctly change the source text using replaceText_internal). This is basically an implementation of the TODO comment next to setSpan in TextView. Change-Id: I6575137530e0bb5c9ac7e40cc2bba9c66dc254d2
1 parent 6db79c3 commit e300be9

File tree

3 files changed

+64
-11
lines changed

3 files changed

+64
-11
lines changed

core/java/android/inputmethodservice/ExtractEditText.java

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,25 +158,46 @@ public boolean hasVerticalScrollBar() {
158158
}
159159

160160
/**
161-
* Delete the range of text, supposedly valid
161+
* {@inheritDoc}
162162
* @hide
163163
*/
164164
@Override
165165
protected void deleteText_internal(int start, int end) {
166-
// Do not call the super method. This will change the source TextView instead, which
167-
// will update the ExtractTextView.
166+
// Do not call the super method.
167+
// This will change the source TextView instead, which will update the ExtractTextView.
168168
mIME.onExtractedDeleteText(start, end);
169169
}
170170

171171
/**
172-
* Replaces the range of text [start, end[ by replacement text
172+
* {@inheritDoc}
173173
* @hide
174174
*/
175175
@Override
176176
protected void replaceText_internal(int start, int end, CharSequence text) {
177-
// Do not call the super method. This will change the source TextView instead, which
178-
// will update the ExtractTextView.
177+
// Do not call the super method.
178+
// This will change the source TextView instead, which will update the ExtractTextView.
179179
mIME.onExtractedReplaceText(start, end, text);
180180
}
181181

182+
/**
183+
* {@inheritDoc}
184+
* @hide
185+
*/
186+
@Override
187+
protected void setSpan_internal(Object span, int start, int end, int flags) {
188+
// Do not call the super method.
189+
// This will change the source TextView instead, which will update the ExtractTextView.
190+
mIME.onExtractedSetSpan(span, start, end, flags);
191+
}
192+
193+
/**
194+
* {@inheritDoc}
195+
* @hide
196+
*/
197+
@Override
198+
protected void setCursorPosition_internal(int start, int end) {
199+
// Do not call the super method.
200+
// This will change the source TextView instead, which will update the ExtractTextView.
201+
mIME.onExtractedSelectionChanged(start, end);
202+
}
182203
}

core/java/android/inputmethodservice/InputMethodService.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2005,6 +2005,22 @@ public void onExtractedReplaceText(int start, int end, CharSequence text) {
20052005
}
20062006
}
20072007

2008+
/**
2009+
* @hide
2010+
*/
2011+
public void onExtractedSetSpan(Object span, int start, int end, int flags) {
2012+
InputConnection conn = getCurrentInputConnection();
2013+
if (conn != null) {
2014+
if (!conn.setSelection(start, end)) return;
2015+
CharSequence text = conn.getSelectedText(InputConnection.GET_TEXT_WITH_STYLES);
2016+
if (text instanceof Spannable) {
2017+
((Spannable) text).setSpan(span, 0, text.length(), flags);
2018+
conn.setComposingRegion(start, end);
2019+
conn.commitText(text, 1);
2020+
}
2021+
}
2022+
}
2023+
20082024
/**
20092025
* This is called when the user has clicked on the extracted text view,
20102026
* when running in fullscreen mode. The default implementation hides

core/java/android/widget/TextView.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9829,7 +9829,7 @@ private void updateSuggestions() {
98299829
highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd);
98309830
}
98319831

9832-
// Add to dictionary item is there a span with the misspelled flag
9832+
// Add to dictionary item if there is a span with the misspelled flag
98339833
if (misspelledSpan != null) {
98349834
final int misspelledStart = spannable.getSpanStart(misspelledSpan);
98359835
final int misspelledEnd = spannable.getSpanEnd(misspelledSpan);
@@ -9915,7 +9915,7 @@ public void onItemClick(AdapterView<?> parent, View view, int position, long id)
99159915

99169916
final int spanStart = editable.getSpanStart(suggestionInfo.suggestionSpan);
99179917
final int spanEnd = editable.getSpanEnd(suggestionInfo.suggestionSpan);
9918-
if (spanStart < 0 || spanEnd < 0) {
9918+
if (spanStart < 0 || spanEnd <= spanStart) {
99199919
// Span has been removed
99209920
hide();
99219921
return;
@@ -9982,14 +9982,14 @@ public void onItemClick(AdapterView<?> parent, View view, int position, long id)
99829982
// way to assign them a valid range after replacement
99839983
if (suggestionSpansStarts[i] <= spanStart &&
99849984
suggestionSpansEnds[i] >= spanEnd) {
9985-
// TODO The ExtractEditText should restore these spans in the original text
9986-
editable.setSpan(suggestionSpans[i], suggestionSpansStarts[i],
9985+
setSpan_internal(suggestionSpans[i], suggestionSpansStarts[i],
99879986
suggestionSpansEnds[i] + lengthDifference, suggestionSpansFlags[i]);
99889987
}
99899988
}
99909989

99919990
// Move cursor at the end of the replaced word
9992-
Selection.setSelection(editable, spanEnd + lengthDifference);
9991+
final int newCursorPosition = spanEnd + lengthDifference;
9992+
setCursorPosition_internal(newCursorPosition, newCursorPosition);
99939993
}
99949994

99959995
hide();
@@ -11462,6 +11462,22 @@ protected void replaceText_internal(int start, int end, CharSequence text) {
1146211462
((Editable) mText).replace(start, end, text);
1146311463
}
1146411464

11465+
/**
11466+
* Sets a span on the specified range of text
11467+
* @hide
11468+
*/
11469+
protected void setSpan_internal(Object span, int start, int end, int flags) {
11470+
((Editable) mText).setSpan(span, start, end, flags);
11471+
}
11472+
11473+
/**
11474+
* Moves the cursor to the specified offset position in text
11475+
* @hide
11476+
*/
11477+
protected void setCursorPosition_internal(int start, int end) {
11478+
Selection.setSelection(((Editable) mText), start, end);
11479+
}
11480+
1146511481
@ViewDebug.ExportedProperty(category = "text")
1146611482
private CharSequence mText;
1146711483
private CharSequence mTransformed;

0 commit comments

Comments
 (0)