| 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 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 mLastUpdateCompositionStart = compositionStart; | 205 mLastUpdateCompositionStart = compositionStart; |
| 207 mLastUpdateCompositionEnd = compositionEnd; | 206 mLastUpdateCompositionEnd = compositionEnd; |
| 208 } | 207 } |
| 209 | 208 |
| 210 /** | 209 /** |
| 211 * @see BaseInputConnection#setComposingText(java.lang.CharSequence, int) | 210 * @see BaseInputConnection#setComposingText(java.lang.CharSequence, int) |
| 212 */ | 211 */ |
| 213 @Override | 212 @Override |
| 214 public boolean setComposingText(CharSequence text, int newCursorPosition) { | 213 public boolean setComposingText(CharSequence text, int newCursorPosition) { |
| 215 if (DEBUG) Log.w(TAG, "setComposingText [" + text + "] [" + newCursorPos
ition + "]"); | 214 if (DEBUG) Log.w(TAG, "setComposingText [" + text + "] [" + newCursorPos
ition + "]"); |
| 216 if (maybePerformEmptyCompositionWorkaround(text)) return true; | |
| 217 super.setComposingText(text, newCursorPosition); | 215 super.setComposingText(text, newCursorPosition); |
| 218 updateSelectionIfRequired(); | 216 updateSelectionIfRequired(); |
| 219 return mImeAdapter.checkCompositionQueueAndCallNative(text, newCursorPos
ition, false); | 217 return mImeAdapter.checkCompositionQueueAndCallNative(text, newCursorPos
ition, false); |
| 220 } | 218 } |
| 221 | 219 |
| 222 /** | 220 /** |
| 223 * @see BaseInputConnection#commitText(java.lang.CharSequence, int) | 221 * @see BaseInputConnection#commitText(java.lang.CharSequence, int) |
| 224 */ | 222 */ |
| 225 @Override | 223 @Override |
| 226 public boolean commitText(CharSequence text, int newCursorPosition) { | 224 public boolean commitText(CharSequence text, int newCursorPosition) { |
| 227 if (DEBUG) Log.w(TAG, "commitText [" + text + "] [" + newCursorPosition
+ "]"); | 225 if (DEBUG) Log.w(TAG, "commitText [" + text + "] [" + newCursorPosition
+ "]"); |
| 228 if (maybePerformEmptyCompositionWorkaround(text)) return true; | |
| 229 super.commitText(text, newCursorPosition); | 226 super.commitText(text, newCursorPosition); |
| 230 updateSelectionIfRequired(); | 227 updateSelectionIfRequired(); |
| 231 return mImeAdapter.checkCompositionQueueAndCallNative(text, newCursorPos
ition, | 228 return mImeAdapter.checkCompositionQueueAndCallNative(text, newCursorPos
ition, |
| 232 text.length() > 0); | 229 text.length() > 0); |
| 233 } | 230 } |
| 234 | 231 |
| 235 /** | 232 /** |
| 236 * @see BaseInputConnection#performEditorAction(int) | 233 * @see BaseInputConnection#performEditorAction(int) |
| 237 */ | 234 */ |
| 238 @Override | 235 @Override |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 if (b < 0) b = 0; | 427 if (b < 0) b = 0; |
| 431 if (a > textLength) a = textLength; | 428 if (a > textLength) a = textLength; |
| 432 if (b > textLength) b = textLength; | 429 if (b > textLength) b = textLength; |
| 433 | 430 |
| 434 if (a == b) { | 431 if (a == b) { |
| 435 removeComposingSpans(mEditable); | 432 removeComposingSpans(mEditable); |
| 436 } else { | 433 } else { |
| 437 super.setComposingRegion(a, b); | 434 super.setComposingRegion(a, b); |
| 438 } | 435 } |
| 439 updateSelectionIfRequired(); | 436 updateSelectionIfRequired(); |
| 440 return mImeAdapter.setComposingRegion(a, b); | 437 |
| 438 CharSequence regionText = null; |
| 439 if (b > a) { |
| 440 regionText = mEditable.subSequence(start, end); |
| 441 } |
| 442 return mImeAdapter.setComposingRegion(regionText, a, b); |
| 441 } | 443 } |
| 442 | 444 |
| 443 boolean isActive() { | 445 boolean isActive() { |
| 444 return getInputMethodManagerWrapper().isActive(mInternalView); | 446 return getInputMethodManagerWrapper().isActive(mInternalView); |
| 445 } | 447 } |
| 446 | 448 |
| 447 private InputMethodManagerWrapper getInputMethodManagerWrapper() { | 449 private InputMethodManagerWrapper getInputMethodManagerWrapper() { |
| 448 return mImeAdapter.getInputMethodManagerWrapper(); | 450 return mImeAdapter.getInputMethodManagerWrapper(); |
| 449 } | 451 } |
| 450 | 452 |
| 451 /** | |
| 452 * This method works around the issue crbug.com/373934 where Blink does not
cancel | |
| 453 * the composition when we send a commit with the empty text. | |
| 454 * | |
| 455 * TODO(aurimas) Remove this once crbug.com/373934 is fixed. | |
| 456 * | |
| 457 * @param text Text that software keyboard requested to commit. | |
| 458 * @return Whether the workaround was performed. | |
| 459 */ | |
| 460 private boolean maybePerformEmptyCompositionWorkaround(CharSequence text) { | |
| 461 int selectionStart = Selection.getSelectionStart(mEditable); | |
| 462 int selectionEnd = Selection.getSelectionEnd(mEditable); | |
| 463 int compositionStart = getComposingSpanStart(mEditable); | |
| 464 int compositionEnd = getComposingSpanEnd(mEditable); | |
| 465 if (TextUtils.isEmpty(text) && (selectionStart == selectionEnd) | |
| 466 && compositionStart != INVALID_COMPOSITION | |
| 467 && compositionEnd != INVALID_COMPOSITION) { | |
| 468 beginBatchEdit(); | |
| 469 finishComposingText(); | |
| 470 int selection = Selection.getSelectionStart(mEditable); | |
| 471 deleteSurroundingText(selection - compositionStart, selection - comp
ositionEnd); | |
| 472 endBatchEdit(); | |
| 473 return true; | |
| 474 } | |
| 475 return false; | |
| 476 } | |
| 477 | |
| 478 @VisibleForTesting | 453 @VisibleForTesting |
| 479 static class ImeState { | 454 static class ImeState { |
| 480 public final String text; | 455 public final String text; |
| 481 public final int selectionStart; | 456 public final int selectionStart; |
| 482 public final int selectionEnd; | 457 public final int selectionEnd; |
| 483 public final int compositionStart; | 458 public final int compositionStart; |
| 484 public final int compositionEnd; | 459 public final int compositionEnd; |
| 485 | 460 |
| 486 public ImeState(String text, int selectionStart, int selectionEnd, | 461 public ImeState(String text, int selectionStart, int selectionEnd, |
| 487 int compositionStart, int compositionEnd) { | 462 int compositionStart, int compositionEnd) { |
| 488 this.text = text; | 463 this.text = text; |
| 489 this.selectionStart = selectionStart; | 464 this.selectionStart = selectionStart; |
| 490 this.selectionEnd = selectionEnd; | 465 this.selectionEnd = selectionEnd; |
| 491 this.compositionStart = compositionStart; | 466 this.compositionStart = compositionStart; |
| 492 this.compositionEnd = compositionEnd; | 467 this.compositionEnd = compositionEnd; |
| 493 } | 468 } |
| 494 } | 469 } |
| 495 | 470 |
| 496 @VisibleForTesting | 471 @VisibleForTesting |
| 497 ImeState getImeStateForTesting() { | 472 ImeState getImeStateForTesting() { |
| 498 String text = mEditable.toString(); | 473 String text = mEditable.toString(); |
| 499 int selectionStart = Selection.getSelectionStart(mEditable); | 474 int selectionStart = Selection.getSelectionStart(mEditable); |
| 500 int selectionEnd = Selection.getSelectionEnd(mEditable); | 475 int selectionEnd = Selection.getSelectionEnd(mEditable); |
| 501 int compositionStart = getComposingSpanStart(mEditable); | 476 int compositionStart = getComposingSpanStart(mEditable); |
| 502 int compositionEnd = getComposingSpanEnd(mEditable); | 477 int compositionEnd = getComposingSpanEnd(mEditable); |
| 503 return new ImeState(text, selectionStart, selectionEnd, compositionStart
, compositionEnd); | 478 return new ImeState(text, selectionStart, selectionEnd, compositionStart
, compositionEnd); |
| 504 } | 479 } |
| 505 } | 480 } |
| OLD | NEW |