BaseInputConnection.java revision 1127895fd42111f95fdc5049141c512e60198292
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * License for the specific language governing permissions and limitations under 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.view.inputmethod; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Editable; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.NoCopySpan; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Selection; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Spannable; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.SpannableStringBuilder; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Spanned; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.method.MetaKeyKeyListener; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.LogPrinter; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyCharacterMap; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewRoot; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass ComposingText implements NoCopySpan { 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Base class for implementors of the InputConnection interface, taking care 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of most of the common behavior for providing a connection to an Editable. 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Implementors of this class will want to be sure to implement 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getEditable} to provide access to their own editable object. 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class BaseInputConnection implements InputConnection { 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean DEBUG = false; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "BaseInputConnection"; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final Object COMPOSING = new ComposingText(); 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final InputMethodManager mIMM; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View mTargetView; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean mDummyMode; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Object[] mDefaultComposingSpans; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Editable mEditable; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KeyCharacterMap mKeyCharacterMap; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 621bf5e22da72b477c8b7a45ed85a4dba94be39db5Dianne Hackborn BaseInputConnection(InputMethodManager mgr, boolean fullEditor) { 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIMM = mgr; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTargetView = null; 651bf5e22da72b477c8b7a45ed85a4dba94be39db5Dianne Hackborn mDummyMode = !fullEditor; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 681bf5e22da72b477c8b7a45ed85a4dba94be39db5Dianne Hackborn public BaseInputConnection(View targetView, boolean fullEditor) { 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIMM = (InputMethodManager)targetView.getContext().getSystemService( 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Context.INPUT_METHOD_SERVICE); 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTargetView = targetView; 721bf5e22da72b477c8b7a45ed85a4dba94be39db5Dianne Hackborn mDummyMode = !fullEditor; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final void removeComposingSpans(Spannable text) { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.removeSpan(COMPOSING); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] sps = text.getSpans(0, text.length(), Object.class); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sps != null) { 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=sps.length-1; i>=0; i--) { 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object o = sps[i]; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((text.getSpanFlags(o)&Spanned.SPAN_COMPOSING) != 0) { 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.removeSpan(o); 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void setComposingSpans(Spannable text) { 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Object[] sps = text.getSpans(0, text.length(), Object.class); 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sps != null) { 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=sps.length-1; i>=0; i--) { 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Object o = sps[i]; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (o == COMPOSING) { 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.removeSpan(o); 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int fl = text.getSpanFlags(o); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((fl&(Spanned.SPAN_COMPOSING|Spanned.SPAN_POINT_MARK_MASK)) 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != (Spanned.SPAN_COMPOSING|Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)) { 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.setSpan(o, text.getSpanStart(o), text.getSpanEnd(o), 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (fl&Spanned.SPAN_POINT_MARK_MASK) 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | Spanned.SPAN_COMPOSING 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.setSpan(COMPOSING, 0, text.length(), 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getComposingSpanStart(Spannable text) { 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return text.getSpanStart(COMPOSING); 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getComposingSpanEnd(Spannable text) { 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return text.getSpanEnd(COMPOSING); 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the target of edit operations. The default implementation 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * returns its own fake editable that is just used for composing text; 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * subclasses that are real text editors should override this and 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * supply their own. 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Editable getEditable() { 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEditable == null) { 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEditable = Editable.Factory.getInstance().newEditable(""); 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Selection.setSelection(mEditable, 0); 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mEditable; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Default implementation does nothing. 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean beginBatchEdit() { 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Default implementation does nothing. 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean endBatchEdit() { 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Default implementation uses 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link MetaKeyKeyListener#clearMetaKeyState(long, int) 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * MetaKeyKeyListener.clearMetaKeyState(long, int)} to clear the state. 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean clearMetaKeyStates(int states) { 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Editable content = getEditable(); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content == null) return false; 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MetaKeyKeyListener.clearMetaKeyState(content, states); 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Default implementation does nothing. 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean commitCompletion(CompletionInfo text) { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Default implementation replaces any existing composing text with 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the given text. In addition, only if dummy mode, a key event is 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sent for the new text and the current editable buffer cleared. 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean commitText(CharSequence text, int newCursorPosition) { 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) Log.v(TAG, "commitText " + text); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project replaceText(text, newCursorPosition, false); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendCurrentText(); 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The default implementation performs the deletion around the current 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * selection position of the editable text. 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean deleteSurroundingText(int leftLength, int rightLength) { 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) Log.v(TAG, "deleteSurroundingText " + leftLength 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " / " + rightLength); 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Editable content = getEditable(); 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content == null) return false; 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project beginBatchEdit(); 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int a = Selection.getSelectionStart(content); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int b = Selection.getSelectionEnd(content); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (a > b) { 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int tmp = a; 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a = b; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b = tmp; 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ignore the composing text. 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ca = getComposingSpanStart(content); 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int cb = getComposingSpanEnd(content); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cb < ca) { 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int tmp = ca; 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ca = cb; 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cb = tmp; 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ca != -1 && cb != -1) { 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ca < a) a = ca; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cb > b) b = cb; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int deleted = 0; 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (leftLength > 0) { 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = a - leftLength; 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start < 0) start = 0; 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.delete(start, a); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project deleted = a - start; 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rightLength > 0) { 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b = b - deleted; 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = b + rightLength; 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end > content.length()) end = content.length(); 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.delete(b, end); 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project endBatchEdit(); 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The default implementation removes the composing state from the 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * current editable text. In addition, only if dummy mode, a key event is 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sent for the new text and the current editable buffer cleared. 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean finishComposingText() { 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) Log.v(TAG, "finishComposingText"); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Editable content = getEditable(); 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content != null) { 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project beginBatchEdit(); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeComposingSpans(content); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project endBatchEdit(); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendCurrentText(); 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The default implementation uses TextUtils.getCapsMode to get the 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * cursor caps mode for the current selection position in the editable 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * text, unless in dummy mode in which case 0 is always returned. 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getCursorCapsMode(int reqModes) { 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDummyMode) return 0; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Editable content = getEditable(); 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content == null) return 0; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int a = Selection.getSelectionStart(content); 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int b = Selection.getSelectionEnd(content); 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (a > b) { 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int tmp = a; 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a = b; 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b = tmp; 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return TextUtils.getCapsMode(content, a, reqModes); 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The default implementation always returns null. 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) { 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The default implementation returns the given amount of text from the 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * current cursor position in the buffer. 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence getTextBeforeCursor(int length, int flags) { 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Editable content = getEditable(); 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content == null) return null; 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int a = Selection.getSelectionStart(content); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int b = Selection.getSelectionEnd(content); 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (a > b) { 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int tmp = a; 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a = b; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b = tmp; 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 300a465a170ce5d7155580fd308d1e50092365117e4Dianne Hackborn if (a <= 0) { 301a465a170ce5d7155580fd308d1e50092365117e4Dianne Hackborn return ""; 302a465a170ce5d7155580fd308d1e50092365117e4Dianne Hackborn } 303a465a170ce5d7155580fd308d1e50092365117e4Dianne Hackborn 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (length > a) { 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project length = a; 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags&GET_TEXT_WITH_STYLES) != 0) { 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return content.subSequence(a - length, a); 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return TextUtils.substring(content, a - length, a); 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The default implementation returns the given amount of text from the 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * current cursor position in the buffer. 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence getTextAfterCursor(int length, int flags) { 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Editable content = getEditable(); 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content == null) return null; 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int a = Selection.getSelectionStart(content); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int b = Selection.getSelectionEnd(content); 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (a > b) { 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int tmp = a; 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a = b; 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b = tmp; 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3311127895fd42111f95fdc5049141c512e60198292Eric Fischer // Guard against the case where the cursor has not been positioned yet. 3321127895fd42111f95fdc5049141c512e60198292Eric Fischer if (b < 0) { 3331127895fd42111f95fdc5049141c512e60198292Eric Fischer b = 0; 3341127895fd42111f95fdc5049141c512e60198292Eric Fischer } 3351127895fd42111f95fdc5049141c512e60198292Eric Fischer 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (b + length > content.length()) { 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project length = content.length() - b; 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags&GET_TEXT_WITH_STYLES) != 0) { 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return content.subSequence(b, b + length); 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return TextUtils.substring(content, b, b + length); 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 34886d56cca9ce23b0f4814418d7c71ec11ea9fd278Dianne Hackborn * The default implementation turns this into the enter key. 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean performEditorAction(int actionCode) { 35186d56cca9ce23b0f4814418d7c71ec11ea9fd278Dianne Hackborn long eventTime = SystemClock.uptimeMillis(); 35286d56cca9ce23b0f4814418d7c71ec11ea9fd278Dianne Hackborn sendKeyEvent(new KeyEvent(eventTime, eventTime, 35386d56cca9ce23b0f4814418d7c71ec11ea9fd278Dianne Hackborn KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0, 35486d56cca9ce23b0f4814418d7c71ec11ea9fd278Dianne Hackborn KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE 35586d56cca9ce23b0f4814418d7c71ec11ea9fd278Dianne Hackborn | KeyEvent.FLAG_EDITOR_ACTION)); 35686d56cca9ce23b0f4814418d7c71ec11ea9fd278Dianne Hackborn sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime, 35786d56cca9ce23b0f4814418d7c71ec11ea9fd278Dianne Hackborn KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0, 35886d56cca9ce23b0f4814418d7c71ec11ea9fd278Dianne Hackborn KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE 35986d56cca9ce23b0f4814418d7c71ec11ea9fd278Dianne Hackborn | KeyEvent.FLAG_EDITOR_ACTION)); 36086d56cca9ce23b0f4814418d7c71ec11ea9fd278Dianne Hackborn return true; 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The default implementation does nothing. 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean performContextMenuAction(int id) { 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The default implementation does nothing. 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean performPrivateCommand(String action, Bundle data) { 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The default implementation places the given text into the editable, 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * replacing any existing composing text. The new text is marked as 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in a composing state with the composing style. 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean setComposingText(CharSequence text, int newCursorPosition) { 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) Log.v(TAG, "setComposingText " + text); 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project replaceText(text, newCursorPosition, true); 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The default implementation changes the selection position in the 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * current editable text. 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean setSelection(int start, int end) { 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) Log.v(TAG, "setSelection " + start + ", " + end); 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Editable content = getEditable(); 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content == null) return false; 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = content.length(); 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start > len || end > len) { 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the given selection is out of bounds, just ignore it. 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Most likely the text was changed out from under the IME, 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the the IME is going to have to update all of its state 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // anyway. 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 404b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (start == end && MetaKeyKeyListener.getMetaState(content, 405b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project MetaKeyKeyListener.META_SELECTING) != 0) { 406b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // If we are in selection mode, then we want to extend the 407b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // selection instead of replacing it. 408b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project Selection.extendSelection(content, start); 409b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } else { 410b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project Selection.setSelection(content, start, end); 411b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Provides standard implementation for sending a key event to the window 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * attached to the input connection's view. 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean sendKeyEvent(KeyEvent event) { 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mIMM.mH) { 4211bf5e22da72b477c8b7a45ed85a4dba94be39db5Dianne Hackborn Handler h = mTargetView != null ? mTargetView.getHandler() : null; 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h == null) { 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIMM.mServedView != null) { 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h = mIMM.mServedView.getHandler(); 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h != null) { 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME, 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event)); 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Updates InputMethodManager with the current fullscreen mode. 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean reportFullscreenMode(boolean enabled) { 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIMM.setFullscreenMode(enabled); 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendCurrentText() { 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mDummyMode) { 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Editable content = getEditable(); 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content != null) { 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int N = content.length(); 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (N == 0) { 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (N == 1) { 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If it's 1 character, we have a chance of being 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // able to generate normal key events... 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mKeyCharacterMap == null) { 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mKeyCharacterMap = KeyCharacterMap.load( 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KeyCharacterMap.BUILT_IN_KEYBOARD); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] chars = new char[1]; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.getChars(0, 1, chars, 0); 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KeyEvent[] events = mKeyCharacterMap.getEvents(chars); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (events != null) { 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<events.length; i++) { 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) Log.v(TAG, "Sending: " + events[i]); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendKeyEvent(events[i]); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.clear(); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Otherwise, revert to the special key event containing 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the actual characters. 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KeyEvent event = new KeyEvent(SystemClock.uptimeMillis(), 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.toString(), KeyCharacterMap.BUILT_IN_KEYBOARD, 0); 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendKeyEvent(event); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.clear(); 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void replaceText(CharSequence text, int newCursorPosition, 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean composing) { 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Editable content = getEditable(); 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content == null) { 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project beginBatchEdit(); 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // delete composing text set previously. 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int a = getComposingSpanStart(content); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int b = getComposingSpanEnd(content); 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) Log.v(TAG, "Composing span: " + a + " to " + b); 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (b < a) { 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int tmp = a; 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a = b; 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b = tmp; 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (a != -1 && b != -1) { 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeComposingSpans(content); 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a = Selection.getSelectionStart(content); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b = Selection.getSelectionEnd(content); 509a465a170ce5d7155580fd308d1e50092365117e4Dianne Hackborn if (a < 0) a = 0; 510a465a170ce5d7155580fd308d1e50092365117e4Dianne Hackborn if (b < 0) b = 0; 511a465a170ce5d7155580fd308d1e50092365117e4Dianne Hackborn if (b < a) { 512a465a170ce5d7155580fd308d1e50092365117e4Dianne Hackborn int tmp = a; 513a465a170ce5d7155580fd308d1e50092365117e4Dianne Hackborn a = b; 514a465a170ce5d7155580fd308d1e50092365117e4Dianne Hackborn b = tmp; 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (composing) { 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable sp = null; 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!(text instanceof Spannable)) { 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp = new SpannableStringBuilder(text); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text = sp; 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDefaultComposingSpans == null) { 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Context context; 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mTargetView != null) { 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context = mTargetView.getContext(); 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mIMM.mServedView != null) { 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context = mIMM.mServedView.getContext(); 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context = null; 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (context != null) { 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedArray ta = context.getTheme() 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .obtainStyledAttributes(new int[] { 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.attr.candidatesTextStyleSpans 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence style = ta.getText(0); 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ta.recycle(); 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style != null && style instanceof Spanned) { 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultComposingSpans = ((Spanned)style).getSpans( 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 0, style.length(), Object.class); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDefaultComposingSpans != null) { 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mDefaultComposingSpans.length; ++i) { 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp.setSpan(mDefaultComposingSpans[i], 0, sp.length(), 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp = (Spannable)text; 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setComposingSpans(sp); 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) Log.v(TAG, "Replacing from " + a + " to " + b + " with \"" 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + text + "\", composing=" + composing 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", type=" + text.getClass().getCanonicalName()); 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) { 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LogPrinter lp = new LogPrinter(Log.VERBOSE, TAG); 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.println("Current text:"); 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.dumpSpans(content, lp, " "); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.println("Composing text:"); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.dumpSpans(text, lp, " "); 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Position the cursor appropriately, so that after replacing the 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // desired range of text it will be located in the correct spot. 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This allows us to deal with filters performing edits on the text 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we are providing here. 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newCursorPosition > 0) { 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newCursorPosition += b - 1; 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newCursorPosition += a; 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newCursorPosition < 0) newCursorPosition = 0; 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newCursorPosition > content.length()) 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newCursorPosition = content.length(); 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Selection.setSelection(content, newCursorPosition); 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.replace(a, b, text); 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) { 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LogPrinter lp = new LogPrinter(Log.VERBOSE, TAG); 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.println("Final text:"); 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.dumpSpans(content, lp, " "); 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project endBatchEdit(); 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 594