AdapterInputConnection.java revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
19085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Copyright 2013 The Chromium Authors. All rights reserved. 29085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Use of this source code is governed by a BSD-style license that can be 39085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// found in the LICENSE file. 45ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 55ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.orgpackage org.chromium.content.browser.input; 65ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 75ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.orgimport android.os.SystemClock; 89085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgimport android.text.Editable; 99085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgimport android.text.InputType; 109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgimport android.text.Selection; 119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgimport android.text.TextUtils; 129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgimport android.util.Log; 139085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgimport android.view.KeyEvent; 149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgimport android.view.View; 159085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgimport android.view.inputmethod.BaseInputConnection; 169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgimport android.view.inputmethod.EditorInfo; 179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgimport android.view.inputmethod.ExtractedText; 189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgimport android.view.inputmethod.ExtractedTextRequest; 199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgimport com.google.common.annotations.VisibleForTesting; 219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org/** 239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * InputConnection is created by ContentView.onCreateInputConnection. 249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * It then adapts android's IME to chrome's RenderWidgetHostView using the 259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * native ImeAdapterAndroid via the class ImeAdapter. 269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org */ 279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgpublic class AdapterInputConnection extends BaseInputConnection { 289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private static final String TAG = "AdapterInputConnection"; 299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private static final boolean DEBUG = false; 309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org /** 319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * Selection value should be -1 if not known. See EditorInfo.java for details. 329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org */ 3356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org public static final int INVALID_SELECTION = -1; 349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public static final int INVALID_COMPOSITION = -1; 359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private final View mInternalView; 379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private final ImeAdapter mImeAdapter; 389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private final Editable mEditable; 399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 40c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org private boolean mSingleLine; 41c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org private int mNumNestedBatchEdits = 0; 4271affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org 4371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org private int mLastUpdateSelectionStart = INVALID_SELECTION; 449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private int mLastUpdateSelectionEnd = INVALID_SELECTION; 45e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org private int mLastUpdateCompositionStart = INVALID_COMPOSITION; 46e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org private int mLastUpdateCompositionEnd = INVALID_COMPOSITION; 47e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 481b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org @VisibleForTesting 4940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org AdapterInputConnection(View view, ImeAdapter imeAdapter, Editable editable, 5040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org EditorInfo outAttrs) { 51e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org super(view, true); 52e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org mInternalView = view; 531b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org mImeAdapter = imeAdapter; 5440b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org mImeAdapter.setInputConnection(this); 5540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org mEditable = editable; 56b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org // The editable passed in might have been in use by a prior keyboard and could have had 57b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org // prior composition spans set. To avoid keyboard conflicts, remove all composing spans 581b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org // when taking ownership of an existing Editable. 5940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org removeComposingSpans(mEditable); 6040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org mSingleLine = true; 61b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN 62b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org | EditorInfo.IME_FLAG_NO_EXTRACT_UI; 631b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT 6440b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org | EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT; 6540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org 66e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeText) { 67e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org // Normal text field 689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org outAttrs.inputType |= EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT; 699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO; 709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } else if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeTextArea || 719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeContentEditable) { 729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org // TextArea or contenteditable. 739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org outAttrs.inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE 749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES 759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org | EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT; 769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org outAttrs.imeOptions |= EditorInfo.IME_ACTION_NONE; 779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org mSingleLine = false; 789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } else if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypePassword) { 799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org // Password 809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org outAttrs.inputType = InputType.TYPE_CLASS_TEXT 819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD; 829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO; 839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } else if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeSearch) { 849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org // Search 859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org outAttrs.imeOptions |= EditorInfo.IME_ACTION_SEARCH; 869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } else if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeUrl) { 879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org // Url 889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org outAttrs.inputType = InputType.TYPE_CLASS_TEXT 899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org | InputType.TYPE_TEXT_VARIATION_URI; 909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO; 91a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } else if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeEmail) { 92a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Email 93a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org outAttrs.inputType = InputType.TYPE_CLASS_TEXT 94a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org | InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS; 95a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO; 96b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org } else if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeTel) { 97a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Telephone 98a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Number and telephone do not have both a Tab key and an 99a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // action in default OSK, so set the action to NEXT 100a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org outAttrs.inputType = InputType.TYPE_CLASS_PHONE; 101a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org outAttrs.imeOptions |= EditorInfo.IME_ACTION_NEXT; 102a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } else if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeNumber) { 103a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Number 104c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org outAttrs.inputType = InputType.TYPE_CLASS_NUMBER 1053a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org | InputType.TYPE_NUMBER_VARIATION_NORMAL 106c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org | InputType.TYPE_NUMBER_FLAG_DECIMAL; 107c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org outAttrs.imeOptions |= EditorInfo.IME_ACTION_NEXT; 108c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org } 109a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org outAttrs.initialSelStart = Selection.getSelectionStart(mEditable); 1103a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org outAttrs.initialSelEnd = Selection.getSelectionEnd(mEditable); 111c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org mLastUpdateSelectionStart = Selection.getSelectionStart(mEditable); 112c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org mLastUpdateSelectionEnd = Selection.getSelectionEnd(mEditable); 113c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org 114a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Selection.setSelection(mEditable, outAttrs.initialSelStart, outAttrs.initialSelEnd); 115a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org updateSelectionIfRequired(); 116a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } 117a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 118a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org /** 119c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org * Updates the AdapterInputConnection's internal representation of the text being edited and 120c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org * its selection and composition properties. The resulting Editable is accessible through the 121a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org * getEditable() method. If the text has not changed, this also calls updateSelection on the 122a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org * InputMethodManager. 123a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org * 124a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org * @param text The String contents of the field being edited. 125c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org * @param selectionStart The character offset of the selection start, or the caret position if 126b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org * there is no selection. 127a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org * @param selectionEnd The character offset of the selection end, or the caret position if there 128a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org * is no selection. 129a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org * @param compositionStart The character offset of the composition start, or -1 if there is no 130a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org * composition. 13184bcc559ac20fb04f806e97d28a314b20b58fd60svenpanne@chromium.org * @param compositionEnd The character offset of the composition end, or -1 if there is no 132eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org * selection. 133755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org * @param isNonImeChange True when the update was caused by non-IME (e.g. Javascript). 134755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org */ 135a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org @VisibleForTesting 1364a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org public void updateState(String text, int selectionStart, int selectionEnd, int compositionStart, 13756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org int compositionEnd, boolean isNonImeChange) { 13856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org if (DEBUG) { 1394a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org Log.w(TAG, "updateState [" + text + "] [" + selectionStart + " " + selectionEnd + "] [" 1409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org + compositionStart + " " + compositionEnd + "] [" + isNonImeChange + "]"); 1419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 1429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org // If this update is from the IME, no further state modification is necessary because the 1434a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org // state should have been updated already by the IM framework directly. 144eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org if (!isNonImeChange) return; 1459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 1469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org // Non-breaking spaces can cause the IME to get confused. Replace with normal spaces. 1475aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org text = text.replace('\u00A0', ' '); 1485aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org 1495aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org selectionStart = Math.min(selectionStart, text.length()); 1505aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org selectionEnd = Math.min(selectionEnd, text.length()); 1515aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org compositionStart = Math.min(compositionStart, text.length()); 1525aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org compositionEnd = Math.min(compositionEnd, text.length()); 1535aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org 1545aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org String prevText = mEditable.toString(); 1555aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org boolean textUnchanged = prevText.equals(text); 1565aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org 1575aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org if (!textUnchanged) { 1585c838251403b0be9a882540f1922577abba4c872ager@chromium.org mEditable.replace(0, mEditable.length(), text); 1595c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 1609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 1610ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org Selection.setSelection(mEditable, selectionStart, selectionEnd); 162c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org 163a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org if (compositionStart == compositionEnd) { 1643a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org removeComposingSpans(mEditable); 1659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } else { 1669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org super.setComposingRegion(compositionStart, compositionEnd); 1671456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org } 1681456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org updateSelectionIfRequired(); 1691456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org } 1701456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org 1711456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org /** 1721456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org * @return Editable object which contains the state of current focused editable element. 1731456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org */ 1741456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org @Override 1751456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org public Editable getEditable() { 1761456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org return mEditable; 1771456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org } 1781456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org 1791456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org /** 1801456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org * Sends selection update to the InputMethodManager unless we are currently in a batch edit or 1811456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org * if the exact same selection and composition update was sent already. 1821456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org */ 1831456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org private void updateSelectionIfRequired() { 1841456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org if (mNumNestedBatchEdits != 0) return; 1851456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org int selectionStart = Selection.getSelectionStart(mEditable); 1861456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org int selectionEnd = Selection.getSelectionEnd(mEditable); 1871456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org int compositionStart = getComposingSpanStart(mEditable); 1881456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org int compositionEnd = getComposingSpanEnd(mEditable); 1891456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org // Avoid sending update if we sent an exact update already previously. 1901456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org if (mLastUpdateSelectionStart == selectionStart && 1911456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org mLastUpdateSelectionEnd == selectionEnd && 1921456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org mLastUpdateCompositionStart == compositionStart && 1931456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org mLastUpdateCompositionEnd == compositionEnd) { 1941456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org return; 1951456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org } 1961456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org if (DEBUG) { 1971456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org Log.w(TAG, "updateSelectionIfRequired [" + selectionStart + " " + selectionEnd + "] [" 1981456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org + compositionStart + " " + compositionEnd + "]"); 1991456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org } 2001456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org // updateSelection should be called every time the selection or composition changes 2011456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org // if it happens not within a batch edit, or at the end of each top level batch edit. 2025aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org getInputMethodManagerWrapper().updateSelection(mInternalView, 2035aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org selectionStart, selectionEnd, compositionStart, compositionEnd); 2049085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org mLastUpdateSelectionStart = selectionStart; 20594b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org mLastUpdateSelectionEnd = selectionEnd; 206a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org mLastUpdateCompositionStart = compositionStart; 207a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org mLastUpdateCompositionEnd = compositionEnd; 208a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org } 209a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 210a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org /** 211a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org * @see BaseInputConnection#setComposingText(java.lang.CharSequence, int) 212a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org */ 213a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org @Override 214a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org public boolean setComposingText(CharSequence text, int newCursorPosition) { 215a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (DEBUG) Log.w(TAG, "setComposingText [" + text + "] [" + newCursorPosition + "]"); 216c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org if (maybePerformEmptyCompositionWorkaround(text)) return true; 217a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org super.setComposingText(text, newCursorPosition); 218c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org updateSelectionIfRequired(); 219c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org return mImeAdapter.checkCompositionQueueAndCallNative(text, newCursorPosition, false); 220c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org } 221c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org 222a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org /** 223a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org * @see BaseInputConnection#commitText(java.lang.CharSequence, int) 224a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org */ 225a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org @Override 226a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org public boolean commitText(CharSequence text, int newCursorPosition) { 227a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (DEBUG) Log.w(TAG, "commitText [" + text + "] [" + newCursorPosition + "]"); 228a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (maybePerformEmptyCompositionWorkaround(text)) return true; 229a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org super.commitText(text, newCursorPosition); 230a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org updateSelectionIfRequired(); 231a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org return mImeAdapter.checkCompositionQueueAndCallNative(text, newCursorPosition, 232a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org text.length() > 0); 233a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } 234a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 235a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org /** 236a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org * @see BaseInputConnection#performEditorAction(int) 237a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org */ 238a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org @Override 239a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org public boolean performEditorAction(int actionCode) { 240a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (DEBUG) Log.w(TAG, "performEditorAction [" + actionCode + "]"); 241a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (actionCode == EditorInfo.IME_ACTION_NEXT) { 242a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org restartInput(); 243a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Send TAB key event 244c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com long timeStampMs = SystemClock.uptimeMillis(); 245c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com mImeAdapter.sendSyntheticKeyEvent( 24694b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org ImeAdapter.sEventTypeRawKeyDown, timeStampMs, KeyEvent.KEYCODE_TAB, 0); 247c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } else { 248c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com mImeAdapter.sendKeyEventWithKeyCode(KeyEvent.KEYCODE_ENTER, 249c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE 25094b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org | KeyEvent.FLAG_EDITOR_ACTION); 251c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org } 2524a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org return true; 2539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 2549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 2559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org /** 2569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * @see BaseInputConnection#performContextMenuAction(int) 25786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org */ 25886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org @Override 25986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org public boolean performContextMenuAction(int id) { 26086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org if (DEBUG) Log.w(TAG, "performContextMenuAction [" + id + "]"); 26186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org switch (id) { 26286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org case android.R.id.selectAll: 26386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org return mImeAdapter.selectAll(); 26486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org case android.R.id.cut: 26586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org return mImeAdapter.cut(); 26686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org case android.R.id.copy: 26786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org return mImeAdapter.copy(); 2689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org case android.R.id.paste: 2699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return mImeAdapter.paste(); 2709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org default: 271b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org return false; 272b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org } 273b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org } 274b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org 275b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org /** 276b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org * @see BaseInputConnection#getExtractedText(android.view.inputmethod.ExtractedTextRequest, 277b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org * int) 278b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org */ 279b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org @Override 280b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) { 281b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org if (DEBUG) Log.w(TAG, "getExtractedText"); 282b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org ExtractedText et = new ExtractedText(); 283b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org et.text = mEditable.toString(); 284b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org et.partialEndOffset = mEditable.length(); 285b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org et.selectionStart = Selection.getSelectionStart(mEditable); 286b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org et.selectionEnd = Selection.getSelectionEnd(mEditable); 2879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org et.flags = mSingleLine ? ExtractedText.FLAG_SINGLE_LINE : 0; 288a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org return et; 289a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } 290a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 291a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org /** 2929085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * @see BaseInputConnection#beginBatchEdit() 2939085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org */ 2949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org @Override 2959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public boolean beginBatchEdit() { 2969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (DEBUG) Log.w(TAG, "beginBatchEdit [" + (mNumNestedBatchEdits == 0) + "]"); 2979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org mNumNestedBatchEdits++; 2989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return true; 2999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 3019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org /** 3029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * @see BaseInputConnection#endBatchEdit() 3039085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org */ 3049085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org @Override 3059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public boolean endBatchEdit() { 3069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (mNumNestedBatchEdits == 0) return false; 3079085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org --mNumNestedBatchEdits; 3089085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (DEBUG) Log.w(TAG, "endBatchEdit [" + (mNumNestedBatchEdits == 0) + "]"); 3099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (mNumNestedBatchEdits == 0) updateSelectionIfRequired(); 3109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return mNumNestedBatchEdits != 0; 3119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 3139d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com /** 3149d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com * @see BaseInputConnection#deleteSurroundingText(int, int) 3159d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com */ 3169d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com @Override 3179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public boolean deleteSurroundingText(int beforeLength, int afterLength) { 3189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (DEBUG) { 3199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org Log.w(TAG, "deleteSurroundingText [" + beforeLength + " " + afterLength + "]"); 3209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int availableBefore = Selection.getSelectionStart(mEditable); 3229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int availableAfter = mEditable.length() - Selection.getSelectionEnd(mEditable); 3239d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com beforeLength = Math.min(beforeLength, availableBefore); 3249d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com afterLength = Math.min(afterLength, availableAfter); 3259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org super.deleteSurroundingText(beforeLength, afterLength); 3269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org updateSelectionIfRequired(); 3279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return mImeAdapter.deleteSurroundingText(beforeLength, afterLength); 3289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 3309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org /** 3319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * @see BaseInputConnection#sendKeyEvent(android.view.KeyEvent) 3325ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org */ 3335ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org @Override 3345ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org public boolean sendKeyEvent(KeyEvent event) { 3355ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org if (DEBUG) { 3369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org Log.w(TAG, "sendKeyEvent [" + event.getAction() + "] [" + event.getKeyCode() + "]"); 3379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org // If this is a key-up, and backspace/del or if the key has a character representation, 3399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org // need to update the underlying Editable (i.e. the local representation of the text 3409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org // being edited). 3419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (event.getAction() == KeyEvent.ACTION_UP) { 3429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) { 3439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org deleteSurroundingText(1, 0); 3449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return true; 3459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } else if (event.getKeyCode() == KeyEvent.KEYCODE_FORWARD_DEL) { 3469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org deleteSurroundingText(0, 1); 3479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return true; 3489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } else { 3499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int unicodeChar = event.getUnicodeChar(); 3509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (unicodeChar != 0) { 3519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int selectionStart = Selection.getSelectionStart(mEditable); 3529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int selectionEnd = Selection.getSelectionEnd(mEditable); 3539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (selectionStart > selectionEnd) { 3549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int temp = selectionStart; 3559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org selectionStart = selectionEnd; 3569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org selectionEnd = temp; 3579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org mEditable.replace(selectionStart, selectionEnd, 3599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org Character.toString((char) unicodeChar)); 3609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3615ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org } 3629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } else if (event.getAction() == KeyEvent.ACTION_DOWN) { 3639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org // TODO(aurimas): remove this workaround when crbug.com/278584 is fixed. 3649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) { 3659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org beginBatchEdit(); 3669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org finishComposingText(); 367755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org mImeAdapter.translateAndSendNativeEvents(event); 3689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org endBatchEdit(); 3699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return true; 370755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org } else if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) { 3719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return true; 3729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } else if (event.getKeyCode() == KeyEvent.KEYCODE_FORWARD_DEL) { 3739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return true; 3749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org mImeAdapter.translateAndSendNativeEvents(event); 3779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return true; 3789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 3803e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org /** 3813e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org * @see BaseInputConnection#finishComposingText() 3823e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org */ 3833e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org @Override 3843e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org public boolean finishComposingText() { 3853e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org if (DEBUG) Log.w(TAG, "finishComposingText"); 3869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (getComposingSpanStart(mEditable) == getComposingSpanEnd(mEditable)) { 3879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return true; 3889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 3909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org super.finishComposingText(); 3919085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org updateSelectionIfRequired(); 392eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org mImeAdapter.finishComposingText(); 3939085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 3949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return true; 395755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org } 396755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 397755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org /** 398755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org * @see BaseInputConnection#setSelection(int, int) 3999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org */ 4009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org @Override 401755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org public boolean setSelection(int start, int end) { 402755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org if (DEBUG) Log.w(TAG, "setSelection [" + start + " " + end + "]"); 403755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org int textLength = mEditable.length(); 4049085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (start < 0 || end < 0 || start > textLength || end > textLength) return true; 4059155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org super.setSelection(start, end); 4069155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org updateSelectionIfRequired(); 4079155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org return mImeAdapter.setEditableSelectionOffsets(start, end); 4089155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org } 4099155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org 4100ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org /** 4110ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org * Informs the InputMethodManager and InputMethodSession (i.e. the IME) that the text 4120ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org * state is no longer what the IME has and that it needs to be updated. 4130ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org */ 414eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org void restartInput() { 415eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org if (DEBUG) Log.w(TAG, "restartInput"); 416eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org getInputMethodManagerWrapper().restartInput(mInternalView); 417eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org mNumNestedBatchEdits = 0; 418eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org } 419eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org 420eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org /** 4219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * @see BaseInputConnection#setComposingRegion(int, int) 4229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org */ 42330ce411529579186181838984710b0b0980857aaricow@chromium.org @Override 4240ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org public boolean setComposingRegion(int start, int end) { 4250ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org if (DEBUG) Log.w(TAG, "setComposingRegion [" + start + " " + end + "]"); 4269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int textLength = mEditable.length(); 427e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org int a = Math.min(start, end); 4289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int b = Math.max(start, end); 429755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org if (a < 0) a = 0; 4309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (b < 0) b = 0; 4319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (a > textLength) a = textLength; 432755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org if (b > textLength) b = textLength; 4339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 4349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (a == b) { 435755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org removeComposingSpans(mEditable); 436755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org } else { 437755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org super.setComposingRegion(a, b); 438755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org } 4399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org updateSelectionIfRequired(); 440755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org return mImeAdapter.setComposingRegion(a, b); 4419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 4429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 4439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org boolean isActive() { 4449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return getInputMethodManagerWrapper().isActive(mInternalView); 445750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org } 4469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 447750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org private InputMethodManagerWrapper getInputMethodManagerWrapper() { 448750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org return mImeAdapter.getInputMethodManagerWrapper(); 4493e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org } 4509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 4513e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org /** 4529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * This method works around the issue crbug.com/373934 where Blink does not cancel 453c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org * the composition when we send a commit with the empty text. 4549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * 4559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * TODO(aurimas) Remove this once crbug.com/373934 is fixed. 4569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * 457c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org * @param text Text that software keyboard requested to commit. 458ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org * @return Whether the workaround was performed. 4599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org */ 460c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org private boolean maybePerformEmptyCompositionWorkaround(CharSequence text) { 461c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org int selectionStart = Selection.getSelectionStart(mEditable); 4629d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com int selectionEnd = Selection.getSelectionEnd(mEditable); 4639d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com int compositionStart = getComposingSpanStart(mEditable); 4647a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org int compositionEnd = getComposingSpanEnd(mEditable); 4659d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com if (TextUtils.isEmpty(text) && (selectionStart == selectionEnd) 4669d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com && compositionStart != INVALID_COMPOSITION 4679d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com && compositionEnd != INVALID_COMPOSITION) { 468750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org beginBatchEdit(); 4699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org finishComposingText(); 470c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org int selection = Selection.getSelectionStart(mEditable); 471750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org deleteSurroundingText(selection - compositionStart, selection - compositionEnd); 472c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org endBatchEdit(); 473750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org return true; 474750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org } 4759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return false; 47683e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org } 477750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org 478750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org @VisibleForTesting 479750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org static class ImeState { 480750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org public final String text; 481ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org public final int selectionStart; 482c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org public final int selectionEnd; 4833e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org public final int compositionStart; 4843e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org public final int compositionEnd; 485ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 486ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org public ImeState(String text, int selectionStart, int selectionEnd, 487c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org int compositionStart, int compositionEnd) { 488ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org this.text = text; 489c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org this.selectionStart = selectionStart; 490c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org this.selectionEnd = selectionEnd; 491c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org this.compositionStart = compositionStart; 492c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org this.compositionEnd = compositionEnd; 493750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org } 494ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org } 495003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org 496ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org @VisibleForTesting 4979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org ImeState getImeStateForTesting() { 4989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org String text = mEditable.toString(); 4999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int selectionStart = Selection.getSelectionStart(mEditable); 500ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org int selectionEnd = Selection.getSelectionEnd(mEditable); 5019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int compositionStart = getComposingSpanStart(mEditable); 5023e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org int compositionEnd = getComposingSpanEnd(mEditable); 5033e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org return new ImeState(text, selectionStart, selectionEnd, compositionStart, compositionEnd); 5043e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org } 5059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} 5063e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org