Merge remote-tracking branch 'goog/mnc-dr-ryu-dev'

main
David Riley 2015-12-21 12:37:57 -08:00
commit fdb2cf4950
3 changed files with 176 additions and 103 deletions

View File

@ -196,6 +196,8 @@ final class EmojiCategory {
addShownCategoryId(EmojiCategory.ID_FLAGS); addShownCategoryId(EmojiCategory.ID_FLAGS);
} }
} }
} else {
addShownCategoryId(EmojiCategory.ID_SYMBOLS);
} }
addShownCategoryId(EmojiCategory.ID_EMOTICONS); addShownCategoryId(EmojiCategory.ID_EMOTICONS);
@ -204,9 +206,14 @@ final class EmojiCategory {
recentsKbd.loadRecentKeys(mCategoryKeyboardMap.values()); recentsKbd.loadRecentKeys(mCategoryKeyboardMap.values());
mCurrentCategoryId = Settings.readLastShownEmojiCategoryId(mPrefs, defaultCategoryId); mCurrentCategoryId = Settings.readLastShownEmojiCategoryId(mPrefs, defaultCategoryId);
if (mCurrentCategoryId == EmojiCategory.ID_RECENTS && Log.i(TAG, "Last Emoji category id is " + mCurrentCategoryId);
if (!isShownCategoryId(mCurrentCategoryId)) {
Log.i(TAG, "Last emoji category " + mCurrentCategoryId +
" is invalid, starting in " + defaultCategoryId);
mCurrentCategoryId = defaultCategoryId;
} else if (mCurrentCategoryId == EmojiCategory.ID_RECENTS &&
recentsKbd.getSortedKeys().isEmpty()) { recentsKbd.getSortedKeys().isEmpty()) {
Log.i(TAG, "No recent emojis found, starting in category " + mCurrentCategoryId); Log.i(TAG, "No recent emojis found, starting in category " + defaultCategoryId);
mCurrentCategoryId = defaultCategoryId; mCurrentCategoryId = defaultCategoryId;
} }
} }
@ -219,6 +226,15 @@ final class EmojiCategory {
mShownCategories.add(properties); mShownCategories.add(properties);
} }
private boolean isShownCategoryId(final int categoryId) {
for (final CategoryProperties prop : mShownCategories) {
if (prop.mCategoryId == categoryId) {
return true;
}
}
return false;
}
public static String getCategoryName(final int categoryId, final int categoryPageId) { public static String getCategoryName(final int categoryId, final int categoryPageId) {
return sCategoryName[categoryId] + "-" + categoryPageId; return sCategoryName[categoryId] + "-" + categoryPageId;
} }

View File

