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
227b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawaimport android.annotation.CallSuper;
237b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbyeimport android.annotation.DrawableRes;
247b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawaimport android.annotation.IntDef;
257b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawaimport android.annotation.MainThread;
26836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackbornimport android.app.ActivityManager;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.Dialog;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Configuration;
30d922ae01ca99a2b6d39a9393f86776a1d10ebd14Dianne Hackbornimport android.content.res.Resources;
31105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.content.res.TypedArray;
327b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawaimport android.database.ContentObserver;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect;
34fbf097732137a32930d151f7ba6816a5b870c32aJeff Brownimport android.graphics.Region;
357b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawaimport android.net.Uri;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
377b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawaimport android.os.Handler;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
394df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Projectimport android.os.ResultReceiver;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.InputType;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Layout;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Spannable;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.method.MovementMethod;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.PrintWriterPrinter;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Printer;
49e30e02f5d9a9141c9ee70c712d4f9d52c88ea969Dianne Hackbornimport android.view.Gravity;
506b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownimport android.view.KeyCharacterMap;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MotionEvent;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewTreeObserver;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Window;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager;
59e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautnerimport android.view.WindowManager.BadTokenException;
60105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.view.animation.AnimationUtils;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.CompletionInfo;
62c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawaimport android.view.inputmethod.CursorAnchorInfo;
638cbb4c6e30cff706a243599634aeb8fd9a818d92Gilles Debunneimport android.view.inputmethod.EditorInfo;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.ExtractedText;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.ExtractedTextRequest;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputBinding;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputConnection;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethod;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethodManager;
70ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.view.inputmethod.InputMethodSubtype;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.FrameLayout;
7291eb2651a06633353592d52c3e37579f01b020eeMark Renoufimport android.widget.ImageButton;
73105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.widget.LinearLayout;
7491eb2651a06633353592d52c3e37579f01b020eeMark Renoufimport android.widget.TextView;
75105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
787b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawaimport java.lang.annotation.Retention;
797b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawaimport java.lang.annotation.RetentionPolicy;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * InputMethodService provides a standard implementation of an InputMethod,
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * which final implementations can derive from and customize.  See the
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * base class {@link AbstractInputMethodService} and the {@link InputMethod}
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * interface for more information on the basics of writing input methods.
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>In addition to the normal Service lifecycle methods, this class
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * introduces some new specific callbacks that most subclasses will want
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to make use of:</p>
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> {@link #onInitializeInterface()} for user-interface initialization,
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in particular to deal with configuration changes while the service is
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * running.
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> {@link #onBindInput} to find out about switching to a new client.
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> {@link #onStartInput} to deal with an input session starting with
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the client.
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> {@link #onCreateInputView()}, {@link #onCreateCandidatesView()},
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and {@link #onCreateExtractTextView()} for non-demand generation of the UI.
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> {@link #onStartInputView(EditorInfo, boolean)} to deal with input
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * starting within the input area of the IME.
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>An input method has significant discretion in how it goes about its
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * work: the {@link android.inputmethodservice.InputMethodService} provides
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a basic framework for standard UI elements (input view, candidates view,
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and running in fullscreen mode), but it is up to a particular implementor
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to decide how to use them.  For example, one input method could implement
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * an input area with a keyboard, another could allow the user to draw text,
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * while a third could have no input area (and thus not be visible to the
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * user) but instead listen to audio and perform text to speech conversion.</p>
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>In the implementation provided here, all of these elements are placed
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * together in a single window managed by the InputMethodService.  It will
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * execute callbacks as it needs information about them, and provides APIs for
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * programmatic control over them.  They layout of these elements is explicitly
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * defined:</p>
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>The soft input view, if available, is placed at the bottom of the
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * screen.
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>The candidates view, if currently shown, is placed above the soft
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * input view.
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>If not running fullscreen, the application is moved or resized to be
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * above these views; if running fullscreen, the window will completely cover
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the application and its top part will contain the extract text of what is
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * currently being edited by the application.
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="SoftInputView"></a>
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Soft Input View</h3>
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Central to most input methods is the soft input view.  This is where most
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * user interaction occurs: pressing on soft keys, drawing characters, or
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * however else your input method wants to generate text.  Most implementations
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will simply have their own view doing all of this work, and return a new
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * instance of it when {@link #onCreateInputView()} is called.  At that point,
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as long as the input view is visible, you will see user interaction in
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that view and can call back on the InputMethodService to interact with the
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * application as appropriate.</p>
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>There are some situations where you want to decide whether or not your
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * soft input view should be shown to the user.  This is done by implementing
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the {@link #onEvaluateInputViewShown()} to return true or false based on
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * whether it should be shown in the current environment.  If any of your
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * state has changed that may impact this, call
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #updateInputViewShown()} to have it re-evaluated.  The default
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * implementation always shows the input view unless there is a hard
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * keyboard available, which is the appropriate behavior for most input
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * methods.</p>
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="CandidatesView"></a>
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Candidates View</h3>
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Often while the user is generating raw text, an input method wants to
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provide them with a list of possible interpretations of that text that can
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be selected for use.  This is accomplished with the candidates view, and
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * like the soft input view you implement {@link #onCreateCandidatesView()}
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to instantiate your own view implementing your candidates UI.</p>
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Management of the candidates view is a little different than the input
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * view, because the candidates view tends to be more transient, being shown
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * only when there are possible candidates for the current text being entered
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by the user.  To control whether the candidates view is shown, you use
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #setCandidatesViewShown(boolean)}.  Note that because the candidate
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * view tends to be shown and hidden a lot, it does not impact the application
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * UI in the same way as the soft input view: it will never cause application
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * windows to resize, only cause them to be panned if needed for the user to
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * see the current focus.</p>
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="FullscreenMode"></a>
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Fullscreen Mode</h3>
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Sometimes your input method UI is too large to integrate with the
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * application UI, so you just want to take over the screen.  This is
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * accomplished by switching to full-screen mode, causing the input method
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * window to fill the entire screen and add its own "extracted text" editor
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * showing the user the text that is being typed.  Unlike the other UI elements,
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * there is a standard implementation for the extract editor that you should
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not need to change.  The editor is placed at the top of the IME, above the
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * input and candidates views.</p>
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Similar to the input view, you control whether the IME is running in
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * fullscreen mode by implementing {@link #onEvaluateFullscreenMode()}
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to return true or false based on
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * whether it should be fullscreen in the current environment.  If any of your
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * state has changed that may impact this, call
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #updateFullscreenMode()} to have it re-evaluated.  The default
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * implementation selects fullscreen mode when the screen is in a landscape
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * orientation, which is appropriate behavior for most input methods that have
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a significant input area.</p>
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>When in fullscreen mode, you have some special requirements because the
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * user can not see the application UI.  In particular, you should implement
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #onDisplayCompletions(CompletionInfo[])} to show completions
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * generated by your application, typically in your candidates view like you
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * would normally show candidates.
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="GeneratingText"></a>
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Generating Text</h3>
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The key part of an IME is of course generating text for the application.
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is done through calls to the
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.inputmethod.InputConnection} interface to the
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * application, which can be retrieved from {@link #getCurrentInputConnection()}.
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This interface allows you to generate raw key events or, if the target
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * supports it, directly edit in strings of candidates and committed text.</p>
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Information about what the target is expected and supports can be found
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * through the {@link android.view.inputmethod.EditorInfo} class, which is
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * retrieved with {@link #getCurrentInputEditorInfo()} method.  The most
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * important part of this is {@link android.view.inputmethod.EditorInfo#inputType
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * EditorInfo.inputType}; in particular, if this is
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.inputmethod.EditorInfo#TYPE_NULL EditorInfo.TYPE_NULL},
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * then the target does not support complex edits and you need to only deliver
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * raw key events to it.  An input method will also want to look at other
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * values here, to for example detect password mode, auto complete text views,
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * phone number entry, etc.</p>
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>When the user switches between input targets, you will receive calls to
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #onFinishInput()} and {@link #onStartInput(EditorInfo, boolean)}.
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You can use these to reset and initialize your input state for the current
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * target.  For example, you will often want to clear any input state, and
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * update a soft keyboard to be appropriate for the new inputType.</p>
228105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project *
229105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @attr ref android.R.styleable#InputMethodService_imeFullscreenBackground
230105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @attr ref android.R.styleable#InputMethodService_imeExtractEnterAnimation
231105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @attr ref android.R.styleable#InputMethodService_imeExtractExitAnimation
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class InputMethodService extends AbstractInputMethodService {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final String TAG = "InputMethodService";
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG = false;
236857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
237857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    /**
238857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     * The back button will close the input window.
239857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     */
240857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public static final int BACK_DISPOSITION_DEFAULT = 0;  // based on window
241857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
242857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    /**
243857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     * This input method will not consume the back key.
244857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     */
245857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public static final int BACK_DISPOSITION_WILL_NOT_DISMISS = 1; // back
246857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
247857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    /**
248857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     * This input method will consume the back key.
249857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     */
250857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public static final int BACK_DISPOSITION_WILL_DISMISS = 2; // down
251857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
252857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    /**
253857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     * @hide
254857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     * The IME is active.  It may or may not be visible.
255857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     */
256857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public static final int IME_ACTIVE = 0x1;
257857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
258857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    /**
259857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     * @hide
260857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     * The IME is visible.
261857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato     */
262857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public static final int IME_VISIBLE = 0x2;
263857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    InputMethodManager mImm;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
266d922ae01ca99a2b6d39a9393f86776a1d10ebd14Dianne Hackborn    int mTheme = 0;
267836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn    boolean mHardwareAccelerated = false;
268105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LayoutInflater mInflater;
270105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    TypedArray mThemeAttrs;
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    View mRootView;
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SoftInputWindow mWindow;
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mInitialized;
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mWindowCreated;
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mWindowAdded;
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mWindowVisible;
277105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    boolean mWindowWasVisible;
278105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    boolean mInShowWindow;
279105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    ViewGroup mFullscreenArea;
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FrameLayout mExtractFrame;
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FrameLayout mCandidatesFrame;
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FrameLayout mInputFrame;
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IBinder mToken;
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    InputBinding mInputBinding;
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    InputConnection mInputConnection;
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mInputStarted;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mInputViewStarted;
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mCandidatesViewStarted;
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    InputConnection mStartedInputConnection;
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    EditorInfo mInputEditorInfo;
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mShowInputFlags;
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowInputRequested;
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mLastShowInputRequested;
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mCandidatesVisibility;
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    CompletionInfo[] mCurCompletions;
299ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mFullscreenApplied;
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mIsFullscreen;
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    View mExtractView;
303105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    boolean mExtractViewHidden;
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ExtractEditText mExtractEditText;
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ViewGroup mExtractAccessories;
30691eb2651a06633353592d52c3e37579f01b020eeMark Renouf    View mExtractAction;
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ExtractedText mExtractedText;
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mExtractedToken;
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    View mInputView;
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mIsInputViewShown;
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mStatusIcon;
314857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    int mBackDisposition;
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3162977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa    /**
3172977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa     * {@code true} when the previous IME had non-empty inset at the bottom of the screen and we
3182977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa     * have not shown our own window yet.  In this situation, the previous inset continues to be
3192977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa     * shown as an empty region until it is explicitly updated. Basically we can trigger the update
3202977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa     * by calling 1) {@code mWindow.show()} or 2) {@link #clearInsetOfPreviousIme()}.
3212977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa     */
3222977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa    boolean mShouldClearInsetOfPreviousIme;
3232977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Insets mTmpInsets = new Insets();
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final int[] mTmpLocation = new int[2];
326ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer =
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            new ViewTreeObserver.OnComputeInternalInsetsListener() {
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
330105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (isExtractViewShown()) {
331105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                // In true fullscreen mode, we just say the window isn't covering
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // any content so we don't impact whatever is behind.
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                View decor = getWindow().getWindow().getDecorView();
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.contentInsets.top = info.visibleInsets.top
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        = decor.getHeight();
336fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown                info.touchableRegion.setEmpty();
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                onComputeInsets(mTmpInsets);
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.contentInsets.top = mTmpInsets.contentTopInsets;
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.visibleInsets.top = mTmpInsets.visibleTopInsets;
342fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown                info.touchableRegion.set(mTmpInsets.touchableRegion);
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.setTouchableInsets(mTmpInsets.touchableInsets);
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final View.OnClickListener mActionClickListener = new View.OnClickListener() {
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onClick(View v) {
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final EditorInfo ei = getCurrentInputEditorInfo();
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final InputConnection ic = getCurrentInputConnection();
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ei != null && ic != null) {
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (ei.actionId != 0) {
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ic.performEditorAction(ei.actionId);
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if ((ei.imeOptions&EditorInfo.IME_MASK_ACTION)
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        != EditorInfo.IME_ACTION_NONE) {
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ic.performEditorAction(ei.imeOptions&EditorInfo.IME_MASK_ACTION);
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Concrete implementation of
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link AbstractInputMethodService.AbstractInputMethodImpl} that provides
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * all of the standard behavior for an input method.
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public class InputMethodImpl extends AbstractInputMethodImpl {
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Take care of attaching the given window token provided by the system.
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void attachToken(IBinder token) {
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mToken == null) {
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mToken = token;
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mWindow.setToken(token);
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Handle a new input binding, calling
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * {@link InputMethodService#onBindInput InputMethodService.onBindInput()}
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * when done.
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void bindInput(InputBinding binding) {
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputBinding = binding;
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputConnection = binding.getConnection();
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "bindInput(): binding=" + binding
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " ic=" + mInputConnection);
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputConnection ic = getCurrentInputConnection();
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ic != null) ic.reportFullscreenMode(mIsFullscreen);
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            initialize();
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onBindInput();
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Clear the current input binding.
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void unbindInput() {
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "unbindInput(): binding=" + mInputBinding
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " ic=" + mInputConnection);
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onUnbindInput();
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputBinding = null;
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputConnection = null;
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void startInput(InputConnection ic, EditorInfo attribute) {
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "startInput(): editor=" + attribute);
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            doStartInput(ic, attribute, false);
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void restartInput(InputConnection ic, EditorInfo attribute) {
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "restartInput(): editor=" + attribute);
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            doStartInput(ic, attribute, true);
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 hide the soft input area.
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4194df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        public void hideSoftInput(int flags, ResultReceiver resultReceiver) {
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "hideSoftInput()");
4214df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            boolean wasVis = isInputViewShown();
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowInputFlags = 0;
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowInputRequested = false;
4242f913d951c481edccbefa4d321a76f28740b48d7satok            doHideWindow();
4252977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa            clearInsetOfPreviousIme();
4264df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            if (resultReceiver != null) {
4274df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                resultReceiver.send(wasVis != isInputViewShown()
4284df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        ? InputMethodManager.RESULT_HIDDEN
4294df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        : (wasVis ? InputMethodManager.RESULT_UNCHANGED_SHOWN
4304df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null);
4314df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Handle a request by the system to show the soft input area.
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4374df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        public void showSoftInput(int flags, ResultReceiver resultReceiver) {
438e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Log.v(TAG, "showSoftInput()");
4394df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            boolean wasVis = isInputViewShown();
440ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa            if (dispatchOnShowInputRequested(flags, false)) {
441e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                try {
442e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    showWindow(true);
443e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                } catch (BadTokenException e) {
4446fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa                    // We have ignored BadTokenException here since Jelly Bean MR-2 (API Level 18).
4456fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa                    // We could ignore BadTokenException in InputMethodService#showWindow() instead,
4466fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa                    // but it may break assumptions for those who override #showWindow() that we can
4476fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa                    // detect errors in #showWindow() by checking BadTokenException.
4486fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa                    // TODO: Investigate its feasibility.  Update JavaDoc of #showWindow() of
4496fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa                    // whether it's OK to override #showWindow() or not.
450e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                }
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4522977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa            clearInsetOfPreviousIme();
453865b97761cc58053f45a8b06b531d60d8e482c3asatok            // If user uses hard keyboard, IME button should always be shown.
454217fd2903d09d40cabcdade9f2a162dc6513f800jungheang.lee            boolean showing = isInputViewShown();
455857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato            mImm.setImeWindowStatus(mToken, IME_ACTIVE | (showing ? IME_VISIBLE : 0),
456857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato                    mBackDisposition);
4574df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            if (resultReceiver != null) {
4584df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                resultReceiver.send(wasVis != isInputViewShown()
4594df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        ? InputMethodManager.RESULT_SHOWN
4604df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        : (wasVis ? InputMethodManager.RESULT_UNCHANGED_SHOWN
4614df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null);
4624df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
464ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
465ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        public void changeInputMethodSubtype(InputMethodSubtype subtype) {
466ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            onCurrentInputMethodSubtypeChanged(subtype);
467ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
469ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Concrete implementation of
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link AbstractInputMethodService.AbstractInputMethodSessionImpl} that provides
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * all of the standard behavior for an input method session.
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public class InputMethodSessionImpl extends AbstractInputMethodSessionImpl {
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void finishInput() {
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!isEnabled()) {
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "finishInput() in " + this);
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            doFinishInput();
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Call {@link InputMethodService#onDisplayCompletions
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * InputMethodService.onDisplayCompletions()}.
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void displayCompletions(CompletionInfo[] completions) {
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!isEnabled()) {
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurCompletions = completions;
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onDisplayCompletions(completions);
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Call {@link InputMethodService#onUpdateExtractedText
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * InputMethodService.onUpdateExtractedText()}.
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void updateExtractedText(int token, ExtractedText text) {
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!isEnabled()) {
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onUpdateExtractedText(token, text);
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Call {@link InputMethodService#onUpdateSelection
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * InputMethodService.onUpdateSelection()}.
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void updateSelection(int oldSelStart, int oldSelEnd,
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int newSelStart, int newSelEnd,
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int candidatesStart, int candidatesEnd) {
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!isEnabled()) {
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputMethodService.this.onUpdateSelection(oldSelStart, oldSelEnd,
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    newSelStart, newSelEnd, candidatesStart, candidatesEnd);
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
520863fcd62171e55bc9f2105d9fb5877df982454d8satok
521863fcd62171e55bc9f2105d9fb5877df982454d8satok        @Override
522863fcd62171e55bc9f2105d9fb5877df982454d8satok        public void viewClicked(boolean focusChanged) {
523863fcd62171e55bc9f2105d9fb5877df982454d8satok            if (!isEnabled()) {
524863fcd62171e55bc9f2105d9fb5877df982454d8satok                return;
525863fcd62171e55bc9f2105d9fb5877df982454d8satok            }
526863fcd62171e55bc9f2105d9fb5877df982454d8satok            InputMethodService.this.onViewClicked(focusChanged);
527863fcd62171e55bc9f2105d9fb5877df982454d8satok        }
528863fcd62171e55bc9f2105d9fb5877df982454d8satok
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Call {@link InputMethodService#onUpdateCursor
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * InputMethodService.onUpdateCursor()}.
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void updateCursor(Rect newCursor) {
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!isEnabled()) {
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputMethodService.this.onUpdateCursor(newCursor);
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Call {@link InputMethodService#onAppPrivateCommand
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * InputMethodService.onAppPrivateCommand()}.
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void appPrivateCommand(String action, Bundle data) {
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!isEnabled()) {
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputMethodService.this.onAppPrivateCommand(action, data);
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5504df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
5514df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        /**
5524df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project         *
5534df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project         */
5544df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        public void toggleSoftInput(int showFlags, int hideFlags) {
5554df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            InputMethodService.this.onToggleSoftInput(showFlags, hideFlags);
5564df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
557c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
558c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        /**
559c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * Call {@link InputMethodService#onUpdateCursorAnchorInfo
560c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * InputMethodService.onUpdateCursorAnchorInfo()}.
561c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         */
562c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        public void updateCursorAnchorInfo(CursorAnchorInfo info) {
563c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            if (!isEnabled()) {
564c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                return;
565c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            }
566c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            InputMethodService.this.onUpdateCursorAnchorInfo(info);
567c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Information about where interesting parts of the input method UI appear.
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final class Insets {
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This is the top part of the UI that is the main content.  It is
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * used to determine the basic space needed, to resize/pan the
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * application behind.  It is assumed that this inset does not
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * change very much, since any change will cause a full resize/pan
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * of the application behind.  This value is relative to the top edge
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * of the input method window.
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int contentTopInsets;
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This is the top part of the UI that is visibly covering the
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * application behind it.  This provides finer-grained control over
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * visibility, allowing you to change it relatively frequently (such
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * as hiding or showing candidates) without disrupting the underlying
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * UI too much.  For example, this will never resize the application
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * UI, will only pan if needed to make the current focus visible, and
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * will not aggressively move the pan position when this changes unless
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * needed to make the focus visible.  This value is relative to the top edge
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * of the input method window.
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int visibleTopInsets;
596fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
597fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        /**
598fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * This is the region of the UI that is touchable.  It is used when
599fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * {@link #touchableInsets} is set to {@link #TOUCHABLE_INSETS_REGION}.
600fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * The region should be specified relative to the origin of the window frame.
601fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         */
602fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        public final Region touchableRegion = new Region();
603fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Option for {@link #touchableInsets}: the entire window frame
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * can be touched.
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int TOUCHABLE_INSETS_FRAME
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Option for {@link #touchableInsets}: the area inside of
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the content insets can be touched.
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int TOUCHABLE_INSETS_CONTENT
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Option for {@link #touchableInsets}: the area inside of
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the visible insets can be touched.
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int TOUCHABLE_INSETS_VISIBLE
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
624fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
625fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        /**
626fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * Option for {@link #touchableInsets}: the region specified by
627fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * {@link #touchableRegion} can be touched.
628fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         */
629fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        public static final int TOUCHABLE_INSETS_REGION
630fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown                = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
631fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Determine which area of the window is touchable by the user.  May
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * be one of: {@link #TOUCHABLE_INSETS_FRAME},
635fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * {@link #TOUCHABLE_INSETS_CONTENT}, {@link #TOUCHABLE_INSETS_VISIBLE},
636fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * or {@link #TOUCHABLE_INSETS_REGION}.
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int touchableInsets;
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
640865b97761cc58053f45a8b06b531d60d8e482c3asatok
641105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    /**
6427b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa     * A {@link ContentObserver} to monitor {@link Settings.Secure#SHOW_IME_WITH_HARD_KEYBOARD}.
6437b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa     *
6447b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa     * <p>Note that {@link Settings.Secure#SHOW_IME_WITH_HARD_KEYBOARD} is not a public API.
6457b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa     * Basically this functionality still needs to be considered as implementation details.</p>
6467b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa     */
6477b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa    @MainThread
6487b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa    private static final class SettingsObserver extends ContentObserver {
6497b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        @Retention(RetentionPolicy.SOURCE)
6507b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        @IntDef({
6517b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                ShowImeWithHardKeyboardType.UNKNOWN,
6527b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                ShowImeWithHardKeyboardType.FALSE,
6537b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                ShowImeWithHardKeyboardType.TRUE,
6547b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        })
6557b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        private @interface ShowImeWithHardKeyboardType {
6567b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            int UNKNOWN = 0;
6577b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            int FALSE = 1;
6587b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            int TRUE = 2;
6597b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        }
6607b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        @ShowImeWithHardKeyboardType
6617b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        private int mShowImeWithHardKeyboard = ShowImeWithHardKeyboardType.UNKNOWN;
6627b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa
6637b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        private final InputMethodService mService;
6647b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa
6657b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        private SettingsObserver(InputMethodService service) {
6667b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            super(new Handler(service.getMainLooper()));
6677b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            mService = service;
6687b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        }
6697b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa
6707b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        /**
6717b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa         * A factory method that internally enforces two-phase initialization to make sure that the
6727b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa         * object reference will not be escaped until the object is properly constructed.
6737b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa         *
6747b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa         * <p>NOTE: Currently {@link SettingsObserver} is accessed only from main thread.  Hence
6757b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa         * this enforcement of two-phase initialization may be unnecessary at the moment.</p>
6767b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa         *
6777b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa         * @param service {@link InputMethodService} that needs to receive the callback.
6787b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa         * @return {@link SettingsObserver} that is already registered to
6797b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa         * {@link android.content.ContentResolver}. The caller must call
6807b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa         * {@link SettingsObserver#unregister()}.
6817b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa         */
6827b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        public static SettingsObserver createAndRegister(InputMethodService service) {
6837b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            final SettingsObserver observer = new SettingsObserver(service);
6847b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            // The observer is properly constructed. Let's start accepting the event.
6857b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            service.getContentResolver().registerContentObserver(
6867b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                    Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD),
6877b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                    false, observer);
6887b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            return observer;
6897b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        }
6907b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa
6917b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        void unregister() {
6927b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            mService.getContentResolver().unregisterContentObserver(this);
6937b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        }
6947b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa
6957b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        private boolean shouldShowImeWithHardKeyboard() {
6967b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            // Lazily initialize as needed.
6977b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            if (mShowImeWithHardKeyboard == ShowImeWithHardKeyboardType.UNKNOWN) {
6987b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                mShowImeWithHardKeyboard = Settings.Secure.getInt(mService.getContentResolver(),
6997b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                        Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0 ?
7007b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                        ShowImeWithHardKeyboardType.TRUE : ShowImeWithHardKeyboardType.FALSE;
7017b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            }
7027b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            switch (mShowImeWithHardKeyboard) {
7037b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                case ShowImeWithHardKeyboardType.TRUE:
7047b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                    return true;
7057b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                case ShowImeWithHardKeyboardType.FALSE:
7067b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                    return false;
7077b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                default:
7087b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                    Log.e(TAG, "Unexpected mShowImeWithHardKeyboard=" + mShowImeWithHardKeyboard);
7097b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                    return false;
7107b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            }
7117b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        }
7127b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa
7137b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        @Override
7147b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        public void onChange(boolean selfChange, Uri uri) {
7157b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            final Uri showImeWithHardKeyboardUri =
7167b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                    Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
7177b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            if (showImeWithHardKeyboardUri.equals(uri)) {
7187b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                mShowImeWithHardKeyboard = Settings.Secure.getInt(mService.getContentResolver(),
7197b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                        Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0 ?
7207b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa                        ShowImeWithHardKeyboardType.TRUE : ShowImeWithHardKeyboardType.FALSE;
7212dbc53242927a796117a0b70d856021c0d4918a5Yohei Yukawa                // In Android M and prior, state change of
7222dbc53242927a796117a0b70d856021c0d4918a5Yohei Yukawa                // Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD has triggered
7232dbc53242927a796117a0b70d856021c0d4918a5Yohei Yukawa                // #onConfigurationChanged().  For compatibility reasons, we reset the internal
7242dbc53242927a796117a0b70d856021c0d4918a5Yohei Yukawa                // state as if configuration was changed.
7252dbc53242927a796117a0b70d856021c0d4918a5Yohei Yukawa                mService.resetStateForNewConfiguration();
7267b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            }
7277b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        }
7287b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa
7297b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        @Override
7307b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        public String toString() {
7317b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            return "SettingsObserver{mShowImeWithHardKeyboard=" + mShowImeWithHardKeyboard  + "}";
7327b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        }
7337b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa    }
7347b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa    private SettingsObserver mSettingsObserver;
7357b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa
7367b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa    /**
737105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * You can call this to customize the theme used by your IME's window.
738105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * This theme should typically be one that derives from
739105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * {@link android.R.style#Theme_InputMethod}, which is the default theme
740105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * you will get.  This must be set before {@link #onCreate}, so you
741105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * will typically call it in your constructor with the resource ID
742105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * of your custom theme.
743105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     */
744ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    @Override
745105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public void setTheme(int theme) {
746105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mWindow != null) {
747105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            throw new IllegalStateException("Must be called before onCreate()");
748105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
749105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mTheme = theme;
750105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
751865b97761cc58053f45a8b06b531d60d8e482c3asatok
752836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn    /**
753836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     * You can call this to try to enable hardware accelerated drawing for
754836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     * your IME. This must be set before {@link #onCreate}, so you
755836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     * will typically call it in your constructor.  It is not always possible
756e07b595519e68a8ee524b1886dea01475047abecAlan Viverette     * to use hardware accelerated drawing in an IME (for example on low-end
757836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     * devices that do not have the resources to support this), so the call
758836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     * returns true if it succeeds otherwise false if you will need to draw
759836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     * in software.  You must be able to handle either case.
760e07b595519e68a8ee524b1886dea01475047abecAlan Viverette     *
761e07b595519e68a8ee524b1886dea01475047abecAlan Viverette     * @deprecated Starting in API 21, hardware acceleration is always enabled
762e07b595519e68a8ee524b1886dea01475047abecAlan Viverette     *             on capable devices.
763836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn     */
764836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn    public boolean enableHardwareAcceleration() {
765836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn        if (mWindow != null) {
766836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn            throw new IllegalStateException("Must be called before onCreate()");
767836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn        }
76898365d7663cbd82979a5700faf0050220b01084dJeff Brown        if (ActivityManager.isHighEndGfx()) {
769836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn            mHardwareAccelerated = true;
770836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn            return true;
771836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn        }
772836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn        return false;
773836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn    }
774836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn
7755effd7e89f83824ac8982a6cbcebbf5cc331e436Alan Viverette    @Override public void onCreate() {
7765effd7e89f83824ac8982a6cbcebbf5cc331e436Alan Viverette        mTheme = Resources.selectSystemTheme(mTheme,
7775effd7e89f83824ac8982a6cbcebbf5cc331e436Alan Viverette                getApplicationInfo().targetSdkVersion,
7785effd7e89f83824ac8982a6cbcebbf5cc331e436Alan Viverette                android.R.style.Theme_InputMethod,
7795effd7e89f83824ac8982a6cbcebbf5cc331e436Alan Viverette                android.R.style.Theme_Holo_InputMethod,
7805effd7e89f83824ac8982a6cbcebbf5cc331e436Alan Viverette                android.R.style.Theme_DeviceDefault_InputMethod,
7815effd7e89f83824ac8982a6cbcebbf5cc331e436Alan Viverette                android.R.style.Theme_DeviceDefault_InputMethod);
782105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        super.setTheme(mTheme);
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onCreate();
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
7857b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        mSettingsObserver = SettingsObserver.createAndRegister(this);
7862977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa        // If the previous IME has occupied non-empty inset in the screen, we need to decide whether
7872977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa        // we continue to use the same size of the inset or update it
7882977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa        mShouldClearInsetOfPreviousIme = (mImm.getInputMethodWindowVisibleHeight() > 0);
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInflater = (LayoutInflater)getSystemService(
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Context.LAYOUT_INFLATER_SERVICE);
791c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn        mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
792e30e02f5d9a9141c9ee70c712d4f9d52c88ea969Dianne Hackborn                WindowManager.LayoutParams.TYPE_INPUT_METHOD, Gravity.BOTTOM, false);
793836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn        if (mHardwareAccelerated) {
794836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn            mWindow.getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
795836531b0c4985b0cf6ead247dd2f403f3ec59e37Dianne Hackborn        }
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initViews();
797980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy        mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
799ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is a hook that subclasses can use to perform initialization of
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * their interface.  It is called for you prior to any of your UI objects
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * being created, both after the service is first created and after a
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * configuration change happens.
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onInitializeInterface() {
80734703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
809ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void initialize() {
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mInitialized) {
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInitialized = true;
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onInitializeInterface();
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
816ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void initViews() {
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInitialized = false;
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWindowCreated = false;
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowInputRequested = false;
821ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa        mShowInputFlags = 0;
822ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa
823105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mThemeAttrs = obtainStyledAttributes(android.R.styleable.InputMethodService);
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRootView = mInflater.inflate(
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                com.android.internal.R.layout.input_method, null);
826c68d577f29604d205573ee4253704c5b2c5e4f81John Spurlock        mRootView.setSystemUiVisibility(
827c68d577f29604d205573ee4253704c5b2c5e4f81John Spurlock                View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWindow.setContentView(mRootView);
82972745fffe8d43b12ebb753b562191e319e5c1cdaSeonggoo Kang        mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsComputer);
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
8316e2bee75cea415621165698fdd9ce857bbb8872eJeff Sharkey        if (Settings.Global.getInt(getContentResolver(),
8326e2bee75cea415621165698fdd9ce857bbb8872eJeff Sharkey                Settings.Global.FANCY_IME_ANIMATIONS, 0) != 0) {
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWindow.getWindow().setWindowAnimations(
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    com.android.internal.R.style.Animation_InputMethodFancy);
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
836105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mFullscreenArea = (ViewGroup)mRootView.findViewById(com.android.internal.R.id.fullscreenArea);
837105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mExtractViewHidden = false;
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractFrame = (FrameLayout)mRootView.findViewById(android.R.id.extractArea);
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractView = null;
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractEditText = null;
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractAccessories = null;
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractAction = null;
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFullscreenApplied = false;
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesFrame = (FrameLayout)mRootView.findViewById(android.R.id.candidatesArea);
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputFrame = (FrameLayout)mRootView.findViewById(android.R.id.inputArea);
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputView = null;
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsInputViewShown = false;
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractFrame.setVisibility(View.GONE);
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesVisibility = getCandidatesHiddenVisibility();
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesFrame.setVisibility(mCandidatesVisibility);
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputFrame.setVisibility(View.GONE);
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
855ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override public void onDestroy() {
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onDestroy();
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInsetsComputer);
860c56191f82956527acadd525b64ebcc033bc107a3Satoshi Kataoka        doFinishInput();
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mWindowAdded) {
862c0c8765719f5c8d0192aa266c27166bdd8c09a33satok            // Disable exit animation for the current IME window
863c0c8765719f5c8d0192aa266c27166bdd8c09a33satok            // to avoid the race condition between the exit and enter animations
864c0c8765719f5c8d0192aa266c27166bdd8c09a33satok            // when the current IME is being switched to another one.
865c0c8765719f5c8d0192aa266c27166bdd8c09a33satok            mWindow.getWindow().setWindowAnimations(0);
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWindow.dismiss();
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8687b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        if (mSettingsObserver != null) {
8697b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            mSettingsObserver.unregister();
8707b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            mSettingsObserver = null;
8717b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        }
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
873f17db9f5257011d5331d27a6da7d4e6fddde1e08satok
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Take care of handling configuration changes.  Subclasses of
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * InputMethodService generally don't need to deal directly with
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this on their own; the standard implementation here takes care of
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * regenerating the input method UI as a result of the configuration
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * change, so you can rely on your {@link #onCreateInputView} and
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * other methods being called as appropriate due to a configuration change.
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>When a configuration change does happen,
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #onInitializeInterface()} is guaranteed to be called the next
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * time prior to any of the other input or UI creation callbacks.  The
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * following will be called immediately depending if appropriate for current
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * state: {@link #onStartInput} if input is active, and
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #onCreateInputView} and {@link #onStartInputView} and related
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * appropriate functions if the UI is displayed.
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override public void onConfigurationChanged(Configuration newConfig) {
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onConfigurationChanged(newConfig);
8922dbc53242927a796117a0b70d856021c0d4918a5Yohei Yukawa        resetStateForNewConfiguration();
8932dbc53242927a796117a0b70d856021c0d4918a5Yohei Yukawa    }
894ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa
8952dbc53242927a796117a0b70d856021c0d4918a5Yohei Yukawa    private void resetStateForNewConfiguration() {
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean visible = mWindowVisible;
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int showFlags = mShowInputFlags;
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean showingInput = mShowInputRequested;
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CompletionInfo[] completions = mCurCompletions;
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initViews();
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputViewStarted = false;
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesViewStarted = false;
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputStarted) {
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            doStartInput(getCurrentInputConnection(),
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    getCurrentInputEditorInfo(), true);
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (visible) {
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showingInput) {
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If we were last showing the soft keyboard, try to do so again.
910ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa                if (dispatchOnShowInputRequested(showFlags, true)) {
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    showWindow(true);
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (completions != null) {
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mCurCompletions = completions;
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        onDisplayCompletions(completions);
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
9172f913d951c481edccbefa4d321a76f28740b48d7satok                    doHideWindow();
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (mCandidatesVisibility == View.VISIBLE) {
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If the candidates are currently visible, make sure the
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // window is shown for them.
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                showWindow(false);
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Otherwise hide the window.
9252f913d951c481edccbefa4d321a76f28740b48d7satok                doHideWindow();
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
927865b97761cc58053f45a8b06b531d60d8e482c3asatok            // If user uses hard keyboard, IME button should always be shown.
928857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato            boolean showing = onEvaluateInputViewShown();
929857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato            mImm.setImeWindowStatus(mToken, IME_ACTIVE | (showing ? IME_VISIBLE : 0),
930857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato                    mBackDisposition);
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Implement to return our standard {@link InputMethodImpl}.  Subclasses
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can override to provide their own customized version.
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
938ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    @Override
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public AbstractInputMethodImpl onCreateInputMethodInterface() {
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new InputMethodImpl();
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Implement to return our standard {@link InputMethodSessionImpl}.  Subclasses
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can override to provide their own customized version.
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
947ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    @Override
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface() {
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new InputMethodSessionImpl();
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public LayoutInflater getLayoutInflater() {
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInflater;
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Dialog getWindow() {
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mWindow;
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
960857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public void setBackDisposition(int disposition) {
961857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato        mBackDisposition = disposition;
962857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    }
963857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
964857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public int getBackDisposition() {
965857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato        return mBackDisposition;
966857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    }
967857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the maximum width, in pixels, available the input method.
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Input methods are positioned at the bottom of the screen and, unless
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * running in fullscreen, will generally want to be as short as possible
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * so should compute their height based on their contents.  However, they
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can stretch as much as needed horizontally.  The function returns to
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * you the maximum amount of space available horizontally, which you can
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * use if needed for UI placement.
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>In many cases this is not needed, you can just rely on the normal
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * view layout mechanisms to position your views within the full horizontal
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * space given to the input method.
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Note that this value can change dynamically, in particular when the
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * screen orientation changes.
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getMaxWidth() {
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return wm.getDefaultDisplay().getWidth();
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the currently active InputBinding for the input method, or
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * null if there is none.
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public InputBinding getCurrentInputBinding() {
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInputBinding;
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Retrieve the currently active InputConnection that is bound to
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the input method, or null if there is none.
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public InputConnection getCurrentInputConnection() {
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputConnection ic = mStartedInputConnection;
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ic != null) {
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ic;
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInputConnection;
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getCurrentInputStarted() {
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInputStarted;
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public EditorInfo getCurrentInputEditorInfo() {
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInputEditorInfo;
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Re-evaluate whether the input method should be running in fullscreen
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * mode, and update its UI if this has changed since the last time it
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * was evaluated.  This will call {@link #onEvaluateFullscreenMode()} to
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * determine whether it should currently run in fullscreen mode.  You
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can use {@link #isFullscreenMode()} to determine if the input method
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is currently running in fullscreen mode.
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateFullscreenMode() {
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isFullscreen = mShowInputRequested && onEvaluateFullscreenMode();
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean changed = mLastShowInputRequested != mShowInputRequested;
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mIsFullscreen != isFullscreen || !mFullscreenApplied) {
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            changed = true;
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIsFullscreen = isFullscreen;
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputConnection ic = getCurrentInputConnection();
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ic != null) ic.reportFullscreenMode(isFullscreen);
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFullscreenApplied = true;
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            initialize();
1035105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
1036105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    mFullscreenArea.getLayoutParams();
1037105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (isFullscreen) {
1038105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mFullscreenArea.setBackgroundDrawable(mThemeAttrs.getDrawable(
1039105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        com.android.internal.R.styleable.InputMethodService_imeFullscreenBackground));
1040105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                lp.height = 0;
1041105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                lp.weight = 1;
1042105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            } else {
1043105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mFullscreenArea.setBackgroundDrawable(null);
1044105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                lp.height = LinearLayout.LayoutParams.WRAP_CONTENT;
1045105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                lp.weight = 0;
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1047105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            ((ViewGroup)mFullscreenArea.getParent()).updateViewLayout(
1048105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    mFullscreenArea, lp);
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isFullscreen) {
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mExtractView == null) {
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    View v = onCreateExtractTextView();
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (v != null) {
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        setExtractView(v);
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                startExtractingText(false);
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1058105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            updateExtractFrameVisibility();
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (changed) {
106234703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne            onConfigureWindow(mWindow.getWindow(), isFullscreen, !mShowInputRequested);
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastShowInputRequested = mShowInputRequested;
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Update the given window's parameters for the given mode.  This is called
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the window is first displayed and each time the fullscreen or
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * candidates only mode changes.
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default implementation makes the layout for the window
1073980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy     * MATCH_PARENT x MATCH_PARENT when in fullscreen mode, and
1074980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy     * MATCH_PARENT x WRAP_CONTENT when in non-fullscreen mode.
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param win The input method's window.
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param isFullscreen If true, the window is running in fullscreen mode
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and intended to cover the entire application display.
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param isCandidatesOnly If true, the window is only showing the
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * candidates view and none of the rest of its UI.  This is mutually
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * exclusive with fullscreen mode.
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onConfigureWindow(Window win, boolean isFullscreen,
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean isCandidatesOnly) {
10858b117c85781be106f16a1fecc73d6928e54a985bSatoshi Kataoka        final int currentHeight = mWindow.getWindow().getAttributes().height;
10868b117c85781be106f16a1fecc73d6928e54a985bSatoshi Kataoka        final int newHeight = isFullscreen ? MATCH_PARENT : WRAP_CONTENT;
10878b117c85781be106f16a1fecc73d6928e54a985bSatoshi Kataoka        if (mIsInputViewShown && currentHeight != newHeight) {
10888b117c85781be106f16a1fecc73d6928e54a985bSatoshi Kataoka            Log.w(TAG, "Window size has been changed. This may cause jankiness of resizing window: "
10898b117c85781be106f16a1fecc73d6928e54a985bSatoshi Kataoka                    + currentHeight + " -> " + newHeight);
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10918b117c85781be106f16a1fecc73d6928e54a985bSatoshi Kataoka        mWindow.getWindow().setLayout(MATCH_PARENT, newHeight);
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return whether the input method is <em>currently</em> running in
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * fullscreen mode.  This is the mode that was last determined and
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * applied by {@link #updateFullscreenMode()}.
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isFullscreenMode() {
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mIsFullscreen;
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Override this to control when the input method should run in
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * fullscreen mode.  The default implementation runs in fullsceen only
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the screen is in landscape mode.  If you change what
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this returns, you will need to call {@link #updateFullscreenMode()}
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * yourself whenever the returned value may have changed to have it
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * re-evaluated and applied.
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onEvaluateFullscreenMode() {
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Configuration config = getResources().getConfiguration();
11132edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins        if (config.orientation != Configuration.ORIENTATION_LANDSCAPE) {
11142edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins            return false;
11152edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins        }
11162edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins        if (mInputEditorInfo != null
11172edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins                && (mInputEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_FULLSCREEN) != 0) {
11182edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins            return false;
11192edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins        }
11202edd68260f26cbd6eddd0df16404bb6bcb22b3b6Leon Scroggins        return true;
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
112234703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1124105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * Controls the visibility of the extracted text area.  This only applies
1125105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * when the input method is in fullscreen mode, and thus showing extracted
1126105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * text.  When false, the extracted text will not be shown, allowing some
1127105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * of the application to be seen behind.  This is normally set for you
1128105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * by {@link #onUpdateExtractingVisibility}.  This controls the visibility
1129105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * of both the extracted text and candidate view; the latter since it is
1130105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * not useful if there is no text to see.
1131105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     */
1132105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public void setExtractViewShown(boolean shown) {
1133105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mExtractViewHidden == shown) {
1134105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mExtractViewHidden = !shown;
1135105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            updateExtractFrameVisibility();
1136105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1137105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
1138105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1139105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    /**
1140105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * Return whether the fullscreen extract view is shown.  This will only
1141105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * return true if {@link #isFullscreenMode()} returns true, and in that
1142105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * case its value depends on the last call to
1143105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * {@link #setExtractViewShown(boolean)}.  This effectively lets you
1144105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * determine if the application window is entirely covered (when this
1145105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * returns true) or if some part of it may be shown (if this returns
1146105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * false, though if {@link #isFullscreenMode()} returns true in that case
1147105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * then it is probably only a sliver of the application).
1148105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     */
1149105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public boolean isExtractViewShown() {
1150105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        return mIsFullscreen && !mExtractViewHidden;
1151105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
1152105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1153105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    void updateExtractFrameVisibility() {
11548b117c85781be106f16a1fecc73d6928e54a985bSatoshi Kataoka        final int vis;
1155105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (isFullscreenMode()) {
1156105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            vis = mExtractViewHidden ? View.INVISIBLE : View.VISIBLE;
11578b117c85781be106f16a1fecc73d6928e54a985bSatoshi Kataoka            // "vis" should be applied for the extract frame as well in the fullscreen mode.
11588b117c85781be106f16a1fecc73d6928e54a985bSatoshi Kataoka            mExtractFrame.setVisibility(vis);
1159105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        } else {
1160105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            vis = View.VISIBLE;
1161105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mExtractFrame.setVisibility(View.GONE);
1162105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1163105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        updateCandidatesVisibility(mCandidatesVisibility == View.VISIBLE);
1164105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mWindowWasVisible && mFullscreenArea.getVisibility() != vis) {
1165105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            int animRes = mThemeAttrs.getResourceId(vis == View.VISIBLE
1166105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    ? com.android.internal.R.styleable.InputMethodService_imeExtractEnterAnimation
1167105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    : com.android.internal.R.styleable.InputMethodService_imeExtractExitAnimation,
1168105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    0);
1169105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (animRes != 0) {
1170105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mFullscreenArea.startAnimation(AnimationUtils.loadAnimation(
1171105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        this, animRes));
1172105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
1173105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1174105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mFullscreenArea.setVisibility(vis);
1175105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
1176105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1177105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    /**
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Compute the interesting insets into your UI.  The default implementation
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * uses the top of the candidates frame for the visible insets, and the
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * top of the input frame for the content insets.  The default touchable
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * insets are {@link Insets#TOUCHABLE_INSETS_VISIBLE}.
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1183105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * <p>Note that this method is not called when
1184105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * {@link #isExtractViewShown} returns true, since
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in that case the application is left as-is behind the input method and
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not impacted by anything in its UI.
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param outInsets Fill in with the current UI insets.
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onComputeInsets(Insets outInsets) {
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int[] loc = mTmpLocation;
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputFrame.getVisibility() == View.VISIBLE) {
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputFrame.getLocationInWindow(loc);
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1195105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            View decor = getWindow().getWindow().getDecorView();
1196105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            loc[1] = decor.getHeight();
1197105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1198105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (isFullscreenMode()) {
1199105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            // In fullscreen mode, we never resize the underlying window.
1200105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            View decor = getWindow().getWindow().getDecorView();
1201105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            outInsets.contentTopInsets = decor.getHeight();
1202105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        } else {
1203105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            outInsets.contentTopInsets = loc[1];
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCandidatesFrame.getVisibility() == View.VISIBLE) {
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCandidatesFrame.getLocationInWindow(loc);
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        outInsets.visibleTopInsets = loc[1];
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_VISIBLE;
1210fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        outInsets.touchableRegion.setEmpty();
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Re-evaluate whether the soft input area should currently be shown, and
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * update its UI if this has changed since the last time it
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * was evaluated.  This will call {@link #onEvaluateInputViewShown()} to
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * determine whether the input view should currently be shown.  You
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can use {@link #isInputViewShown()} to determine if the input view
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is currently shown.
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateInputViewShown() {
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isShown = mShowInputRequested && onEvaluateInputViewShown();
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mIsInputViewShown != isShown && mWindowVisible) {
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIsInputViewShown = isShown;
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputFrame.setVisibility(isShown ? View.VISIBLE : View.GONE);
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mInputView == null) {
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                initialize();
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                View v = onCreateInputView();
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (v != null) {
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setInputView(v);
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if we have been asked to show our input view.
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShowInputRequested() {
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mShowInputRequested;
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return whether the soft input view is <em>currently</em> shown to the
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * user.  This is the state that was last determined and
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * applied by {@link #updateInputViewShown()}.
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isInputViewShown() {
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mIsInputViewShown && mWindowVisible;
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12517b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12537b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa     * Override this to control when the soft input area should be shown to the user.  The default
12547b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa     * implementation returns {@code false} when there is no hard keyboard or the keyboard is hidden
12557b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa     * unless the user shows an intention to use software keyboard.  If you change what this
12567b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa     * returns, you will need to call {@link #updateInputViewShown()} yourself whenever the returned
12577b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa     * value may have changed to have it re-evaluated and applied.
12587b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa     *
12597b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa     * <p>When you override this method, it is recommended to call
12607b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa     * {@code super.onEvaluateInputViewShown()} and return {@code true} when {@code true} is
12617b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa     * returned.</p>
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12637b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa    @CallSuper
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onEvaluateInputViewShown() {
1265cf8403bc36395eecd9ab03c6b5e128272c3592e9Yohei Yukawa        if (mSettingsObserver == null) {
1266cf8403bc36395eecd9ab03c6b5e128272c3592e9Yohei Yukawa            Log.w(TAG, "onEvaluateInputViewShown: mSettingsObserver must not be null here.");
1267cf8403bc36395eecd9ab03c6b5e128272c3592e9Yohei Yukawa            return false;
1268cf8403bc36395eecd9ab03c6b5e128272c3592e9Yohei Yukawa        }
12697b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        if (mSettingsObserver.shouldShowImeWithHardKeyboard()) {
12707b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa            return true;
12717b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        }
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Configuration config = getResources().getConfiguration();
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return config.keyboard == Configuration.KEYBOARD_NOKEYS
12748710e76a897cd546a79ee4338a4147eeb9f3e068Ken Wakasa                || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES;
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12767b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Controls the visibility of the candidates display area.  By default
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * it is hidden.
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setCandidatesViewShown(boolean shown) {
1282105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        updateCandidatesVisibility(shown);
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mShowInputRequested && mWindowVisible != shown) {
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If we are being asked to show the candidates view while the app
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // has not asked for the input view to be shown, then we need
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // to update whether the window is shown.
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (shown) {
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                showWindow(false);
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
12902f913d951c481edccbefa4d321a76f28740b48d7satok                doHideWindow();
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1295105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    void updateCandidatesVisibility(boolean shown) {
1296105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        int vis = shown ? View.VISIBLE : getCandidatesHiddenVisibility();
1297105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mCandidatesVisibility != vis) {
1298105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mCandidatesFrame.setVisibility(vis);
1299105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mCandidatesVisibility = vis;
1300105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1301105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
1302105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the visibility mode (either {@link View#INVISIBLE View.INVISIBLE}
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or {@link View#GONE View.GONE}) of the candidates view when it is not
1306105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * shown.  The default implementation returns GONE when
1307105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * {@link #isExtractViewShown} returns true,
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise VISIBLE.  Be careful if you change this to return GONE in
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * other situations -- if showing or hiding the candidates view causes
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * your window to resize, this can cause temporary drawing artifacts as
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the resize takes place.
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getCandidatesHiddenVisibility() {
1314105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        return isExtractViewShown() ? View.GONE : View.INVISIBLE;
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13177b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbye    public void showStatusIcon(@DrawableRes int iconResId) {
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStatusIcon = iconResId;
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mImm.showStatusIcon(mToken, getPackageName(), iconResId);
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void hideStatusIcon() {
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStatusIcon = 0;
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mImm.hideStatusIcon(mToken);
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Force switch to a new input method, as identified by <var>id</var>.  This
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * input method will be destroyed, and the requested one started on the
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * current input field.
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param id Unique identifier of the new input method ot start.
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void switchInputMethod(String id) {
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mImm.setInputMethod(mToken, id);
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setExtractView(View view) {
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractFrame.removeAllViews();
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractFrame.addView(view, new FrameLayout.LayoutParams(
1341980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                ViewGroup.LayoutParams.MATCH_PARENT,
1342980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                ViewGroup.LayoutParams.MATCH_PARENT));
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtractView = view;
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (view != null) {
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractEditText = (ExtractEditText)view.findViewById(
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    com.android.internal.R.id.inputExtractEditText);
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractEditText.setIME(this);
134891eb2651a06633353592d52c3e37579f01b020eeMark Renouf            mExtractAction = view.findViewById(
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    com.android.internal.R.id.inputExtractAction);
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mExtractAction != null) {
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mExtractAccessories = (ViewGroup)view.findViewById(
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        com.android.internal.R.id.inputExtractAccessories);
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startExtractingText(false);
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractEditText = null;
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractAccessories = null;
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractAction = null;
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Replaces the current candidates view with a new one.  You only need to
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * call this when dynamically changing the view; normally, you should
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implement {@link #onCreateCandidatesView()} and create your view when
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * first needed by the input method.
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setCandidatesView(View view) {
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesFrame.removeAllViews();
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesFrame.addView(view, new FrameLayout.LayoutParams(
1371980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                ViewGroup.LayoutParams.MATCH_PARENT,
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ViewGroup.LayoutParams.WRAP_CONTENT));
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Replaces the current input view with a new one.  You only need to
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * call this when dynamically changing the view; normally, you should
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implement {@link #onCreateInputView()} and create your view when
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * first needed by the input method.
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setInputView(View view) {
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputFrame.removeAllViews();
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputFrame.addView(view, new FrameLayout.LayoutParams(
1384980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                ViewGroup.LayoutParams.MATCH_PARENT,
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ViewGroup.LayoutParams.WRAP_CONTENT));
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputView = view;
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called by the framework to create the layout for showing extacted text.
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Only called when in fullscreen mode.  The returned view hierarchy must
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * have an {@link ExtractEditText} whose ID is
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.R.id#inputExtractEditText}.
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View onCreateExtractTextView() {
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInflater.inflate(
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                com.android.internal.R.layout.input_method_extract_view, null);
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create and return the view hierarchy used to show candidates.  This will
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be called once, when the candidates are first displayed.  You can return
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * null to have no candidates view; the default implementation returns null.
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>To control when the candidates view is displayed, use
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #setCandidatesViewShown(boolean)}.
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * To change the candidates view after the first one is created by this
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * function, use {@link #setCandidatesView(View)}.
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View onCreateCandidatesView() {
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create and return the view hierarchy used for the input area (such as
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a soft keyboard).  This will be called once, when the input area is
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * first displayed.  You can return null to have no input area; the default
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementation returns null.
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>To control when the input view is displayed, implement
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #onEvaluateInputViewShown()}.
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * To change the input view after the first one is created by this
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * function, use {@link #setInputView(View)}.
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View onCreateInputView() {
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the input view is being shown and input has started on
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a new editor.  This will always be called after {@link #onStartInput},
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * allowing you to do your general setup there and just view-specific
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * setup here.  You are guaranteed that {@link #onCreateInputView()} will
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * have been called some time before this function is called.
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param info Description of the type of text being edited.
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param restarting Set to true if we are restarting input on the
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * same text field as before.
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onStartInputView(EditorInfo info, boolean restarting) {
144134703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the input view is being hidden from the user.  This will
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be called either prior to hiding the window, or prior to switching to
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * another target for editing.
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementation uses the InputConnection to clear any active composing
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * text; you can override this (not calling the base class implementation)
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to perform whatever behavior you would like.
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14544df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * @param finishingInput If true, {@link #onFinishInput} will be
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called immediately after.
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onFinishInputView(boolean finishingInput) {
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!finishingInput) {
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputConnection ic = getCurrentInputConnection();
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ic != null) {
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ic.finishComposingText();
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when only the candidates view has been shown for showing
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * processing as the user enters text through a hard keyboard.
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This will always be called after {@link #onStartInput},
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * allowing you to do your general setup there and just view-specific
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * setup here.  You are guaranteed that {@link #onCreateCandidatesView()}
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will have been called some time before this function is called.
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Note that this will <em>not</em> be called when the input method
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is running in full editing mode, and thus receiving
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #onStartInputView} to initiate that operation.  This is only
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for the case when candidates are being shown while the input method
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * editor is hidden but wants to show its candidates UI as text is
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * entered through some other mechanism.
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param info Description of the type of text being edited.
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param restarting Set to true if we are restarting input on the
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * same text field as before.
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onStartCandidatesView(EditorInfo info, boolean restarting) {
148634703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the candidates view is being hidden from the user.  This will
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be called either prior to hiding the window, or prior to switching to
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * another target for editing.
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementation uses the InputConnection to clear any active composing
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * text; you can override this (not calling the base class implementation)
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to perform whatever behavior you would like.
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14994df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * @param finishingInput If true, {@link #onFinishInput} will be
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called immediately after.
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onFinishCandidatesView(boolean finishingInput) {
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!finishingInput) {
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputConnection ic = getCurrentInputConnection();
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ic != null) {
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ic.finishComposingText();
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The system has decided that it may be time to show your input method.
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is called due to a corresponding call to your
15144df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * {@link InputMethod#showSoftInput InputMethod.showSoftInput()}
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * method.  The default implementation uses
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #onEvaluateInputViewShown()}, {@link #onEvaluateFullscreenMode()},
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and the current configuration to decide whether the input view should
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be shown at this point.
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param flags Provides additional information about the show request,
15214df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * as per {@link InputMethod#showSoftInput InputMethod.showSoftInput()}.
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param configChange This is true if we are re-showing due to a
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * configuration change.
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns true to indicate that the window should be shown.
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onShowInputRequested(int flags, boolean configChange) {
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!onEvaluateInputViewShown()) {
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethod.SHOW_EXPLICIT) == 0) {
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!configChange && onEvaluateFullscreenMode()) {
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Don't show if this is not explicitly requested by the user and
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // the input method is fullscreen.  That would be too disruptive.
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // However, we skip this change for a config change, since if
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // the IME is already shown we do want to go into fullscreen
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // mode at this point.
15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1539d0d07974745dcc947bb498198166f5872c7ec4a1Yohei Yukawa            if (!mSettingsObserver.shouldShowImeWithHardKeyboard() &&
1540d0d07974745dcc947bb498198166f5872c7ec4a1Yohei Yukawa                    getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS) {
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // And if the device has a hard keyboard, even if it is
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // currently hidden, don't show the input method implicitly.
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // These kinds of devices don't need it that much.
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1549ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa
1550ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa    /**
1551ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa     * A utility method to call {{@link #onShowInputRequested(int, boolean)}} and update internal
1552ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa     * states depending on its result.  Since {@link #onShowInputRequested(int, boolean)} is
1553ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa     * exposed to IME authors as an overridable public method without {@code @CallSuper}, we have
1554ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa     * to have this method to ensure that those internal states are always updated no matter how
1555ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa     * {@link #onShowInputRequested(int, boolean)} is overridden by the IME author.
1556ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa     * @param flags Provides additional information about the show request,
1557ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa     * as per {@link InputMethod#showSoftInput InputMethod.showSoftInput()}.
1558ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa     * @param configChange This is true if we are re-showing due to a
1559ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa     * configuration change.
1560ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa     * @return Returns true to indicate that the window should be shown.
1561ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa     * @see #onShowInputRequested(int, boolean)
1562ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa     */
1563ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa    private boolean dispatchOnShowInputRequested(int flags, boolean configChange) {
1564ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa        final boolean result = onShowInputRequested(flags, configChange);
1565ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa        if (result) {
1566ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa            mShowInputFlags = flags;
1567ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa        } else {
1568ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa            mShowInputFlags = 0;
1569ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa        }
1570ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa        return result;
1571ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa    }
1572ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showWindow(boolean showInput) {
1574e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner        if (DEBUG) Log.v(TAG, "Showing window: showInput=" + showInput
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mShowInputRequested=" + mShowInputRequested
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mWindowAdded=" + mWindowAdded
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mWindowCreated=" + mWindowCreated
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mWindowVisible=" + mWindowVisible
1579ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa                + " mInputStarted=" + mInputStarted
1580ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa                + " mShowInputFlags=" + mShowInputFlags);
1581ef5b4657a8b03b33d6c4087e0ced33606fcf05f3Yohei Yukawa
1582105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mInShowWindow) {
1583105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.w(TAG, "Re-entrance in to showWindow");
1584105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return;
1585105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1586105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1587105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        try {
1588105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mWindowWasVisible = mWindowVisible;
1589105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mInShowWindow = true;
1590105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            showWindowInner(showInput);
15916fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa        } catch (BadTokenException e) {
15926fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa            // BadTokenException is a normal consequence in certain situations, e.g., swapping IMEs
15936fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa            // while there is a DO_SHOW_SOFT_INPUT message in the IIMethodWrapper queue.
15946fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa            if (DEBUG) Log.v(TAG, "BadTokenException: IME is done.");
15956fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa            mWindowVisible = false;
15966fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa            mWindowAdded = false;
15976fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa            // Rethrow the exception to preserve the existing behavior.  Some IMEs may have directly
15986fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa            // called this method and relied on this exception for some clean-up tasks.
15996fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa            // TODO: Give developers a clear guideline of whether it's OK to call this method or
16006fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa            // InputMethodManager#showSoftInputFromInputMethod() should always be used instead.
16016fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa            throw e;
1602105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        } finally {
16036fcbb5629019489a88a9748f278d40d554cc5cdcYohei Yukawa            // TODO: Is it OK to set true when we get BadTokenException?
1604105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mWindowWasVisible = true;
1605105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mInShowWindow = false;
1606105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1607105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
160806487a58be22b100daf3f950b9a1d25c3ea42aa2satok
1609105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    void showWindowInner(boolean showInput) {
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean doShowInput = false;
161198d88028ae449fccfa8bace0d4ed3e34f6290658Seigo Nonaka        final int previousImeWindowStatus =
161298d88028ae449fccfa8bace0d4ed3e34f6290658Seigo Nonaka                (mWindowVisible ? IME_ACTIVE : 0) | (isInputViewShown() ? IME_VISIBLE : 0);
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWindowVisible = true;
1614ac8bdd203c18d0f99b825132cf6134dce5d12bc6Yohei Yukawa        if (!mShowInputRequested && mInputStarted && showInput) {
1615ac8bdd203c18d0f99b825132cf6134dce5d12bc6Yohei Yukawa            doShowInput = true;
1616ac8bdd203c18d0f99b825132cf6134dce5d12bc6Yohei Yukawa            mShowInputRequested = true;
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
161806487a58be22b100daf3f950b9a1d25c3ea42aa2satok
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DEBUG) Log.v(TAG, "showWindow: updating UI");
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initialize();
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateFullscreenMode();
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateInputViewShown();
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mWindowAdded || !mWindowCreated) {
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWindowAdded = true;
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWindowCreated = true;
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            initialize();
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "CALL: onCreateCandidatesView");
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View v = onCreateCandidatesView();
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "showWindow: candidates=" + v);
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (v != null) {
16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                setCandidatesView(v);
16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowInputRequested) {
16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mInputViewStarted) {
16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) Log.v(TAG, "CALL: onStartInputView");
16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInputViewStarted = true;
16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                onStartInputView(mInputEditorInfo, false);
16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (!mCandidatesViewStarted) {
16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "CALL: onStartCandidatesView");
16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCandidatesViewStarted = true;
16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onStartCandidatesView(mInputEditorInfo, false);
16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (doShowInput) {
16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startExtractingText(false);
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
165006487a58be22b100daf3f950b9a1d25c3ea42aa2satok
165198d88028ae449fccfa8bace0d4ed3e34f6290658Seigo Nonaka        final int nextImeWindowStatus = IME_ACTIVE | (isInputViewShown() ? IME_VISIBLE : 0);
165298d88028ae449fccfa8bace0d4ed3e34f6290658Seigo Nonaka        if (previousImeWindowStatus != nextImeWindowStatus) {
165398d88028ae449fccfa8bace0d4ed3e34f6290658Seigo Nonaka            mImm.setImeWindowStatus(mToken, nextImeWindowStatus, mBackDisposition);
165498d88028ae449fccfa8bace0d4ed3e34f6290658Seigo Nonaka        }
165598d88028ae449fccfa8bace0d4ed3e34f6290658Seigo Nonaka        if ((previousImeWindowStatus & IME_ACTIVE) == 0) {
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "showWindow: showing!");
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onWindowShown();
16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWindow.show();
16592977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa            // Put here rather than in onWindowShown() in case people forget to call
16602977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa            // super.onWindowShown().
16612977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa            mShouldClearInsetOfPreviousIme = false;
16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
166406487a58be22b100daf3f950b9a1d25c3ea42aa2satok
1665f17db9f5257011d5331d27a6da7d4e6fddde1e08satok    private void finishViews() {
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputViewStarted) {
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "CALL: onFinishInputView");
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onFinishInputView(false);
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mCandidatesViewStarted) {
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "CALL: onFinishCandidatesView");
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onFinishCandidatesView(false);
16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputViewStarted = false;
16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesViewStarted = false;
1675f17db9f5257011d5331d27a6da7d4e6fddde1e08satok    }
1676f17db9f5257011d5331d27a6da7d4e6fddde1e08satok
16772f913d951c481edccbefa4d321a76f28740b48d7satok    private void doHideWindow() {
16782f913d951c481edccbefa4d321a76f28740b48d7satok        mImm.setImeWindowStatus(mToken, 0, mBackDisposition);
16792f913d951c481edccbefa4d321a76f28740b48d7satok        hideWindow();
16802f913d951c481edccbefa4d321a76f28740b48d7satok    }
16812f913d951c481edccbefa4d321a76f28740b48d7satok
1682f17db9f5257011d5331d27a6da7d4e6fddde1e08satok    public void hideWindow() {
1683f17db9f5257011d5331d27a6da7d4e6fddde1e08satok        finishViews();
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mWindowVisible) {
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWindow.hide();
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWindowVisible = false;
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onWindowHidden();
1688105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mWindowWasVisible = false;
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
169093c47eab2b4e11103b29f923bdda932569d0b6a5Seigo Nonaka        updateFullscreenMode();
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
169206487a58be22b100daf3f950b9a1d25c3ea42aa2satok
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the input method window has been shown to the user, after
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * previously not being visible.  This is done after all of the UI setup
16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for the window has occurred (creating its views etc).
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onWindowShown() {
169934703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the input method window has been hidden from the user,
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * after previously being visible.
17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onWindowHidden() {
170734703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17092977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa
17102977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa    /**
17112977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa     * Reset the inset occupied the previous IME when and only when
17122977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa     * {@link #mShouldClearInsetOfPreviousIme} is {@code true}.
17132977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa     */
17142977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa    private void clearInsetOfPreviousIme() {
17152977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa        if (DEBUG) Log.v(TAG, "clearInsetOfPreviousIme() "
17162977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa                + " mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme);
1717833bdcedceee60a873694a77587393abfc830eb5Yohei Yukawa        if (!mShouldClearInsetOfPreviousIme) return;
1718833bdcedceee60a873694a77587393abfc830eb5Yohei Yukawa
1719833bdcedceee60a873694a77587393abfc830eb5Yohei Yukawa        mImm.clearLastInputMethodWindowForTransition(mToken);
17202977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa        mShouldClearInsetOfPreviousIme = false;
17212977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa    }
17222977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa
17239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when a new client has bound to the input method.  This
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * may be followed by a series of {@link #onStartInput(EditorInfo, boolean)}
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and {@link #onFinishInput()} calls as the user navigates through its
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * UI.  Upon this call you know that {@link #getCurrentInputBinding}
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and {@link #getCurrentInputConnection} return valid objects.
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onBindInput() {
173134703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the previous bound client is no longer associated
17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with the input method.  After returning {@link #getCurrentInputBinding}
17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and {@link #getCurrentInputConnection} will no longer return
17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * valid objects.
17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onUnbindInput() {
174134703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
17429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
17459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called to inform the input method that text input has started in an
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * editor.  You should use this callback to initialize the state of your
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * input to match the state of the editor given to it.
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attribute The attributes of the editor that input is starting
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in.
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param restarting Set to true if input is restarting in the same
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * editor such as because the application has changed the text in
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the editor.  Otherwise will be false, indicating this is a new
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * session with the editor.
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onStartInput(EditorInfo attribute, boolean restarting) {
175734703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void doFinishInput() {
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputViewStarted) {
17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "CALL: onFinishInputView");
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onFinishInputView(true);
17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mCandidatesViewStarted) {
17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "CALL: onFinishCandidatesView");
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onFinishCandidatesView(true);
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputViewStarted = false;
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCandidatesViewStarted = false;
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputStarted) {
17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) Log.v(TAG, "CALL: onFinishInput");
17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onFinishInput();
17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputStarted = false;
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStartedInputConnection = null;
17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurCompletions = null;
17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17784df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void doStartInput(InputConnection ic, EditorInfo attribute, boolean restarting) {
17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!restarting) {
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            doFinishInput();
17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputStarted = true;
17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStartedInputConnection = ic;
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputEditorInfo = attribute;
17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initialize();
17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DEBUG) Log.v(TAG, "CALL: onStartInput");
17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onStartInput(attribute, restarting);
17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mWindowVisible) {
17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mShowInputRequested) {
17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) Log.v(TAG, "CALL: onStartInputView");
17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInputViewStarted = true;
17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                onStartInputView(mInputEditorInfo, restarting);
17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                startExtractingText(true);
17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (mCandidatesVisibility == View.VISIBLE) {
17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) Log.v(TAG, "CALL: onStartCandidatesView");
17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCandidatesViewStarted = true;
17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                onStartCandidatesView(mInputEditorInfo, restarting);
17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called to inform the input method that text input has finished in
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the last editor.  At this point there may be a call to
18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #onStartInput(EditorInfo, boolean)} to perform input in a
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * new editor, or the input method may be left idle.  This method is
18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <em>not</em> called when input restarts in the same editor.
18099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
18109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default
18119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementation uses the InputConnection to clear any active composing
18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * text; you can override this (not calling the base class implementation)
18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to perform whatever behavior you would like.
18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onFinishInput() {
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputConnection ic = getCurrentInputConnection();
18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ic != null) {
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ic.finishComposingText();
18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the application has reported auto-completion candidates that
18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * it would like to have the input method displayed.  Typically these are
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * only used when an input method is running in full-screen mode, since
18269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise the user can see and interact with the pop-up window of
18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * completions shown by the application.
18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default implementation here does nothing.
18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onDisplayCompletions(CompletionInfo[] completions) {
183234703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the application has reported new extracted text to be shown
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * due to changes in its current text state.  The default implementation
18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * here places the new text in the extract edit text, when the input
18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * method is running in fullscreen mode.
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onUpdateExtractedText(int token, ExtractedText text) {
18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mExtractedToken != token) {
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1845b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (text != null) {
1846b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            if (mExtractEditText != null) {
1847b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mExtractedText = text;
1848b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mExtractEditText.setExtractedText(text);
1849b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            }
18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
18549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the application has reported a new selection region of
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the text.  This is called whether or not the input method has requested
18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * extracted text updates, although if so it will not receive this call
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if the extracted text has changed as well.
1858c743cb94770701ec20a01b57b09232f1aae5bcbbJean Chalard     *
1859c743cb94770701ec20a01b57b09232f1aae5bcbbJean Chalard     * <p>Be careful about changing the text in reaction to this call with
1860c743cb94770701ec20a01b57b09232f1aae5bcbbJean Chalard     * methods such as setComposingText, commitText or
1861c743cb94770701ec20a01b57b09232f1aae5bcbbJean Chalard     * deleteSurroundingText. If the cursor moves as a result, this method
1862c743cb94770701ec20a01b57b09232f1aae5bcbbJean Chalard     * will be called again, which may result in an infinite loop.
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default implementation takes care of updating the cursor in
18659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the extract text, if it is being shown.
18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onUpdateSelection(int oldSelStart, int oldSelEnd,
18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int newSelStart, int newSelEnd,
18699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int candidatesStart, int candidatesEnd) {
18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ExtractEditText eet = mExtractEditText;
1871c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        if (eet != null && isFullscreenMode() && mExtractedText != null) {
18729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int off = mExtractedText.startOffset;
18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            eet.startInternalChanges();
1874c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            newSelStart -= off;
1875c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            newSelEnd -= off;
1876c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            final int len = eet.getText().length();
1877c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            if (newSelStart < 0) newSelStart = 0;
1878c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            else if (newSelStart > len) newSelStart = len;
1879c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            if (newSelEnd < 0) newSelEnd = 0;
1880c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            else if (newSelEnd > len) newSelEnd = len;
1881c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            eet.setSelection(newSelStart, newSelEnd);
18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            eet.finishInternalChanges();
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1887863fcd62171e55bc9f2105d9fb5877df982454d8satok     * Called when the user tapped or clicked a text view.
1888863fcd62171e55bc9f2105d9fb5877df982454d8satok     * IMEs can't rely on this method being called because this was not part of the original IME
1889863fcd62171e55bc9f2105d9fb5877df982454d8satok     * protocol, so applications with custom text editing written before this method appeared will
1890863fcd62171e55bc9f2105d9fb5877df982454d8satok     * not call to inform the IME of this interaction.
1891863fcd62171e55bc9f2105d9fb5877df982454d8satok     * @param focusChanged true if the user changed the focused view by this click.
1892863fcd62171e55bc9f2105d9fb5877df982454d8satok     */
1893863fcd62171e55bc9f2105d9fb5877df982454d8satok    public void onViewClicked(boolean focusChanged) {
189434703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
1895863fcd62171e55bc9f2105d9fb5877df982454d8satok    }
1896863fcd62171e55bc9f2105d9fb5877df982454d8satok
1897863fcd62171e55bc9f2105d9fb5877df982454d8satok    /**
1898a277db28e990d1f6f74ace0c32fe92401660a840Yohei Yukawa     * Called when the application has reported a new location of its text
1899a277db28e990d1f6f74ace0c32fe92401660a840Yohei Yukawa     * cursor.  This is only called if explicitly requested by the input method.
1900a277db28e990d1f6f74ace0c32fe92401660a840Yohei Yukawa     * The default implementation does nothing.
1901a277db28e990d1f6f74ace0c32fe92401660a840Yohei Yukawa     * @deprecated Use {#link onUpdateCursorAnchorInfo(CursorAnchorInfo)} instead.
19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1903a277db28e990d1f6f74ace0c32fe92401660a840Yohei Yukawa    @Deprecated
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onUpdateCursor(Rect newCursor) {
190534703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        // Intentionally empty
19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1909c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Called when the application has reported a new location of its text insertion point and
1910c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * characters in the composition string.  This is only called if explicitly requested by the
1911c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * input method. The default implementation does nothing.
1912c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * @param cursorAnchorInfo The positional information of the text insertion point and the
1913c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * composition string.
1914c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
1915c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public void onUpdateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo) {
1916c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        // Intentionally empty
1917c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
1918c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
1919c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Close this input method's soft input area, removing it from the display.
19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The input method will continue running, but the user can no longer use
19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * it to generate input by touching the screen.
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param flags Provides additional operating flags.  Currently may be
19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * 0 or have the {@link InputMethodManager#HIDE_IMPLICIT_ONLY
19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * InputMethodManager.HIDE_IMPLICIT_ONLY} bit set.
19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19274df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public void requestHideSelf(int flags) {
19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mImm.hideSoftInputFromInputMethod(mToken, flags);
19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19324df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * Show the input method. This is a call back to the
19334df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * IMF to handle showing the input method.
19344df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * @param flags Provides additional operating flags.  Currently may be
19354df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * 0 or have the {@link InputMethodManager#SHOW_FORCED
19364df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * InputMethodManager.} bit set.
19374df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     */
19384df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    private void requestShowSelf(int flags) {
19394df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        mImm.showSoftInputFromInputMethod(mToken, flags);
19404df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    }
19411036c74784d8f8ca7232aaa26b1b0c3796c29d1dAndrei Stingaceanu
194283fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn    private boolean handleBack(boolean doIt) {
194383fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        if (mShowInputRequested) {
194483fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            // If the soft input area is shown, back closes it and we
194583fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            // consume the back key.
194683fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            if (doIt) requestHideSelf(0);
194783fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            return true;
194883fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        } else if (mWindowVisible) {
194983fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            if (mCandidatesVisibility == View.VISIBLE) {
195083fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                // If we are showing candidates even if no input area, then
195183fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                // hide them.
195283fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                if (doIt) setCandidatesViewShown(false);
195383fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            } else {
195483fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                // If we have the window visible for some other reason --
195583fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                // most likely to show candidates -- then just get rid
195683fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                // of it.  This really shouldn't happen, but just in case...
19572f913d951c481edccbefa4d321a76f28740b48d7satok                if (doIt) doHideWindow();
195883fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            }
195983fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            return true;
196083fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        }
196183fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        return false;
196283fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn    }
196338940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa
196438940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa    /**
196538940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa     * @return {#link ExtractEditText} if it is considered to be visible and active. Otherwise
196638940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa     * {@code null} is returned.
196738940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa     */
196838940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa    private ExtractEditText getExtractEditTextIfVisible() {
196938940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa        if (!isExtractViewShown() || !isInputViewShown()) {
197038940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa            return null;
197138940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa        }
197238940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa        return mExtractEditText;
197338940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa    }
197438940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa
19754df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    /**
19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Override this to intercept key down events before they are processed by the
1977ee71b1fa2d3905214fafaa9478fa4fc2834b06fcQuddus Chong     * application.  If you return true, the application will not
1978ee71b1fa2d3905214fafaa9478fa4fc2834b06fcQuddus Chong     * process the event itself.  If you return false, the normal application processing
19799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will occur as if the IME had not seen the event at all.
19809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK
198283fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * KeyEvent.KEYCODE_BACK} if the IME is currently shown, to
198383fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * possibly hide it when the key goes up (if not canceled or long pressed).  In
198483fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * addition, in fullscreen mode only, it will consume DPAD movement
19859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * events to move the cursor in the extracted text view, not allowing
19869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * them to perform navigation in the underlying application.
19879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
198983fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
199038940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa            final ExtractEditText eet = getExtractEditTextIfVisible();
199138940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa            if (eet != null && eet.handleBackInTextActionModeIfNeeded(event)) {
199238940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa                return true;
199338940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa            }
199483fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            if (handleBack(false)) {
199583fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn                event.startTracking();
19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
19979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
199883fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn            return false;
19999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return doMovementKey(keyCode, event, MOVEMENT_DOWN);
20019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
200483fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
200583fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
200683fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * the event).
200783fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     */
200883fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
200983fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        return false;
201083fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn    }
201183fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn
201283fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn    /**
20139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Override this to intercept special key multiple events before they are
20149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * processed by the
20159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * application.  If you return true, the application will not itself
2016b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * process the event.  If you return false, the normal application processing
20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will occur as if the IME had not seen the event at all.
20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
20199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The default implementation always returns false, except when
20209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in fullscreen mode, where it will consume DPAD movement
20219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * events to move the cursor in the extracted text view, not allowing
20229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * them to perform navigation in the underlying application.
20239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return doMovementKey(keyCode, event, count);
20269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Override this to intercept key up events before they are processed by the
20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * application.  If you return true, the application will not itself
2031b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * process the event.  If you return false, the normal application processing
20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will occur as if the IME had not seen the event at all.
20339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
203483fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK
203583fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * KeyEvent.KEYCODE_BACK} to hide the current IME UI if it is shown.  In
203683fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn     * addition, in fullscreen mode only, it will consume DPAD movement
20379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * events to move the cursor in the extracted text view, not allowing
20389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * them to perform navigation in the underlying application.
20399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onKeyUp(int keyCode, KeyEvent event) {
204138940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
204238940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa            final ExtractEditText eet = getExtractEditTextIfVisible();
204338940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa            if (eet != null && eet.handleBackInTextActionModeIfNeeded(event)) {
204438940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa                return true;
204538940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa            }
204638940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa            if (event.isTracking() && !event.isCanceled()) {
204738940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa                return handleBack(true);
204838940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa            }
204983fe3f559249451706957b1a5f660b2b8272f114Dianne Hackborn        }
20509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return doMovementKey(keyCode, event, MOVEMENT_UP);
20519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2053b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease    /**
2054b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * Override this to intercept trackball motion events before they are
2055b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * processed by the application.
2056b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * If you return true, the application will not itself process the event.
2057b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * If you return false, the normal application processing will occur as if
2058b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * the IME had not seen the event at all.
2059b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     */
2060ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    @Override
20619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onTrackballEvent(MotionEvent event) {
2062b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease        if (DEBUG) Log.v(TAG, "onTrackballEvent: " + event);
2063b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease        return false;
2064b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease    }
2065b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease
2066b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease    /**
2067b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * Override this to intercept generic motion events before they are
2068b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * processed by the application.
2069b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * If you return true, the application will not itself process the event.
2070b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * If you return false, the normal application processing will occur as if
2071b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     * the IME had not seen the event at all.
2072b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease     */
2073b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease    @Override
2074b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease    public boolean onGenericMotionEvent(MotionEvent event) {
2075b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease        if (DEBUG) Log.v(TAG, "onGenericMotionEvent(): event " + event);
20769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
20779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onAppPrivateCommand(String action, Bundle data) {
20809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20824df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    /**
20834df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * Handle a request by the system to toggle the soft input area.
20844df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     */
20854df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    private void onToggleSoftInput(int showFlags, int hideFlags) {
20864df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        if (DEBUG) Log.v(TAG, "toggleSoftInput()");
20874df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        if (isInputViewShown()) {
20884df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            requestHideSelf(hideFlags);
20894df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        } else {
20904df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            requestShowSelf(showFlags);
20914df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
20924df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    }
20934df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
20949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MOVEMENT_DOWN = -1;
20959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MOVEMENT_UP = -2;
20969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void reportExtractedMovement(int keyCode, int count) {
20989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int dx = 0, dy = 0;
20999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (keyCode) {
21009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_LEFT:
21019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dx = -count;
21029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
21039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_RIGHT:
21049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dx = count;
21059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
21069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_UP:
21079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dy = -count;
21089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
21099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_DOWN:
21109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dy = count;
21119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
21129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2113ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        onExtractedCursorMovement(dx, dy);
21149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
211538940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa
21169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean doMovementKey(int keyCode, KeyEvent event, int count) {
211738940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa        final ExtractEditText eet = getExtractEditTextIfVisible();
211838940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa        if (eet != null) {
21199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If we are in fullscreen mode, the cursor will move around
21209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // the extract edit text, but should NOT cause focus to move
21219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // to other fields.
21229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MovementMethod movement = eet.getMovementMethod();
21239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Layout layout = eet.getLayout();
21249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (movement != null && layout != null) {
21259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // We want our own movement method to handle the key, so the
21269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // cursor will properly move in our own word wrapping.
21279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (count == MOVEMENT_DOWN) {
212824182f3dacf2d2f1b77e5eadd38547f11cd4270dYohei Yukawa                    if (movement.onKeyDown(eet, eet.getText(), keyCode, event)) {
21299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        reportExtractedMovement(keyCode, 1);
21309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        return true;
21319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
21329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (count == MOVEMENT_UP) {
213324182f3dacf2d2f1b77e5eadd38547f11cd4270dYohei Yukawa                    if (movement.onKeyUp(eet, eet.getText(), keyCode, event)) {
21349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        return true;
21359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
21369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
213724182f3dacf2d2f1b77e5eadd38547f11cd4270dYohei Yukawa                    if (movement.onKeyOther(eet, eet.getText(), event)) {
21389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        reportExtractedMovement(keyCode, count);
21399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
2140105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        KeyEvent down = KeyEvent.changeAction(event, KeyEvent.ACTION_DOWN);
214124182f3dacf2d2f1b77e5eadd38547f11cd4270dYohei Yukawa                        if (movement.onKeyDown(eet, eet.getText(), keyCode, down)) {
2142105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            KeyEvent up = KeyEvent.changeAction(event, KeyEvent.ACTION_UP);
214324182f3dacf2d2f1b77e5eadd38547f11cd4270dYohei Yukawa                            movement.onKeyUp(eet, eet.getText(), keyCode, up);
21449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            while (--count > 0) {
214524182f3dacf2d2f1b77e5eadd38547f11cd4270dYohei Yukawa                                movement.onKeyDown(eet, eet.getText(), keyCode, down);
214624182f3dacf2d2f1b77e5eadd38547f11cd4270dYohei Yukawa                                movement.onKeyUp(eet, eet.getText(), keyCode, up);
21479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
21489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            reportExtractedMovement(keyCode, count);
21499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
21509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
21519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
21529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
21539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Regardless of whether the movement method handled the key,
21549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // we never allow DPAD navigation to the application.
21559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (keyCode) {
21569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case KeyEvent.KEYCODE_DPAD_LEFT:
21579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case KeyEvent.KEYCODE_DPAD_RIGHT:
21589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case KeyEvent.KEYCODE_DPAD_UP:
21599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case KeyEvent.KEYCODE_DPAD_DOWN:
21609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return true;
21619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
21629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
216338940aab693be587d5901f4ef110cbf95da0e22fYohei Yukawa
21649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
21659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
21689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Send the given key event code (as defined by {@link KeyEvent}) to the
21699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * current input connection is a key down + key up event pair.  The sent
21709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * events have {@link KeyEvent#FLAG_SOFT_KEYBOARD KeyEvent.FLAG_SOFT_KEYBOARD}
21719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * set, so that the recipient can identify them as coming from a software
21729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * input method, and
21739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link KeyEvent#FLAG_KEEP_TOUCH_MODE KeyEvent.FLAG_KEEP_TOUCH_MODE}, so
21749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that they don't impact the current touch mode of the UI.
21759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2176405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * <p>Note that it's discouraged to send such key events in normal operation;
2177405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * this is mainly for use with {@link android.text.InputType#TYPE_NULL} type
2178405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * text fields, or for non-rich input methods. A reasonably capable software
2179405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * input method should use the
2180405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * {@link android.view.inputmethod.InputConnection#commitText} family of methods
2181405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * to send text to an application, rather than sending key events.</p>
2182405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     *
21839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param keyEventCode The raw key code to send, as defined by
21849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link KeyEvent}.
21859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
21869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void sendDownUpKeyEvents(int keyEventCode) {
21879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputConnection ic = getCurrentInputConnection();
21889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ic == null) return;
21899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long eventTime = SystemClock.uptimeMillis();
21909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ic.sendKeyEvent(new KeyEvent(eventTime, eventTime,
21916b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown                KeyEvent.ACTION_DOWN, keyEventCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
21929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
2193cb95cd6baebb1ffa365ff8981b0ae5e0b02e4bedTadashi G. Takaoka        ic.sendKeyEvent(new KeyEvent(eventTime, SystemClock.uptimeMillis(),
21946b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown                KeyEvent.ACTION_UP, keyEventCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
21959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
21969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
21999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Ask the input target to execute its default action via
22009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InputConnection#performEditorAction
22019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * InputConnection.performEditorAction()}.
22029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
22039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param fromEnterKey If true, this will be executed as if the user had
22049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pressed an enter key on the keyboard, that is it will <em>not</em>
22059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be done if the editor has set {@link EditorInfo#IME_FLAG_NO_ENTER_ACTION
22069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * EditorInfo.IME_FLAG_NO_ENTER_ACTION}.  If false, the action will be
22079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * sent regardless of how the editor has set that flag.
22089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
22099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a boolean indicating whether an action has been sent.
22109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If false, either the editor did not specify a default action or it
22119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * does not want an action from the enter key.  If true, the action was
22129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * sent (or there was no input connection at all).
22139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
22149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendDefaultEditorAction(boolean fromEnterKey) {
22159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        EditorInfo ei = getCurrentInputEditorInfo();
22169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ei != null &&
22179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (!fromEnterKey || (ei.imeOptions &
22189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        EditorInfo.IME_FLAG_NO_ENTER_ACTION) == 0) &&
22199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (ei.imeOptions & EditorInfo.IME_MASK_ACTION) !=
22209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    EditorInfo.IME_ACTION_NONE) {
22219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the enter key was pressed, and the editor has a default
22229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // action associated with pressing enter, then send it that
22239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // explicit action instead of the key event.
22249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputConnection ic = getCurrentInputConnection();
22259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ic != null) {
22269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ic.performEditorAction(ei.imeOptions&EditorInfo.IME_MASK_ACTION);
22279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
22289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
22299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
22329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
22359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Send the given UTF-16 character to the current input connection.  Most
22369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * characters will be delivered simply by calling
22379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InputConnection#commitText InputConnection.commitText()} with
22389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the character; some, however, may be handled different.  In particular,
22399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the enter character ('\n') will either be delivered as an action code
2240405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * or a raw key event, as appropriate.  Consider this as a convenience
2241405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * method for IMEs that do not have a full implementation of actions; a
2242405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * fully complying IME will decide of the right action for each event and
2243405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * will likely never call this method except maybe to handle events coming
2244405bc51c5dc73846a4abdc325cd234eb2d37469fJean Chalard     * from an actual hardware keyboard.
22459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
22469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param charCode The UTF-16 character code to send.
22479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
22489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void sendKeyChar(char charCode) {
22499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (charCode) {
22509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case '\n': // Apps may be listening to an enter key to perform an action
22519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!sendDefaultEditorAction(true)) {
22529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    sendDownUpKeyEvents(KeyEvent.KEYCODE_ENTER);
22539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
22549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
22559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
22569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Make sure that digits go through any text watcher on the client side.
22579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (charCode >= '0' && charCode <= '9') {
22589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    sendDownUpKeyEvents(charCode - '0' + KeyEvent.KEYCODE_0);
22599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
22609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    InputConnection ic = getCurrentInputConnection();
22619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (ic != null) {
226224182f3dacf2d2f1b77e5eadd38547f11cd4270dYohei Yukawa                        ic.commitText(String.valueOf(charCode), 1);
22639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
22649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
22659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
22669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
22709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is called when the user has moved the cursor in the extracted
22719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * text view, when running in fullsreen mode.  The default implementation
22729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * performs the corresponding selection change on the underlying text
22739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * editor.
22749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
22759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onExtractedSelectionChanged(int start, int end) {
22769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputConnection conn = getCurrentInputConnection();
22779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (conn != null) {
22789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            conn.setSelection(start, end);
22799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
228139ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne
228239ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne    /**
228339ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne     * @hide
228439ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne     */
228539ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne    public void onExtractedDeleteText(int start, int end) {
228639ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne        InputConnection conn = getCurrentInputConnection();
228739ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne        if (conn != null) {
2288755c0095a13365617b0752b8960e0be4044634acKeisuke Kuroyanagi            conn.finishComposingText();
228939ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne            conn.setSelection(start, start);
2290755c0095a13365617b0752b8960e0be4044634acKeisuke Kuroyanagi            conn.deleteSurroundingText(0, end - start);
229139ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne        }
229239ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne    }
229339ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne
229439ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne    /**
229539ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne     * @hide
229639ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne     */
229739ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne    public void onExtractedReplaceText(int start, int end, CharSequence text) {
229839ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne        InputConnection conn = getCurrentInputConnection();
229939ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne        if (conn != null) {
230039ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne            conn.setComposingRegion(start, end);
230139ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne            conn.commitText(text, 1);
230239ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne        }
230339ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne    }
230439ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne
23059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2306e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne     * @hide
2307e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne     */
2308e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne    public void onExtractedSetSpan(Object span, int start, int end, int flags) {
2309e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne        InputConnection conn = getCurrentInputConnection();
2310e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne        if (conn != null) {
2311e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne            if (!conn.setSelection(start, end)) return;
2312e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne            CharSequence text = conn.getSelectedText(InputConnection.GET_TEXT_WITH_STYLES);
2313e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne            if (text instanceof Spannable) {
2314e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne                ((Spannable) text).setSpan(span, 0, text.length(), flags);
2315e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne                conn.setComposingRegion(start, end);
2316e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne                conn.commitText(text, 1);
2317e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne            }
2318e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne        }
2319e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne    }
2320e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne
2321e300be9c29b7915450ddb62f2957d312b52cfa32Gilles Debunne    /**
23229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is called when the user has clicked on the extracted text view,
23239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when running in fullscreen mode.  The default implementation hides
23249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the candidates view when this happens, but only if the extracted text
23259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * editor has a vertical scroll bar because its text doesn't fit.
23269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Re-implement this to provide whatever behavior you want.
23279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
23289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onExtractedTextClicked() {
23299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mExtractEditText == null) {
23309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
23319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mExtractEditText.hasVerticalScrollBar()) {
23339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setCandidatesViewShown(false);
23349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
233639ba6d9c4cf5a88d71edb800f3f48f85f61187c4Gilles Debunne
23379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
23389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is called when the user has performed a cursor movement in the
23399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * extracted text view, when it is running in fullscreen mode.  The default
23409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementation hides the candidates view when a vertical movement
23419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * happens, but only if the extracted text editor has a vertical scroll bar
23429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * because its text doesn't fit.
23439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Re-implement this to provide whatever behavior you want.
23449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param dx The amount of cursor movement in the x dimension.
23459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param dy The amount of cursor movement in the y dimension.
23469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
23479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onExtractedCursorMovement(int dx, int dy) {
23489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mExtractEditText == null || dy == 0) {
23499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
23509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mExtractEditText.hasVerticalScrollBar()) {
23529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setCandidatesViewShown(false);
23539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
23579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is called when the user has selected a context menu item from the
23589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * extracted text view, when running in fullscreen mode.  The default
23599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementation sends this action to the current InputConnection's
23609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InputConnection#performContextMenuAction(int)}, for it
23619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to be processed in underlying "real" editor.  Re-implement this to
23629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * provide whatever behavior you want.
23639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
23649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onExtractTextContextMenuItem(int id) {
23659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputConnection ic = getCurrentInputConnection();
23669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ic != null) {
23679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ic.performContextMenuAction(id);
23689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
23709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
23739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return text that can be used as a button label for the given
23749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link EditorInfo#imeOptions EditorInfo.imeOptions}.  Returns null
23759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if there is no action requested.  Note that there is no guarantee that
23769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the returned text will be relatively short, so you probably do not
23779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * want to use it as text on a soft keyboard key label.
23789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
23799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param imeOptions The value from @link EditorInfo#imeOptions EditorInfo.imeOptions}.
23809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
23819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a label to use, or null if there is no action.
23829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
23839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public CharSequence getTextForImeAction(int imeOptions) {
23849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (imeOptions&EditorInfo.IME_MASK_ACTION) {
23859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EditorInfo.IME_ACTION_NONE:
23869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
23879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EditorInfo.IME_ACTION_GO:
23889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return getText(com.android.internal.R.string.ime_action_go);
23899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EditorInfo.IME_ACTION_SEARCH:
23909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return getText(com.android.internal.R.string.ime_action_search);
23919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EditorInfo.IME_ACTION_SEND:
23929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return getText(com.android.internal.R.string.ime_action_send);
23939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EditorInfo.IME_ACTION_NEXT:
23949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return getText(com.android.internal.R.string.ime_action_next);
23954df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            case EditorInfo.IME_ACTION_DONE:
23964df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return getText(com.android.internal.R.string.ime_action_done);
2397dea3ef7967228f0ddcc03f2455a4f1254758e584Dianne Hackborn            case EditorInfo.IME_ACTION_PREVIOUS:
2398dea3ef7967228f0ddcc03f2455a4f1254758e584Dianne Hackborn                return getText(com.android.internal.R.string.ime_action_previous);
23999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
24009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return getText(com.android.internal.R.string.ime_action_default);
24019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
24029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
240391eb2651a06633353592d52c3e37579f01b020eeMark Renouf
240491eb2651a06633353592d52c3e37579f01b020eeMark Renouf    /**
240591eb2651a06633353592d52c3e37579f01b020eeMark Renouf     * Return a drawable resource id that can be used as a button icon for the given
240691eb2651a06633353592d52c3e37579f01b020eeMark Renouf     * {@link EditorInfo#imeOptions EditorInfo.imeOptions}.
240791eb2651a06633353592d52c3e37579f01b020eeMark Renouf     *
240891eb2651a06633353592d52c3e37579f01b020eeMark Renouf     * @param imeOptions The value from @link EditorInfo#imeOptions EditorInfo.imeOptions}.
240991eb2651a06633353592d52c3e37579f01b020eeMark Renouf     *
241091eb2651a06633353592d52c3e37579f01b020eeMark Renouf     * @return Returns a drawable resource id to use.
241191eb2651a06633353592d52c3e37579f01b020eeMark Renouf     */
241291eb2651a06633353592d52c3e37579f01b020eeMark Renouf    @DrawableRes
241391eb2651a06633353592d52c3e37579f01b020eeMark Renouf    private int getIconForImeAction(int imeOptions) {
241491eb2651a06633353592d52c3e37579f01b020eeMark Renouf        switch (imeOptions&EditorInfo.IME_MASK_ACTION) {
241591eb2651a06633353592d52c3e37579f01b020eeMark Renouf            case EditorInfo.IME_ACTION_GO:
241691eb2651a06633353592d52c3e37579f01b020eeMark Renouf                return com.android.internal.R.drawable.ic_input_extract_action_go;
241791eb2651a06633353592d52c3e37579f01b020eeMark Renouf            case EditorInfo.IME_ACTION_SEARCH:
241891eb2651a06633353592d52c3e37579f01b020eeMark Renouf                return com.android.internal.R.drawable.ic_input_extract_action_search;
241991eb2651a06633353592d52c3e37579f01b020eeMark Renouf            case EditorInfo.IME_ACTION_SEND:
242091eb2651a06633353592d52c3e37579f01b020eeMark Renouf                return com.android.internal.R.drawable.ic_input_extract_action_send;
242191eb2651a06633353592d52c3e37579f01b020eeMark Renouf            case EditorInfo.IME_ACTION_NEXT:
242291eb2651a06633353592d52c3e37579f01b020eeMark Renouf                return com.android.internal.R.drawable.ic_input_extract_action_next;
242391eb2651a06633353592d52c3e37579f01b020eeMark Renouf            case EditorInfo.IME_ACTION_DONE:
242491eb2651a06633353592d52c3e37579f01b020eeMark Renouf                return com.android.internal.R.drawable.ic_input_extract_action_done;
242591eb2651a06633353592d52c3e37579f01b020eeMark Renouf            case EditorInfo.IME_ACTION_PREVIOUS:
242691eb2651a06633353592d52c3e37579f01b020eeMark Renouf                return com.android.internal.R.drawable.ic_input_extract_action_previous;
242791eb2651a06633353592d52c3e37579f01b020eeMark Renouf            default:
242891eb2651a06633353592d52c3e37579f01b020eeMark Renouf                return com.android.internal.R.drawable.ic_input_extract_action_return;
242991eb2651a06633353592d52c3e37579f01b020eeMark Renouf        }
243091eb2651a06633353592d52c3e37579f01b020eeMark Renouf    }
243191eb2651a06633353592d52c3e37579f01b020eeMark Renouf
24329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2433105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * Called when the fullscreen-mode extracting editor info has changed,
2434105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * to determine whether the extracting (extract text and candidates) portion
2435105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * of the UI should be shown.  The standard implementation hides or shows
2436105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * the extract area depending on whether it makes sense for the
2437105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * current editor.  In particular, a {@link InputType#TYPE_NULL}
2438105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * input type or {@link EditorInfo#IME_FLAG_NO_EXTRACT_UI} flag will
2439105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * turn off the extract area since there is no text to be shown.
2440105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     */
2441105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public void onUpdateExtractingVisibility(EditorInfo ei) {
2442105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (ei.inputType == InputType.TYPE_NULL ||
2443105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                (ei.imeOptions&EditorInfo.IME_FLAG_NO_EXTRACT_UI) != 0) {
2444105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            // No reason to show extract UI!
2445105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            setExtractViewShown(false);
2446105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return;
2447105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
2448105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2449105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        setExtractViewShown(true);
2450105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
2451105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2452105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    /**
2453105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * Called when the fullscreen-mode extracting editor info has changed,
2454105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * to update the state of its UI such as the action buttons shown.
2455105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * You do not need to deal with this if you are using the standard
24569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * full screen extract UI.  If replacing it, you will need to re-implement
2457105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * this to put the appropriate action button in your own UI and handle it,
2458105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * and perform any other changes.
2459105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     *
2460105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * <p>The standard implementation turns on or off its accessory area
2461105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * depending on whether there is an action button, and hides or shows
2462105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * the entire extract area depending on whether it makes sense for the
2463105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * current editor.  In particular, a {@link InputType#TYPE_NULL} or
2464105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * {@link InputType#TYPE_TEXT_VARIATION_FILTER} input type will turn off the
2465105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * extract area since there is no text to be shown.
24669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2467105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public void onUpdateExtractingViews(EditorInfo ei) {
2468105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (!isExtractViewShown()) {
2469105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return;
2470105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
2471105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
24729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mExtractAccessories == null) {
24739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
24749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
24759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean hasAction = ei.actionLabel != null || (
24769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (ei.imeOptions&EditorInfo.IME_MASK_ACTION) != EditorInfo.IME_ACTION_NONE &&
2477105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                (ei.imeOptions&EditorInfo.IME_FLAG_NO_ACCESSORY_ACTION) == 0 &&
2478105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                ei.inputType != InputType.TYPE_NULL);
24799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (hasAction) {
24809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractAccessories.setVisibility(View.VISIBLE);
248159eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik            if (mExtractAction != null) {
248291eb2651a06633353592d52c3e37579f01b020eeMark Renouf                if (mExtractAction instanceof ImageButton) {
248391eb2651a06633353592d52c3e37579f01b020eeMark Renouf                    ((ImageButton) mExtractAction)
248491eb2651a06633353592d52c3e37579f01b020eeMark Renouf                            .setImageResource(getIconForImeAction(ei.imeOptions));
248591eb2651a06633353592d52c3e37579f01b020eeMark Renouf                    if (ei.actionLabel != null) {
248691eb2651a06633353592d52c3e37579f01b020eeMark Renouf                        mExtractAction.setContentDescription(ei.actionLabel);
248791eb2651a06633353592d52c3e37579f01b020eeMark Renouf                    } else {
248891eb2651a06633353592d52c3e37579f01b020eeMark Renouf                        mExtractAction.setContentDescription(getTextForImeAction(ei.imeOptions));
248991eb2651a06633353592d52c3e37579f01b020eeMark Renouf                    }
249059eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik                } else {
249191eb2651a06633353592d52c3e37579f01b020eeMark Renouf                    if (ei.actionLabel != null) {
249291eb2651a06633353592d52c3e37579f01b020eeMark Renouf                        ((TextView) mExtractAction).setText(ei.actionLabel);
249391eb2651a06633353592d52c3e37579f01b020eeMark Renouf                    } else {
249491eb2651a06633353592d52c3e37579f01b020eeMark Renouf                        ((TextView) mExtractAction).setText(getTextForImeAction(ei.imeOptions));
249591eb2651a06633353592d52c3e37579f01b020eeMark Renouf                    }
249659eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik                }
249759eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik                mExtractAction.setOnClickListener(mActionClickListener);
24989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
24999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
25009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractAccessories.setVisibility(View.GONE);
250159eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik            if (mExtractAction != null) {
250259eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik                mExtractAction.setOnClickListener(null);
250359eb69192c47ba53cf2ea412a5fba160f2a7892dSteve Kondik            }
25049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
25069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
25089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is called when, while currently displayed in extract mode, the
25099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * current input target changes.  The default implementation will
25109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * auto-hide the IME if the new target is not a full editor, since this
2511f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa     * can be a confusing experience for the user.
25129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
25139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onExtractingInputChanged(EditorInfo ei) {
25149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ei.inputType == InputType.TYPE_NULL) {
25154df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            requestHideSelf(InputMethodManager.HIDE_NOT_ALWAYS);
25169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
25189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void startExtractingText(boolean inputChanged) {
25209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ExtractEditText eet = mExtractEditText;
25219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (eet != null && getCurrentInputStarted()
25229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && isFullscreenMode()) {
25239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtractedToken++;
25249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ExtractedTextRequest req = new ExtractedTextRequest();
25259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            req.token = mExtractedToken;
25269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            req.flags = InputConnection.GET_TEXT_WITH_STYLES;
25279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            req.hintMaxLines = 10;
25289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            req.hintMaxChars = 10000;
2529ba4d93fcd76fdd7c8368e23c7faf9a20684e51a0Amith Yamasani            InputConnection ic = getCurrentInputConnection();
2530ba4d93fcd76fdd7c8368e23c7faf9a20684e51a0Amith Yamasani            mExtractedText = ic == null? null
2531ba4d93fcd76fdd7c8368e23c7faf9a20684e51a0Amith Yamasani                    : ic.getExtractedText(req, InputConnection.GET_EXTRACTED_TEXT_MONITOR);
2532a8b00c8801be8e7bd21ddab64a3cde9b5ff2984aAmith Yamasani            if (mExtractedText == null || ic == null) {
2533a8b00c8801be8e7bd21ddab64a3cde9b5ff2984aAmith Yamasani                Log.e(TAG, "Unexpected null in startExtractingText : mExtractedText = "
2534a8b00c8801be8e7bd21ddab64a3cde9b5ff2984aAmith Yamasani                        + mExtractedText + ", input connection = " + ic);
2535a8b00c8801be8e7bd21ddab64a3cde9b5ff2984aAmith Yamasani            }
25369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final EditorInfo ei = getCurrentInputEditorInfo();
25379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
25399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                eet.startInternalChanges();
2540105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                onUpdateExtractingVisibility(ei);
2541105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                onUpdateExtractingViews(ei);
25429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int inputType = ei.inputType;
25439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((inputType&EditorInfo.TYPE_MASK_CLASS)
25449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        == EditorInfo.TYPE_CLASS_TEXT) {
25459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if ((inputType&EditorInfo.TYPE_TEXT_FLAG_IME_MULTI_LINE) != 0) {
25469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
25479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
25489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
25499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                eet.setInputType(inputType);
25509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                eet.setHint(ei.hintText);
25519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mExtractedText != null) {
25529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    eet.setEnabled(true);
25539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    eet.setExtractedText(mExtractedText);
25549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
25559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    eet.setEnabled(false);
25569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    eet.setText("");
25579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
25589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
25599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                eet.finishInternalChanges();
25609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
25619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (inputChanged) {
25639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                onExtractingInputChanged(ei);
25649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
25659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2567ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2568ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    // TODO: Handle the subtype change event
2569ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
2570ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * Called when the subtype was changed.
2571ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @param newSubtype the subtype which is being changed to.
2572ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
2573ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    protected void onCurrentInputMethodSubtypeChanged(InputMethodSubtype newSubtype) {
2574ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        if (DEBUG) {
2575ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            int nameResId = newSubtype.getNameResId();
25769ef0283bdcd9534cc09ae37eb2b78771b95247b5satok            String mode = newSubtype.getMode();
2577ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            String output = "changeInputMethodSubtype:"
2578ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                + (nameResId == 0 ? "<none>" : getString(nameResId)) + ","
25799ef0283bdcd9534cc09ae37eb2b78771b95247b5satok                + mode + ","
2580ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                + newSubtype.getLocale() + "," + newSubtype.getExtraValue();
2581ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            Log.v(TAG, "--- " + output);
2582ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
2583ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2584ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
25859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2586658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka     * @return The recommended height of the input method window.
2587658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka     * An IME author can get the last input method's height as the recommended height
2588658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka     * by calling this in
2589658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka     * {@link android.inputmethodservice.InputMethodService#onStartInputView(EditorInfo, boolean)}.
2590658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka     * If you don't need to use a predefined fixed height, you can avoid the window-resizing of IME
2591658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka     * switching by using this value as a visible inset height. It's efficient for the smooth
2592658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka     * transition between different IMEs. However, note that this may return 0 (or possibly
2593658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka     * unexpectedly low height). You should thus avoid relying on the return value of this method
2594658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka     * all the time. Please make sure to use a reasonable height for the IME.
2595658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka     */
2596658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    public int getInputMethodWindowRecommendedHeight() {
2597658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka        return mImm.getInputMethodWindowVisibleHeight();
2598658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    }
2599658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka
2600658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    /**
26019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Performs a dump of the InputMethodService's internal state.  Override
26029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to add your own information to the dump.
26039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
26049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
26059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Printer p = new PrintWriterPrinter(fout);
26069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("Input method service state for " + this + ":");
26079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mWindowCreated=" + mWindowCreated
2608105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                + " mWindowAdded=" + mWindowAdded);
2609105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        p.println("  mWindowVisible=" + mWindowVisible
2610105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                + " mWindowWasVisible=" + mWindowWasVisible
2611105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                + " mInShowWindow=" + mInShowWindow);
26129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  Configuration=" + getResources().getConfiguration());
26139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mToken=" + mToken);
26149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mInputBinding=" + mInputBinding);
26159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mInputConnection=" + mInputConnection);
26169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mStartedInputConnection=" + mStartedInputConnection);
26179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mInputStarted=" + mInputStarted
26189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mInputViewStarted=" + mInputViewStarted
26199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mCandidatesViewStarted=" + mCandidatesViewStarted);
26209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputEditorInfo != null) {
26229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mInputEditorInfo:");
26239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputEditorInfo.dump(p, "    ");
26249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
26259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mInputEditorInfo: null");
26269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
26279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mShowInputRequested=" + mShowInputRequested
26299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mLastShowInputRequested=" + mLastShowInputRequested
26309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags));
26319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mCandidatesVisibility=" + mCandidatesVisibility
26329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mFullscreenApplied=" + mFullscreenApplied
2633105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                + " mIsFullscreen=" + mIsFullscreen
2634105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                + " mExtractViewHidden=" + mExtractViewHidden);
26359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mExtractedText != null) {
26379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mExtractedText:");
26389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("    text=" + mExtractedText.text.length() + " chars"
26399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " startOffset=" + mExtractedText.startOffset);
26409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("    selectionStart=" + mExtractedText.selectionStart
26419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " selectionEnd=" + mExtractedText.selectionEnd
26429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " flags=0x" + Integer.toHexString(mExtractedText.flags));
26439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
26449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mExtractedText: null");
26459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
26469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mExtractedToken=" + mExtractedToken);
26479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  mIsInputViewShown=" + mIsInputViewShown
26489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " mStatusIcon=" + mStatusIcon);
26499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("Last computed insets:");
26509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.println("  contentTopInsets=" + mTmpInsets.contentTopInsets
26519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " visibleTopInsets=" + mTmpInsets.visibleTopInsets
2652fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown                + " touchableInsets=" + mTmpInsets.touchableInsets
2653fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown                + " touchableRegion=" + mTmpInsets.touchableRegion);
26542977eb7b6ce82309a1bb1ba4ab698f503cb0388aYohei Yukawa        p.println(" mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme);
26557b739a802cb7d97460a0bf8a1e9774efe96fa552Yohei Yukawa        p.println(" mSettingsObserver=" + mSettingsObserver);
26569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
26579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2658