Implement both automatic and manual temporary upper cases

With this change,
- Shift and Shift lock state of keyboard is maintained by
  LatinKeyboard.ShiftState.
- Shift key state is maintained by ShiftKeyState object in
  KeyboardSwitcher.
- LatinIME informs KeyboardSwitcher that shift key press, release and
  long press and KeyboardSwitcher determines which state LatinKeyboard
  and ShiftLeyState should be.

Bug: 3193390
Change-Id: I948ef26fda512eb1cb0ebddc89d322c4f4f4d670
This commit is contained in:
Tadashi G. Takaoka 2010-11-13 00:16:34 -08:00
parent 1d2d3228a3
commit f27364600c
11 changed files with 312 additions and 102 deletions

View file

@ -626,7 +626,7 @@ public class BaseKeyboard {
return false; return false;
} }
public boolean isShifted() { public boolean isShiftedOrShiftLocked() {
return mShifted; return mShifted;
} }

View file

@ -683,7 +683,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
} }
protected CharSequence adjustCase(CharSequence label) { protected CharSequence adjustCase(CharSequence label) {
if (mKeyboard.isShifted() && label != null && label.length() < 3 if (mKeyboard.isShiftedOrShiftLocked() && label != null && label.length() < 3
&& Character.isLowerCase(label.charAt(0))) { && Character.isLowerCase(label.charAt(0))) {
label = label.toString().toUpperCase(); label = label.toString().toUpperCase();
} }
@ -772,8 +772,8 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
final int kbdPaddingTop = getPaddingTop(); final int kbdPaddingTop = getPaddingTop();
final Key[] keys = mKeys; final Key[] keys = mKeys;
final Key invalidKey = mInvalidatedKey; final Key invalidKey = mInvalidatedKey;
final boolean isTemporaryUpperCase = (mKeyboard instanceof LatinKeyboard final boolean isManualTemporaryUpperCase = (mKeyboard instanceof LatinKeyboard
&& ((LatinKeyboard)mKeyboard).isTemporaryUpperCase()); && ((LatinKeyboard)mKeyboard).isManualTemporaryUpperCase());
paint.setColor(mKeyTextColor); paint.setColor(mKeyTextColor);
boolean drawSingleKey = false; boolean drawSingleKey = false;
@ -853,7 +853,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
int drawableHeight = key.height; int drawableHeight = key.height;
int drawableX = 0; int drawableX = 0;
int drawableY = HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL; int drawableY = HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL;
Drawable icon = (isTemporaryUpperCase Drawable icon = (isManualTemporaryUpperCase
&& key.manualTemporaryUpperCaseHintIcon != null) && key.manualTemporaryUpperCaseHintIcon != null)
? key.manualTemporaryUpperCaseHintIcon : key.hintIcon; ? key.manualTemporaryUpperCaseHintIcon : key.hintIcon;
drawIcon(canvas, icon, drawableX, drawableY, drawableWidth, drawableHeight); drawIcon(canvas, icon, drawableX, drawableY, drawableWidth, drawableHeight);
@ -1226,7 +1226,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
// TODO: change the below line to use getLatinKeyboard() instead of getKeyboard() // TODO: change the below line to use getLatinKeyboard() instead of getKeyboard()
BaseKeyboard baseMiniKeyboard = mMiniKeyboard.getKeyboard(); BaseKeyboard baseMiniKeyboard = mMiniKeyboard.getKeyboard();
if (baseMiniKeyboard != null && baseMiniKeyboard.setShifted(mKeyboard == null if (baseMiniKeyboard != null && baseMiniKeyboard.setShifted(mKeyboard == null
? false : mKeyboard.isShifted())) { ? false : mKeyboard.isShiftedOrShiftLocked())) {
mMiniKeyboard.invalidateAllKeys(); mMiniKeyboard.invalidateAllKeys();
} }
// Mini keyboard needs no pop-up key preview displayed. // Mini keyboard needs no pop-up key preview displayed.

View file

@ -18,7 +18,6 @@ package com.android.inputmethod.latin;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
@ -32,6 +31,7 @@ import java.util.Locale;
public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener { public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "KeyboardSwitcher"; private static final String TAG = "KeyboardSwitcher";
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
public static final boolean DEBUG_STATE = false;
public static final int MODE_TEXT = 0; public static final int MODE_TEXT = 0;
public static final int MODE_URL = 1; public static final int MODE_URL = 1;
@ -76,8 +76,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private LatinKeyboardView mInputView; private LatinKeyboardView mInputView;
private LatinIME mInputMethodService; private LatinIME mInputMethodService;
private ShiftKeyState mShiftState = new ShiftKeyState(); private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift");
private ModifierKeyState mSymbolKeyState = new ModifierKeyState(); private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol");
private KeyboardId mSymbolsId; private KeyboardId mSymbolsId;
private KeyboardId mSymbolsShiftedId; private KeyboardId mSymbolsShiftedId;
@ -374,10 +374,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
latinKeyboard.keyReleased(); latinKeyboard.keyReleased();
} }
public boolean isShifted() { public boolean isShiftedOrShiftLocked() {
LatinKeyboard latinKeyboard = getLatinKeyboard(); LatinKeyboard latinKeyboard = getLatinKeyboard();
if (latinKeyboard != null) if (latinKeyboard != null)
return latinKeyboard.isShifted(); return latinKeyboard.isShiftedOrShiftLocked();
return false; return false;
} }
@ -388,7 +388,21 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
return false; return false;
} }
private void setShifted(boolean shifted) { public boolean isAutomaticTemporaryUpperCase() {
LatinKeyboard latinKeyboard = getLatinKeyboard();
if (latinKeyboard != null)
return latinKeyboard.isAutomaticTemporaryUpperCase();
return false;
}
public boolean isManualTemporaryUpperCase() {
LatinKeyboard latinKeyboard = getLatinKeyboard();
if (latinKeyboard != null)
return latinKeyboard.isManualTemporaryUpperCase();
return false;
}
private void setManualTemporaryUpperCase(boolean shifted) {
LatinKeyboard latinKeyboard = getLatinKeyboard(); LatinKeyboard latinKeyboard = getLatinKeyboard();
if (latinKeyboard != null && latinKeyboard.setShifted(shifted)) { if (latinKeyboard != null && latinKeyboard.setShifted(shifted)) {
mInputView.invalidateAllKeys(); mInputView.invalidateAllKeys();
@ -403,21 +417,13 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
} }
public void toggleShift() { public void toggleShift() {
handleShiftInternal(false);
}
private void resetShift() {
handleShiftInternal(true);
}
private void handleShiftInternal(boolean forceNormal) {
mInputMethodService.mHandler.cancelUpdateShiftState(); mInputMethodService.mHandler.cancelUpdateShiftState();
if (DEBUG_STATE)
Log.d(TAG, "toggleShift:"
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " shiftKeyState=" + mShiftKeyState);
if (isAlphabetMode()) { if (isAlphabetMode()) {
if (forceNormal) { setManualTemporaryUpperCase(!isShiftedOrShiftLocked());
setShifted(false);
} else {
setShifted(!isShifted());
}
} else { } else {
toggleShiftInSymbol(); toggleShiftInSymbol();
} }
@ -425,27 +431,50 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
public void toggleCapsLock() { public void toggleCapsLock() {
mInputMethodService.mHandler.cancelUpdateShiftState(); mInputMethodService.mHandler.cancelUpdateShiftState();
if (DEBUG_STATE)
Log.d(TAG, "toggleCapsLock:"
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " shiftKeyState=" + mShiftKeyState);
if (isAlphabetMode()) { if (isAlphabetMode()) {
if (isShiftLocked()) { if (isShiftLocked()) {
// setShifted(false) also disable shift locked state. // Shift key is long pressed while caps lock state, we will toggle back to normal
// Note: Caps lock LED is off when Key.on is false. // state. And mark as if shift key is released.
setShifted(false); setShiftLocked(false);
mShiftKeyState.onRelease();
} else { } else {
// setShiftLocked(true) enable shift state too.
// Note: Caps lock LED is on when Key.on is true.
setShiftLocked(true); setShiftLocked(true);
} }
} }
} }
private void setAutomaticTemporaryUpperCase() {
LatinKeyboard latinKeyboard = getLatinKeyboard();
if (latinKeyboard != null) {
latinKeyboard.setAutomaticTemporaryUpperCase();
mInputView.invalidateAllKeys();
}
}
public void updateShiftState() { public void updateShiftState() {
if (isAlphabetMode() && !mShiftState.isIgnoring()) { if (DEBUG_STATE)
final boolean autoCapsMode = mInputMethodService.getCurrentAutoCapsState(); Log.d(TAG, "updateShiftState:"
setShifted(mShiftState.isMomentary() || isShiftLocked() || autoCapsMode); + " autoCaps=" + mInputMethodService.getCurrentAutoCapsState()
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " shiftKeyState=" + mShiftKeyState);
if (isAlphabetMode() && !isShiftLocked() && !mShiftKeyState.isIgnoring()) {
if (mInputMethodService.getCurrentAutoCapsState()) {
setAutomaticTemporaryUpperCase();
} else {
setManualTemporaryUpperCase(mShiftKeyState.isMomentary());
}
} }
} }
public void changeKeyboardMode() { public void changeKeyboardMode() {
if (DEBUG_STATE)
Log.d(TAG, "changeKeyboardMode:"
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " shiftKeyState=" + mShiftKeyState);
toggleKeyboardMode(); toggleKeyboardMode();
if (isShiftLocked() && isAlphabetMode()) if (isShiftLocked() && isAlphabetMode())
setShiftLocked(true); setShiftLocked(true);
@ -455,47 +484,82 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
public void onPressShift() { public void onPressShift() {
if (!isKeyboardAvailable()) if (!isKeyboardAvailable())
return; return;
if (isAlphabetMode() && isShifted()) { ShiftKeyState shiftKeyState = mShiftKeyState;
// In alphabet mode, we don't call toggleShift() when we are already in the shifted if (DEBUG_STATE)
// state. Log.d(TAG, "onPressShift:"
mShiftState.onPressOnShifted(); + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " shiftKeyState=" + shiftKeyState);
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.
setManualTemporaryUpperCase(true);
shiftKeyState.onPress();
} else if (isAutomaticTemporaryUpperCase()) {
// Shift key is pressed while automatic temporary upper case, we have to move to
// manual temporary upper case.
setManualTemporaryUpperCase(true);
shiftKeyState.onPressOnShifted();
} else if (isShiftedOrShiftLocked()) {
// In manual upper case state, we just record shift key has been pressing while
// shifted state.
shiftKeyState.onPressOnShifted();
} else { } else {
// In alphabet mode, we call toggleShift() to go into the shifted mode only when we are // In base layout, chording or manual temporary upper case mode is started.
// not in the shifted state.
// This else clause also handles shift key pressing in symbol mode.
mShiftState.onPress();
toggleShift(); toggleShift();
shiftKeyState.onPress();
}
} else {
// In symbol mode, just toggle symbol and symbol more keyboard.
toggleShift();
shiftKeyState.onPress();
} }
} }
public void onReleaseShift() { public void onReleaseShift() {
if (!isKeyboardAvailable()) if (!isKeyboardAvailable())
return; return;
ShiftKeyState shiftKeyState = mShiftKeyState;
if (DEBUG_STATE)
Log.d(TAG, "onReleaseShift:"
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " shiftKeyState=" + shiftKeyState);
if (isAlphabetMode()) { if (isAlphabetMode()) {
if (mShiftState.isMomentary()) { if (shiftKeyState.isMomentary()) {
resetShift(); // After chording input while normal state.
} else if (isShifted() && mShiftState.isPressingOnShifted()) { toggleShift();
// In alphabet mode, we call toggleShift() to go into the non shifted state only } else if (isShiftLocked() && !shiftKeyState.isIgnoring()) {
// when we are in the shifted state -- temporary shifted mode or caps lock mode. // Shift has been pressed without chording while caps lock state.
toggleCapsLock();
} else if (isShiftedOrShiftLocked() && shiftKeyState.isPressingOnShifted()) {
// Shift has been pressed without chording while shifted state.
toggleShift(); toggleShift();
} }
} }
mShiftState.onRelease(); shiftKeyState.onRelease();
} }
public void onPressSymbol() { public void onPressSymbol() {
if (DEBUG_STATE)
Log.d(TAG, "onReleaseShift:"
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " symbolKeyState=" + mSymbolKeyState);
changeKeyboardMode(); changeKeyboardMode();
mSymbolKeyState.onPress(); mSymbolKeyState.onPress();
} }
public void onReleaseSymbol() { public void onReleaseSymbol() {
if (DEBUG_STATE)
Log.d(TAG, "onReleaseShift:"
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
+ " symbolKeyState=" + mSymbolKeyState);
if (mSymbolKeyState.isMomentary()) if (mSymbolKeyState.isMomentary())
changeKeyboardMode(); changeKeyboardMode();
mSymbolKeyState.onRelease(); mSymbolKeyState.onRelease();
} }
public void onOtherKeyPressed() { public void onOtherKeyPressed() {
mShiftState.onOtherKeyPressed(); mShiftKeyState.onOtherKeyPressed();
mSymbolKeyState.onOtherKeyPressed(); mSymbolKeyState.onOtherKeyPressed();
} }
@ -521,7 +585,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
mInputView.setKeyboard(keyboard); mInputView.setKeyboard(keyboard);
} }
public void toggleKeyboardMode() { private void toggleKeyboardMode() {
loadKeyboardInternal(mMode, mImeOptions, mVoiceButtonEnabled, mVoiceButtonOnPrimary, loadKeyboardInternal(mMode, mImeOptions, mVoiceButtonEnabled, mVoiceButtonOnPrimary,
!mIsSymbols); !mIsSymbols);
if (mIsSymbols) { if (mIsSymbols) {

View file

@ -1004,7 +1004,8 @@ public class LatinIME extends InputMethodService
return true; return true;
} }
// Enable shift key and DPAD to do selections // Enable shift key and DPAD to do selections
if (mKeyboardSwitcher.isInputViewShown() && mKeyboardSwitcher.isShifted()) { if (mKeyboardSwitcher.isInputViewShown()
&& mKeyboardSwitcher.isShiftedOrShiftLocked()) {
event = new KeyEvent(event.getDownTime(), event.getEventTime(), event = new KeyEvent(event.getDownTime(), event.getEventTime(),
event.getAction(), event.getKeyCode(), event.getRepeatCount(), event.getAction(), event.getKeyCode(), event.getRepeatCount(),
event.getDeviceId(), event.getScanCode(), event.getDeviceId(), event.getScanCode(),
@ -1373,7 +1374,7 @@ public class LatinIME extends InputMethodService
} }
} }
KeyboardSwitcher switcher = mKeyboardSwitcher; KeyboardSwitcher switcher = mKeyboardSwitcher;
if (switcher.isShifted()) { if (switcher.isShiftedOrShiftLocked()) {
if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT
|| keyCodes[0] > Character.MAX_CODE_POINT) { || keyCodes[0] > Character.MAX_CODE_POINT) {
return; return;
@ -1392,7 +1393,8 @@ public class LatinIME extends InputMethodService
} }
} }
if (mPredicting) { if (mPredicting) {
if (mComposing.length() == 0 && switcher.isAlphabetMode() && switcher.isShifted()) { if (mComposing.length() == 0 && switcher.isAlphabetMode()
&& switcher.isShiftedOrShiftLocked()) {
mWord.setFirstCharCapitalized(true); mWord.setFirstCharCapitalized(true);
} }
mComposing.append((char) primaryCode); mComposing.append((char) primaryCode);
@ -1677,7 +1679,7 @@ public class LatinIME extends InputMethodService
final List<CharSequence> nBest = new ArrayList<CharSequence>(); final List<CharSequence> nBest = new ArrayList<CharSequence>();
KeyboardSwitcher switcher = mKeyboardSwitcher; KeyboardSwitcher switcher = mKeyboardSwitcher;
boolean capitalizeFirstWord = preferCapitalization() boolean capitalizeFirstWord = preferCapitalization()
|| (switcher.isAlphabetMode() && switcher.isShifted()); || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked());
for (String c : mVoiceResults.candidates) { for (String c : mVoiceResults.candidates) {
if (capitalizeFirstWord) { if (capitalizeFirstWord) {
c = Character.toUpperCase(c.charAt(0)) + c.substring(1, c.length()); c = Character.toUpperCase(c.charAt(0)) + c.substring(1, c.length());

View file

@ -46,9 +46,9 @@ public class LatinKeyboard extends BaseKeyboard {
private static final int OPACITY_FULLY_OPAQUE = 255; private static final int OPACITY_FULLY_OPAQUE = 255;
private static final int SPACE_LED_LENGTH_PERCENT = 80; private static final int SPACE_LED_LENGTH_PERCENT = 80;
private Drawable mShiftLockIcon; private Drawable mShiftedIcon;
private Drawable mShiftLockPreviewIcon; private Drawable mShiftLockPreviewIcon;
private final HashMap<Key, Drawable> mOldShiftIcons = new HashMap<Key, Drawable>(); private final HashMap<Key, Drawable> mNormalShiftIcons = new HashMap<Key, Drawable>();
private Drawable mSpaceIcon; private Drawable mSpaceIcon;
private Drawable mSpaceAutoCompletionIndicator; private Drawable mSpaceAutoCompletionIndicator;
private Drawable mSpacePreviewIcon; private Drawable mSpacePreviewIcon;
@ -92,11 +92,7 @@ public class LatinKeyboard extends BaseKeyboard {
// TODO: generalize for any keyboardId // TODO: generalize for any keyboardId
private boolean mIsBlackSym; private boolean mIsBlackSym;
private static final int SHIFT_OFF = 0; private LatinKeyboardShiftState mShiftState = new LatinKeyboardShiftState();
private static final int SHIFT_ON = 1;
private static final int SHIFT_LOCKED = 2;
private int mShiftState = SHIFT_OFF;
private static final float SPACEBAR_DRAG_THRESHOLD = 0.8f; private static final float SPACEBAR_DRAG_THRESHOLD = 0.8f;
private static final float OVERLAP_PERCENTAGE_LOW_PROB = 0.70f; private static final float OVERLAP_PERCENTAGE_LOW_PROB = 0.70f;
@ -117,7 +113,7 @@ public class LatinKeyboard extends BaseKeyboard {
mContext = context; mContext = context;
mRes = res; mRes = res;
mMode = id.mMode; mMode = id.mMode;
mShiftLockIcon = res.getDrawable(R.drawable.sym_keyboard_shift_locked); mShiftedIcon = res.getDrawable(R.drawable.sym_keyboard_shift_locked);
mShiftLockPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_shift_locked); mShiftLockPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_shift_locked);
setDefaultBounds(mShiftLockPreviewIcon); setDefaultBounds(mShiftLockPreviewIcon);
mSpaceIcon = res.getDrawable(R.drawable.sym_keyboard_space); mSpaceIcon = res.getDrawable(R.drawable.sym_keyboard_space);
@ -226,61 +222,62 @@ public class LatinKeyboard extends BaseKeyboard {
if (key instanceof LatinKey) { if (key instanceof LatinKey) {
((LatinKey)key).enableShiftLock(); ((LatinKey)key).enableShiftLock();
} }
mOldShiftIcons.put(key, key.icon); mNormalShiftIcons.put(key, key.icon);
} }
} }
public boolean setShiftLocked(boolean shiftLocked) { public boolean setShiftLocked(boolean newShiftLockState) {
// TODO: cleanup this method with BaseKeyboard.Key
for (final Key key : getShiftKeys()) { for (final Key key : getShiftKeys()) {
key.on = shiftLocked; key.on = newShiftLockState;
key.icon = mShiftLockIcon; key.icon = newShiftLockState ? mShiftedIcon : mNormalShiftIcons.get(key);
} }
mShiftState = shiftLocked ? SHIFT_LOCKED : SHIFT_ON; mShiftState.setShiftLocked(newShiftLockState);
return true; return true;
} }
public boolean isShiftLocked() { public boolean isShiftLocked() {
return mShiftState == SHIFT_LOCKED; return mShiftState.isShiftLocked();
} }
@Override @Override
public boolean setShifted(boolean shiftState) { public boolean setShifted(boolean newShiftState) {
// TODO: cleanup this method with BaseKeyboard.Key. if (getShiftKeys().size() == 0)
boolean shiftChanged = false; return super.setShifted(newShiftState);
if (getShiftKeys().size() > 0) {
for (final Key key : getShiftKeys()) { for (final Key key : getShiftKeys()) {
if (shiftState == false) { if (!newShiftState && !mShiftState.isShiftLocked()) {
key.on = false; key.icon = mNormalShiftIcons.get(key);
key.icon = mOldShiftIcons.get(key); } else if (newShiftState && !mShiftState.isShiftedOrShiftLocked()) {
} else if (mShiftState == SHIFT_OFF) { key.icon = mShiftedIcon;
key.icon = mShiftLockIcon;
} }
} }
if (shiftState == false) { return mShiftState.setShifted(newShiftState);
shiftChanged = mShiftState != SHIFT_OFF;
mShiftState = SHIFT_OFF;
} else if (mShiftState == SHIFT_OFF) {
shiftChanged = mShiftState == SHIFT_OFF;
mShiftState = SHIFT_ON;
}
return shiftChanged;
} else {
return super.setShifted(shiftState);
}
} }
@Override @Override
public boolean isShifted() { public boolean isShiftedOrShiftLocked() {
if (getShiftKeys().size() > 0) { if (getShiftKeys().size() > 0) {
return mShiftState != SHIFT_OFF; return mShiftState.isShiftedOrShiftLocked();
} else { } else {
return super.isShifted(); return super.isShiftedOrShiftLocked();
} }
} }
public boolean isTemporaryUpperCase() { public void setAutomaticTemporaryUpperCase() {
return mIsAlphaKeyboard && isShifted() && !isShiftLocked(); setShifted(true);
mShiftState.setAutomaticTemporaryUpperCase();
}
public boolean isAutomaticTemporaryUpperCase() {
return mIsAlphaKeyboard && mShiftState.isAutomaticTemporaryUpperCase();
}
public boolean isManualTemporaryUpperCase() {
return mIsAlphaKeyboard && mShiftState.isManualTemporaryUpperCase();
}
/* package */ LatinKeyboardShiftState getKeyboardShiftState() {
return mShiftState;
} }
public boolean isAlphaKeyboard() { public boolean isAlphaKeyboard() {
@ -291,12 +288,12 @@ public class LatinKeyboard extends BaseKeyboard {
mIsBlackSym = isBlack; mIsBlackSym = isBlack;
final Resources res = mRes; final Resources res = mRes;
if (isBlack) { if (isBlack) {
mShiftLockIcon = res.getDrawable(R.drawable.sym_bkeyboard_shift_locked); mShiftedIcon = res.getDrawable(R.drawable.sym_bkeyboard_shift_locked);
mSpaceIcon = res.getDrawable(R.drawable.sym_bkeyboard_space); mSpaceIcon = res.getDrawable(R.drawable.sym_bkeyboard_space);
mMicIcon = res.getDrawable(R.drawable.sym_bkeyboard_mic); mMicIcon = res.getDrawable(R.drawable.sym_bkeyboard_mic);
m123MicIcon = res.getDrawable(R.drawable.sym_bkeyboard_123_mic); m123MicIcon = res.getDrawable(R.drawable.sym_bkeyboard_123_mic);
} else { } else {
mShiftLockIcon = res.getDrawable(R.drawable.sym_keyboard_shift_locked); mShiftedIcon = res.getDrawable(R.drawable.sym_keyboard_shift_locked);
mSpaceIcon = res.getDrawable(R.drawable.sym_keyboard_space); mSpaceIcon = res.getDrawable(R.drawable.sym_keyboard_space);
mMicIcon = res.getDrawable(R.drawable.sym_keyboard_mic); mMicIcon = res.getDrawable(R.drawable.sym_keyboard_mic);
m123MicIcon = res.getDrawable(R.drawable.sym_keyboard_123_mic); m123MicIcon = res.getDrawable(R.drawable.sym_keyboard_123_mic);

View file

@ -0,0 +1,88 @@
package com.android.inputmethod.latin;
import android.util.Log;
public class LatinKeyboardShiftState {
private static final String TAG = "LatinKeyboardShiftState";
private static final boolean DEBUG = KeyboardSwitcher.DEBUG_STATE;
private static final int NORMAL = 0;
private static final int MANUAL_SHIFTED = 1;
private static final int SHIFT_LOCKED = 2;
private static final int AUTO_SHIFTED = 3;
private static final int SHIFT_LOCK_SHIFTED = 4;
private int mState = NORMAL;
public boolean setShifted(boolean newShiftState) {
final int oldState = mState;
if (newShiftState) {
if (oldState == NORMAL || oldState == AUTO_SHIFTED) {
mState = MANUAL_SHIFTED;
} else if (oldState == SHIFT_LOCKED) {
mState = SHIFT_LOCK_SHIFTED;
}
} else {
if (oldState == MANUAL_SHIFTED || oldState == AUTO_SHIFTED) {
mState = NORMAL;
} else if (oldState == SHIFT_LOCK_SHIFTED) {
mState = SHIFT_LOCKED;
}
}
if (DEBUG)
Log.d(TAG, "setShifted: " + toString(oldState) + " > " + this);
return mState != oldState;
}
public void setShiftLocked(boolean newShiftLockState) {
final int oldState = mState;
if (newShiftLockState) {
if (oldState == NORMAL || oldState == MANUAL_SHIFTED || oldState == AUTO_SHIFTED)
mState = SHIFT_LOCKED;
} else {
if (oldState == SHIFT_LOCKED || oldState == SHIFT_LOCK_SHIFTED)
mState = NORMAL;
}
if (DEBUG)
Log.d(TAG, "setShiftLocked: " + toString(oldState) + " > " + this);
}
public void setAutomaticTemporaryUpperCase() {
final int oldState = mState;
mState = AUTO_SHIFTED;
if (DEBUG)
Log.d(TAG, "setAutomaticTemporaryUpperCase: " + toString(oldState) + " > " + this);
}
public boolean isShiftedOrShiftLocked() {
return mState != NORMAL;
}
public boolean isShiftLocked() {
return mState == SHIFT_LOCKED || mState == SHIFT_LOCK_SHIFTED;
}
public boolean isAutomaticTemporaryUpperCase() {
return mState == AUTO_SHIFTED;
}
public boolean isManualTemporaryUpperCase() {
return mState == MANUAL_SHIFTED || mState == SHIFT_LOCK_SHIFTED;
}
@Override
public String toString() {
return toString(mState);
}
private static String toString(int state) {
switch (state) {
case NORMAL: return "NORMAL";
case MANUAL_SHIFTED: return "MANUAL_SHIFTED";
case SHIFT_LOCKED: return "SHIFT_LOCKED";
case AUTO_SHIFTED: return "AUTO_SHIFTED";
case SHIFT_LOCK_SHIFTED: return "SHIFT_LOCK_SHIFTED";
default: return "UKNOWN";
}
}
}

View file

@ -119,7 +119,7 @@ public class LatinKeyboardView extends BaseKeyboardView {
protected CharSequence adjustCase(CharSequence label) { protected CharSequence adjustCase(CharSequence label) {
LatinKeyboard keyboard = getLatinKeyboard(); LatinKeyboard keyboard = getLatinKeyboard();
if (keyboard.isAlphaKeyboard() if (keyboard.isAlphaKeyboard()
&& keyboard.isShifted() && keyboard.isShiftedOrShiftLocked()
&& !TextUtils.isEmpty(label) && label.length() < 3 && !TextUtils.isEmpty(label) && label.length() < 3
&& Character.isLowerCase(label.charAt(0))) { && Character.isLowerCase(label.charAt(0))) {
label = label.toString().toUpperCase(); label = label.toString().toUpperCase();

View file

@ -16,26 +16,60 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import android.util.Log;
public class ModifierKeyState { public class ModifierKeyState {
protected static final String TAG = "ModifierKeyState";
protected static final boolean DEBUG = KeyboardSwitcher.DEBUG_STATE;
protected static final int RELEASING = 0; protected static final int RELEASING = 0;
protected static final int PRESSING = 1; protected static final int PRESSING = 1;
protected static final int MOMENTARY = 2; protected static final int MOMENTARY = 2;
protected final String mName;
protected int mState = RELEASING; protected int mState = RELEASING;
public ModifierKeyState(String name) {
mName = name;
}
public void onPress() { public void onPress() {
final int oldState = mState;
mState = PRESSING; mState = PRESSING;
if (DEBUG)
Log.d(TAG, mName + ".onPress: " + toString(oldState) + " > " + this);
} }
public void onRelease() { public void onRelease() {
final int oldState = mState;
mState = RELEASING; mState = RELEASING;
if (DEBUG)
Log.d(TAG, mName + ".onRelease: " + toString(oldState) + " > " + this);
} }
public void onOtherKeyPressed() { public void onOtherKeyPressed() {
final int oldState = mState;
if (mState == PRESSING)
mState = MOMENTARY; mState = MOMENTARY;
if (DEBUG)
Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this);
} }
public boolean isMomentary() { public boolean isMomentary() {
return mState == MOMENTARY; return mState == MOMENTARY;
} }
@Override
public String toString() {
return toString(mState);
}
protected static String toString(int state) {
switch (state) {
case RELEASING: return "RELEASING";
case PRESSING: return "PRESSING";
case MOMENTARY: return "MOMENTARY";
default: return "UNKNOWN";
}
}
} }

View file

@ -423,9 +423,9 @@ public class PointerTracker {
} }
} }
private boolean isTemporaryUpperCase() { private boolean isManualTemporaryUpperCase() {
return mKeyboard instanceof LatinKeyboard return mKeyboard instanceof LatinKeyboard
&& ((LatinKeyboard)mKeyboard).isTemporaryUpperCase(); && ((LatinKeyboard)mKeyboard).isManualTemporaryUpperCase();
} }
private void detectAndSendKey(int index, int x, int y, long eventTime) { private void detectAndSendKey(int index, int x, int y, long eventTime) {
@ -458,7 +458,7 @@ public class PointerTracker {
// If keyboard is in manual temporary upper case state and key has manual temporary // If keyboard is in manual temporary upper case state and key has manual temporary
// shift code, alternate character code should be sent. // shift code, alternate character code should be sent.
if (isTemporaryUpperCase() && key.manualTemporaryUpperCaseCode != 0) { if (isManualTemporaryUpperCase() && key.manualTemporaryUpperCaseCode != 0) {
code = key.manualTemporaryUpperCaseCode; code = key.manualTemporaryUpperCaseCode;
codes[0] = code; codes[0] = code;
} }

View file

@ -16,21 +16,33 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import android.util.Log;
public class ShiftKeyState extends ModifierKeyState { public class ShiftKeyState extends ModifierKeyState {
private static final int PRESSING_ON_SHIFTED = 3; // both temporary shifted & shift locked private static final int PRESSING_ON_SHIFTED = 3; // both temporary shifted & shift locked
private static final int IGNORING = 4; private static final int IGNORING = 4;
public ShiftKeyState(String name) {
super(name);
}
@Override @Override
public void onOtherKeyPressed() { public void onOtherKeyPressed() {
int oldState = mState;
if (mState == PRESSING) { if (mState == PRESSING) {
mState = MOMENTARY; mState = MOMENTARY;
} else if (mState == PRESSING_ON_SHIFTED) { } else if (mState == PRESSING_ON_SHIFTED) {
mState = IGNORING; mState = IGNORING;
} }
if (DEBUG)
Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this);
} }
public void onPressOnShifted() { public void onPressOnShifted() {
int oldState = mState;
mState = PRESSING_ON_SHIFTED; mState = PRESSING_ON_SHIFTED;
if (DEBUG)
Log.d(TAG, mName + ".onPressOnShifted: " + toString(oldState) + " > " + this);
} }
public boolean isPressingOnShifted() { public boolean isPressingOnShifted() {
@ -40,4 +52,17 @@ public class ShiftKeyState extends ModifierKeyState {
public boolean isIgnoring() { public boolean isIgnoring() {
return mState == IGNORING; return mState == IGNORING;
} }
@Override
public String toString() {
return toString(mState);
}
protected static String toString(int state) {
switch (state) {
case PRESSING_ON_SHIFTED: return "PRESSING_ON_SHIFTED";
case IGNORING: return "IGNORING";
default: return ModifierKeyState.toString(state);
}
}
} }

View file

@ -217,7 +217,7 @@ public class Tutorial implements OnTouchListener {
return; return;
} }
if (mBubbleIndex == 3 || mBubbleIndex == 4) { if (mBubbleIndex == 3 || mBubbleIndex == 4) {
mKeyboardSwitcher.toggleKeyboardMode(); mKeyboardSwitcher.changeKeyboardMode();
} }
mHandler.sendMessageDelayed( mHandler.sendMessageDelayed(
mHandler.obtainMessage(MSG_SHOW_BUBBLE, mBubbles.get(mBubbleIndex)), 500); mHandler.obtainMessage(MSG_SHOW_BUBBLE, mBubbles.get(mBubbleIndex)), 500);