115a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root/* 215a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Copyright (C) 2008 The Android Open Source Project 315a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * 415a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 515a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * you may not use this file except in compliance with the License. 615a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * You may obtain a copy of the License at 715a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * 815a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * http://www.apache.org/licenses/LICENSE-2.0 915a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * 1015a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Unless required by applicable law or agreed to in writing, software 1115a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * distributed under the License is distributed on an "AS IS" BASIS, 1215a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1315a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * See the License for the specific language governing permissions and 1415a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * limitations under the License. 1515a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root */ 1615a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.inputmethodservice; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.ExtractedText; 22a67a3cfc7c5db3b0a7710a75b57cd5360fce015asatokimport android.view.inputmethod.InputMethodManager; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.EditText; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*** 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Specialization of {@link EditText} for showing and interacting with the 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * extracted text in a full-screen input method. 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ExtractEditText extends EditText { 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private InputMethodService mIME; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mSettingExtractedText; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ExtractEditText(Context context) { 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context, null); 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ExtractEditText(Context context, AttributeSet attrs) { 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context, attrs, com.android.internal.R.attr.editTextStyle); 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public ExtractEditText(Context context, AttributeSet attrs, int defStyleAttr) { 42617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette this(context, attrs, defStyleAttr, 0); 43617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette } 44617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 45617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public ExtractEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 46617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette super(context, attrs, defStyleAttr, defStyleRes); 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void setIME(InputMethodService ime) { 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIME = ime; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Start making changes that will not be reported to the client. That 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is, {@link #onSelectionChanged(int, int)} will not result in sending 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the new selection to the client 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void startInternalChanges() { 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSettingExtractedText += 1; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Finish making changes that will not be reported to the client. That 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is, {@link #onSelectionChanged(int, int)} will not result in sending 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the new selection to the client 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void finishInternalChanges() { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSettingExtractedText -= 1; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Implement just to keep track of when we are setting text from the 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * client (vs. seeing changes in ourself from the user). 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public void setExtractedText(ExtractedText text) { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSettingExtractedText++; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.setExtractedText(text); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSettingExtractedText--; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Report to the underlying text editor about selection changes. 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override protected void onSelectionChanged(int selStart, int selEnd) { 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSettingExtractedText == 0 && mIME != null && selStart >= 0 && selEnd >= 0) { 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIME.onExtractedSelectionChanged(selStart, selEnd); 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Redirect clicks to the IME for handling there. First allows any 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * on click handler to run, though. 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public boolean performClick() { 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!super.performClick() && mIME != null) { 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIME.onExtractedTextClicked(); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public boolean onTextContextMenuItem(int id) { 106459ac63adae54bafff2391f1f60c607f5deece4aGilles Debunne if (mIME != null && mIME.onExtractTextContextMenuItem(id)) { 10714568c3f76cc4d3ad75dfd0206a3dc2130135c58Gilles Debunne // Mode was started on Extracted, needs to be stopped here. 10814568c3f76cc4d3ad75dfd0206a3dc2130135c58Gilles Debunne // Cut and paste will change the text, which stops selection mode. 10914568c3f76cc4d3ad75dfd0206a3dc2130135c58Gilles Debunne if (id == android.R.id.copy) stopSelectionActionMode(); 110459ac63adae54bafff2391f1f60c607f5deece4aGilles Debunne return true; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.onTextContextMenuItem(id); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We are always considered to be an input method target. 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 118e67b58a347109b444070a34e86e81ce119f266b3Gilles Debunne @Override 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isInputMethodTarget() { 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return true if the edit text is currently showing a scroll bar. 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean hasVerticalScrollBar() { 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return computeVerticalScrollRange() > computeVerticalScrollExtent(); 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Pretend like the window this view is in always has focus, so its 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * highlight and cursor will be displayed. 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public boolean hasWindowFocus() { 135e67b58a347109b444070a34e86e81ce119f266b3Gilles Debunne return this.isEnabled(); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Pretend like this view always has focus, so its 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * highlight and cursor will be displayed. 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public boolean isFocused() { 143e67b58a347109b444070a34e86e81ce119f266b3Gilles Debunne return this.isEnabled(); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Pretend like this view always has focus, so its 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * highlight and cursor will be displayed. 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public boolean hasFocus() { 151e67b58a347109b444070a34e86e81ce119f266b3Gilles Debunne return this.isEnabled(); 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 153a67a3cfc7c5db3b0a7710a75b57cd5360fce015asatok 154a67a3cfc7c5db3b0a7710a75b57cd5360fce015asatok /** 155a67a3cfc7c5db3b0a7710a75b57cd5360fce015asatok * @hide 156a67a3cfc7c5db3b0a7710a75b57cd5360fce015asatok */ 157a67a3cfc7c5db3b0a7710a75b57cd5360fce015asatok @Override protected void viewClicked(InputMethodManager imm) { 158a67a3cfc7c5db3b0a7710a75b57cd5360fce015asatok // As an instance of this class is supposed to be owned by IMS, 159a67a3cfc7c5db3b0a7710a75b57cd5360fce015asatok // and it has a reference to the IMS (the current IME), 160a67a3cfc7c5db3b0a7710a75b57cd5360fce015asatok // we just need to call back its onViewClicked() here. 161a67a3cfc7c5db3b0a7710a75b57cd5360fce015asatok // It should be good to avoid unnecessary IPCs by doing this as well. 162a67a3cfc7c5db3b0a7710a75b57cd5360fce015asatok if (mIME != null) { 163a67a3cfc7c5db3b0a7710a75b57cd5360fce015asatok mIME.onViewClicked(false); 164a67a3cfc7c5db3b0a7710a75b57cd5360fce015asatok } 165a67a3cfc7c5db3b0a7710a75b57cd5360fce015asatok } 16639ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne 16739ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne /** 168e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne * {@inheritDoc} 16939ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne * @hide 17039ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne */ 17139ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne @Override 17239ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne protected void deleteText_internal(int start, int end) { 173e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne // Do not call the super method. 174e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne // This will change the source TextView instead, which will update the ExtractTextView. 17539ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne mIME.onExtractedDeleteText(start, end); 17639ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne } 17739ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne 17839ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne /** 179e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne * {@inheritDoc} 18039ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne * @hide 18139ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne */ 18239ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne @Override 18339ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne protected void replaceText_internal(int start, int end, CharSequence text) { 184e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne // Do not call the super method. 185e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne // This will change the source TextView instead, which will update the ExtractTextView. 18639ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne mIME.onExtractedReplaceText(start, end, text); 18739ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne } 18839ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne 189e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne /** 190e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne * {@inheritDoc} 191e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne * @hide 192e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne */ 193e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne @Override 194e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne protected void setSpan_internal(Object span, int start, int end, int flags) { 195e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne // Do not call the super method. 196e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne // This will change the source TextView instead, which will update the ExtractTextView. 197e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne mIME.onExtractedSetSpan(span, start, end, flags); 198e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne } 199e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne 200e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne /** 201e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne * {@inheritDoc} 202e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne * @hide 203e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne */ 204e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne @Override 205e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne protected void setCursorPosition_internal(int start, int end) { 206e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne // Do not call the super method. 207e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne // This will change the source TextView instead, which will update the ExtractTextView. 208e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne mIME.onExtractedSelectionChanged(start, end); 209e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 211