@ -18,14 +18,15 @@ package com.android.inputmethod.latin;
import android.content.res.Resources; import android.content.res.Resources;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import android.view.KeyEvent; import android.view.KeyEvent;
import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.latin.settings.Settings; import com.android.inputmethod.latin.settings.Settings;
import java.util.HashMap; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -35,28 +36,155 @@ import javax.annotation.Nonnull;
*/ */
final class EmojiAltPhysicalKeyDetector { final class EmojiAltPhysicalKeyDetector {
private static final String TAG = "EmojiAltPhysicalKeyDetector"; private static final String TAG = "EmojiAltPhysicalKeyDetector";
private static final boolean DEBUG = false;
private final Map<Integer, Integer> mEmojiSwitcherMap; private List<EmojiHotKeys> mHotKeysList;
private final Map<Integer, Integer> mSymbolsShiftedSwitcherMap;
private final Map<Integer, Integer> mCombinedSwitcherMap;
// Set of keys codes that have been used as modifiers. private static class HotKeySet extends HashSet<Pair<Integer, Integer>> { };
private Set<Integer> mActiveModifiers;
public EmojiAltPhysicalKeyDetector(@Nonnull final Resources resources) { private abstract class EmojiHotKeys {
mEmojiSwitcherMap = parseSwitchDefinition(resources, R.array.keyboard_switcher_emoji); private final String mName;
mSymbolsShiftedSwitcherMap = parseSwitchDefinition( private final HotKeySet mKeySet;
resources, R.array.keyboard_switcher_symbols_shifted);
mCombinedSwitcherMap = new HashMap<>(); boolean mCanFire;
mCombinedSwitcherMap.putAll(mEmojiSwitcherMap); int mMetaState;
mCombinedSwitcherMap.putAll(mSymbolsShiftedSwitcherMap);
mActiveModifiers = new HashSet<>(); public EmojiHotKeys(final String name, HotKeySet keySet) {
mName = name;
mKeySet = keySet;
mCanFire = false;
}
public void onKeyDown(@Nonnull final KeyEvent keyEvent) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - considering " + keyEvent);
}
final Pair<Integer, Integer> key =
Pair.create(keyEvent.getKeyCode(), keyEvent.getMetaState());
if (mKeySet.contains(key)) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - enabling action");
}
mCanFire = true;
mMetaState = keyEvent.getMetaState();
} else if (mCanFire) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - disabling action");
}
mCanFire = false;
}
}
public void onKeyUp(@Nonnull final KeyEvent keyEvent) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyUp() - " + mName + " - considering " + keyEvent);
}
final int keyCode = keyEvent.getKeyCode();
int metaState = keyEvent.getMetaState();
if (KeyEvent.isModifierKey(keyCode)) {
// Try restoring meta stat in case the released key was a modifier.
// I am sure one can come up with scenarios to break this, but it
// seems to work well in practice.
metaState |= mMetaState;
}
final Pair<Integer, Integer> key = Pair.create(keyCode, metaState);
if (mKeySet.contains(key)) {
if (mCanFire) {
if (!keyEvent.isCanceled()) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyUp() - " + mName + " - firing action");
}
action();
} else {
// This key up event was a part of key combinations and
// should be ignored.
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyUp() - " + mName + " - canceled, ignoring action");
}
}
mCanFire = false;
}
}
if (mCanFire) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyUp() - " + mName + " - disabling action");
}
mCanFire = false;
}
}
protected abstract void action();
} }
private static Map<Integer, Integer> parseSwitchDefinition( public EmojiAltPhysicalKeyDetector(@Nonnull final Resources resources) {
@Nonnull final Resources resources, mHotKeysList = new ArrayList<EmojiHotKeys>();
final int resourceId) {
final Map<Integer, Integer> definition = new HashMap<>(); final HotKeySet emojiSwitchSet = parseHotKeys(
resources, R.array.keyboard_switcher_emoji);
final EmojiHotKeys emojiHotKeys = new EmojiHotKeys("emoji", emojiSwitchSet) {
@Override
protected void action() {
final KeyboardSwitcher switcher = KeyboardSwitcher.getInstance();
switcher.onToggleKeyboard(KeyboardSwitcher.KeyboardSwitchState.EMOJI);
}
};
mHotKeysList.add(emojiHotKeys);
final HotKeySet symbolsSwitchSet = parseHotKeys(
resources, R.array.keyboard_switcher_symbols_shifted);
final EmojiHotKeys symbolsHotKeys = new EmojiHotKeys("symbols", symbolsSwitchSet) {
@Override
protected void action() {
final KeyboardSwitcher switcher = KeyboardSwitcher.getInstance();
switcher.onToggleKeyboard(KeyboardSwitcher.KeyboardSwitchState.SYMBOLS_SHIFTED);
}
};
mHotKeysList.add(symbolsHotKeys);
}
public void onKeyDown(@Nonnull final KeyEvent keyEvent) {
if (DEBUG) {
Log.d(TAG, "onKeyDown(): " + keyEvent);
}
if (shouldProcessEvent(keyEvent)) {
for (EmojiHotKeys hotKeys : mHotKeysList) {
hotKeys.onKeyDown(keyEvent);
}
}
}
public void onKeyUp(@Nonnull final KeyEvent keyEvent) {
if (DEBUG) {
Log.d(TAG, "onKeyUp(): " + keyEvent);
}
if (shouldProcessEvent(keyEvent)) {
for (EmojiHotKeys hotKeys : mHotKeysList) {
hotKeys.onKeyUp(keyEvent);
}
}
}
private static boolean shouldProcessEvent(@Nonnull final KeyEvent keyEvent) {
if (!Settings.getInstance().getCurrent().mEnableEmojiAltPhysicalKey) {
// The feature is disabled.
if (DEBUG) {
Log.d(TAG, "shouldProcessEvent(): Disabled");
}
return false;
}
return true;
}
private static HotKeySet parseHotKeys(
@Nonnull final Resources resources, final int resourceId) {
final HotKeySet keySet = new HotKeySet();
final String name = resources.getResourceEntryName(resourceId); final String name = resources.getResourceEntryName(resourceId);
final String[] values = resources.getStringArray(resourceId); final String[] values = resources.getStringArray(resourceId);
for (int i = 0; values != null && i < values.length; i++) { for (int i = 0; values != null && i < values.length; i++) {
@ -65,91 +193,15 @@ final class EmojiAltPhysicalKeyDetector {
Log.w(TAG, "Expected 2 integers in " + name + "[" + i + "] : " + values[i]); Log.w(TAG, "Expected 2 integers in " + name + "[" + i + "] : " + values[i]);
} }
try { try {
definition.put(Integer.parseInt(valuePair[0]), Integer.parseInt(valuePair[1])); final Integer keyCode = Integer.parseInt(valuePair[0]);
final Integer metaState = Integer.parseInt(valuePair[1]);
final Pair<Integer, Integer> key = Pair.create(
keyCode, KeyEvent.normalizeMetaState(metaState));
keySet.add(key);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
Log.w(TAG, "Failed to parse " + name + "[" + i + "] : " + values[i], e); Log.w(TAG, "Failed to parse " + name + "[" + i + "] : " + values[i], e);
} }
} }
return definition; return keySet;
}
/**
* Determine whether an up key event came from a mapped modifier key.
*
* @param keyEvent an up key event.
*/
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;
}
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;
}
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 (!isMappedKeyCode(keyEvent)) {
// Nothing special about this key.
Log.d(TAG, "onKeyUp() : Not Mapped: " + keyCode);
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);
}
}
/**
* @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;
}
/**
* @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();
final int metaState = keyEvent.getMetaState();
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;
} }
} }

View File

@ -1658,6 +1658,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Hooks for hardware keyboard // Hooks for hardware keyboard
@Override @Override
public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) { public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) {
if (mEmojiAltPhysicalKeyDetector == null) {
mEmojiAltPhysicalKeyDetector = new EmojiAltPhysicalKeyDetector(
getApplicationContext().getResources());
}
mEmojiAltPhysicalKeyDetector.onKeyDown(keyEvent);
if (!ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) { if (!ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) {
return super.onKeyDown(keyCode, keyEvent); return super.onKeyDown(keyCode, keyEvent);
} }