blob: 8ab8991c7a4216c5fe5b284b6ccfe4cb0304d4b6 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package android.inputmethodservice;
18
Romain Guy980a9382010-01-08 15:06:28 -080019import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
21
Tor Norbye7b9c9122013-05-30 16:48:33 -070022import android.annotation.DrawableRes;
Dianne Hackborn836531b2012-08-01 19:00:38 -070023import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.app.Dialog;
25import android.content.Context;
26import android.content.res.Configuration;
Dianne Hackbornd922ae02011-01-14 11:43:24 -080027import android.content.res.Resources;
The Android Open Source Project10592532009-03-18 17:39:46 -070028import android.content.res.TypedArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.graphics.Rect;
Jeff Brownfbf09772011-01-16 14:06:57 -080030import android.graphics.Region;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.os.Bundle;
32import android.os.IBinder;
The Android Open Source Project4df24232009-03-05 14:34:35 -080033import android.os.ResultReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.os.SystemClock;
35import android.provider.Settings;
36import android.text.InputType;
37import android.text.Layout;
38import android.text.Spannable;
39import android.text.method.MovementMethod;
40import android.util.Log;
41import android.util.PrintWriterPrinter;
42import android.util.Printer;
Dianne Hackborne30e02f2014-05-27 18:24:45 -070043import android.view.Gravity;
Jeff Brown6b53e8d2010-11-10 16:03:06 -080044import android.view.KeyCharacterMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.view.KeyEvent;
46import android.view.LayoutInflater;
47import android.view.MotionEvent;
48import android.view.View;
49import android.view.ViewGroup;
50import android.view.ViewTreeObserver;
51import android.view.Window;
52import android.view.WindowManager;
Craig Mautnere4bbb1c2013-03-15 11:38:44 -070053import android.view.WindowManager.BadTokenException;
The Android Open Source Project10592532009-03-18 17:39:46 -070054import android.view.animation.AnimationUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.view.inputmethod.CompletionInfo;
Yohei Yukawac2ddd602014-05-06 21:22:49 +090056import android.view.inputmethod.CursorAnchorInfo;
Gilles Debunne8cbb4c62011-01-24 12:33:56 -080057import android.view.inputmethod.EditorInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.view.inputmethod.ExtractedText;
59import android.view.inputmethod.ExtractedTextRequest;
60import android.view.inputmethod.InputBinding;
61import android.view.inputmethod.InputConnection;
62import android.view.inputmethod.InputMethod;
63import android.view.inputmethod.InputMethodManager;
satokab751aa2010-09-14 19:17:36 +090064import android.view.inputmethod.InputMethodSubtype;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.widget.Button;
66import android.widget.FrameLayout;
The Android Open Source Project10592532009-03-18 17:39:46 -070067import android.widget.LinearLayout;
68
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import java.io.FileDescriptor;
70import java.io.PrintWriter;
71
72/**
73 * InputMethodService provides a standard implementation of an InputMethod,
74 * which final implementations can derive from and customize. See the
75 * base class {@link AbstractInputMethodService} and the {@link InputMethod}
76 * interface for more information on the basics of writing input methods.
77 *
78 * <p>In addition to the normal Service lifecycle methods, this class
79 * introduces some new specific callbacks that most subclasses will want
80 * to make use of:</p>
81 * <ul>
82 * <li> {@link #onInitializeInterface()} for user-interface initialization,
83 * in particular to deal with configuration changes while the service is
84 * running.
85 * <li> {@link #onBindInput} to find out about switching to a new client.
86 * <li> {@link #onStartInput} to deal with an input session starting with
87 * the client.
88 * <li> {@link #onCreateInputView()}, {@link #onCreateCandidatesView()},
89 * and {@link #onCreateExtractTextView()} for non-demand generation of the UI.
90 * <li> {@link #onStartInputView(EditorInfo, boolean)} to deal with input
91 * starting within the input area of the IME.
92 * </ul>
93 *
94 * <p>An input method has significant discretion in how it goes about its
95 * work: the {@link android.inputmethodservice.InputMethodService} provides
96 * a basic framework for standard UI elements (input view, candidates view,
97 * and running in fullscreen mode), but it is up to a particular implementor
98 * to decide how to use them. For example, one input method could implement
99 * an input area with a keyboard, another could allow the user to draw text,
100 * while a third could have no input area (and thus not be visible to the
101 * user) but instead listen to audio and perform text to speech conversion.</p>
102 *
103 * <p>In the implementation provided here, all of these elements are placed
104 * together in a single window managed by the InputMethodService. It will
105 * execute callbacks as it needs information about them, and provides APIs for
106 * programmatic control over them. They layout of these elements is explicitly
107 * defined:</p>
108 *
109 * <ul>
110 * <li>The soft input view, if available, is placed at the bottom of the
111 * screen.
112 * <li>The candidates view, if currently shown, is placed above the soft
113 * input view.
114 * <li>If not running fullscreen, the application is moved or resized to be
115 * above these views; if running fullscreen, the window will completely cover
116 * the application and its top part will contain the extract text of what is
117 * currently being edited by the application.
118 * </ul>
119 *
120 *
121 * <a name="SoftInputView"></a>
122 * <h3>Soft Input View</h3>
123 *
124 * <p>Central to most input methods is the soft input view. This is where most
125 * user interaction occurs: pressing on soft keys, drawing characters, or
126 * however else your input method wants to generate text. Most implementations
127 * will simply have their own view doing all of this work, and return a new
128 * instance of it when {@link #onCreateInputView()} is called. At that point,
129 * as long as the input view is visible, you will see user interaction in
130 * that view and can call back on the InputMethodService to interact with the
131 * application as appropriate.</p>
132 *
133 * <p>There are some situations where you want to decide whether or not your
134 * soft input view should be shown to the user. This is done by implementing
135 * the {@link #onEvaluateInputViewShown()} to return true or false based on
136 * whether it should be shown in the current environment. If any of your
137 * state has changed that may impact this, call
138 * {@link #updateInputViewShown()} to have it re-evaluated. The default
139 * implementation always shows the input view unless there is a hard
140 * keyboard available, which is the appropriate behavior for most input
141 * methods.</p>
142 *
143 *
144 * <a name="CandidatesView"></a>
145 * <h3>Candidates View</h3>
146 *
147 * <p>Often while the user is generating raw text, an input method wants to
148 * provide them with a list of possible interpretations of that text that can
149 * be selected for use. This is accomplished with the candidates view, and
150 * like the soft input view you implement {@link #onCreateCandidatesView()}
151 * to instantiate your own view implementing your candidates UI.</p>
152 *
153 * <p>Management of the candidates view is a little different than the input
154 * view, because the candidates view tends to be more transient, being shown
155 * only when there are possible candidates for the current text being entered
156 * by the user. To control whether the candidates view is shown, you use
157 * {@link #setCandidatesViewShown(boolean)}. Note that because the candidate
158 * view tends to be shown and hidden a lot, it does not impact the application
159 * UI in the same way as the soft input view: it will never cause application
160 * windows to resize, only cause them to be panned if needed for the user to
161 * see the current focus.</p>
162 *
163 *
164 * <a name="FullscreenMode"></a>
165 * <h3>Fullscreen Mode</h3>
166 *
167 * <p>Sometimes your input method UI is too large to integrate with the
168 * application UI, so you just want to take over the screen. This is
169 * accomplished by switching to full-screen mode, causing the input method
170 * window to fill the entire screen and add its own "extracted text" editor
171 * showing the user the text that is being typed. Unlike the other UI elements,
172 * there is a standard implementation for the extract editor that you should
173 * not need to change. The editor is placed at the top of the IME, above the
174 * input and candidates views.</p>
175 *
176 * <p>Similar to the input view, you control whether the IME is running in
177 * fullscreen mode by implementing {@link #onEvaluateFullscreenMode()}
178 * to return true or false based on
179 * whether it should be fullscreen in the current environment. If any of your
180 * state has changed that may impact this, call
181 * {@link #updateFullscreenMode()} to have it re-evaluated. The default
182 * implementation selects fullscreen mode when the screen is in a landscape
183 * orientation, which is appropriate behavior for most input methods that have
184 * a significant input area.</p>
185 *
186 * <p>When in fullscreen mode, you have some special requirements because the
187 * user can not see the application UI. In particular, you should implement
188 * {@link #onDisplayCompletions(CompletionInfo[])} to show completions
189 * generated by your application, typically in your candidates view like you
190 * would normally show candidates.
191 *
192 *
193 * <a name="GeneratingText"></a>
194 * <h3>Generating Text</h3>
195 *
196 * <p>The key part of an IME is of course generating text for the application.
197 * This is done through calls to the
198 * {@link android.view.inputmethod.InputConnection} interface to the
199 * application, which can be retrieved from {@link #getCurrentInputConnection()}.
200 * This interface allows you to generate raw key events or, if the target
201 * supports it, directly edit in strings of candidates and committed text.</p>
202 *
203 * <p>Information about what the target is expected and supports can be found
204 * through the {@link android.view.inputmethod.EditorInfo} class, which is
205 * retrieved with {@link #getCurrentInputEditorInfo()} method. The most
206 * important part of this is {@link android.view.inputmethod.EditorInfo#inputType
207 * EditorInfo.inputType}; in particular, if this is
208 * {@link android.view.inputmethod.EditorInfo#TYPE_NULL EditorInfo.TYPE_NULL},
209 * then the target does not support complex edits and you need to only deliver
210 * raw key events to it. An input method will also want to look at other
211 * values here, to for example detect password mode, auto complete text views,
212 * phone number entry, etc.</p>
213 *
214 * <p>When the user switches between input targets, you will receive calls to
215 * {@link #onFinishInput()} and {@link #onStartInput(EditorInfo, boolean)}.
216 * You can use these to reset and initialize your input state for the current
217 * target. For example, you will often want to clear any input state, and
218 * update a soft keyboard to be appropriate for the new inputType.</p>
The Android Open Source Project10592532009-03-18 17:39:46 -0700219 *
220 * @attr ref android.R.styleable#InputMethodService_imeFullscreenBackground
221 * @attr ref android.R.styleable#InputMethodService_imeExtractEnterAnimation
222 * @attr ref android.R.styleable#InputMethodService_imeExtractExitAnimation
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 */
224public class InputMethodService extends AbstractInputMethodService {
225 static final String TAG = "InputMethodService";
226 static final boolean DEBUG = false;
Joe Onorato857fd9b2011-01-27 15:08:35 -0800227
228 /**
229 * The back button will close the input window.
230 */
231 public static final int BACK_DISPOSITION_DEFAULT = 0; // based on window
232
233 /**
234 * This input method will not consume the back key.
235 */
236 public static final int BACK_DISPOSITION_WILL_NOT_DISMISS = 1; // back
237
238 /**
239 * This input method will consume the back key.
240 */
241 public static final int BACK_DISPOSITION_WILL_DISMISS = 2; // down
242
243 /**
244 * @hide
245 * The IME is active. It may or may not be visible.
246 */
247 public static final int IME_ACTIVE = 0x1;
248
249 /**
250 * @hide
251 * The IME is visible.
252 */
253 public static final int IME_VISIBLE = 0x2;
254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 InputMethodManager mImm;
256
Dianne Hackbornd922ae02011-01-14 11:43:24 -0800257 int mTheme = 0;
Dianne Hackborn836531b2012-08-01 19:00:38 -0700258 boolean mHardwareAccelerated = false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 LayoutInflater mInflater;
The Android Open Source Project10592532009-03-18 17:39:46 -0700261 TypedArray mThemeAttrs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262 View mRootView;
263 SoftInputWindow mWindow;
264 boolean mInitialized;
265 boolean mWindowCreated;
266 boolean mWindowAdded;
267 boolean mWindowVisible;
The Android Open Source Project10592532009-03-18 17:39:46 -0700268 boolean mWindowWasVisible;
269 boolean mInShowWindow;
270 ViewGroup mFullscreenArea;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 FrameLayout mExtractFrame;
272 FrameLayout mCandidatesFrame;
273 FrameLayout mInputFrame;
274
275 IBinder mToken;
276
277 InputBinding mInputBinding;
278 InputConnection mInputConnection;
279 boolean mInputStarted;
280 boolean mInputViewStarted;
281 boolean mCandidatesViewStarted;
282 InputConnection mStartedInputConnection;
283 EditorInfo mInputEditorInfo;
284
285 int mShowInputFlags;
286 boolean mShowInputRequested;
287 boolean mLastShowInputRequested;
288 int mCandidatesVisibility;
289 CompletionInfo[] mCurCompletions;
290
291 boolean mShowInputForced;
292
293 boolean mFullscreenApplied;
294 boolean mIsFullscreen;
295 View mExtractView;
The Android Open Source Project10592532009-03-18 17:39:46 -0700296 boolean mExtractViewHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 ExtractEditText mExtractEditText;
298 ViewGroup mExtractAccessories;
299 Button mExtractAction;
300 ExtractedText mExtractedText;
301 int mExtractedToken;
302
303 View mInputView;
304 boolean mIsInputViewShown;
305
306 int mStatusIcon;
Joe Onorato857fd9b2011-01-27 15:08:35 -0800307 int mBackDisposition;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308
Yohei Yukawa2977eb72015-05-27 18:54:18 -0700309 /**
310 * {@code true} when the previous IME had non-empty inset at the bottom of the screen and we
311 * have not shown our own window yet. In this situation, the previous inset continues to be
312 * shown as an empty region until it is explicitly updated. Basically we can trigger the update
313 * by calling 1) {@code mWindow.show()} or 2) {@link #clearInsetOfPreviousIme()}.
314 */
315 boolean mShouldClearInsetOfPreviousIme;
316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 final Insets mTmpInsets = new Insets();
318 final int[] mTmpLocation = new int[2];
satokab751aa2010-09-14 19:17:36 +0900319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer =
321 new ViewTreeObserver.OnComputeInternalInsetsListener() {
322 public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700323 if (isExtractViewShown()) {
324 // In true fullscreen mode, we just say the window isn't covering
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325 // any content so we don't impact whatever is behind.
326 View decor = getWindow().getWindow().getDecorView();
327 info.contentInsets.top = info.visibleInsets.top
328 = decor.getHeight();
Jeff Brownfbf09772011-01-16 14:06:57 -0800329 info.touchableRegion.setEmpty();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
331 } else {
332 onComputeInsets(mTmpInsets);
333 info.contentInsets.top = mTmpInsets.contentTopInsets;
334 info.visibleInsets.top = mTmpInsets.visibleTopInsets;
Jeff Brownfbf09772011-01-16 14:06:57 -0800335 info.touchableRegion.set(mTmpInsets.touchableRegion);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 info.setTouchableInsets(mTmpInsets.touchableInsets);
337 }
338 }
339 };
340
341 final View.OnClickListener mActionClickListener = new View.OnClickListener() {
342 public void onClick(View v) {
343 final EditorInfo ei = getCurrentInputEditorInfo();
344 final InputConnection ic = getCurrentInputConnection();
345 if (ei != null && ic != null) {
346 if (ei.actionId != 0) {
347 ic.performEditorAction(ei.actionId);
348 } else if ((ei.imeOptions&EditorInfo.IME_MASK_ACTION)
349 != EditorInfo.IME_ACTION_NONE) {
350 ic.performEditorAction(ei.imeOptions&EditorInfo.IME_MASK_ACTION);
351 }
352 }
353 }
354 };
355
356 /**
357 * Concrete implementation of
358 * {@link AbstractInputMethodService.AbstractInputMethodImpl} that provides
359 * all of the standard behavior for an input method.
360 */
361 public class InputMethodImpl extends AbstractInputMethodImpl {
362 /**
363 * Take care of attaching the given window token provided by the system.
364 */
365 public void attachToken(IBinder token) {
366 if (mToken == null) {
367 mToken = token;
368 mWindow.setToken(token);
369 }
370 }
371
372 /**
373 * Handle a new input binding, calling
374 * {@link InputMethodService#onBindInput InputMethodService.onBindInput()}
375 * when done.
376 */
377 public void bindInput(InputBinding binding) {
378 mInputBinding = binding;
379 mInputConnection = binding.getConnection();
380 if (DEBUG) Log.v(TAG, "bindInput(): binding=" + binding
381 + " ic=" + mInputConnection);
382 InputConnection ic = getCurrentInputConnection();
383 if (ic != null) ic.reportFullscreenMode(mIsFullscreen);
384 initialize();
385 onBindInput();
386 }
387
388 /**
389 * Clear the current input binding.
390 */
391 public void unbindInput() {
392 if (DEBUG) Log.v(TAG, "unbindInput(): binding=" + mInputBinding
393 + " ic=" + mInputConnection);
394 onUnbindInput();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395 mInputBinding = null;
396 mInputConnection = null;
397 }
398
399 public void startInput(InputConnection ic, EditorInfo attribute) {
400 if (DEBUG) Log.v(TAG, "startInput(): editor=" + attribute);
401 doStartInput(ic, attribute, false);
402 }
403
404 public void restartInput(InputConnection ic, EditorInfo attribute) {
405 if (DEBUG) Log.v(TAG, "restartInput(): editor=" + attribute);
406 doStartInput(ic, attribute, true);
407 }
408
409 /**
410 * Handle a request by the system to hide the soft input area.
411 */
The Android Open Source Project4df24232009-03-05 14:34:35 -0800412 public void hideSoftInput(int flags, ResultReceiver resultReceiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 if (DEBUG) Log.v(TAG, "hideSoftInput()");
The Android Open Source Project4df24232009-03-05 14:34:35 -0800414 boolean wasVis = isInputViewShown();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 mShowInputFlags = 0;
416 mShowInputRequested = false;
417 mShowInputForced = false;
satok2f913d92012-05-10 01:48:03 +0900418 doHideWindow();
Yohei Yukawa2977eb72015-05-27 18:54:18 -0700419 clearInsetOfPreviousIme();
The Android Open Source Project4df24232009-03-05 14:34:35 -0800420 if (resultReceiver != null) {
421 resultReceiver.send(wasVis != isInputViewShown()
422 ? InputMethodManager.RESULT_HIDDEN
423 : (wasVis ? InputMethodManager.RESULT_UNCHANGED_SHOWN
424 : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null);
425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 }
427
428 /**
429 * Handle a request by the system to show the soft input area.
430 */
The Android Open Source Project4df24232009-03-05 14:34:35 -0800431 public void showSoftInput(int flags, ResultReceiver resultReceiver) {
Craig Mautnere4bbb1c2013-03-15 11:38:44 -0700432 if (DEBUG) Log.v(TAG, "showSoftInput()");
The Android Open Source Project4df24232009-03-05 14:34:35 -0800433 boolean wasVis = isInputViewShown();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 mShowInputFlags = 0;
435 if (onShowInputRequested(flags, false)) {
Craig Mautnere4bbb1c2013-03-15 11:38:44 -0700436 try {
437 showWindow(true);
438 } catch (BadTokenException e) {
Yohei Yukawa6fcbb562015-09-14 16:48:15 -0700439 // We have ignored BadTokenException here since Jelly Bean MR-2 (API Level 18).
440 // We could ignore BadTokenException in InputMethodService#showWindow() instead,
441 // but it may break assumptions for those who override #showWindow() that we can
442 // detect errors in #showWindow() by checking BadTokenException.
443 // TODO: Investigate its feasibility. Update JavaDoc of #showWindow() of
444 // whether it's OK to override #showWindow() or not.
Craig Mautnere4bbb1c2013-03-15 11:38:44 -0700445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 }
Yohei Yukawa2977eb72015-05-27 18:54:18 -0700447 clearInsetOfPreviousIme();
satok865b9772011-01-21 02:45:06 +0900448 // If user uses hard keyboard, IME button should always be shown.
jungheang.lee217fd292013-02-26 16:53:22 +0900449 boolean showing = isInputViewShown();
Joe Onorato857fd9b2011-01-27 15:08:35 -0800450 mImm.setImeWindowStatus(mToken, IME_ACTIVE | (showing ? IME_VISIBLE : 0),
451 mBackDisposition);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800452 if (resultReceiver != null) {
453 resultReceiver.send(wasVis != isInputViewShown()
454 ? InputMethodManager.RESULT_SHOWN
455 : (wasVis ? InputMethodManager.RESULT_UNCHANGED_SHOWN
456 : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null);
457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 }
satokab751aa2010-09-14 19:17:36 +0900459
460 public void changeInputMethodSubtype(InputMethodSubtype subtype) {
461 onCurrentInputMethodSubtypeChanged(subtype);
462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 }
satokab751aa2010-09-14 19:17:36 +0900464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465 /**
466 * Concrete implementation of
467 * {@link AbstractInputMethodService.AbstractInputMethodSessionImpl} that provides
468 * all of the standard behavior for an input method session.
469 */
470 public class InputMethodSessionImpl extends AbstractInputMethodSessionImpl {
471 public void finishInput() {
472 if (!isEnabled()) {
473 return;
474 }
475 if (DEBUG) Log.v(TAG, "finishInput() in " + this);
476 doFinishInput();
477 }
478
479 /**
480 * Call {@link InputMethodService#onDisplayCompletions
481 * InputMethodService.onDisplayCompletions()}.
482 */
483 public void displayCompletions(CompletionInfo[] completions) {
484 if (!isEnabled()) {
485 return;
486 }
487 mCurCompletions = completions;
488 onDisplayCompletions(completions);
489 }
490
491 /**
492 * Call {@link InputMethodService#onUpdateExtractedText
493 * InputMethodService.onUpdateExtractedText()}.
494 */
495 public void updateExtractedText(int token, ExtractedText text) {
496 if (!isEnabled()) {
497 return;
498 }
499 onUpdateExtractedText(token, text);
500 }
501
502 /**
503 * Call {@link InputMethodService#onUpdateSelection
504 * InputMethodService.onUpdateSelection()}.
505 */
506 public void updateSelection(int oldSelStart, int oldSelEnd,
507 int newSelStart, int newSelEnd,
508 int candidatesStart, int candidatesEnd) {
509 if (!isEnabled()) {
510 return;
511 }
512 InputMethodService.this.onUpdateSelection(oldSelStart, oldSelEnd,
513 newSelStart, newSelEnd, candidatesStart, candidatesEnd);
514 }
satok863fcd62011-06-21 17:38:02 +0900515
516 @Override
517 public void viewClicked(boolean focusChanged) {
518 if (!isEnabled()) {
519 return;
520 }
521 InputMethodService.this.onViewClicked(focusChanged);
522 }
523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 /**
525 * Call {@link InputMethodService#onUpdateCursor
526 * InputMethodService.onUpdateCursor()}.
527 */
528 public void updateCursor(Rect newCursor) {
529 if (!isEnabled()) {
530 return;
531 }
532 InputMethodService.this.onUpdateCursor(newCursor);
533 }
534
535 /**
536 * Call {@link InputMethodService#onAppPrivateCommand
537 * InputMethodService.onAppPrivateCommand()}.
538 */
539 public void appPrivateCommand(String action, Bundle data) {
540 if (!isEnabled()) {
541 return;
542 }
543 InputMethodService.this.onAppPrivateCommand(action, data);
544 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800545
546 /**
547 *
548 */
549 public void toggleSoftInput(int showFlags, int hideFlags) {
550 InputMethodService.this.onToggleSoftInput(showFlags, hideFlags);
551 }
Yohei Yukawac2ddd602014-05-06 21:22:49 +0900552
553 /**
554 * Call {@link InputMethodService#onUpdateCursorAnchorInfo
555 * InputMethodService.onUpdateCursorAnchorInfo()}.
556 */
557 public void updateCursorAnchorInfo(CursorAnchorInfo info) {
558 if (!isEnabled()) {
559 return;
560 }
561 InputMethodService.this.onUpdateCursorAnchorInfo(info);
562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563 }
564
565 /**
566 * Information about where interesting parts of the input method UI appear.
567 */
568 public static final class Insets {
569 /**
570 * This is the top part of the UI that is the main content. It is
571 * used to determine the basic space needed, to resize/pan the
572 * application behind. It is assumed that this inset does not
573 * change very much, since any change will cause a full resize/pan
574 * of the application behind. This value is relative to the top edge
575 * of the input method window.
576 */
577 public int contentTopInsets;
578
579 /**
580 * This is the top part of the UI that is visibly covering the
581 * application behind it. This provides finer-grained control over
582 * visibility, allowing you to change it relatively frequently (such
583 * as hiding or showing candidates) without disrupting the underlying
584 * UI too much. For example, this will never resize the application
585 * UI, will only pan if needed to make the current focus visible, and
586 * will not aggressively move the pan position when this changes unless
587 * needed to make the focus visible. This value is relative to the top edge
588 * of the input method window.
589 */
590 public int visibleTopInsets;
Jeff Brownfbf09772011-01-16 14:06:57 -0800591
592 /**
593 * This is the region of the UI that is touchable. It is used when
594 * {@link #touchableInsets} is set to {@link #TOUCHABLE_INSETS_REGION}.
595 * The region should be specified relative to the origin of the window frame.
596 */
597 public final Region touchableRegion = new Region();
598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800599 /**
600 * Option for {@link #touchableInsets}: the entire window frame
601 * can be touched.
602 */
603 public static final int TOUCHABLE_INSETS_FRAME
604 = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
605
606 /**
607 * Option for {@link #touchableInsets}: the area inside of
608 * the content insets can be touched.
609 */
610 public static final int TOUCHABLE_INSETS_CONTENT
611 = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
612
613 /**
614 * Option for {@link #touchableInsets}: the area inside of
615 * the visible insets can be touched.
616 */
617 public static final int TOUCHABLE_INSETS_VISIBLE
618 = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
Jeff Brownfbf09772011-01-16 14:06:57 -0800619
620 /**
621 * Option for {@link #touchableInsets}: the region specified by
622 * {@link #touchableRegion} can be touched.
623 */
624 public static final int TOUCHABLE_INSETS_REGION
625 = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800627 /**
628 * Determine which area of the window is touchable by the user. May
629 * be one of: {@link #TOUCHABLE_INSETS_FRAME},
Jeff Brownfbf09772011-01-16 14:06:57 -0800630 * {@link #TOUCHABLE_INSETS_CONTENT}, {@link #TOUCHABLE_INSETS_VISIBLE},
631 * or {@link #TOUCHABLE_INSETS_REGION}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 */
633 public int touchableInsets;
634 }
satok865b9772011-01-21 02:45:06 +0900635
The Android Open Source Project10592532009-03-18 17:39:46 -0700636 /**
637 * You can call this to customize the theme used by your IME's window.
638 * This theme should typically be one that derives from
639 * {@link android.R.style#Theme_InputMethod}, which is the default theme
640 * you will get. This must be set before {@link #onCreate}, so you
641 * will typically call it in your constructor with the resource ID
642 * of your custom theme.
643 */
satokab751aa2010-09-14 19:17:36 +0900644 @Override
The Android Open Source Project10592532009-03-18 17:39:46 -0700645 public void setTheme(int theme) {
646 if (mWindow != null) {
647 throw new IllegalStateException("Must be called before onCreate()");
648 }
649 mTheme = theme;
650 }
satok865b9772011-01-21 02:45:06 +0900651
Dianne Hackborn836531b2012-08-01 19:00:38 -0700652 /**
653 * You can call this to try to enable hardware accelerated drawing for
654 * your IME. This must be set before {@link #onCreate}, so you
655 * will typically call it in your constructor. It is not always possible
Alan Viverettee07b5952014-08-13 19:13:54 -0700656 * to use hardware accelerated drawing in an IME (for example on low-end
Dianne Hackborn836531b2012-08-01 19:00:38 -0700657 * devices that do not have the resources to support this), so the call
658 * returns true if it succeeds otherwise false if you will need to draw
659 * in software. You must be able to handle either case.
Alan Viverettee07b5952014-08-13 19:13:54 -0700660 *
661 * @deprecated Starting in API 21, hardware acceleration is always enabled
662 * on capable devices.
Dianne Hackborn836531b2012-08-01 19:00:38 -0700663 */
664 public boolean enableHardwareAcceleration() {
665 if (mWindow != null) {
666 throw new IllegalStateException("Must be called before onCreate()");
667 }
Jeff Brown98365d72012-08-19 20:30:52 -0700668 if (ActivityManager.isHighEndGfx()) {
Dianne Hackborn836531b2012-08-01 19:00:38 -0700669 mHardwareAccelerated = true;
670 return true;
671 }
672 return false;
673 }
674
Alan Viverette5effd7e2014-05-05 12:25:33 -0700675 @Override public void onCreate() {
676 mTheme = Resources.selectSystemTheme(mTheme,
677 getApplicationInfo().targetSdkVersion,
678 android.R.style.Theme_InputMethod,
679 android.R.style.Theme_Holo_InputMethod,
680 android.R.style.Theme_DeviceDefault_InputMethod,
681 android.R.style.Theme_DeviceDefault_InputMethod);
The Android Open Source Project10592532009-03-18 17:39:46 -0700682 super.setTheme(mTheme);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683 super.onCreate();
684 mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
Yohei Yukawa2977eb72015-05-27 18:54:18 -0700685 // If the previous IME has occupied non-empty inset in the screen, we need to decide whether
686 // we continue to use the same size of the inset or update it
687 mShouldClearInsetOfPreviousIme = (mImm.getInputMethodWindowVisibleHeight() > 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 mInflater = (LayoutInflater)getSystemService(
689 Context.LAYOUT_INFLATER_SERVICE);
Dianne Hackbornc03c9162014-05-02 10:45:59 -0700690 mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700691 WindowManager.LayoutParams.TYPE_INPUT_METHOD, Gravity.BOTTOM, false);
Dianne Hackborn836531b2012-08-01 19:00:38 -0700692 if (mHardwareAccelerated) {
693 mWindow.getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695 initViews();
Romain Guy980a9382010-01-08 15:06:28 -0800696 mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 }
satokab751aa2010-09-14 19:17:36 +0900698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800699 /**
700 * This is a hook that subclasses can use to perform initialization of
701 * their interface. It is called for you prior to any of your UI objects
702 * being created, both after the service is first created and after a
703 * configuration change happens.
704 */
705 public void onInitializeInterface() {
Gilles Debunne34703b62011-09-08 11:16:25 -0700706 // Intentionally empty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 }
satokab751aa2010-09-14 19:17:36 +0900708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709 void initialize() {
710 if (!mInitialized) {
711 mInitialized = true;
712 onInitializeInterface();
713 }
714 }
satokab751aa2010-09-14 19:17:36 +0900715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 void initViews() {
717 mInitialized = false;
718 mWindowCreated = false;
719 mShowInputRequested = false;
720 mShowInputForced = false;
721
The Android Open Source Project10592532009-03-18 17:39:46 -0700722 mThemeAttrs = obtainStyledAttributes(android.R.styleable.InputMethodService);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 mRootView = mInflater.inflate(
724 com.android.internal.R.layout.input_method, null);
John Spurlockc68d5772013-10-08 11:47:58 -0400725 mRootView.setSystemUiVisibility(
726 View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 mWindow.setContentView(mRootView);
Seonggoo Kang72745ff2014-12-24 13:55:50 +0900728 mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsComputer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
Jeff Sharkey6e2bee72012-10-01 13:39:08 -0700730 if (Settings.Global.getInt(getContentResolver(),
731 Settings.Global.FANCY_IME_ANIMATIONS, 0) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 mWindow.getWindow().setWindowAnimations(
733 com.android.internal.R.style.Animation_InputMethodFancy);
734 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700735 mFullscreenArea = (ViewGroup)mRootView.findViewById(com.android.internal.R.id.fullscreenArea);
736 mExtractViewHidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800737 mExtractFrame = (FrameLayout)mRootView.findViewById(android.R.id.extractArea);
738 mExtractView = null;
739 mExtractEditText = null;
740 mExtractAccessories = null;
741 mExtractAction = null;
742 mFullscreenApplied = false;
743
744 mCandidatesFrame = (FrameLayout)mRootView.findViewById(android.R.id.candidatesArea);
745 mInputFrame = (FrameLayout)mRootView.findViewById(android.R.id.inputArea);
746 mInputView = null;
747 mIsInputViewShown = false;
748
749 mExtractFrame.setVisibility(View.GONE);
750 mCandidatesVisibility = getCandidatesHiddenVisibility();
751 mCandidatesFrame.setVisibility(mCandidatesVisibility);
752 mInputFrame.setVisibility(View.GONE);
753 }
satokab751aa2010-09-14 19:17:36 +0900754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 @Override public void onDestroy() {
756 super.onDestroy();
757 mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
758 mInsetsComputer);
Satoshi Kataokac56191f2013-05-30 13:14:47 +0900759 doFinishInput();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 if (mWindowAdded) {
satokc0c87652011-09-12 12:08:05 +0900761 // Disable exit animation for the current IME window
762 // to avoid the race condition between the exit and enter animations
763 // when the current IME is being switched to another one.
764 mWindow.getWindow().setWindowAnimations(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 mWindow.dismiss();
766 }
767 }
satokf17db9f2011-09-14 18:55:58 +0900768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 /**
770 * Take care of handling configuration changes. Subclasses of
771 * InputMethodService generally don't need to deal directly with
772 * this on their own; the standard implementation here takes care of
773 * regenerating the input method UI as a result of the configuration
774 * change, so you can rely on your {@link #onCreateInputView} and
775 * other methods being called as appropriate due to a configuration change.
776 *
777 * <p>When a configuration change does happen,
778 * {@link #onInitializeInterface()} is guaranteed to be called the next
779 * time prior to any of the other input or UI creation callbacks. The
780 * following will be called immediately depending if appropriate for current
781 * state: {@link #onStartInput} if input is active, and
782 * {@link #onCreateInputView} and {@link #onStartInputView} and related
783 * appropriate functions if the UI is displayed.
784 */
785 @Override public void onConfigurationChanged(Configuration newConfig) {
786 super.onConfigurationChanged(newConfig);
787
788 boolean visible = mWindowVisible;
789 int showFlags = mShowInputFlags;
790 boolean showingInput = mShowInputRequested;
791 CompletionInfo[] completions = mCurCompletions;
792 initViews();
793 mInputViewStarted = false;
794 mCandidatesViewStarted = false;
795 if (mInputStarted) {
796 doStartInput(getCurrentInputConnection(),
797 getCurrentInputEditorInfo(), true);
798 }
799 if (visible) {
800 if (showingInput) {
801 // If we were last showing the soft keyboard, try to do so again.
802 if (onShowInputRequested(showFlags, true)) {
803 showWindow(true);
804 if (completions != null) {
805 mCurCompletions = completions;
806 onDisplayCompletions(completions);
807 }
808 } else {
satok2f913d92012-05-10 01:48:03 +0900809 doHideWindow();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800810 }
811 } else if (mCandidatesVisibility == View.VISIBLE) {
812 // If the candidates are currently visible, make sure the
813 // window is shown for them.
814 showWindow(false);
815 } else {
816 // Otherwise hide the window.
satok2f913d92012-05-10 01:48:03 +0900817 doHideWindow();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800818 }
satok865b9772011-01-21 02:45:06 +0900819 // If user uses hard keyboard, IME button should always be shown.
Joe Onorato857fd9b2011-01-27 15:08:35 -0800820 boolean showing = onEvaluateInputViewShown();
821 mImm.setImeWindowStatus(mToken, IME_ACTIVE | (showing ? IME_VISIBLE : 0),
822 mBackDisposition);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800823 }
824 }
825
826 /**
827 * Implement to return our standard {@link InputMethodImpl}. Subclasses
828 * can override to provide their own customized version.
829 */
satokab751aa2010-09-14 19:17:36 +0900830 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 public AbstractInputMethodImpl onCreateInputMethodInterface() {
832 return new InputMethodImpl();
833 }
834
835 /**
836 * Implement to return our standard {@link InputMethodSessionImpl}. Subclasses
837 * can override to provide their own customized version.
838 */
satokab751aa2010-09-14 19:17:36 +0900839 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 public AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface() {
841 return new InputMethodSessionImpl();
842 }
843
844 public LayoutInflater getLayoutInflater() {
845 return mInflater;
846 }
847
848 public Dialog getWindow() {
849 return mWindow;
850 }
851
Joe Onorato857fd9b2011-01-27 15:08:35 -0800852 public void setBackDisposition(int disposition) {
853 mBackDisposition = disposition;
854 }
855
856 public int getBackDisposition() {
857 return mBackDisposition;
858 }
859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 /**
861 * Return the maximum width, in pixels, available the input method.
862 * Input methods are positioned at the bottom of the screen and, unless
863 * running in fullscreen, will generally want to be as short as possible
864 * so should compute their height based on their contents. However, they
865 * can stretch as much as needed horizontally. The function returns to
866 * you the maximum amount of space available horizontally, which you can
867 * use if needed for UI placement.
868 *
869 * <p>In many cases this is not needed, you can just rely on the normal
870 * view layout mechanisms to position your views within the full horizontal
871 * space given to the input method.
872 *
873 * <p>Note that this value can change dynamically, in particular when the
874 * screen orientation changes.
875 */
876 public int getMaxWidth() {
877 WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
878 return wm.getDefaultDisplay().getWidth();
879 }
880
881 /**
882 * Return the currently active InputBinding for the input method, or
883 * null if there is none.
884 */
885 public InputBinding getCurrentInputBinding() {
886 return mInputBinding;
887 }
888
889 /**
890 * Retrieve the currently active InputConnection that is bound to
891 * the input method, or null if there is none.
892 */
893 public InputConnection getCurrentInputConnection() {
894 InputConnection ic = mStartedInputConnection;
895 if (ic != null) {
896 return ic;
897 }
898 return mInputConnection;
899 }
900
901 public boolean getCurrentInputStarted() {
902 return mInputStarted;
903 }
904
905 public EditorInfo getCurrentInputEditorInfo() {
906 return mInputEditorInfo;
907 }
908
909 /**
910 * Re-evaluate whether the input method should be running in fullscreen
911 * mode, and update its UI if this has changed since the last time it
912 * was evaluated. This will call {@link #onEvaluateFullscreenMode()} to
913 * determine whether it should currently run in fullscreen mode. You
914 * can use {@link #isFullscreenMode()} to determine if the input method
915 * is currently running in fullscreen mode.
916 */
917 public void updateFullscreenMode() {
918 boolean isFullscreen = mShowInputRequested && onEvaluateFullscreenMode();
919 boolean changed = mLastShowInputRequested != mShowInputRequested;
920 if (mIsFullscreen != isFullscreen || !mFullscreenApplied) {
921 changed = true;
922 mIsFullscreen = isFullscreen;
923 InputConnection ic = getCurrentInputConnection();
924 if (ic != null) ic.reportFullscreenMode(isFullscreen);
925 mFullscreenApplied = true;
926 initialize();
The Android Open Source Project10592532009-03-18 17:39:46 -0700927 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
928 mFullscreenArea.getLayoutParams();
929 if (isFullscreen) {
930 mFullscreenArea.setBackgroundDrawable(mThemeAttrs.getDrawable(
931 com.android.internal.R.styleable.InputMethodService_imeFullscreenBackground));
932 lp.height = 0;
933 lp.weight = 1;
934 } else {
935 mFullscreenArea.setBackgroundDrawable(null);
936 lp.height = LinearLayout.LayoutParams.WRAP_CONTENT;
937 lp.weight = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700939 ((ViewGroup)mFullscreenArea.getParent()).updateViewLayout(
940 mFullscreenArea, lp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 if (isFullscreen) {
942 if (mExtractView == null) {
943 View v = onCreateExtractTextView();
944 if (v != null) {
945 setExtractView(v);
946 }
947 }
948 startExtractingText(false);
949 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700950 updateExtractFrameVisibility();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800951 }
952
953 if (changed) {
Gilles Debunne34703b62011-09-08 11:16:25 -0700954 onConfigureWindow(mWindow.getWindow(), isFullscreen, !mShowInputRequested);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955 mLastShowInputRequested = mShowInputRequested;
956 }
957 }
958
959 /**
960 * Update the given window's parameters for the given mode. This is called
961 * when the window is first displayed and each time the fullscreen or
962 * candidates only mode changes.
963 *
964 * <p>The default implementation makes the layout for the window
Romain Guy980a9382010-01-08 15:06:28 -0800965 * MATCH_PARENT x MATCH_PARENT when in fullscreen mode, and
966 * MATCH_PARENT x WRAP_CONTENT when in non-fullscreen mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 *
968 * @param win The input method's window.
969 * @param isFullscreen If true, the window is running in fullscreen mode
970 * and intended to cover the entire application display.
971 * @param isCandidatesOnly If true, the window is only showing the
972 * candidates view and none of the rest of its UI. This is mutually
973 * exclusive with fullscreen mode.
974 */
975 public void onConfigureWindow(Window win, boolean isFullscreen,
976 boolean isCandidatesOnly) {
Satoshi Kataoka8b117c82012-11-06 18:59:23 +0900977 final int currentHeight = mWindow.getWindow().getAttributes().height;
978 final int newHeight = isFullscreen ? MATCH_PARENT : WRAP_CONTENT;
979 if (mIsInputViewShown && currentHeight != newHeight) {
980 Log.w(TAG, "Window size has been changed. This may cause jankiness of resizing window: "
981 + currentHeight + " -> " + newHeight);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 }
Satoshi Kataoka8b117c82012-11-06 18:59:23 +0900983 mWindow.getWindow().setLayout(MATCH_PARENT, newHeight);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 }
985
986 /**
987 * Return whether the input method is <em>currently</em> running in
988 * fullscreen mode. This is the mode that was last determined and
989 * applied by {@link #updateFullscreenMode()}.
990 */
991 public boolean isFullscreenMode() {
992 return mIsFullscreen;
993 }
994
995 /**
996 * Override this to control when the input method should run in
997 * fullscreen mode. The default implementation runs in fullsceen only
998 * when the screen is in landscape mode. If you change what
999 * this returns, you will need to call {@link #updateFullscreenMode()}
1000 * yourself whenever the returned value may have changed to have it
1001 * re-evaluated and applied.
1002 */
1003 public boolean onEvaluateFullscreenMode() {
1004 Configuration config = getResources().getConfiguration();
Leon Scroggins2edd6822010-01-12 11:36:13 -05001005 if (config.orientation != Configuration.ORIENTATION_LANDSCAPE) {
1006 return false;
1007 }
1008 if (mInputEditorInfo != null
1009 && (mInputEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_FULLSCREEN) != 0) {
1010 return false;
1011 }
1012 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 }
Gilles Debunne34703b62011-09-08 11:16:25 -07001014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 /**
The Android Open Source Project10592532009-03-18 17:39:46 -07001016 * Controls the visibility of the extracted text area. This only applies
1017 * when the input method is in fullscreen mode, and thus showing extracted
1018 * text. When false, the extracted text will not be shown, allowing some
1019 * of the application to be seen behind. This is normally set for you
1020 * by {@link #onUpdateExtractingVisibility}. This controls the visibility
1021 * of both the extracted text and candidate view; the latter since it is
1022 * not useful if there is no text to see.
1023 */
1024 public void setExtractViewShown(boolean shown) {
1025 if (mExtractViewHidden == shown) {
1026 mExtractViewHidden = !shown;
1027 updateExtractFrameVisibility();
1028 }
1029 }
1030
1031 /**
1032 * Return whether the fullscreen extract view is shown. This will only
1033 * return true if {@link #isFullscreenMode()} returns true, and in that
1034 * case its value depends on the last call to
1035 * {@link #setExtractViewShown(boolean)}. This effectively lets you
1036 * determine if the application window is entirely covered (when this
1037 * returns true) or if some part of it may be shown (if this returns
1038 * false, though if {@link #isFullscreenMode()} returns true in that case
1039 * then it is probably only a sliver of the application).
1040 */
1041 public boolean isExtractViewShown() {
1042 return mIsFullscreen && !mExtractViewHidden;
1043 }
1044
1045 void updateExtractFrameVisibility() {
Satoshi Kataoka8b117c82012-11-06 18:59:23 +09001046 final int vis;
The Android Open Source Project10592532009-03-18 17:39:46 -07001047 if (isFullscreenMode()) {
1048 vis = mExtractViewHidden ? View.INVISIBLE : View.VISIBLE;
Satoshi Kataoka8b117c82012-11-06 18:59:23 +09001049 // "vis" should be applied for the extract frame as well in the fullscreen mode.
1050 mExtractFrame.setVisibility(vis);
The Android Open Source Project10592532009-03-18 17:39:46 -07001051 } else {
1052 vis = View.VISIBLE;
1053 mExtractFrame.setVisibility(View.GONE);
1054 }
1055 updateCandidatesVisibility(mCandidatesVisibility == View.VISIBLE);
1056 if (mWindowWasVisible && mFullscreenArea.getVisibility() != vis) {
1057 int animRes = mThemeAttrs.getResourceId(vis == View.VISIBLE
1058 ? com.android.internal.R.styleable.InputMethodService_imeExtractEnterAnimation
1059 : com.android.internal.R.styleable.InputMethodService_imeExtractExitAnimation,
1060 0);
1061 if (animRes != 0) {
1062 mFullscreenArea.startAnimation(AnimationUtils.loadAnimation(
1063 this, animRes));
1064 }
1065 }
1066 mFullscreenArea.setVisibility(vis);
1067 }
1068
1069 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070 * Compute the interesting insets into your UI. The default implementation
1071 * uses the top of the candidates frame for the visible insets, and the
1072 * top of the input frame for the content insets. The default touchable
1073 * insets are {@link Insets#TOUCHABLE_INSETS_VISIBLE}.
1074 *
The Android Open Source Project10592532009-03-18 17:39:46 -07001075 * <p>Note that this method is not called when
1076 * {@link #isExtractViewShown} returns true, since
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 * in that case the application is left as-is behind the input method and
1078 * not impacted by anything in its UI.
1079 *
1080 * @param outInsets Fill in with the current UI insets.
1081 */
1082 public void onComputeInsets(Insets outInsets) {
1083 int[] loc = mTmpLocation;
1084 if (mInputFrame.getVisibility() == View.VISIBLE) {
1085 mInputFrame.getLocationInWindow(loc);
1086 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07001087 View decor = getWindow().getWindow().getDecorView();
1088 loc[1] = decor.getHeight();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 }
The Android Open Source Project10592532009-03-18 17:39:46 -07001090 if (isFullscreenMode()) {
1091 // In fullscreen mode, we never resize the underlying window.
1092 View decor = getWindow().getWindow().getDecorView();
1093 outInsets.contentTopInsets = decor.getHeight();
1094 } else {
1095 outInsets.contentTopInsets = loc[1];
1096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 if (mCandidatesFrame.getVisibility() == View.VISIBLE) {
1098 mCandidatesFrame.getLocationInWindow(loc);
1099 }
1100 outInsets.visibleTopInsets = loc[1];
1101 outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_VISIBLE;
Jeff Brownfbf09772011-01-16 14:06:57 -08001102 outInsets.touchableRegion.setEmpty();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 }
1104
1105 /**
1106 * Re-evaluate whether the soft input area should currently be shown, and
1107 * update its UI if this has changed since the last time it
1108 * was evaluated. This will call {@link #onEvaluateInputViewShown()} to
1109 * determine whether the input view should currently be shown. You
1110 * can use {@link #isInputViewShown()} to determine if the input view
1111 * is currently shown.
1112 */
1113 public void updateInputViewShown() {
1114 boolean isShown = mShowInputRequested && onEvaluateInputViewShown();
1115 if (mIsInputViewShown != isShown && mWindowVisible) {
1116 mIsInputViewShown = isShown;
1117 mInputFrame.setVisibility(isShown ? View.VISIBLE : View.GONE);
1118 if (mInputView == null) {
1119 initialize();
1120 View v = onCreateInputView();
1121 if (v != null) {
1122 setInputView(v);
1123 }
1124 }
1125 }
1126 }
1127
1128 /**
1129 * Returns true if we have been asked to show our input view.
1130 */
1131 public boolean isShowInputRequested() {
1132 return mShowInputRequested;
1133 }
1134
1135 /**
1136 * Return whether the soft input view is <em>currently</em> shown to the
1137 * user. This is the state that was last determined and
1138 * applied by {@link #updateInputViewShown()}.
1139 */
1140 public boolean isInputViewShown() {
1141 return mIsInputViewShown && mWindowVisible;
1142 }
1143
1144 /**
1145 * Override this to control when the soft input area should be shown to
1146 * the user. The default implementation only shows the input view when
1147 * there is no hard keyboard or the keyboard is hidden. If you change what
1148 * this returns, you will need to call {@link #updateInputViewShown()}
1149 * yourself whenever the returned value may have changed to have it
Gilles Debunne8cbb4c62011-01-24 12:33:56 -08001150 * re-evaluated and applied.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 */
1152 public boolean onEvaluateInputViewShown() {
1153 Configuration config = getResources().getConfiguration();
1154 return config.keyboard == Configuration.KEYBOARD_NOKEYS
Ken Wakasa8710e762011-01-30 11:02:09 +09001155 || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 }
1157
1158 /**
1159 * Controls the visibility of the candidates display area. By default
1160 * it is hidden.
1161 */
1162 public void setCandidatesViewShown(boolean shown) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001163 updateCandidatesVisibility(shown);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 if (!mShowInputRequested && mWindowVisible != shown) {
1165 // If we are being asked to show the candidates view while the app
1166 // has not asked for the input view to be shown, then we need
1167 // to update whether the window is shown.
1168 if (shown) {
1169 showWindow(false);
1170 } else {
satok2f913d92012-05-10 01:48:03 +09001171 doHideWindow();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 }
1173 }
1174 }
1175
The Android Open Source Project10592532009-03-18 17:39:46 -07001176 void updateCandidatesVisibility(boolean shown) {
1177 int vis = shown ? View.VISIBLE : getCandidatesHiddenVisibility();
1178 if (mCandidatesVisibility != vis) {
1179 mCandidatesFrame.setVisibility(vis);
1180 mCandidatesVisibility = vis;
1181 }
1182 }
1183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001184 /**
1185 * Returns the visibility mode (either {@link View#INVISIBLE View.INVISIBLE}
1186 * or {@link View#GONE View.GONE}) of the candidates view when it is not
The Android Open Source Project10592532009-03-18 17:39:46 -07001187 * shown. The default implementation returns GONE when
1188 * {@link #isExtractViewShown} returns true,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 * otherwise VISIBLE. Be careful if you change this to return GONE in
1190 * other situations -- if showing or hiding the candidates view causes
1191 * your window to resize, this can cause temporary drawing artifacts as
1192 * the resize takes place.
1193 */
1194 public int getCandidatesHiddenVisibility() {
The Android Open Source Project10592532009-03-18 17:39:46 -07001195 return isExtractViewShown() ? View.GONE : View.INVISIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196 }
1197
Tor Norbye7b9c9122013-05-30 16:48:33 -07001198 public void showStatusIcon(@DrawableRes int iconResId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 mStatusIcon = iconResId;
1200 mImm.showStatusIcon(mToken, getPackageName(), iconResId);
1201 }
1202
1203 public void hideStatusIcon() {
1204 mStatusIcon = 0;
1205 mImm.hideStatusIcon(mToken);
1206 }
1207
1208 /**
1209 * Force switch to a new input method, as identified by <var>id</var>. This
1210 * input method will be destroyed, and the requested one started on the
1211 * current input field.
1212 *
1213 * @param id Unique identifier of the new input method ot start.
1214 */
1215 public void switchInputMethod(String id) {
1216 mImm.setInputMethod(mToken, id);
1217 }
1218
1219 public void setExtractView(View view) {
1220 mExtractFrame.removeAllViews();
1221 mExtractFrame.addView(view, new FrameLayout.LayoutParams(
Romain Guy980a9382010-01-08 15:06:28 -08001222 ViewGroup.LayoutParams.MATCH_PARENT,
1223 ViewGroup.LayoutParams.MATCH_PARENT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 mExtractView = view;
1225 if (view != null) {
1226 mExtractEditText = (ExtractEditText)view.findViewById(
1227 com.android.internal.R.id.inputExtractEditText);
1228 mExtractEditText.setIME(this);
1229 mExtractAction = (Button)view.findViewById(
1230 com.android.internal.R.id.inputExtractAction);
1231 if (mExtractAction != null) {
1232 mExtractAccessories = (ViewGroup)view.findViewById(
1233 com.android.internal.R.id.inputExtractAccessories);
1234 }
1235 startExtractingText(false);
1236 } else {
1237 mExtractEditText = null;
1238 mExtractAccessories = null;
1239 mExtractAction = null;
1240 }
1241 }
1242
1243 /**
1244 * Replaces the current candidates view with a new one. You only need to
1245 * call this when dynamically changing the view; normally, you should
1246 * implement {@link #onCreateCandidatesView()} and create your view when
1247 * first needed by the input method.
1248 */
1249 public void setCandidatesView(View view) {
1250 mCandidatesFrame.removeAllViews();
1251 mCandidatesFrame.addView(view, new FrameLayout.LayoutParams(
Romain Guy980a9382010-01-08 15:06:28 -08001252 ViewGroup.LayoutParams.MATCH_PARENT,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 ViewGroup.LayoutParams.WRAP_CONTENT));
1254 }
1255
1256 /**
1257 * Replaces the current input view with a new one. You only need to
1258 * call this when dynamically changing the view; normally, you should
1259 * implement {@link #onCreateInputView()} and create your view when
1260 * first needed by the input method.
1261 */
1262 public void setInputView(View view) {
1263 mInputFrame.removeAllViews();
1264 mInputFrame.addView(view, new FrameLayout.LayoutParams(
Romain Guy980a9382010-01-08 15:06:28 -08001265 ViewGroup.LayoutParams.MATCH_PARENT,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001266 ViewGroup.LayoutParams.WRAP_CONTENT));
1267 mInputView = view;
1268 }
1269
1270 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001271 * Called by the framework to create the layout for showing extacted text.
1272 * Only called when in fullscreen mode. The returned view hierarchy must
1273 * have an {@link ExtractEditText} whose ID is
1274 * {@link android.R.id#inputExtractEditText}.
1275 */
1276 public View onCreateExtractTextView() {
1277 return mInflater.inflate(
1278 com.android.internal.R.layout.input_method_extract_view, null);
1279 }
1280
1281 /**
1282 * Create and return the view hierarchy used to show candidates. This will
1283 * be called once, when the candidates are first displayed. You can return
1284 * null to have no candidates view; the default implementation returns null.
1285 *
1286 * <p>To control when the candidates view is displayed, use
1287 * {@link #setCandidatesViewShown(boolean)}.
1288 * To change the candidates view after the first one is created by this
1289 * function, use {@link #setCandidatesView(View)}.
1290 */
1291 public View onCreateCandidatesView() {
1292 return null;
1293 }
1294
1295 /**
1296 * Create and return the view hierarchy used for the input area (such as
1297 * a soft keyboard). This will be called once, when the input area is
1298 * first displayed. You can return null to have no input area; the default
1299 * implementation returns null.
1300 *
1301 * <p>To control when the input view is displayed, implement
1302 * {@link #onEvaluateInputViewShown()}.
1303 * To change the input view after the first one is created by this
1304 * function, use {@link #setInputView(View)}.
1305 */
1306 public View onCreateInputView() {
1307 return null;
1308 }
1309
1310 /**
1311 * Called when the input view is being shown and input has started on
1312 * a new editor. This will always be called after {@link #onStartInput},
1313 * allowing you to do your general setup there and just view-specific
1314 * setup here. You are guaranteed that {@link #onCreateInputView()} will
1315 * have been called some time before this function is called.
1316 *
1317 * @param info Description of the type of text being edited.
1318 * @param restarting Set to true if we are restarting input on the
1319 * same text field as before.
1320 */
1321 public void onStartInputView(EditorInfo info, boolean restarting) {
Gilles Debunne34703b62011-09-08 11:16:25 -07001322 // Intentionally empty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001323 }
1324
1325 /**
1326 * Called when the input view is being hidden from the user. This will
1327 * be called either prior to hiding the window, or prior to switching to
1328 * another target for editing.
1329 *
1330 * <p>The default
1331 * implementation uses the InputConnection to clear any active composing
1332 * text; you can override this (not calling the base class implementation)
1333 * to perform whatever behavior you would like.
1334 *
The Android Open Source Project4df24232009-03-05 14:34:35 -08001335 * @param finishingInput If true, {@link #onFinishInput} will be
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 * called immediately after.
1337 */
1338 public void onFinishInputView(boolean finishingInput) {
1339 if (!finishingInput) {
1340 InputConnection ic = getCurrentInputConnection();
1341 if (ic != null) {
1342 ic.finishComposingText();
1343 }
1344 }
1345 }
1346
1347 /**
1348 * Called when only the candidates view has been shown for showing
1349 * processing as the user enters text through a hard keyboard.
1350 * This will always be called after {@link #onStartInput},
1351 * allowing you to do your general setup there and just view-specific
1352 * setup here. You are guaranteed that {@link #onCreateCandidatesView()}
1353 * will have been called some time before this function is called.
1354 *
1355 * <p>Note that this will <em>not</em> be called when the input method
1356 * is running in full editing mode, and thus receiving
1357 * {@link #onStartInputView} to initiate that operation. This is only
1358 * for the case when candidates are being shown while the input method
1359 * editor is hidden but wants to show its candidates UI as text is
1360 * entered through some other mechanism.
1361 *
1362 * @param info Description of the type of text being edited.
1363 * @param restarting Set to true if we are restarting input on the
1364 * same text field as before.
1365 */
1366 public void onStartCandidatesView(EditorInfo info, boolean restarting) {
Gilles Debunne34703b62011-09-08 11:16:25 -07001367 // Intentionally empty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 }
1369
1370 /**
1371 * Called when the candidates view is being hidden from the user. This will
1372 * be called either prior to hiding the window, or prior to switching to
1373 * another target for editing.
1374 *
1375 * <p>The default
1376 * implementation uses the InputConnection to clear any active composing
1377 * text; you can override this (not calling the base class implementation)
1378 * to perform whatever behavior you would like.
1379 *
The Android Open Source Project4df24232009-03-05 14:34:35 -08001380 * @param finishingInput If true, {@link #onFinishInput} will be
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 * called immediately after.
1382 */
1383 public void onFinishCandidatesView(boolean finishingInput) {
1384 if (!finishingInput) {
1385 InputConnection ic = getCurrentInputConnection();
1386 if (ic != null) {
1387 ic.finishComposingText();
1388 }
1389 }
1390 }
1391
1392 /**
1393 * The system has decided that it may be time to show your input method.
1394 * This is called due to a corresponding call to your
The Android Open Source Project4df24232009-03-05 14:34:35 -08001395 * {@link InputMethod#showSoftInput InputMethod.showSoftInput()}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 * method. The default implementation uses
1397 * {@link #onEvaluateInputViewShown()}, {@link #onEvaluateFullscreenMode()},
1398 * and the current configuration to decide whether the input view should
1399 * be shown at this point.
1400 *
1401 * @param flags Provides additional information about the show request,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001402 * as per {@link InputMethod#showSoftInput InputMethod.showSoftInput()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403 * @param configChange This is true if we are re-showing due to a
1404 * configuration change.
1405 * @return Returns true to indicate that the window should be shown.
1406 */
1407 public boolean onShowInputRequested(int flags, boolean configChange) {
1408 if (!onEvaluateInputViewShown()) {
1409 return false;
1410 }
1411 if ((flags&InputMethod.SHOW_EXPLICIT) == 0) {
1412 if (!configChange && onEvaluateFullscreenMode()) {
1413 // Don't show if this is not explicitly requested by the user and
1414 // the input method is fullscreen. That would be too disruptive.
1415 // However, we skip this change for a config change, since if
1416 // the IME is already shown we do want to go into fullscreen
1417 // mode at this point.
1418 return false;
1419 }
1420 Configuration config = getResources().getConfiguration();
1421 if (config.keyboard != Configuration.KEYBOARD_NOKEYS) {
1422 // And if the device has a hard keyboard, even if it is
1423 // currently hidden, don't show the input method implicitly.
1424 // These kinds of devices don't need it that much.
1425 return false;
1426 }
1427 }
1428 if ((flags&InputMethod.SHOW_FORCED) != 0) {
1429 mShowInputForced = true;
1430 }
1431 return true;
1432 }
1433
1434 public void showWindow(boolean showInput) {
Craig Mautnere4bbb1c2013-03-15 11:38:44 -07001435 if (DEBUG) Log.v(TAG, "Showing window: showInput=" + showInput
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001436 + " mShowInputRequested=" + mShowInputRequested
1437 + " mWindowAdded=" + mWindowAdded
1438 + " mWindowCreated=" + mWindowCreated
1439 + " mWindowVisible=" + mWindowVisible
1440 + " mInputStarted=" + mInputStarted);
The Android Open Source Project10592532009-03-18 17:39:46 -07001441
1442 if (mInShowWindow) {
1443 Log.w(TAG, "Re-entrance in to showWindow");
1444 return;
1445 }
1446
1447 try {
1448 mWindowWasVisible = mWindowVisible;
1449 mInShowWindow = true;
1450 showWindowInner(showInput);
Yohei Yukawa6fcbb562015-09-14 16:48:15 -07001451 } catch (BadTokenException e) {
1452 // BadTokenException is a normal consequence in certain situations, e.g., swapping IMEs
1453 // while there is a DO_SHOW_SOFT_INPUT message in the IIMethodWrapper queue.
1454 if (DEBUG) Log.v(TAG, "BadTokenException: IME is done.");
1455 mWindowVisible = false;
1456 mWindowAdded = false;
1457 // Rethrow the exception to preserve the existing behavior. Some IMEs may have directly
1458 // called this method and relied on this exception for some clean-up tasks.
1459 // TODO: Give developers a clear guideline of whether it's OK to call this method or
1460 // InputMethodManager#showSoftInputFromInputMethod() should always be used instead.
1461 throw e;
The Android Open Source Project10592532009-03-18 17:39:46 -07001462 } finally {
Yohei Yukawa6fcbb562015-09-14 16:48:15 -07001463 // TODO: Is it OK to set true when we get BadTokenException?
The Android Open Source Project10592532009-03-18 17:39:46 -07001464 mWindowWasVisible = true;
1465 mInShowWindow = false;
1466 }
1467 }
satok06487a52010-10-29 11:37:18 +09001468
The Android Open Source Project10592532009-03-18 17:39:46 -07001469 void showWindowInner(boolean showInput) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 boolean doShowInput = false;
Seigo Nonaka98d88022015-04-15 18:31:32 +09001471 final int previousImeWindowStatus =
1472 (mWindowVisible ? IME_ACTIVE : 0) | (isInputViewShown() ? IME_VISIBLE : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 mWindowVisible = true;
Yohei Yukawaac8bdd22015-09-11 18:17:11 -07001474 if (!mShowInputRequested && mInputStarted && showInput) {
1475 doShowInput = true;
1476 mShowInputRequested = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 }
satok06487a52010-10-29 11:37:18 +09001478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 if (DEBUG) Log.v(TAG, "showWindow: updating UI");
1480 initialize();
1481 updateFullscreenMode();
1482 updateInputViewShown();
1483
1484 if (!mWindowAdded || !mWindowCreated) {
1485 mWindowAdded = true;
1486 mWindowCreated = true;
1487 initialize();
1488 if (DEBUG) Log.v(TAG, "CALL: onCreateCandidatesView");
1489 View v = onCreateCandidatesView();
1490 if (DEBUG) Log.v(TAG, "showWindow: candidates=" + v);
1491 if (v != null) {
1492 setCandidatesView(v);
1493 }
1494 }
1495 if (mShowInputRequested) {
1496 if (!mInputViewStarted) {
1497 if (DEBUG) Log.v(TAG, "CALL: onStartInputView");
1498 mInputViewStarted = true;
1499 onStartInputView(mInputEditorInfo, false);
1500 }
1501 } else if (!mCandidatesViewStarted) {
1502 if (DEBUG) Log.v(TAG, "CALL: onStartCandidatesView");
1503 mCandidatesViewStarted = true;
1504 onStartCandidatesView(mInputEditorInfo, false);
1505 }
1506
1507 if (doShowInput) {
1508 startExtractingText(false);
1509 }
satok06487a52010-10-29 11:37:18 +09001510
Seigo Nonaka98d88022015-04-15 18:31:32 +09001511 final int nextImeWindowStatus = IME_ACTIVE | (isInputViewShown() ? IME_VISIBLE : 0);
1512 if (previousImeWindowStatus != nextImeWindowStatus) {
1513 mImm.setImeWindowStatus(mToken, nextImeWindowStatus, mBackDisposition);
1514 }
1515 if ((previousImeWindowStatus & IME_ACTIVE) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 if (DEBUG) Log.v(TAG, "showWindow: showing!");
1517 onWindowShown();
1518 mWindow.show();
Yohei Yukawa2977eb72015-05-27 18:54:18 -07001519 // Put here rather than in onWindowShown() in case people forget to call
1520 // super.onWindowShown().
1521 mShouldClearInsetOfPreviousIme = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 }
1523 }
satok06487a52010-10-29 11:37:18 +09001524
satokf17db9f2011-09-14 18:55:58 +09001525 private void finishViews() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 if (mInputViewStarted) {
1527 if (DEBUG) Log.v(TAG, "CALL: onFinishInputView");
1528 onFinishInputView(false);
1529 } else if (mCandidatesViewStarted) {
1530 if (DEBUG) Log.v(TAG, "CALL: onFinishCandidatesView");
1531 onFinishCandidatesView(false);
1532 }
1533 mInputViewStarted = false;
1534 mCandidatesViewStarted = false;
satokf17db9f2011-09-14 18:55:58 +09001535 }
1536
satok2f913d92012-05-10 01:48:03 +09001537 private void doHideWindow() {
1538 mImm.setImeWindowStatus(mToken, 0, mBackDisposition);
1539 hideWindow();
1540 }
1541
satokf17db9f2011-09-14 18:55:58 +09001542 public void hideWindow() {
1543 finishViews();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001544 if (mWindowVisible) {
1545 mWindow.hide();
1546 mWindowVisible = false;
1547 onWindowHidden();
The Android Open Source Project10592532009-03-18 17:39:46 -07001548 mWindowWasVisible = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 }
Seigo Nonaka93c47ea2015-07-14 15:05:04 +09001550 updateFullscreenMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001551 }
satok06487a52010-10-29 11:37:18 +09001552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 /**
1554 * Called when the input method window has been shown to the user, after
1555 * previously not being visible. This is done after all of the UI setup
1556 * for the window has occurred (creating its views etc).
1557 */
1558 public void onWindowShown() {
Gilles Debunne34703b62011-09-08 11:16:25 -07001559 // Intentionally empty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 }
1561
1562 /**
1563 * Called when the input method window has been hidden from the user,
1564 * after previously being visible.
1565 */
1566 public void onWindowHidden() {
Gilles Debunne34703b62011-09-08 11:16:25 -07001567 // Intentionally empty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 }
Yohei Yukawa2977eb72015-05-27 18:54:18 -07001569
1570 /**
1571 * Reset the inset occupied the previous IME when and only when
1572 * {@link #mShouldClearInsetOfPreviousIme} is {@code true}.
1573 */
1574 private void clearInsetOfPreviousIme() {
1575 if (DEBUG) Log.v(TAG, "clearInsetOfPreviousIme() "
1576 + " mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme);
1577 if (!mShouldClearInsetOfPreviousIme || mWindow == null) return;
Seigo Nonakae9372162015-06-04 17:46:27 +09001578 try {
1579 // We do not call onWindowShown() and onWindowHidden() so as not to make the IME author
1580 // confused.
1581 // TODO: Find out a better way which has less side-effect.
1582 mWindow.show();
1583 mWindow.hide();
1584 } catch (WindowManager.BadTokenException e) {
1585 if (DEBUG) Log.v(TAG, "clearInsetOfPreviousIme: BadTokenException: IME is done.");
1586 mWindowVisible = false;
1587 mWindowAdded = false;
1588 }
Yohei Yukawa2977eb72015-05-27 18:54:18 -07001589 mShouldClearInsetOfPreviousIme = false;
1590 }
1591
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 /**
1593 * Called when a new client has bound to the input method. This
1594 * may be followed by a series of {@link #onStartInput(EditorInfo, boolean)}
1595 * and {@link #onFinishInput()} calls as the user navigates through its
1596 * UI. Upon this call you know that {@link #getCurrentInputBinding}
1597 * and {@link #getCurrentInputConnection} return valid objects.
1598 */
1599 public void onBindInput() {
Gilles Debunne34703b62011-09-08 11:16:25 -07001600 // Intentionally empty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 }
1602
1603 /**
1604 * Called when the previous bound client is no longer associated
1605 * with the input method. After returning {@link #getCurrentInputBinding}
1606 * and {@link #getCurrentInputConnection} will no longer return
1607 * valid objects.
1608 */
1609 public void onUnbindInput() {
Gilles Debunne34703b62011-09-08 11:16:25 -07001610 // Intentionally empty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 }
1612
1613 /**
1614 * Called to inform the input method that text input has started in an
1615 * editor. You should use this callback to initialize the state of your
1616 * input to match the state of the editor given to it.
1617 *
1618 * @param attribute The attributes of the editor that input is starting
1619 * in.
1620 * @param restarting Set to true if input is restarting in the same
1621 * editor such as because the application has changed the text in
1622 * the editor. Otherwise will be false, indicating this is a new
1623 * session with the editor.
1624 */
1625 public void onStartInput(EditorInfo attribute, boolean restarting) {
Gilles Debunne34703b62011-09-08 11:16:25 -07001626 // Intentionally empty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001627 }
1628
1629 void doFinishInput() {
1630 if (mInputViewStarted) {
1631 if (DEBUG) Log.v(TAG, "CALL: onFinishInputView");
1632 onFinishInputView(true);
1633 } else if (mCandidatesViewStarted) {
1634 if (DEBUG) Log.v(TAG, "CALL: onFinishCandidatesView");
1635 onFinishCandidatesView(true);
1636 }
1637 mInputViewStarted = false;
1638 mCandidatesViewStarted = false;
1639 if (mInputStarted) {
1640 if (DEBUG) Log.v(TAG, "CALL: onFinishInput");
1641 onFinishInput();
1642 }
1643 mInputStarted = false;
1644 mStartedInputConnection = null;
1645 mCurCompletions = null;
1646 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 void doStartInput(InputConnection ic, EditorInfo attribute, boolean restarting) {
1649 if (!restarting) {
1650 doFinishInput();
1651 }
1652 mInputStarted = true;
1653 mStartedInputConnection = ic;
1654 mInputEditorInfo = attribute;
1655 initialize();
1656 if (DEBUG) Log.v(TAG, "CALL: onStartInput");
1657 onStartInput(attribute, restarting);
1658 if (mWindowVisible) {
1659 if (mShowInputRequested) {
1660 if (DEBUG) Log.v(TAG, "CALL: onStartInputView");
1661 mInputViewStarted = true;
1662 onStartInputView(mInputEditorInfo, restarting);
1663 startExtractingText(true);
1664 } else if (mCandidatesVisibility == View.VISIBLE) {
1665 if (DEBUG) Log.v(TAG, "CALL: onStartCandidatesView");
1666 mCandidatesViewStarted = true;
1667 onStartCandidatesView(mInputEditorInfo, restarting);
1668 }
1669 }
1670 }
1671
1672 /**
1673 * Called to inform the input method that text input has finished in
1674 * the last editor. At this point there may be a call to
1675 * {@link #onStartInput(EditorInfo, boolean)} to perform input in a
1676 * new editor, or the input method may be left idle. This method is
1677 * <em>not</em> called when input restarts in the same editor.
1678 *
1679 * <p>The default
1680 * implementation uses the InputConnection to clear any active composing
1681 * text; you can override this (not calling the base class implementation)
1682 * to perform whatever behavior you would like.
1683 */
1684 public void onFinishInput() {
1685 InputConnection ic = getCurrentInputConnection();
1686 if (ic != null) {
1687 ic.finishComposingText();
1688 }
1689 }
1690
1691 /**
1692 * Called when the application has reported auto-completion candidates that
1693 * it would like to have the input method displayed. Typically these are
1694 * only used when an input method is running in full-screen mode, since
1695 * otherwise the user can see and interact with the pop-up window of
1696 * completions shown by the application.
1697 *
1698 * <p>The default implementation here does nothing.
1699 */
1700 public void onDisplayCompletions(CompletionInfo[] completions) {
Gilles Debunne34703b62011-09-08 11:16:25 -07001701 // Intentionally empty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 }
1703
1704 /**
1705 * Called when the application has reported new extracted text to be shown
1706 * due to changes in its current text state. The default implementation
1707 * here places the new text in the extract edit text, when the input
1708 * method is running in fullscreen mode.
1709 */
1710 public void onUpdateExtractedText(int token, ExtractedText text) {
1711 if (mExtractedToken != token) {
1712 return;
1713 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001714 if (text != null) {
1715 if (mExtractEditText != null) {
1716 mExtractedText = text;
1717 mExtractEditText.setExtractedText(text);
1718 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001719 }
1720 }
1721
1722 /**
1723 * Called when the application has reported a new selection region of
1724 * the text. This is called whether or not the input method has requested
1725 * extracted text updates, although if so it will not receive this call
1726 * if the extracted text has changed as well.
Jean Chalardc743cb92013-09-12 16:28:45 +09001727 *
1728 * <p>Be careful about changing the text in reaction to this call with
1729 * methods such as setComposingText, commitText or
1730 * deleteSurroundingText. If the cursor moves as a result, this method
1731 * will be called again, which may result in an infinite loop.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001732 *
1733 * <p>The default implementation takes care of updating the cursor in
1734 * the extract text, if it is being shown.
1735 */
1736 public void onUpdateSelection(int oldSelStart, int oldSelEnd,
1737 int newSelStart, int newSelEnd,
1738 int candidatesStart, int candidatesEnd) {
1739 final ExtractEditText eet = mExtractEditText;
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07001740 if (eet != null && isFullscreenMode() && mExtractedText != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 final int off = mExtractedText.startOffset;
1742 eet.startInternalChanges();
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07001743 newSelStart -= off;
1744 newSelEnd -= off;
1745 final int len = eet.getText().length();
1746 if (newSelStart < 0) newSelStart = 0;
1747 else if (newSelStart > len) newSelStart = len;
1748 if (newSelEnd < 0) newSelEnd = 0;
1749 else if (newSelEnd > len) newSelEnd = len;
1750 eet.setSelection(newSelStart, newSelEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751 eet.finishInternalChanges();
1752 }
1753 }
1754
1755 /**
satok863fcd62011-06-21 17:38:02 +09001756 * Called when the user tapped or clicked a text view.
1757 * IMEs can't rely on this method being called because this was not part of the original IME
1758 * protocol, so applications with custom text editing written before this method appeared will
1759 * not call to inform the IME of this interaction.
1760 * @param focusChanged true if the user changed the focused view by this click.
1761 */
1762 public void onViewClicked(boolean focusChanged) {
Gilles Debunne34703b62011-09-08 11:16:25 -07001763 // Intentionally empty
satok863fcd62011-06-21 17:38:02 +09001764 }
1765
1766 /**
Yohei Yukawaa277db22014-08-21 18:38:44 -07001767 * Called when the application has reported a new location of its text
1768 * cursor. This is only called if explicitly requested by the input method.
1769 * The default implementation does nothing.
1770 * @deprecated Use {#link onUpdateCursorAnchorInfo(CursorAnchorInfo)} instead.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 */
Yohei Yukawaa277db22014-08-21 18:38:44 -07001772 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 public void onUpdateCursor(Rect newCursor) {
Gilles Debunne34703b62011-09-08 11:16:25 -07001774 // Intentionally empty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001775 }
1776
1777 /**
Yohei Yukawac2ddd602014-05-06 21:22:49 +09001778 * Called when the application has reported a new location of its text insertion point and
1779 * characters in the composition string. This is only called if explicitly requested by the
1780 * input method. The default implementation does nothing.
1781 * @param cursorAnchorInfo The positional information of the text insertion point and the
1782 * composition string.
1783 */
1784 public void onUpdateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo) {
1785 // Intentionally empty
1786 }
1787
1788 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789 * Close this input method's soft input area, removing it from the display.
1790 * The input method will continue running, but the user can no longer use
1791 * it to generate input by touching the screen.
1792 * @param flags Provides additional operating flags. Currently may be
1793 * 0 or have the {@link InputMethodManager#HIDE_IMPLICIT_ONLY
1794 * InputMethodManager.HIDE_IMPLICIT_ONLY} bit set.
1795 */
The Android Open Source Project4df24232009-03-05 14:34:35 -08001796 public void requestHideSelf(int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 mImm.hideSoftInputFromInputMethod(mToken, flags);
1798 }
1799
1800 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -08001801 * Show the input method. This is a call back to the
1802 * IMF to handle showing the input method.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001803 * @param flags Provides additional operating flags. Currently may be
1804 * 0 or have the {@link InputMethodManager#SHOW_FORCED
1805 * InputMethodManager.} bit set.
1806 */
1807 private void requestShowSelf(int flags) {
1808 mImm.showSoftInputFromInputMethod(mToken, flags);
1809 }
Andrei Stingaceanu1036c742015-06-11 14:34:50 +00001810
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07001811 private boolean handleBack(boolean doIt) {
1812 if (mShowInputRequested) {
1813 // If the soft input area is shown, back closes it and we
1814 // consume the back key.
1815 if (doIt) requestHideSelf(0);
1816 return true;
1817 } else if (mWindowVisible) {
1818 if (mCandidatesVisibility == View.VISIBLE) {
1819 // If we are showing candidates even if no input area, then
1820 // hide them.
1821 if (doIt) setCandidatesViewShown(false);
1822 } else {
1823 // If we have the window visible for some other reason --
1824 // most likely to show candidates -- then just get rid
1825 // of it. This really shouldn't happen, but just in case...
satok2f913d92012-05-10 01:48:03 +09001826 if (doIt) doHideWindow();
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07001827 }
1828 return true;
1829 }
1830 return false;
1831 }
Yohei Yukawa38940aa2015-06-24 00:20:24 -07001832
1833 /**
1834 * @return {#link ExtractEditText} if it is considered to be visible and active. Otherwise
1835 * {@code null} is returned.
1836 */
1837 private ExtractEditText getExtractEditTextIfVisible() {
1838 if (!isExtractViewShown() || !isInputViewShown()) {
1839 return null;
1840 }
1841 return mExtractEditText;
1842 }
1843
The Android Open Source Project4df24232009-03-05 14:34:35 -08001844 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001845 * Override this to intercept key down events before they are processed by the
Quddus Chongee71b1f2012-04-12 11:49:37 -07001846 * application. If you return true, the application will not
1847 * process the event itself. If you return false, the normal application processing
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848 * will occur as if the IME had not seen the event at all.
1849 *
1850 * <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07001851 * KeyEvent.KEYCODE_BACK} if the IME is currently shown, to
1852 * possibly hide it when the key goes up (if not canceled or long pressed). In
1853 * addition, in fullscreen mode only, it will consume DPAD movement
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854 * events to move the cursor in the extracted text view, not allowing
1855 * them to perform navigation in the underlying application.
1856 */
1857 public boolean onKeyDown(int keyCode, KeyEvent event) {
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07001858 if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
Yohei Yukawa38940aa2015-06-24 00:20:24 -07001859 final ExtractEditText eet = getExtractEditTextIfVisible();
1860 if (eet != null && eet.handleBackInTextActionModeIfNeeded(event)) {
1861 return true;
1862 }
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07001863 if (handleBack(false)) {
1864 event.startTracking();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001865 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001866 }
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07001867 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 return doMovementKey(keyCode, event, MOVEMENT_DOWN);
1870 }
1871
1872 /**
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07001873 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
1874 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
1875 * the event).
1876 */
1877 public boolean onKeyLongPress(int keyCode, KeyEvent event) {
1878 return false;
1879 }
1880
1881 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001882 * Override this to intercept special key multiple events before they are
1883 * processed by the
1884 * application. If you return true, the application will not itself
Victoria Leaseb38070c2012-08-24 13:46:02 -07001885 * process the event. If you return false, the normal application processing
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 * will occur as if the IME had not seen the event at all.
1887 *
1888 * <p>The default implementation always returns false, except when
1889 * in fullscreen mode, where it will consume DPAD movement
1890 * events to move the cursor in the extracted text view, not allowing
1891 * them to perform navigation in the underlying application.
1892 */
1893 public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
1894 return doMovementKey(keyCode, event, count);
1895 }
1896
1897 /**
1898 * Override this to intercept key up events before they are processed by the
1899 * application. If you return true, the application will not itself
Victoria Leaseb38070c2012-08-24 13:46:02 -07001900 * process the event. If you return false, the normal application processing
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001901 * will occur as if the IME had not seen the event at all.
1902 *
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07001903 * <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK
1904 * KeyEvent.KEYCODE_BACK} to hide the current IME UI if it is shown. In
1905 * addition, in fullscreen mode only, it will consume DPAD movement
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001906 * events to move the cursor in the extracted text view, not allowing
1907 * them to perform navigation in the underlying application.
1908 */
1909 public boolean onKeyUp(int keyCode, KeyEvent event) {
Yohei Yukawa38940aa2015-06-24 00:20:24 -07001910 if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
1911 final ExtractEditText eet = getExtractEditTextIfVisible();
1912 if (eet != null && eet.handleBackInTextActionModeIfNeeded(event)) {
1913 return true;
1914 }
1915 if (event.isTracking() && !event.isCanceled()) {
1916 return handleBack(true);
1917 }
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07001918 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001919 return doMovementKey(keyCode, event, MOVEMENT_UP);
1920 }
1921
Victoria Leaseb38070c2012-08-24 13:46:02 -07001922 /**
1923 * Override this to intercept trackball motion events before they are
1924 * processed by the application.
1925 * If you return true, the application will not itself process the event.
1926 * If you return false, the normal application processing will occur as if
1927 * the IME had not seen the event at all.
1928 */
satokab751aa2010-09-14 19:17:36 +09001929 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 public boolean onTrackballEvent(MotionEvent event) {
Victoria Leaseb38070c2012-08-24 13:46:02 -07001931 if (DEBUG) Log.v(TAG, "onTrackballEvent: " + event);
1932 return false;
1933 }
1934
1935 /**
1936 * Override this to intercept generic motion events before they are
1937 * processed by the application.
1938 * If you return true, the application will not itself process the event.
1939 * If you return false, the normal application processing will occur as if
1940 * the IME had not seen the event at all.
1941 */
1942 @Override
1943 public boolean onGenericMotionEvent(MotionEvent event) {
1944 if (DEBUG) Log.v(TAG, "onGenericMotionEvent(): event " + event);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001945 return false;
1946 }
1947
1948 public void onAppPrivateCommand(String action, Bundle data) {
1949 }
1950
The Android Open Source Project4df24232009-03-05 14:34:35 -08001951 /**
1952 * Handle a request by the system to toggle the soft input area.
1953 */
1954 private void onToggleSoftInput(int showFlags, int hideFlags) {
1955 if (DEBUG) Log.v(TAG, "toggleSoftInput()");
1956 if (isInputViewShown()) {
1957 requestHideSelf(hideFlags);
1958 } else {
1959 requestShowSelf(showFlags);
1960 }
1961 }
1962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001963 static final int MOVEMENT_DOWN = -1;
1964 static final int MOVEMENT_UP = -2;
1965
1966 void reportExtractedMovement(int keyCode, int count) {
1967 int dx = 0, dy = 0;
1968 switch (keyCode) {
1969 case KeyEvent.KEYCODE_DPAD_LEFT:
1970 dx = -count;
1971 break;
1972 case KeyEvent.KEYCODE_DPAD_RIGHT:
1973 dx = count;
1974 break;
1975 case KeyEvent.KEYCODE_DPAD_UP:
1976 dy = -count;
1977 break;
1978 case KeyEvent.KEYCODE_DPAD_DOWN:
1979 dy = count;
1980 break;
1981 }
satokab751aa2010-09-14 19:17:36 +09001982 onExtractedCursorMovement(dx, dy);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001983 }
Yohei Yukawa38940aa2015-06-24 00:20:24 -07001984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985 boolean doMovementKey(int keyCode, KeyEvent event, int count) {
Yohei Yukawa38940aa2015-06-24 00:20:24 -07001986 final ExtractEditText eet = getExtractEditTextIfVisible();
1987 if (eet != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001988 // If we are in fullscreen mode, the cursor will move around
1989 // the extract edit text, but should NOT cause focus to move
1990 // to other fields.
1991 MovementMethod movement = eet.getMovementMethod();
1992 Layout layout = eet.getLayout();
1993 if (movement != null && layout != null) {
1994 // We want our own movement method to handle the key, so the
1995 // cursor will properly move in our own word wrapping.
1996 if (count == MOVEMENT_DOWN) {
Yohei Yukawa24182f32015-09-11 18:33:33 -07001997 if (movement.onKeyDown(eet, eet.getText(), keyCode, event)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001998 reportExtractedMovement(keyCode, 1);
1999 return true;
2000 }
2001 } else if (count == MOVEMENT_UP) {
Yohei Yukawa24182f32015-09-11 18:33:33 -07002002 if (movement.onKeyUp(eet, eet.getText(), keyCode, event)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002003 return true;
2004 }
2005 } else {
Yohei Yukawa24182f32015-09-11 18:33:33 -07002006 if (movement.onKeyOther(eet, eet.getText(), event)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002007 reportExtractedMovement(keyCode, count);
2008 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002009 KeyEvent down = KeyEvent.changeAction(event, KeyEvent.ACTION_DOWN);
Yohei Yukawa24182f32015-09-11 18:33:33 -07002010 if (movement.onKeyDown(eet, eet.getText(), keyCode, down)) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002011 KeyEvent up = KeyEvent.changeAction(event, KeyEvent.ACTION_UP);
Yohei Yukawa24182f32015-09-11 18:33:33 -07002012 movement.onKeyUp(eet, eet.getText(), keyCode, up);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002013 while (--count > 0) {
Yohei Yukawa24182f32015-09-11 18:33:33 -07002014 movement.onKeyDown(eet, eet.getText(), keyCode, down);
2015 movement.onKeyUp(eet, eet.getText(), keyCode, up);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002016 }
2017 reportExtractedMovement(keyCode, count);
2018 }
2019 }
2020 }
2021 }
2022 // Regardless of whether the movement method handled the key,
2023 // we never allow DPAD navigation to the application.
2024 switch (keyCode) {
2025 case KeyEvent.KEYCODE_DPAD_LEFT:
2026 case KeyEvent.KEYCODE_DPAD_RIGHT:
2027 case KeyEvent.KEYCODE_DPAD_UP:
2028 case KeyEvent.KEYCODE_DPAD_DOWN:
2029 return true;
2030 }
2031 }
Yohei Yukawa38940aa2015-06-24 00:20:24 -07002032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002033 return false;
2034 }
2035
2036 /**
2037 * Send the given key event code (as defined by {@link KeyEvent}) to the
2038 * current input connection is a key down + key up event pair. The sent
2039 * events have {@link KeyEvent#FLAG_SOFT_KEYBOARD KeyEvent.FLAG_SOFT_KEYBOARD}
2040 * set, so that the recipient can identify them as coming from a software
2041 * input method, and
2042 * {@link KeyEvent#FLAG_KEEP_TOUCH_MODE KeyEvent.FLAG_KEEP_TOUCH_MODE}, so
2043 * that they don't impact the current touch mode of the UI.
2044 *
Jean Chalard405bc512012-05-29 19:12:34 +09002045 * <p>Note that it's discouraged to send such key events in normal operation;
2046 * this is mainly for use with {@link android.text.InputType#TYPE_NULL} type
2047 * text fields, or for non-rich input methods. A reasonably capable software
2048 * input method should use the
2049 * {@link android.view.inputmethod.InputConnection#commitText} family of methods
2050 * to send text to an application, rather than sending key events.</p>
2051 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002052 * @param keyEventCode The raw key code to send, as defined by
2053 * {@link KeyEvent}.
2054 */
2055 public void sendDownUpKeyEvents(int keyEventCode) {
2056 InputConnection ic = getCurrentInputConnection();
2057 if (ic == null) return;
2058 long eventTime = SystemClock.uptimeMillis();
2059 ic.sendKeyEvent(new KeyEvent(eventTime, eventTime,
Jeff Brown6b53e8d2010-11-10 16:03:06 -08002060 KeyEvent.ACTION_DOWN, keyEventCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061 KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
Tadashi G. Takaokacb95cd62012-10-26 17:20:59 +09002062 ic.sendKeyEvent(new KeyEvent(eventTime, SystemClock.uptimeMillis(),
Jeff Brown6b53e8d2010-11-10 16:03:06 -08002063 KeyEvent.ACTION_UP, keyEventCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
2065 }
2066
2067 /**
2068 * Ask the input target to execute its default action via
2069 * {@link InputConnection#performEditorAction
2070 * InputConnection.performEditorAction()}.
2071 *
2072 * @param fromEnterKey If true, this will be executed as if the user had
2073 * pressed an enter key on the keyboard, that is it will <em>not</em>
2074 * be done if the editor has set {@link EditorInfo#IME_FLAG_NO_ENTER_ACTION
2075 * EditorInfo.IME_FLAG_NO_ENTER_ACTION}. If false, the action will be
2076 * sent regardless of how the editor has set that flag.
2077 *
2078 * @return Returns a boolean indicating whether an action has been sent.
2079 * If false, either the editor did not specify a default action or it
2080 * does not want an action from the enter key. If true, the action was
2081 * sent (or there was no input connection at all).
2082 */
2083 public boolean sendDefaultEditorAction(boolean fromEnterKey) {
2084 EditorInfo ei = getCurrentInputEditorInfo();
2085 if (ei != null &&
2086 (!fromEnterKey || (ei.imeOptions &
2087 EditorInfo.IME_FLAG_NO_ENTER_ACTION) == 0) &&
2088 (ei.imeOptions & EditorInfo.IME_MASK_ACTION) !=
2089 EditorInfo.IME_ACTION_NONE) {
2090 // If the enter key was pressed, and the editor has a default
2091 // action associated with pressing enter, then send it that
2092 // explicit action instead of the key event.
2093 InputConnection ic = getCurrentInputConnection();
2094 if (ic != null) {
2095 ic.performEditorAction(ei.imeOptions&EditorInfo.IME_MASK_ACTION);
2096 }
2097 return true;
2098 }
2099
2100 return false;
2101 }
2102
2103 /**
2104 * Send the given UTF-16 character to the current input connection. Most
2105 * characters will be delivered simply by calling
2106 * {@link InputConnection#commitText InputConnection.commitText()} with
2107 * the character; some, however, may be handled different. In particular,
2108 * the enter character ('\n') will either be delivered as an action code
Jean Chalard405bc512012-05-29 19:12:34 +09002109 * or a raw key event, as appropriate. Consider this as a convenience
2110 * method for IMEs that do not have a full implementation of actions; a
2111 * fully complying IME will decide of the right action for each event and
2112 * will likely never call this method except maybe to handle events coming
2113 * from an actual hardware keyboard.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002114 *
2115 * @param charCode The UTF-16 character code to send.
2116 */
2117 public void sendKeyChar(char charCode) {
2118 switch (charCode) {
2119 case '\n': // Apps may be listening to an enter key to perform an action
2120 if (!sendDefaultEditorAction(true)) {
2121 sendDownUpKeyEvents(KeyEvent.KEYCODE_ENTER);
2122 }
2123 break;
2124 default:
2125 // Make sure that digits go through any text watcher on the client side.
2126 if (charCode >= '0' && charCode <= '9') {
2127 sendDownUpKeyEvents(charCode - '0' + KeyEvent.KEYCODE_0);
2128 } else {
2129 InputConnection ic = getCurrentInputConnection();
2130 if (ic != null) {
Yohei Yukawa24182f32015-09-11 18:33:33 -07002131 ic.commitText(String.valueOf(charCode), 1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132 }
2133 }
2134 break;
2135 }
2136 }
2137
2138 /**
2139 * This is called when the user has moved the cursor in the extracted
2140 * text view, when running in fullsreen mode. The default implementation
2141 * performs the corresponding selection change on the underlying text
2142 * editor.
2143 */
2144 public void onExtractedSelectionChanged(int start, int end) {
2145 InputConnection conn = getCurrentInputConnection();
2146 if (conn != null) {
2147 conn.setSelection(start, end);
2148 }
2149 }
Gilles Debunne39ba6d92011-11-09 05:26:26 +01002150
2151 /**
2152 * @hide
2153 */
2154 public void onExtractedDeleteText(int start, int end) {
2155 InputConnection conn = getCurrentInputConnection();
2156 if (conn != null) {
2157 conn.setSelection(start, start);
2158 conn.deleteSurroundingText(0, end-start);
2159 }
2160 }
2161
2162 /**
2163 * @hide
2164 */
2165 public void onExtractedReplaceText(int start, int end, CharSequence text) {
2166 InputConnection conn = getCurrentInputConnection();
2167 if (conn != null) {
2168 conn.setComposingRegion(start, end);
2169 conn.commitText(text, 1);
2170 }
2171 }
2172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002173 /**
Gilles Debunnee300be92011-12-06 10:15:56 -08002174 * @hide
2175 */
2176 public void onExtractedSetSpan(Object span, int start, int end, int flags) {
2177 InputConnection conn = getCurrentInputConnection();
2178 if (conn != null) {
2179 if (!conn.setSelection(start, end)) return;
2180 CharSequence text = conn.getSelectedText(InputConnection.GET_TEXT_WITH_STYLES);
2181 if (text instanceof Spannable) {
2182 ((Spannable) text).setSpan(span, 0, text.length(), flags);
2183 conn.setComposingRegion(start, end);
2184 conn.commitText(text, 1);
2185 }
2186 }
2187 }
2188
2189 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002190 * This is called when the user has clicked on the extracted text view,
2191 * when running in fullscreen mode. The default implementation hides
2192 * the candidates view when this happens, but only if the extracted text
2193 * editor has a vertical scroll bar because its text doesn't fit.
2194 * Re-implement this to provide whatever behavior you want.
2195 */
2196 public void onExtractedTextClicked() {
2197 if (mExtractEditText == null) {
2198 return;
2199 }
2200 if (mExtractEditText.hasVerticalScrollBar()) {
2201 setCandidatesViewShown(false);
2202 }
2203 }
Gilles Debunne39ba6d92011-11-09 05:26:26 +01002204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002205 /**
2206 * This is called when the user has performed a cursor movement in the
2207 * extracted text view, when it is running in fullscreen mode. The default
2208 * implementation hides the candidates view when a vertical movement
2209 * happens, but only if the extracted text editor has a vertical scroll bar
2210 * because its text doesn't fit.
2211 * Re-implement this to provide whatever behavior you want.
2212 * @param dx The amount of cursor movement in the x dimension.
2213 * @param dy The amount of cursor movement in the y dimension.
2214 */
2215 public void onExtractedCursorMovement(int dx, int dy) {
2216 if (mExtractEditText == null || dy == 0) {
2217 return;
2218 }
2219 if (mExtractEditText.hasVerticalScrollBar()) {
2220 setCandidatesViewShown(false);
2221 }
2222 }
2223
2224 /**
2225 * This is called when the user has selected a context menu item from the
2226 * extracted text view, when running in fullscreen mode. The default
2227 * implementation sends this action to the current InputConnection's
2228 * {@link InputConnection#performContextMenuAction(int)}, for it
2229 * to be processed in underlying "real" editor. Re-implement this to
2230 * provide whatever behavior you want.
2231 */
2232 public boolean onExtractTextContextMenuItem(int id) {
2233 InputConnection ic = getCurrentInputConnection();
2234 if (ic != null) {
2235 ic.performContextMenuAction(id);
2236 }
2237 return true;
2238 }
2239
2240 /**
2241 * Return text that can be used as a button label for the given
2242 * {@link EditorInfo#imeOptions EditorInfo.imeOptions}. Returns null
2243 * if there is no action requested. Note that there is no guarantee that
2244 * the returned text will be relatively short, so you probably do not
2245 * want to use it as text on a soft keyboard key label.
2246 *
2247 * @param imeOptions The value from @link EditorInfo#imeOptions EditorInfo.imeOptions}.
2248 *
2249 * @return Returns a label to use, or null if there is no action.
2250 */
2251 public CharSequence getTextForImeAction(int imeOptions) {
2252 switch (imeOptions&EditorInfo.IME_MASK_ACTION) {
2253 case EditorInfo.IME_ACTION_NONE:
2254 return null;
2255 case EditorInfo.IME_ACTION_GO:
2256 return getText(com.android.internal.R.string.ime_action_go);
2257 case EditorInfo.IME_ACTION_SEARCH:
2258 return getText(com.android.internal.R.string.ime_action_search);
2259 case EditorInfo.IME_ACTION_SEND:
2260 return getText(com.android.internal.R.string.ime_action_send);
2261 case EditorInfo.IME_ACTION_NEXT:
2262 return getText(com.android.internal.R.string.ime_action_next);
The Android Open Source Project4df24232009-03-05 14:34:35 -08002263 case EditorInfo.IME_ACTION_DONE:
2264 return getText(com.android.internal.R.string.ime_action_done);
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002265 case EditorInfo.IME_ACTION_PREVIOUS:
2266 return getText(com.android.internal.R.string.ime_action_previous);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002267 default:
2268 return getText(com.android.internal.R.string.ime_action_default);
2269 }
2270 }
2271
2272 /**
The Android Open Source Project10592532009-03-18 17:39:46 -07002273 * Called when the fullscreen-mode extracting editor info has changed,
2274 * to determine whether the extracting (extract text and candidates) portion
2275 * of the UI should be shown. The standard implementation hides or shows
2276 * the extract area depending on whether it makes sense for the
2277 * current editor. In particular, a {@link InputType#TYPE_NULL}
2278 * input type or {@link EditorInfo#IME_FLAG_NO_EXTRACT_UI} flag will
2279 * turn off the extract area since there is no text to be shown.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002280 */
The Android Open Source Project10592532009-03-18 17:39:46 -07002281 public void onUpdateExtractingVisibility(EditorInfo ei) {
2282 if (ei.inputType == InputType.TYPE_NULL ||
2283 (ei.imeOptions&EditorInfo.IME_FLAG_NO_EXTRACT_UI) != 0) {
2284 // No reason to show extract UI!
2285 setExtractViewShown(false);
2286 return;
2287 }
2288
2289 setExtractViewShown(true);
2290 }
2291
2292 /**
2293 * Called when the fullscreen-mode extracting editor info has changed,
2294 * to update the state of its UI such as the action buttons shown.
2295 * You do not need to deal with this if you are using the standard
2296 * full screen extract UI. If replacing it, you will need to re-implement
2297 * this to put the appropriate action button in your own UI and handle it,
2298 * and perform any other changes.
2299 *
2300 * <p>The standard implementation turns on or off its accessory area
2301 * depending on whether there is an action button, and hides or shows
2302 * the entire extract area depending on whether it makes sense for the
2303 * current editor. In particular, a {@link InputType#TYPE_NULL} or
2304 * {@link InputType#TYPE_TEXT_VARIATION_FILTER} input type will turn off the
2305 * extract area since there is no text to be shown.
2306 */
2307 public void onUpdateExtractingViews(EditorInfo ei) {
2308 if (!isExtractViewShown()) {
2309 return;
2310 }
2311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312 if (mExtractAccessories == null) {
2313 return;
2314 }
2315 final boolean hasAction = ei.actionLabel != null || (
2316 (ei.imeOptions&EditorInfo.IME_MASK_ACTION) != EditorInfo.IME_ACTION_NONE &&
The Android Open Source Project10592532009-03-18 17:39:46 -07002317 (ei.imeOptions&EditorInfo.IME_FLAG_NO_ACCESSORY_ACTION) == 0 &&
2318 ei.inputType != InputType.TYPE_NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002319 if (hasAction) {
2320 mExtractAccessories.setVisibility(View.VISIBLE);
Steve Kondik59eb6912009-09-07 22:53:34 -04002321 if (mExtractAction != null) {
2322 if (ei.actionLabel != null) {
2323 mExtractAction.setText(ei.actionLabel);
2324 } else {
2325 mExtractAction.setText(getTextForImeAction(ei.imeOptions));
2326 }
2327 mExtractAction.setOnClickListener(mActionClickListener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002329 } else {
2330 mExtractAccessories.setVisibility(View.GONE);
Steve Kondik59eb6912009-09-07 22:53:34 -04002331 if (mExtractAction != null) {
2332 mExtractAction.setOnClickListener(null);
2333 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002334 }
2335 }
2336
2337 /**
2338 * This is called when, while currently displayed in extract mode, the
2339 * current input target changes. The default implementation will
2340 * auto-hide the IME if the new target is not a full editor, since this
Ken Wakasaf76a50c2012-03-09 19:56:35 +09002341 * can be a confusing experience for the user.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002342 */
2343 public void onExtractingInputChanged(EditorInfo ei) {
2344 if (ei.inputType == InputType.TYPE_NULL) {
The Android Open Source Project4df24232009-03-05 14:34:35 -08002345 requestHideSelf(InputMethodManager.HIDE_NOT_ALWAYS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002346 }
2347 }
2348
2349 void startExtractingText(boolean inputChanged) {
2350 final ExtractEditText eet = mExtractEditText;
2351 if (eet != null && getCurrentInputStarted()
2352 && isFullscreenMode()) {
2353 mExtractedToken++;
2354 ExtractedTextRequest req = new ExtractedTextRequest();
2355 req.token = mExtractedToken;
2356 req.flags = InputConnection.GET_TEXT_WITH_STYLES;
2357 req.hintMaxLines = 10;
2358 req.hintMaxChars = 10000;
Amith Yamasaniba4d93f2009-08-19 18:27:56 -07002359 InputConnection ic = getCurrentInputConnection();
2360 mExtractedText = ic == null? null
2361 : ic.getExtractedText(req, InputConnection.GET_EXTRACTED_TEXT_MONITOR);
Amith Yamasania8b00c82010-03-05 15:41:31 -08002362 if (mExtractedText == null || ic == null) {
2363 Log.e(TAG, "Unexpected null in startExtractingText : mExtractedText = "
2364 + mExtractedText + ", input connection = " + ic);
2365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002366 final EditorInfo ei = getCurrentInputEditorInfo();
2367
2368 try {
2369 eet.startInternalChanges();
The Android Open Source Project10592532009-03-18 17:39:46 -07002370 onUpdateExtractingVisibility(ei);
2371 onUpdateExtractingViews(ei);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002372 int inputType = ei.inputType;
2373 if ((inputType&EditorInfo.TYPE_MASK_CLASS)
2374 == EditorInfo.TYPE_CLASS_TEXT) {
2375 if ((inputType&EditorInfo.TYPE_TEXT_FLAG_IME_MULTI_LINE) != 0) {
2376 inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
2377 }
2378 }
2379 eet.setInputType(inputType);
2380 eet.setHint(ei.hintText);
2381 if (mExtractedText != null) {
2382 eet.setEnabled(true);
2383 eet.setExtractedText(mExtractedText);
2384 } else {
2385 eet.setEnabled(false);
2386 eet.setText("");
2387 }
2388 } finally {
2389 eet.finishInternalChanges();
2390 }
2391
2392 if (inputChanged) {
2393 onExtractingInputChanged(ei);
2394 }
2395 }
2396 }
satokab751aa2010-09-14 19:17:36 +09002397
2398 // TODO: Handle the subtype change event
2399 /**
2400 * Called when the subtype was changed.
2401 * @param newSubtype the subtype which is being changed to.
2402 */
2403 protected void onCurrentInputMethodSubtypeChanged(InputMethodSubtype newSubtype) {
2404 if (DEBUG) {
2405 int nameResId = newSubtype.getNameResId();
satok9ef02832010-11-04 21:17:48 +09002406 String mode = newSubtype.getMode();
satokab751aa2010-09-14 19:17:36 +09002407 String output = "changeInputMethodSubtype:"
2408 + (nameResId == 0 ? "<none>" : getString(nameResId)) + ","
satok9ef02832010-11-04 21:17:48 +09002409 + mode + ","
satokab751aa2010-09-14 19:17:36 +09002410 + newSubtype.getLocale() + "," + newSubtype.getExtraValue();
2411 Log.v(TAG, "--- " + output);
2412 }
2413 }
2414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002415 /**
Satoshi Kataoka658c7b82013-10-10 17:03:51 +09002416 * @return The recommended height of the input method window.
2417 * An IME author can get the last input method's height as the recommended height
2418 * by calling this in
2419 * {@link android.inputmethodservice.InputMethodService#onStartInputView(EditorInfo, boolean)}.
2420 * If you don't need to use a predefined fixed height, you can avoid the window-resizing of IME
2421 * switching by using this value as a visible inset height. It's efficient for the smooth
2422 * transition between different IMEs. However, note that this may return 0 (or possibly
2423 * unexpectedly low height). You should thus avoid relying on the return value of this method
2424 * all the time. Please make sure to use a reasonable height for the IME.
2425 */
2426 public int getInputMethodWindowRecommendedHeight() {
2427 return mImm.getInputMethodWindowVisibleHeight();
2428 }
2429
2430 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002431 * Performs a dump of the InputMethodService's internal state. Override
2432 * to add your own information to the dump.
2433 */
2434 @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
2435 final Printer p = new PrintWriterPrinter(fout);
2436 p.println("Input method service state for " + this + ":");
2437 p.println(" mWindowCreated=" + mWindowCreated
The Android Open Source Project10592532009-03-18 17:39:46 -07002438 + " mWindowAdded=" + mWindowAdded);
2439 p.println(" mWindowVisible=" + mWindowVisible
2440 + " mWindowWasVisible=" + mWindowWasVisible
2441 + " mInShowWindow=" + mInShowWindow);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002442 p.println(" Configuration=" + getResources().getConfiguration());
2443 p.println(" mToken=" + mToken);
2444 p.println(" mInputBinding=" + mInputBinding);
2445 p.println(" mInputConnection=" + mInputConnection);
2446 p.println(" mStartedInputConnection=" + mStartedInputConnection);
2447 p.println(" mInputStarted=" + mInputStarted
2448 + " mInputViewStarted=" + mInputViewStarted
2449 + " mCandidatesViewStarted=" + mCandidatesViewStarted);
2450
2451 if (mInputEditorInfo != null) {
2452 p.println(" mInputEditorInfo:");
2453 mInputEditorInfo.dump(p, " ");
2454 } else {
2455 p.println(" mInputEditorInfo: null");
2456 }
2457
2458 p.println(" mShowInputRequested=" + mShowInputRequested
2459 + " mLastShowInputRequested=" + mLastShowInputRequested
2460 + " mShowInputForced=" + mShowInputForced
2461 + " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags));
2462 p.println(" mCandidatesVisibility=" + mCandidatesVisibility
2463 + " mFullscreenApplied=" + mFullscreenApplied
The Android Open Source Project10592532009-03-18 17:39:46 -07002464 + " mIsFullscreen=" + mIsFullscreen
2465 + " mExtractViewHidden=" + mExtractViewHidden);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002466
2467 if (mExtractedText != null) {
2468 p.println(" mExtractedText:");
2469 p.println(" text=" + mExtractedText.text.length() + " chars"
2470 + " startOffset=" + mExtractedText.startOffset);
2471 p.println(" selectionStart=" + mExtractedText.selectionStart
2472 + " selectionEnd=" + mExtractedText.selectionEnd
2473 + " flags=0x" + Integer.toHexString(mExtractedText.flags));
2474 } else {
2475 p.println(" mExtractedText: null");
2476 }
2477 p.println(" mExtractedToken=" + mExtractedToken);
2478 p.println(" mIsInputViewShown=" + mIsInputViewShown
2479 + " mStatusIcon=" + mStatusIcon);
2480 p.println("Last computed insets:");
2481 p.println(" contentTopInsets=" + mTmpInsets.contentTopInsets
2482 + " visibleTopInsets=" + mTmpInsets.visibleTopInsets
Jeff Brownfbf09772011-01-16 14:06:57 -08002483 + " touchableInsets=" + mTmpInsets.touchableInsets
2484 + " touchableRegion=" + mTmpInsets.touchableRegion);
Yohei Yukawa2977eb72015-05-27 18:54:18 -07002485 p.println(" mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002486 }
2487}