am 7aedc8a0
: Automaticaly snap back to the previous mode from sliding input (DO NOT MERGE)
* commit '7aedc8a054aca41e6c80d8faf0ed2dd47f9815c4': Automaticaly snap back to the previous mode from sliding input (DO NOT MERGE)
This commit is contained in:
commit
0b157cc66f
4 changed files with 213 additions and 68 deletions
|
@ -82,10 +82,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
R.xml.kbd_symbols_shift, R.xml.kbd_symbols_shift_black};
|
R.xml.kbd_symbols_shift, R.xml.kbd_symbols_shift_black};
|
||||||
private static final int[] KBD_QWERTY = new int[] {R.xml.kbd_qwerty, R.xml.kbd_qwerty_black};
|
private static final int[] KBD_QWERTY = new int[] {R.xml.kbd_qwerty, R.xml.kbd_qwerty_black};
|
||||||
|
|
||||||
private static final int SYMBOLS_MODE_STATE_NONE = 0;
|
|
||||||
private static final int SYMBOLS_MODE_STATE_BEGIN = 1;
|
|
||||||
private static final int SYMBOLS_MODE_STATE_SYMBOL = 2;
|
|
||||||
|
|
||||||
private LatinKeyboardView mInputView;
|
private LatinKeyboardView mInputView;
|
||||||
private static final int[] ALPHABET_MODES = {
|
private static final int[] ALPHABET_MODES = {
|
||||||
KEYBOARDMODE_NORMAL,
|
KEYBOARDMODE_NORMAL,
|
||||||
|
@ -99,13 +95,14 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
KEYBOARDMODE_IM_WITH_SETTINGS_KEY,
|
KEYBOARDMODE_IM_WITH_SETTINGS_KEY,
|
||||||
KEYBOARDMODE_WEB_WITH_SETTINGS_KEY };
|
KEYBOARDMODE_WEB_WITH_SETTINGS_KEY };
|
||||||
|
|
||||||
private final LatinIME mInputMethodService;
|
private LatinIME mInputMethodService;
|
||||||
|
|
||||||
private KeyboardId mSymbolsId;
|
private KeyboardId mSymbolsId;
|
||||||
private KeyboardId mSymbolsShiftedId;
|
private KeyboardId mSymbolsShiftedId;
|
||||||
|
|
||||||
private KeyboardId mCurrentId;
|
private KeyboardId mCurrentId;
|
||||||
private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboards;
|
private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboards =
|
||||||
|
new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
|
||||||
|
|
||||||
private int mMode = MODE_NONE; /** One of the MODE_XXX values */
|
private int mMode = MODE_NONE; /** One of the MODE_XXX values */
|
||||||
private int mImeOptions;
|
private int mImeOptions;
|
||||||
|
@ -116,7 +113,14 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
private boolean mHasVoice;
|
private boolean mHasVoice;
|
||||||
private boolean mVoiceOnPrimary;
|
private boolean mVoiceOnPrimary;
|
||||||
private boolean mPreferSymbols;
|
private boolean mPreferSymbols;
|
||||||
private int mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
|
|
||||||
|
private static final int AUTO_MODE_SWITCH_STATE_ALPHA = 0;
|
||||||
|
private static final int AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN = 1;
|
||||||
|
private static final int AUTO_MODE_SWITCH_STATE_SYMBOL = 2;
|
||||||
|
// The following states are used only on the distinct multi-touch panel devices.
|
||||||
|
private static final int AUTO_MODE_SWITCH_STATE_MOMENTARY = 3;
|
||||||
|
private static final int AUTO_MODE_SWITCH_STATE_CHORDING = 4;
|
||||||
|
private int mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA;
|
||||||
|
|
||||||
// Indicates whether or not we have the settings key
|
// Indicates whether or not we have the settings key
|
||||||
private boolean mHasSettingsKey;
|
private boolean mHasSettingsKey;
|
||||||
|
@ -133,17 +137,27 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
|
|
||||||
private int mLayoutId;
|
private int mLayoutId;
|
||||||
|
|
||||||
public KeyboardSwitcher(LatinIME ims) {
|
private static final KeyboardSwitcher sInstance = new KeyboardSwitcher();
|
||||||
mInputMethodService = ims;
|
|
||||||
|
public static KeyboardSwitcher getInstance() {
|
||||||
|
return sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private KeyboardSwitcher() {
|
||||||
|
// Intentional empty constructor for singleton.
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init(LatinIME ims) {
|
||||||
|
sInstance.mInputMethodService = ims;
|
||||||
|
|
||||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ims);
|
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ims);
|
||||||
mLayoutId = Integer.valueOf(prefs.getString(PREF_KEYBOARD_LAYOUT, DEFAULT_LAYOUT_ID));
|
sInstance.mLayoutId = Integer.valueOf(
|
||||||
updateSettingsKeyState(prefs);
|
prefs.getString(PREF_KEYBOARD_LAYOUT, DEFAULT_LAYOUT_ID));
|
||||||
prefs.registerOnSharedPreferenceChangeListener(this);
|
sInstance.updateSettingsKeyState(prefs);
|
||||||
|
prefs.registerOnSharedPreferenceChangeListener(sInstance);
|
||||||
|
|
||||||
mKeyboards = new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
|
sInstance.mSymbolsId = sInstance.makeSymbolsId(false);
|
||||||
mSymbolsId = makeSymbolsId(false);
|
sInstance.mSymbolsShiftedId = sInstance.makeSymbolsShiftedId(false);
|
||||||
mSymbolsShiftedId = makeSymbolsShiftedId(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -243,7 +257,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKeyboardMode(int mode, int imeOptions, boolean enableVoice) {
|
public void setKeyboardMode(int mode, int imeOptions, boolean enableVoice) {
|
||||||
mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
|
mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA;
|
||||||
mPreferSymbols = mode == MODE_SYMBOLS;
|
mPreferSymbols = mode == MODE_SYMBOLS;
|
||||||
if (mode == MODE_SYMBOLS) {
|
if (mode == MODE_SYMBOLS) {
|
||||||
mode = MODE_TEXT;
|
mode = MODE_TEXT;
|
||||||
|
@ -410,12 +424,18 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onCancelInput() {
|
||||||
|
// Snap back to the previous keyboard mode if the user cancels sliding input.
|
||||||
|
if (mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_MOMENTARY && getPointerCount() == 1)
|
||||||
|
mInputMethodService.changeKeyboardMode();
|
||||||
|
}
|
||||||
|
|
||||||
public void toggleSymbols() {
|
public void toggleSymbols() {
|
||||||
setKeyboardMode(mMode, mImeOptions, mHasVoice, !mIsSymbols);
|
setKeyboardMode(mMode, mImeOptions, mHasVoice, !mIsSymbols);
|
||||||
if (mIsSymbols && !mPreferSymbols) {
|
if (mIsSymbols && !mPreferSymbols) {
|
||||||
mSymbolsModeState = SYMBOLS_MODE_STATE_BEGIN;
|
mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN;
|
||||||
} else {
|
} else {
|
||||||
mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
|
mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,24 +443,72 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
return mInputView != null && mInputView.hasDistinctMultitouch();
|
return mInputView != null && mInputView.hasDistinctMultitouch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAutoModeSwitchStateMomentary() {
|
||||||
|
mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_MOMENTARY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInMomentaryAutoModeSwitchState() {
|
||||||
|
return mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_MOMENTARY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInChordingAutoModeSwitchState() {
|
||||||
|
return mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_CHORDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isVibrateAndSoundFeedbackRequired() {
|
||||||
|
return mInputView != null && !mInputView.isInSlidingKeyInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getPointerCount() {
|
||||||
|
return mInputView == null ? 0 : mInputView.getPointerCount();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates state machine to figure out when to automatically switch back to alpha mode.
|
* Updates state machine to figure out when to automatically snap back to the previous mode.
|
||||||
* Returns true if the keyboard needs to switch back
|
|
||||||
*/
|
*/
|
||||||
public boolean onKey(int key) {
|
public void onKey(int key) {
|
||||||
// Switch back to alpha mode if user types one or more non-space/enter characters
|
// Switch back to alpha mode if user types one or more non-space/enter characters
|
||||||
// followed by a space/enter
|
// followed by a space/enter
|
||||||
switch (mSymbolsModeState) {
|
switch (mAutoModeSwitchState) {
|
||||||
case SYMBOLS_MODE_STATE_BEGIN:
|
case AUTO_MODE_SWITCH_STATE_MOMENTARY:
|
||||||
if (key != LatinIME.KEYCODE_SPACE && key != LatinIME.KEYCODE_ENTER && key > 0) {
|
// Only distinct multi touch devices can be in this state.
|
||||||
mSymbolsModeState = SYMBOLS_MODE_STATE_SYMBOL;
|
// On non-distinct multi touch devices, mode change key is handled by {@link onKey},
|
||||||
|
// not by {@link onPress} and {@link onRelease}. So, on such devices,
|
||||||
|
// {@link mAutoModeSwitchState} starts from {@link AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN},
|
||||||
|
// or {@link AUTO_MODE_SWITCH_STATE_ALPHA}, not from
|
||||||
|
// {@link AUTO_MODE_SWITCH_STATE_MOMENTARY}.
|
||||||
|
if (key == LatinKeyboard.KEYCODE_MODE_CHANGE) {
|
||||||
|
// Detected only the mode change key has been pressed, and then released.
|
||||||
|
if (mIsSymbols) {
|
||||||
|
mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN;
|
||||||
|
} else {
|
||||||
|
mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA;
|
||||||
|
}
|
||||||
|
} else if (getPointerCount() == 1) {
|
||||||
|
// Snap back to the previous keyboard mode if the user pressed the mode change key
|
||||||
|
// and slid to other key, then released the finger.
|
||||||
|
// If the user cancels the sliding input, snapping back to the previous keyboard
|
||||||
|
// mode is handled by {@link #onCancelInput}.
|
||||||
|
mInputMethodService.changeKeyboardMode();
|
||||||
|
} else {
|
||||||
|
// Chording input is being started. The keyboard mode will be snapped back to the
|
||||||
|
// previous mode in {@link onReleaseSymbol} when the mode change key is released.
|
||||||
|
mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_CHORDING;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SYMBOLS_MODE_STATE_SYMBOL:
|
case AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN:
|
||||||
if (key == LatinIME.KEYCODE_ENTER || key == LatinIME.KEYCODE_SPACE) return true;
|
if (key != LatinIME.KEYCODE_SPACE && key != LatinIME.KEYCODE_ENTER && key >= 0) {
|
||||||
|
mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AUTO_MODE_SWITCH_STATE_SYMBOL:
|
||||||
|
// Snap back to alpha keyboard mode if user types one or more non-space/enter
|
||||||
|
// characters followed by a space/enter.
|
||||||
|
if (key == LatinIME.KEYCODE_ENTER || key == LatinIME.KEYCODE_SPACE) {
|
||||||
|
mInputMethodService.changeKeyboardMode();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LatinKeyboardView getInputView() {
|
public LatinKeyboardView getInputView() {
|
||||||
|
|
|
@ -342,6 +342,7 @@ public class LatinIME extends InputMethodService
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
LatinImeLogger.init(this);
|
LatinImeLogger.init(this);
|
||||||
|
KeyboardSwitcher.init(this);
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
//setStatusIcon(R.drawable.ime_qwerty);
|
//setStatusIcon(R.drawable.ime_qwerty);
|
||||||
mResources = getResources();
|
mResources = getResources();
|
||||||
|
@ -349,7 +350,7 @@ public class LatinIME extends InputMethodService
|
||||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
mLanguageSwitcher = new LanguageSwitcher(this);
|
mLanguageSwitcher = new LanguageSwitcher(this);
|
||||||
mLanguageSwitcher.loadLocales(prefs);
|
mLanguageSwitcher.loadLocales(prefs);
|
||||||
mKeyboardSwitcher = new KeyboardSwitcher(this);
|
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
|
||||||
mKeyboardSwitcher.setLanguageSwitcher(mLanguageSwitcher);
|
mKeyboardSwitcher.setLanguageSwitcher(mLanguageSwitcher);
|
||||||
mSystemLocale = conf.locale.toString();
|
mSystemLocale = conf.locale.toString();
|
||||||
mLanguageSwitcher.setSystemLocale(conf.locale);
|
mLanguageSwitcher.setSystemLocale(conf.locale);
|
||||||
|
@ -1247,9 +1248,7 @@ public class LatinIME extends InputMethodService
|
||||||
// Cancel the just reverted state
|
// Cancel the just reverted state
|
||||||
mJustRevertedSeparator = null;
|
mJustRevertedSeparator = null;
|
||||||
}
|
}
|
||||||
if (mKeyboardSwitcher.onKey(primaryCode)) {
|
mKeyboardSwitcher.onKey(primaryCode);
|
||||||
changeKeyboardMode();
|
|
||||||
}
|
|
||||||
// Reset after any single keystroke
|
// Reset after any single keystroke
|
||||||
mEnteredText = null;
|
mEnteredText = null;
|
||||||
}
|
}
|
||||||
|
@ -1269,6 +1268,7 @@ public class LatinIME extends InputMethodService
|
||||||
ic.commitText(text, 1);
|
ic.commitText(text, 1);
|
||||||
ic.endBatchEdit();
|
ic.endBatchEdit();
|
||||||
updateShiftKeyState(getCurrentInputEditorInfo());
|
updateShiftKeyState(getCurrentInputEditorInfo());
|
||||||
|
mKeyboardSwitcher.onKey(0); // dummy key code.
|
||||||
mJustRevertedSeparator = null;
|
mJustRevertedSeparator = null;
|
||||||
mJustAddedAutoSpace = false;
|
mJustAddedAutoSpace = false;
|
||||||
mEnteredText = text;
|
mEnteredText = text;
|
||||||
|
@ -1276,6 +1276,7 @@ public class LatinIME extends InputMethodService
|
||||||
|
|
||||||
public void onCancel() {
|
public void onCancel() {
|
||||||
// User released a finger outside any key
|
// User released a finger outside any key
|
||||||
|
mKeyboardSwitcher.onCancelInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleBackspace() {
|
private void handleBackspace() {
|
||||||
|
@ -2283,15 +2284,18 @@ public class LatinIME extends InputMethodService
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onPress(int primaryCode) {
|
public void onPress(int primaryCode) {
|
||||||
|
if (mKeyboardSwitcher.isVibrateAndSoundFeedbackRequired()) {
|
||||||
vibrate();
|
vibrate();
|
||||||
playKeyClick(primaryCode);
|
playKeyClick(primaryCode);
|
||||||
|
}
|
||||||
final boolean distinctMultiTouch = mKeyboardSwitcher.hasDistinctMultitouch();
|
final boolean distinctMultiTouch = mKeyboardSwitcher.hasDistinctMultitouch();
|
||||||
if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) {
|
if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) {
|
||||||
mShiftKeyState.onPress();
|
mShiftKeyState.onPress();
|
||||||
handleShift();
|
handleShift();
|
||||||
} else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
|
} else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
|
||||||
mSymbolKeyState.onPress();
|
|
||||||
changeKeyboardMode();
|
changeKeyboardMode();
|
||||||
|
mSymbolKeyState.onPress();
|
||||||
|
mKeyboardSwitcher.setAutoModeSwitchStateMomentary();
|
||||||
} else {
|
} else {
|
||||||
mShiftKeyState.onOtherKeyPressed();
|
mShiftKeyState.onOtherKeyPressed();
|
||||||
mSymbolKeyState.onOtherKeyPressed();
|
mSymbolKeyState.onOtherKeyPressed();
|
||||||
|
@ -2308,7 +2312,9 @@ public class LatinIME extends InputMethodService
|
||||||
resetShift();
|
resetShift();
|
||||||
mShiftKeyState.onRelease();
|
mShiftKeyState.onRelease();
|
||||||
} else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
|
} else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
|
||||||
if (mSymbolKeyState.isMomentary())
|
// Snap back to the previous keyboard mode if the user chords the mode change key and
|
||||||
|
// other key, then released the mode change key.
|
||||||
|
if (mKeyboardSwitcher.isInChordingAutoModeSwitchState())
|
||||||
changeKeyboardMode();
|
changeKeyboardMode();
|
||||||
mSymbolKeyState.onRelease();
|
mSymbolKeyState.onRelease();
|
||||||
}
|
}
|
||||||
|
@ -2562,7 +2568,7 @@ public class LatinIME extends InputMethodService
|
||||||
mOptionsDialog.show();
|
mOptionsDialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void changeKeyboardMode() {
|
public void changeKeyboardMode() {
|
||||||
mKeyboardSwitcher.toggleSymbols();
|
mKeyboardSwitcher.toggleSymbols();
|
||||||
if (mCapsLock && mKeyboardSwitcher.isAlphabetMode()) {
|
if (mCapsLock && mKeyboardSwitcher.isAlphabetMode()) {
|
||||||
mKeyboardSwitcher.setShiftLocked(mCapsLock);
|
mKeyboardSwitcher.setShiftLocked(mCapsLock);
|
||||||
|
|
|
@ -343,7 +343,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
cancelPopupPreview();
|
cancelPopupPreview();
|
||||||
cancelDismissPreview();
|
cancelDismissPreview();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
static class PointerQueue {
|
static class PointerQueue {
|
||||||
private LinkedList<PointerTracker> mQueue = new LinkedList<PointerTracker>();
|
private LinkedList<PointerTracker> mQueue = new LinkedList<PointerTracker>();
|
||||||
|
@ -391,6 +391,14 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
public void remove(PointerTracker tracker) {
|
public void remove(PointerTracker tracker) {
|
||||||
mQueue.remove(tracker);
|
mQueue.remove(tracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isInSlidingKeyInput() {
|
||||||
|
for (final PointerTracker tracker : mQueue) {
|
||||||
|
if (tracker.isInSlidingKeyInput())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LatinKeyboardBaseView(Context context, AttributeSet attrs) {
|
public LatinKeyboardBaseView(Context context, AttributeSet attrs) {
|
||||||
|
@ -1086,6 +1094,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCancel() {
|
public void onCancel() {
|
||||||
|
mKeyboardActionListener.onCancel();
|
||||||
dismissPopupKeyboard();
|
dismissPopupKeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1294,15 +1303,29 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
return pointers.get(id);
|
return pointers.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isInSlidingKeyInput() {
|
||||||
|
if (mMiniKeyboard != null) {
|
||||||
|
return mMiniKeyboard.isInSlidingKeyInput();
|
||||||
|
} else {
|
||||||
|
return mPointerQueue.isInSlidingKeyInput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPointerCount() {
|
||||||
|
return mOldPointerCount;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent me) {
|
public boolean onTouchEvent(MotionEvent me) {
|
||||||
final int pointerCount = me.getPointerCount();
|
|
||||||
final int action = me.getActionMasked();
|
final int action = me.getActionMasked();
|
||||||
|
final int pointerCount = me.getPointerCount();
|
||||||
|
final int oldPointerCount = mOldPointerCount;
|
||||||
|
mOldPointerCount = pointerCount;
|
||||||
|
|
||||||
// TODO: cleanup this code into a multi-touch to single-touch event converter class?
|
// TODO: cleanup this code into a multi-touch to single-touch event converter class?
|
||||||
// If the device does not have distinct multi-touch support panel, ignore all multi-touch
|
// If the device does not have distinct multi-touch support panel, ignore all multi-touch
|
||||||
// events except a transition from/to single-touch.
|
// events except a transition from/to single-touch.
|
||||||
if (!mHasDistinctMultitouch && pointerCount > 1 && mOldPointerCount > 1) {
|
if (!mHasDistinctMultitouch && pointerCount > 1 && oldPointerCount > 1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1358,7 +1381,6 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
if (!mHasDistinctMultitouch) {
|
if (!mHasDistinctMultitouch) {
|
||||||
// Use only main (id=0) pointer tracker.
|
// Use only main (id=0) pointer tracker.
|
||||||
PointerTracker tracker = getPointerTracker(0);
|
PointerTracker tracker = getPointerTracker(0);
|
||||||
int oldPointerCount = mOldPointerCount;
|
|
||||||
if (pointerCount == 1 && oldPointerCount == 2) {
|
if (pointerCount == 1 && oldPointerCount == 2) {
|
||||||
// Multi-touch to single touch transition.
|
// Multi-touch to single touch transition.
|
||||||
// Send a down event for the latest pointer.
|
// Send a down event for the latest pointer.
|
||||||
|
@ -1373,7 +1395,6 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
Log.w(TAG, "Unknown touch panel behavior: pointer count is " + pointerCount
|
Log.w(TAG, "Unknown touch panel behavior: pointer count is " + pointerCount
|
||||||
+ " (old " + oldPointerCount + ")");
|
+ " (old " + oldPointerCount + ")");
|
||||||
}
|
}
|
||||||
mOldPointerCount = pointerCount;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ public class PointerTracker {
|
||||||
private final UIHandler mHandler;
|
private final UIHandler mHandler;
|
||||||
private final KeyDetector mKeyDetector;
|
private final KeyDetector mKeyDetector;
|
||||||
private OnKeyboardActionListener mListener;
|
private OnKeyboardActionListener mListener;
|
||||||
|
private final KeyboardSwitcher mKeyboardSwitcher;
|
||||||
private final boolean mHasDistinctMultitouch;
|
private final boolean mHasDistinctMultitouch;
|
||||||
|
|
||||||
private Key[] mKeys;
|
private Key[] mKeys;
|
||||||
|
@ -58,12 +59,18 @@ public class PointerTracker {
|
||||||
|
|
||||||
private final KeyState mKeyState;
|
private final KeyState mKeyState;
|
||||||
|
|
||||||
|
// true if keyboard layout has been changed.
|
||||||
|
private boolean mKeyboardLayoutHasBeenChanged;
|
||||||
|
|
||||||
// true if event is already translated to a key action (long press or mini-keyboard)
|
// true if event is already translated to a key action (long press or mini-keyboard)
|
||||||
private boolean mKeyAlreadyProcessed;
|
private boolean mKeyAlreadyProcessed;
|
||||||
|
|
||||||
// true if this pointer is repeatable key
|
// true if this pointer is repeatable key
|
||||||
private boolean mIsRepeatableKey;
|
private boolean mIsRepeatableKey;
|
||||||
|
|
||||||
|
// true if this pointer is in sliding key input
|
||||||
|
private boolean mIsInSlidingKeyInput;
|
||||||
|
|
||||||
// For multi-tap
|
// For multi-tap
|
||||||
private int mLastSentIndex;
|
private int mLastSentIndex;
|
||||||
private int mTapCount;
|
private int mTapCount;
|
||||||
|
@ -157,10 +164,6 @@ public class PointerTracker {
|
||||||
public int onUpKey(int x, int y) {
|
public int onUpKey(int x, int y) {
|
||||||
return onMoveKeyInternal(x, y);
|
return onMoveKeyInternal(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSetKeyboard() {
|
|
||||||
mKeyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(mKeyX, mKeyY, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector, UIProxy proxy,
|
public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector, UIProxy proxy,
|
||||||
|
@ -171,6 +174,7 @@ public class PointerTracker {
|
||||||
mProxy = proxy;
|
mProxy = proxy;
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
mKeyDetector = keyDetector;
|
mKeyDetector = keyDetector;
|
||||||
|
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
|
||||||
mKeyState = new KeyState(keyDetector);
|
mKeyState = new KeyState(keyDetector);
|
||||||
mHasDistinctMultitouch = proxy.hasDistinctMultitouch();
|
mHasDistinctMultitouch = proxy.hasDistinctMultitouch();
|
||||||
mDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start);
|
mDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start);
|
||||||
|
@ -188,8 +192,12 @@ public class PointerTracker {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
mKeys = keys;
|
mKeys = keys;
|
||||||
mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance);
|
mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance);
|
||||||
// Update current key index because keyboard layout has been changed.
|
// Mark that keyboard layout has been changed.
|
||||||
mKeyState.onSetKeyboard();
|
mKeyboardLayoutHasBeenChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInSlidingKeyInput() {
|
||||||
|
return mIsInSlidingKeyInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidKeyIndex(int keyIndex) {
|
private boolean isValidKeyIndex(int keyIndex) {
|
||||||
|
@ -268,15 +276,21 @@ public class PointerTracker {
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
debugLog("onDownEvent:", x, y);
|
debugLog("onDownEvent:", x, y);
|
||||||
int keyIndex = mKeyState.onDownKey(x, y, eventTime);
|
int keyIndex = mKeyState.onDownKey(x, y, eventTime);
|
||||||
|
mKeyboardLayoutHasBeenChanged = false;
|
||||||
mKeyAlreadyProcessed = false;
|
mKeyAlreadyProcessed = false;
|
||||||
mIsRepeatableKey = false;
|
mIsRepeatableKey = false;
|
||||||
|
mIsInSlidingKeyInput = false;
|
||||||
checkMultiTap(eventTime, keyIndex);
|
checkMultiTap(eventTime, keyIndex);
|
||||||
if (mListener != null) {
|
if (mListener != null) {
|
||||||
if (isValidKeyIndex(keyIndex)) {
|
if (isValidKeyIndex(keyIndex)) {
|
||||||
mListener.onPress(mKeys[keyIndex].codes[0]);
|
mListener.onPress(mKeys[keyIndex].codes[0]);
|
||||||
// This onPress call may have changed keyboard layout and have updated mKeyIndex.
|
// This onPress call may have changed keyboard layout. Those cases are detected at
|
||||||
// If that's the case, mKeyIndex has been updated in setKeyboard().
|
// {@link #setKeyboard}. In those cases, we should update keyIndex according to the
|
||||||
keyIndex = mKeyState.getKeyIndex();
|
// new keyboard layout.
|
||||||
|
if (mKeyboardLayoutHasBeenChanged) {
|
||||||
|
mKeyboardLayoutHasBeenChanged = false;
|
||||||
|
keyIndex = mKeyState.onDownKey(x, y, eventTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isValidKeyIndex(keyIndex)) {
|
if (isValidKeyIndex(keyIndex)) {
|
||||||
|
@ -285,7 +299,7 @@ public class PointerTracker {
|
||||||
mHandler.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this);
|
mHandler.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this);
|
||||||
mIsRepeatableKey = true;
|
mIsRepeatableKey = true;
|
||||||
}
|
}
|
||||||
mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this);
|
startLongPressTimer(keyIndex);
|
||||||
}
|
}
|
||||||
showKeyPreviewAndUpdateKey(keyIndex);
|
showKeyPreviewAndUpdateKey(keyIndex);
|
||||||
}
|
}
|
||||||
|
@ -295,42 +309,70 @@ public class PointerTracker {
|
||||||
debugLog("onMoveEvent:", x, y);
|
debugLog("onMoveEvent:", x, y);
|
||||||
if (mKeyAlreadyProcessed)
|
if (mKeyAlreadyProcessed)
|
||||||
return;
|
return;
|
||||||
KeyState keyState = mKeyState;
|
final KeyState keyState = mKeyState;
|
||||||
final int keyIndex = keyState.onMoveKey(x, y);
|
int keyIndex = keyState.onMoveKey(x, y);
|
||||||
final Key oldKey = getKey(keyState.getKeyIndex());
|
final Key oldKey = getKey(keyState.getKeyIndex());
|
||||||
if (isValidKeyIndex(keyIndex)) {
|
if (isValidKeyIndex(keyIndex)) {
|
||||||
if (oldKey == null) {
|
if (oldKey == null) {
|
||||||
|
// The pointer has been slid in to the new key, but the finger was not on any keys.
|
||||||
|
// In this case, we must call onPress() to notify that the new key is being pressed.
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onPress(getKey(keyIndex).codes[0]);
|
||||||
|
// This onPress call may have changed keyboard layout. Those cases are detected
|
||||||
|
// at {@link #setKeyboard}. In those cases, we should update keyIndex according
|
||||||
|
// to the new keyboard layout.
|
||||||
|
if (mKeyboardLayoutHasBeenChanged) {
|
||||||
|
mKeyboardLayoutHasBeenChanged = false;
|
||||||
|
keyIndex = keyState.onMoveKey(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
keyState.onMoveToNewKey(keyIndex, x, y);
|
keyState.onMoveToNewKey(keyIndex, x, y);
|
||||||
mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this);
|
startLongPressTimer(keyIndex);
|
||||||
} else if (!isMinorMoveBounce(x, y, keyIndex)) {
|
} else if (!isMinorMoveBounce(x, y, keyIndex)) {
|
||||||
|
// The pointer has been slid in to the new key from the previous key, we must call
|
||||||
|
// onRelease() first to notify that the previous key has been released, then call
|
||||||
|
// onPress() to notify that the new key is being pressed.
|
||||||
|
mIsInSlidingKeyInput = true;
|
||||||
if (mListener != null)
|
if (mListener != null)
|
||||||
mListener.onRelease(oldKey.codes[0]);
|
mListener.onRelease(oldKey.codes[0]);
|
||||||
resetMultiTap();
|
resetMultiTap();
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onPress(getKey(keyIndex).codes[0]);
|
||||||
|
// This onPress call may have changed keyboard layout. Those cases are detected
|
||||||
|
// at {@link #setKeyboard}. In those cases, we should update keyIndex according
|
||||||
|
// to the new keyboard layout.
|
||||||
|
if (mKeyboardLayoutHasBeenChanged) {
|
||||||
|
mKeyboardLayoutHasBeenChanged = false;
|
||||||
|
keyIndex = keyState.onMoveKey(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
keyState.onMoveToNewKey(keyIndex, x, y);
|
keyState.onMoveToNewKey(keyIndex, x, y);
|
||||||
mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this);
|
startLongPressTimer(keyIndex);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (oldKey != null) {
|
if (oldKey != null && !isMinorMoveBounce(x, y, keyIndex)) {
|
||||||
|
// The pointer has been slid out from the previous key, we must call onRelease() to
|
||||||
|
// notify that the previous key has been released.
|
||||||
|
mIsInSlidingKeyInput = true;
|
||||||
if (mListener != null)
|
if (mListener != null)
|
||||||
mListener.onRelease(oldKey.codes[0]);
|
mListener.onRelease(oldKey.codes[0]);
|
||||||
keyState.onMoveToNewKey(keyIndex, x ,y);
|
|
||||||
mHandler.cancelLongPressTimer();
|
|
||||||
} else if (!isMinorMoveBounce(x, y, keyIndex)) {
|
|
||||||
resetMultiTap();
|
resetMultiTap();
|
||||||
keyState.onMoveToNewKey(keyIndex, x ,y);
|
keyState.onMoveToNewKey(keyIndex, x ,y);
|
||||||
mHandler.cancelLongPressTimer();
|
mHandler.cancelLongPressTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
showKeyPreviewAndUpdateKey(mKeyState.getKeyIndex());
|
showKeyPreviewAndUpdateKey(keyState.getKeyIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onUpEvent(int x, int y, long eventTime) {
|
public void onUpEvent(int x, int y, long eventTime) {
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
debugLog("onUpEvent :", x, y);
|
debugLog("onUpEvent :", x, y);
|
||||||
if (mKeyAlreadyProcessed)
|
|
||||||
return;
|
|
||||||
mHandler.cancelKeyTimers();
|
mHandler.cancelKeyTimers();
|
||||||
mHandler.cancelPopupPreview();
|
mHandler.cancelPopupPreview();
|
||||||
|
showKeyPreviewAndUpdateKey(NOT_A_KEY);
|
||||||
|
mIsInSlidingKeyInput = false;
|
||||||
|
if (mKeyAlreadyProcessed)
|
||||||
|
return;
|
||||||
int keyIndex = mKeyState.onUpKey(x, y);
|
int keyIndex = mKeyState.onUpKey(x, y);
|
||||||
if (isMinorMoveBounce(x, y, keyIndex)) {
|
if (isMinorMoveBounce(x, y, keyIndex)) {
|
||||||
// Use previous fixed key index and coordinates.
|
// Use previous fixed key index and coordinates.
|
||||||
|
@ -338,7 +380,6 @@ public class PointerTracker {
|
||||||
x = mKeyState.getKeyX();
|
x = mKeyState.getKeyX();
|
||||||
y = mKeyState.getKeyY();
|
y = mKeyState.getKeyY();
|
||||||
}
|
}
|
||||||
showKeyPreviewAndUpdateKey(NOT_A_KEY);
|
|
||||||
if (!mIsRepeatableKey) {
|
if (!mIsRepeatableKey) {
|
||||||
detectAndSendKey(keyIndex, x, y, eventTime);
|
detectAndSendKey(keyIndex, x, y, eventTime);
|
||||||
}
|
}
|
||||||
|
@ -353,6 +394,7 @@ public class PointerTracker {
|
||||||
mHandler.cancelKeyTimers();
|
mHandler.cancelKeyTimers();
|
||||||
mHandler.cancelPopupPreview();
|
mHandler.cancelPopupPreview();
|
||||||
showKeyPreviewAndUpdateKey(NOT_A_KEY);
|
showKeyPreviewAndUpdateKey(NOT_A_KEY);
|
||||||
|
mIsInSlidingKeyInput = false;
|
||||||
int keyIndex = mKeyState.getKeyIndex();
|
int keyIndex = mKeyState.getKeyIndex();
|
||||||
if (isValidKeyIndex(keyIndex))
|
if (isValidKeyIndex(keyIndex))
|
||||||
mProxy.invalidateKey(mKeys[keyIndex]);
|
mProxy.invalidateKey(mKeys[keyIndex]);
|
||||||
|
@ -425,6 +467,15 @@ public class PointerTracker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startLongPressTimer(int keyIndex) {
|
||||||
|
if (mKeyboardSwitcher.isInMomentaryAutoModeSwitchState()) {
|
||||||
|
// We use longer timeout for sliding finger input started from the symbols mode key.
|
||||||
|
mHandler.startLongPressTimer(mLongPressKeyTimeout * 3, keyIndex, this);
|
||||||
|
} else {
|
||||||
|
mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void detectAndSendKey(int index, int x, int y, long eventTime) {
|
private void detectAndSendKey(int index, int x, int y, long eventTime) {
|
||||||
final OnKeyboardActionListener listener = mListener;
|
final OnKeyboardActionListener listener = mListener;
|
||||||
final Key key = getKey(index);
|
final Key key = getKey(index);
|
||||||
|
@ -436,11 +487,10 @@ public class PointerTracker {
|
||||||
if (key.text != null) {
|
if (key.text != null) {
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.onText(key.text);
|
listener.onText(key.text);
|
||||||
listener.onRelease(NOT_A_KEY);
|
listener.onRelease(0); // dummy key code
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int code = key.codes[0];
|
int code = key.codes[0];
|
||||||
//TextEntryState.keyPressedAt(key, x, y);
|
|
||||||
int[] codes = mKeyDetector.newCodeArray();
|
int[] codes = mKeyDetector.newCodeArray();
|
||||||
mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes);
|
mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes);
|
||||||
// Multi-tap
|
// Multi-tap
|
||||||
|
|
Loading…
Reference in a new issue