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: I31f928cd7db1cddd771c548cd3dc42f8af64d0e2main
parent
48b071249c
commit
edd94a449e
|
@ -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() {
|
||||||
|
|
|
@ -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()}.
|
||||||
|
|
|
@ -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(
|
||||||
|
|
Loading…
Reference in New Issue