Add KeyboardState to host shift and symbol key states

The KeyboardState will conatin all logic of keyboard state when series
of refactoring are achieved.  And the KeyboardState should not be
entangled with other objcets such as Keyboard and KeyboardSwitcher in
order to keep it easily testable.

Bug: 5708602
Change-Id: I288bc169c47e1b4de27fe78854baadbcc85c5d23
main
Tadashi G. Takaoka 2011-12-05 15:02:06 +09:00
parent c410e243e9
commit b88c9acd88
2 changed files with 180 additions and 60 deletions

View File

@ -30,8 +30,7 @@ import android.view.View;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
import com.android.inputmethod.keyboard.internal.ModifierKeyState; import com.android.inputmethod.keyboard.internal.KeyboardState;
import com.android.inputmethod.keyboard.internal.ShiftKeyState;
import com.android.inputmethod.latin.InputView; import com.android.inputmethod.latin.InputView;
import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.LatinImeLogger;
@ -69,9 +68,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private String mPackageName; private String mPackageName;
private Resources mResources; private Resources mResources;
// TODO: Combine these key state objects with auto mode switch state. private KeyboardState mState;
private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift");
private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol");
private KeyboardId mMainKeyboardId; private KeyboardId mMainKeyboardId;
private KeyboardId mSymbolsKeyboardId; private KeyboardId mSymbolsKeyboardId;
@ -88,7 +85,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private boolean mIsAutoCorrectionActive; private boolean mIsAutoCorrectionActive;
// TODO: Encapsulate these state handling to separate class and combine with ShiftKeyState // TODO: Encapsulate these state handling to separate class and combine with ShiftKeyState
// and ModifierKeyState. // and ModifierKeyState into KeyboardState.
private static final int SWITCH_STATE_ALPHA = 0; private static final int SWITCH_STATE_ALPHA = 0;
private static final int SWITCH_STATE_SYMBOL_BEGIN = 1; private static final int SWITCH_STATE_SYMBOL_BEGIN = 1;
private static final int SWITCH_STATE_SYMBOL = 2; private static final int SWITCH_STATE_SYMBOL = 2;
@ -173,6 +170,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
mResources = ims.getResources(); mResources = ims.getResources();
mPrefs = prefs; mPrefs = prefs;
mSubtypeSwitcher = SubtypeSwitcher.getInstance(); mSubtypeSwitcher = SubtypeSwitcher.getInstance();
mState = new KeyboardState();
setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs)); setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs));
prefs.registerOnSharedPreferenceChangeListener(this); prefs.registerOnSharedPreferenceChangeListener(this);
} }
@ -442,10 +440,11 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
*/ */
public void toggleShift() { public void toggleShift() {
mInputMethodService.mHandler.cancelUpdateShiftState(); mInputMethodService.mHandler.cancelUpdateShiftState();
if (DEBUG_STATE) if (DEBUG_STATE) {
Log.d(TAG, "toggleShift:" Log.d(TAG, "toggleShift:"
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " shiftKeyState=" + mShiftKeyState); + " state=" + mState);
}
if (isAlphabetMode()) { if (isAlphabetMode()) {
setManualTemporaryUpperCase(!isShiftedOrShiftLocked()); setManualTemporaryUpperCase(!isShiftedOrShiftLocked());
} else { } else {
@ -455,16 +454,17 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
public void toggleCapsLock() { public void toggleCapsLock() {
mInputMethodService.mHandler.cancelUpdateShiftState(); mInputMethodService.mHandler.cancelUpdateShiftState();
if (DEBUG_STATE) if (DEBUG_STATE) {
Log.d(TAG, "toggleCapsLock:" Log.d(TAG, "toggleCapsLock:"
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " shiftKeyState=" + mShiftKeyState); + " state=" + mState);
}
if (isAlphabetMode()) { if (isAlphabetMode()) {
if (isShiftLocked()) { if (isShiftLocked()) {
// Shift key is long pressed while caps lock state, we will toggle back to normal // Shift key is long pressed while caps lock state, we will toggle back to normal
// state. And mark as if shift key is released. // state. And mark as if shift key is released.
setShiftLocked(false); setShiftLocked(false);
mShiftKeyState.onRelease(); mState.onToggleCapsLock();
} else { } else {
setShiftLocked(true); setShiftLocked(true);
} }
@ -483,35 +483,35 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
* Update keyboard shift state triggered by connected EditText status change. * Update keyboard shift state triggered by connected EditText status change.
*/ */
public void updateShiftState() { public void updateShiftState() {
final ShiftKeyState shiftKeyState = mShiftKeyState; final boolean isAlphabetMode = isAlphabetMode();
if (DEBUG_STATE) final boolean isShiftLocked = isShiftLocked();
if (DEBUG_STATE) {
Log.d(TAG, "updateShiftState:" Log.d(TAG, "updateShiftState:"
+ " autoCaps=" + mInputMethodService.getCurrentAutoCapsState() + " autoCaps=" + mInputMethodService.getCurrentAutoCapsState()
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " shiftKeyState=" + shiftKeyState + " isAlphabetMode=" + isAlphabetMode
+ " isAlphabetMode=" + isAlphabetMode() + " isShiftLocked=" + isShiftLocked
+ " isShiftLocked=" + isShiftLocked()); + " state=" + mState);
if (isAlphabetMode()) { }
if (!isShiftLocked() && !shiftKeyState.isIgnoring()) { if (isAlphabetMode) {
if (shiftKeyState.isReleasing() && mInputMethodService.getCurrentAutoCapsState()) { if (!isShiftLocked && !mState.isShiftKeyIgnoring()) {
if (mState.isShiftKeyReleasing() && mInputMethodService.getCurrentAutoCapsState()) {
// Only when shift key is releasing, automatic temporary upper case will be set. // Only when shift key is releasing, automatic temporary upper case will be set.
setAutomaticTemporaryUpperCase(); setAutomaticTemporaryUpperCase();
} else { } else {
setManualTemporaryUpperCase(shiftKeyState.isMomentary()); setManualTemporaryUpperCase(mState.isShiftKeyMomentary());
} }
} }
} else {
// In symbol keyboard mode, we should clear shift key state because only alphabet
// keyboard has shift key.
shiftKeyState.onRelease();
} }
mState.onUpdateShiftState(isAlphabetMode);
} }
public void changeKeyboardMode() { public void changeKeyboardMode() {
if (DEBUG_STATE) if (DEBUG_STATE) {
Log.d(TAG, "changeKeyboardMode:" Log.d(TAG, "changeKeyboardMode:"
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " shiftKeyState=" + mShiftKeyState); + " state=" + mState);
}
toggleKeyboardMode(); toggleKeyboardMode();
if (isShiftLocked() && isAlphabetMode()) if (isShiftLocked() && isAlphabetMode())
setShiftLocked(true); setShiftLocked(true);
@ -521,66 +521,72 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
public void onPressShift(boolean withSliding) { public void onPressShift(boolean withSliding) {
if (!isKeyboardAvailable()) if (!isKeyboardAvailable())
return; return;
ShiftKeyState shiftKeyState = mShiftKeyState; if (DEBUG_STATE) {
if (DEBUG_STATE)
Log.d(TAG, "onPressShift:" Log.d(TAG, "onPressShift:"
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding); + " state=" + mState + " sliding=" + withSliding);
if (isAlphabetMode()) { }
if (isShiftLocked()) { final boolean isAlphabetMode = isAlphabetMode();
final boolean isShiftLocked = isShiftLocked();
final boolean isAutomaticTemporaryUpperCase = isAutomaticTemporaryUpperCase();
final boolean isShiftedOrShiftLocked = isShiftedOrShiftLocked();
if (isAlphabetMode) {
if (isShiftLocked) {
// Shift key is pressed while caps lock state, we will treat this state as shifted // Shift key is pressed while caps lock state, we will treat this state as shifted
// caps lock state and mark as if shift key pressed while normal state. // caps lock state and mark as if shift key pressed while normal state.
shiftKeyState.onPress();
setManualTemporaryUpperCase(true); setManualTemporaryUpperCase(true);
} else if (isAutomaticTemporaryUpperCase()) { } else if (isAutomaticTemporaryUpperCase) {
// Shift key is pressed while automatic temporary upper case, we have to move to // Shift key is pressed while automatic temporary upper case, we have to move to
// manual temporary upper case. // manual temporary upper case.
shiftKeyState.onPress();
setManualTemporaryUpperCase(true); setManualTemporaryUpperCase(true);
} else if (isShiftedOrShiftLocked()) { } else if (isShiftedOrShiftLocked) {
// In manual upper case state, we just record shift key has been pressing while // In manual upper case state, we just record shift key has been pressing while
// shifted state. // shifted state.
shiftKeyState.onPressOnShifted();
} else { } else {
// In base layout, chording or manual temporary upper case mode is started. // In base layout, chording or manual temporary upper case mode is started.
shiftKeyState.onPress();
toggleShift(); toggleShift();
} }
} else { } else {
// In symbol mode, just toggle symbol and symbol more keyboard. // In symbol mode, just toggle symbol and symbol more keyboard.
shiftKeyState.onPress();
toggleShift(); toggleShift();
mSwitchState = SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE; mSwitchState = SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE;
} }
mState.onPressShift(isAlphabetMode, isShiftLocked, isAutomaticTemporaryUpperCase,
isShiftedOrShiftLocked);
} }
public void onReleaseShift(boolean withSliding) { public void onReleaseShift(boolean withSliding) {
if (!isKeyboardAvailable()) if (!isKeyboardAvailable())
return; return;
ShiftKeyState shiftKeyState = mShiftKeyState; if (DEBUG_STATE) {
if (DEBUG_STATE)
Log.d(TAG, "onReleaseShift:" Log.d(TAG, "onReleaseShift:"
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding); + " state=" + mState + " sliding=" + withSliding);
if (isAlphabetMode()) { }
if (shiftKeyState.isMomentary()) { final boolean isAlphabetMode = isAlphabetMode();
final boolean isShiftLocked = isShiftLocked();
final boolean isShiftLockShifted = isShiftLockShifted();
final boolean isShiftedOrShiftLocked = isShiftedOrShiftLocked();
final boolean isManualTemporaryUpperCaseFromAuto = isManualTemporaryUpperCaseFromAuto();
if (isAlphabetMode) {
if (mState.isShiftKeyMomentary()) {
// After chording input while normal state. // After chording input while normal state.
toggleShift(); toggleShift();
} else if (isShiftLocked() && !isShiftLockShifted() && (shiftKeyState.isPressing() } else if (isShiftLocked && !isShiftLockShifted && (mState.isShiftKeyPressing()
|| shiftKeyState.isPressingOnShifted()) && !withSliding) { || mState.isShiftKeyPressingOnShifted()) && !withSliding) {
// Shift has been long pressed, ignore this release. // Shift has been long pressed, ignore this release.
} else if (isShiftLocked() && !shiftKeyState.isIgnoring() && !withSliding) { } else if (isShiftLocked && !mState.isShiftKeyIgnoring() && !withSliding) {
// Shift has been pressed without chording while caps lock state. // Shift has been pressed without chording while caps lock state.
toggleCapsLock(); toggleCapsLock();
// To be able to turn off caps lock by "double tap" on shift key, we should ignore // To be able to turn off caps lock by "double tap" on shift key, we should ignore
// the second tap of the "double tap" from now for a while because we just have // the second tap of the "double tap" from now for a while because we just have
// already turned off caps lock above. // already turned off caps lock above.
mKeyboardView.startIgnoringDoubleTap(); mKeyboardView.startIgnoringDoubleTap();
} else if (isShiftedOrShiftLocked() && shiftKeyState.isPressingOnShifted() } else if (isShiftedOrShiftLocked && mState.isShiftKeyPressingOnShifted()
&& !withSliding) { && !withSliding) {
// Shift has been pressed without chording while shifted state. // Shift has been pressed without chording while shifted state.
toggleShift(); toggleShift();
} else if (isManualTemporaryUpperCaseFromAuto() && shiftKeyState.isPressing() } else if (isManualTemporaryUpperCaseFromAuto && mState.isShiftKeyPressing()
&& !withSliding) { && !withSliding) {
// Shift has been pressed without chording while manual temporary upper case // Shift has been pressed without chording while manual temporary upper case
// transited from automatic temporary upper case. // transited from automatic temporary upper case.
@ -593,40 +599,41 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
toggleShift(); toggleShift();
} }
} }
shiftKeyState.onRelease(); mState.onReleaseShift();
} }
public void onPressSymbol() { public void onPressSymbol() {
if (DEBUG_STATE) if (DEBUG_STATE) {
Log.d(TAG, "onPressSymbol:" Log.d(TAG, "onPressSymbol:"
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " symbolKeyState=" + mSymbolKeyState); + " state=" + mState);
}
changeKeyboardMode(); changeKeyboardMode();
mSymbolKeyState.onPress(); mState.onPressSymbol();
mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL; mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL;
} }
public void onReleaseSymbol() { public void onReleaseSymbol() {
if (DEBUG_STATE) if (DEBUG_STATE) {
Log.d(TAG, "onReleaseSymbol:" Log.d(TAG, "onReleaseSymbol:"
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " symbolKeyState=" + mSymbolKeyState); + " state=" + mState);
}
// Snap back to the previous keyboard mode if the user chords the mode change key and // Snap back to the previous keyboard mode if the user chords the mode change key and
// another key, then releases the mode change key. // another key, then releases the mode change key.
if (mSwitchState == SWITCH_STATE_CHORDING_ALPHA) { if (mSwitchState == SWITCH_STATE_CHORDING_ALPHA) {
changeKeyboardMode(); changeKeyboardMode();
} }
mSymbolKeyState.onRelease(); mState.onReleaseSymbol();
} }
public void onOtherKeyPressed() { public void onOtherKeyPressed() {
if (DEBUG_STATE) if (DEBUG_STATE) {
Log.d(TAG, "onOtherKeyPressed:" Log.d(TAG, "onOtherKeyPressed:"
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " shiftKeyState=" + mShiftKeyState + " state=" + mState);
+ " symbolKeyState=" + mSymbolKeyState); }
mShiftKeyState.onOtherKeyPressed(); mState.onOtherKeyPressed();
mSymbolKeyState.onOtherKeyPressed();
} }
public void onCancelInput() { public void onCancelInput() {

View File

@ -0,0 +1,113 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.keyboard.internal;
// TODO: Add unit tests
public class KeyboardState {
// TODO: Combine these key state objects with auto mode switch state.
private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift");
private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol");
public KeyboardState() {
}
// TODO: Get rid of this method
public boolean isShiftKeyIgnoring() {
return mShiftKeyState.isIgnoring();
}
// TODO: Get rid of this method
public boolean isShiftKeyReleasing() {
return mShiftKeyState.isReleasing();
}
// TODO: Get rid of this method
public boolean isShiftKeyMomentary() {
return mShiftKeyState.isMomentary();
}
// TODO: Get rid of this method
public boolean isShiftKeyPressing() {
return mShiftKeyState.isPressing();
}
// TODO: Get rid of this method
public boolean isShiftKeyPressingOnShifted() {
return mShiftKeyState.isPressingOnShifted();
}
public void onToggleCapsLock() {
mShiftKeyState.onRelease();
}
public void onPressSymbol() {
mSymbolKeyState.onPress();
}
public void onReleaseSymbol() {
mSymbolKeyState.onRelease();
}
public void onOtherKeyPressed() {
mShiftKeyState.onOtherKeyPressed();
mSymbolKeyState.onOtherKeyPressed();
}
public void onUpdateShiftState(boolean isAlphabetMode) {
if (!isAlphabetMode) {
// In symbol keyboard mode, we should clear shift key state because only alphabet
// keyboard has shift key.
mSymbolKeyState.onRelease();
}
}
// TODO: Get rid of these boolean arguments.
public void onPressShift(boolean isAlphabetMode, boolean isShiftLocked,
boolean isAutomaticTemporaryUpperCase, boolean isShiftedOrShiftLocked) {
if (isAlphabetMode) {
if (isShiftLocked) {
// Shift key is pressed while caps lock state, we will treat this state as shifted
// caps lock state and mark as if shift key pressed while normal state.
mShiftKeyState.onPress();
} else if (isAutomaticTemporaryUpperCase) {
// Shift key is pressed while automatic temporary upper case, we have to move to
// manual temporary upper case.
mShiftKeyState.onPress();
} else if (isShiftedOrShiftLocked) {
// In manual upper case state, we just record shift key has been pressing while
// shifted state.
mShiftKeyState.onPressOnShifted();
} else {
// In base layout, chording or manual temporary upper case mode is started.
mShiftKeyState.onPress();
}
} else {
// In symbol mode, just toggle symbol and symbol more keyboard.
mShiftKeyState.onPress();
}
}
public void onReleaseShift() {
mShiftKeyState.onRelease();
}
@Override
public String toString() {
return "shiftKeyState=" + mShiftKeyState
+ " symbolKeyState=" + mSymbolKeyState;
}
}