InputMethodService.java revision 6e2bee75cea415621165698fdd9ce857bbb8872e
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007-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.inputmethodservice;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guyimport static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackbornimport android.app.ActivityManager;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.Dialog;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Configuration;
26d922ae01ca99a2b6d39a9393f86776a1d10ebd14Dianne Hackbornimport android.content.res.Resources;
27105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.content.res.TypedArray;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect;
29fbf097732137a32930d151f7ba6816a5b870c32aJeff Brownimport android.graphics.Region;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
324df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Projectimport android.os.ResultReceiver;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.InputType;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Layout;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Spannable;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.method.MovementMethod;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.PrintWriterPrinter;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Printer;
426b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownimport android.view.KeyCharacterMap;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MotionEvent;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewTreeObserver;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Window;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager;
51105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.view.animation.AnimationUtils;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.CompletionInfo;
538cbb4c6e30cff706a243599634aeb8fd9a818d92Gilles Debunneimport android.view.inputmethod.EditorInfo;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.ExtractedText;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.ExtractedTextRequest;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputBinding;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputConnection;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethod;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethodManager;
60ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.view.inputmethod.InputMethodSubtype;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.Button;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.FrameLayout;
63105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.widget.LinearLayout;
64105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * InputMethodService provides a standard implementation of an InputMethod,
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * which final implementations can derive from and customize.  See the
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * base class {@link AbstractInputMethodService} and the {@link InputMethod}
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * interface for more information on the basics of writing input methods.
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>In addition to the normal Service lifecycle methods, this class
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * introduces some new specific callbacks that most subclasses will want
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to make use of:</p>
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> {@link #onInitializeInterface()} for user-interface initialization,
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in particular to deal with configuration changes while the service is
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * running.
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> {@link #onBindInput} to find out about switching to a new client.
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> {@link #onStartInput} to deal with an input session starting with
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the client.
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> {@link #onCreateInputView()}, {@link #onCreateCandidatesView()},
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and {@link #onCreateExtractTextView()} for non-demand generation of the UI.
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> {@link #onStartInputView(EditorInfo, boolean)} to deal with input
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * starting within the input area of the IME.
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>An input method has significant discretion in how it goes about its
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * work: the {@link android.inputmethodservice.InputMethodService} provides
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a basic framework for standard UI elements (input view, candidates view,
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and running in fullscreen mode), but it is up to a particular implementor
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to decide how to use them.  For example, one input method could implement
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * an input area with a keyboard, another could allow the user to draw text,
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * while a third could have no input area (and thus not be visible to the
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * user) but instead listen to audio and perform text to speech conversion.</p>
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>In the implementation provided here, all of these elements are placed
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * together in a single window managed by the InputMethodService.  It will
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * execute callbacks as it needs information about them, and provides APIs for
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * programmatic control over them.  They layout of these elements is explicitly
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * defined:</p>
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>The soft input view, if available, is placed at the bottom of the
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * screen.
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>The candidates view, if currently shown, is placed above the soft
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * input view.
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>If not running fullscreen, the application is moved or resized to be
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * above these views; if running fullscreen, the window will completely cover
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the application and its top part will contain the extract text of what is
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * currently being edited by the application.
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="SoftInputView"></a>
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Soft Input View</h3>
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Central to most input methods is the soft input view.  This is where most
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * user interaction occurs: pressing on soft keys, drawing characters, or
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * however else your input method wants to generate text.  Most implementations
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will simply have their own view doing all of this work, and return a new
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * instance of it when {@link #onCreateInputView()} is called.  At that point,
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as long as the input view is visible, you will see user interaction in
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that view and can call back on the InputMethodService to interact with the
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * application as appropriate.</p>
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>There are some situations where you want to decide whether or not your
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * soft input view should be shown to the user.  This is done by implementing
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the {@link #onEvaluateInputViewShown()} to return true or false based on
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * whether it should be shown in the current environment.  If any of your
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * state has changed that may impact this, call
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #updateInputViewShown()} to have it re-evaluated.  The default
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * implementation always shows the input view unless there is a hard
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * keyboard available, which is the appropriate behavior for most input
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * methods.</p>
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="CandidatesView"></a>
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Candidates View</h3>
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Often while the user is generating raw text, an input method wants to
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provide them with a list of possible interpretations of that text that can
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be selected for use.  This is accomplished with the candidates view, and
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * like the soft input view you implement {@link #onCreateCandidatesView()}
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to instantiate your own view implementing your candidates UI.</p>
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Management of the candidates view is a little different than the input
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * view, because the candidates view tends to be more transient, being shown
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * only when there are possible candidates for the current text being entered
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by the user.  To control whether the candidates view is shown, you use
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #setCandidatesViewShown(boolean)}.  Note that because the candidate
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * view tends to be shown and hidden a lot, it does not impact the application
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * UI in the same way as the soft input view: it will never cause application
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * windows to resize, only cause them to be panned if needed for the user to
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * see the current focus.</p>
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="FullscreenMode"></a>
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Fullscreen Mode</h3>
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Sometimes your input method UI is too large to integrate with the
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * application UI, so you just want to take over the screen.  This is
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * accomplished by switching to full-screen mode, causing the input method
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * window to fill the entire screen and add its own "extracted text" editor
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * showing the user the text that is being typed.  Unlike the other UI elements,
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * there is a standard implementation for the extract editor that you should
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not need to change.  The editor is placed at the top of the IME, above the
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * input and candidates views.</p>
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Similar to the input view, you control whether the IME is running in
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * fullscreen mode by implementing {@link #onEvaluateFullscreenMode()}
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to return true or false based on
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * whether it should be fullscreen in the current environment.  If any of your
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * state has changed that may impact this, call
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #updateFullscreenMode()} to have it re-evaluated.  The default
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * implementation selects fullscreen mode when the screen is in a landscape
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * orientation, which is appropriate behavior for most input methods that have
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a significant input area.</p>
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>When in fullscreen mode, you have some special requirements because the
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * user can not see the application UI.  In particular, you should implement
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #onDisplayCompletions(CompletionInfo[])} to show completions
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * generated by your application, typically in your candidates view like you
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * would normally show candidates.
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="GeneratingText"></a>
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Generating Text</h3>
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The key part of an IME is of course generating text for the application.
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is done through calls to the
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.inputmethod.InputConnection} interface to the
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * application, which can be retrieved from {@link #getCurrentInputConnection()}.
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This interface allows you to generate raw key events or, if the target
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * supports it, directly edit in strings of candidates and committed text.</p>
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Information about what the target is expected and supports can be found
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * through the {@link android.view.inputmethod.EditorInfo} class, which is
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * retrieved with {@link #getCurrentInputEditorInfo()} method.  The most
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * important part of this is {@link android.view.inputmethod.EditorInfo#inputType
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * EditorInfo.inputType}; in particular, if this is
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.inputmethod.EditorInfo#TYPE_NULL EditorInfo.TYPE_NULL},
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * then the target does not support complex edits and you need to only deliver
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * raw key events to it.  An input method will also want to look at other
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * values here, to for example detect password mode, auto complete text views,
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * phone number entry, etc.</p>
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>When the user switches between input targets, you will receive calls to
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #onFinishInput()} and {@link #onStartInput(EditorInfo, boolean)}.
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You can use these to reset and initialize your input state for the current
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * target.  For example, you will often want to clear any input state, and
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * update a soft keyboard to be appropriate for the new inputType.</p>
215105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project *
216105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @attr ref android.R.styleable#InputMethodService_imeFullscreenBackground
217105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @attr ref android.R.styleable#InputMethodService_imeExtractEnterAnimation
218105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @attr ref android.R.styleable#InputMethodService_imeExtractExitAnimation
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class InputMethodService extends AbstractInputMethodService {
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final String TAG = "InputMethodService";
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG = false;
223857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
224857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    /**
225857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     * The back button will close the input window.
226857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     */
227857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public static final int BACK_DISPOSITION_DEFAULT = 0;  // based on window
228857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
229857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    /**
230857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     * This input method will not consume the back key.
231857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     */
232857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public static final int BACK_DISPOSITION_WILL_NOT_DISMISS = 1; // back
233857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
234857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    /**
235857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     * This input method will consume the back key.
236857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     */
237857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public static final int BACK_DISPOSITION_WILL_DISMISS = 2; // down
238857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
239857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    /**
240857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     * @hide
241857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     * The IME is active.  It may or may not be visible.
242857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     */
243857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public static final int IME_ACTIVE = 0x1;
244857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
245857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    /**
246857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     * @hide
247857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     * The IME is visible.
248857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     */
249857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public static final int IME_VISIBLE = 0x2;
250857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    InputMethodManager mImm;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
253d922ae01ca99a2b6d39a9393f86776a1d10ebd14Dianne Hackborn    int mTheme = 0;
254836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn    boolean mHardwareAccelerated = false;
255105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LayoutInflater mInflater;
257105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    TypedArray mThemeAttrs;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    View mRootView;
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SoftInputWindow mWindow;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mInitialized;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mWindowCreated;
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mWindowAdded;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mWindowVisible;
264105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    boolean mWindowWasVisible;
265105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    boolean mInShowWindow;
266105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    ViewGroup mFullscreenArea;
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FrameLayout mExtractFrame;
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FrameLayout mCandidatesFrame;
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FrameLayout mInputFrame;
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IBinder mToken;
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    InputBinding mInputBinding;
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    InputConnection mInputConnection;
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mInputStarted;
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mInputViewStarted;
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mCandidatesViewStarted;
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    InputConnection mStartedInputConnection;
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    EditorInfo mInputEditorInfo;
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mShowInputFlags;
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowInputRequested;
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mLastShowInputRequested;
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mCandidatesVisibility;
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    CompletionInfo[] mCurCompletions;
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowInputForced;
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mFullscreenApplied;
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mIsFullscreen;
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    View mExtractView;
292105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    boolean mExtractViewHidden;
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ExtractEditText mExtractEditText;
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ViewGroup mExtractAccessories;
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Button mExtractAction;
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ExtractedText mExtractedText;
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mExtractedToken;
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    View mInputView;
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mIsInputViewShown;
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mStatusIcon;
303857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    int mBackDisposition;
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Insets mTmpInsets = new Insets();
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final int[] mTmpLocation = new int[2];
307ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer =
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            new ViewTreeObserver.OnComputeInternalInsetsListener() {
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
311105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (isExtractViewShown()) {
312105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                // In true fullscreen mode, we just say the window isn't covering
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // any content so we don't impact whatever is behind.
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                View decor = getWindow().getWindow().getDecorView();
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.contentInsets.top = info.visibleInsets.top
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        = decor.getHeight();
317fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown                info.touchableRegion.setEmpty();
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                onComputeInsets(mTmpInsets);
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.contentInsets.top = mTmpInsets.contentTopInsets;
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.visibleInsets.top = mTmpInsets.visibleTopInsets;
323fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown                info.touchableRegion.set(mTmpInsets.touchableRegion);
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.setTouchableInsets(mTmpInsets.touchableInsets);
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final View.OnClickListener mActionClickListener = new View.OnClickListener() {
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onClick(View v) {
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final EditorInfo ei = getCurrentInputEditorInfo();
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final InputConnection ic = getCurrentInputConnection();
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ei != null && ic != null) {
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (ei.actionId != 0) {
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ic.performEditorAction(ei.actionId);
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if ((ei.imeOptions&EditorInfo.IME_MASK_ACTION)
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        != EditorInfo.IME_ACTION_NONE) {
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ic.performEditorAction(ei.imeOptions&EditorInfo.IME_MASK_ACTION);
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Concrete implementation of
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link AbstractInputMethodService.AbstractInputMethodImpl} that provides
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * all of the standard behavior for an input method.
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public class InputMethodImpl extends AbstractInputMethodImpl {
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Take care of attaching the given window token provided by the system.
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void attachToken(IBinder token) {
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mToken == null) {
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mToken = token;
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mWindow.setToken(token);
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Handle a new input binding, calling
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * {@link InputMethodService#onBindInput InputMethodService.onBindInput()}
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * when done.
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void bindInput(InputBinding binding) {
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputBinding = binding;
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputConnection = binding.getConnection();
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "bindInput(): binding=" + binding
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " ic=" + mInputConnection);
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputConnection ic = getCurrentInputConnection();
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ic != null) ic.reportFullscreenMode(mIsFullscreen);
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            initialize();
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onBindInput();
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Clear the current input binding.
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void unbindInput() {
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "unbindInput(): binding=" + mInputBinding
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " ic=" + mInputConnection);
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onUnbindInput();
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputStarted = false;
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputBinding = null;
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputConnection = null;
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void startInput(InputConnection ic, EditorInfo attribute) {
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "startInput(): editor=" + attribute);
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            doStartInput(ic, attribute, false);
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void restartInput(InputConnection ic, EditorInfo attribute) {
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "restartInput(): editor=" + attribute);
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            doStartInput(ic, attribute, true);
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Handle a request by the system to hide the soft input area.
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4014df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        public void hideSoftInput(int flags, ResultReceiver resultReceiver) {
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "hideSoftInput()");
4034df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            boolean wasVis = isInputViewShown();
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowInputFlags = 0;
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowInputRequested = false;
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowInputForced = false;
4072f913d951c481edccbefa4d321a76f28740b48d7satok            doHideWindow();
4084df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            if (resultReceiver != null) {
4094df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                resultReceiver.send(wasVis != isInputViewShown()
4104df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        ? InputMethodManager.RESULT_HIDDEN
4114df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        : (wasVis ? InputMethodManager.RESULT_UNCHANGED_SHOWN
4124df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null);
4134df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Handle a request by the system to show the soft input area.
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4194df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        public void showSoftInput(int flags, ResultReceiver resultReceiver) {
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "showSoftInput()");
4214df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            boolean wasVis = isInputViewShown();
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowInputFlags = 0;
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (onShowInputRequested(flags, false)) {
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                showWindow(true);
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
426865b97761cc58053f45a8b06b531d60d8e482c3asatok            // If user uses hard keyboard, IME button should always be shown.
427857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato            boolean showing = onEvaluateInputViewShown();
428857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato            mImm.setImeWindowStatus(mToken, IME_ACTIVE | (showing ? IME_VISIBLE : 0),
429857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato                    mBackDisposition);
4304df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            if (resultReceiver != null) {
4314df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                resultReceiver.send(wasVis != isInputViewShown()
4324df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        ? InputMethodManager.RESULT_SHOWN
4334df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        : (wasVis ? InputMethodManager.RESULT_UNCHANGED_SHOWN
4344df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null);
4354df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
437ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
438ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        public void changeInputMethodSubtype(InputMethodSubtype subtype) {
439ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            onCurrentInputMethodSubtypeChanged(subtype);
440ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
442ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Concrete implementation of
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link AbstractInputMethodService.AbstractInputMethodSessionImpl} that provides
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * all of the standard behavior for an input method session.
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public class InputMethodSessionImpl extends AbstractInputMethodSessionImpl {
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void finishInput() {
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!isEnabled()) {
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "finishInput() in " + this);
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            doFinishInput();
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Call {@link InputMethodService#onDisplayCompletions
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * InputMethodService.onDisplayCompletions()}.
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void displayCompletions(CompletionInfo[] completions) {
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!isEnabled()) {
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurCompletions = completions;
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onDisplayCompletions(completions);
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Call {@link InputMethodService#onUpdateExtractedText
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * InputMethodService.onUpdateExtractedText()}.
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void updateExtractedText(int token, ExtractedText text) {
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!isEnabled()) {
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onUpdateExtractedText(token, text);
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Call {@link InputMethodService#onUpdateSelection
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * InputMethodService.onUpdateSelection()}.
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void updateSelection(int oldSelStart, int oldSelEnd,
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int newSelStart, int newSelEnd,
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int candidatesStart, int candidatesEnd) {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!isEnabled()) {
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputMethodService.this.onUpdateSelection(oldSelStart, oldSelEnd,
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    newSelStart, newSelEnd, candidatesStart, candidatesEnd);
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
493863fcd62171e55bc9f2105d9fb5877df982454d8satok
494863fcd62171e55bc9f2105d9fb5877df982454d8satok        @Override
495863fcd62171e55bc9f2105d9fb5877df982454d8satok        public void viewClicked(boolean focusChanged) {
496863fcd62171e55bc9f2105d9fb5877df982454d8satok            if (!isEnabled()) {
497863fcd62171e55bc9f2105d9fb5877df982454d8satok                return;
498863fcd62171e55bc9f2105d9fb5877df982454d8satok            }
499863fcd62171e55bc9f2105d9fb5877df982454d8satok            InputMethodService.this.onViewClicked(focusChanged);
500863fcd62171e55bc9f2105d9fb5877df982454d8satok        }
501863fcd62171e55bc9f2105d9fb5877df982454d8satok
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Call {@link InputMethodService#onUpdateCursor
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * InputMethodService.onUpdateCursor()}.
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void updateCursor(Rect newCursor) {
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!isEnabled()) {
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputMethodService.this.onUpdateCursor(newCursor);
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Call {@link InputMethodService#onAppPrivateCommand
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * InputMethodService.onAppPrivateCommand()}.
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void appPrivateCommand(String action, Bundle data) {
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!isEnabled()) {
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputMethodService.this.onAppPrivateCommand(action, data);
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5234df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
5244df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        /**
5254df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project         *
5264df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project         */
5274df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        public void toggleSoftInput(int showFlags, int hideFlags) {
5284df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            InputMethodService.this.onToggleSoftInput(showFlags, hideFlags);
5294df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Information about where interesting parts of the input method UI appear.
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final class Insets {
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This is the top part of the UI that is the main content.  It is
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * used to determine the basic space needed, to resize/pan the
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * application behind.  It is assumed that this inset does not
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * change very much, since any change will cause a full resize/pan
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * of the application behind.  This value is relative to the top edge
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * of the input method window.
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int contentTopInsets;
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This is the top part of the UI that is visibly covering the
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * application behind it.  This provides finer-grained control over
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * visibility, allowing you to change it relatively frequently (such
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * as hiding or showing candidates) without disrupting the underlying
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * UI too much.  For example, this will never resize the application
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * UI, will only pan if needed to make the current focus visible, and
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * will not aggressively move the pan position when this changes unless
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * needed to make the focus visible.  This value is relative to the top edge
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * of the input method window.
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int visibleTopInsets;
558fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
559fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        /**
560fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * This is the region of the UI that is touchable.  It is used when
561fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * {@link #touchableInsets} is set to {@link #TOUCHABLE_INSETS_REGION}.
562fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * The region should be specified relative to the origin of the window frame.
563fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         */
564fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        public final Region touchableRegion = new Region();
565fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Option for {@link #touchableInsets}: the entire window frame
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * can be touched.
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int TOUCHABLE_INSETS_FRAME
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Option for {@link #touchableInsets}: the area inside of
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the content insets can be touched.
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int TOUCHABLE_INSETS_CONTENT
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Option for {@link #touchableInsets}: the area inside of
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the visible insets can be touched.
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int TOUCHABLE_INSETS_VISIBLE
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
586fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
587fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        /**
588fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * Option for {@link #touchableInsets}: the region specified by
589fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * {@link #touchableRegion} can be touched.
590fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         */
591fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        public static final int TOUCHABLE_INSETS_REGION
592fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown                = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
593fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Determine which area of the window is touchable by the user.  May
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * be one of: {@link #TOUCHABLE_INSETS_FRAME},
597fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * {@link #TOUCHABLE_INSETS_CONTENT}, {@link #TOUCHABLE_INSETS_VISIBLE},
598fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * or {@link #TOUCHABLE_INSETS_REGION}.
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int touchableInsets;
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
602865b97761cc58053f45a8b06b531d60d8e482c3asatok
603105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    /**
604105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * You can call this to customize the theme used by your IME's window.
605105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * This theme should typically be one that derives from
606105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * {@link android.R.style#Theme_InputMethod}, which is the default theme
607105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * you will get.  This must be set before {@link #onCreate}, so you
608105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * will typically call it in your constructor with the resource ID
609105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * of your custom theme.
610105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     */
611ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    @Override
612105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public void setTheme(int theme) {
613105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mWindow != null) {
614105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            throw new IllegalStateException("Must be called before onCreate()");
615105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
616105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mTheme = theme;
617105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
618865b97761cc58053f45a8b06b531d60d8e482c3asatok
619836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn    /**
620836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     * You can call this to try to enable hardware accelerated drawing for
621836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     * your IME. This must be set before {@link #onCreate}, so you
622836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     * will typically call it in your constructor.  It is not always possible
623836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     * to use hardware acclerated drawing in an IME (for example on low-end
624836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     * devices that do not have the resources to support this), so the call
625836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     * returns true if it succeeds otherwise false if you will need to draw
626836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     * in software.  You must be able to handle either case.
627836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     */
628836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn    public boolean enableHardwareAcceleration() {
629836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn        if (mWindow != null) {
630836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn            throw new IllegalStateException("Must be called before onCreate()");
631836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn        }
63298365d7663cbd82979a5700faf0050220b01084dJeff Brown        if (ActivityManager.isHighEndGfx()) {
633836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn            mHardwareAccelerated = true;
634836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn            return true;
635836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn        }
636836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn        return false;
637836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn    }
638836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override public void onCreate() {
640d922ae01ca99a2b6d39a9393f86776a1d10ebd14Dianne Hackborn        mTheme = Resources.selectSystemTheme(mTheme,
641d922ae01ca99a2b6d39a9393f86776a1d10ebd14Dianne Hackborn                getApplicationInfo().targetSdkVersion,
6426e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell                android.R.style.Theme_InputMethod,
64336a97e4030010298736928f9b391a390fea6941bAdam Powell                android.R.style.Theme_Holo_InputMethod,
6446e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell                android.R.style.Theme_DeviceDefault_InputMethod);
645105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        super.setTheme(mTheme);
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onCreate();
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInflater = (LayoutInflater)getSystemService(
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Context.LAYOUT_INFLATER_SERVICE);
65083fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        mWindow = new SoftInputWindow(this, mTheme, mDispatcherState);
651836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn        if (mHardwareAccelerated) {
652836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn            mWindow.getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
653836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn        }
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initViews();
655980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy        mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
657ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is a hook that subclasses can use to perform initialization of
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * their interface.  It is called for you prior to any of your UI objects
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * being created, both after the service is first created and after a
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * configuration change happens.
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onInitializeInterface() {
66534703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
667ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void initialize() {
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mInitialized) {
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInitialized = true;
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onInitializeInterface();
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
674ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void initViews() {
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInitialized = false;
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWindowCreated = false;
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowInputRequested = false;
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowInputForced = false;
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
681105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mThemeAttrs = obtainStyledAttributes(android.R.styleable.InputMethodService);
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRootView = mInflater.inflate(
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                com.android.internal.R.layout.input_method, null);
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWindow.setContentView(mRootView);
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
6866e2bee75cea415621165698fdd9ce857bbb8872eJeff Sharkey        if (Settings.Global.getInt(getContentResolver(),
6876e2bee75cea415621165698fdd9ce857bbb8872eJeff Sharkey                Settings.Global.FANCY_IME_ANIMATIONS, 0) != 0) {
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWindow.getWindow().setWindowAnimations(
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    com.android.internal.R.style.Animation_InputMethodFancy);
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
691105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mFullscreenArea = (ViewGroup)mRootView.findViewById(com.android.internal.R.id.fullscreenArea);
692105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mExtractViewHidden = false;
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractFrame = (FrameLayout)mRootView.findViewById(android.R.id.extractArea);
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractView = null;
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractEditText = null;
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractAccessories = null;
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractAction = null;
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFullscreenApplied = false;
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesFrame = (FrameLayout)mRootView.findViewById(android.R.id.candidatesArea);
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputFrame = (FrameLayout)mRootView.findViewById(android.R.id.inputArea);
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputView = null;
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsInputViewShown = false;
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractFrame.setVisibility(View.GONE);
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesVisibility = getCandidatesHiddenVisibility();
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesFrame.setVisibility(mCandidatesVisibility);
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputFrame.setVisibility(View.GONE);
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
710ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override public void onDestroy() {
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onDestroy();
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInsetsComputer);
715f17db9f5257011d5331d27a6da7d4e6fddde1e08satok        finishViews();
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mWindowAdded) {
717c0c8765719f5c8d0192aa266c27166bdd8c09a33satok            // Disable exit animation for the current IME window
718c0c8765719f5c8d0192aa266c27166bdd8c09a33satok            // to avoid the race condition between the exit and enter animations
719c0c8765719f5c8d0192aa266c27166bdd8c09a33satok            // when the current IME is being switched to another one.
720c0c8765719f5c8d0192aa266c27166bdd8c09a33satok            mWindow.getWindow().setWindowAnimations(0);
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWindow.dismiss();
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
724f17db9f5257011d5331d27a6da7d4e6fddde1e08satok
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Take care of handling configuration changes.  Subclasses of
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * InputMethodService generally don't need to deal directly with
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this on their own; the standard implementation here takes care of
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * regenerating the input method UI as a result of the configuration
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * change, so you can rely on your {@link #onCreateInputView} and
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * other methods being called as appropriate due to a configuration change.
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>When a configuration change does happen,
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #onInitializeInterface()} is guaranteed to be called the next
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * time prior to any of the other input or UI creation callbacks.  The
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * following will be called immediately depending if appropriate for current
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * state: {@link #onStartInput} if input is active, and
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #onCreateInputView} and {@link #onStartInputView} and related
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * appropriate functions if the UI is displayed.
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override public void onConfigurationChanged(Configuration newConfig) {
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onConfigurationChanged(newConfig);
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean visible = mWindowVisible;
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int showFlags = mShowInputFlags;
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean showingInput = mShowInputRequested;
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CompletionInfo[] completions = mCurCompletions;
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initViews();
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputViewStarted = false;
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesViewStarted = false;
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputStarted) {
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            doStartInput(getCurrentInputConnection(),
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    getCurrentInputEditorInfo(), true);
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (visible) {
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showingInput) {
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If we were last showing the soft keyboard, try to do so again.
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (onShowInputRequested(showFlags, true)) {
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    showWindow(true);
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (completions != null) {
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mCurCompletions = completions;
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        onDisplayCompletions(completions);
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
7652f913d951c481edccbefa4d321a76f28740b48d7satok                    doHideWindow();
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (mCandidatesVisibility == View.VISIBLE) {
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If the candidates are currently visible, make sure the
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // window is shown for them.
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                showWindow(false);
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Otherwise hide the window.
7732f913d951c481edccbefa4d321a76f28740b48d7satok                doHideWindow();
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
775865b97761cc58053f45a8b06b531d60d8e482c3asatok            // If user uses hard keyboard, IME button should always be shown.
776857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato            boolean showing = onEvaluateInputViewShown();
777857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato            mImm.setImeWindowStatus(mToken, IME_ACTIVE | (showing ? IME_VISIBLE : 0),
778857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato                    mBackDisposition);
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Implement to return our standard {@link InputMethodImpl}.  Subclasses
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can override to provide their own customized version.
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
786ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    @Override
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public AbstractInputMethodImpl onCreateInputMethodInterface() {
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new InputMethodImpl();
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Implement to return our standard {@link InputMethodSessionImpl}.  Subclasses
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can override to provide their own customized version.
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
795ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    @Override
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface() {
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new InputMethodSessionImpl();
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public LayoutInflater getLayoutInflater() {
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInflater;
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Dialog getWindow() {
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mWindow;
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
808857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public void setBackDisposition(int disposition) {
809857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato        mBackDisposition = disposition;
810857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    }
811857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
812857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public int getBackDisposition() {
813857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato        return mBackDisposition;
814857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    }
815857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the maximum width, in pixels, available the input method.
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Input methods are positioned at the bottom of the screen and, unless
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * running in fullscreen, will generally want to be as short as possible
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * so should compute their height based on their contents.  However, they
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can stretch as much as needed horizontally.  The function returns to
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * you the maximum amount of space available horizontally, which you can
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * use if needed for UI placement.
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>In many cases this is not needed, you can just rely on the normal
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * view layout mechanisms to position your views within the full horizontal
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * space given to the input method.
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Note that this value can change dynamically, in particular when the
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * screen orientation changes.
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getMaxWidth() {
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return wm.getDefaultDisplay().getWidth();
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the currently active InputBinding for the input method, or
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * null if there is none.
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public InputBinding getCurrentInputBinding() {
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInputBinding;
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Retrieve the currently active InputConnection that is bound to
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the input method, or null if there is none.
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public InputConnection getCurrentInputConnection() {
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputConnection ic = mStartedInputConnection;
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ic != null) {
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ic;
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInputConnection;
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getCurrentInputStarted() {
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInputStarted;
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public EditorInfo getCurrentInputEditorInfo() {
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInputEditorInfo;
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Re-evaluate whether the input method should be running in fullscreen
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * mode, and update its UI if this has changed since the last time it
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * was evaluated.  This will call {@link #onEvaluateFullscreenMode()} to
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * determine whether it should currently run in fullscreen mode.  You
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can use {@link #isFullscreenMode()} to determine if the input method
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is currently running in fullscreen mode.
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateFullscreenMode() {
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isFullscreen = mShowInputRequested && onEvaluateFullscreenMode();
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean changed = mLastShowInputRequested != mShowInputRequested;
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mIsFullscreen != isFullscreen || !mFullscreenApplied) {
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            changed = true;
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIsFullscreen = isFullscreen;
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputConnection ic = getCurrentInputConnection();
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ic != null) ic.reportFullscreenMode(isFullscreen);
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFullscreenApplied = true;
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            initialize();
883105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
884105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    mFullscreenArea.getLayoutParams();
885105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (isFullscreen) {
886105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mFullscreenArea.setBackgroundDrawable(mThemeAttrs.getDrawable(
887105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        com.android.internal.R.styleable.InputMethodService_imeFullscreenBackground));
888105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                lp.height = 0;
889105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                lp.weight = 1;
890105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            } else {
891105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mFullscreenArea.setBackgroundDrawable(null);
892105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                lp.height = LinearLayout.LayoutParams.WRAP_CONTENT;
893105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                lp.weight = 0;
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
895105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            ((ViewGroup)mFullscreenArea.getParent()).updateViewLayout(
896105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    mFullscreenArea, lp);
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isFullscreen) {
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mExtractView == null) {
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    View v = onCreateExtractTextView();
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (v != null) {
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        setExtractView(v);
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                startExtractingText(false);
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
906105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            updateExtractFrameVisibility();
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (changed) {
91034703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne            onConfigureWindow(mWindow.getWindow(), isFullscreen, !mShowInputRequested);
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastShowInputRequested = mShowInputRequested;
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Update the given window's parameters for the given mode.  This is called
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the window is first displayed and each time the fullscreen or
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * candidates only mode changes.
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default implementation makes the layout for the window
921980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy     * MATCH_PARENT x MATCH_PARENT when in fullscreen mode, and
922980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy     * MATCH_PARENT x WRAP_CONTENT when in non-fullscreen mode.
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param win The input method's window.
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param isFullscreen If true, the window is running in fullscreen mode
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and intended to cover the entire application display.
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param isCandidatesOnly If true, the window is only showing the
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * candidates view and none of the rest of its UI.  This is mutually
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * exclusive with fullscreen mode.
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onConfigureWindow(Window win, boolean isFullscreen,
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean isCandidatesOnly) {
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isFullscreen) {
934980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy            mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT);
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
936980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy            mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return whether the input method is <em>currently</em> running in
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * fullscreen mode.  This is the mode that was last determined and
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * applied by {@link #updateFullscreenMode()}.
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isFullscreenMode() {
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mIsFullscreen;
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Override this to control when the input method should run in
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * fullscreen mode.  The default implementation runs in fullsceen only
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the screen is in landscape mode.  If you change what
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this returns, you will need to call {@link #updateFullscreenMode()}
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * yourself whenever the returned value may have changed to have it
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * re-evaluated and applied.
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onEvaluateFullscreenMode() {
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Configuration config = getResources().getConfiguration();
9592edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins        if (config.orientation != Configuration.ORIENTATION_LANDSCAPE) {
9602edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins            return false;
9612edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins        }
9622edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins        if (mInputEditorInfo != null
9632edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins                && (mInputEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_FULLSCREEN) != 0) {
9642edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins            return false;
9652edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins        }
9662edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins        return true;
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
96834703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
970105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * Controls the visibility of the extracted text area.  This only applies
971105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * when the input method is in fullscreen mode, and thus showing extracted
972105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * text.  When false, the extracted text will not be shown, allowing some
973105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * of the application to be seen behind.  This is normally set for you
974105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * by {@link #onUpdateExtractingVisibility}.  This controls the visibility
975105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * of both the extracted text and candidate view; the latter since it is
976105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * not useful if there is no text to see.
977105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     */
978105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public void setExtractViewShown(boolean shown) {
979105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mExtractViewHidden == shown) {
980105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mExtractViewHidden = !shown;
981105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            updateExtractFrameVisibility();
982105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
983105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
984105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
985105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    /**
986105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * Return whether the fullscreen extract view is shown.  This will only
987105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * return true if {@link #isFullscreenMode()} returns true, and in that
988105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * case its value depends on the last call to
989105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * {@link #setExtractViewShown(boolean)}.  This effectively lets you
990105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * determine if the application window is entirely covered (when this
991105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * returns true) or if some part of it may be shown (if this returns
992105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * false, though if {@link #isFullscreenMode()} returns true in that case
993105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * then it is probably only a sliver of the application).
994105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     */
995105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public boolean isExtractViewShown() {
996105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        return mIsFullscreen && !mExtractViewHidden;
997105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
998105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
999105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    void updateExtractFrameVisibility() {
1000105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        int vis;
1001105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (isFullscreenMode()) {
1002105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            vis = mExtractViewHidden ? View.INVISIBLE : View.VISIBLE;
1003105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mExtractFrame.setVisibility(View.VISIBLE);
1004105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        } else {
1005105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            vis = View.VISIBLE;
1006105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mExtractFrame.setVisibility(View.GONE);
1007105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1008105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        updateCandidatesVisibility(mCandidatesVisibility == View.VISIBLE);
1009105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mWindowWasVisible && mFullscreenArea.getVisibility() != vis) {
1010105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            int animRes = mThemeAttrs.getResourceId(vis == View.VISIBLE
1011105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    ? com.android.internal.R.styleable.InputMethodService_imeExtractEnterAnimation
1012105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    : com.android.internal.R.styleable.InputMethodService_imeExtractExitAnimation,
1013105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    0);
1014105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (animRes != 0) {
1015105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mFullscreenArea.startAnimation(AnimationUtils.loadAnimation(
1016105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        this, animRes));
1017105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
1018105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1019105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mFullscreenArea.setVisibility(vis);
1020105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
1021105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1022105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    /**
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Compute the interesting insets into your UI.  The default implementation
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * uses the top of the candidates frame for the visible insets, and the
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * top of the input frame for the content insets.  The default touchable
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * insets are {@link Insets#TOUCHABLE_INSETS_VISIBLE}.
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1028105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * <p>Note that this method is not called when
1029105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * {@link #isExtractViewShown} returns true, since
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in that case the application is left as-is behind the input method and
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not impacted by anything in its UI.
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param outInsets Fill in with the current UI insets.
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onComputeInsets(Insets outInsets) {
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int[] loc = mTmpLocation;
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputFrame.getVisibility() == View.VISIBLE) {
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputFrame.getLocationInWindow(loc);
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1040105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            View decor = getWindow().getWindow().getDecorView();
1041105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            loc[1] = decor.getHeight();
1042105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1043105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (isFullscreenMode()) {
1044105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            // In fullscreen mode, we never resize the underlying window.
1045105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            View decor = getWindow().getWindow().getDecorView();
1046105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            outInsets.contentTopInsets = decor.getHeight();
1047105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        } else {
1048105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            outInsets.contentTopInsets = loc[1];
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCandidatesFrame.getVisibility() == View.VISIBLE) {
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCandidatesFrame.getLocationInWindow(loc);
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        outInsets.visibleTopInsets = loc[1];
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_VISIBLE;
1055fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        outInsets.touchableRegion.setEmpty();
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Re-evaluate whether the soft input area should currently be shown, and
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * update its UI if this has changed since the last time it
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * was evaluated.  This will call {@link #onEvaluateInputViewShown()} to
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * determine whether the input view should currently be shown.  You
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can use {@link #isInputViewShown()} to determine if the input view
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is currently shown.
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateInputViewShown() {
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isShown = mShowInputRequested && onEvaluateInputViewShown();
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mIsInputViewShown != isShown && mWindowVisible) {
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIsInputViewShown = isShown;
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputFrame.setVisibility(isShown ? View.VISIBLE : View.GONE);
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mInputView == null) {
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                initialize();
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                View v = onCreateInputView();
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (v != null) {
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setInputView(v);
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if we have been asked to show our input view.
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShowInputRequested() {
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mShowInputRequested;
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return whether the soft input view is <em>currently</em> shown to the
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * user.  This is the state that was last determined and
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * applied by {@link #updateInputViewShown()}.
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isInputViewShown() {
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mIsInputViewShown && mWindowVisible;
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Override this to control when the soft input area should be shown to
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the user.  The default implementation only shows the input view when
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * there is no hard keyboard or the keyboard is hidden.  If you change what
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this returns, you will need to call {@link #updateInputViewShown()}
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * yourself whenever the returned value may have changed to have it
11038cbb4c6e30cff706a243599634aeb8fd9a818d92Gilles Debunne     * re-evaluated and applied.
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onEvaluateInputViewShown() {
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Configuration config = getResources().getConfiguration();
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return config.keyboard == Configuration.KEYBOARD_NOKEYS
11088710e76a897cd546a79ee4338a4147eeb9f3e068Ken Wakasa                || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES;
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Controls the visibility of the candidates display area.  By default
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * it is hidden.
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setCandidatesViewShown(boolean shown) {
1116105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        updateCandidatesVisibility(shown);
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mShowInputRequested && mWindowVisible != shown) {
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If we are being asked to show the candidates view while the app
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // has not asked for the input view to be shown, then we need
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // to update whether the window is shown.
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (shown) {
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                showWindow(false);
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
11242f913d951c481edccbefa4d321a76f28740b48d7satok                doHideWindow();
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    void updateCandidatesVisibility(boolean shown) {
1130105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        int vis = shown ? View.VISIBLE : getCandidatesHiddenVisibility();
1131105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mCandidatesVisibility != vis) {
1132105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mCandidatesFrame.setVisibility(vis);
1133105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mCandidatesVisibility = vis;
1134105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1135105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
1136105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the visibility mode (either {@link View#INVISIBLE View.INVISIBLE}
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or {@link View#GONE View.GONE}) of the candidates view when it is not
1140105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * shown.  The default implementation returns GONE when
1141105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * {@link #isExtractViewShown} returns true,
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise VISIBLE.  Be careful if you change this to return GONE in
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * other situations -- if showing or hiding the candidates view causes
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * your window to resize, this can cause temporary drawing artifacts as
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the resize takes place.
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getCandidatesHiddenVisibility() {
1148105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        return isExtractViewShown() ? View.GONE : View.INVISIBLE;
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showStatusIcon(int iconResId) {
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStatusIcon = iconResId;
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mImm.showStatusIcon(mToken, getPackageName(), iconResId);
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void hideStatusIcon() {
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStatusIcon = 0;
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mImm.hideStatusIcon(mToken);
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Force switch to a new input method, as identified by <var>id</var>.  This
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * input method will be destroyed, and the requested one started on the
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * current input field.
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param id Unique identifier of the new input method ot start.
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void switchInputMethod(String id) {
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mImm.setInputMethod(mToken, id);
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setExtractView(View view) {
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractFrame.removeAllViews();
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractFrame.addView(view, new FrameLayout.LayoutParams(
1175980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                ViewGroup.LayoutParams.MATCH_PARENT,
1176980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                ViewGroup.LayoutParams.MATCH_PARENT));
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractView = view;
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (view != null) {
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractEditText = (ExtractEditText)view.findViewById(
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    com.android.internal.R.id.inputExtractEditText);
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractEditText.setIME(this);
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractAction = (Button)view.findViewById(
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    com.android.internal.R.id.inputExtractAction);
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mExtractAction != null) {
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mExtractAccessories = (ViewGroup)view.findViewById(
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        com.android.internal.R.id.inputExtractAccessories);
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startExtractingText(false);
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractEditText = null;
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractAccessories = null;
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractAction = null;
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Replaces the current candidates view with a new one.  You only need to
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * call this when dynamically changing the view; normally, you should
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implement {@link #onCreateCandidatesView()} and create your view when
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * first needed by the input method.
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setCandidatesView(View view) {
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesFrame.removeAllViews();
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesFrame.addView(view, new FrameLayout.LayoutParams(
1205980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                ViewGroup.LayoutParams.MATCH_PARENT,
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ViewGroup.LayoutParams.WRAP_CONTENT));
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Replaces the current input view with a new one.  You only need to
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * call this when dynamically changing the view; normally, you should
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implement {@link #onCreateInputView()} and create your view when
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * first needed by the input method.
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setInputView(View view) {
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputFrame.removeAllViews();
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputFrame.addView(view, new FrameLayout.LayoutParams(
1218980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                ViewGroup.LayoutParams.MATCH_PARENT,
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ViewGroup.LayoutParams.WRAP_CONTENT));
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputView = view;
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called by the framework to create the layout for showing extacted text.
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Only called when in fullscreen mode.  The returned view hierarchy must
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * have an {@link ExtractEditText} whose ID is
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.R.id#inputExtractEditText}.
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View onCreateExtractTextView() {
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInflater.inflate(
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                com.android.internal.R.layout.input_method_extract_view, null);
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create and return the view hierarchy used to show candidates.  This will
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be called once, when the candidates are first displayed.  You can return
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * null to have no candidates view; the default implementation returns null.
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>To control when the candidates view is displayed, use
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #setCandidatesViewShown(boolean)}.
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * To change the candidates view after the first one is created by this
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * function, use {@link #setCandidatesView(View)}.
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View onCreateCandidatesView() {
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create and return the view hierarchy used for the input area (such as
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a soft keyboard).  This will be called once, when the input area is
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * first displayed.  You can return null to have no input area; the default
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementation returns null.
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>To control when the input view is displayed, implement
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #onEvaluateInputViewShown()}.
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * To change the input view after the first one is created by this
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * function, use {@link #setInputView(View)}.
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View onCreateInputView() {
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the input view is being shown and input has started on
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a new editor.  This will always be called after {@link #onStartInput},
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * allowing you to do your general setup there and just view-specific
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * setup here.  You are guaranteed that {@link #onCreateInputView()} will
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * have been called some time before this function is called.
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param info Description of the type of text being edited.
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param restarting Set to true if we are restarting input on the
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * same text field as before.
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onStartInputView(EditorInfo info, boolean restarting) {
127534703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the input view is being hidden from the user.  This will
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be called either prior to hiding the window, or prior to switching to
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * another target for editing.
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementation uses the InputConnection to clear any active composing
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * text; you can override this (not calling the base class implementation)
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to perform whatever behavior you would like.
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12884df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * @param finishingInput If true, {@link #onFinishInput} will be
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called immediately after.
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onFinishInputView(boolean finishingInput) {
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!finishingInput) {
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputConnection ic = getCurrentInputConnection();
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ic != null) {
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ic.finishComposingText();
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when only the candidates view has been shown for showing
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * processing as the user enters text through a hard keyboard.
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This will always be called after {@link #onStartInput},
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * allowing you to do your general setup there and just view-specific
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * setup here.  You are guaranteed that {@link #onCreateCandidatesView()}
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will have been called some time before this function is called.
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Note that this will <em>not</em> be called when the input method
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is running in full editing mode, and thus receiving
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #onStartInputView} to initiate that operation.  This is only
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for the case when candidates are being shown while the input method
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * editor is hidden but wants to show its candidates UI as text is
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * entered through some other mechanism.
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param info Description of the type of text being edited.
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param restarting Set to true if we are restarting input on the
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * same text field as before.
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onStartCandidatesView(EditorInfo info, boolean restarting) {
132034703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the candidates view is being hidden from the user.  This will
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be called either prior to hiding the window, or prior to switching to
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * another target for editing.
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementation uses the InputConnection to clear any active composing
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * text; you can override this (not calling the base class implementation)
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to perform whatever behavior you would like.
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13334df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * @param finishingInput If true, {@link #onFinishInput} will be
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called immediately after.
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onFinishCandidatesView(boolean finishingInput) {
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!finishingInput) {
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputConnection ic = getCurrentInputConnection();
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ic != null) {
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ic.finishComposingText();
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The system has decided that it may be time to show your input method.
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is called due to a corresponding call to your
13484df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * {@link InputMethod#showSoftInput InputMethod.showSoftInput()}
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * method.  The default implementation uses
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #onEvaluateInputViewShown()}, {@link #onEvaluateFullscreenMode()},
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and the current configuration to decide whether the input view should
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be shown at this point.
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param flags Provides additional information about the show request,
13554df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * as per {@link InputMethod#showSoftInput InputMethod.showSoftInput()}.
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param configChange This is true if we are re-showing due to a
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * configuration change.
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns true to indicate that the window should be shown.
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onShowInputRequested(int flags, boolean configChange) {
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!onEvaluateInputViewShown()) {
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethod.SHOW_EXPLICIT) == 0) {
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!configChange && onEvaluateFullscreenMode()) {
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Don't show if this is not explicitly requested by the user and
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // the input method is fullscreen.  That would be too disruptive.
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // However, we skip this change for a config change, since if
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // the IME is already shown we do want to go into fullscreen
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // mode at this point.
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Configuration config = getResources().getConfiguration();
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (config.keyboard != Configuration.KEYBOARD_NOKEYS) {
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // And if the device has a hard keyboard, even if it is
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // currently hidden, don't show the input method implicitly.
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // These kinds of devices don't need it that much.
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethod.SHOW_FORCED) != 0) {
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowInputForced = true;
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showWindow(boolean showInput) {
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DEBUG) Log.v(TAG, "Showing window: showInput=" + showInput
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mShowInputRequested=" + mShowInputRequested
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mWindowAdded=" + mWindowAdded
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mWindowCreated=" + mWindowCreated
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mWindowVisible=" + mWindowVisible
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mInputStarted=" + mInputStarted);
1394105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1395105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mInShowWindow) {
1396105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.w(TAG, "Re-entrance in to showWindow");
1397105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return;
1398105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1399105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1400105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        try {
1401105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mWindowWasVisible = mWindowVisible;
1402105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mInShowWindow = true;
1403105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            showWindowInner(showInput);
1404105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        } finally {
1405105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mWindowWasVisible = true;
1406105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mInShowWindow = false;
1407105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1408105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
140906487a58be22b100daf3f950b9a1d25c3ea42aa2satok
1410105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    void showWindowInner(boolean showInput) {
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean doShowInput = false;
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean wasVisible = mWindowVisible;
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWindowVisible = true;
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mShowInputRequested) {
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mInputStarted) {
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (showInput) {
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    doShowInput = true;
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mShowInputRequested = true;
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            showInput = true;
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
142406487a58be22b100daf3f950b9a1d25c3ea42aa2satok
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DEBUG) Log.v(TAG, "showWindow: updating UI");
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initialize();
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateFullscreenMode();
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateInputViewShown();
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mWindowAdded || !mWindowCreated) {
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWindowAdded = true;
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWindowCreated = true;
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            initialize();
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "CALL: onCreateCandidatesView");
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View v = onCreateCandidatesView();
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "showWindow: candidates=" + v);
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (v != null) {
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                setCandidatesView(v);
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowInputRequested) {
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mInputViewStarted) {
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) Log.v(TAG, "CALL: onStartInputView");
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInputViewStarted = true;
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                onStartInputView(mInputEditorInfo, false);
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (!mCandidatesViewStarted) {
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "CALL: onStartCandidatesView");
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCandidatesViewStarted = true;
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onStartCandidatesView(mInputEditorInfo, false);
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (doShowInput) {
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startExtractingText(false);
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
145606487a58be22b100daf3f950b9a1d25c3ea42aa2satok
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!wasVisible) {
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "showWindow: showing!");
1459857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato            mImm.setImeWindowStatus(mToken, IME_ACTIVE, mBackDisposition);
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onWindowShown();
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWindow.show();
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
146406487a58be22b100daf3f950b9a1d25c3ea42aa2satok
1465f17db9f5257011d5331d27a6da7d4e6fddde1e08satok    private void finishViews() {
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputViewStarted) {
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "CALL: onFinishInputView");
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onFinishInputView(false);
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mCandidatesViewStarted) {
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "CALL: onFinishCandidatesView");
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onFinishCandidatesView(false);
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputViewStarted = false;
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesViewStarted = false;
1475f17db9f5257011d5331d27a6da7d4e6fddde1e08satok    }
1476f17db9f5257011d5331d27a6da7d4e6fddde1e08satok
14772f913d951c481edccbefa4d321a76f28740b48d7satok    private void doHideWindow() {
14782f913d951c481edccbefa4d321a76f28740b48d7satok        mImm.setImeWindowStatus(mToken, 0, mBackDisposition);
14792f913d951c481edccbefa4d321a76f28740b48d7satok        hideWindow();
14802f913d951c481edccbefa4d321a76f28740b48d7satok    }
14812f913d951c481edccbefa4d321a76f28740b48d7satok
1482f17db9f5257011d5331d27a6da7d4e6fddde1e08satok    public void hideWindow() {
1483f17db9f5257011d5331d27a6da7d4e6fddde1e08satok        finishViews();
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mWindowVisible) {
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWindow.hide();
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWindowVisible = false;
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onWindowHidden();
1488105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mWindowWasVisible = false;
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
149106487a58be22b100daf3f950b9a1d25c3ea42aa2satok
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the input method window has been shown to the user, after
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * previously not being visible.  This is done after all of the UI setup
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for the window has occurred (creating its views etc).
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onWindowShown() {
149834703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the input method window has been hidden from the user,
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * after previously being visible.
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onWindowHidden() {
150634703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when a new client has bound to the input method.  This
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * may be followed by a series of {@link #onStartInput(EditorInfo, boolean)}
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and {@link #onFinishInput()} calls as the user navigates through its
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * UI.  Upon this call you know that {@link #getCurrentInputBinding}
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and {@link #getCurrentInputConnection} return valid objects.
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onBindInput() {
151734703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the previous bound client is no longer associated
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with the input method.  After returning {@link #getCurrentInputBinding}
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and {@link #getCurrentInputConnection} will no longer return
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * valid objects.
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onUnbindInput() {
152734703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called to inform the input method that text input has started in an
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * editor.  You should use this callback to initialize the state of your
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * input to match the state of the editor given to it.
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attribute The attributes of the editor that input is starting
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in.
15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param restarting Set to true if input is restarting in the same
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * editor such as because the application has changed the text in
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the editor.  Otherwise will be false, indicating this is a new
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * session with the editor.
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onStartInput(EditorInfo attribute, boolean restarting) {
154334703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void doFinishInput() {
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputViewStarted) {
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "CALL: onFinishInputView");
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onFinishInputView(true);
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mCandidatesViewStarted) {
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "CALL: onFinishCandidatesView");
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onFinishCandidatesView(true);
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputViewStarted = false;
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesViewStarted = false;
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputStarted) {
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "CALL: onFinishInput");
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onFinishInput();
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputStarted = false;
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStartedInputConnection = null;
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurCompletions = null;
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15644df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void doStartInput(InputConnection ic, EditorInfo attribute, boolean restarting) {
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!restarting) {
15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            doFinishInput();
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputStarted = true;
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStartedInputConnection = ic;
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputEditorInfo = attribute;
15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initialize();
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DEBUG) Log.v(TAG, "CALL: onStartInput");
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onStartInput(attribute, restarting);
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mWindowVisible) {
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mShowInputRequested) {
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) Log.v(TAG, "CALL: onStartInputView");
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInputViewStarted = true;
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                onStartInputView(mInputEditorInfo, restarting);
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                startExtractingText(true);
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (mCandidatesVisibility == View.VISIBLE) {
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) Log.v(TAG, "CALL: onStartCandidatesView");
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCandidatesViewStarted = true;
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                onStartCandidatesView(mInputEditorInfo, restarting);
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called to inform the input method that text input has finished in
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the last editor.  At this point there may be a call to
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #onStartInput(EditorInfo, boolean)} to perform input in a
15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * new editor, or the input method may be left idle.  This method is
15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <em>not</em> called when input restarts in the same editor.
15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default
15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementation uses the InputConnection to clear any active composing
15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * text; you can override this (not calling the base class implementation)
15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to perform whatever behavior you would like.
16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onFinishInput() {
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputConnection ic = getCurrentInputConnection();
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ic != null) {
16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ic.finishComposingText();
16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the application has reported auto-completion candidates that
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * it would like to have the input method displayed.  Typically these are
16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * only used when an input method is running in full-screen mode, since
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise the user can see and interact with the pop-up window of
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * completions shown by the application.
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default implementation here does nothing.
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onDisplayCompletions(CompletionInfo[] completions) {
161834703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the application has reported new extracted text to be shown
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * due to changes in its current text state.  The default implementation
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * here places the new text in the extract edit text, when the input
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * method is running in fullscreen mode.
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onUpdateExtractedText(int token, ExtractedText text) {
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mExtractedToken != token) {
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1631b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (text != null) {
1632b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            if (mExtractEditText != null) {
1633b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mExtractedText = text;
1634b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mExtractEditText.setExtractedText(text);
1635b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            }
16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the application has reported a new selection region of
16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the text.  This is called whether or not the input method has requested
16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * extracted text updates, although if so it will not receive this call
16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if the extracted text has changed as well.
16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default implementation takes care of updating the cursor in
16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the extract text, if it is being shown.
16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onUpdateSelection(int oldSelStart, int oldSelEnd,
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int newSelStart, int newSelEnd,
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int candidatesStart, int candidatesEnd) {
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ExtractEditText eet = mExtractEditText;
1652c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        if (eet != null && isFullscreenMode() && mExtractedText != null) {
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int off = mExtractedText.startOffset;
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            eet.startInternalChanges();
1655c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            newSelStart -= off;
1656c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            newSelEnd -= off;
1657c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            final int len = eet.getText().length();
1658c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            if (newSelStart < 0) newSelStart = 0;
1659c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            else if (newSelStart > len) newSelStart = len;
1660c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            if (newSelEnd < 0) newSelEnd = 0;
1661c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            else if (newSelEnd > len) newSelEnd = len;
1662c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            eet.setSelection(newSelStart, newSelEnd);
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            eet.finishInternalChanges();
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1668863fcd62171e55bc9f2105d9fb5877df982454d8satok     * Called when the user tapped or clicked a text view.
1669863fcd62171e55bc9f2105d9fb5877df982454d8satok     * IMEs can't rely on this method being called because this was not part of the original IME
1670863fcd62171e55bc9f2105d9fb5877df982454d8satok     * protocol, so applications with custom text editing written before this method appeared will
1671863fcd62171e55bc9f2105d9fb5877df982454d8satok     * not call to inform the IME of this interaction.
1672863fcd62171e55bc9f2105d9fb5877df982454d8satok     * @param focusChanged true if the user changed the focused view by this click.
1673863fcd62171e55bc9f2105d9fb5877df982454d8satok     */
1674863fcd62171e55bc9f2105d9fb5877df982454d8satok    public void onViewClicked(boolean focusChanged) {
167534703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
1676863fcd62171e55bc9f2105d9fb5877df982454d8satok    }
1677863fcd62171e55bc9f2105d9fb5877df982454d8satok
1678863fcd62171e55bc9f2105d9fb5877df982454d8satok    /**
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the application has reported a new location of its text
16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cursor.  This is only called if explicitly requested by the input method.
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The default implementation does nothing.
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onUpdateCursor(Rect newCursor) {
168434703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Close this input method's soft input area, removing it from the display.
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The input method will continue running, but the user can no longer use
16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * it to generate input by touching the screen.
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param flags Provides additional operating flags.  Currently may be
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * 0 or have the {@link InputMethodManager#HIDE_IMPLICIT_ONLY
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * InputMethodManager.HIDE_IMPLICIT_ONLY} bit set.
16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16954df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public void requestHideSelf(int flags) {
16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mImm.hideSoftInputFromInputMethod(mToken, flags);
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
17004df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * Show the input method. This is a call back to the
17014df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * IMF to handle showing the input method.
17024df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * @param flags Provides additional operating flags.  Currently may be
17034df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * 0 or have the {@link InputMethodManager#SHOW_FORCED
17044df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * InputMethodManager.} bit set.
17054df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     */
17064df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    private void requestShowSelf(int flags) {
17074df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        mImm.showSoftInputFromInputMethod(mToken, flags);
17084df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    }
17094df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
171083fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn    private boolean handleBack(boolean doIt) {
171183fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        if (mShowInputRequested) {
171234703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne            if (isExtractViewShown() && mExtractView instanceof ExtractEditLayout) {
171334703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne                ExtractEditLayout extractEditLayout = (ExtractEditLayout) mExtractView;
171434703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne                if (extractEditLayout.isActionModeStarted()) {
171534703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne                    if (doIt) extractEditLayout.finishActionMode();
171634703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne                    return true;
171734703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne                }
171834703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne            }
171983fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            // If the soft input area is shown, back closes it and we
172083fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            // consume the back key.
172183fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            if (doIt) requestHideSelf(0);
172283fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            return true;
172383fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        } else if (mWindowVisible) {
172483fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            if (mCandidatesVisibility == View.VISIBLE) {
172583fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                // If we are showing candidates even if no input area, then
172683fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                // hide them.
172783fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                if (doIt) setCandidatesViewShown(false);
172883fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            } else {
172983fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                // If we have the window visible for some other reason --
173083fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                // most likely to show candidates -- then just get rid
173183fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                // of it.  This really shouldn't happen, but just in case...
17322f913d951c481edccbefa4d321a76f28740b48d7satok                if (doIt) doHideWindow();
173383fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            }
173483fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            return true;
173583fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        }
173683fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        return false;
173783fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn    }
173883fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn
17394df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    /**
17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Override this to intercept key down events before they are processed by the
1741ee71b1fa2d3905214fafaa9478fa4fc2834b06fcQuddus Chong     * application.  If you return true, the application will not
1742ee71b1fa2d3905214fafaa9478fa4fc2834b06fcQuddus Chong     * process the event itself.  If you return false, the normal application processing
17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will occur as if the IME had not seen the event at all.
17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
17459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK
174683fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * KeyEvent.KEYCODE_BACK} if the IME is currently shown, to
174783fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * possibly hide it when the key goes up (if not canceled or long pressed).  In
174883fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * addition, in fullscreen mode only, it will consume DPAD movement
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * events to move the cursor in the extracted text view, not allowing
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * them to perform navigation in the underlying application.
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
175383fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
175483fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            if (handleBack(false)) {
175583fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                event.startTracking();
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
175883fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            return false;
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return doMovementKey(keyCode, event, MOVEMENT_DOWN);
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
176483fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
176583fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
176683fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * the event).
176783fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     */
176883fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
176983fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        return false;
177083fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn    }
177183fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn
177283fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn    /**
17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Override this to intercept special key multiple events before they are
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * processed by the
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * application.  If you return true, the application will not itself
1776b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * process the event.  If you return false, the normal application processing
17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will occur as if the IME had not seen the event at all.
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default implementation always returns false, except when
17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in fullscreen mode, where it will consume DPAD movement
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * events to move the cursor in the extracted text view, not allowing
17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * them to perform navigation in the underlying application.
17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return doMovementKey(keyCode, event, count);
17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Override this to intercept key up events before they are processed by the
17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * application.  If you return true, the application will not itself
1791b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * process the event.  If you return false, the normal application processing
17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will occur as if the IME had not seen the event at all.
17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
179483fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK
179583fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * KeyEvent.KEYCODE_BACK} to hide the current IME UI if it is shown.  In
179683fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * addition, in fullscreen mode only, it will consume DPAD movement
17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * events to move the cursor in the extracted text view, not allowing
17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * them to perform navigation in the underlying application.
17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onKeyUp(int keyCode, KeyEvent event) {
180183fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.isTracking()
180283fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                && !event.isCanceled()) {
180383fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            return handleBack(true);
180483fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        }
180583fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn
18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return doMovementKey(keyCode, event, MOVEMENT_UP);
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1809b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease    /**
1810b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * Override this to intercept trackball motion events before they are
1811b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * processed by the application.
1812b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * If you return true, the application will not itself process the event.
1813b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * If you return false, the normal application processing will occur as if
1814b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * the IME had not seen the event at all.
1815b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     */
1816ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    @Override
18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onTrackballEvent(MotionEvent event) {
1818b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease        if (DEBUG) Log.v(TAG, "onTrackballEvent: " + event);
1819b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease        return false;
1820b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease    }
1821b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease
1822b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease    /**
1823b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * Override this to intercept generic motion events before they are
1824b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * processed by the application.
1825b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * If you return true, the application will not itself process the event.
1826b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * If you return false, the normal application processing will occur as if
1827b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * the IME had not seen the event at all.
1828b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     */
1829b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease    @Override
1830b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease    public boolean onGenericMotionEvent(MotionEvent event) {
1831b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease        if (DEBUG) Log.v(TAG, "onGenericMotionEvent(): event " + event);
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onAppPrivateCommand(String action, Bundle data) {
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18384df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    /**
18394df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * Handle a request by the system to toggle the soft input area.
18404df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     */
18414df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    private void onToggleSoftInput(int showFlags, int hideFlags) {
18424df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        if (DEBUG) Log.v(TAG, "toggleSoftInput()");
18434df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        if (isInputViewShown()) {
18444df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            requestHideSelf(hideFlags);
18454df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        } else {
18464df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            requestShowSelf(showFlags);
18474df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
18484df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    }
18494df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MOVEMENT_DOWN = -1;
18519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MOVEMENT_UP = -2;
18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void reportExtractedMovement(int keyCode, int count) {
18549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int dx = 0, dy = 0;
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (keyCode) {
18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_LEFT:
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dx = -count;
18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_RIGHT:
18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dx = count;
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_UP:
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dy = -count;
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
18659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_DOWN:
18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dy = count;
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1869ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        onExtractedCursorMovement(dx, dy);
18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean doMovementKey(int keyCode, KeyEvent event, int count) {
18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ExtractEditText eet = mExtractEditText;
1874105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (isExtractViewShown() && isInputViewShown() && eet != null) {
18759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If we are in fullscreen mode, the cursor will move around
18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // the extract edit text, but should NOT cause focus to move
18779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // to other fields.
18789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MovementMethod movement = eet.getMovementMethod();
18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Layout layout = eet.getLayout();
18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (movement != null && layout != null) {
18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // We want our own movement method to handle the key, so the
18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // cursor will properly move in our own word wrapping.
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (count == MOVEMENT_DOWN) {
18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (movement.onKeyDown(eet,
18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (Spannable)eet.getText(), keyCode, event)) {
18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        reportExtractedMovement(keyCode, 1);
18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        return true;
18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (count == MOVEMENT_UP) {
18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (movement.onKeyUp(eet,
18919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (Spannable)eet.getText(), keyCode, event)) {
18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        return true;
18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (movement.onKeyOther(eet, (Spannable)eet.getText(), event)) {
18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        reportExtractedMovement(keyCode, count);
18979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
1898105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        KeyEvent down = KeyEvent.changeAction(event, KeyEvent.ACTION_DOWN);
18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (movement.onKeyDown(eet,
19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                (Spannable)eet.getText(), keyCode, down)) {
1901105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            KeyEvent up = KeyEvent.changeAction(event, KeyEvent.ACTION_UP);
19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            movement.onKeyUp(eet,
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    (Spannable)eet.getText(), keyCode, up);
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            while (--count > 0) {
19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                movement.onKeyDown(eet,
19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        (Spannable)eet.getText(), keyCode, down);
19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                movement.onKeyUp(eet,
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        (Spannable)eet.getText(), keyCode, up);
19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            reportExtractedMovement(keyCode, count);
19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Regardless of whether the movement method handled the key,
19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // we never allow DPAD navigation to the application.
19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (keyCode) {
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case KeyEvent.KEYCODE_DPAD_LEFT:
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case KeyEvent.KEYCODE_DPAD_RIGHT:
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case KeyEvent.KEYCODE_DPAD_UP:
19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case KeyEvent.KEYCODE_DPAD_DOWN:
19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return true;
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Send the given key event code (as defined by {@link KeyEvent}) to the
19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * current input connection is a key down + key up event pair.  The sent
19329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * events have {@link KeyEvent#FLAG_SOFT_KEYBOARD KeyEvent.FLAG_SOFT_KEYBOARD}
19339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * set, so that the recipient can identify them as coming from a software
19349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * input method, and
19359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link KeyEvent#FLAG_KEEP_TOUCH_MODE KeyEvent.FLAG_KEEP_TOUCH_MODE}, so
19369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that they don't impact the current touch mode of the UI.
19379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1938405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * <p>Note that it's discouraged to send such key events in normal operation;
1939405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * this is mainly for use with {@link android.text.InputType#TYPE_NULL} type
1940405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * text fields, or for non-rich input methods. A reasonably capable software
1941405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * input method should use the
1942405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * {@link android.view.inputmethod.InputConnection#commitText} family of methods
1943405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * to send text to an application, rather than sending key events.</p>
1944405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     *
19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param keyEventCode The raw key code to send, as defined by
19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link KeyEvent}.
19479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void sendDownUpKeyEvents(int keyEventCode) {
19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputConnection ic = getCurrentInputConnection();
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ic == null) return;
19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long eventTime = SystemClock.uptimeMillis();
19529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ic.sendKeyEvent(new KeyEvent(eventTime, eventTime,
19536b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown                KeyEvent.ACTION_DOWN, keyEventCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ic.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
19566b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown                KeyEvent.ACTION_UP, keyEventCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Ask the input target to execute its default action via
19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InputConnection#performEditorAction
19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * InputConnection.performEditorAction()}.
19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param fromEnterKey If true, this will be executed as if the user had
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pressed an enter key on the keyboard, that is it will <em>not</em>
19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be done if the editor has set {@link EditorInfo#IME_FLAG_NO_ENTER_ACTION
19689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * EditorInfo.IME_FLAG_NO_ENTER_ACTION}.  If false, the action will be
19699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * sent regardless of how the editor has set that flag.
19709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a boolean indicating whether an action has been sent.
19729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If false, either the editor did not specify a default action or it
19739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * does not want an action from the enter key.  If true, the action was
19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * sent (or there was no input connection at all).
19759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendDefaultEditorAction(boolean fromEnterKey) {
19779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        EditorInfo ei = getCurrentInputEditorInfo();
19789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ei != null &&
19799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (!fromEnterKey || (ei.imeOptions &
19809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        EditorInfo.IME_FLAG_NO_ENTER_ACTION) == 0) &&
19819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (ei.imeOptions & EditorInfo.IME_MASK_ACTION) !=
19829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    EditorInfo.IME_ACTION_NONE) {
19839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the enter key was pressed, and the editor has a default
19849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // action associated with pressing enter, then send it that
19859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // explicit action instead of the key event.
19869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputConnection ic = getCurrentInputConnection();
19879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ic != null) {
19889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ic.performEditorAction(ei.imeOptions&EditorInfo.IME_MASK_ACTION);
19899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
19919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
19949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Send the given UTF-16 character to the current input connection.  Most
19989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * characters will be delivered simply by calling
19999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InputConnection#commitText InputConnection.commitText()} with
20009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the character; some, however, may be handled different.  In particular,
20019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the enter character ('\n') will either be delivered as an action code
2002405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * or a raw key event, as appropriate.  Consider this as a convenience
2003405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * method for IMEs that do not have a full implementation of actions; a
2004405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * fully complying IME will decide of the right action for each event and
2005405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * will likely never call this method except maybe to handle events coming
2006405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * from an actual hardware keyboard.
20079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
20089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param charCode The UTF-16 character code to send.
20099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void sendKeyChar(char charCode) {
20119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (charCode) {
20129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case '\n': // Apps may be listening to an enter key to perform an action
20139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!sendDefaultEditorAction(true)) {
20149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    sendDownUpKeyEvents(KeyEvent.KEYCODE_ENTER);
20159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
20169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Make sure that digits go through any text watcher on the client side.
20199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (charCode >= '0' && charCode <= '9') {
20209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    sendDownUpKeyEvents(charCode - '0' + KeyEvent.KEYCODE_0);
20219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
20229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    InputConnection ic = getCurrentInputConnection();
20239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (ic != null) {
20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ic.commitText(String.valueOf((char) charCode), 1);
20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
20269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
20279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is called when the user has moved the cursor in the extracted
20339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * text view, when running in fullsreen mode.  The default implementation
20349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * performs the corresponding selection change on the underlying text
20359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * editor.
20369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onExtractedSelectionChanged(int start, int end) {
20389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputConnection conn = getCurrentInputConnection();
20399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (conn != null) {
20409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            conn.setSelection(start, end);
20419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
204339ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne
204439ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne    /**
204539ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne     * @hide
204639ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne     */
204739ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne    public void onExtractedDeleteText(int start, int end) {
204839ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne        InputConnection conn = getCurrentInputConnection();
204939ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne        if (conn != null) {
205039ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne            conn.setSelection(start, start);
205139ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne            conn.deleteSurroundingText(0, end-start);
205239ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne        }
205339ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne    }
205439ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne
205539ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne    /**
205639ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne     * @hide
205739ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne     */
205839ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne    public void onExtractedReplaceText(int start, int end, CharSequence text) {
205939ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne        InputConnection conn = getCurrentInputConnection();
206039ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne        if (conn != null) {
206139ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne            conn.setComposingRegion(start, end);
206239ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne            conn.commitText(text, 1);
206339ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne        }
206439ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne    }
206539ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne
20669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2067e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne     * @hide
2068e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne     */
2069e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne    public void onExtractedSetSpan(Object span, int start, int end, int flags) {
2070e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne        InputConnection conn = getCurrentInputConnection();
2071e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne        if (conn != null) {
2072e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne            if (!conn.setSelection(start, end)) return;
2073e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne            CharSequence text = conn.getSelectedText(InputConnection.GET_TEXT_WITH_STYLES);
2074e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne            if (text instanceof Spannable) {
2075e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne                ((Spannable) text).setSpan(span, 0, text.length(), flags);
2076e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne                conn.setComposingRegion(start, end);
2077e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne                conn.commitText(text, 1);
2078e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne            }
2079e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne        }
2080e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne    }
2081e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne
2082e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne    /**
20839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is called when the user has clicked on the extracted text view,
20849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when running in fullscreen mode.  The default implementation hides
20859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the candidates view when this happens, but only if the extracted text
20869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * editor has a vertical scroll bar because its text doesn't fit.
20879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Re-implement this to provide whatever behavior you want.
20889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onExtractedTextClicked() {
20909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mExtractEditText == null) {
20919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
20929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mExtractEditText.hasVerticalScrollBar()) {
20949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setCandidatesViewShown(false);
20959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
209739ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne
20989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
20999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is called when the user has performed a cursor movement in the
21009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * extracted text view, when it is running in fullscreen mode.  The default
21019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementation hides the candidates view when a vertical movement
21029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * happens, but only if the extracted text editor has a vertical scroll bar
21039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * because its text doesn't fit.
21049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Re-implement this to provide whatever behavior you want.
21059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param dx The amount of cursor movement in the x dimension.
21069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param dy The amount of cursor movement in the y dimension.
21079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
21089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onExtractedCursorMovement(int dx, int dy) {
21099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mExtractEditText == null || dy == 0) {
21109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
21119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mExtractEditText.hasVerticalScrollBar()) {
21139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setCandidatesViewShown(false);
21149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
21189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is called when the user has selected a context menu item from the
21199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * extracted text view, when running in fullscreen mode.  The default
21209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementation sends this action to the current InputConnection's
21219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InputConnection#performContextMenuAction(int)}, for it
21229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to be processed in underlying "real" editor.  Re-implement this to
21239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * provide whatever behavior you want.
21249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
21259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onExtractTextContextMenuItem(int id) {
21269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputConnection ic = getCurrentInputConnection();
21279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ic != null) {
21289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ic.performContextMenuAction(id);
21299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
21319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
21349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return text that can be used as a button label for the given
21359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link EditorInfo#imeOptions EditorInfo.imeOptions}.  Returns null
21369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if there is no action requested.  Note that there is no guarantee that
21379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the returned text will be relatively short, so you probably do not
21389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * want to use it as text on a soft keyboard key label.
21399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
21409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param imeOptions The value from @link EditorInfo#imeOptions EditorInfo.imeOptions}.
21419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
21429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a label to use, or null if there is no action.
21439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
21449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public CharSequence getTextForImeAction(int imeOptions) {
21459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (imeOptions&EditorInfo.IME_MASK_ACTION) {
21469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EditorInfo.IME_ACTION_NONE:
21479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
21489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EditorInfo.IME_ACTION_GO:
21499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return getText(com.android.internal.R.string.ime_action_go);
21509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EditorInfo.IME_ACTION_SEARCH:
21519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return getText(com.android.internal.R.string.ime_action_search);
21529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EditorInfo.IME_ACTION_SEND:
21539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return getText(com.android.internal.R.string.ime_action_send);
21549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EditorInfo.IME_ACTION_NEXT:
21559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return getText(com.android.internal.R.string.ime_action_next);
21564df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            case EditorInfo.IME_ACTION_DONE:
21574df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return getText(com.android.internal.R.string.ime_action_done);
2158dea3ef7967228f0ddcc03f2455a4f1254758e584Dianne Hackborn            case EditorInfo.IME_ACTION_PREVIOUS:
2159dea3ef7967228f0ddcc03f2455a4f1254758e584Dianne Hackborn                return getText(com.android.internal.R.string.ime_action_previous);
21609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
21619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return getText(com.android.internal.R.string.ime_action_default);
21629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2166105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * Called when the fullscreen-mode extracting editor info has changed,
2167105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * to determine whether the extracting (extract text and candidates) portion
2168105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * of the UI should be shown.  The standard implementation hides or shows
2169105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * the extract area depending on whether it makes sense for the
2170105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * current editor.  In particular, a {@link InputType#TYPE_NULL}
2171105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * input type or {@link EditorInfo#IME_FLAG_NO_EXTRACT_UI} flag will
2172105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * turn off the extract area since there is no text to be shown.
2173105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     */
2174105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public void onUpdateExtractingVisibility(EditorInfo ei) {
2175105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (ei.inputType == InputType.TYPE_NULL ||
2176105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                (ei.imeOptions&EditorInfo.IME_FLAG_NO_EXTRACT_UI) != 0) {
2177105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            // No reason to show extract UI!
2178105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            setExtractViewShown(false);
2179105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return;
2180105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
2181105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2182105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        setExtractViewShown(true);
2183105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
2184105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2185105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    /**
2186105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * Called when the fullscreen-mode extracting editor info has changed,
2187105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * to update the state of its UI such as the action buttons shown.
2188105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * You do not need to deal with this if you are using the standard
21899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * full screen extract UI.  If replacing it, you will need to re-implement
2190105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * this to put the appropriate action button in your own UI and handle it,
2191105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * and perform any other changes.
2192105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     *
2193105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * <p>The standard implementation turns on or off its accessory area
2194105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * depending on whether there is an action button, and hides or shows
2195105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * the entire extract area depending on whether it makes sense for the
2196105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * current editor.  In particular, a {@link InputType#TYPE_NULL} or
2197105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * {@link InputType#TYPE_TEXT_VARIATION_FILTER} input type will turn off the
2198105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * extract area since there is no text to be shown.
21999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2200105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public void onUpdateExtractingViews(EditorInfo ei) {
2201105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (!isExtractViewShown()) {
2202105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return;
2203105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
2204105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
22059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mExtractAccessories == null) {
22069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
22079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean hasAction = ei.actionLabel != null || (
22099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (ei.imeOptions&EditorInfo.IME_MASK_ACTION) != EditorInfo.IME_ACTION_NONE &&
2210105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                (ei.imeOptions&EditorInfo.IME_FLAG_NO_ACCESSORY_ACTION) == 0 &&
2211105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                ei.inputType != InputType.TYPE_NULL);
22129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (hasAction) {
22139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractAccessories.setVisibility(View.VISIBLE);
221459eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik            if (mExtractAction != null) {
221559eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik                if (ei.actionLabel != null) {
221659eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik                    mExtractAction.setText(ei.actionLabel);
221759eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik                } else {
221859eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik                    mExtractAction.setText(getTextForImeAction(ei.imeOptions));
221959eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik                }
222059eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik                mExtractAction.setOnClickListener(mActionClickListener);
22219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
22229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
22239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractAccessories.setVisibility(View.GONE);
222459eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik            if (mExtractAction != null) {
222559eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik                mExtractAction.setOnClickListener(null);
222659eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik            }
22279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
22319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is called when, while currently displayed in extract mode, the
22329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * current input target changes.  The default implementation will
22339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * auto-hide the IME if the new target is not a full editor, since this
2234f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa     * can be a confusing experience for the user.
22359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
22369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onExtractingInputChanged(EditorInfo ei) {
22379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ei.inputType == InputType.TYPE_NULL) {
22384df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            requestHideSelf(InputMethodManager.HIDE_NOT_ALWAYS);
22399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void startExtractingText(boolean inputChanged) {
22439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ExtractEditText eet = mExtractEditText;
22449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (eet != null && getCurrentInputStarted()
22459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && isFullscreenMode()) {
22469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractedToken++;
22479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ExtractedTextRequest req = new ExtractedTextRequest();
22489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            req.token = mExtractedToken;
22499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            req.flags = InputConnection.GET_TEXT_WITH_STYLES;
22509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            req.hintMaxLines = 10;
22519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            req.hintMaxChars = 10000;
2252ba4d93fcd76fdd7c8368e23c7faf9a20684e51a0Amith Yamasani            InputConnection ic = getCurrentInputConnection();
2253ba4d93fcd76fdd7c8368e23c7faf9a20684e51a0Amith Yamasani            mExtractedText = ic == null? null
2254ba4d93fcd76fdd7c8368e23c7faf9a20684e51a0Amith Yamasani                    : ic.getExtractedText(req, InputConnection.GET_EXTRACTED_TEXT_MONITOR);
2255a8b00c8801be8e7bd21ddab64a3cde9b5ff2984aAmith Yamasani            if (mExtractedText == null || ic == null) {
2256a8b00c8801be8e7bd21ddab64a3cde9b5ff2984aAmith Yamasani                Log.e(TAG, "Unexpected null in startExtractingText : mExtractedText = "
2257a8b00c8801be8e7bd21ddab64a3cde9b5ff2984aAmith Yamasani                        + mExtractedText + ", input connection = " + ic);
2258a8b00c8801be8e7bd21ddab64a3cde9b5ff2984aAmith Yamasani            }
22599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final EditorInfo ei = getCurrentInputEditorInfo();
22609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
22629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                eet.startInternalChanges();
2263105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                onUpdateExtractingVisibility(ei);
2264105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                onUpdateExtractingViews(ei);
22659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int inputType = ei.inputType;
22669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((inputType&EditorInfo.TYPE_MASK_CLASS)
22679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        == EditorInfo.TYPE_CLASS_TEXT) {
22689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if ((inputType&EditorInfo.TYPE_TEXT_FLAG_IME_MULTI_LINE) != 0) {
22699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
22709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
22719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
22729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                eet.setInputType(inputType);
22739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                eet.setHint(ei.hintText);
22749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mExtractedText != null) {
22759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    eet.setEnabled(true);
22769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    eet.setExtractedText(mExtractedText);
22779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
22789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    eet.setEnabled(false);
22799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    eet.setText("");
22809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
22819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
22829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                eet.finishInternalChanges();
22839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
22849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (inputChanged) {
22869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                onExtractingInputChanged(ei);
22879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
22889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2290ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2291ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    // TODO: Handle the subtype change event
2292ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
2293ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * Called when the subtype was changed.
2294ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @param newSubtype the subtype which is being changed to.
2295ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
2296ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    protected void onCurrentInputMethodSubtypeChanged(InputMethodSubtype newSubtype) {
2297ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        if (DEBUG) {
2298ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            int nameResId = newSubtype.getNameResId();
22999ef0283bdcd9534cc09ae37eb2b78771b95247b5satok            String mode = newSubtype.getMode();
2300ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            String output = "changeInputMethodSubtype:"
2301ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                + (nameResId == 0 ? "<none>" : getString(nameResId)) + ","
23029ef0283bdcd9534cc09ae37eb2b78771b95247b5satok                + mode + ","
2303ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                + newSubtype.getLocale() + "," + newSubtype.getExtraValue();
2304ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            Log.v(TAG, "--- " + output);
2305ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
2306ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2307ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
23089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
23099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Performs a dump of the InputMethodService's internal state.  Override
23109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to add your own information to the dump.
23119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
23129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
23139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Printer p = new PrintWriterPrinter(fout);
23149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("Input method service state for " + this + ":");
23159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mWindowCreated=" + mWindowCreated
2316105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                + " mWindowAdded=" + mWindowAdded);
2317105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        p.println("  mWindowVisible=" + mWindowVisible
2318105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                + " mWindowWasVisible=" + mWindowWasVisible
2319105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                + " mInShowWindow=" + mInShowWindow);
23209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  Configuration=" + getResources().getConfiguration());
23219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mToken=" + mToken);
23229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mInputBinding=" + mInputBinding);
23239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mInputConnection=" + mInputConnection);
23249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mStartedInputConnection=" + mStartedInputConnection);
23259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mInputStarted=" + mInputStarted
23269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mInputViewStarted=" + mInputViewStarted
23279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mCandidatesViewStarted=" + mCandidatesViewStarted);
23289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputEditorInfo != null) {
23309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mInputEditorInfo:");
23319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputEditorInfo.dump(p, "    ");
23329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
23339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mInputEditorInfo: null");
23349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mShowInputRequested=" + mShowInputRequested
23379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mLastShowInputRequested=" + mLastShowInputRequested
23389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mShowInputForced=" + mShowInputForced
23399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags));
23409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mCandidatesVisibility=" + mCandidatesVisibility
23419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mFullscreenApplied=" + mFullscreenApplied
2342105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                + " mIsFullscreen=" + mIsFullscreen
2343105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                + " mExtractViewHidden=" + mExtractViewHidden);
23449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mExtractedText != null) {
23469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mExtractedText:");
23479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("    text=" + mExtractedText.text.length() + " chars"
23489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " startOffset=" + mExtractedText.startOffset);
23499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("    selectionStart=" + mExtractedText.selectionStart
23509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " selectionEnd=" + mExtractedText.selectionEnd
23519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " flags=0x" + Integer.toHexString(mExtractedText.flags));
23529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
23539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mExtractedText: null");
23549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mExtractedToken=" + mExtractedToken);
23569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mIsInputViewShown=" + mIsInputViewShown
23579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mStatusIcon=" + mStatusIcon);
23589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("Last computed insets:");
23599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  contentTopInsets=" + mTmpInsets.contentTopInsets
23609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " visibleTopInsets=" + mTmpInsets.visibleTopInsets
2361fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown                + " touchableInsets=" + mTmpInsets.touchableInsets
2362fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown                + " touchableRegion=" + mTmpInsets.touchableRegion);
23639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2365