Ignore the Emoji key when not connected.

When the LatinIME does not have an active InputConnection, it will not try
to toggle the Emoji keyboard.

Bug 19513415.

Change-Id: I31f928cd7db1cddd771c548cd3dc42f8af64d0e2
main
Dan Zivkovic 2015-02-26 11:10:37 -08:00
parent 48b071249c
commit edd94a449e
3 changed files with 49 additions and 27 deletions

View File

@ -16,6 +16,7 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardSwitcher;
@ -25,10 +26,18 @@ import com.android.inputmethod.latin.settings.Settings;
* A class for detecting Emoji-Alt physical key. * A class for detecting Emoji-Alt physical key.
*/ */
final class EmojiAltPhysicalKeyDetector { final class EmojiAltPhysicalKeyDetector {
private static final String TAG = "EmojiAltPhysicalKeyDetector";
private final RichInputConnection mRichInputConnection;
// True if the Alt key has been used as a modifier. In this case the Alt key up isn't // True if the Alt key has been used as a modifier. In this case the Alt key up isn't
// recognized as an emoji key. // recognized as an emoji key.
private boolean mAltHasBeenUsedAsAModifier; private boolean mAltHasBeenUsedAsAModifier;
public EmojiAltPhysicalKeyDetector(final RichInputConnection richInputConnection) {
mRichInputConnection = richInputConnection;
}
/** /**
* Record a down key event. * Record a down key event.
* @param keyEvent a down key event. * @param keyEvent a down key event.
@ -62,9 +71,14 @@ final class EmojiAltPhysicalKeyDetector {
if (!Settings.getInstance().getCurrent().mEnableEmojiAltPhysicalKey) { if (!Settings.getInstance().getCurrent().mEnableEmojiAltPhysicalKey) {
return; return;
} }
if (!mAltHasBeenUsedAsAModifier) { if (mAltHasBeenUsedAsAModifier) {
onEmojiAltKeyDetected(); return;
} }
if (!mRichInputConnection.isConnected()) {
Log.w(TAG, "onKeyUp() : No connection to text view");
return;
}
onEmojiAltKeyDetected();
} }
private static void onEmojiAltKeyDetected() { private static void onEmojiAltKeyDetected() {

View File

@ -143,7 +143,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher; @UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
private final SubtypeState mSubtypeState = new SubtypeState(); private final SubtypeState mSubtypeState = new SubtypeState();
private final EmojiAltPhysicalKeyDetector mEmojiAltPhysicalKeyDetector = private final EmojiAltPhysicalKeyDetector mEmojiAltPhysicalKeyDetector =
new EmojiAltPhysicalKeyDetector(); new EmojiAltPhysicalKeyDetector(mInputLogic.mConnection);
private StatsUtilsManager mStatsUtilsManager; private StatsUtilsManager mStatsUtilsManager;
// Working variable for {@link #startShowingInputView()} and // Working variable for {@link #startShowingInputView()} and
// {@link #onEvaluateInputViewShown()}. // {@link #onEvaluateInputViewShown()}.

View File

@ -101,12 +101,17 @@ public final class RichInputConnection implements PrivateCommandPerformer {
private final InputMethodService mParent; private final InputMethodService mParent;
InputConnection mIC; InputConnection mIC;
int mNestLevel; int mNestLevel;
public RichInputConnection(final InputMethodService parent) { public RichInputConnection(final InputMethodService parent) {
mParent = parent; mParent = parent;
mIC = null; mIC = null;
mNestLevel = 0; mNestLevel = 0;
} }
public boolean isConnected() {
return mIC != null;
}
private void checkConsistencyForDebug() { private void checkConsistencyForDebug() {
final ExtractedTextRequest r = new ExtractedTextRequest(); final ExtractedTextRequest r = new ExtractedTextRequest();
r.hintMaxChars = 0; r.hintMaxChars = 0;
@ -142,7 +147,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
public void beginBatchEdit() { public void beginBatchEdit() {
if (++mNestLevel == 1) { if (++mNestLevel == 1) {
mIC = mParent.getCurrentInputConnection(); mIC = mParent.getCurrentInputConnection();
if (null != mIC) { if (isConnected()) {
mIC.beginBatchEdit(); mIC.beginBatchEdit();
} }
} else { } else {
@ -157,7 +162,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
public void endBatchEdit() { public void endBatchEdit() {
if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
if (--mNestLevel == 0 && null != mIC) { if (--mNestLevel == 0 && isConnected()) {
mIC.endBatchEdit(); mIC.endBatchEdit();
} }
if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
@ -189,7 +194,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
Log.d(TAG, "Will try to retrieve text later."); Log.d(TAG, "Will try to retrieve text later.");
return false; return false;
} }
if (null != mIC && shouldFinishComposition) { if (isConnected() && shouldFinishComposition) {
mIC.finishComposingText(); mIC.finishComposingText();
} }
return true; return true;
@ -205,8 +210,9 @@ public final class RichInputConnection implements PrivateCommandPerformer {
mIC = mParent.getCurrentInputConnection(); mIC = mParent.getCurrentInputConnection();
// Call upon the inputconnection directly since our own method is using the cache, and // Call upon the inputconnection directly since our own method is using the cache, and
// we want to refresh it. // we want to refresh it.
final CharSequence textBeforeCursor = null == mIC ? null : final CharSequence textBeforeCursor = isConnected()
mIC.getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE, 0); ? mIC.getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE, 0)
: null;
if (null == textBeforeCursor) { if (null == textBeforeCursor) {
// For some reason the app thinks we are not connected to it. This looks like a // For some reason the app thinks we are not connected to it. This looks like a
// framework bug... Fall back to ground state and return false. // framework bug... Fall back to ground state and return false.
@ -235,7 +241,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
// it works, but it's wrong and should be fixed. // it works, but it's wrong and should be fixed.
mCommittedTextBeforeComposingText.append(mComposingText); mCommittedTextBeforeComposingText.append(mComposingText);
mComposingText.setLength(0); mComposingText.setLength(0);
if (null != mIC) { if (isConnected()) {
mIC.finishComposingText(); mIC.finishComposingText();
} }
} }
@ -256,7 +262,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
mExpectedSelStart += text.length() - mComposingText.length(); mExpectedSelStart += text.length() - mComposingText.length();
mExpectedSelEnd = mExpectedSelStart; mExpectedSelEnd = mExpectedSelStart;
mComposingText.setLength(0); mComposingText.setLength(0);
if (null != mIC) { if (isConnected()) {
mTempObjectForCommitText.clear(); mTempObjectForCommitText.clear();
mTempObjectForCommitText.append(text); mTempObjectForCommitText.append(text);
final CharacterStyle[] spans = mTempObjectForCommitText.getSpans( final CharacterStyle[] spans = mTempObjectForCommitText.getSpans(
@ -283,7 +289,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
} }
public CharSequence getSelectedText(final int flags) { public CharSequence getSelectedText(final int flags) {
return (null == mIC) ? null : mIC.getSelectedText(flags); return isConnected() ? mIC.getSelectedText(flags) : null;
} }
public boolean canDeleteCharacters() { public boolean canDeleteCharacters() {
@ -308,7 +314,9 @@ public final class RichInputConnection implements PrivateCommandPerformer {
public int getCursorCapsMode(final int inputType, public int getCursorCapsMode(final int inputType,
final SpacingAndPunctuations spacingAndPunctuations, final boolean hasSpaceBefore) { final SpacingAndPunctuations spacingAndPunctuations, final boolean hasSpaceBefore) {
mIC = mParent.getCurrentInputConnection(); mIC = mParent.getCurrentInputConnection();
if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF; if (!isConnected()) {
return Constants.TextUtils.CAP_MODE_OFF;
}
if (!TextUtils.isEmpty(mComposingText)) { if (!TextUtils.isEmpty(mComposingText)) {
if (hasSpaceBefore) { if (hasSpaceBefore) {
// If we have some composing text and a space before, then we should have // If we have some composing text and a space before, then we should have
@ -368,12 +376,12 @@ public final class RichInputConnection implements PrivateCommandPerformer {
return s; return s;
} }
mIC = mParent.getCurrentInputConnection(); mIC = mParent.getCurrentInputConnection();
return (null == mIC) ? null : mIC.getTextBeforeCursor(n, flags); return isConnected() ? mIC.getTextBeforeCursor(n, flags) : null;
} }
public CharSequence getTextAfterCursor(final int n, final int flags) { public CharSequence getTextAfterCursor(final int n, final int flags) {
mIC = mParent.getCurrentInputConnection(); mIC = mParent.getCurrentInputConnection();
return (null == mIC) ? null : mIC.getTextAfterCursor(n, flags); return isConnected() ? mIC.getTextAfterCursor(n, flags) : null;
} }
public void deleteSurroundingText(final int beforeLength, final int afterLength) { public void deleteSurroundingText(final int beforeLength, final int afterLength) {
@ -400,7 +408,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
mExpectedSelEnd -= mExpectedSelStart; mExpectedSelEnd -= mExpectedSelStart;
mExpectedSelStart = 0; mExpectedSelStart = 0;
} }
if (null != mIC) { if (isConnected()) {
mIC.deleteSurroundingText(beforeLength, afterLength); mIC.deleteSurroundingText(beforeLength, afterLength);
} }
if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
@ -408,7 +416,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
public void performEditorAction(final int actionId) { public void performEditorAction(final int actionId) {
mIC = mParent.getCurrentInputConnection(); mIC = mParent.getCurrentInputConnection();
if (null != mIC) { if (isConnected()) {
mIC.performEditorAction(actionId); mIC.performEditorAction(actionId);
} }
} }
@ -460,7 +468,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
break; break;
} }
} }
if (null != mIC) { if (isConnected()) {
mIC.sendKeyEvent(keyEvent); mIC.sendKeyEvent(keyEvent);
} }
} }
@ -483,7 +491,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
mCommittedTextBeforeComposingText.append( mCommittedTextBeforeComposingText.append(
textBeforeCursor.subSequence(0, indexOfStartOfComposingText)); textBeforeCursor.subSequence(0, indexOfStartOfComposingText));
} }
if (null != mIC) { if (isConnected()) {
mIC.setComposingRegion(start, end); mIC.setComposingRegion(start, end);
} }
} }
@ -497,7 +505,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
mComposingText.append(text); mComposingText.append(text);
// TODO: support values of newCursorPosition != 1. At this time, this is never called with // TODO: support values of newCursorPosition != 1. At this time, this is never called with
// newCursorPosition != 1. // newCursorPosition != 1.
if (null != mIC) { if (isConnected()) {
mIC.setComposingText(text, newCursorPosition); mIC.setComposingText(text, newCursorPosition);
} }
if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
@ -522,7 +530,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
} }
mExpectedSelStart = start; mExpectedSelStart = start;
mExpectedSelEnd = end; mExpectedSelEnd = end;
if (null != mIC) { if (isConnected()) {
final boolean isIcValid = mIC.setSelection(start, end); final boolean isIcValid = mIC.setSelection(start, end);
if (!isIcValid) { if (!isIcValid) {
return false; return false;
@ -536,7 +544,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
// This has no effect on the text field and does not change its content. It only makes // This has no effect on the text field and does not change its content. It only makes
// TextView flash the text for a second based on indices contained in the argument. // TextView flash the text for a second based on indices contained in the argument.
if (null != mIC) { if (isConnected()) {
mIC.commitCorrection(correctionInfo); mIC.commitCorrection(correctionInfo);
} }
if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
@ -552,7 +560,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
mExpectedSelStart += text.length() - mComposingText.length(); mExpectedSelStart += text.length() - mComposingText.length();
mExpectedSelEnd = mExpectedSelStart; mExpectedSelEnd = mExpectedSelStart;
mComposingText.setLength(0); mComposingText.setLength(0);
if (null != mIC) { if (isConnected()) {
mIC.commitCompletion(completionInfo); mIC.commitCompletion(completionInfo);
} }
if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
@ -563,7 +571,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
public NgramContext getNgramContextFromNthPreviousWord( public NgramContext getNgramContextFromNthPreviousWord(
final SpacingAndPunctuations spacingAndPunctuations, final int n) { final SpacingAndPunctuations spacingAndPunctuations, final int n) {
mIC = mParent.getCurrentInputConnection(); mIC = mParent.getCurrentInputConnection();
if (null == mIC) { if (!isConnected()) {
return NgramContext.EMPTY_PREV_WORDS_INFO; return NgramContext.EMPTY_PREV_WORDS_INFO;
} }
final CharSequence prev = getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); final CharSequence prev = getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
@ -608,7 +616,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
public TextRange getWordRangeAtCursor(final SpacingAndPunctuations spacingAndPunctuations, public TextRange getWordRangeAtCursor(final SpacingAndPunctuations spacingAndPunctuations,
final int scriptId) { final int scriptId) {
mIC = mParent.getCurrentInputConnection(); mIC = mParent.getCurrentInputConnection();
if (mIC == null) { if (!isConnected()) {
return null; return null;
} }
final CharSequence before = mIC.getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE, final CharSequence before = mIC.getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE,
@ -824,7 +832,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
mIC = mParent.getCurrentInputConnection(); mIC = mParent.getCurrentInputConnection();
final CharSequence textBeforeCursor = getTextBeforeCursor( final CharSequence textBeforeCursor = getTextBeforeCursor(
Constants.EDITOR_CONTENTS_CACHE_SIZE, 0); Constants.EDITOR_CONTENTS_CACHE_SIZE, 0);
final CharSequence selectedText = null == mIC ? null : mIC.getSelectedText(0 /* flags */); final CharSequence selectedText = isConnected() ? mIC.getSelectedText(0 /* flags */) : null;
if (null == textBeforeCursor || if (null == textBeforeCursor ||
(!TextUtils.isEmpty(selectedText) && mExpectedSelEnd == mExpectedSelStart)) { (!TextUtils.isEmpty(selectedText) && mExpectedSelEnd == mExpectedSelStart)) {
// If textBeforeCursor is null, we have no idea what kind of text field we have or if // If textBeforeCursor is null, we have no idea what kind of text field we have or if
@ -863,7 +871,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
@Override @Override
public boolean performPrivateCommand(final String action, final Bundle data) { public boolean performPrivateCommand(final String action, final Bundle data) {
mIC = mParent.getCurrentInputConnection(); mIC = mParent.getCurrentInputConnection();
if (mIC == null) { if (!isConnected()) {
return false; return false;
} }
return mIC.performPrivateCommand(action, data); return mIC.performPrivateCommand(action, data);
@ -923,7 +931,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
public boolean requestCursorUpdates(final boolean enableMonitor, public boolean requestCursorUpdates(final boolean enableMonitor,
final boolean requestImmediateCallback) { final boolean requestImmediateCallback) {
mIC = mParent.getCurrentInputConnection(); mIC = mParent.getCurrentInputConnection();
if (mIC == null) { if (!isConnected()) {
return false; return false;
} }
return InputConnectionCompatUtils.requestCursorUpdates( return InputConnectionCompatUtils.requestCursorUpdates(