Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.content.browser.input; | 5 package org.chromium.content.browser.input; |
| 6 | 6 |
| 7 import android.os.SystemClock; | 7 import android.os.SystemClock; |
| 8 import android.text.Editable; | 8 import android.text.Editable; |
| 9 import android.text.InputType; | 9 import android.text.InputType; |
| 10 import android.text.Selection; | 10 import android.text.Selection; |
| 11 import android.text.TextUtils; | |
| 12 import android.util.Log; | 11 import android.util.Log; |
| 13 import android.view.KeyEvent; | 12 import android.view.KeyEvent; |
| 14 import android.view.View; | 13 import android.view.View; |
| 15 import android.view.inputmethod.BaseInputConnection; | 14 import android.view.inputmethod.BaseInputConnection; |
| 16 import android.view.inputmethod.EditorInfo; | 15 import android.view.inputmethod.EditorInfo; |
| 17 import android.view.inputmethod.ExtractedText; | 16 import android.view.inputmethod.ExtractedText; |
| 18 import android.view.inputmethod.ExtractedTextRequest; | 17 import android.view.inputmethod.ExtractedTextRequest; |
| 19 | 18 |
| 20 import com.google.common.annotations.VisibleForTesting; | 19 import com.google.common.annotations.VisibleForTesting; |
| 21 | 20 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 132 * selection. | 131 * selection. |
| 133 * @param isNonImeChange True when the update was caused by non-IME (e.g. Ja vascript). | 132 * @param isNonImeChange True when the update was caused by non-IME (e.g. Ja vascript). |
| 134 */ | 133 */ |
| 135 @VisibleForTesting | 134 @VisibleForTesting |
| 136 public void updateState(String text, int selectionStart, int selectionEnd, i nt compositionStart, | 135 public void updateState(String text, int selectionStart, int selectionEnd, i nt compositionStart, |
| 137 int compositionEnd, boolean isNonImeChange) { | 136 int compositionEnd, boolean isNonImeChange) { |
| 138 if (DEBUG) { | 137 if (DEBUG) { |
| 139 Log.w(TAG, "updateState [" + text + "] [" + selectionStart + " " + s electionEnd + "] [" | 138 Log.w(TAG, "updateState [" + text + "] [" + selectionStart + " " + s electionEnd + "] [" |
| 140 + compositionStart + " " + compositionEnd + "] [" + isNonIme Change + "]"); | 139 + compositionStart + " " + compositionEnd + "] [" + isNonIme Change + "]"); |
| 141 } | 140 } |
| 141 | |
|
aurimas (slooooooooow)
2014/07/22 16:25:43
Undo this new line change.
bcwhite
2014/07/22 17:28:33
Done.
| |
| 142 // If this update is from the IME, no further state modification is nece ssary because the | 142 // If this update is from the IME, no further state modification is nece ssary because the |
| 143 // state should have been updated already by the IM framework directly. | 143 // state should have been updated already by the IM framework directly. |
| 144 if (!isNonImeChange) return; | 144 if (!isNonImeChange) return; |
| 145 | 145 |
| 146 // Non-breaking spaces can cause the IME to get confused. Replace with n ormal spaces. | 146 // Non-breaking spaces can cause the IME to get confused. Replace with n ormal spaces. |
| 147 text = text.replace('\u00A0', ' '); | 147 text = text.replace('\u00A0', ' '); |
| 148 | 148 |
| 149 selectionStart = Math.min(selectionStart, text.length()); | 149 selectionStart = Math.min(selectionStart, text.length()); |
| 150 selectionEnd = Math.min(selectionEnd, text.length()); | 150 selectionEnd = Math.min(selectionEnd, text.length()); |
| 151 compositionStart = Math.min(compositionStart, text.length()); | 151 compositionStart = Math.min(compositionStart, text.length()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 206 mLastUpdateCompositionStart = compositionStart; | 206 mLastUpdateCompositionStart = compositionStart; |
| 207 mLastUpdateCompositionEnd = compositionEnd; | 207 mLastUpdateCompositionEnd = compositionEnd; |
| 208 } | 208 } |
| 209 | 209 |
| 210 /** | 210 /** |
| 211 * @see BaseInputConnection#setComposingText(java.lang.CharSequence, int) | 211 * @see BaseInputConnection#setComposingText(java.lang.CharSequence, int) |
| 212 */ | 212 */ |
| 213 @Override | 213 @Override |
| 214 public boolean setComposingText(CharSequence text, int newCursorPosition) { | 214 public boolean setComposingText(CharSequence text, int newCursorPosition) { |
| 215 if (DEBUG) Log.w(TAG, "setComposingText [" + text + "] [" + newCursorPos ition + "]"); | 215 if (DEBUG) Log.w(TAG, "setComposingText [" + text + "] [" + newCursorPos ition + "]"); |
| 216 if (maybePerformEmptyCompositionWorkaround(text)) return true; | |
| 217 super.setComposingText(text, newCursorPosition); | 216 super.setComposingText(text, newCursorPosition); |
| 218 updateSelectionIfRequired(); | 217 updateSelectionIfRequired(); |
| 219 return mImeAdapter.checkCompositionQueueAndCallNative(text, newCursorPos ition, false); | 218 return mImeAdapter.checkCompositionQueueAndCallNative(text, newCursorPos ition, false); |
| 220 } | 219 } |
| 221 | 220 |
| 222 /** | 221 /** |
| 223 * @see BaseInputConnection#commitText(java.lang.CharSequence, int) | 222 * @see BaseInputConnection#commitText(java.lang.CharSequence, int) |
| 224 */ | 223 */ |
| 225 @Override | 224 @Override |
| 226 public boolean commitText(CharSequence text, int newCursorPosition) { | 225 public boolean commitText(CharSequence text, int newCursorPosition) { |
| 227 if (DEBUG) Log.w(TAG, "commitText [" + text + "] [" + newCursorPosition + "]"); | 226 if (DEBUG) Log.w(TAG, "commitText [" + text + "] [" + newCursorPosition + "]"); |
| 228 if (maybePerformEmptyCompositionWorkaround(text)) return true; | |
| 229 super.commitText(text, newCursorPosition); | 227 super.commitText(text, newCursorPosition); |
| 230 updateSelectionIfRequired(); | 228 updateSelectionIfRequired(); |
| 231 return mImeAdapter.checkCompositionQueueAndCallNative(text, newCursorPos ition, | 229 return mImeAdapter.checkCompositionQueueAndCallNative(text, newCursorPos ition, |
| 232 text.length() > 0); | 230 text.length() > 0); |
| 233 } | 231 } |
| 234 | 232 |
| 235 /** | 233 /** |
| 236 * @see BaseInputConnection#performEditorAction(int) | 234 * @see BaseInputConnection#performEditorAction(int) |
| 237 */ | 235 */ |
| 238 @Override | 236 @Override |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 453 if (b < 0) b = 0; | 451 if (b < 0) b = 0; |
| 454 if (a > textLength) a = textLength; | 452 if (a > textLength) a = textLength; |
| 455 if (b > textLength) b = textLength; | 453 if (b > textLength) b = textLength; |
| 456 | 454 |
| 457 if (a == b) { | 455 if (a == b) { |
| 458 removeComposingSpans(mEditable); | 456 removeComposingSpans(mEditable); |
| 459 } else { | 457 } else { |
| 460 super.setComposingRegion(a, b); | 458 super.setComposingRegion(a, b); |
| 461 } | 459 } |
| 462 updateSelectionIfRequired(); | 460 updateSelectionIfRequired(); |
| 463 return mImeAdapter.setComposingRegion(a, b); | 461 |
| 462 CharSequence regionText = null; | |
| 463 if (b > a) { | |
| 464 regionText = mEditable.subSequence(start, end); | |
| 465 } | |
| 466 return mImeAdapter.setComposingRegion(regionText, a, b); | |
| 464 } | 467 } |
| 465 | 468 |
| 466 boolean isActive() { | 469 boolean isActive() { |
| 467 return getInputMethodManagerWrapper().isActive(mInternalView); | 470 return getInputMethodManagerWrapper().isActive(mInternalView); |
| 468 } | 471 } |
| 469 | 472 |
| 470 private InputMethodManagerWrapper getInputMethodManagerWrapper() { | 473 private InputMethodManagerWrapper getInputMethodManagerWrapper() { |
| 471 return mImeAdapter.getInputMethodManagerWrapper(); | 474 return mImeAdapter.getInputMethodManagerWrapper(); |
| 472 } | 475 } |
| 473 | 476 |
| 474 /** | |
| 475 * This method works around the issue crbug.com/373934 where Blink does not cancel | |
| 476 * the composition when we send a commit with the empty text. | |
| 477 * | |
| 478 * TODO(aurimas) Remove this once crbug.com/373934 is fixed. | |
| 479 * | |
| 480 * @param text Text that software keyboard requested to commit. | |
| 481 * @return Whether the workaround was performed. | |
| 482 */ | |
| 483 private boolean maybePerformEmptyCompositionWorkaround(CharSequence text) { | |
|
aurimas (slooooooooow)
2014/07/22 16:25:43
I was under impression that you did not want to re
bcwhite
2014/07/22 17:28:33
I wasn't going to. But apparently I must have tri
aurimas (slooooooooow)
2014/07/22 17:48:10
Let's land it as a separate CL in case it needs to
| |
| 484 int selectionStart = Selection.getSelectionStart(mEditable); | |
| 485 int selectionEnd = Selection.getSelectionEnd(mEditable); | |
| 486 int compositionStart = getComposingSpanStart(mEditable); | |
| 487 int compositionEnd = getComposingSpanEnd(mEditable); | |
| 488 if (TextUtils.isEmpty(text) && (selectionStart == selectionEnd) | |
| 489 && compositionStart != INVALID_COMPOSITION | |
| 490 && compositionEnd != INVALID_COMPOSITION) { | |
| 491 beginBatchEdit(); | |
| 492 finishComposingText(); | |
| 493 int selection = Selection.getSelectionStart(mEditable); | |
| 494 deleteSurroundingText(selection - compositionStart, selection - comp ositionEnd); | |
| 495 endBatchEdit(); | |
| 496 return true; | |
| 497 } | |
| 498 return false; | |
| 499 } | |
| 500 | |
| 501 @VisibleForTesting | 477 @VisibleForTesting |
| 502 static class ImeState { | 478 static class ImeState { |
| 503 public final String text; | 479 public final String text; |
| 504 public final int selectionStart; | 480 public final int selectionStart; |
| 505 public final int selectionEnd; | 481 public final int selectionEnd; |
| 506 public final int compositionStart; | 482 public final int compositionStart; |
| 507 public final int compositionEnd; | 483 public final int compositionEnd; |
| 508 | 484 |
| 509 public ImeState(String text, int selectionStart, int selectionEnd, | 485 public ImeState(String text, int selectionStart, int selectionEnd, |
| 510 int compositionStart, int compositionEnd) { | 486 int compositionStart, int compositionEnd) { |
| 511 this.text = text; | 487 this.text = text; |
| 512 this.selectionStart = selectionStart; | 488 this.selectionStart = selectionStart; |
| 513 this.selectionEnd = selectionEnd; | 489 this.selectionEnd = selectionEnd; |
| 514 this.compositionStart = compositionStart; | 490 this.compositionStart = compositionStart; |
| 515 this.compositionEnd = compositionEnd; | 491 this.compositionEnd = compositionEnd; |
| 516 } | 492 } |
| 517 } | 493 } |
| 518 | 494 |
| 519 @VisibleForTesting | 495 @VisibleForTesting |
| 520 ImeState getImeStateForTesting() { | 496 ImeState getImeStateForTesting() { |
| 521 String text = mEditable.toString(); | 497 String text = mEditable.toString(); |
| 522 int selectionStart = Selection.getSelectionStart(mEditable); | 498 int selectionStart = Selection.getSelectionStart(mEditable); |
| 523 int selectionEnd = Selection.getSelectionEnd(mEditable); | 499 int selectionEnd = Selection.getSelectionEnd(mEditable); |
| 524 int compositionStart = getComposingSpanStart(mEditable); | 500 int compositionStart = getComposingSpanStart(mEditable); |
| 525 int compositionEnd = getComposingSpanEnd(mEditable); | 501 int compositionEnd = getComposingSpanEnd(mEditable); |
| 526 return new ImeState(text, selectionStart, selectionEnd, compositionStart , compositionEnd); | 502 return new ImeState(text, selectionStart, selectionEnd, compositionStart , compositionEnd); |
| 527 } | 503 } |
| 528 } | 504 } |
| OLD | NEW |