From 00245473dbdf5469ad40d1ca6d2f53a87462efcb Mon Sep 17 00:00:00 2001 From: Andrei Stingaceanu Date: Thu, 11 Jun 2015 14:38:58 +0100 Subject: Completely remove ExtractActionMode - master cherrypick Use the floating toolbar action mode instead. This CL is identical to ag/701639. The merge to master was skipped due to a conflict. This is the 'manual merge' Bug: 20128047 Change-Id: I5ef9b4b5b9574a4a360a853b2d1abd5b374f2fd5 --- core/java/android/inputmethodservice/InputMethodService.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index a7afa91e3fae..ae74b9aaed8b 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1797,16 +1797,9 @@ public class InputMethodService extends AbstractInputMethodService { private void requestShowSelf(int flags) { mImm.showSoftInputFromInputMethod(mToken, flags); } - + private boolean handleBack(boolean doIt) { if (mShowInputRequested) { - if (isExtractViewShown() && mExtractView instanceof ExtractEditLayout) { - ExtractEditLayout extractEditLayout = (ExtractEditLayout) mExtractView; - if (extractEditLayout.isActionModeStarted()) { - if (doIt) extractEditLayout.finishActionMode(); - return true; - } - } // If the soft input area is shown, back closes it and we // consume the back key. if (doIt) requestHideSelf(0); -- cgit v1.2.3 From 1036c74784d8f8ca7232aaa26b1b0c3796c29d1d Mon Sep 17 00:00:00 2001 From: Andrei Stingaceanu Date: Thu, 11 Jun 2015 14:34:50 +0000 Subject: Revert "Completely remove ExtractActionMode - master cherrypick" This reverts commit 00245473dbdf5469ad40d1ca6d2f53a87462efcb. Change-Id: If078c09fbdfd00d005ff58d543f03601b96eef0a --- core/java/android/inputmethodservice/InputMethodService.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index ae74b9aaed8b..a7afa91e3fae 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1797,9 +1797,16 @@ public class InputMethodService extends AbstractInputMethodService { private void requestShowSelf(int flags) { mImm.showSoftInputFromInputMethod(mToken, flags); } - + private boolean handleBack(boolean doIt) { if (mShowInputRequested) { + if (isExtractViewShown() && mExtractView instanceof ExtractEditLayout) { + ExtractEditLayout extractEditLayout = (ExtractEditLayout) mExtractView; + if (extractEditLayout.isActionModeStarted()) { + if (doIt) extractEditLayout.finishActionMode(); + return true; + } + } // If the soft input area is shown, back closes it and we // consume the back key. if (doIt) requestHideSelf(0); -- cgit v1.2.3 From 710645eb36e88a6a788f51bea9edbeee53853de1 Mon Sep 17 00:00:00 2001 From: Andrei Stingaceanu Date: Thu, 11 Jun 2015 16:40:12 +0100 Subject: Remove ExtractEditAction - part 1 Use the floating toolbar action mode instead. This change is identical to 7315b15a034eeb2d9a4cd24c100023c048ca (minus string changes). Due to scary conflicts in strings I will make the string changes in the next CL. Change-Id: Ia66ef5e886df1fc42a8e1ba52d77141e1e88dbd4 --- core/java/android/inputmethodservice/InputMethodService.java | 7 ------- 1 file changed, 7 deletions(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index a7afa91e3fae..e163d5adf4d7 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1800,13 +1800,6 @@ public class InputMethodService extends AbstractInputMethodService { private boolean handleBack(boolean doIt) { if (mShowInputRequested) { - if (isExtractViewShown() && mExtractView instanceof ExtractEditLayout) { - ExtractEditLayout extractEditLayout = (ExtractEditLayout) mExtractView; - if (extractEditLayout.isActionModeStarted()) { - if (doIt) extractEditLayout.finishActionMode(); - return true; - } - } // If the soft input area is shown, back closes it and we // consume the back key. if (doIt) requestHideSelf(0); -- cgit v1.2.3 From 93c47eab2b4e11103b29f923bdda932569d0b6a5 Mon Sep 17 00:00:00 2001 From: Seigo Nonaka Date: Tue, 14 Jul 2015 15:05:04 +0900 Subject: Update fullscreen state on hiding window. Need to update fullscreen state on hiding window as well as showing window, otherwise IMM#isFullscreenWindow reports obsolete state after hiding window by back key or device rotation. Bug: 22238567 Change-Id: Ic8de161cd5d2ee161f32b9942cdc2c331ea4d48e --- core/java/android/inputmethodservice/InputMethodService.java | 1 + 1 file changed, 1 insertion(+) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 3b996845b7d1..112ae1076aa3 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1538,6 +1538,7 @@ public class InputMethodService extends AbstractInputMethodService { onWindowHidden(); mWindowWasVisible = false; } + updateFullscreenMode(); } /** -- cgit v1.2.3 From ac8bdd203c18d0f99b825132cf6134dce5d12bc6 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Fri, 11 Sep 2015 18:17:11 -0700 Subject: Mechanical merge of nested if statements. This is just a mechanical merge of nested if statements with a dead code removal. Nothing is changed logically. Bug: 22285167 Change-Id: I28c1de84635b68108b25ec32ec58de2128758512 --- core/java/android/inputmethodservice/InputMethodService.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 112ae1076aa3..5d667e1fa3f2 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1456,15 +1456,9 @@ public class InputMethodService extends AbstractInputMethodService { final int previousImeWindowStatus = (mWindowVisible ? IME_ACTIVE : 0) | (isInputViewShown() ? IME_VISIBLE : 0); mWindowVisible = true; - if (!mShowInputRequested) { - if (mInputStarted) { - if (showInput) { - doShowInput = true; - mShowInputRequested = true; - } - } - } else { - showInput = true; + if (!mShowInputRequested && mInputStarted && showInput) { + doShowInput = true; + mShowInputRequested = true; } if (DEBUG) Log.v(TAG, "showWindow: updating UI"); -- cgit v1.2.3 From 24182f3dacf2d2f1b77e5eadd38547f11cd4270d Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Fri, 11 Sep 2015 18:33:33 -0700 Subject: Remove redundant casts. This Cl is just a mechanical removal of redundant casts. Nothing is changed logically. Bug: 22285167 Change-Id: I460b781753553c002b6cd232ae5918b7acd616d9 --- .../inputmethodservice/InputMethodService.java | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 112ae1076aa3..aad759e0f734 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1985,31 +1985,25 @@ public class InputMethodService extends AbstractInputMethodService { // We want our own movement method to handle the key, so the // cursor will properly move in our own word wrapping. if (count == MOVEMENT_DOWN) { - if (movement.onKeyDown(eet, - (Spannable)eet.getText(), keyCode, event)) { + if (movement.onKeyDown(eet, eet.getText(), keyCode, event)) { reportExtractedMovement(keyCode, 1); return true; } } else if (count == MOVEMENT_UP) { - if (movement.onKeyUp(eet, - (Spannable)eet.getText(), keyCode, event)) { + if (movement.onKeyUp(eet, eet.getText(), keyCode, event)) { return true; } } else { - if (movement.onKeyOther(eet, (Spannable)eet.getText(), event)) { + if (movement.onKeyOther(eet, eet.getText(), event)) { reportExtractedMovement(keyCode, count); } else { KeyEvent down = KeyEvent.changeAction(event, KeyEvent.ACTION_DOWN); - if (movement.onKeyDown(eet, - (Spannable)eet.getText(), keyCode, down)) { + if (movement.onKeyDown(eet, eet.getText(), keyCode, down)) { KeyEvent up = KeyEvent.changeAction(event, KeyEvent.ACTION_UP); - movement.onKeyUp(eet, - (Spannable)eet.getText(), keyCode, up); + movement.onKeyUp(eet, eet.getText(), keyCode, up); while (--count > 0) { - movement.onKeyDown(eet, - (Spannable)eet.getText(), keyCode, down); - movement.onKeyUp(eet, - (Spannable)eet.getText(), keyCode, up); + movement.onKeyDown(eet, eet.getText(), keyCode, down); + movement.onKeyUp(eet, eet.getText(), keyCode, up); } reportExtractedMovement(keyCode, count); } @@ -2125,7 +2119,7 @@ public class InputMethodService extends AbstractInputMethodService { } else { InputConnection ic = getCurrentInputConnection(); if (ic != null) { - ic.commitText(String.valueOf((char) charCode), 1); + ic.commitText(String.valueOf(charCode), 1); } } break; -- cgit v1.2.3 From 6fcbb5629019489a88a9748f278d40d554cc5cdc Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Mon, 14 Sep 2015 16:48:15 -0700 Subject: Handle BadTokenException exception more reliably. This is a follow up for I2c21573cf972145ab08e66604cdb9344139a3f31, which added BadTokenException handler so that we can deal with unavoidable runtime exceptions. However, it turns out that CL does not work well in a certain case. One problem in I2c21573cf972145ab08e66604cdb9344139a3f31 that it added the exception handler in the call site of InputMethodService#showWindow(boolean) rather than callee side as follows. try { showWindow(true); } catch (BadTokenException e) { if (DEBUG) Log.v(TAG, "BadTokenException: IME is done."); mWindowVisible = false; } However, the above code fails to update #mWindowVisible if an IME overrides InputMethodService#showWindow(boolean) but catch-and-ignore BadTokenException as follows. @Override public void showWindow(boolean showInput) { try { super.showWindow(showInput); // Do something if super.showWindow() succeeds. } catch (BadTokenException ex) { // Do something if super.showWindow() fails. } } With this CL, InputMethodService#mWindowVisible is always updated in the callee side whenever it should be. Note that this CL does not change anything about which method can throw BadTokenException and which method catch-and-ignores it so as not to break existing IMEs unexpectedly. Bug: 23798142 Change-Id: Id1e5f236f48c8ef01b7f157ba3f6e7ab2c26b135 --- .../inputmethodservice/InputMethodService.java | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 6e28982fe4f8..8ab8991c7a42 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -436,9 +436,12 @@ public class InputMethodService extends AbstractInputMethodService { try { showWindow(true); } catch (BadTokenException e) { - if (DEBUG) Log.v(TAG, "BadTokenException: IME is done."); - mWindowVisible = false; - mWindowAdded = false; + // We have ignored BadTokenException here since Jelly Bean MR-2 (API Level 18). + // We could ignore BadTokenException in InputMethodService#showWindow() instead, + // but it may break assumptions for those who override #showWindow() that we can + // detect errors in #showWindow() by checking BadTokenException. + // TODO: Investigate its feasibility. Update JavaDoc of #showWindow() of + // whether it's OK to override #showWindow() or not. } } clearInsetOfPreviousIme(); @@ -1445,7 +1448,19 @@ public class InputMethodService extends AbstractInputMethodService { mWindowWasVisible = mWindowVisible; mInShowWindow = true; showWindowInner(showInput); + } catch (BadTokenException e) { + // BadTokenException is a normal consequence in certain situations, e.g., swapping IMEs + // while there is a DO_SHOW_SOFT_INPUT message in the IIMethodWrapper queue. + if (DEBUG) Log.v(TAG, "BadTokenException: IME is done."); + mWindowVisible = false; + mWindowAdded = false; + // Rethrow the exception to preserve the existing behavior. Some IMEs may have directly + // called this method and relied on this exception for some clean-up tasks. + // TODO: Give developers a clear guideline of whether it's OK to call this method or + // InputMethodManager#showSoftInputFromInputMethod() should always be used instead. + throw e; } finally { + // TODO: Is it OK to set true when we get BadTokenException? mWindowWasVisible = true; mInShowWindow = false; } -- cgit v1.2.3 From 7b739a802cb7d97460a0bf8a1e9774efe96fa552 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Mon, 21 Dec 2015 13:30:44 -0800 Subject: Stop lying about hardware keyboard presence. Here is a brief history of "Use Physical Keyboard", or "Show input method", or SHOW_IME_WITH_HARD_KEYBOARD. In Honeycomb, we introduced a mechanism which allows users to temporary disconnect the physical keyboard connection from a UI [1]. That state was temporary and non-persistent, but it was implemented to have system-wide effect. Whenever the user turned on that temporarily disconnected state, not only IMEs but also other processes would be notified that Configuration#keyboard was changed to KEYBOARD_NOKEYS. The UI to do that was available only in tablet UI at that point and nothing changed in phones. In JellyBean, we decided to port that UI to phone, and the "Use Physical Keyboard" toggle switch found its new home on the IME switcher dialog [2]. In Lollipop, we revised the wording for the toggle switch on the IME switcher dialog. Now it's labeled as "Show input method" [3]. In Lollipop, we also decided to make the settings of "Show input method" to be persistent as @hide entry in the secure settings [4]. [1] 2992ea782fa61780d8e0de7a36a2a84622f8694b I136087ca4f726d0068d5983d7d3686787ba60c55 [2] cb598b11ea2c012bd15e7e7f44a3006f752c0b81 (Ica768083f95c33dc1e494a28ba7d8b6eb989b0ef) [3] be11f3a5cea67c68a08c8da9ce85b3418501060a (I9c8a7eb98b5277f1d09cc19fa7402e9b4cf51d92) [4] b64e56aad3ffb267aec44308f57641a4c91caa83 (I2237ded850a0d4ab43ca441d0b7df13e0958e630) Now, we have hard time making everyone happy. Having an easy way to bring software keyboard back is probably still a valid use case, but after several wording changes it is no longer obvious why onConfigurationChanged() event is sent to all the processes as a consequence of tapping that toggle. In order to address above confusions, this CL removes the concept of "temporarily disconnected physical keyboard" but tries to implement "Show input method" functionality in InputMethodManagerService and InputMethodService to keep the affordance that has been offered in the IME switcher dialog. As long as the IME overrides InputMethodService#onEvaluateInputViewShown() as follows, the behavior of "Show input method" toggle remains the same except for processes including IMEs no longer receive onConfigurationChanged() event with faked Configuration#keyboard value. @Override public boolean onEvaluateInputViewShown() { // If the default implementation returns true, recommend honoring // it. if (super.onEvaluateInputViewShown()) { return true; } // Implement the logic that is specific to your IME here. return myOnEvaluateInputViewShown(); } Bug: 22517687 Change-Id: Id4d332e3909590c68345e10e1f2e18650efb2eb7 --- .../inputmethodservice/InputMethodService.java | 128 +++++++++++++++++++-- 1 file changed, 120 insertions(+), 8 deletions(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 8ab8991c7a42..f642f08df76e 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -19,16 +19,22 @@ package android.inputmethodservice; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import android.annotation.CallSuper; import android.annotation.DrawableRes; +import android.annotation.IntDef; +import android.annotation.MainThread; import android.app.ActivityManager; import android.app.Dialog; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; +import android.database.ContentObserver; import android.graphics.Rect; import android.graphics.Region; +import android.net.Uri; import android.os.Bundle; +import android.os.Handler; import android.os.IBinder; import android.os.ResultReceiver; import android.os.SystemClock; @@ -68,6 +74,8 @@ import android.widget.LinearLayout; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * InputMethodService provides a standard implementation of an InputMethod, @@ -633,6 +641,97 @@ public class InputMethodService extends AbstractInputMethodService { public int touchableInsets; } + /** + * A {@link ContentObserver} to monitor {@link Settings.Secure#SHOW_IME_WITH_HARD_KEYBOARD}. + * + *

Note that {@link Settings.Secure#SHOW_IME_WITH_HARD_KEYBOARD} is not a public API. + * Basically this functionality still needs to be considered as implementation details.

+ */ + @MainThread + private static final class SettingsObserver extends ContentObserver { + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + ShowImeWithHardKeyboardType.UNKNOWN, + ShowImeWithHardKeyboardType.FALSE, + ShowImeWithHardKeyboardType.TRUE, + }) + private @interface ShowImeWithHardKeyboardType { + int UNKNOWN = 0; + int FALSE = 1; + int TRUE = 2; + } + @ShowImeWithHardKeyboardType + private int mShowImeWithHardKeyboard = ShowImeWithHardKeyboardType.UNKNOWN; + + private final InputMethodService mService; + + private SettingsObserver(InputMethodService service) { + super(new Handler(service.getMainLooper())); + mService = service; + } + + /** + * A factory method that internally enforces two-phase initialization to make sure that the + * object reference will not be escaped until the object is properly constructed. + * + *

NOTE: Currently {@link SettingsObserver} is accessed only from main thread. Hence + * this enforcement of two-phase initialization may be unnecessary at the moment.

+ * + * @param service {@link InputMethodService} that needs to receive the callback. + * @return {@link SettingsObserver} that is already registered to + * {@link android.content.ContentResolver}. The caller must call + * {@link SettingsObserver#unregister()}. + */ + public static SettingsObserver createAndRegister(InputMethodService service) { + final SettingsObserver observer = new SettingsObserver(service); + // The observer is properly constructed. Let's start accepting the event. + service.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), + false, observer); + return observer; + } + + void unregister() { + mService.getContentResolver().unregisterContentObserver(this); + } + + private boolean shouldShowImeWithHardKeyboard() { + // Lazily initialize as needed. + if (mShowImeWithHardKeyboard == ShowImeWithHardKeyboardType.UNKNOWN) { + mShowImeWithHardKeyboard = Settings.Secure.getInt(mService.getContentResolver(), + Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0 ? + ShowImeWithHardKeyboardType.TRUE : ShowImeWithHardKeyboardType.FALSE; + } + switch (mShowImeWithHardKeyboard) { + case ShowImeWithHardKeyboardType.TRUE: + return true; + case ShowImeWithHardKeyboardType.FALSE: + return false; + default: + Log.e(TAG, "Unexpected mShowImeWithHardKeyboard=" + mShowImeWithHardKeyboard); + return false; + } + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + final Uri showImeWithHardKeyboardUri = + Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD); + if (showImeWithHardKeyboardUri.equals(uri)) { + mShowImeWithHardKeyboard = Settings.Secure.getInt(mService.getContentResolver(), + Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0 ? + ShowImeWithHardKeyboardType.TRUE : ShowImeWithHardKeyboardType.FALSE; + mService.updateInputViewShown(); + } + } + + @Override + public String toString() { + return "SettingsObserver{mShowImeWithHardKeyboard=" + mShowImeWithHardKeyboard + "}"; + } + } + private SettingsObserver mSettingsObserver; + /** * You can call this to customize the theme used by your IME's window. * This theme should typically be one that derives from @@ -682,6 +781,7 @@ public class InputMethodService extends AbstractInputMethodService { super.setTheme(mTheme); super.onCreate(); mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE); + mSettingsObserver = SettingsObserver.createAndRegister(this); // If the previous IME has occupied non-empty inset in the screen, we need to decide whether // we continue to use the same size of the inset or update it mShouldClearInsetOfPreviousIme = (mImm.getInputMethodWindowVisibleHeight() > 0); @@ -764,6 +864,10 @@ public class InputMethodService extends AbstractInputMethodService { mWindow.getWindow().setWindowAnimations(0); mWindow.dismiss(); } + if (mSettingsObserver != null) { + mSettingsObserver.unregister(); + mSettingsObserver = null; + } } /** @@ -1140,21 +1244,28 @@ public class InputMethodService extends AbstractInputMethodService { public boolean isInputViewShown() { return mIsInputViewShown && mWindowVisible; } - + /** - * Override this to control when the soft input area should be shown to - * the user. The default implementation only shows the input view when - * there is no hard keyboard or the keyboard is hidden. If you change what - * this returns, you will need to call {@link #updateInputViewShown()} - * yourself whenever the returned value may have changed to have it - * re-evaluated and applied. + * Override this to control when the soft input area should be shown to the user. The default + * implementation returns {@code false} when there is no hard keyboard or the keyboard is hidden + * unless the user shows an intention to use software keyboard. If you change what this + * returns, you will need to call {@link #updateInputViewShown()} yourself whenever the returned + * value may have changed to have it re-evaluated and applied. + * + *

When you override this method, it is recommended to call + * {@code super.onEvaluateInputViewShown()} and return {@code true} when {@code true} is + * returned.

*/ + @CallSuper public boolean onEvaluateInputViewShown() { + if (mSettingsObserver.shouldShowImeWithHardKeyboard()) { + return true; + } Configuration config = getResources().getConfiguration(); return config.keyboard == Configuration.KEYBOARD_NOKEYS || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES; } - + /** * Controls the visibility of the candidates display area. By default * it is hidden. @@ -2483,5 +2594,6 @@ public class InputMethodService extends AbstractInputMethodService { + " touchableInsets=" + mTmpInsets.touchableInsets + " touchableRegion=" + mTmpInsets.touchableRegion); p.println(" mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme); + p.println(" mSettingsObserver=" + mSettingsObserver); } } -- cgit v1.2.3 From cf8403bc36395eecd9ab03c6b5e128272c3592e9 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Tue, 12 Jan 2016 11:54:58 -0800 Subject: Suppress NPE in IMS#onEvaluateInputViewShown(). This is a follow up CL for the previous commit [1], which may have triggered an unknown bug in either Android Framework or LatinIME. [1]: Id4d332e3909590c68345e10e1f2e18650efb2eb7 7b739a802cb7d97460a0bf8a1e9774efe96fa552 InputMethodService#mSettingsObserver is initialized in #onCreate() and cleard with null in #onDestroy(). Hence hitting NPE against it implies that InputMethodService#onEvaluateInputViewShown() can be called before InputMethodService#onCreate() or after InputMethodService#onDestroy(). Both possibilities are equaly problematic. Note that this might be a long-standing issue that just became obvious because of [1]. This CL does not attempt to fix the root cause but just tries to suppresses the NPE to unblock QA tasks. A proper fix should be made in subsequent CLs. Bug: 22517687 Bug: 26511607 Change-Id: I6bc87c3d18b560fe2253fb9f05557b95b04d0cf0 --- core/java/android/inputmethodservice/InputMethodService.java | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index f642f08df76e..282688295fee 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1258,6 +1258,10 @@ public class InputMethodService extends AbstractInputMethodService { */ @CallSuper public boolean onEvaluateInputViewShown() { + if (mSettingsObserver == null) { + Log.w(TAG, "onEvaluateInputViewShown: mSettingsObserver must not be null here."); + return false; + } if (mSettingsObserver.shouldShowImeWithHardKeyboard()) { return true; } -- cgit v1.2.3 From 755c0095a13365617b0752b8960e0be4044634ac Mon Sep 17 00:00:00 2001 From: Keisuke Kuroyanagi Date: Mon, 14 Mar 2016 19:09:20 +0900 Subject: Fix: onExtractedDeleteText deletes unintended region. InputMethodService#onExtractedDeleteText doesn't reset composing region and InputConnection#deleteSurroundingText deletes text around the composing region. As a result, #onExtractedDeleteText can delete unintended region of the text. This happens when a user perform Drag&Drop or tap "Delete" in SuggestionsPopup in full screen extracted mode. Bug: 22440907 Bug: 27536702 Change-Id: I875f2919896f8ff453a77fb4a1b642ad78079b78 --- core/java/android/inputmethodservice/InputMethodService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 282688295fee..6b79a8ac438a 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -2269,8 +2269,9 @@ public class InputMethodService extends AbstractInputMethodService { public void onExtractedDeleteText(int start, int end) { InputConnection conn = getCurrentInputConnection(); if (conn != null) { + conn.finishComposingText(); conn.setSelection(start, start); - conn.deleteSurroundingText(0, end-start); + conn.deleteSurroundingText(0, end - start); } } -- cgit v1.2.3 From ef5b4657a8b03b33d6c4087e0ced33606fcf05f3 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Sun, 3 Apr 2016 22:50:11 -0700 Subject: Fix a bug that IMS#mShowInputFlags is never updated. As a preparation to fix bug 26985193, this CL fixes a bug that IMS#ShowInputFlags is never updated. As a result, IMS#onConfigurationChanged() has always called IMS#onShowInputRequested() with specifying 0 to flags parameter, which is wrong. With this CL, we can assume that IMS#mShowInputFlags keeps tracking the last value when it should do. Also, we can remove IMS#mShowInputForced since it is now determined by IMS#mShowInputFlags. Bug: 26985193 Change-Id: Ieff634b69ce941d78ffe208547f7edd19ea28643 --- .../inputmethodservice/InputMethodService.java | 50 ++++++++++++++-------- 1 file changed, 33 insertions(+), 17 deletions(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 6b79a8ac438a..9d53a0001a84 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -295,9 +295,7 @@ public class InputMethodService extends AbstractInputMethodService { boolean mLastShowInputRequested; int mCandidatesVisibility; CompletionInfo[] mCurCompletions; - - boolean mShowInputForced; - + boolean mFullscreenApplied; boolean mIsFullscreen; View mExtractView; @@ -422,7 +420,6 @@ public class InputMethodService extends AbstractInputMethodService { boolean wasVis = isInputViewShown(); mShowInputFlags = 0; mShowInputRequested = false; - mShowInputForced = false; doHideWindow(); clearInsetOfPreviousIme(); if (resultReceiver != null) { @@ -439,8 +436,7 @@ public class InputMethodService extends AbstractInputMethodService { public void showSoftInput(int flags, ResultReceiver resultReceiver) { if (DEBUG) Log.v(TAG, "showSoftInput()"); boolean wasVis = isInputViewShown(); - mShowInputFlags = 0; - if (onShowInputRequested(flags, false)) { + if (dispatchOnShowInputRequested(flags, false)) { try { showWindow(true); } catch (BadTokenException e) { @@ -817,8 +813,8 @@ public class InputMethodService extends AbstractInputMethodService { mInitialized = false; mWindowCreated = false; mShowInputRequested = false; - mShowInputForced = false; - + mShowInputFlags = 0; + mThemeAttrs = obtainStyledAttributes(android.R.styleable.InputMethodService); mRootView = mInflater.inflate( com.android.internal.R.layout.input_method, null); @@ -888,7 +884,7 @@ public class InputMethodService extends AbstractInputMethodService { */ @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - + boolean visible = mWindowVisible; int showFlags = mShowInputFlags; boolean showingInput = mShowInputRequested; @@ -903,7 +899,7 @@ public class InputMethodService extends AbstractInputMethodService { if (visible) { if (showingInput) { // If we were last showing the soft keyboard, try to do so again. - if (onShowInputRequested(showFlags, true)) { + if (dispatchOnShowInputRequested(showFlags, true)) { showWindow(true); if (completions != null) { mCurCompletions = completions; @@ -1540,20 +1536,41 @@ public class InputMethodService extends AbstractInputMethodService { return false; } } - if ((flags&InputMethod.SHOW_FORCED) != 0) { - mShowInputForced = true; - } return true; } - + + /** + * A utility method to call {{@link #onShowInputRequested(int, boolean)}} and update internal + * states depending on its result. Since {@link #onShowInputRequested(int, boolean)} is + * exposed to IME authors as an overridable public method without {@code @CallSuper}, we have + * to have this method to ensure that those internal states are always updated no matter how + * {@link #onShowInputRequested(int, boolean)} is overridden by the IME author. + * @param flags Provides additional information about the show request, + * as per {@link InputMethod#showSoftInput InputMethod.showSoftInput()}. + * @param configChange This is true if we are re-showing due to a + * configuration change. + * @return Returns true to indicate that the window should be shown. + * @see #onShowInputRequested(int, boolean) + */ + private boolean dispatchOnShowInputRequested(int flags, boolean configChange) { + final boolean result = onShowInputRequested(flags, configChange); + if (result) { + mShowInputFlags = flags; + } else { + mShowInputFlags = 0; + } + return result; + } + public void showWindow(boolean showInput) { if (DEBUG) Log.v(TAG, "Showing window: showInput=" + showInput + " mShowInputRequested=" + mShowInputRequested + " mWindowAdded=" + mWindowAdded + " mWindowCreated=" + mWindowCreated + " mWindowVisible=" + mWindowVisible - + " mInputStarted=" + mInputStarted); - + + " mInputStarted=" + mInputStarted + + " mShowInputFlags=" + mShowInputFlags); + if (mInShowWindow) { Log.w(TAG, "Re-entrance in to showWindow"); return; @@ -2573,7 +2590,6 @@ public class InputMethodService extends AbstractInputMethodService { p.println(" mShowInputRequested=" + mShowInputRequested + " mLastShowInputRequested=" + mLastShowInputRequested - + " mShowInputForced=" + mShowInputForced + " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags)); p.println(" mCandidatesVisibility=" + mCandidatesVisibility + " mFullscreenApplied=" + mFullscreenApplied -- cgit v1.2.3 From 2dbc53242927a796117a0b70d856021c0d4918a5 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Sun, 3 Apr 2016 22:50:18 -0700 Subject: Fix a regression in SHOW_IME_WITH_HARD_KEYBOARD handling. This is a follow up CL to my previous CL [1], which caused a regression that LatinIME does not correctly initialize its UI when: 1. Make sure SHOW_IME_WITH_HARD_KEYBOARD is off. 2. Pair a hardware keyboard. 3. Reboot. 4. Make sure the hardware keyboard is paird. 5. Focus in a text box. 6. Make sure that LatinIME does not show software keyboard. 7. Tap the IME switcher and turn of "Show Input Method" toggle. Previously IMS had called many methods from IMS#onConfigurationChanged(), which was just replaced with IMS#restartInput() by my CL [1] then broke some assumptions in LatinIME. This could also break other IMEs' assumptions as well. To avoid unexpected regressions between M and N like this, this CL ensures that those methods are called as we have done until [1]. [1]: Id4d332e3909590c68345e10e1f2e18650efb2eb7 7b739a802cb7d97460a0bf8a1e9774efe96fa552 Bug: 26985193 Change-Id: Iebd98f26d388b64cb318ac202b3bcdd956bd3a27 --- core/java/android/inputmethodservice/InputMethodService.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 9d53a0001a84..cc201bc78bb5 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -717,7 +717,11 @@ public class InputMethodService extends AbstractInputMethodService { mShowImeWithHardKeyboard = Settings.Secure.getInt(mService.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0 ? ShowImeWithHardKeyboardType.TRUE : ShowImeWithHardKeyboardType.FALSE; - mService.updateInputViewShown(); + // In Android M and prior, state change of + // Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD has triggered + // #onConfigurationChanged(). For compatibility reasons, we reset the internal + // state as if configuration was changed. + mService.resetStateForNewConfiguration(); } } @@ -884,7 +888,10 @@ public class InputMethodService extends AbstractInputMethodService { */ @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); + resetStateForNewConfiguration(); + } + private void resetStateForNewConfiguration() { boolean visible = mWindowVisible; int showFlags = mShowInputFlags; boolean showingInput = mShowInputRequested; -- cgit v1.2.3 From 880602eb640f1f0f7f77f8d17c4ad34aca8b751d Mon Sep 17 00:00:00 2001 From: Mark Renouf Date: Tue, 5 Apr 2016 13:21:57 -0400 Subject: Customizes input extract edit view for Wear Provides an alternate presentation of the extract edit area of an input method window, designed for sub 250dp width screens. An icon is used on a round material style button in place of a text action, providing more horizontal space for the editing area. BUG: 22512982 Change-Id: I16226ce393f2d15065d08e66a36d008eb1a0c8a1 (cherry picked from commit fd71a6a5d99bad5d3ab32edc328fb5b026b66215) --- .../inputmethodservice/InputMethodService.java | 53 +++++++++++++++++++--- 1 file changed, 46 insertions(+), 7 deletions(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index cc201bc78bb5..085b97cc0f6d 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -68,9 +68,10 @@ import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethod; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; -import android.widget.Button; import android.widget.FrameLayout; +import android.widget.ImageButton; import android.widget.LinearLayout; +import android.widget.TextView; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -302,7 +303,7 @@ public class InputMethodService extends AbstractInputMethodService { boolean mExtractViewHidden; ExtractEditText mExtractEditText; ViewGroup mExtractAccessories; - Button mExtractAction; + View mExtractAction; ExtractedText mExtractedText; int mExtractedToken; @@ -1344,7 +1345,7 @@ public class InputMethodService extends AbstractInputMethodService { mExtractEditText = (ExtractEditText)view.findViewById( com.android.internal.R.id.inputExtractEditText); mExtractEditText.setIME(this); - mExtractAction = (Button)view.findViewById( + mExtractAction = view.findViewById( com.android.internal.R.id.inputExtractAction); if (mExtractAction != null) { mExtractAccessories = (ViewGroup)view.findViewById( @@ -2408,7 +2409,35 @@ public class InputMethodService extends AbstractInputMethodService { return getText(com.android.internal.R.string.ime_action_default); } } - + + /** + * Return a drawable resource id that can be used as a button icon for the given + * {@link EditorInfo#imeOptions EditorInfo.imeOptions}. + * + * @param imeOptions The value from @link EditorInfo#imeOptions EditorInfo.imeOptions}. + * + * @return Returns a drawable resource id to use. + */ + @DrawableRes + private int getIconForImeAction(int imeOptions) { + switch (imeOptions&EditorInfo.IME_MASK_ACTION) { + case EditorInfo.IME_ACTION_GO: + return com.android.internal.R.drawable.ic_input_extract_action_go; + case EditorInfo.IME_ACTION_SEARCH: + return com.android.internal.R.drawable.ic_input_extract_action_search; + case EditorInfo.IME_ACTION_SEND: + return com.android.internal.R.drawable.ic_input_extract_action_send; + case EditorInfo.IME_ACTION_NEXT: + return com.android.internal.R.drawable.ic_input_extract_action_next; + case EditorInfo.IME_ACTION_DONE: + return com.android.internal.R.drawable.ic_input_extract_action_done; + case EditorInfo.IME_ACTION_PREVIOUS: + return com.android.internal.R.drawable.ic_input_extract_action_previous; + default: + return com.android.internal.R.drawable.ic_input_extract_action_return; + } + } + /** * Called when the fullscreen-mode extracting editor info has changed, * to determine whether the extracting (extract text and candidates) portion @@ -2459,10 +2488,20 @@ public class InputMethodService extends AbstractInputMethodService { if (hasAction) { mExtractAccessories.setVisibility(View.VISIBLE); if (mExtractAction != null) { - if (ei.actionLabel != null) { - mExtractAction.setText(ei.actionLabel); + if (mExtractAction instanceof ImageButton) { + ((ImageButton) mExtractAction) + .setImageResource(getIconForImeAction(ei.imeOptions)); + if (ei.actionLabel != null) { + mExtractAction.setContentDescription(ei.actionLabel); + } else { + mExtractAction.setContentDescription(getTextForImeAction(ei.imeOptions)); + } } else { - mExtractAction.setText(getTextForImeAction(ei.imeOptions)); + if (ei.actionLabel != null) { + ((TextView) mExtractAction).setText(ei.actionLabel); + } else { + ((TextView) mExtractAction).setText(getTextForImeAction(ei.imeOptions)); + } } mExtractAction.setOnClickListener(mActionClickListener); } -- cgit v1.2.3 From 757224008e6187bbb04c89fadbe6921bf8ceda9f Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Sat, 9 Apr 2016 15:24:02 -0700 Subject: Revert "Customizes input extract edit view for Wear" This reverts commit 880602eb640f1f0f7f77f8d17c4ad34aca8b751d [1], which was committed with a wrong author email address and lacked license notice in some files. To avoid confusion, this we decided to temporarily revert that CL so that we can commit it with proper license notice and author address again. [1]: I16226ce393f2d15065d08e66a36d008eb1a0c8a1 Bug: 22512982 Bug: 28098677 Change-Id: I3dd3c7bf0ee9634fc4f3bf433bf5023675873e46 --- .../inputmethodservice/InputMethodService.java | 53 +++------------------- 1 file changed, 7 insertions(+), 46 deletions(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 085b97cc0f6d..cc201bc78bb5 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -68,10 +68,9 @@ import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethod; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; +import android.widget.Button; import android.widget.FrameLayout; -import android.widget.ImageButton; import android.widget.LinearLayout; -import android.widget.TextView; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -303,7 +302,7 @@ public class InputMethodService extends AbstractInputMethodService { boolean mExtractViewHidden; ExtractEditText mExtractEditText; ViewGroup mExtractAccessories; - View mExtractAction; + Button mExtractAction; ExtractedText mExtractedText; int mExtractedToken; @@ -1345,7 +1344,7 @@ public class InputMethodService extends AbstractInputMethodService { mExtractEditText = (ExtractEditText)view.findViewById( com.android.internal.R.id.inputExtractEditText); mExtractEditText.setIME(this); - mExtractAction = view.findViewById( + mExtractAction = (Button)view.findViewById( com.android.internal.R.id.inputExtractAction); if (mExtractAction != null) { mExtractAccessories = (ViewGroup)view.findViewById( @@ -2409,35 +2408,7 @@ public class InputMethodService extends AbstractInputMethodService { return getText(com.android.internal.R.string.ime_action_default); } } - - /** - * Return a drawable resource id that can be used as a button icon for the given - * {@link EditorInfo#imeOptions EditorInfo.imeOptions}. - * - * @param imeOptions The value from @link EditorInfo#imeOptions EditorInfo.imeOptions}. - * - * @return Returns a drawable resource id to use. - */ - @DrawableRes - private int getIconForImeAction(int imeOptions) { - switch (imeOptions&EditorInfo.IME_MASK_ACTION) { - case EditorInfo.IME_ACTION_GO: - return com.android.internal.R.drawable.ic_input_extract_action_go; - case EditorInfo.IME_ACTION_SEARCH: - return com.android.internal.R.drawable.ic_input_extract_action_search; - case EditorInfo.IME_ACTION_SEND: - return com.android.internal.R.drawable.ic_input_extract_action_send; - case EditorInfo.IME_ACTION_NEXT: - return com.android.internal.R.drawable.ic_input_extract_action_next; - case EditorInfo.IME_ACTION_DONE: - return com.android.internal.R.drawable.ic_input_extract_action_done; - case EditorInfo.IME_ACTION_PREVIOUS: - return com.android.internal.R.drawable.ic_input_extract_action_previous; - default: - return com.android.internal.R.drawable.ic_input_extract_action_return; - } - } - + /** * Called when the fullscreen-mode extracting editor info has changed, * to determine whether the extracting (extract text and candidates) portion @@ -2488,20 +2459,10 @@ public class InputMethodService extends AbstractInputMethodService { if (hasAction) { mExtractAccessories.setVisibility(View.VISIBLE); if (mExtractAction != null) { - if (mExtractAction instanceof ImageButton) { - ((ImageButton) mExtractAction) - .setImageResource(getIconForImeAction(ei.imeOptions)); - if (ei.actionLabel != null) { - mExtractAction.setContentDescription(ei.actionLabel); - } else { - mExtractAction.setContentDescription(getTextForImeAction(ei.imeOptions)); - } + if (ei.actionLabel != null) { + mExtractAction.setText(ei.actionLabel); } else { - if (ei.actionLabel != null) { - ((TextView) mExtractAction).setText(ei.actionLabel); - } else { - ((TextView) mExtractAction).setText(getTextForImeAction(ei.imeOptions)); - } + mExtractAction.setText(getTextForImeAction(ei.imeOptions)); } mExtractAction.setOnClickListener(mActionClickListener); } -- cgit v1.2.3 From 91eb2651a06633353592d52c3e37579f01b020ee Mon Sep 17 00:00:00 2001 From: Mark Renouf Date: Mon, 11 Apr 2016 16:03:26 -0400 Subject: Customizes input extract edit view for Wear Provides an alternate presentation of the extract edit area of an input method window, designed for sub 250dp width screens. An icon is used on a round material style button in place of a text action, providing more horizontal space for the editing area. BUG: 28098677 (cherry picked from commit fd71a6a5d99bad5d3ab32edc328fb5b026b66215) Change-Id: I0e559d17f78d1a48b37979a49e11ae1aad7503f4 --- .../inputmethodservice/InputMethodService.java | 53 +++++++++++++++++++--- 1 file changed, 46 insertions(+), 7 deletions(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index cc201bc78bb5..085b97cc0f6d 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -68,9 +68,10 @@ import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethod; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; -import android.widget.Button; import android.widget.FrameLayout; +import android.widget.ImageButton; import android.widget.LinearLayout; +import android.widget.TextView; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -302,7 +303,7 @@ public class InputMethodService extends AbstractInputMethodService { boolean mExtractViewHidden; ExtractEditText mExtractEditText; ViewGroup mExtractAccessories; - Button mExtractAction; + View mExtractAction; ExtractedText mExtractedText; int mExtractedToken; @@ -1344,7 +1345,7 @@ public class InputMethodService extends AbstractInputMethodService { mExtractEditText = (ExtractEditText)view.findViewById( com.android.internal.R.id.inputExtractEditText); mExtractEditText.setIME(this); - mExtractAction = (Button)view.findViewById( + mExtractAction = view.findViewById( com.android.internal.R.id.inputExtractAction); if (mExtractAction != null) { mExtractAccessories = (ViewGroup)view.findViewById( @@ -2408,7 +2409,35 @@ public class InputMethodService extends AbstractInputMethodService { return getText(com.android.internal.R.string.ime_action_default); } } - + + /** + * Return a drawable resource id that can be used as a button icon for the given + * {@link EditorInfo#imeOptions EditorInfo.imeOptions}. + * + * @param imeOptions The value from @link EditorInfo#imeOptions EditorInfo.imeOptions}. + * + * @return Returns a drawable resource id to use. + */ + @DrawableRes + private int getIconForImeAction(int imeOptions) { + switch (imeOptions&EditorInfo.IME_MASK_ACTION) { + case EditorInfo.IME_ACTION_GO: + return com.android.internal.R.drawable.ic_input_extract_action_go; + case EditorInfo.IME_ACTION_SEARCH: + return com.android.internal.R.drawable.ic_input_extract_action_search; + case EditorInfo.IME_ACTION_SEND: + return com.android.internal.R.drawable.ic_input_extract_action_send; + case EditorInfo.IME_ACTION_NEXT: + return com.android.internal.R.drawable.ic_input_extract_action_next; + case EditorInfo.IME_ACTION_DONE: + return com.android.internal.R.drawable.ic_input_extract_action_done; + case EditorInfo.IME_ACTION_PREVIOUS: + return com.android.internal.R.drawable.ic_input_extract_action_previous; + default: + return com.android.internal.R.drawable.ic_input_extract_action_return; + } + } + /** * Called when the fullscreen-mode extracting editor info has changed, * to determine whether the extracting (extract text and candidates) portion @@ -2459,10 +2488,20 @@ public class InputMethodService extends AbstractInputMethodService { if (hasAction) { mExtractAccessories.setVisibility(View.VISIBLE); if (mExtractAction != null) { - if (ei.actionLabel != null) { - mExtractAction.setText(ei.actionLabel); + if (mExtractAction instanceof ImageButton) { + ((ImageButton) mExtractAction) + .setImageResource(getIconForImeAction(ei.imeOptions)); + if (ei.actionLabel != null) { + mExtractAction.setContentDescription(ei.actionLabel); + } else { + mExtractAction.setContentDescription(getTextForImeAction(ei.imeOptions)); + } } else { - mExtractAction.setText(getTextForImeAction(ei.imeOptions)); + if (ei.actionLabel != null) { + ((TextView) mExtractAction).setText(ei.actionLabel); + } else { + ((TextView) mExtractAction).setText(getTextForImeAction(ei.imeOptions)); + } } mExtractAction.setOnClickListener(mActionClickListener); } -- cgit v1.2.3 From d0d07974745dcc947bb498198166f5872c7ec4a1 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Wed, 4 May 2016 11:56:35 -0700 Subject: Fix a behavior change in "Show software keyboard". This bug was a corner case of stopping lying about Configuration#keyboard when "Show software keyboard" is turned on, which was done by my CL [1] in Android N development cycle. Previous implementation if (config.keyboard != Configuration.KEYBOARD_NOKEYS) { had relied on the fact that the system was lying about config.keyboard, which is no longer valid. We need to change the behavior of InputMethodService#onShowInputRequested() depending on Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD like we did for InputMethodService#onEvaluateInputViewShown() in [1] to minimize the impact on stopping lying about Configuration#keyboard. [1]: Id4d332e3909590c68345e10e1f2e18650efb2eb7 7b739a802cb7d97460a0bf8a1e9774efe96fa552 Bug: 28423439 Change-Id: I8a774cbf61ac706d8446be91b17bceee57a13656 --- core/java/android/inputmethodservice/InputMethodService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 085b97cc0f6d..923be5e06582 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1536,8 +1536,8 @@ public class InputMethodService extends AbstractInputMethodService { // mode at this point. return false; } - Configuration config = getResources().getConfiguration(); - if (config.keyboard != Configuration.KEYBOARD_NOKEYS) { + if (!mSettingsObserver.shouldShowImeWithHardKeyboard() && + getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS) { // And if the device has a hard keyboard, even if it is // currently hidden, don't show the input method implicitly. // These kinds of devices don't need it that much. -- cgit v1.2.3 From 833bdcedceee60a873694a77587393abfc830eb5 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Sun, 15 May 2016 20:05:56 -0700 Subject: Make IMS#clearInsetOfPreviousIme() reliable. This is a follow-up to my previous CL [1] for Bug 15922840 so that we can clear the following variables in a more reliable way. - PhoneWindowManager#mLastInputMethodWindow - PhoneWindowManager#mLastInputMethodTargetWindow The idea behind CL [2] is that when InputMethodManagerService (IMMS) is switching from an IME to another IME, IMMS can send a signal to WindowManagerService (WMS) to remember the current IME's inset so that the system can continue using it to reduce jank until the new inset is specified by the next IME. As summarized in Bug 28781358, however, if the next IME does not show the window after the IME switch, WMS (or PhoneWindowManager to be precise) keeps using the previous IME's inset unexpectedly until the new IME shows its window. All we have seen in Bug 15922840 and Bug 26663589 fall into this category. The idea of this CL is just adding a hidden API to InputMethodManager so that InputMethodService#clearInsetOfPreviousIme() can surely terminate the IME transition state managed in PhoneWindowManager, rather than relying on a hack of calling SoftInputWindow#show() and SoftInputWindow#hide(), which actually does not work for Bug 26663589. [1]: Ib04967f39b2529251e4835c42e9f99dba2cf43f2 2977eb7b6ce82309a1bb1ba4ab698f503cb0388a [2]: I5723f627ce323b0d12bd7b93f5b35fc4d342b50c 792faa2c16d319e874a1d633f964a78266d5f3f2 Note that addressing all the corner cases in [2] still requires lots of non-trivial change. Hence this CL focuses only on Bug 26663589 (and the case we handled in Bug 15922840). Bug: 26663589 Change-Id: Ib567daa009c1139858dccadcfc6a04465ebecf36 --- .../android/inputmethodservice/InputMethodService.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 923be5e06582..4799773d9ed6 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1714,18 +1714,9 @@ public class InputMethodService extends AbstractInputMethodService { private void clearInsetOfPreviousIme() { if (DEBUG) Log.v(TAG, "clearInsetOfPreviousIme() " + " mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme); - if (!mShouldClearInsetOfPreviousIme || mWindow == null) return; - try { - // We do not call onWindowShown() and onWindowHidden() so as not to make the IME author - // confused. - // TODO: Find out a better way which has less side-effect. - mWindow.show(); - mWindow.hide(); - } catch (WindowManager.BadTokenException e) { - if (DEBUG) Log.v(TAG, "clearInsetOfPreviousIme: BadTokenException: IME is done."); - mWindowVisible = false; - mWindowAdded = false; - } + if (!mShouldClearInsetOfPreviousIme) return; + + mImm.clearLastInputMethodWindowForTransition(mToken); mShouldClearInsetOfPreviousIme = false; } -- cgit v1.2.3