summaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
-rw-r--r--java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java138
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java27
2 files changed, 111 insertions, 54 deletions
diff --git a/java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java b/java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java
index 2a92daebc..2529424c0 100644
--- a/java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java
+++ b/java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java
@@ -16,88 +16,140 @@
package com.android.inputmethod.latin;
+import android.content.res.Resources;
import android.util.Log;
import android.view.KeyEvent;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.latin.settings.Settings;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
/**
* A class for detecting Emoji-Alt physical key.
*/
final class EmojiAltPhysicalKeyDetector {
private static final String TAG = "EmojiAltPhysicalKeyDetector";
- private final RichInputConnection mRichInputConnection;
+ private final Map<Integer, Integer> mEmojiSwitcherMap;
+ private final Map<Integer, Integer> mSymbolsShiftedSwitcherMap;
+ private final Map<Integer, Integer> mCombinedSwitcherMap;
- // 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.
- private boolean mAltHasBeenUsedAsAModifier;
+ // Set of keys codes that have been used as modifiers.
+ private Set<Integer> mActiveModifiers;
- public EmojiAltPhysicalKeyDetector(final RichInputConnection richInputConnection) {
- mRichInputConnection = richInputConnection;
+ public EmojiAltPhysicalKeyDetector(@Nonnull final Resources resources) {
+ mEmojiSwitcherMap = parseSwitchDefinition(resources, R.array.keyboard_switcher_emoji);
+ mSymbolsShiftedSwitcherMap = parseSwitchDefinition(
+ resources, R.array.keyboard_switcher_symbols_shifted);
+ mCombinedSwitcherMap = new HashMap<>();
+ mCombinedSwitcherMap.putAll(mEmojiSwitcherMap);
+ mCombinedSwitcherMap.putAll(mSymbolsShiftedSwitcherMap);
+ mActiveModifiers = new HashSet<>();
}
- /**
- * Record a down key event.
- * @param keyEvent a down key event.
- */
- public void onKeyDown(final KeyEvent keyEvent) {
- if (isAltKey(keyEvent)) {
- mAltHasBeenUsedAsAModifier = false;
- }
- if (containsAltModifier(keyEvent)) {
- mAltHasBeenUsedAsAModifier = true;
+ private static Map<Integer, Integer> parseSwitchDefinition(
+ @Nonnull final Resources resources,
+ final int resourceId) {
+ final Map<Integer, Integer> definition = new HashMap<>();
+ final String name = resources.getResourceEntryName(resourceId);
+ final String[] values = resources.getStringArray(resourceId);
+ for (int i = 0; values != null && i < values.length; i++) {
+ String[] valuePair = values[i].split(",");
+ if (valuePair.length != 2) {
+ Log.w(TAG, "Expected 2 integers in " + name + "[" + i + "] : " + values[i]);
+ }
+ try {
+ definition.put(Integer.parseInt(valuePair[0]), Integer.parseInt(valuePair[1]));
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "Failed to parse " + name + "[" + i + "] : " + values[i], e);
+ }
}
+ return definition;
}
/**
- * Determine whether an up key event is a special key up or not.
+ * Determine whether an up key event came from a mapped modifier key.
+ *
* @param keyEvent an up key event.
*/
- public void onKeyUp(final KeyEvent keyEvent) {
+ public void onKeyUp(@Nonnull final KeyEvent keyEvent) {
+ Log.d(TAG, "onKeyUp() : " + keyEvent);
+ if (!Settings.getInstance().getCurrent().mEnableEmojiAltPhysicalKey) {
+ // The feature is disabled.
+ Log.d(TAG, "onKeyUp() : Disabled");
+ return;
+ }
if (keyEvent.isCanceled()) {
// This key up event was a part of key combinations and should be ignored.
+ Log.d(TAG, "onKeyUp() : Canceled");
return;
}
- if (!isAltKey(keyEvent)) {
- mAltHasBeenUsedAsAModifier |= containsAltModifier(keyEvent);
+ final Integer mappedModifier = getMappedModifier(keyEvent);
+ if (mappedModifier != null) {
+ // If the key was modified by a mapped key, then ignore the next time
+ // the same modifier key comes up.
+ Log.d(TAG, "onKeyUp() : Using Modifier: " + mappedModifier);
+ mActiveModifiers.add(mappedModifier);
return;
}
- if (containsAltModifier(keyEvent)) {
- mAltHasBeenUsedAsAModifier = true;
+ final int keyCode = keyEvent.getKeyCode();
+ if (mActiveModifiers.contains(keyCode)) {
+ // Used as a modifier, not a standalone key press.
+ Log.d(TAG, "onKeyUp() : Used as Modifier: " + keyCode);
+ mActiveModifiers.remove(keyCode);
return;
}
- if (!Settings.getInstance().getCurrent().mEnableEmojiAltPhysicalKey) {
+ if (!isMappedKeyCode(keyEvent)) {
+ // Nothing special about this key.
+ Log.d(TAG, "onKeyUp() : Not Mapped: " + keyCode);
return;
}
- if (mAltHasBeenUsedAsAModifier) {
- return;
+ final KeyboardSwitcher switcher = KeyboardSwitcher.getInstance();
+ if (mEmojiSwitcherMap.keySet().contains(keyCode)) {
+ switcher.onToggleKeyboard(KeyboardSwitcher.KeyboardSwitchState.EMOJI);
+ } else if (mSymbolsShiftedSwitcherMap.keySet().contains(keyCode)) {
+ switcher.onToggleKeyboard(KeyboardSwitcher.KeyboardSwitchState.SYMBOLS_SHIFTED);
+ } else {
+ Log.w(TAG, "Cannot toggle on keyCode: " + keyCode);
}
- onEmojiAltKeyDetected();
}
- private static void onEmojiAltKeyDetected() {
- KeyboardSwitcher.getInstance().onToggleEmojiKeyboard();
+ /**
+ * @param keyEvent pressed key event
+ * @return true iff the user pressed a mapped modifier key.
+ */
+ private boolean isMappedKeyCode(@Nonnull final KeyEvent keyEvent) {
+ return mCombinedSwitcherMap.get(keyEvent.getKeyCode()) != null;
}
- private static boolean isAltKey(final KeyEvent keyEvent) {
+ /**
+ * @param keyEvent pressed key event
+ * @return the mapped modifier used with this key opress, if any.
+ */
+ private Integer getMappedModifier(@Nonnull final KeyEvent keyEvent) {
final int keyCode = keyEvent.getKeyCode();
- return keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT;
- }
-
- private static boolean containsAltModifier(final KeyEvent keyEvent) {
final int metaState = keyEvent.getMetaState();
- // TODO: Support multiple keyboards. Take device id into account.
- switch (keyEvent.getKeyCode()) {
- case KeyEvent.KEYCODE_ALT_LEFT:
- // Return true if Left-Alt is pressed with Right-Alt pressed.
- return (metaState & KeyEvent.META_ALT_RIGHT_ON) != 0;
- case KeyEvent.KEYCODE_ALT_RIGHT:
- // Return true if Right-Alt is pressed with Left-Alt pressed.
- return (metaState & KeyEvent.META_ALT_LEFT_ON) != 0;
- default:
- return (metaState & (KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_RIGHT_ON)) != 0;
+ for (int mappedKeyCode : mCombinedSwitcherMap.keySet()) {
+ if (keyCode == mappedKeyCode) {
+ Log.d(TAG, "getMappedModifier() : KeyCode = MappedKeyCode = " + mappedKeyCode);
+ continue;
+ }
+ final Integer mappedMeta = mCombinedSwitcherMap.get(mappedKeyCode);
+ if (mappedMeta == null || mappedMeta.intValue() == -1) {
+ continue;
+ }
+ if ((metaState & mappedMeta) != 0) {
+ Log.d(TAG, "getMappedModifier() : MetaState(" + metaState
+ + ") contains MappedMeta(" + mappedMeta + ")");
+ return mappedKeyCode;
+ }
}
+ return null;
}
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 1f2b6f25d..25a5de250 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -142,8 +142,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private RichInputMethodManager mRichImm;
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
private final SubtypeState mSubtypeState = new SubtypeState();
- private final EmojiAltPhysicalKeyDetector mEmojiAltPhysicalKeyDetector =
- new EmojiAltPhysicalKeyDetector(mInputLogic.mConnection);
+ private EmojiAltPhysicalKeyDetector mEmojiAltPhysicalKeyDetector;
private StatsUtilsManager mStatsUtilsManager;
// Working variable for {@link #startShowingInputView()} and
// {@link #onEvaluateInputViewShown()}.
@@ -702,6 +701,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mInputLogic.recycle();
}
+ private boolean isImeSuppressedByHardwareKeyboard() {
+ final KeyboardSwitcher switcher = KeyboardSwitcher.getInstance();
+ return switcher.isImeSuppressedByHardwareKeyboard(
+ mSettings.getCurrent(), switcher.getKeyboardSwitchState());
+ }
+
@Override
public void onConfigurationChanged(final Configuration conf) {
SettingsValues settingsValues = mSettings.getCurrent();
@@ -716,7 +721,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// have a change in hardware keyboard configuration.
loadSettings();
settingsValues = mSettings.getCurrent();
- if (settingsValues.mHasHardwareKeyboard) {
+ if (isImeSuppressedByHardwareKeyboard()) {
// We call cleanupInternalStateForFinishInput() because it's the right thing to do;
// however, it seems at the moment the framework is passing us a seemingly valid
// but actually non-functional InputConnection object. So if this bug ever gets
@@ -874,7 +879,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// can go into the correct mode, so we need to do some housekeeping here.
final boolean needToCallLoadKeyboardLater;
final Suggest suggest = mInputLogic.mSuggest;
- if (!currentSettingsValues.mHasHardwareKeyboard) {
+ if (!isImeSuppressedByHardwareKeyboard()) {
// The app calling setText() has the effect of clearing the composing
// span, so we should reset our state unconditionally, even if restarting is true.
// We also tell the input logic about the combining rules for the current subtype, so
@@ -1118,8 +1123,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return;
}
final int inputHeight = mInputView.getHeight();
- final boolean hasHardwareKeyboard = settingsValues.mHasHardwareKeyboard;
- if (hasHardwareKeyboard && visibleKeyboardView.getVisibility() == View.GONE) {
+ if (isImeSuppressedByHardwareKeyboard() && !visibleKeyboardView.isShown()) {
// If there is a hardware keyboard and a visible software keyboard view has been hidden,
// no visual element will be shown on the screen.
outInsets.contentTopInsets = inputHeight;
@@ -1165,7 +1169,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public boolean onShowInputRequested(final int flags, final boolean configChange) {
- if (Settings.getInstance().getCurrent().mHasHardwareKeyboard) {
+ if (isImeSuppressedByHardwareKeyboard()) {
return true;
}
return super.onShowInputRequested(flags, configChange);
@@ -1182,7 +1186,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public boolean onEvaluateFullscreenMode() {
final SettingsValues settingsValues = mSettings.getCurrent();
- if (settingsValues.mHasHardwareKeyboard) {
+ if (isImeSuppressedByHardwareKeyboard()) {
// If there is a hardware keyboard, disable full screen mode.
return false;
}
@@ -1646,8 +1650,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Hooks for hardware keyboard
@Override
public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) {
- // TODO: This should be processed in {@link InputLogic}.
- mEmojiAltPhysicalKeyDetector.onKeyDown(keyEvent);
if (!ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) {
return super.onKeyDown(keyCode, keyEvent);
}
@@ -1668,7 +1670,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public boolean onKeyUp(final int keyCode, final KeyEvent keyEvent) {
- // TODO: This should be processed in {@link InputLogic}.
+ if (mEmojiAltPhysicalKeyDetector == null) {
+ mEmojiAltPhysicalKeyDetector = new EmojiAltPhysicalKeyDetector(
+ getApplicationContext().getResources());
+ }
mEmojiAltPhysicalKeyDetector.onKeyUp(keyEvent);
if (!ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) {
return super.onKeyUp(keyCode, keyEvent);