From 276845c7a9ea90fd34289d060873c8e3a7ed342c Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Tue, 26 Oct 2010 19:04:48 +0900 Subject: Follow-up change to revise Caps Lock sequence. bug: 3122877 Change-Id: I44c539d7c041443f3ad027de4b75a67adf6b2c87 --- .../android/inputmethod/latin/ModifierKeyState.java | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ModifierKeyState.java') diff --git a/java/src/com/android/inputmethod/latin/ModifierKeyState.java b/java/src/com/android/inputmethod/latin/ModifierKeyState.java index 097e87abe..75820e7d3 100644 --- a/java/src/com/android/inputmethod/latin/ModifierKeyState.java +++ b/java/src/com/android/inputmethod/latin/ModifierKeyState.java @@ -19,7 +19,9 @@ package com.android.inputmethod.latin; class ModifierKeyState { private static final int RELEASING = 0; private static final int PRESSING = 1; - private static final int MOMENTARY = 2; + private static final int PRESSING_ON_SHIFTED = 2; // both temporary shifted & shift locked + private static final int MOMENTARY = 3; + private static final int IGNORING = 4; private int mState = RELEASING; @@ -27,16 +29,31 @@ class ModifierKeyState { mState = PRESSING; } + public void onPressOnShifted() { + mState = PRESSING_ON_SHIFTED; + } + public void onRelease() { mState = RELEASING; } public void onOtherKeyPressed() { - if (mState == PRESSING) + if (mState == PRESSING) { mState = MOMENTARY; + } else if (mState == PRESSING_ON_SHIFTED) { + mState = IGNORING; + } } public boolean isMomentary() { return mState == MOMENTARY; } + + public boolean isPressingOnShifted() { + return mState == PRESSING_ON_SHIFTED; + } + + public boolean isIgnoring() { + return mState == IGNORING; + } } -- cgit v1.2.3-83-g751a From 889691eca1ad991a85fb721deb37ecba6a913762 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Tue, 16 Nov 2010 01:47:39 -0800 Subject: Refactor shift key state into KeyboardSwitcher Change-Id: If484d3d7e7a0794ee7fc88f0771229d6f90db466 --- .../inputmethod/latin/KeyboardSwitcher.java | 28 +++++++++++++- .../com/android/inputmethod/latin/LatinIME.java | 18 ++++----- .../inputmethod/latin/ModifierKeyState.java | 30 +++------------ .../android/inputmethod/latin/ShiftKeyState.java | 43 ++++++++++++++++++++++ 4 files changed, 83 insertions(+), 36 deletions(-) create mode 100644 java/src/com/android/inputmethod/latin/ShiftKeyState.java (limited to 'java/src/com/android/inputmethod/latin/ModifierKeyState.java') diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java index fdcf0ad4e..fce0e34fe 100644 --- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java @@ -75,7 +75,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private final LatinIME mInputMethodService; private final LanguageSwitcher mLanguageSwitcher; + private ShiftKeyState mShiftState = new ShiftKeyState(); private ModifierKeyState mSymbolKeyState = new ModifierKeyState(); + private KeyboardId mSymbolsId; private KeyboardId mSymbolsShiftedId; @@ -383,6 +385,30 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha mInputView.setShiftLocked(shiftLocked); } + public void onPressShift() { + mShiftState.onPress(); + } + + public void onPressShiftOnShifted() { + mShiftState.onPressOnShifted(); + } + + public void onReleaseShift() { + mShiftState.onRelease(); + } + + public boolean isShiftMomentary() { + return mShiftState.isMomentary(); + } + + public boolean isShiftPressingOnShifted() { + return mShiftState.isPressingOnShifted(); + } + + public boolean isShiftIgnoring() { + return mShiftState.isIgnoring(); + } + public void onPressSymbol() { mSymbolKeyState.onPress(); } @@ -396,7 +422,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha } public void onOtherKeyPressed() { - // TODO: shift key state will be handled too. + mShiftState.onOtherKeyPressed(); mSymbolKeyState.onOtherKeyPressed(); } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index a432eaa02..156d0bcca 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -235,9 +235,6 @@ public class LatinIME extends InputMethodService private int mDeleteCount; private long mLastKeyTime; - // Modifier keys state - private final ModifierKeyState mShiftKeyState = new ModifierKeyState(); - private Tutorial mTutorial; private AudioManager mAudioManager; @@ -1091,8 +1088,8 @@ public class LatinIME extends InputMethodService if (!switcher.isKeyboardAvailable()) return; if (ic != null && attr != null && switcher.isAlphabetMode() - && !mShiftKeyState.isIgnoring()) { - switcher.setShifted(mShiftKeyState.isMomentary() + && !switcher.isShiftIgnoring()) { + switcher.setShifted(switcher.isShiftMomentary() || switcher.isShiftLocked() || getCursorCapsMode(ic, attr) != 0); } } @@ -2342,16 +2339,15 @@ public class LatinIME extends InputMethodService // In alphabet mode, we call handleShift() to go into the shifted mode in this // method, onPress(), only when we are in the small letter mode. if (switcher.isAlphabetMode() && switcher.isShifted()) { - mShiftKeyState.onPressOnShifted(); + switcher.onPressShiftOnShifted(); } else { - mShiftKeyState.onPress(); + switcher.onPressShift(); handleShift(); } } else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) { switcher.onPressSymbol(); changeKeyboardMode(); } else { - mShiftKeyState.onOtherKeyPressed(); switcher.onOtherKeyPressed(); } } @@ -2364,18 +2360,18 @@ public class LatinIME extends InputMethodService switcher.keyReleased(); final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) { - if (mShiftKeyState.isMomentary()) { + if (switcher.isShiftMomentary()) { resetShift(); } if (switcher.isAlphabetMode()) { // In alphabet mode, we call handleShift() to go into the small letter mode in this // method, onRelease(), only when we are in the shifted modes -- temporary shifted // mode or caps lock mode. - if (switcher.isShifted() && mShiftKeyState.isPressingOnShifted()) { + if (switcher.isShifted() && switcher.isShiftPressingOnShifted()) { handleShift(); } } - mShiftKeyState.onRelease(); + switcher.onReleaseShift(); } else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) { if (switcher.isSymbolMomentary()) { changeKeyboardMode(); diff --git a/java/src/com/android/inputmethod/latin/ModifierKeyState.java b/java/src/com/android/inputmethod/latin/ModifierKeyState.java index 75820e7d3..8139ec531 100644 --- a/java/src/com/android/inputmethod/latin/ModifierKeyState.java +++ b/java/src/com/android/inputmethod/latin/ModifierKeyState.java @@ -16,44 +16,26 @@ package com.android.inputmethod.latin; -class ModifierKeyState { - private static final int RELEASING = 0; - private static final int PRESSING = 1; - private static final int PRESSING_ON_SHIFTED = 2; // both temporary shifted & shift locked - private static final int MOMENTARY = 3; - private static final int IGNORING = 4; +public class ModifierKeyState { + protected static final int RELEASING = 0; + protected static final int PRESSING = 1; + protected static final int MOMENTARY = 2; - private int mState = RELEASING; + protected int mState = RELEASING; public void onPress() { mState = PRESSING; } - public void onPressOnShifted() { - mState = PRESSING_ON_SHIFTED; - } - public void onRelease() { mState = RELEASING; } public void onOtherKeyPressed() { - if (mState == PRESSING) { - mState = MOMENTARY; - } else if (mState == PRESSING_ON_SHIFTED) { - mState = IGNORING; - } + mState = MOMENTARY; } public boolean isMomentary() { return mState == MOMENTARY; } - - public boolean isPressingOnShifted() { - return mState == PRESSING_ON_SHIFTED; - } - - public boolean isIgnoring() { - return mState == IGNORING; - } } diff --git a/java/src/com/android/inputmethod/latin/ShiftKeyState.java b/java/src/com/android/inputmethod/latin/ShiftKeyState.java new file mode 100644 index 000000000..5312ce2cc --- /dev/null +++ b/java/src/com/android/inputmethod/latin/ShiftKeyState.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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.latin; + +public class ShiftKeyState extends ModifierKeyState { + private static final int PRESSING_ON_SHIFTED = 3; // both temporary shifted & shift locked + private static final int IGNORING = 4; + + @Override + public void onOtherKeyPressed() { + if (mState == PRESSING) { + mState = MOMENTARY; + } else if (mState == PRESSING_ON_SHIFTED) { + mState = IGNORING; + } + } + + public void onPressOnShifted() { + mState = PRESSING_ON_SHIFTED; + } + + public boolean isPressingOnShifted() { + return mState == PRESSING_ON_SHIFTED; + } + + public boolean isIgnoring() { + return mState == IGNORING; + } +} -- cgit v1.2.3-83-g751a From f27364600c742509b48857e6b8f17312033e0dc7 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Sat, 13 Nov 2010 00:16:34 -0800 Subject: 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 --- .../android/inputmethod/latin/BaseKeyboard.java | 2 +- .../inputmethod/latin/BaseKeyboardView.java | 10 +- .../inputmethod/latin/KeyboardSwitcher.java | 150 +++++++++++++++------ .../com/android/inputmethod/latin/LatinIME.java | 10 +- .../android/inputmethod/latin/LatinKeyboard.java | 83 ++++++------ .../inputmethod/latin/LatinKeyboardShiftState.java | 88 ++++++++++++ .../inputmethod/latin/LatinKeyboardView.java | 2 +- .../inputmethod/latin/ModifierKeyState.java | 36 ++++- .../android/inputmethod/latin/PointerTracker.java | 6 +- .../android/inputmethod/latin/ShiftKeyState.java | 25 ++++ .../com/android/inputmethod/latin/Tutorial.java | 2 +- 11 files changed, 312 insertions(+), 102 deletions(-) create mode 100644 java/src/com/android/inputmethod/latin/LatinKeyboardShiftState.java (limited to 'java/src/com/android/inputmethod/latin/ModifierKeyState.java') diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboard.java b/java/src/com/android/inputmethod/latin/BaseKeyboard.java index 0f8b75d45..9dbfff34a 100644 --- a/java/src/com/android/inputmethod/latin/BaseKeyboard.java +++ b/java/src/com/android/inputmethod/latin/BaseKeyboard.java @@ -626,7 +626,7 @@ public class BaseKeyboard { return false; } - public boolean isShifted() { + public boolean isShiftedOrShiftLocked() { return mShifted; } diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboardView.java b/java/src/com/android/inputmethod/latin/BaseKeyboardView.java index ad0e8d41a..89c9572b1 100644 --- a/java/src/com/android/inputmethod/latin/BaseKeyboardView.java +++ b/java/src/com/android/inputmethod/latin/BaseKeyboardView.java @@ -683,7 +683,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy { } 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))) { label = label.toString().toUpperCase(); } @@ -772,8 +772,8 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy { final int kbdPaddingTop = getPaddingTop(); final Key[] keys = mKeys; final Key invalidKey = mInvalidatedKey; - final boolean isTemporaryUpperCase = (mKeyboard instanceof LatinKeyboard - && ((LatinKeyboard)mKeyboard).isTemporaryUpperCase()); + final boolean isManualTemporaryUpperCase = (mKeyboard instanceof LatinKeyboard + && ((LatinKeyboard)mKeyboard).isManualTemporaryUpperCase()); paint.setColor(mKeyTextColor); boolean drawSingleKey = false; @@ -853,7 +853,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy { int drawableHeight = key.height; int drawableX = 0; int drawableY = HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL; - Drawable icon = (isTemporaryUpperCase + Drawable icon = (isManualTemporaryUpperCase && key.manualTemporaryUpperCaseHintIcon != null) ? key.manualTemporaryUpperCaseHintIcon : key.hintIcon; 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() BaseKeyboard baseMiniKeyboard = mMiniKeyboard.getKeyboard(); if (baseMiniKeyboard != null && baseMiniKeyboard.setShifted(mKeyboard == null - ? false : mKeyboard.isShifted())) { + ? false : mKeyboard.isShiftedOrShiftLocked())) { mMiniKeyboard.invalidateAllKeys(); } // Mini keyboard needs no pop-up key preview displayed. diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java index 3f6b6ca33..15a2279fa 100644 --- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java @@ -18,7 +18,6 @@ package com.android.inputmethod.latin; import android.content.Context; import android.content.SharedPreferences; -import android.content.res.Configuration; import android.content.res.Resources; import android.preference.PreferenceManager; import android.util.Log; @@ -32,6 +31,7 @@ import java.util.Locale; public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = "KeyboardSwitcher"; 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_URL = 1; @@ -76,8 +76,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private LatinKeyboardView mInputView; private LatinIME mInputMethodService; - private ShiftKeyState mShiftState = new ShiftKeyState(); - private ModifierKeyState mSymbolKeyState = new ModifierKeyState(); + private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift"); + private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol"); private KeyboardId mSymbolsId; private KeyboardId mSymbolsShiftedId; @@ -374,10 +374,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha latinKeyboard.keyReleased(); } - public boolean isShifted() { + public boolean isShiftedOrShiftLocked() { LatinKeyboard latinKeyboard = getLatinKeyboard(); if (latinKeyboard != null) - return latinKeyboard.isShifted(); + return latinKeyboard.isShiftedOrShiftLocked(); return false; } @@ -388,7 +388,21 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha 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(); if (latinKeyboard != null && latinKeyboard.setShifted(shifted)) { mInputView.invalidateAllKeys(); @@ -403,21 +417,13 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha } public void toggleShift() { - handleShiftInternal(false); - } - - private void resetShift() { - handleShiftInternal(true); - } - - private void handleShiftInternal(boolean forceNormal) { mInputMethodService.mHandler.cancelUpdateShiftState(); + if (DEBUG_STATE) + Log.d(TAG, "toggleShift:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + mShiftKeyState); if (isAlphabetMode()) { - if (forceNormal) { - setShifted(false); - } else { - setShifted(!isShifted()); - } + setManualTemporaryUpperCase(!isShiftedOrShiftLocked()); } else { toggleShiftInSymbol(); } @@ -425,27 +431,50 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha public void toggleCapsLock() { mInputMethodService.mHandler.cancelUpdateShiftState(); + if (DEBUG_STATE) + Log.d(TAG, "toggleCapsLock:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + mShiftKeyState); if (isAlphabetMode()) { if (isShiftLocked()) { - // setShifted(false) also disable shift locked state. - // Note: Caps lock LED is off when Key.on is false. - setShifted(false); + // Shift key is long pressed while caps lock state, we will toggle back to normal + // state. And mark as if shift key is released. + setShiftLocked(false); + mShiftKeyState.onRelease(); } else { - // setShiftLocked(true) enable shift state too. - // Note: Caps lock LED is on when Key.on is true. setShiftLocked(true); } } } + private void setAutomaticTemporaryUpperCase() { + LatinKeyboard latinKeyboard = getLatinKeyboard(); + if (latinKeyboard != null) { + latinKeyboard.setAutomaticTemporaryUpperCase(); + mInputView.invalidateAllKeys(); + } + } + public void updateShiftState() { - if (isAlphabetMode() && !mShiftState.isIgnoring()) { - final boolean autoCapsMode = mInputMethodService.getCurrentAutoCapsState(); - setShifted(mShiftState.isMomentary() || isShiftLocked() || autoCapsMode); + if (DEBUG_STATE) + Log.d(TAG, "updateShiftState:" + + " autoCaps=" + mInputMethodService.getCurrentAutoCapsState() + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + mShiftKeyState); + if (isAlphabetMode() && !isShiftLocked() && !mShiftKeyState.isIgnoring()) { + if (mInputMethodService.getCurrentAutoCapsState()) { + setAutomaticTemporaryUpperCase(); + } else { + setManualTemporaryUpperCase(mShiftKeyState.isMomentary()); + } } } public void changeKeyboardMode() { + if (DEBUG_STATE) + Log.d(TAG, "changeKeyboardMode:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + mShiftKeyState); toggleKeyboardMode(); if (isShiftLocked() && isAlphabetMode()) setShiftLocked(true); @@ -455,47 +484,82 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha public void onPressShift() { if (!isKeyboardAvailable()) return; - if (isAlphabetMode() && isShifted()) { - // In alphabet mode, we don't call toggleShift() when we are already in the shifted - // state. - mShiftState.onPressOnShifted(); + ShiftKeyState shiftKeyState = mShiftKeyState; + if (DEBUG_STATE) + Log.d(TAG, "onPressShift:" + + " 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 { + // In base layout, chording or manual temporary upper case mode is started. + toggleShift(); + shiftKeyState.onPress(); + } } else { - // In alphabet mode, we call toggleShift() to go into the shifted mode only when we are - // not in the shifted state. - // This else clause also handles shift key pressing in symbol mode. - mShiftState.onPress(); + // In symbol mode, just toggle symbol and symbol more keyboard. toggleShift(); + shiftKeyState.onPress(); } } public void onReleaseShift() { if (!isKeyboardAvailable()) return; + ShiftKeyState shiftKeyState = mShiftKeyState; + if (DEBUG_STATE) + Log.d(TAG, "onReleaseShift:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + shiftKeyState); if (isAlphabetMode()) { - if (mShiftState.isMomentary()) { - resetShift(); - } else if (isShifted() && mShiftState.isPressingOnShifted()) { - // In alphabet mode, we call toggleShift() to go into the non shifted state only - // when we are in the shifted state -- temporary shifted mode or caps lock mode. + if (shiftKeyState.isMomentary()) { + // After chording input while normal state. + toggleShift(); + } else if (isShiftLocked() && !shiftKeyState.isIgnoring()) { + // 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(); } } - mShiftState.onRelease(); + shiftKeyState.onRelease(); } public void onPressSymbol() { + if (DEBUG_STATE) + Log.d(TAG, "onReleaseShift:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " symbolKeyState=" + mSymbolKeyState); changeKeyboardMode(); mSymbolKeyState.onPress(); } public void onReleaseSymbol() { + if (DEBUG_STATE) + Log.d(TAG, "onReleaseShift:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " symbolKeyState=" + mSymbolKeyState); if (mSymbolKeyState.isMomentary()) changeKeyboardMode(); mSymbolKeyState.onRelease(); } public void onOtherKeyPressed() { - mShiftState.onOtherKeyPressed(); + mShiftKeyState.onOtherKeyPressed(); mSymbolKeyState.onOtherKeyPressed(); } @@ -521,7 +585,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha mInputView.setKeyboard(keyboard); } - public void toggleKeyboardMode() { + private void toggleKeyboardMode() { loadKeyboardInternal(mMode, mImeOptions, mVoiceButtonEnabled, mVoiceButtonOnPrimary, !mIsSymbols); if (mIsSymbols) { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 295a03be3..307021a37 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1004,7 +1004,8 @@ public class LatinIME extends InputMethodService return true; } // 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.getAction(), event.getKeyCode(), event.getRepeatCount(), event.getDeviceId(), event.getScanCode(), @@ -1373,7 +1374,7 @@ public class LatinIME extends InputMethodService } } KeyboardSwitcher switcher = mKeyboardSwitcher; - if (switcher.isShifted()) { + if (switcher.isShiftedOrShiftLocked()) { if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT || keyCodes[0] > Character.MAX_CODE_POINT) { return; @@ -1392,7 +1393,8 @@ public class LatinIME extends InputMethodService } } if (mPredicting) { - if (mComposing.length() == 0 && switcher.isAlphabetMode() && switcher.isShifted()) { + if (mComposing.length() == 0 && switcher.isAlphabetMode() + && switcher.isShiftedOrShiftLocked()) { mWord.setFirstCharCapitalized(true); } mComposing.append((char) primaryCode); @@ -1677,7 +1679,7 @@ public class LatinIME extends InputMethodService final List nBest = new ArrayList(); KeyboardSwitcher switcher = mKeyboardSwitcher; boolean capitalizeFirstWord = preferCapitalization() - || (switcher.isAlphabetMode() && switcher.isShifted()); + || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked()); for (String c : mVoiceResults.candidates) { if (capitalizeFirstWord) { c = Character.toUpperCase(c.charAt(0)) + c.substring(1, c.length()); diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java index 6520d08e6..6fcea227d 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboard.java @@ -46,9 +46,9 @@ public class LatinKeyboard extends BaseKeyboard { private static final int OPACITY_FULLY_OPAQUE = 255; private static final int SPACE_LED_LENGTH_PERCENT = 80; - private Drawable mShiftLockIcon; + private Drawable mShiftedIcon; private Drawable mShiftLockPreviewIcon; - private final HashMap mOldShiftIcons = new HashMap(); + private final HashMap mNormalShiftIcons = new HashMap(); private Drawable mSpaceIcon; private Drawable mSpaceAutoCompletionIndicator; private Drawable mSpacePreviewIcon; @@ -92,11 +92,7 @@ public class LatinKeyboard extends BaseKeyboard { // TODO: generalize for any keyboardId private boolean mIsBlackSym; - private static final int SHIFT_OFF = 0; - private static final int SHIFT_ON = 1; - private static final int SHIFT_LOCKED = 2; - - private int mShiftState = SHIFT_OFF; + private LatinKeyboardShiftState mShiftState = new LatinKeyboardShiftState(); private static final float SPACEBAR_DRAG_THRESHOLD = 0.8f; private static final float OVERLAP_PERCENTAGE_LOW_PROB = 0.70f; @@ -117,7 +113,7 @@ public class LatinKeyboard extends BaseKeyboard { mContext = context; mRes = res; 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); setDefaultBounds(mShiftLockPreviewIcon); mSpaceIcon = res.getDrawable(R.drawable.sym_keyboard_space); @@ -226,61 +222,62 @@ public class LatinKeyboard extends BaseKeyboard { if (key instanceof LatinKey) { ((LatinKey)key).enableShiftLock(); } - mOldShiftIcons.put(key, key.icon); + mNormalShiftIcons.put(key, key.icon); } } - public boolean setShiftLocked(boolean shiftLocked) { - // TODO: cleanup this method with BaseKeyboard.Key + public boolean setShiftLocked(boolean newShiftLockState) { for (final Key key : getShiftKeys()) { - key.on = shiftLocked; - key.icon = mShiftLockIcon; + key.on = newShiftLockState; + key.icon = newShiftLockState ? mShiftedIcon : mNormalShiftIcons.get(key); } - mShiftState = shiftLocked ? SHIFT_LOCKED : SHIFT_ON; + mShiftState.setShiftLocked(newShiftLockState); return true; } public boolean isShiftLocked() { - return mShiftState == SHIFT_LOCKED; + return mShiftState.isShiftLocked(); } @Override - public boolean setShifted(boolean shiftState) { - // TODO: cleanup this method with BaseKeyboard.Key. - boolean shiftChanged = false; - if (getShiftKeys().size() > 0) { - for (final Key key : getShiftKeys()) { - if (shiftState == false) { - key.on = false; - key.icon = mOldShiftIcons.get(key); - } else if (mShiftState == SHIFT_OFF) { - key.icon = mShiftLockIcon; - } - } - if (shiftState == false) { - shiftChanged = mShiftState != SHIFT_OFF; - mShiftState = SHIFT_OFF; - } else if (mShiftState == SHIFT_OFF) { - shiftChanged = mShiftState == SHIFT_OFF; - mShiftState = SHIFT_ON; + public boolean setShifted(boolean newShiftState) { + if (getShiftKeys().size() == 0) + return super.setShifted(newShiftState); + + for (final Key key : getShiftKeys()) { + if (!newShiftState && !mShiftState.isShiftLocked()) { + key.icon = mNormalShiftIcons.get(key); + } else if (newShiftState && !mShiftState.isShiftedOrShiftLocked()) { + key.icon = mShiftedIcon; } - return shiftChanged; - } else { - return super.setShifted(shiftState); } + return mShiftState.setShifted(newShiftState); } @Override - public boolean isShifted() { + public boolean isShiftedOrShiftLocked() { if (getShiftKeys().size() > 0) { - return mShiftState != SHIFT_OFF; + return mShiftState.isShiftedOrShiftLocked(); } else { - return super.isShifted(); + return super.isShiftedOrShiftLocked(); } } - public boolean isTemporaryUpperCase() { - return mIsAlphaKeyboard && isShifted() && !isShiftLocked(); + public void setAutomaticTemporaryUpperCase() { + 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() { @@ -291,12 +288,12 @@ public class LatinKeyboard extends BaseKeyboard { mIsBlackSym = isBlack; final Resources res = mRes; 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); mMicIcon = res.getDrawable(R.drawable.sym_bkeyboard_mic); m123MicIcon = res.getDrawable(R.drawable.sym_bkeyboard_123_mic); } 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); mMicIcon = res.getDrawable(R.drawable.sym_keyboard_mic); m123MicIcon = res.getDrawable(R.drawable.sym_keyboard_123_mic); diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardShiftState.java b/java/src/com/android/inputmethod/latin/LatinKeyboardShiftState.java new file mode 100644 index 000000000..74c474293 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardShiftState.java @@ -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"; + } + } +} \ No newline at end of file diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java index 3bcac4ec1..a215621d1 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java @@ -119,7 +119,7 @@ public class LatinKeyboardView extends BaseKeyboardView { protected CharSequence adjustCase(CharSequence label) { LatinKeyboard keyboard = getLatinKeyboard(); if (keyboard.isAlphaKeyboard() - && keyboard.isShifted() + && keyboard.isShiftedOrShiftLocked() && !TextUtils.isEmpty(label) && label.length() < 3 && Character.isLowerCase(label.charAt(0))) { label = label.toString().toUpperCase(); diff --git a/java/src/com/android/inputmethod/latin/ModifierKeyState.java b/java/src/com/android/inputmethod/latin/ModifierKeyState.java index 8139ec531..07a5c4f7f 100644 --- a/java/src/com/android/inputmethod/latin/ModifierKeyState.java +++ b/java/src/com/android/inputmethod/latin/ModifierKeyState.java @@ -16,26 +16,60 @@ package com.android.inputmethod.latin; +import android.util.Log; + 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 PRESSING = 1; protected static final int MOMENTARY = 2; + protected final String mName; protected int mState = RELEASING; + public ModifierKeyState(String name) { + mName = name; + } + public void onPress() { + final int oldState = mState; mState = PRESSING; + if (DEBUG) + Log.d(TAG, mName + ".onPress: " + toString(oldState) + " > " + this); } public void onRelease() { + final int oldState = mState; mState = RELEASING; + if (DEBUG) + Log.d(TAG, mName + ".onRelease: " + toString(oldState) + " > " + this); } public void onOtherKeyPressed() { - mState = MOMENTARY; + final int oldState = mState; + if (mState == PRESSING) + mState = MOMENTARY; + if (DEBUG) + Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this); } public boolean isMomentary() { 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"; + } + } } diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index e76f8c705..4d9133045 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -423,9 +423,9 @@ public class PointerTracker { } } - private boolean isTemporaryUpperCase() { + private boolean isManualTemporaryUpperCase() { return mKeyboard instanceof LatinKeyboard - && ((LatinKeyboard)mKeyboard).isTemporaryUpperCase(); + && ((LatinKeyboard)mKeyboard).isManualTemporaryUpperCase(); } 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 // shift code, alternate character code should be sent. - if (isTemporaryUpperCase() && key.manualTemporaryUpperCaseCode != 0) { + if (isManualTemporaryUpperCase() && key.manualTemporaryUpperCaseCode != 0) { code = key.manualTemporaryUpperCaseCode; codes[0] = code; } diff --git a/java/src/com/android/inputmethod/latin/ShiftKeyState.java b/java/src/com/android/inputmethod/latin/ShiftKeyState.java index 5312ce2cc..ef13ddc9b 100644 --- a/java/src/com/android/inputmethod/latin/ShiftKeyState.java +++ b/java/src/com/android/inputmethod/latin/ShiftKeyState.java @@ -16,21 +16,33 @@ package com.android.inputmethod.latin; +import android.util.Log; + public class ShiftKeyState extends ModifierKeyState { private static final int PRESSING_ON_SHIFTED = 3; // both temporary shifted & shift locked private static final int IGNORING = 4; + public ShiftKeyState(String name) { + super(name); + } + @Override public void onOtherKeyPressed() { + int oldState = mState; if (mState == PRESSING) { mState = MOMENTARY; } else if (mState == PRESSING_ON_SHIFTED) { mState = IGNORING; } + if (DEBUG) + Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this); } public void onPressOnShifted() { + int oldState = mState; mState = PRESSING_ON_SHIFTED; + if (DEBUG) + Log.d(TAG, mName + ".onPressOnShifted: " + toString(oldState) + " > " + this); } public boolean isPressingOnShifted() { @@ -40,4 +52,17 @@ public class ShiftKeyState extends ModifierKeyState { public boolean isIgnoring() { 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); + } + } } diff --git a/java/src/com/android/inputmethod/latin/Tutorial.java b/java/src/com/android/inputmethod/latin/Tutorial.java index 3563a8c73..cd7636f3c 100644 --- a/java/src/com/android/inputmethod/latin/Tutorial.java +++ b/java/src/com/android/inputmethod/latin/Tutorial.java @@ -217,7 +217,7 @@ public class Tutorial implements OnTouchListener { return; } if (mBubbleIndex == 3 || mBubbleIndex == 4) { - mKeyboardSwitcher.toggleKeyboardMode(); + mKeyboardSwitcher.changeKeyboardMode(); } mHandler.sendMessageDelayed( mHandler.obtainMessage(MSG_SHOW_BUBBLE, mBubbles.get(mBubbleIndex)), 500); -- cgit v1.2.3-83-g751a From 6769c67987f323008647f5d029c02f8cc95272ee Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 19 Nov 2010 13:52:58 -0800 Subject: Fix automatic temporary upper case mode behaviour This change is a followup of I948ef26f Automatic Temporary Upper Case mode acts like Normal mode until shift key is pressed. However, after shift key is pressed, it acts like Manual Temporary Upper Case mode. Bug: 3193390 Change-Id: Id3d7a38a1f5905322cd46ded36b1db26576d49af --- java/src/com/android/inputmethod/latin/KeyboardSwitcher.java | 8 ++++---- java/src/com/android/inputmethod/latin/ModifierKeyState.java | 4 ++-- java/src/com/android/inputmethod/latin/ShiftKeyState.java | 9 +++++---- 3 files changed, 11 insertions(+), 10 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ModifierKeyState.java') diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java index 5f78cb91e..0d116dcf9 100644 --- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java @@ -499,26 +499,26 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha 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(); + setManualTemporaryUpperCase(true); } else if (isAutomaticTemporaryUpperCase()) { // Shift key is pressed while automatic temporary upper case, we have to move to // manual temporary upper case. + shiftKeyState.onPress(); 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 { // In base layout, chording or manual temporary upper case mode is started. - toggleShift(); shiftKeyState.onPress(); + toggleShift(); } } else { // In symbol mode, just toggle symbol and symbol more keyboard. - toggleShift(); shiftKeyState.onPress(); + toggleShift(); } } diff --git a/java/src/com/android/inputmethod/latin/ModifierKeyState.java b/java/src/com/android/inputmethod/latin/ModifierKeyState.java index 07a5c4f7f..8443be433 100644 --- a/java/src/com/android/inputmethod/latin/ModifierKeyState.java +++ b/java/src/com/android/inputmethod/latin/ModifierKeyState.java @@ -49,7 +49,7 @@ public class ModifierKeyState { public void onOtherKeyPressed() { final int oldState = mState; - if (mState == PRESSING) + if (oldState == PRESSING) mState = MOMENTARY; if (DEBUG) Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this); @@ -64,7 +64,7 @@ public class ModifierKeyState { return toString(mState); } - protected static String toString(int state) { + protected String toString(int state) { switch (state) { case RELEASING: return "RELEASING"; case PRESSING: return "PRESSING"; diff --git a/java/src/com/android/inputmethod/latin/ShiftKeyState.java b/java/src/com/android/inputmethod/latin/ShiftKeyState.java index ef13ddc9b..7412a566d 100644 --- a/java/src/com/android/inputmethod/latin/ShiftKeyState.java +++ b/java/src/com/android/inputmethod/latin/ShiftKeyState.java @@ -29,9 +29,9 @@ public class ShiftKeyState extends ModifierKeyState { @Override public void onOtherKeyPressed() { int oldState = mState; - if (mState == PRESSING) { + if (oldState == PRESSING) { mState = MOMENTARY; - } else if (mState == PRESSING_ON_SHIFTED) { + } else if (oldState == PRESSING_ON_SHIFTED) { mState = IGNORING; } if (DEBUG) @@ -58,11 +58,12 @@ public class ShiftKeyState extends ModifierKeyState { return toString(mState); } - protected static String toString(int state) { + @Override + protected String toString(int state) { switch (state) { case PRESSING_ON_SHIFTED: return "PRESSING_ON_SHIFTED"; case IGNORING: return "IGNORING"; - default: return ModifierKeyState.toString(state); + default: return super.toString(state); } } } -- cgit v1.2.3-83-g751a From 45911256fd4e32880e33c42259b19e8d7af70cb1 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 12 Nov 2010 15:49:56 -0800 Subject: Perform editor action IME_ACTION_NEXT/PREVIOUS by tab key Bug: 3122995 Change-Id: I44280fe1c6cc27f429b311edec71e1027178222d --- .../inputmethod/latin/KeyboardSwitcher.java | 25 ++++++++++++---- .../com/android/inputmethod/latin/LatinIME.java | 33 +++++++++++++++++++--- .../inputmethod/latin/LatinKeyboardShiftState.java | 5 ++-- .../inputmethod/latin/ModifierKeyState.java | 4 +++ 4 files changed, 55 insertions(+), 12 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ModifierKeyState.java') diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java index 0d116dcf9..7ae597f75 100644 --- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java @@ -462,17 +462,25 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha } public void updateShiftState() { + final ShiftKeyState shiftKeyState = mShiftKeyState; if (DEBUG_STATE) Log.d(TAG, "updateShiftState:" + " autoCaps=" + mInputMethodService.getCurrentAutoCapsState() + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " shiftKeyState=" + mShiftKeyState); - if (isAlphabetMode() && !isShiftLocked() && !mShiftKeyState.isIgnoring()) { - if (mInputMethodService.getCurrentAutoCapsState()) { - setAutomaticTemporaryUpperCase(); - } else { - setManualTemporaryUpperCase(mShiftKeyState.isMomentary()); + + " shiftKeyState=" + shiftKeyState); + if (isAlphabetMode()) { + if (!isShiftLocked() && !shiftKeyState.isIgnoring()) { + if (shiftKeyState.isReleasing() && mInputMethodService.getCurrentAutoCapsState()) { + // Only when shift key is releasing, automatic temporary upper case will be set. + setAutomaticTemporaryUpperCase(); + } else { + setManualTemporaryUpperCase(shiftKeyState.isMomentary()); + } } + } else { + // In symbol keyboard mode, we should clear shift key state because only alphabet + // keyboard has shift key. + shiftKeyState.onRelease(); } } @@ -565,6 +573,11 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha } public void onOtherKeyPressed() { + if (DEBUG_STATE) + Log.d(TAG, "onOtherKeyPressed:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + mShiftKeyState + + " symbolKeyState=" + mSymbolKeyState); mShiftKeyState.onOtherKeyPressed(); mSymbolKeyState.onOtherKeyPressed(); } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 307021a37..e24bc0e6d 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -572,7 +572,8 @@ public class LatinIME extends InputMethodService @Override public void onStartInputView(EditorInfo attribute, boolean restarting) { - LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); + final KeyboardSwitcher switcher = mKeyboardSwitcher; + LatinKeyboardView inputView = switcher.getInputView(); // In landscape mode, this method gets called without the input view being created. if (inputView == null) { return; @@ -678,9 +679,9 @@ public class LatinIME extends InputMethodService mJustAddedAutoSpace = false; loadSettings(attribute); - mKeyboardSwitcher.loadKeyboard(mode, attribute.imeOptions, mVoiceButtonEnabled, + switcher.loadKeyboard(mode, attribute.imeOptions, mVoiceButtonEnabled, mVoiceButtonOnPrimary); - mKeyboardSwitcher.updateShiftState(); + switcher.updateShiftState(); setCandidatesViewShownInternal(isCandidateStripVisible(), false /* needsInputViewShown */ ); @@ -1228,7 +1229,7 @@ public class LatinIME extends InputMethodService } break; case KEYCODE_TAB: - sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); + handleTab(); break; default: if (primaryCode != KEYCODE_ENTER) { @@ -1343,6 +1344,30 @@ public class LatinIME extends InputMethodService ic.endBatchEdit(); } + private void handleTab() { + final int imeOptions = getCurrentInputEditorInfo().imeOptions; + final int navigationFlags = + EditorInfo.IME_FLAG_NAVIGATE_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS; + if ((imeOptions & navigationFlags) == 0) { + sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); + return; + } + + final InputConnection ic = getCurrentInputConnection(); + if (ic == null) + return; + + // True if keyboard is in either chording shift or manual temporary upper case mode. + final boolean isManualTemporaryUpperCase = mKeyboardSwitcher.isManualTemporaryUpperCase(); + if ((imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0 + && !isManualTemporaryUpperCase) { + ic.performEditorAction(EditorInfo.IME_ACTION_NEXT); + } else if ((imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0 + && isManualTemporaryUpperCase) { + ic.performEditorAction(EditorInfo.IME_ACTION_PREVIOUS); + } + } + private void abortCorrection(boolean force) { if (force || TextEntryState.isCorrecting()) { TextEntryState.onAbortCorrection(); diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardShiftState.java b/java/src/com/android/inputmethod/latin/LatinKeyboardShiftState.java index 74c474293..e916306c8 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardShiftState.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardShiftState.java @@ -30,7 +30,7 @@ public class LatinKeyboardShiftState { } } if (DEBUG) - Log.d(TAG, "setShifted: " + toString(oldState) + " > " + this); + Log.d(TAG, "setShifted(" + newShiftState + "): " + toString(oldState) + " > " + this); return mState != oldState; } @@ -44,7 +44,8 @@ public class LatinKeyboardShiftState { mState = NORMAL; } if (DEBUG) - Log.d(TAG, "setShiftLocked: " + toString(oldState) + " > " + this); + Log.d(TAG, "setShiftLocked(" + newShiftLockState + "): " + toString(oldState) + + " > " + this); } public void setAutomaticTemporaryUpperCase() { diff --git a/java/src/com/android/inputmethod/latin/ModifierKeyState.java b/java/src/com/android/inputmethod/latin/ModifierKeyState.java index 8443be433..eb1204f70 100644 --- a/java/src/com/android/inputmethod/latin/ModifierKeyState.java +++ b/java/src/com/android/inputmethod/latin/ModifierKeyState.java @@ -55,6 +55,10 @@ public class ModifierKeyState { Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this); } + public boolean isReleasing() { + return mState == RELEASING; + } + public boolean isMomentary() { return mState == MOMENTARY; } -- cgit v1.2.3-83-g751a From 571bdb401f670b92bd7710a12a990cb65a99b7d3 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 2 Dec 2010 20:54:32 +0900 Subject: Refactor LatinKeyboard and LatinKey This change also moves KeyboardSwitcher and related classes to com.android.inputmethod.keyboard package. Multi project change with Ib23017b2 Change-Id: Id7d54b24615fe22ebb540ca847549909e346ee24 --- java/src/com/android/inputmethod/keyboard/Key.java | 198 ++++--- .../com/android/inputmethod/keyboard/Keyboard.java | 149 +++-- .../android/inputmethod/keyboard/KeyboardId.java | 10 +- .../inputmethod/keyboard/KeyboardParser.java | 8 +- .../inputmethod/keyboard/KeyboardShiftState.java | 105 ++++ .../inputmethod/keyboard/KeyboardSwitcher.java | 646 +++++++++++++++++++++ .../android/inputmethod/keyboard/KeyboardView.java | 136 +++-- .../com/android/inputmethod/keyboard/LatinKey.java | 54 +- .../inputmethod/keyboard/LatinKeyboard.java | 162 +----- .../keyboard/LatinKeyboardShiftState.java | 107 ---- .../inputmethod/keyboard/LatinKeyboardView.java | 19 +- .../keyboard/MiniKeyboardKeyDetector.java | 2 +- .../inputmethod/keyboard/ModifierKeyState.java | 79 +++ .../inputmethod/keyboard/PointerTracker.java | 53 +- .../inputmethod/keyboard/ProximityKeyDetector.java | 4 +- java/src/com/android/inputmethod/keyboard/Row.java | 28 +- .../inputmethod/keyboard/ShiftKeyState.java | 69 +++ .../inputmethod/latin/KeyboardSwitcher.java | 644 -------------------- .../com/android/inputmethod/latin/LatinIME.java | 81 ++- .../inputmethod/latin/LatinIMESettings.java | 2 +- .../inputmethod/latin/ModifierKeyState.java | 79 --- .../android/inputmethod/latin/ShiftKeyState.java | 69 --- .../android/inputmethod/latin/SubtypeSwitcher.java | 6 +- .../android/inputmethod/latin/TextEntryState.java | 12 +- .../com/android/inputmethod/latin/Tutorial.java | 1 + .../inputmethod/voice/VoiceIMEConnector.java | 2 +- 26 files changed, 1341 insertions(+), 1384 deletions(-) create mode 100644 java/src/com/android/inputmethod/keyboard/KeyboardShiftState.java create mode 100644 java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java delete mode 100644 java/src/com/android/inputmethod/keyboard/LatinKeyboardShiftState.java create mode 100644 java/src/com/android/inputmethod/keyboard/ModifierKeyState.java create mode 100644 java/src/com/android/inputmethod/keyboard/ShiftKeyState.java delete mode 100644 java/src/com/android/inputmethod/latin/KeyboardSwitcher.java delete mode 100644 java/src/com/android/inputmethod/latin/ModifierKeyState.java delete mode 100644 java/src/com/android/inputmethod/latin/ShiftKeyState.java (limited to 'java/src/com/android/inputmethod/latin/ModifierKeyState.java') diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index 9b7937618..c268abb89 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -35,47 +35,47 @@ public class Key { * All the key codes (unicode or custom code) that this key could generate, zero'th * being the most important. */ - public int[] codes; + public int[] mCodes; /** The unicode that this key generates in manual temporary upper case mode. */ - public int manualTemporaryUpperCaseCode; + public int mManualTemporaryUpperCaseCode; /** Label to display */ - public CharSequence label; + public CharSequence mLabel; /** Option of the label */ - public int labelOption; + public int mLabelOption; /** Icon to display instead of a label. Icon takes precedence over a label */ - public Drawable icon; + public Drawable mIcon; /** Hint icon to display on the key in conjunction with the label */ - public Drawable hintIcon; + public Drawable mHintIcon; /** Preview version of the icon, for the preview popup */ /** * The hint icon to display on the key when keyboard is in manual temporary upper case * mode. */ - public Drawable manualTemporaryUpperCaseHintIcon; + public Drawable mManualTemporaryUpperCaseHintIcon; - public Drawable iconPreview; + public Drawable mPreviewIcon; /** Width of the key, not including the gap */ - public int width; + public int mWidth; /** Height of the key, not including the gap */ - public int height; + public int mHeight; /** The horizontal gap before this key */ - public int gap; + public int mGap; /** Whether this key is sticky, i.e., a toggle key */ - public boolean sticky; + public boolean mSticky; /** X coordinate of the key in the keyboard layout */ - public int x; + public int mX; /** Y coordinate of the key in the keyboard layout */ - public int y; + public int mY; /** The current pressed state of this key */ - public boolean pressed; + public boolean mPressed; /** If this is a sticky key, is it on? */ - public boolean on; + public boolean mOn; /** Text to output when pressed. This can be multiple characters, like ".com" */ - public CharSequence text; + public CharSequence mOutputText; /** Popup characters */ - public CharSequence popupCharacters; + public CharSequence mPopupCharacters; /** * Flags that specify the anchoring to edges of the keyboard for detecting touch events @@ -83,18 +83,18 @@ public class Key { * {@link Keyboard#EDGE_LEFT}, {@link Keyboard#EDGE_RIGHT}, * {@link Keyboard#EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM}. */ - public int edgeFlags; + public int mEdgeFlags; /** Whether this is a modifier key, such as Shift or Alt */ - public boolean modifier; + public boolean mModifier; /** The Keyboard that this key belongs to */ - protected final Keyboard keyboard; + protected final Keyboard mKeyboard; /** * If this key pops up a mini keyboard, this is the resource id for the XML layout for that * keyboard. */ - public int popupResId; + public int mPopupResId; /** Whether this key repeats itself when held down */ - public boolean repeatable; + public boolean mRepeatable; private final static int[] KEY_STATE_NORMAL_ON = { @@ -124,13 +124,24 @@ public class Key { android.R.attr.state_pressed }; + // functional normal state (with properties) + private static final int[] KEY_STATE_FUNCTIONAL_NORMAL = { + android.R.attr.state_single + }; + + // functional pressed state (with properties) + private static final int[] KEY_STATE_FUNCTIONAL_PRESSED = { + android.R.attr.state_single, + android.R.attr.state_pressed + }; + /** Create an empty key with no attributes. */ public Key(Row parent) { - keyboard = parent.parent; - height = parent.defaultHeight; - gap = parent.defaultHorizontalGap; - width = parent.defaultWidth - gap; - edgeFlags = parent.rowEdgeFlags; + mKeyboard = parent.mParent; + mHeight = parent.mDefaultHeight; + mGap = parent.mDefaultHorizontalGap; + mWidth = parent.mDefaultWidth - mGap; + mEdgeFlags = parent.mRowEdgeFlags; } /** Create a key with the given top-left coordinate and extract its attributes from @@ -148,15 +159,15 @@ public class Key { TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.Keyboard); - height = KeyboardParser.getDimensionOrFraction(a, + mHeight = KeyboardParser.getDimensionOrFraction(a, R.styleable.Keyboard_keyHeight, - keyboard.mDisplayHeight, parent.defaultHeight); - gap = KeyboardParser.getDimensionOrFraction(a, + mKeyboard.mDisplayHeight, parent.mDefaultHeight); + mGap = KeyboardParser.getDimensionOrFraction(a, R.styleable.Keyboard_horizontalGap, - keyboard.mDisplayWidth, parent.defaultHorizontalGap); - width = KeyboardParser.getDimensionOrFraction(a, + mKeyboard.mDisplayWidth, parent.mDefaultHorizontalGap); + mWidth = KeyboardParser.getDimensionOrFraction(a, R.styleable.Keyboard_keyWidth, - keyboard.mDisplayWidth, parent.defaultWidth) - gap; + mKeyboard.mDisplayWidth, parent.mDefaultWidth) - mGap; a.recycle(); a = res.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.Keyboard_Key); @@ -172,42 +183,48 @@ public class Key { } // Horizontal gap is divided equally to both sides of the key. - this.x = x + gap / 2; - this.y = y; - - codes = style.getIntArray(a, R.styleable.Keyboard_Key_codes); - iconPreview = style.getDrawable(a, R.styleable.Keyboard_Key_iconPreview); - Keyboard.setDefaultBounds(iconPreview); - popupCharacters = style.getText(a, R.styleable.Keyboard_Key_popupCharacters); - popupResId = style.getResourceId(a, R.styleable.Keyboard_Key_popupKeyboard, 0); - repeatable = style.getBoolean(a, R.styleable.Keyboard_Key_isRepeatable, false); - modifier = style.getBoolean(a, R.styleable.Keyboard_Key_isModifier, false); - sticky = style.getBoolean(a, R.styleable.Keyboard_Key_isSticky, false); - edgeFlags = style.getFlag(a, R.styleable.Keyboard_Key_keyEdgeFlags, 0); - edgeFlags |= parent.rowEdgeFlags; - - icon = style.getDrawable(a, R.styleable.Keyboard_Key_keyIcon); - Keyboard.setDefaultBounds(icon); - hintIcon = style.getDrawable(a, R.styleable.Keyboard_Key_keyHintIcon); - Keyboard.setDefaultBounds(hintIcon); - manualTemporaryUpperCaseHintIcon = style.getDrawable(a, + this.mX = x + mGap / 2; + this.mY = y; + + mCodes = style.getIntArray(a, R.styleable.Keyboard_Key_codes); + mPreviewIcon = style.getDrawable(a, R.styleable.Keyboard_Key_iconPreview); + Keyboard.setDefaultBounds(mPreviewIcon); + mPopupCharacters = style.getText(a, R.styleable.Keyboard_Key_popupCharacters); + mPopupResId = style.getResourceId(a, R.styleable.Keyboard_Key_popupKeyboard, 0); + mRepeatable = style.getBoolean(a, R.styleable.Keyboard_Key_isRepeatable, false); + mModifier = style.getBoolean(a, R.styleable.Keyboard_Key_isModifier, false); + mSticky = style.getBoolean(a, R.styleable.Keyboard_Key_isSticky, false); + mEdgeFlags = style.getFlag(a, R.styleable.Keyboard_Key_keyEdgeFlags, 0); + mEdgeFlags |= parent.mRowEdgeFlags; + + mIcon = style.getDrawable(a, R.styleable.Keyboard_Key_keyIcon); + Keyboard.setDefaultBounds(mIcon); + mHintIcon = style.getDrawable(a, R.styleable.Keyboard_Key_keyHintIcon); + Keyboard.setDefaultBounds(mHintIcon); + mManualTemporaryUpperCaseHintIcon = style.getDrawable(a, R.styleable.Keyboard_Key_manualTemporaryUpperCaseHintIcon); - Keyboard.setDefaultBounds(manualTemporaryUpperCaseHintIcon); + Keyboard.setDefaultBounds(mManualTemporaryUpperCaseHintIcon); - label = style.getText(a, R.styleable.Keyboard_Key_keyLabel); - labelOption = style.getFlag(a, R.styleable.Keyboard_Key_keyLabelOption, 0); - manualTemporaryUpperCaseCode = style.getInt(a, + mLabel = style.getText(a, R.styleable.Keyboard_Key_keyLabel); + mLabelOption = style.getFlag(a, R.styleable.Keyboard_Key_keyLabelOption, 0); + mManualTemporaryUpperCaseCode = style.getInt(a, R.styleable.Keyboard_Key_manualTemporaryUpperCaseCode, 0); - text = style.getText(a, R.styleable.Keyboard_Key_keyOutputText); + mOutputText = style.getText(a, R.styleable.Keyboard_Key_keyOutputText); final Drawable shiftedIcon = style.getDrawable(a, R.styleable.Keyboard_Key_shiftedIcon); + a.recycle(); + if (shiftedIcon != null) - keyboard.getShiftedIcons().put(this, shiftedIcon); + mKeyboard.getShiftedIcons().put(this, shiftedIcon); - if (codes == null && !TextUtils.isEmpty(label)) { - codes = new int[] { label.charAt(0) }; + if (mCodes == null && !TextUtils.isEmpty(mLabel)) { + mCodes = new int[] { mLabel.charAt(0) }; + } + + if (mPopupCharacters == null || mPopupCharacters.length() == 0) { + // If there is a keyboard with no keys specified in popupCharacters + mPopupResId = 0; } - a.recycle(); } /** @@ -216,7 +233,7 @@ public class Key { * @see #onReleased(boolean) */ public void onPressed() { - pressed = !pressed; + mPressed = !mPressed; } /** @@ -226,10 +243,9 @@ public class Key { * @see #onPressed() */ public void onReleased(boolean inside) { - pressed = !pressed; - if (sticky) { - on = !on; - } + mPressed = !mPressed; + if (mSticky && !mKeyboard.isShiftLockEnabled(this)) + mOn = !mOn; } /** @@ -241,14 +257,14 @@ public class Key { * inside the key. */ public boolean isInside(int x, int y) { - boolean leftEdge = (edgeFlags & Keyboard.EDGE_LEFT) > 0; - boolean rightEdge = (edgeFlags & Keyboard.EDGE_RIGHT) > 0; - boolean topEdge = (edgeFlags & Keyboard.EDGE_TOP) > 0; - boolean bottomEdge = (edgeFlags & Keyboard.EDGE_BOTTOM) > 0; - if ((x >= this.x || (leftEdge && x <= this.x + this.width)) - && (x < this.x + this.width || (rightEdge && x >= this.x)) - && (y >= this.y || (topEdge && y <= this.y + this.height)) - && (y < this.y + this.height || (bottomEdge && y >= this.y))) { + boolean leftEdge = (mEdgeFlags & Keyboard.EDGE_LEFT) > 0; + boolean rightEdge = (mEdgeFlags & Keyboard.EDGE_RIGHT) > 0; + boolean topEdge = (mEdgeFlags & Keyboard.EDGE_TOP) > 0; + boolean bottomEdge = (mEdgeFlags & Keyboard.EDGE_BOTTOM) > 0; + if ((x >= this.mX || (leftEdge && x <= this.mX + this.mWidth)) + && (x < this.mX + this.mWidth || (rightEdge && x >= this.mX)) + && (y >= this.mY || (topEdge && y <= this.mY + this.mHeight)) + && (y < this.mY + this.mHeight || (bottomEdge && y >= this.mY))) { return true; } else { return false; @@ -262,10 +278,10 @@ public class Key { * @return the square of the distance of the point from the nearest edge of the key */ public int squaredDistanceToEdge(int x, int y) { - final int left = this.x; - final int right = left + this.width; - final int top = this.y; - final int bottom = top + this.height; + final int left = this.mX; + final int right = left + this.mWidth; + final int top = this.mY; + final int bottom = top + this.mHeight; final int edgeX = x < left ? left : (x > right ? right : x); final int edgeY = y < top ? top : (y > bottom ? bottom : y); final int dx = x - edgeX; @@ -273,29 +289,43 @@ public class Key { return dx * dx + dy * dy; } + // sticky is used for shift key. If a key is not sticky and is modifier, + // the key will be treated as functional. + private boolean isFunctionalKey() { + return !mSticky && mModifier; + } + /** * Returns the drawable state for the key, based on the current state and type of the key. * @return the drawable state of the key. * @see android.graphics.drawable.StateListDrawable#setState(int[]) */ public int[] getCurrentDrawableState() { + if (isFunctionalKey()) { + if (mPressed) { + return KEY_STATE_FUNCTIONAL_PRESSED; + } else { + return KEY_STATE_FUNCTIONAL_NORMAL; + } + } + int[] states = KEY_STATE_NORMAL; - if (on) { - if (pressed) { + if (mOn) { + if (mPressed) { states = KEY_STATE_PRESSED_ON; } else { states = KEY_STATE_NORMAL_ON; } } else { - if (sticky) { - if (pressed) { + if (mSticky) { + if (mPressed) { states = KEY_STATE_PRESSED_OFF; } else { states = KEY_STATE_NORMAL_OFF; } } else { - if (pressed) { + if (mPressed) { states = KEY_STATE_PRESSED; } } diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index b75415579..869d13067 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -29,6 +29,7 @@ import android.util.Log; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; @@ -51,20 +52,32 @@ import java.util.Map; * */ public class Keyboard { - - static final String TAG = "Keyboard"; + private static final String TAG = "Keyboard"; public static final int EDGE_LEFT = 0x01; public static final int EDGE_RIGHT = 0x02; public static final int EDGE_TOP = 0x04; public static final int EDGE_BOTTOM = 0x08; - public static final int KEYCODE_SHIFT = -1; - public static final int KEYCODE_MODE_CHANGE = -2; - public static final int KEYCODE_CANCEL = -3; - public static final int KEYCODE_DONE = -4; - public static final int KEYCODE_DELETE = -5; - public static final int KEYCODE_ALT = -6; + public static final int CODE_ENTER = '\n'; + public static final int CODE_TAB = '\t'; + public static final int CODE_SPACE = ' '; + public static final int CODE_PERIOD = '.'; + + public static final int CODE_SHIFT = -1; + public static final int CODE_MODE_CHANGE = -2; + public static final int CODE_CANCEL = -3; + public static final int CODE_DONE = -4; + public static final int CODE_DELETE = -5; + public static final int CODE_ALT = -6; + + public static final int CODE_OPTIONS = -100; + public static final int CODE_OPTIONS_LONGPRESS = -101; + public static final int CODE_CAPSLOCK = -103; + public static final int CODE_NEXT_LANGUAGE = -104; + public static final int CODE_PREV_LANGUAGE = -105; + // TODO: remove this once LatinIME stops referring to this. + public static final int CODE_VOICE = -109; /** Horizontal gap default for all rows */ int mDefaultHorizontalGap; @@ -78,14 +91,17 @@ public class Keyboard { /** Default gap between rows */ int mDefaultVerticalGap; - /** Is the keyboard in the shifted state */ - private boolean mShifted; - - /** List of shift keys in this keyboard */ + /** List of shift keys in this keyboard and its icons and state */ private final List mShiftKeys = new ArrayList(); - - /** List of shift keys and its shifted state icon */ private final HashMap mShiftedIcons = new HashMap(); + private final HashMap mNormalShiftIcons = new HashMap(); + private final HashSet mShiftLockEnabled = new HashSet(); + private final KeyboardShiftState mShiftState = new KeyboardShiftState(); + + /** Space key and its icons */ + protected Key mSpaceKey; + protected Drawable mSpaceIcon; + protected Drawable mSpacePreviewIcon; /** Total height of the keyboard, including the padding and keys */ private int mTotalHeight; @@ -191,11 +207,11 @@ public class Keyboard { mTotalWidth = 0; Row row = new Row(this); - row.defaultHeight = mDefaultHeight; - row.defaultWidth = mDefaultWidth; - row.defaultHorizontalGap = mDefaultHorizontalGap; - row.verticalGap = mDefaultVerticalGap; - row.rowEdgeFlags = EDGE_TOP | EDGE_BOTTOM; + row.mDefaultHeight = mDefaultHeight; + row.mDefaultWidth = mDefaultWidth; + row.mDefaultHorizontalGap = mDefaultHorizontalGap; + row.mVerticalGap = mDefaultVerticalGap; + row.mRowEdgeFlags = EDGE_TOP | EDGE_BOTTOM; final int maxColumns = columns == -1 ? Integer.MAX_VALUE : columns; for (int i = 0; i < characters.length(); i++) { char c = characters.charAt(i); @@ -207,12 +223,12 @@ public class Keyboard { } final Key key = new Key(row); // Horizontal gap is divided equally to both sides of the key. - key.x = x + key.gap / 2; - key.y = y; - key.label = String.valueOf(c); - key.codes = new int[] { c }; + key.mX = x + key.mGap / 2; + key.mY = y; + key.mLabel = String.valueOf(c); + key.mCodes = new int[] { c }; column++; - x += key.width + key.gap; + x += key.mWidth + key.mGap; mKeys.add(key); if (x > mTotalWidth) { mTotalWidth = x; @@ -283,27 +299,88 @@ public class Keyboard { return mDisplayWidth; } - public boolean setShifted(boolean shiftState) { - for (final Key key : mShiftKeys) { - key.on = shiftState; + public List getShiftKeys() { + return mShiftKeys; + } + + public Map getShiftedIcons() { + return mShiftedIcons; + } + + public void enableShiftLock() { + for (final Key key : getShiftKeys()) { + mShiftLockEnabled.add(key); + mNormalShiftIcons.put(key, key.mIcon); } - if (mShifted != shiftState) { - mShifted = shiftState; - return true; + } + + public boolean isShiftLockEnabled(Key key) { + return mShiftLockEnabled.contains(key); + } + + public boolean setShiftLocked(boolean newShiftLockState) { + final Map shiftedIcons = getShiftedIcons(); + for (final Key key : getShiftKeys()) { + key.mOn = newShiftLockState; + key.mIcon = newShiftLockState ? shiftedIcons.get(key) : mNormalShiftIcons.get(key); + } + mShiftState.setShiftLocked(newShiftLockState); + return true; + } + + public boolean isShiftLocked() { + return mShiftState.isShiftLocked(); + } + + public boolean setShifted(boolean newShiftState) { + final Map shiftedIcons = getShiftedIcons(); + for (final Key key : getShiftKeys()) { + if (!newShiftState && !mShiftState.isShiftLocked()) { + key.mIcon = mNormalShiftIcons.get(key); + } else if (newShiftState && !mShiftState.isShiftedOrShiftLocked()) { + key.mIcon = shiftedIcons.get(key); + } } - return false; + return mShiftState.setShifted(newShiftState); } public boolean isShiftedOrShiftLocked() { - return mShifted; + return mShiftState.isShiftedOrShiftLocked(); } - public List getShiftKeys() { - return mShiftKeys; + public void setAutomaticTemporaryUpperCase() { + setShifted(true); + mShiftState.setAutomaticTemporaryUpperCase(); } - public Map getShiftedIcons() { - return mShiftedIcons; + public boolean isAutomaticTemporaryUpperCase() { + return isAlphaKeyboard() && mShiftState.isAutomaticTemporaryUpperCase(); + } + + public boolean isManualTemporaryUpperCase() { + return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCase(); + } + + public KeyboardShiftState getKeyboardShiftState() { + return mShiftState; + } + + public boolean isAlphaKeyboard() { + return mId.isAlphabetKeyboard(); + } + + public boolean isPhoneKeyboard() { + return mId.isPhoneKeyboard(); + } + + public boolean isNumberKeyboard() { + return mId.isNumberKeyboard(); + } + + public void setSpaceKey(Key space) { + mSpaceKey = space; + mSpaceIcon = space.mIcon; + mSpacePreviewIcon = space.mPreviewIcon; } private void computeNearestNeighbors() { diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java index 289e4c0e8..883d2175c 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java @@ -83,10 +83,18 @@ public class KeyboardId { return mXmlId; } - public boolean isAlphabetMode() { + public boolean isAlphabetKeyboard() { return mXmlId == R.xml.kbd_qwerty; } + public boolean isPhoneKeyboard() { + return mMode == MODE_PHONE; + } + + public boolean isNumberKeyboard() { + return mMode == MODE_NUMBER; + } + @Override public boolean equals(Object other) { return other instanceof KeyboardId && equals((KeyboardId) other); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardParser.java b/java/src/com/android/inputmethod/keyboard/KeyboardParser.java index 2147ee289..dd80f0ed0 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardParser.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardParser.java @@ -264,8 +264,10 @@ public class KeyboardParser { mKeyStyles); checkEndTag(TAG_KEY, parser); keys.add(key); - if (key.codes[0] == Keyboard.KEYCODE_SHIFT) + if (key.mCodes[0] == Keyboard.CODE_SHIFT) mKeyboard.getShiftKeys().add(key); + if (key.mCodes[0] == Keyboard.CODE_SPACE) + mKeyboard.setSpaceKey(key); endKey(key); } } @@ -492,12 +494,12 @@ public class KeyboardParser { private void endRow() { if (mCurrentRow == null) throw new InflateException("orphant end row tag"); - mCurrentY += mCurrentRow.verticalGap + mCurrentRow.defaultHeight; + mCurrentY += mCurrentRow.mVerticalGap + mCurrentRow.mDefaultHeight; mCurrentRow = null; } private void endKey(Key key) { - mCurrentX += key.gap + key.width; + mCurrentX += key.mGap + key.mWidth; if (mCurrentX > mMaxRowWidth) mMaxRowWidth = mCurrentX; } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardShiftState.java b/java/src/com/android/inputmethod/keyboard/KeyboardShiftState.java new file mode 100644 index 000000000..3e1eaf44e --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/KeyboardShiftState.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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; + +import android.util.Log; + +public class KeyboardShiftState { + private static final String TAG = "KeyboardShiftState"; + 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(" + newShiftState + "): " + 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(" + newShiftLockState + "): " + 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"; + } + } +} diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java new file mode 100644 index 000000000..d3302fd6f --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -0,0 +1,646 @@ +/* + * Copyright (C) 2008 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; + +import com.android.inputmethod.latin.LatinIME; +import com.android.inputmethod.latin.LatinIMESettings; +import com.android.inputmethod.latin.LatinIMEUtil; +import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.SubtypeSwitcher; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.util.Log; +import android.view.InflateException; +import android.view.inputmethod.InputMethodManager; + +import java.lang.ref.SoftReference; +import java.util.HashMap; +import java.util.Locale; + +public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener { + private static final String TAG = "KeyboardSwitcher"; + private static final boolean DEBUG = false; + public static final boolean DEBUG_STATE = false; + + // Changing DEFAULT_LAYOUT_ID also requires prefs_for_debug.xml to be matched with. + public static final String DEFAULT_LAYOUT_ID = "5"; + public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902"; + private static final int[] THEMES = new int [] { + R.layout.input_basic, + R.layout.input_basic_highcontrast, + R.layout.input_stone_normal, + R.layout.input_stone_bold, + R.layout.input_gingerbread, + R.layout.input_honeycomb, // DEFAULT_LAYOUT_ID + }; + + 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 SubtypeSwitcher mSubtypeSwitcher; + private SharedPreferences mPrefs; + + private LatinKeyboardView mInputView; + private LatinIME mInputMethodService; + + private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift"); + private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol"); + + private KeyboardId mSymbolsId; + private KeyboardId mSymbolsShiftedId; + + private KeyboardId mCurrentId; + private final HashMap> mKeyboardCache = + new HashMap>(); + + private int mMode = KeyboardId.MODE_TEXT; /* default value */ + private int mImeOptions; + private boolean mIsSymbols; + /** mIsAutoCompletionActive indicates that auto completed word will be input instead of + * what user actually typed. */ + private boolean mIsAutoCompletionActive; + private boolean mVoiceKeyEnabled; + private boolean mVoiceButtonOnPrimary; + private int mSymbolsModeState = SYMBOLS_MODE_STATE_NONE; + + // Indicates whether or not we have the settings key + private boolean mHasSettingsKey; + private static final int SETTINGS_KEY_MODE_AUTO = R.string.settings_key_mode_auto; + private static final int SETTINGS_KEY_MODE_ALWAYS_SHOW = + R.string.settings_key_mode_always_show; + // NOTE: No need to have SETTINGS_KEY_MODE_ALWAYS_HIDE here because it's not being referred to + // in the source code now. + // Default is SETTINGS_KEY_MODE_AUTO. + private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO; + + private int mLayoutId; + + private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); + + public static KeyboardSwitcher getInstance() { + return sInstance; + } + + private KeyboardSwitcher() { + } + + public static void init(LatinIME ims, SharedPreferences prefs) { + sInstance.mInputMethodService = ims; + sInstance.mPrefs = prefs; + sInstance.mSubtypeSwitcher = SubtypeSwitcher.getInstance(); + + sInstance.mLayoutId = Integer.valueOf( + prefs.getString(PREF_KEYBOARD_LAYOUT, DEFAULT_LAYOUT_ID)); + prefs.registerOnSharedPreferenceChangeListener(sInstance); + } + + private void makeSymbolsKeyboardIds() { + final Locale locale = mSubtypeSwitcher.getInputLocale(); + final int orientation = mInputMethodService.getResources().getConfiguration().orientation; + final int mode = mMode; + final int colorScheme = getColorScheme(); + final boolean hasSettingsKey = mHasSettingsKey; + final boolean voiceKeyEnabled = mVoiceKeyEnabled; + final boolean hasVoiceKey = voiceKeyEnabled && !mVoiceButtonOnPrimary; + final int imeOptions = mImeOptions; + // Note: This comment is only applied for phone number keyboard layout. + // On non-xlarge device, "@integer/key_switch_alpha_symbol" key code is used to switch + // between "phone keyboard" and "phone symbols keyboard". But on xlarge device, + // "@integer/key_shift" key code is used for that purpose in order to properly display + // "more" and "locked more" key labels. To achieve these behavior, we should initialize + // mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard" + // respectively here for xlarge device's layout switching. + mSymbolsId = new KeyboardId(locale, orientation, mode, + mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone : R.xml.kbd_symbols, + colorScheme, hasSettingsKey, voiceKeyEnabled, hasVoiceKey, imeOptions, true); + mSymbolsShiftedId = new KeyboardId(locale, orientation, mode, + mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone_symbols : R.xml.kbd_symbols_shift, + colorScheme, hasSettingsKey, voiceKeyEnabled, hasVoiceKey, imeOptions, true); + } + + private boolean hasVoiceKey(boolean isSymbols) { + return mVoiceKeyEnabled && (isSymbols != mVoiceButtonOnPrimary); + } + + public void loadKeyboard(int mode, int imeOptions, boolean voiceKeyEnabled, + boolean voiceButtonOnPrimary) { + mSymbolsModeState = SYMBOLS_MODE_STATE_NONE; + try { + loadKeyboardInternal(mode, imeOptions, voiceKeyEnabled, voiceButtonOnPrimary, + false); + } catch (RuntimeException e) { + Log.w(TAG, e); + LatinImeLogger.logOnException(mode + "," + imeOptions, e); + } + } + + private void loadKeyboardInternal(int mode, int imeOptions, boolean voiceButtonEnabled, + boolean voiceButtonOnPrimary, boolean isSymbols) { + if (mInputView == null) return; + mInputView.setPreviewEnabled(mInputMethodService.getPopupOn()); + + mMode = mode; + mImeOptions = imeOptions; + mVoiceKeyEnabled = voiceButtonEnabled; + mVoiceButtonOnPrimary = voiceButtonOnPrimary; + mIsSymbols = isSymbols; + // Update the settings key state because number of enabled IMEs could have been changed + mHasSettingsKey = getSettingsKeyMode(mPrefs, mInputMethodService); + makeSymbolsKeyboardIds(); + + KeyboardId id = getKeyboardId(mode, imeOptions, isSymbols); + LatinKeyboard keyboard = getKeyboard(id); + + mCurrentId = id; + mInputView.setKeyboard(keyboard); + } + + private LatinKeyboard getKeyboard(KeyboardId id) { + final SoftReference ref = mKeyboardCache.get(id); + LatinKeyboard keyboard = (ref == null) ? null : ref.get(); + if (keyboard == null) { + final Locale savedLocale = mSubtypeSwitcher.changeSystemLocale( + mSubtypeSwitcher.getInputLocale()); + + keyboard = new LatinKeyboard(mInputMethodService, id); + + if (id.mEnableShiftLock) { + keyboard.enableShiftLock(); + } + + mKeyboardCache.put(id, new SoftReference(keyboard)); + if (DEBUG) + Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": " + + ((ref == null) ? "LOAD" : "GCed") + " id=" + id); + + mSubtypeSwitcher.changeSystemLocale(savedLocale); + } else if (DEBUG) { + Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id); + } + + keyboard.onAutoCompletionStateChanged(mIsAutoCompletionActive); + keyboard.setShifted(false); + return keyboard; + } + + private KeyboardId getKeyboardId(int mode, int imeOptions, boolean isSymbols) { + final boolean hasVoiceKey = hasVoiceKey(isSymbols); + final int charColorId = getColorScheme(); + final int xmlId; + final boolean enableShiftLock; + + if (isSymbols) { + if (mode == KeyboardId.MODE_PHONE) { + xmlId = R.xml.kbd_phone_symbols; + } else if (mode == KeyboardId.MODE_NUMBER) { + // Note: MODE_NUMBER keyboard layout has no "switch alpha symbol" key. + xmlId = R.xml.kbd_number; + } else { + xmlId = R.xml.kbd_symbols; + } + enableShiftLock = false; + } else { + if (mode == KeyboardId.MODE_PHONE) { + xmlId = R.xml.kbd_phone; + enableShiftLock = false; + } else if (mode == KeyboardId.MODE_NUMBER) { + xmlId = R.xml.kbd_number; + enableShiftLock = false; + } else { + xmlId = R.xml.kbd_qwerty; + enableShiftLock = true; + } + } + final int orientation = mInputMethodService.getResources().getConfiguration().orientation; + final Locale locale = mSubtypeSwitcher.getInputLocale(); + return new KeyboardId(locale, orientation, mode, xmlId, charColorId, + mHasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, imeOptions, enableShiftLock); + } + + public int getKeyboardMode() { + return mMode; + } + + public boolean isAlphabetMode() { + return mCurrentId != null && mCurrentId.isAlphabetKeyboard(); + } + + public boolean isInputViewShown() { + return mInputView != null && mInputView.isShown(); + } + + public boolean isKeyboardAvailable() { + if (mInputView != null) + return mInputView.getLatinKeyboard() != null; + return false; + } + + private LatinKeyboard getLatinKeyboard() { + if (mInputView != null) + return mInputView.getLatinKeyboard(); + return null; + } + + public void setPreferredLetters(int[] frequencies) { + LatinKeyboard latinKeyboard = getLatinKeyboard(); + if (latinKeyboard != null) + latinKeyboard.setPreferredLetters(frequencies); + } + + public void keyReleased() { + LatinKeyboard latinKeyboard = getLatinKeyboard(); + if (latinKeyboard != null) + latinKeyboard.keyReleased(); + } + + public boolean isShiftedOrShiftLocked() { + LatinKeyboard latinKeyboard = getLatinKeyboard(); + if (latinKeyboard != null) + return latinKeyboard.isShiftedOrShiftLocked(); + return false; + } + + public boolean isShiftLocked() { + LatinKeyboard latinKeyboard = getLatinKeyboard(); + if (latinKeyboard != null) + return latinKeyboard.isShiftLocked(); + return false; + } + + 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(); + if (latinKeyboard != null) { + // On non-distinct multi touch panel device, we should also turn off the shift locked + // state when shift key is pressed to go to normal mode. + // On the other hand, on distinct multi touch panel device, turning off the shift locked + // state with shift key pressing is handled by onReleaseShift(). + if (!hasDistinctMultitouch() && !shifted && latinKeyboard.isShiftLocked()) { + latinKeyboard.setShiftLocked(false); + } + if (latinKeyboard.setShifted(shifted)) { + mInputView.invalidateAllKeys(); + } + } + } + + private void setShiftLocked(boolean shiftLocked) { + LatinKeyboard latinKeyboard = getLatinKeyboard(); + if (latinKeyboard != null && latinKeyboard.setShiftLocked(shiftLocked)) { + mInputView.invalidateAllKeys(); + } + } + + /** + * Toggle keyboard shift state triggered by user touch event. + */ + public void toggleShift() { + mInputMethodService.mHandler.cancelUpdateShiftState(); + if (DEBUG_STATE) + Log.d(TAG, "toggleShift:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + mShiftKeyState); + if (isAlphabetMode()) { + setManualTemporaryUpperCase(!isShiftedOrShiftLocked()); + } else { + toggleShiftInSymbol(); + } + } + + public void toggleCapsLock() { + mInputMethodService.mHandler.cancelUpdateShiftState(); + if (DEBUG_STATE) + Log.d(TAG, "toggleCapsLock:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + mShiftKeyState); + if (isAlphabetMode()) { + if (isShiftLocked()) { + // Shift key is long pressed while caps lock state, we will toggle back to normal + // state. And mark as if shift key is released. + setShiftLocked(false); + mShiftKeyState.onRelease(); + } else { + setShiftLocked(true); + } + } + } + + private void setAutomaticTemporaryUpperCase() { + LatinKeyboard latinKeyboard = getLatinKeyboard(); + if (latinKeyboard != null) { + latinKeyboard.setAutomaticTemporaryUpperCase(); + mInputView.invalidateAllKeys(); + } + } + + /** + * Update keyboard shift state triggered by connected EditText status change. + */ + public void updateShiftState() { + final ShiftKeyState shiftKeyState = mShiftKeyState; + if (DEBUG_STATE) + Log.d(TAG, "updateShiftState:" + + " autoCaps=" + mInputMethodService.getCurrentAutoCapsState() + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + shiftKeyState); + if (isAlphabetMode()) { + if (!isShiftLocked() && !shiftKeyState.isIgnoring()) { + if (shiftKeyState.isReleasing() && mInputMethodService.getCurrentAutoCapsState()) { + // Only when shift key is releasing, automatic temporary upper case will be set. + setAutomaticTemporaryUpperCase(); + } else { + setManualTemporaryUpperCase(shiftKeyState.isMomentary()); + } + } + } else { + // In symbol keyboard mode, we should clear shift key state because only alphabet + // keyboard has shift key. + shiftKeyState.onRelease(); + } + } + + public void changeKeyboardMode() { + if (DEBUG_STATE) + Log.d(TAG, "changeKeyboardMode:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + mShiftKeyState); + toggleKeyboardMode(); + if (isShiftLocked() && isAlphabetMode()) + setShiftLocked(true); + updateShiftState(); + } + + public void onPressShift() { + if (!isKeyboardAvailable()) + return; + ShiftKeyState shiftKeyState = mShiftKeyState; + if (DEBUG_STATE) + Log.d(TAG, "onPressShift:" + + " 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. + shiftKeyState.onPress(); + setManualTemporaryUpperCase(true); + } else if (isAutomaticTemporaryUpperCase()) { + // Shift key is pressed while automatic temporary upper case, we have to move to + // manual temporary upper case. + shiftKeyState.onPress(); + setManualTemporaryUpperCase(true); + } else if (isShiftedOrShiftLocked()) { + // In manual upper case state, we just record shift key has been pressing while + // shifted state. + shiftKeyState.onPressOnShifted(); + } else { + // In base layout, chording or manual temporary upper case mode is started. + shiftKeyState.onPress(); + toggleShift(); + } + } else { + // In symbol mode, just toggle symbol and symbol more keyboard. + shiftKeyState.onPress(); + toggleShift(); + } + } + + public void onReleaseShift() { + if (!isKeyboardAvailable()) + return; + ShiftKeyState shiftKeyState = mShiftKeyState; + if (DEBUG_STATE) + Log.d(TAG, "onReleaseShift:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + shiftKeyState); + if (isAlphabetMode()) { + if (shiftKeyState.isMomentary()) { + // After chording input while normal state. + toggleShift(); + } else if (isShiftLocked() && !shiftKeyState.isIgnoring()) { + // 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(); + } + } + shiftKeyState.onRelease(); + } + + public void onPressSymbol() { + if (DEBUG_STATE) + Log.d(TAG, "onReleaseShift:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " symbolKeyState=" + mSymbolKeyState); + changeKeyboardMode(); + mSymbolKeyState.onPress(); + } + + public void onReleaseSymbol() { + if (DEBUG_STATE) + Log.d(TAG, "onReleaseShift:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " symbolKeyState=" + mSymbolKeyState); + if (mSymbolKeyState.isMomentary()) + changeKeyboardMode(); + mSymbolKeyState.onRelease(); + } + + public void onOtherKeyPressed() { + if (DEBUG_STATE) + Log.d(TAG, "onOtherKeyPressed:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + mShiftKeyState + + " symbolKeyState=" + mSymbolKeyState); + mShiftKeyState.onOtherKeyPressed(); + mSymbolKeyState.onOtherKeyPressed(); + } + + private void toggleShiftInSymbol() { + if (isAlphabetMode()) + return; + final LatinKeyboard keyboard; + if (mCurrentId.equals(mSymbolsId) || !mCurrentId.equals(mSymbolsShiftedId)) { + mCurrentId = mSymbolsShiftedId; + keyboard = getKeyboard(mCurrentId); + // Symbol shifted keyboard has an ALT key that has a caps lock style indicator. To + // enable the indicator, we need to call enableShiftLock() and setShiftLocked(true). + // Thus we can keep the ALT key's Key.on value true while LatinKey.onRelease() is + // called. + keyboard.setShiftLocked(true); + } else { + mCurrentId = mSymbolsId; + keyboard = getKeyboard(mCurrentId); + // Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the + // indicator, we need to call enableShiftLock() and setShiftLocked(false). + keyboard.setShifted(false); + } + mInputView.setKeyboard(keyboard); + } + + private void toggleKeyboardMode() { + loadKeyboardInternal(mMode, mImeOptions, mVoiceKeyEnabled, mVoiceButtonOnPrimary, + !mIsSymbols); + if (mIsSymbols) { + mSymbolsModeState = SYMBOLS_MODE_STATE_BEGIN; + } else { + mSymbolsModeState = SYMBOLS_MODE_STATE_NONE; + } + } + + public boolean hasDistinctMultitouch() { + return mInputView != null && mInputView.hasDistinctMultitouch(); + } + + /** + * Updates state machine to figure out when to automatically switch back to alpha mode. + */ + public void onKey(int key) { + // Switch back to alpha mode if user types one or more non-space/enter + // characters followed by a space/enter + switch (mSymbolsModeState) { + case SYMBOLS_MODE_STATE_BEGIN: + if (key != Keyboard.CODE_SPACE && key != Keyboard.CODE_ENTER && key > 0) { + mSymbolsModeState = SYMBOLS_MODE_STATE_SYMBOL; + } + break; + case SYMBOLS_MODE_STATE_SYMBOL: + if (key == Keyboard.CODE_ENTER || key == Keyboard.CODE_SPACE) { + changeKeyboardMode(); + } + break; + } + } + + public LatinKeyboardView getInputView() { + return mInputView; + } + + public LatinKeyboardView onCreateInputView() { + createInputViewInternal(mLayoutId, true); + return mInputView; + } + + private void createInputViewInternal(int newLayout, boolean forceReset) { + if (mLayoutId != newLayout || mInputView == null || forceReset) { + if (mInputView != null) { + mInputView.closing(); + } + if (THEMES.length <= newLayout) { + newLayout = Integer.valueOf(DEFAULT_LAYOUT_ID); + } + + LatinIMEUtil.GCUtils.getInstance().reset(); + boolean tryGC = true; + for (int i = 0; i < LatinIMEUtil.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { + try { + mInputView = (LatinKeyboardView) mInputMethodService.getLayoutInflater( + ).inflate(THEMES[newLayout], null); + tryGC = false; + } catch (OutOfMemoryError e) { + Log.w(TAG, "load keyboard failed: " + e); + tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait( + mLayoutId + "," + newLayout, e); + } catch (InflateException e) { + Log.w(TAG, "load keyboard failed: " + e); + tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait( + mLayoutId + "," + newLayout, e); + } + } + mInputView.setOnKeyboardActionListener(mInputMethodService); + mLayoutId = newLayout; + } + } + + private void postSetInputView() { + mInputMethodService.mHandler.post(new Runnable() { + @Override + public void run() { + if (mInputView != null) { + mInputMethodService.setInputView(mInputView); + } + mInputMethodService.updateInputViewShown(); + } + }); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (PREF_KEYBOARD_LAYOUT.equals(key)) { + final int layoutId = Integer.valueOf( + sharedPreferences.getString(key, DEFAULT_LAYOUT_ID)); + createInputViewInternal(layoutId, false); + postSetInputView(); + } else if (LatinIMESettings.PREF_SETTINGS_KEY.equals(key)) { + mHasSettingsKey = getSettingsKeyMode(sharedPreferences, mInputMethodService); + createInputViewInternal(mLayoutId, true); + postSetInputView(); + } + } + + private int getColorScheme() { + return (mInputView != null) + ? mInputView.getColorScheme() : KeyboardView.COLOR_SCHEME_WHITE; + } + + public void onAutoCompletionStateChanged(boolean isAutoCompletion) { + if (isAutoCompletion != mIsAutoCompletionActive) { + LatinKeyboardView keyboardView = getInputView(); + mIsAutoCompletionActive = isAutoCompletion; + keyboardView.invalidateKey(((LatinKeyboard) keyboardView.getKeyboard()) + .onAutoCompletionStateChanged(isAutoCompletion)); + } + } + + private static boolean getSettingsKeyMode(SharedPreferences prefs, Context context) { + Resources resources = context.getResources(); + final boolean showSettingsKeyOption = resources.getBoolean( + R.bool.config_enable_show_settings_key_option); + if (showSettingsKeyOption) { + final String settingsKeyMode = prefs.getString(LatinIMESettings.PREF_SETTINGS_KEY, + resources.getString(DEFAULT_SETTINGS_KEY_MODE)); + // We show the settings key when 1) SETTINGS_KEY_MODE_ALWAYS_SHOW or + // 2) SETTINGS_KEY_MODE_AUTO and there are two or more enabled IMEs on the system + if (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_ALWAYS_SHOW)) + || (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_AUTO)) + && LatinIMEUtil.hasMultipleEnabledIMEsOrSubtypes( + ((InputMethodManager) context.getSystemService( + Context.INPUT_METHOD_SERVICE))))) { + return true; + } + } + return false; + } +} diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index ae6d09716..5fecb3000 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -58,8 +58,6 @@ import java.util.WeakHashMap; * A view that renders a virtual {@link Keyboard}. It handles rendering of keys and detecting key * presses and touch movements. * - * TODO: References to LatinKeyboard in this class should be replaced with ones to its base class. - * * @attr ref R.styleable#KeyboardView_keyBackground * @attr ref R.styleable#KeyboardView_keyPreviewLayout * @attr ref R.styleable#KeyboardView_keyPreviewOffset @@ -592,7 +590,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { int maxCount = 0; int mostCommonWidth = 0; for (Key key : keys) { - final Integer width = key.width + key.gap; + final Integer width = key.mWidth + key.mGap; Integer count = histogram.get(width); if (count == null) count = 0; @@ -648,17 +646,16 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { final int kbdPaddingTop = getPaddingTop(); final Key[] keys = mKeys; final Key invalidKey = mInvalidatedKey; - final boolean isManualTemporaryUpperCase = (mKeyboard instanceof LatinKeyboard - && ((LatinKeyboard)mKeyboard).isManualTemporaryUpperCase()); + final boolean isManualTemporaryUpperCase = mKeyboard.isManualTemporaryUpperCase(); boolean drawSingleKey = false; if (invalidKey != null && canvas.getClipBounds(clipRegion)) { // TODO we should use Rect.inset and Rect.contains here. // Is clipRegion completely contained within the invalidated key? - if (invalidKey.x + kbdPaddingLeft - 1 <= clipRegion.left && - invalidKey.y + kbdPaddingTop - 1 <= clipRegion.top && - invalidKey.x + invalidKey.width + kbdPaddingLeft + 1 >= clipRegion.right && - invalidKey.y + invalidKey.height + kbdPaddingTop + 1 >= clipRegion.bottom) { + if (invalidKey.mX + kbdPaddingLeft - 1 <= clipRegion.left && + invalidKey.mY + kbdPaddingTop - 1 <= clipRegion.top && + invalidKey.mX + invalidKey.mWidth + kbdPaddingLeft + 1 >= clipRegion.right && + invalidKey.mY + invalidKey.mHeight + kbdPaddingTop + 1 >= clipRegion.bottom) { drawSingleKey = true; } } @@ -673,16 +670,16 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { keyBackground.setState(drawableState); // Switch the character to uppercase if shift is pressed - String label = key.label == null? null : adjustCase(key.label).toString(); + String label = key.mLabel == null? null : adjustCase(key.mLabel).toString(); final Rect bounds = keyBackground.getBounds(); - if (key.width != bounds.right || key.height != bounds.bottom) { - keyBackground.setBounds(0, 0, key.width, key.height); + if (key.mWidth != bounds.right || key.mHeight != bounds.bottom) { + keyBackground.setBounds(0, 0, key.mWidth, key.mHeight); } - canvas.translate(key.x + kbdPaddingLeft, key.y + kbdPaddingTop); + canvas.translate(key.mX + kbdPaddingLeft, key.mY + kbdPaddingTop); keyBackground.draw(canvas); - final int rowHeight = padding.top + key.height; + final int rowHeight = padding.top + key.mHeight; // Draw key label if (label != null) { // For characters, use large font. For labels like "Done", use small font. @@ -691,36 +688,36 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { // Vertical label text alignment. final float baseline; - if ((key.labelOption & KEY_LABEL_OPTION_ALIGN_BOTTOM) != 0) { - baseline = key.height - + if ((key.mLabelOption & KEY_LABEL_OPTION_ALIGN_BOTTOM) != 0) { + baseline = key.mHeight - + labelCharHeight * KEY_LABEL_VERTICAL_PADDING_FACTOR; if (DEBUG_SHOW_ALIGN) - drawHorizontalLine(canvas, (int)baseline, key.width, 0xc0008000, + drawHorizontalLine(canvas, (int)baseline, key.mWidth, 0xc0008000, new Paint()); } else { // Align center - final float centerY = (key.height + padding.top - padding.bottom) / 2; + final float centerY = (key.mHeight + padding.top - padding.bottom) / 2; baseline = centerY + labelCharHeight * KEY_LABEL_VERTICAL_ADJUSTMENT_FACTOR_CENTER; } // Horizontal label text alignment final int positionX; - if ((key.labelOption & KEY_LABEL_OPTION_ALIGN_LEFT) != 0) { + if ((key.mLabelOption & KEY_LABEL_OPTION_ALIGN_LEFT) != 0) { positionX = mKeyLabelHorizontalPadding + padding.left; paint.setTextAlign(Align.LEFT); if (DEBUG_SHOW_ALIGN) drawVerticalLine(canvas, positionX, rowHeight, 0xc0800080, new Paint()); - } else if ((key.labelOption & KEY_LABEL_OPTION_ALIGN_RIGHT) != 0) { - positionX = key.width - mKeyLabelHorizontalPadding - padding.right; + } else if ((key.mLabelOption & KEY_LABEL_OPTION_ALIGN_RIGHT) != 0) { + positionX = key.mWidth - mKeyLabelHorizontalPadding - padding.right; paint.setTextAlign(Align.RIGHT); if (DEBUG_SHOW_ALIGN) drawVerticalLine(canvas, positionX, rowHeight, 0xc0808000, new Paint()); } else { - positionX = (key.width + padding.left - padding.right) / 2; + positionX = (key.mWidth + padding.left - padding.right) / 2; paint.setTextAlign(Align.CENTER); if (DEBUG_SHOW_ALIGN && label.length() > 1) drawVerticalLine(canvas, positionX, rowHeight, 0xc0008080, new Paint()); } - if (key.manualTemporaryUpperCaseHintIcon != null && isManualTemporaryUpperCase) { + if (key.mManualTemporaryUpperCaseHintIcon != null && isManualTemporaryUpperCase) { paint.setColor(mKeyTextColorDisabled); } else { paint.setColor(mKeyTextColor); @@ -732,47 +729,47 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { paint.setShadowLayer(0, 0, 0, 0); } // Draw key icon - if (key.label == null && key.icon != null) { - final int drawableWidth = key.icon.getIntrinsicWidth(); - final int drawableHeight = key.icon.getIntrinsicHeight(); + if (key.mLabel == null && key.mIcon != null) { + final int drawableWidth = key.mIcon.getIntrinsicWidth(); + final int drawableHeight = key.mIcon.getIntrinsicHeight(); final int drawableX; final int drawableY = ( - key.height + padding.top - padding.bottom - drawableHeight) / 2; - if ((key.labelOption & KEY_LABEL_OPTION_ALIGN_LEFT) != 0) { + key.mHeight + padding.top - padding.bottom - drawableHeight) / 2; + if ((key.mLabelOption & KEY_LABEL_OPTION_ALIGN_LEFT) != 0) { drawableX = padding.left + mKeyLabelHorizontalPadding; if (DEBUG_SHOW_ALIGN) drawVerticalLine(canvas, drawableX, rowHeight, 0xc0800080, new Paint()); - } else if ((key.labelOption & KEY_LABEL_OPTION_ALIGN_RIGHT) != 0) { - drawableX = key.width - padding.right - mKeyLabelHorizontalPadding + } else if ((key.mLabelOption & KEY_LABEL_OPTION_ALIGN_RIGHT) != 0) { + drawableX = key.mWidth - padding.right - mKeyLabelHorizontalPadding - drawableWidth; if (DEBUG_SHOW_ALIGN) drawVerticalLine(canvas, drawableX + drawableWidth, rowHeight, 0xc0808000, new Paint()); } else { // Align center - drawableX = (key.width + padding.left - padding.right - drawableWidth) / 2; + drawableX = (key.mWidth + padding.left - padding.right - drawableWidth) / 2; if (DEBUG_SHOW_ALIGN) drawVerticalLine(canvas, drawableX + drawableWidth / 2, rowHeight, 0xc0008080, new Paint()); } - drawIcon(canvas, key.icon, drawableX, drawableY, drawableWidth, drawableHeight); + drawIcon(canvas, key.mIcon, drawableX, drawableY, drawableWidth, drawableHeight); if (DEBUG_SHOW_ALIGN) drawRectangle(canvas, drawableX, drawableY, drawableWidth, drawableHeight, 0x80c00000, new Paint()); } - if (key.hintIcon != null) { - final int drawableWidth = key.width; - final int drawableHeight = key.height; + if (key.mHintIcon != null) { + final int drawableWidth = key.mWidth; + final int drawableHeight = key.mHeight; final int drawableX = 0; final int drawableY = HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL; Drawable icon = (isManualTemporaryUpperCase - && key.manualTemporaryUpperCaseHintIcon != null) - ? key.manualTemporaryUpperCaseHintIcon : key.hintIcon; + && key.mManualTemporaryUpperCaseHintIcon != null) + ? key.mManualTemporaryUpperCaseHintIcon : key.mHintIcon; drawIcon(canvas, icon, drawableX, drawableY, drawableWidth, drawableHeight); if (DEBUG_SHOW_ALIGN) drawRectangle(canvas, drawableX, drawableY, drawableWidth, drawableHeight, 0x80c0c000, new Paint()); } - canvas.translate(-key.x - kbdPaddingLeft, -key.y - kbdPaddingTop); + canvas.translate(-key.mX - kbdPaddingLeft, -key.mY - kbdPaddingTop); } if (DEBUG_KEYBOARD_GRID) { @@ -822,9 +819,9 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { // For characters, use large font. For labels like "Done", use small font. final int labelSize; final Typeface labelStyle; - if (label.length() > 1 && key.codes.length < 2) { + if (label.length() > 1 && key.mCodes.length < 2) { labelSize = mLabelTextSize; - if ((key.labelOption & KEY_LABEL_OPTION_FONT_NORMAL) != 0) { + if ((key.mLabelOption & KEY_LABEL_OPTION_FONT_NORMAL) != 0) { labelStyle = Typeface.DEFAULT; } else { labelStyle = Typeface.DEFAULT_BOLD; @@ -927,11 +924,11 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { if (key == null || !mInForeground) return; // What we show as preview should match what we show on key top in onBufferDraw(). - if (key.label != null) { + if (key.mLabel != null) { // TODO Should take care of temporaryShiftLabel here. mPreviewText.setCompoundDrawables(null, null, null, null); mPreviewText.setText(adjustCase(tracker.getPreviewText(key))); - if (key.label.length() > 1 && key.codes.length < 2) { + if (key.mLabel.length() > 1 && key.mCodes.length < 2) { mPreviewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mKeyLetterSize); mPreviewText.setTypeface(Typeface.DEFAULT_BOLD); } else { @@ -940,12 +937,12 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } } else { mPreviewText.setCompoundDrawables(null, null, null, - key.iconPreview != null ? key.iconPreview : key.icon); + key.mPreviewIcon != null ? key.mPreviewIcon : key.mIcon); mPreviewText.setText(null); } mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - int popupWidth = Math.max(mPreviewText.getMeasuredWidth(), key.width + int popupWidth = Math.max(mPreviewText.getMeasuredWidth(), key.mWidth + mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight()); final int popupHeight = mPreviewHeight; LayoutParams lp = mPreviewText.getLayoutParams(); @@ -954,8 +951,8 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { lp.height = popupHeight; } - int popupPreviewX = key.x - (popupWidth - key.width) / 2; - int popupPreviewY = key.y - popupHeight + mPreviewOffset; + int popupPreviewX = key.mX - (popupWidth - key.mWidth) / 2; + int popupPreviewY = key.mY - popupHeight + mPreviewOffset; mHandler.cancelDismissPreview(); if (mOffsetInWindow == null) { @@ -969,7 +966,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } // Set the preview background state mPreviewText.getBackground().setState( - key.popupResId != 0 ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET); + key.mPopupResId != 0 ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET); popupPreviewX += mOffsetInWindow[0]; popupPreviewY += mOffsetInWindow[1]; @@ -977,10 +974,10 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { if (popupPreviewY + mWindowY < 0) { // If the key you're pressing is on the left side of the keyboard, show the popup on // the right, offset by enough to see at least one key to the left/right. - if (key.x + key.width <= getWidth() / 2) { - popupPreviewX += (int) (key.width * 2.5); + if (key.mX + key.mWidth <= getWidth() / 2) { + popupPreviewX += (int) (key.mWidth * 2.5); } else { - popupPreviewX -= (int) (key.width * 2.5); + popupPreviewX -= (int) (key.mWidth * 2.5); } popupPreviewY += popupHeight; } @@ -1028,11 +1025,11 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { return; mInvalidatedKey = key; // TODO we should clean up this and record key's region to use in onBufferDraw. - mDirtyRect.union(key.x + getPaddingLeft(), key.y + getPaddingTop(), - key.x + key.width + getPaddingLeft(), key.y + key.height + getPaddingTop()); + mDirtyRect.union(key.mX + getPaddingLeft(), key.mY + getPaddingTop(), + key.mX + key.mWidth + getPaddingLeft(), key.mY + key.mHeight + getPaddingTop()); onBufferDraw(); - invalidate(key.x + getPaddingLeft(), key.y + getPaddingTop(), - key.x + key.width + getPaddingLeft(), key.y + key.height + getPaddingTop()); + invalidate(key.mX + getPaddingLeft(), key.mY + getPaddingTop(), + key.mX + key.mWidth + getPaddingLeft(), key.mY + key.mHeight + getPaddingTop()); } private boolean openPopupIfRequired(int keyIndex, PointerTracker tracker) { @@ -1058,11 +1055,11 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { private void onLongPressShiftKey(PointerTracker tracker) { tracker.setAlreadyProcessed(); mPointerQueue.remove(tracker); - mKeyboardActionListener.onKey(LatinKeyboard.KEYCODE_CAPSLOCK, null, 0, 0); + mKeyboardActionListener.onKey(Keyboard.CODE_CAPSLOCK, null, 0, 0); } private View inflateMiniKeyboardContainer(Key popupKey) { - int popupKeyboardId = popupKey.popupResId; + int popupKeyboardId = popupKey.mPopupResId; LayoutInflater inflater = (LayoutInflater)getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); View container = inflater.inflate(mPopupLayout, null); @@ -1116,8 +1113,8 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { miniKeyboard.mGestureDetector = null; Keyboard keyboard; - if (popupKey.popupCharacters != null) { - keyboard = new Keyboard(getContext(), popupKeyboardId, popupKey.popupCharacters, + if (popupKey.mPopupCharacters != null) { + keyboard = new Keyboard(getContext(), popupKeyboardId, popupKey.mPopupCharacters, -1, getPaddingLeft() + getPaddingRight()); } else { keyboard = new Keyboard(getContext(), popupKeyboardId); @@ -1133,7 +1130,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { private static boolean isOneRowKeys(List keys) { if (keys.size() == 0) return false; - final int edgeFlags = keys.get(0).edgeFlags; + final int edgeFlags = keys.get(0).mEdgeFlags; // HACK: The first key of mini keyboard which was inflated from xml and has multiple rows, // does not have both top and bottom edge flags on at the same time. On the other hand, // the first key of mini keyboard that was created with popupCharacters must have both top @@ -1155,7 +1152,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { // TODO if popupKey.popupCharacters has only one letter, send it as key without opening // mini keyboard. - if (popupKey.popupResId == 0) + if (popupKey.mPopupResId == 0) return false; View container = mMiniKeyboardCache.get(popupKey); @@ -1177,22 +1174,22 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { // b) When we have the rightmost key in popup keyboard directly above the pressed key // Left edges of both keys should be aligned for consistent default selection final List miniKeys = mMiniKeyboard.getKeyboard().getKeys(); - final int miniKeyWidth = miniKeys.size() > 0 ? miniKeys.get(0).width : 0; + final int miniKeyWidth = miniKeys.size() > 0 ? miniKeys.get(0).mWidth : 0; // HACK: Have the leftmost number in the popup characters right above the key boolean isNumberAtLeftmost = hasMultiplePopupChars(popupKey) && isNumberAtLeftmostPopupChar(popupKey); - int popupX = popupKey.x + mWindowOffset[0]; + int popupX = popupKey.mX + mWindowOffset[0]; popupX += getPaddingLeft(); if (isNumberAtLeftmost) { - popupX += popupKey.width - miniKeyWidth; // adjustment for a) described above + popupX += popupKey.mWidth - miniKeyWidth; // adjustment for a) described above popupX -= container.getPaddingLeft(); } else { popupX += miniKeyWidth; // adjustment for b) described above popupX -= container.getMeasuredWidth(); popupX += container.getPaddingRight(); } - int popupY = popupKey.y + mWindowOffset[1]; + int popupY = popupKey.mY + mWindowOffset[1]; popupY += getPaddingTop(); popupY -= container.getMeasuredHeight(); popupY += container.getPaddingBottom(); @@ -1208,7 +1205,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { mMiniKeyboardOriginX = adjustedX + container.getPaddingLeft() - mWindowOffset[0]; mMiniKeyboardOriginY = y + container.getPaddingTop() - mWindowOffset[1]; mMiniKeyboard.setPopupOffset(adjustedX, y); - // TODO: change the below line to use getLatinKeyboard() instead of getKeyboard() Keyboard baseMiniKeyboard = mMiniKeyboard.getKeyboard(); if (baseMiniKeyboard != null && baseMiniKeyboard.setShifted(mKeyboard == null ? false : mKeyboard.isShiftedOrShiftLocked())) { @@ -1224,8 +1220,8 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { // Inject down event on the key to mini keyboard. long eventTime = SystemClock.uptimeMillis(); mMiniKeyboardPopupTime = eventTime; - MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN, popupKey.x - + popupKey.width / 2, popupKey.y + popupKey.height / 2, eventTime); + MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN, popupKey.mX + + popupKey.mWidth / 2, popupKey.mY + popupKey.mHeight / 2, eventTime); mMiniKeyboard.onTouchEvent(downEvent); downEvent.recycle(); @@ -1234,15 +1230,15 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } private static boolean hasMultiplePopupChars(Key key) { - if (key.popupCharacters != null && key.popupCharacters.length() > 1) { + if (key.mPopupCharacters != null && key.mPopupCharacters.length() > 1) { return true; } return false; } private static boolean isNumberAtLeftmostPopupChar(Key key) { - if (key.popupCharacters != null && key.popupCharacters.length() > 0 - && isAsciiDigit(key.popupCharacters.charAt(0))) { + if (key.mPopupCharacters != null && key.mPopupCharacters.length() > 0 + && isAsciiDigit(key.mPopupCharacters.charAt(0))) { return true; } return false; diff --git a/java/src/com/android/inputmethod/keyboard/LatinKey.java b/java/src/com/android/inputmethod/keyboard/LatinKey.java index 4eaf4c8f6..1df4227ae 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKey.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKey.java @@ -19,47 +19,11 @@ package com.android.inputmethod.keyboard; import android.content.res.Resources; import android.content.res.XmlResourceParser; +// TODO: We should remove this class public class LatinKey extends Key { - - // functional normal state (with properties) - private final int[] KEY_STATE_FUNCTIONAL_NORMAL = { - android.R.attr.state_single - }; - - // functional pressed state (with properties) - private final int[] KEY_STATE_FUNCTIONAL_PRESSED = { - android.R.attr.state_single, - android.R.attr.state_pressed - }; - - private boolean mShiftLockEnabled; - public LatinKey(Resources res, Row parent, int x, int y, XmlResourceParser parser, KeyStyles keyStyles) { super(res, parent, x, y, parser, keyStyles); - if (popupCharacters != null && popupCharacters.length() == 0) { - // If there is a keyboard with no keys specified in popupCharacters - popupResId = 0; - } - } - - void enableShiftLock() { - mShiftLockEnabled = true; - } - - // sticky is used for shift key. If a key is not sticky and is modifier, - // the key will be treated as functional. - private boolean isFunctionalKey() { - return !sticky && modifier; - } - - @Override - public void onReleased(boolean inside) { - if (!mShiftLockEnabled) { - super.onReleased(inside); - } else { - pressed = !pressed; - } } /** @@ -67,24 +31,12 @@ public class LatinKey extends Key { */ @Override public boolean isInside(int x, int y) { - boolean result = (keyboard instanceof LatinKeyboard) - && ((LatinKeyboard)keyboard).isInside(this, x, y); + boolean result = (mKeyboard instanceof LatinKeyboard) + && ((LatinKeyboard)mKeyboard).isInside(this, x, y); return result; } boolean isInsideSuper(int x, int y) { return super.isInside(x, y); } - - @Override - public int[] getCurrentDrawableState() { - if (isFunctionalKey()) { - if (pressed) { - return KEY_STATE_FUNCTIONAL_PRESSED; - } else { - return KEY_STATE_FUNCTIONAL_NORMAL; - } - } - return super.getCurrentDrawableState(); - } } diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java index 29f749a46..934874868 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java @@ -16,7 +16,6 @@ package com.android.inputmethod.keyboard; -import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SubtypeSwitcher; @@ -34,36 +33,23 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.util.Log; -import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map; +// TODO: We should remove this class public class LatinKeyboard extends Keyboard { private static final boolean DEBUG_PREFERRED_LETTER = false; private static final String TAG = "LatinKeyboard"; - public static final int KEYCODE_OPTIONS = -100; - public static final int KEYCODE_OPTIONS_LONGPRESS = -101; - // TODO: remove this once LatinIME stops referring to this. - public static final int KEYCODE_VOICE = -102; - public static final int KEYCODE_NEXT_LANGUAGE = -104; - public static final int KEYCODE_PREV_LANGUAGE = -105; - public static final int KEYCODE_CAPSLOCK = -106; - - static final int OPACITY_FULLY_OPAQUE = 255; + public static final int OPACITY_FULLY_OPAQUE = 255; private static final int SPACE_LED_LENGTH_PERCENT = 80; private Drawable mShiftLockPreviewIcon; - private final HashMap mNormalShiftIcons = new HashMap(); - private Drawable mSpaceIcon; private Drawable mSpaceAutoCompletionIndicator; - private Drawable mSpacePreviewIcon; private final Drawable mButtonArrowLeftIcon; private final Drawable mButtonArrowRightIcon; private final int mSpaceBarTextShadowColor; - private Key mSpaceKey; private int mSpaceKeyIndex = -1; private int mSpaceDragStartX; private int mSpaceDragLastDiff; @@ -77,8 +63,6 @@ public class LatinKeyboard extends Keyboard { private int mPrefLetterY; private int mPrefDistance; - private LatinKeyboardShiftState mShiftState = new LatinKeyboardShiftState(); - 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_HIGH_PROB = 0.85f; @@ -111,99 +95,13 @@ public class LatinKeyboard extends Keyboard { mButtonArrowRightIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_right); sSpacebarVerticalCorrection = res.getDimensionPixelOffset( R.dimen.spacebar_vertical_correction); - mSpaceKeyIndex = indexOf(LatinIME.KEYCODE_SPACE); + mSpaceKeyIndex = indexOf(CODE_SPACE); } @Override protected Key createKeyFromXml(Resources res, Row parent, int x, int y, XmlResourceParser parser, KeyStyles keyStyles) { - Key key = new LatinKey(res, parent, x, y, parser, keyStyles); - switch (key.codes[0]) { - case LatinIME.KEYCODE_SPACE: - mSpaceKey = key; - mSpaceIcon = key.icon; - mSpacePreviewIcon = key.iconPreview; - break; - } - - return key; - } - - public void enableShiftLock() { - for (final Key key : getShiftKeys()) { - if (key instanceof LatinKey) { - ((LatinKey)key).enableShiftLock(); - } - mNormalShiftIcons.put(key, key.icon); - } - } - - public boolean setShiftLocked(boolean newShiftLockState) { - final Map shiftedIcons = getShiftedIcons(); - for (final Key key : getShiftKeys()) { - key.on = newShiftLockState; - key.icon = newShiftLockState ? shiftedIcons.get(key) : mNormalShiftIcons.get(key); - } - mShiftState.setShiftLocked(newShiftLockState); - return true; - } - - public boolean isShiftLocked() { - return mShiftState.isShiftLocked(); - } - - @Override - public boolean setShifted(boolean newShiftState) { - if (getShiftKeys().size() == 0) - return super.setShifted(newShiftState); - - final Map shiftedIcons = getShiftedIcons(); - for (final Key key : getShiftKeys()) { - if (!newShiftState && !mShiftState.isShiftLocked()) { - key.icon = mNormalShiftIcons.get(key); - } else if (newShiftState && !mShiftState.isShiftedOrShiftLocked()) { - key.icon = shiftedIcons.get(key); - } - } - return mShiftState.setShifted(newShiftState); - } - - @Override - public boolean isShiftedOrShiftLocked() { - if (getShiftKeys().size() > 0) { - return mShiftState.isShiftedOrShiftLocked(); - } else { - return super.isShiftedOrShiftLocked(); - } - } - - public void setAutomaticTemporaryUpperCase() { - setShifted(true); - mShiftState.setAutomaticTemporaryUpperCase(); - } - - public boolean isAutomaticTemporaryUpperCase() { - return isAlphaKeyboard() && mShiftState.isAutomaticTemporaryUpperCase(); - } - - public boolean isManualTemporaryUpperCase() { - return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCase(); - } - - public LatinKeyboardShiftState getKeyboardShiftState() { - return mShiftState; - } - - public boolean isAlphaKeyboard() { - return mId.getXmlId() == R.xml.kbd_qwerty; - } - - public boolean isPhoneKeyboard() { - return mId.mMode == KeyboardId.MODE_PHONE; - } - - public boolean isNumberKeyboard() { - return mId.mMode == KeyboardId.MODE_NUMBER; + return new LatinKey(res, parent, x, y, parser, keyStyles); } /** @@ -218,15 +116,15 @@ public class LatinKeyboard extends Keyboard { final Resources res = mRes; // If application locales are explicitly selected. if (SubtypeSwitcher.getInstance().needsToDisplayLanguage()) { - mSpaceKey.icon = new BitmapDrawable(res, + mSpaceKey.mIcon = new BitmapDrawable(res, drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCompletion)); } else { // sym_keyboard_space_led can be shared with Black and White symbol themes. if (isAutoCompletion) { - mSpaceKey.icon = new BitmapDrawable(res, + mSpaceKey.mIcon = new BitmapDrawable(res, drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCompletion)); } else { - mSpaceKey.icon = mSpaceIcon; + mSpaceKey.mIcon = mSpaceIcon; } } } @@ -283,7 +181,7 @@ public class LatinKeyboard extends Keyboard { @SuppressWarnings("unused") private Bitmap drawSpaceBar(int opacity, boolean isAutoCompletion) { - final int width = mSpaceKey.width; + final int width = mSpaceKey.mWidth; final int height = mSpaceIcon.getIntrinsicHeight(); final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(buffer); @@ -341,26 +239,26 @@ public class LatinKeyboard extends Keyboard { private void updateLocaleDrag(int diff) { if (mSlidingLocaleIcon == null) { - final int width = Math.max(mSpaceKey.width, + final int width = Math.max(mSpaceKey.mWidth, (int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO)); final int height = mSpacePreviewIcon.getIntrinsicHeight(); mSlidingLocaleIcon = new SlidingLocaleDrawable(mContext, mSpacePreviewIcon, width, height); mSlidingLocaleIcon.setBounds(0, 0, width, height); - mSpaceKey.iconPreview = mSlidingLocaleIcon; + mSpaceKey.mPreviewIcon = mSlidingLocaleIcon; } mSlidingLocaleIcon.setDiff(diff); if (Math.abs(diff) == Integer.MAX_VALUE) { - mSpaceKey.iconPreview = mSpacePreviewIcon; + mSpaceKey.mPreviewIcon = mSpacePreviewIcon; } else { - mSpaceKey.iconPreview = mSlidingLocaleIcon; + mSpaceKey.mPreviewIcon = mSlidingLocaleIcon; } - mSpaceKey.iconPreview.invalidateSelf(); + mSpaceKey.mPreviewIcon.invalidateSelf(); } public int getLanguageChangeDirection() { if (mSpaceKey == null || SubtypeSwitcher.getInstance().getEnabledKeyboardLocaleCount() <= 1 - || Math.abs(mSpaceDragLastDiff) < mSpaceKey.width * SPACEBAR_DRAG_THRESHOLD) { + || Math.abs(mSpaceDragLastDiff) < mSpaceKey.mWidth * SPACEBAR_DRAG_THRESHOLD) { return 0; // No change } return mSpaceDragLastDiff > 0 ? 1 : -1; @@ -393,12 +291,12 @@ public class LatinKeyboard extends Keyboard { */ @SuppressWarnings("unused") public boolean isInside(LatinKey key, int x, int y) { - final int code = key.codes[0]; - if (code == KEYCODE_SHIFT || code == KEYCODE_DELETE) { - y -= key.height / 10; - if (code == KEYCODE_SHIFT) x += key.width / 6; - if (code == KEYCODE_DELETE) x -= key.width / 6; - } else if (code == LatinIME.KEYCODE_SPACE) { + final int code = key.mCodes[0]; + if (code == CODE_SHIFT || code == CODE_DELETE) { + y -= key.mHeight / 10; + if (code == CODE_SHIFT) x += key.mWidth / 6; + if (code == CODE_DELETE) x -= key.mWidth / 6; + } else if (code == CODE_SPACE) { y += LatinKeyboard.sSpacebarVerticalCorrection; if (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER && SubtypeSwitcher.getInstance().getEnabledKeyboardLocaleCount() > 1) { @@ -447,11 +345,11 @@ public class LatinKeyboard extends Keyboard { mPrefLetterY = y; for (int i = 0; i < nearby.length; i++) { Key k = nearbyKeys.get(nearby[i]); - if (k != key && inPrefList(k.codes[0], pref)) { + if (k != key && inPrefList(k.mCodes[0], pref)) { final int dist = distanceFrom(k, x, y); - if (dist < (int) (k.width * OVERLAP_PERCENTAGE_LOW_PROB) && - (pref[k.codes[0]] > pref[mPrefLetter] * 3)) { - mPrefLetter = k.codes[0]; + if (dist < (int) (k.mWidth * OVERLAP_PERCENTAGE_LOW_PROB) && + (pref[k.mCodes[0]] > pref[mPrefLetter] * 3)) { + mPrefLetter = k.mCodes[0]; mPrefDistance = dist; if (DEBUG_PREFERRED_LETTER) { Log.d(TAG, "CORRECTED ALTHOUGH PREFERRED !!!!!!"); @@ -475,11 +373,11 @@ public class LatinKeyboard extends Keyboard { for (int i = 0; i < nearby.length; i++) { Key k = nearbyKeys.get(nearby[i]); - if (inPrefList(k.codes[0], pref)) { + if (inPrefList(k.mCodes[0], pref)) { final int dist = distanceFrom(k, x, y); - if (dist < (int) (k.width * OVERLAP_PERCENTAGE_HIGH_PROB) + if (dist < (int) (k.mWidth * OVERLAP_PERCENTAGE_HIGH_PROB) && dist < mPrefDistance) { - mPrefLetter = k.codes[0]; + mPrefLetter = k.mCodes[0]; mPrefLetterX = x; mPrefLetterY = y; mPrefDistance = dist; @@ -507,8 +405,8 @@ public class LatinKeyboard extends Keyboard { } private int distanceFrom(Key k, int x, int y) { - if (y > k.y && y < k.y + k.height) { - return Math.abs(k.x + k.width / 2 - x); + if (y > k.mY && y < k.mY + k.mHeight) { + return Math.abs(k.mX + k.mWidth / 2 - x); } else { return Integer.MAX_VALUE; } @@ -529,7 +427,7 @@ public class LatinKeyboard extends Keyboard { List keys = getKeys(); int count = keys.size(); for (int i = 0; i < count; i++) { - if (keys.get(i).codes[0] == code) return i; + if (keys.get(i).mCodes[0] == code) return i; } return -1; } diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardShiftState.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardShiftState.java deleted file mode 100644 index 6d7842857..000000000 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardShiftState.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. - * - * 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; - -import com.android.inputmethod.latin.KeyboardSwitcher; - -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(" + newShiftState + "): " + 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(" + newShiftLockState + "): " + 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"; - } - } -} diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 55427d23f..4e0caa1f6 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -31,6 +31,7 @@ import android.view.MotionEvent; import java.util.List; +// TODO: We should remove this class public class LatinKeyboardView extends KeyboardView { /** Whether we've started dropping move events because we found a big jump */ @@ -86,9 +87,9 @@ public class LatinKeyboardView extends KeyboardView { @Override protected boolean onLongPress(Key key) { - int primaryCode = key.codes[0]; - if (primaryCode == LatinKeyboard.KEYCODE_OPTIONS) { - return invokeOnKey(LatinKeyboard.KEYCODE_OPTIONS_LONGPRESS); + int primaryCode = key.mCodes[0]; + if (primaryCode == Keyboard.CODE_OPTIONS) { + return invokeOnKey(Keyboard.CODE_OPTIONS_LONGPRESS); } else if (primaryCode == '0' && getLatinKeyboard().isPhoneKeyboard()) { // Long pressing on 0 in phone number keypad gives you a '+'. return invokeOnKey('+'); @@ -216,7 +217,7 @@ public class LatinKeyboardView extends KeyboardView { if (languageDirection != 0) { getOnKeyboardActionListener().onKey( languageDirection == 1 - ? LatinKeyboard.KEYCODE_NEXT_LANGUAGE : LatinKeyboard.KEYCODE_PREV_LANGUAGE, + ? Keyboard.CODE_NEXT_LANGUAGE : Keyboard.CODE_PREV_LANGUAGE, null, mLastX, mLastY); me.setAction(MotionEvent.ACTION_CANCEL); keyboard.keyReleased(); @@ -271,8 +272,8 @@ public class LatinKeyboardView extends KeyboardView { } c = mStringToPlay.charAt(mStringIndex); } - int x = mAsciiKeys[c].x + 10; - int y = mAsciiKeys[c].y + 26; + int x = mAsciiKeys[c].mX + 10; + int y = mAsciiKeys[c].mY + 26; MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, x, y, 0); @@ -284,8 +285,8 @@ public class LatinKeyboardView extends KeyboardView { break; case MSG_TOUCH_UP: char cUp = mStringToPlay.charAt(mStringIndex); - int x2 = mAsciiKeys[cUp].x + 10; - int y2 = mAsciiKeys[cUp].y + 26; + int x2 = mAsciiKeys[cUp].mX + 10; + int y2 = mAsciiKeys[cUp].mY + 26; mStringIndex++; MotionEvent me2 = MotionEvent.obtain(SystemClock.uptimeMillis(), @@ -309,7 +310,7 @@ public class LatinKeyboardView extends KeyboardView { List keys = getLatinKeyboard().getKeys(); // Get the keys on this keyboard for (int i = 0; i < keys.size(); i++) { - int code = keys.get(i).codes[0]; + int code = keys.get(i).mCodes[0]; if (code >= 0 && code <= 255) { mAsciiKeys[code] = keys.get(i); } diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java index 53879cde1..774b39ab7 100644 --- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java +++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java @@ -52,7 +52,7 @@ public class MiniKeyboardKeyDetector extends KeyDetector { } if (allKeys != null && closestKeyIndex != NOT_A_KEY) - allKeys[0] = keys[closestKeyIndex].codes[0]; + allKeys[0] = keys[closestKeyIndex].mCodes[0]; return closestKeyIndex; } } diff --git a/java/src/com/android/inputmethod/keyboard/ModifierKeyState.java b/java/src/com/android/inputmethod/keyboard/ModifierKeyState.java new file mode 100644 index 000000000..1bd3d8040 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/ModifierKeyState.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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; + +import android.util.Log; + +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 PRESSING = 1; + protected static final int MOMENTARY = 2; + + protected final String mName; + protected int mState = RELEASING; + + public ModifierKeyState(String name) { + mName = name; + } + + public void onPress() { + final int oldState = mState; + mState = PRESSING; + if (DEBUG) + Log.d(TAG, mName + ".onPress: " + toString(oldState) + " > " + this); + } + + public void onRelease() { + final int oldState = mState; + mState = RELEASING; + if (DEBUG) + Log.d(TAG, mName + ".onRelease: " + toString(oldState) + " > " + this); + } + + public void onOtherKeyPressed() { + final int oldState = mState; + if (oldState == PRESSING) + mState = MOMENTARY; + if (DEBUG) + Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this); + } + + public boolean isReleasing() { + return mState == RELEASING; + } + + public boolean isMomentary() { + return mState == MOMENTARY; + } + + @Override + public String toString() { + return toString(mState); + } + + protected String toString(int state) { + switch (state) { + case RELEASING: return "RELEASING"; + case PRESSING: return "PRESSING"; + case MOMENTARY: return "MOMENTARY"; + default: return "UNKNOWN"; + } + } +} diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index aa0f9bd37..269ae1530 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -17,7 +17,6 @@ package com.android.inputmethod.keyboard; import com.android.inputmethod.keyboard.KeyboardView.UIHandler; -import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.R; import android.content.res.Resources; @@ -45,7 +44,7 @@ public class PointerTracker { // Miscellaneous constants private static final int NOT_A_KEY = KeyDetector.NOT_A_KEY; - private static final int[] KEY_DELETE = { Keyboard.KEYCODE_DELETE }; + private static final int[] KEY_DELETE = { Keyboard.CODE_DELETE }; private final UIProxy mProxy; private final UIHandler mHandler; @@ -207,9 +206,9 @@ public class PointerTracker { Key key = getKey(keyIndex); if (key == null) return false; - int primaryCode = key.codes[0]; - return primaryCode == Keyboard.KEYCODE_SHIFT - || primaryCode == Keyboard.KEYCODE_MODE_CHANGE; + int primaryCode = key.mCodes[0]; + return primaryCode == Keyboard.CODE_SHIFT + || primaryCode == Keyboard.CODE_MODE_CHANGE; } public boolean isModifier() { @@ -222,7 +221,7 @@ public class PointerTracker { public boolean isSpaceKey(int keyIndex) { Key key = getKey(keyIndex); - return key != null && key.codes[0] == LatinIME.KEYCODE_SPACE; + return key != null && key.mCodes[0] == Keyboard.CODE_SPACE; } public void releaseKey() { @@ -278,14 +277,14 @@ public class PointerTracker { checkMultiTap(eventTime, keyIndex); if (mListener != null) { if (isValidKeyIndex(keyIndex)) { - mListener.onPress(mKeys[keyIndex].codes[0]); + mListener.onPress(mKeys[keyIndex].mCodes[0]); // This onPress call may have changed keyboard layout and have updated mKeyIndex. // If that's the case, mKeyIndex has been updated in setKeyboard(). keyIndex = mKeyState.getKeyIndex(); } } if (isValidKeyIndex(keyIndex)) { - if (mKeys[keyIndex].repeatable) { + if (mKeys[keyIndex].mRepeatable) { repeatKey(keyIndex); mHandler.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this); mIsRepeatableKey = true; @@ -309,7 +308,7 @@ public class PointerTracker { startLongPressTimer(keyIndex); } else if (!isMinorMoveBounce(x, y, keyIndex)) { if (mListener != null) - mListener.onRelease(oldKey.codes[0]); + mListener.onRelease(oldKey.mCodes[0]); resetMultiTap(); keyState.onMoveToNewKey(keyIndex, x, y); startLongPressTimer(keyIndex); @@ -317,7 +316,7 @@ public class PointerTracker { } else { if (oldKey != null) { if (mListener != null) - mListener.onRelease(oldKey.codes[0]); + mListener.onRelease(oldKey.mCodes[0]); keyState.onMoveToNewKey(keyIndex, x ,y); mHandler.cancelLongPressTimers(); } else if (!isMinorMoveBounce(x, y, keyIndex)) { @@ -368,7 +367,7 @@ public class PointerTracker { if (key != null) { // While key is repeating, because there is no need to handle multi-tap key, we can // pass -1 as eventTime argument. - detectAndSendKey(keyIndex, key.x, key.y, -1); + detectAndSendKey(keyIndex, key.mX, key.mY, -1); } } @@ -420,18 +419,13 @@ public class PointerTracker { private void startLongPressTimer(int keyIndex) { Key key = getKey(keyIndex); - if (key.codes[0] == Keyboard.KEYCODE_SHIFT) { + if (key.mCodes[0] == Keyboard.CODE_SHIFT) { mHandler.startLongPressShiftTimer(mLongPressShiftKeyTimeout, keyIndex, this); } else { mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this); } } - private boolean isManualTemporaryUpperCase() { - return mKeyboard instanceof LatinKeyboard - && ((LatinKeyboard)mKeyboard).isManualTemporaryUpperCase(); - } - private void detectAndSendKey(int index, int x, int y, long eventTime) { final KeyboardActionListener listener = mListener; final Key key = getKey(index); @@ -440,30 +434,31 @@ public class PointerTracker { if (listener != null) listener.onCancel(); } else { - if (key.text != null) { + if (key.mOutputText != null) { if (listener != null) { - listener.onText(key.text); + listener.onText(key.mOutputText); listener.onRelease(NOT_A_KEY); } } else { - int code = key.codes[0]; + int code = key.mCodes[0]; //TextEntryState.keyPressedAt(key, x, y); int[] codes = mKeyDetector.newCodeArray(); mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes); // Multi-tap if (mInMultiTap) { if (mTapCount != -1) { - mListener.onKey(Keyboard.KEYCODE_DELETE, KEY_DELETE, x, y); + mListener.onKey(Keyboard.CODE_DELETE, KEY_DELETE, x, y); } else { mTapCount = 0; } - code = key.codes[mTapCount]; + code = key.mCodes[mTapCount]; } // If keyboard is in manual temporary upper case state and key has manual temporary // shift code, alternate character code should be sent. - if (isManualTemporaryUpperCase() && key.manualTemporaryUpperCaseCode != 0) { - code = key.manualTemporaryUpperCaseCode; + if (mKeyboard.isManualTemporaryUpperCase() + && key.mManualTemporaryUpperCaseCode != 0) { + code = key.mManualTemporaryUpperCaseCode; codes[0] = code; } @@ -493,10 +488,10 @@ public class PointerTracker { if (mInMultiTap) { // Multi-tap mPreviewLabel.setLength(0); - mPreviewLabel.append((char) key.codes[mTapCount < 0 ? 0 : mTapCount]); + mPreviewLabel.append((char) key.mCodes[mTapCount < 0 ? 0 : mTapCount]); return mPreviewLabel; } else { - return key.label; + return key.mLabel; } } @@ -514,10 +509,10 @@ public class PointerTracker { final boolean isMultiTap = (eventTime < mLastTapTime + mMultiTapKeyTimeout && keyIndex == mLastSentIndex); - if (key.codes.length > 1) { + if (key.mCodes.length > 1) { mInMultiTap = true; if (isMultiTap) { - mTapCount = (mTapCount + 1) % key.codes.length; + mTapCount = (mTapCount + 1) % key.mCodes.length; return; } else { mTapCount = -1; @@ -536,7 +531,7 @@ public class PointerTracker { if (key == null) { code = "----"; } else { - int primaryCode = key.codes[0]; + int primaryCode = key.mCodes[0]; code = String.format((primaryCode < 0) ? "%4d" : "0x%02x", primaryCode); } Log.d(TAG, String.format("%s%s[%d] %3d,%3d %3d(%s) %s", title, diff --git a/java/src/com/android/inputmethod/keyboard/ProximityKeyDetector.java b/java/src/com/android/inputmethod/keyboard/ProximityKeyDetector.java index 047173445..43596ae2e 100644 --- a/java/src/com/android/inputmethod/keyboard/ProximityKeyDetector.java +++ b/java/src/com/android/inputmethod/keyboard/ProximityKeyDetector.java @@ -53,7 +53,7 @@ public class ProximityKeyDetector extends KeyDetector { } if (allKeys == null) continue; - final int nCodes = key.codes.length; + final int nCodes = key.mCodes.length; // Find insertion point for (int j = 0; j < distances.length; j++) { if (distances[j] > dist) { @@ -62,7 +62,7 @@ public class ProximityKeyDetector extends KeyDetector { distances.length - (j + nCodes)); System.arraycopy(allKeys, j, allKeys, j + nCodes, allKeys.length - (j + nCodes)); - System.arraycopy(key.codes, 0, allKeys, j, nCodes); + System.arraycopy(key.mCodes, 0, allKeys, j, nCodes); Arrays.fill(distances, j, j + nCodes, dist); break; } diff --git a/java/src/com/android/inputmethod/keyboard/Row.java b/java/src/com/android/inputmethod/keyboard/Row.java index cb778f317..0768b1ff8 100644 --- a/java/src/com/android/inputmethod/keyboard/Row.java +++ b/java/src/com/android/inputmethod/keyboard/Row.java @@ -30,44 +30,44 @@ import android.util.Xml; */ public class Row { /** Default width of a key in this row. */ - public int defaultWidth; + public int mDefaultWidth; /** Default height of a key in this row. */ - public int defaultHeight; + public int mDefaultHeight; /** Default horizontal gap between keys in this row. */ - public int defaultHorizontalGap; + public int mDefaultHorizontalGap; /** Vertical gap following this row. */ - public int verticalGap; + public int mVerticalGap; /** * Edge flags for this row of keys. Possible values that can be assigned are * {@link Keyboard#EDGE_TOP EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM EDGE_BOTTOM} */ - public int rowEdgeFlags; + public int mRowEdgeFlags; - final Keyboard parent; + /* package */ final Keyboard mParent; - Row(Keyboard parent) { - this.parent = parent; + /* package */ Row(Keyboard parent) { + this.mParent = parent; } public Row(Resources res, Keyboard parent, XmlResourceParser parser) { - this.parent = parent; + this.mParent = parent; TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.Keyboard); - defaultWidth = KeyboardParser.getDimensionOrFraction(a, + mDefaultWidth = KeyboardParser.getDimensionOrFraction(a, R.styleable.Keyboard_keyWidth, parent.mDisplayWidth, parent.mDefaultWidth); - defaultHeight = KeyboardParser.getDimensionOrFraction(a, + mDefaultHeight = KeyboardParser.getDimensionOrFraction(a, R.styleable.Keyboard_keyHeight, parent.mDisplayHeight, parent.mDefaultHeight); - defaultHorizontalGap = KeyboardParser.getDimensionOrFraction(a, + mDefaultHorizontalGap = KeyboardParser.getDimensionOrFraction(a, R.styleable.Keyboard_horizontalGap, parent.mDisplayWidth, parent.mDefaultHorizontalGap); - verticalGap = KeyboardParser.getDimensionOrFraction(a, + mVerticalGap = KeyboardParser.getDimensionOrFraction(a, R.styleable.Keyboard_verticalGap, parent.mDisplayHeight, parent.mDefaultVerticalGap); a.recycle(); a = res.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.Keyboard_Row); - rowEdgeFlags = a.getInt(R.styleable.Keyboard_Row_rowEdgeFlags, 0); + mRowEdgeFlags = a.getInt(R.styleable.Keyboard_Row_rowEdgeFlags, 0); } } diff --git a/java/src/com/android/inputmethod/keyboard/ShiftKeyState.java b/java/src/com/android/inputmethod/keyboard/ShiftKeyState.java new file mode 100644 index 000000000..9229208a9 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/ShiftKeyState.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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; + +import android.util.Log; + +public class ShiftKeyState extends ModifierKeyState { + private static final int PRESSING_ON_SHIFTED = 3; // both temporary shifted & shift locked + private static final int IGNORING = 4; + + public ShiftKeyState(String name) { + super(name); + } + + @Override + public void onOtherKeyPressed() { + int oldState = mState; + if (oldState == PRESSING) { + mState = MOMENTARY; + } else if (oldState == PRESSING_ON_SHIFTED) { + mState = IGNORING; + } + if (DEBUG) + Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this); + } + + public void onPressOnShifted() { + int oldState = mState; + mState = PRESSING_ON_SHIFTED; + if (DEBUG) + Log.d(TAG, mName + ".onPressOnShifted: " + toString(oldState) + " > " + this); + } + + public boolean isPressingOnShifted() { + return mState == PRESSING_ON_SHIFTED; + } + + public boolean isIgnoring() { + return mState == IGNORING; + } + + @Override + public String toString() { + return toString(mState); + } + + @Override + protected String toString(int state) { + switch (state) { + case PRESSING_ON_SHIFTED: return "PRESSING_ON_SHIFTED"; + case IGNORING: return "IGNORING"; + default: return super.toString(state); + } + } +} diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java deleted file mode 100644 index e8487e798..000000000 --- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +++ /dev/null @@ -1,644 +0,0 @@ -/* - * Copyright (C) 2008 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.latin; - -import com.android.inputmethod.keyboard.KeyboardView; -import com.android.inputmethod.keyboard.KeyboardId; -import com.android.inputmethod.keyboard.LatinKeyboard; -import com.android.inputmethod.keyboard.LatinKeyboardView; - -import android.content.Context; -import android.content.SharedPreferences; -import android.content.res.Resources; -import android.util.Log; -import android.view.InflateException; -import android.view.inputmethod.InputMethodManager; - -import java.lang.ref.SoftReference; -import java.util.HashMap; -import java.util.Locale; - -public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener { - private static final String TAG = "KeyboardSwitcher"; - private static final boolean DEBUG = false; - public static final boolean DEBUG_STATE = false; - - // Changing DEFAULT_LAYOUT_ID also requires prefs_for_debug.xml to be matched with. - public static final String DEFAULT_LAYOUT_ID = "5"; - public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902"; - private static final int[] THEMES = new int [] { - R.layout.input_basic, - R.layout.input_basic_highcontrast, - R.layout.input_stone_normal, - R.layout.input_stone_bold, - R.layout.input_gingerbread, - R.layout.input_honeycomb, // DEFAULT_LAYOUT_ID - }; - - 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 SubtypeSwitcher mSubtypeSwitcher; - private SharedPreferences mPrefs; - - private LatinKeyboardView mInputView; - private LatinIME mInputMethodService; - - private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift"); - private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol"); - - private KeyboardId mSymbolsId; - private KeyboardId mSymbolsShiftedId; - - private KeyboardId mCurrentId; - private final HashMap> mKeyboardCache = - new HashMap>(); - - private int mMode = KeyboardId.MODE_TEXT; /* default value */ - private int mImeOptions; - private boolean mIsSymbols; - /** mIsAutoCompletionActive indicates that auto completed word will be input instead of - * what user actually typed. */ - private boolean mIsAutoCompletionActive; - private boolean mVoiceKeyEnabled; - private boolean mVoiceButtonOnPrimary; - private int mSymbolsModeState = SYMBOLS_MODE_STATE_NONE; - - // Indicates whether or not we have the settings key - private boolean mHasSettingsKey; - private static final int SETTINGS_KEY_MODE_AUTO = R.string.settings_key_mode_auto; - private static final int SETTINGS_KEY_MODE_ALWAYS_SHOW = - R.string.settings_key_mode_always_show; - // NOTE: No need to have SETTINGS_KEY_MODE_ALWAYS_HIDE here because it's not being referred to - // in the source code now. - // Default is SETTINGS_KEY_MODE_AUTO. - private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO; - - private int mLayoutId; - - private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); - - public static KeyboardSwitcher getInstance() { - return sInstance; - } - - private KeyboardSwitcher() { - } - - public static void init(LatinIME ims, SharedPreferences prefs) { - sInstance.mInputMethodService = ims; - sInstance.mPrefs = prefs; - sInstance.mSubtypeSwitcher = SubtypeSwitcher.getInstance(); - - sInstance.mLayoutId = Integer.valueOf( - prefs.getString(PREF_KEYBOARD_LAYOUT, DEFAULT_LAYOUT_ID)); - prefs.registerOnSharedPreferenceChangeListener(sInstance); - } - - private void makeSymbolsKeyboardIds() { - final Locale locale = mSubtypeSwitcher.getInputLocale(); - final int orientation = mInputMethodService.getResources().getConfiguration().orientation; - final int mode = mMode; - final int colorScheme = getColorScheme(); - final boolean hasSettingsKey = mHasSettingsKey; - final boolean voiceKeyEnabled = mVoiceKeyEnabled; - final boolean hasVoiceKey = voiceKeyEnabled && !mVoiceButtonOnPrimary; - final int imeOptions = mImeOptions; - // Note: This comment is only applied for phone number keyboard layout. - // On non-xlarge device, "@integer/key_switch_alpha_symbol" key code is used to switch - // between "phone keyboard" and "phone symbols keyboard". But on xlarge device, - // "@integer/key_shift" key code is used for that purpose in order to properly display - // "more" and "locked more" key labels. To achieve these behavior, we should initialize - // mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard" - // respectively here for xlarge device's layout switching. - mSymbolsId = new KeyboardId(locale, orientation, mode, - mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone : R.xml.kbd_symbols, - colorScheme, hasSettingsKey, voiceKeyEnabled, hasVoiceKey, imeOptions, true); - mSymbolsShiftedId = new KeyboardId(locale, orientation, mode, - mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone_symbols : R.xml.kbd_symbols_shift, - colorScheme, hasSettingsKey, voiceKeyEnabled, hasVoiceKey, imeOptions, true); - } - - private boolean hasVoiceKey(boolean isSymbols) { - return mVoiceKeyEnabled && (isSymbols != mVoiceButtonOnPrimary); - } - - public void loadKeyboard(int mode, int imeOptions, boolean voiceKeyEnabled, - boolean voiceButtonOnPrimary) { - mSymbolsModeState = SYMBOLS_MODE_STATE_NONE; - try { - loadKeyboardInternal(mode, imeOptions, voiceKeyEnabled, voiceButtonOnPrimary, - false); - } catch (RuntimeException e) { - Log.w(TAG, e); - LatinImeLogger.logOnException(mode + "," + imeOptions, e); - } - } - - private void loadKeyboardInternal(int mode, int imeOptions, boolean voiceButtonEnabled, - boolean voiceButtonOnPrimary, boolean isSymbols) { - if (mInputView == null) return; - mInputView.setPreviewEnabled(mInputMethodService.getPopupOn()); - - mMode = mode; - mImeOptions = imeOptions; - mVoiceKeyEnabled = voiceButtonEnabled; - mVoiceButtonOnPrimary = voiceButtonOnPrimary; - mIsSymbols = isSymbols; - // Update the settings key state because number of enabled IMEs could have been changed - mHasSettingsKey = getSettingsKeyMode(mPrefs, mInputMethodService); - makeSymbolsKeyboardIds(); - - KeyboardId id = getKeyboardId(mode, imeOptions, isSymbols); - LatinKeyboard keyboard = getKeyboard(id); - - mCurrentId = id; - mInputView.setKeyboard(keyboard); - } - - private LatinKeyboard getKeyboard(KeyboardId id) { - final SoftReference ref = mKeyboardCache.get(id); - LatinKeyboard keyboard = (ref == null) ? null : ref.get(); - if (keyboard == null) { - final Locale savedLocale = mSubtypeSwitcher.changeSystemLocale( - mSubtypeSwitcher.getInputLocale()); - - keyboard = new LatinKeyboard(mInputMethodService, id); - - if (id.mEnableShiftLock) { - keyboard.enableShiftLock(); - } - - mKeyboardCache.put(id, new SoftReference(keyboard)); - if (DEBUG) - Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": " - + ((ref == null) ? "LOAD" : "GCed") + " id=" + id); - - mSubtypeSwitcher.changeSystemLocale(savedLocale); - } else if (DEBUG) { - Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id); - } - - keyboard.onAutoCompletionStateChanged(mIsAutoCompletionActive); - keyboard.setShifted(false); - return keyboard; - } - - private KeyboardId getKeyboardId(int mode, int imeOptions, boolean isSymbols) { - final boolean hasVoiceKey = hasVoiceKey(isSymbols); - final int charColorId = getColorScheme(); - final int xmlId; - final boolean enableShiftLock; - - if (isSymbols) { - if (mode == KeyboardId.MODE_PHONE) { - xmlId = R.xml.kbd_phone_symbols; - } else if (mode == KeyboardId.MODE_NUMBER) { - // Note: MODE_NUMBER keyboard layout has no "switch alpha symbol" key. - xmlId = R.xml.kbd_number; - } else { - xmlId = R.xml.kbd_symbols; - } - enableShiftLock = false; - } else { - if (mode == KeyboardId.MODE_PHONE) { - xmlId = R.xml.kbd_phone; - enableShiftLock = false; - } else if (mode == KeyboardId.MODE_NUMBER) { - xmlId = R.xml.kbd_number; - enableShiftLock = false; - } else { - xmlId = R.xml.kbd_qwerty; - enableShiftLock = true; - } - } - final int orientation = mInputMethodService.getResources().getConfiguration().orientation; - final Locale locale = mSubtypeSwitcher.getInputLocale(); - return new KeyboardId(locale, orientation, mode, xmlId, charColorId, - mHasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, imeOptions, enableShiftLock); - } - - public int getKeyboardMode() { - return mMode; - } - - public boolean isAlphabetMode() { - return mCurrentId != null && mCurrentId.isAlphabetMode(); - } - - public boolean isInputViewShown() { - return mInputView != null && mInputView.isShown(); - } - - public boolean isKeyboardAvailable() { - if (mInputView != null) - return mInputView.getLatinKeyboard() != null; - return false; - } - - private LatinKeyboard getLatinKeyboard() { - if (mInputView != null) - return mInputView.getLatinKeyboard(); - return null; - } - - public void setPreferredLetters(int[] frequencies) { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null) - latinKeyboard.setPreferredLetters(frequencies); - } - - public void keyReleased() { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null) - latinKeyboard.keyReleased(); - } - - public boolean isShiftedOrShiftLocked() { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null) - return latinKeyboard.isShiftedOrShiftLocked(); - return false; - } - - public boolean isShiftLocked() { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null) - return latinKeyboard.isShiftLocked(); - return false; - } - - 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(); - if (latinKeyboard != null) { - // On non-distinct multi touch panel device, we should also turn off the shift locked - // state when shift key is pressed to go to normal mode. - // On the other hand, on distinct multi touch panel device, turning off the shift locked - // state with shift key pressing is handled by onReleaseShift(). - if (!hasDistinctMultitouch() && !shifted && latinKeyboard.isShiftLocked()) { - latinKeyboard.setShiftLocked(false); - } - if (latinKeyboard.setShifted(shifted)) { - mInputView.invalidateAllKeys(); - } - } - } - - private void setShiftLocked(boolean shiftLocked) { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null && latinKeyboard.setShiftLocked(shiftLocked)) { - mInputView.invalidateAllKeys(); - } - } - - /** - * Toggle keyboard shift state triggered by user touch event. - */ - public void toggleShift() { - mInputMethodService.mHandler.cancelUpdateShiftState(); - if (DEBUG_STATE) - Log.d(TAG, "toggleShift:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " shiftKeyState=" + mShiftKeyState); - if (isAlphabetMode()) { - setManualTemporaryUpperCase(!isShiftedOrShiftLocked()); - } else { - toggleShiftInSymbol(); - } - } - - public void toggleCapsLock() { - mInputMethodService.mHandler.cancelUpdateShiftState(); - if (DEBUG_STATE) - Log.d(TAG, "toggleCapsLock:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " shiftKeyState=" + mShiftKeyState); - if (isAlphabetMode()) { - if (isShiftLocked()) { - // Shift key is long pressed while caps lock state, we will toggle back to normal - // state. And mark as if shift key is released. - setShiftLocked(false); - mShiftKeyState.onRelease(); - } else { - setShiftLocked(true); - } - } - } - - private void setAutomaticTemporaryUpperCase() { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null) { - latinKeyboard.setAutomaticTemporaryUpperCase(); - mInputView.invalidateAllKeys(); - } - } - - /** - * Update keyboard shift state triggered by connected EditText status change. - */ - public void updateShiftState() { - final ShiftKeyState shiftKeyState = mShiftKeyState; - if (DEBUG_STATE) - Log.d(TAG, "updateShiftState:" - + " autoCaps=" + mInputMethodService.getCurrentAutoCapsState() - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " shiftKeyState=" + shiftKeyState); - if (isAlphabetMode()) { - if (!isShiftLocked() && !shiftKeyState.isIgnoring()) { - if (shiftKeyState.isReleasing() && mInputMethodService.getCurrentAutoCapsState()) { - // Only when shift key is releasing, automatic temporary upper case will be set. - setAutomaticTemporaryUpperCase(); - } else { - setManualTemporaryUpperCase(shiftKeyState.isMomentary()); - } - } - } else { - // In symbol keyboard mode, we should clear shift key state because only alphabet - // keyboard has shift key. - shiftKeyState.onRelease(); - } - } - - public void changeKeyboardMode() { - if (DEBUG_STATE) - Log.d(TAG, "changeKeyboardMode:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " shiftKeyState=" + mShiftKeyState); - toggleKeyboardMode(); - if (isShiftLocked() && isAlphabetMode()) - setShiftLocked(true); - updateShiftState(); - } - - public void onPressShift() { - if (!isKeyboardAvailable()) - return; - ShiftKeyState shiftKeyState = mShiftKeyState; - if (DEBUG_STATE) - Log.d(TAG, "onPressShift:" - + " 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. - shiftKeyState.onPress(); - setManualTemporaryUpperCase(true); - } else if (isAutomaticTemporaryUpperCase()) { - // Shift key is pressed while automatic temporary upper case, we have to move to - // manual temporary upper case. - shiftKeyState.onPress(); - setManualTemporaryUpperCase(true); - } else if (isShiftedOrShiftLocked()) { - // In manual upper case state, we just record shift key has been pressing while - // shifted state. - shiftKeyState.onPressOnShifted(); - } else { - // In base layout, chording or manual temporary upper case mode is started. - shiftKeyState.onPress(); - toggleShift(); - } - } else { - // In symbol mode, just toggle symbol and symbol more keyboard. - shiftKeyState.onPress(); - toggleShift(); - } - } - - public void onReleaseShift() { - if (!isKeyboardAvailable()) - return; - ShiftKeyState shiftKeyState = mShiftKeyState; - if (DEBUG_STATE) - Log.d(TAG, "onReleaseShift:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " shiftKeyState=" + shiftKeyState); - if (isAlphabetMode()) { - if (shiftKeyState.isMomentary()) { - // After chording input while normal state. - toggleShift(); - } else if (isShiftLocked() && !shiftKeyState.isIgnoring()) { - // 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(); - } - } - shiftKeyState.onRelease(); - } - - public void onPressSymbol() { - if (DEBUG_STATE) - Log.d(TAG, "onReleaseShift:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " symbolKeyState=" + mSymbolKeyState); - changeKeyboardMode(); - mSymbolKeyState.onPress(); - } - - public void onReleaseSymbol() { - if (DEBUG_STATE) - Log.d(TAG, "onReleaseShift:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " symbolKeyState=" + mSymbolKeyState); - if (mSymbolKeyState.isMomentary()) - changeKeyboardMode(); - mSymbolKeyState.onRelease(); - } - - public void onOtherKeyPressed() { - if (DEBUG_STATE) - Log.d(TAG, "onOtherKeyPressed:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " shiftKeyState=" + mShiftKeyState - + " symbolKeyState=" + mSymbolKeyState); - mShiftKeyState.onOtherKeyPressed(); - mSymbolKeyState.onOtherKeyPressed(); - } - - private void toggleShiftInSymbol() { - if (isAlphabetMode()) - return; - final LatinKeyboard keyboard; - if (mCurrentId.equals(mSymbolsId) || !mCurrentId.equals(mSymbolsShiftedId)) { - mCurrentId = mSymbolsShiftedId; - keyboard = getKeyboard(mCurrentId); - // Symbol shifted keyboard has an ALT key that has a caps lock style indicator. To - // enable the indicator, we need to call enableShiftLock() and setShiftLocked(true). - // Thus we can keep the ALT key's Key.on value true while LatinKey.onRelease() is - // called. - keyboard.setShiftLocked(true); - } else { - mCurrentId = mSymbolsId; - keyboard = getKeyboard(mCurrentId); - // Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the - // indicator, we need to call enableShiftLock() and setShiftLocked(false). - keyboard.setShifted(false); - } - mInputView.setKeyboard(keyboard); - } - - private void toggleKeyboardMode() { - loadKeyboardInternal(mMode, mImeOptions, mVoiceKeyEnabled, mVoiceButtonOnPrimary, - !mIsSymbols); - if (mIsSymbols) { - mSymbolsModeState = SYMBOLS_MODE_STATE_BEGIN; - } else { - mSymbolsModeState = SYMBOLS_MODE_STATE_NONE; - } - } - - public boolean hasDistinctMultitouch() { - return mInputView != null && mInputView.hasDistinctMultitouch(); - } - - /** - * Updates state machine to figure out when to automatically switch back to alpha mode. - */ - public void onKey(int key) { - // Switch back to alpha mode if user types one or more non-space/enter - // characters followed by a space/enter - switch (mSymbolsModeState) { - case SYMBOLS_MODE_STATE_BEGIN: - if (key != LatinIME.KEYCODE_SPACE && key != LatinIME.KEYCODE_ENTER && key > 0) { - mSymbolsModeState = SYMBOLS_MODE_STATE_SYMBOL; - } - break; - case SYMBOLS_MODE_STATE_SYMBOL: - if (key == LatinIME.KEYCODE_ENTER || key == LatinIME.KEYCODE_SPACE) { - changeKeyboardMode(); - } - break; - } - } - - public LatinKeyboardView getInputView() { - return mInputView; - } - - public LatinKeyboardView onCreateInputView() { - createInputViewInternal(mLayoutId, true); - return mInputView; - } - - private void createInputViewInternal(int newLayout, boolean forceReset) { - if (mLayoutId != newLayout || mInputView == null || forceReset) { - if (mInputView != null) { - mInputView.closing(); - } - if (THEMES.length <= newLayout) { - newLayout = Integer.valueOf(DEFAULT_LAYOUT_ID); - } - - LatinIMEUtil.GCUtils.getInstance().reset(); - boolean tryGC = true; - for (int i = 0; i < LatinIMEUtil.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { - try { - mInputView = (LatinKeyboardView) mInputMethodService.getLayoutInflater( - ).inflate(THEMES[newLayout], null); - tryGC = false; - } catch (OutOfMemoryError e) { - Log.w(TAG, "load keyboard failed: " + e); - tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait( - mLayoutId + "," + newLayout, e); - } catch (InflateException e) { - Log.w(TAG, "load keyboard failed: " + e); - tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait( - mLayoutId + "," + newLayout, e); - } - } - mInputView.setOnKeyboardActionListener(mInputMethodService); - mLayoutId = newLayout; - } - } - - private void postSetInputView() { - mInputMethodService.mHandler.post(new Runnable() { - @Override - public void run() { - if (mInputView != null) { - mInputMethodService.setInputView(mInputView); - } - mInputMethodService.updateInputViewShown(); - } - }); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if (PREF_KEYBOARD_LAYOUT.equals(key)) { - final int layoutId = Integer.valueOf( - sharedPreferences.getString(key, DEFAULT_LAYOUT_ID)); - createInputViewInternal(layoutId, false); - postSetInputView(); - } else if (LatinIMESettings.PREF_SETTINGS_KEY.equals(key)) { - mHasSettingsKey = getSettingsKeyMode(sharedPreferences, mInputMethodService); - createInputViewInternal(mLayoutId, true); - postSetInputView(); - } - } - - private int getColorScheme() { - return (mInputView != null) - ? mInputView.getColorScheme() : KeyboardView.COLOR_SCHEME_WHITE; - } - - public void onAutoCompletionStateChanged(boolean isAutoCompletion) { - if (isAutoCompletion != mIsAutoCompletionActive) { - LatinKeyboardView keyboardView = getInputView(); - mIsAutoCompletionActive = isAutoCompletion; - keyboardView.invalidateKey(((LatinKeyboard) keyboardView.getKeyboard()) - .onAutoCompletionStateChanged(isAutoCompletion)); - } - } - - private static boolean getSettingsKeyMode(SharedPreferences prefs, Context context) { - Resources resources = context.getResources(); - final boolean showSettingsKeyOption = resources.getBoolean( - R.bool.config_enable_show_settings_key_option); - if (showSettingsKeyOption) { - final String settingsKeyMode = prefs.getString(LatinIMESettings.PREF_SETTINGS_KEY, - resources.getString(DEFAULT_SETTINGS_KEY_MODE)); - // We show the settings key when 1) SETTINGS_KEY_MODE_ALWAYS_SHOW or - // 2) SETTINGS_KEY_MODE_AUTO and there are two or more enabled IMEs on the system - if (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_ALWAYS_SHOW)) - || (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_AUTO)) - && LatinIMEUtil.hasMultipleEnabledIMEsOrSubtypes( - ((InputMethodManager) context.getSystemService( - Context.INPUT_METHOD_SERVICE))))) { - return true; - } - } - return false; - } -} diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 4f4112fa8..5bf635fd3 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -19,8 +19,8 @@ package com.android.inputmethod.latin; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardActionListener; import com.android.inputmethod.keyboard.KeyboardId; +import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardView; -import com.android.inputmethod.keyboard.LatinKeyboard; import com.android.inputmethod.keyboard.LatinKeyboardView; import com.android.inputmethod.latin.LatinIMEUtil.RingCharBuffer; import com.android.inputmethod.voice.VoiceIMEConnector; @@ -109,11 +109,6 @@ public class LatinIME extends InputMethodService // Key events coming any faster than this are long-presses. private static final int QUICK_PRESS = 200; - public static final int KEYCODE_ENTER = '\n'; - public static final int KEYCODE_TAB = '\t'; - public static final int KEYCODE_SPACE = ' '; - public static final int KEYCODE_PERIOD = '.'; - // Contextual menu positions private static final int POS_METHOD = 0; private static final int POS_SETTINGS = 1; @@ -255,7 +250,7 @@ public class LatinIME extends InputMethodService } } - /* package */ final UIHandler mHandler = new UIHandler(); + public final UIHandler mHandler = new UIHandler(); public class UIHandler extends Handler { private static final int MSG_UPDATE_SUGGESTIONS = 0; @@ -968,7 +963,8 @@ public class LatinIME extends InputMethodService if (ic == null) return; CharSequence lastTwo = ic.getTextBeforeCursor(2, 0); if (lastTwo != null && lastTwo.length() == 2 - && lastTwo.charAt(0) == KEYCODE_SPACE && isSentenceSeparator(lastTwo.charAt(1))) { + && lastTwo.charAt(0) == Keyboard.CODE_SPACE + && isSentenceSeparator(lastTwo.charAt(1))) { ic.beginBatchEdit(); ic.deleteSurroundingText(2, 0); ic.commitText(lastTwo.charAt(1) + " ", 1); @@ -983,9 +979,9 @@ public class LatinIME extends InputMethodService if (ic == null) return; CharSequence lastThree = ic.getTextBeforeCursor(3, 0); if (lastThree != null && lastThree.length() == 3 - && lastThree.charAt(0) == KEYCODE_PERIOD - && lastThree.charAt(1) == KEYCODE_SPACE - && lastThree.charAt(2) == KEYCODE_PERIOD) { + && lastThree.charAt(0) == Keyboard.CODE_PERIOD + && lastThree.charAt(1) == Keyboard.CODE_SPACE + && lastThree.charAt(2) == Keyboard.CODE_PERIOD) { ic.beginBatchEdit(); ic.deleteSurroundingText(3, 0); ic.commitText(" ..", 1); @@ -1002,7 +998,8 @@ public class LatinIME extends InputMethodService CharSequence lastThree = ic.getTextBeforeCursor(3, 0); if (lastThree != null && lastThree.length() == 3 && Character.isLetterOrDigit(lastThree.charAt(0)) - && lastThree.charAt(1) == KEYCODE_SPACE && lastThree.charAt(2) == KEYCODE_SPACE) { + && lastThree.charAt(1) == Keyboard.CODE_SPACE + && lastThree.charAt(2) == Keyboard.CODE_SPACE) { ic.beginBatchEdit(); ic.deleteSurroundingText(2, 0); ic.commitText(". ", 1); @@ -1020,8 +1017,8 @@ public class LatinIME extends InputMethodService // if there is one. CharSequence lastOne = ic.getTextBeforeCursor(1, 0); if (lastOne != null && lastOne.length() == 1 - && lastOne.charAt(0) == KEYCODE_PERIOD - && text.charAt(0) == KEYCODE_PERIOD) { + && lastOne.charAt(0) == Keyboard.CODE_PERIOD + && text.charAt(0) == Keyboard.CODE_PERIOD) { ic.deleteSurroundingText(1, 0); } } @@ -1032,7 +1029,7 @@ public class LatinIME extends InputMethodService CharSequence lastOne = ic.getTextBeforeCursor(1, 0); if (lastOne != null && lastOne.length() == 1 - && lastOne.charAt(0) == KEYCODE_SPACE) { + && lastOne.charAt(0) == Keyboard.CODE_SPACE) { ic.deleteSurroundingText(1, 0); } } @@ -1082,57 +1079,57 @@ public class LatinIME extends InputMethodService @Override public void onKey(int primaryCode, int[] keyCodes, int x, int y) { long when = SystemClock.uptimeMillis(); - if (primaryCode != Keyboard.KEYCODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { + if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { mDeleteCount = 0; } mLastKeyTime = when; KeyboardSwitcher switcher = mKeyboardSwitcher; final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); switch (primaryCode) { - case Keyboard.KEYCODE_DELETE: + case Keyboard.CODE_DELETE: handleBackspace(); mDeleteCount++; LatinImeLogger.logOnDelete(); break; - case Keyboard.KEYCODE_SHIFT: + case Keyboard.CODE_SHIFT: // Shift key is handled in onPress() when device has distinct multi-touch panel. if (!distinctMultiTouch) switcher.toggleShift(); break; - case Keyboard.KEYCODE_MODE_CHANGE: + case Keyboard.CODE_MODE_CHANGE: // Symbol key is handled in onPress() when device has distinct multi-touch panel. if (!distinctMultiTouch) switcher.changeKeyboardMode(); break; - case Keyboard.KEYCODE_CANCEL: + case Keyboard.CODE_CANCEL: if (!isShowingOptionDialog()) { handleClose(); } break; - case LatinKeyboard.KEYCODE_OPTIONS: + case Keyboard.CODE_OPTIONS: onOptionKeyPressed(); break; - case LatinKeyboard.KEYCODE_OPTIONS_LONGPRESS: + case Keyboard.CODE_OPTIONS_LONGPRESS: onOptionKeyLongPressed(); break; - case LatinKeyboard.KEYCODE_NEXT_LANGUAGE: + case Keyboard.CODE_NEXT_LANGUAGE: toggleLanguage(false, true); break; - case LatinKeyboard.KEYCODE_PREV_LANGUAGE: + case Keyboard.CODE_PREV_LANGUAGE: toggleLanguage(false, false); break; - case LatinKeyboard.KEYCODE_CAPSLOCK: + case Keyboard.CODE_CAPSLOCK: switcher.toggleCapsLock(); break; - case LatinKeyboard.KEYCODE_VOICE: /* was a button press, was not a swipe */ + case Keyboard.CODE_VOICE: /* was a button press, was not a swipe */ mVoiceConnector.startListening(false, mKeyboardSwitcher.getInputView().getWindowToken(), mConfigurationChanging); break; - case KEYCODE_TAB: + case Keyboard.CODE_TAB: handleTab(); break; default: - if (primaryCode != KEYCODE_ENTER) { + if (primaryCode != Keyboard.CODE_ENTER) { mJustAddedAutoSpace = false; } RingCharBuffer.getInstance().push((char)primaryCode, x, y); @@ -1344,14 +1341,14 @@ public class LatinIME extends InputMethodService pickedDefault = pickDefaultSuggestion(); // Picked the suggestion by the space key. We consider this // as "added an auto space". - if (primaryCode == KEYCODE_SPACE) { + if (primaryCode == Keyboard.CODE_SPACE) { mJustAddedAutoSpace = true; } } else { commitTyped(ic); } } - if (mJustAddedAutoSpace && primaryCode == KEYCODE_ENTER) { + if (mJustAddedAutoSpace && primaryCode == Keyboard.CODE_ENTER) { removeTrailingSpace(); mJustAddedAutoSpace = false; } @@ -1360,15 +1357,15 @@ public class LatinIME extends InputMethodService // Handle the case of ". ." -> " .." with auto-space if necessary // before changing the TextEntryState. if (TextEntryState.getState() == TextEntryState.State.PUNCTUATION_AFTER_ACCEPTED - && primaryCode == KEYCODE_PERIOD) { + && primaryCode == Keyboard.CODE_PERIOD) { reswapPeriodAndSpace(); } TextEntryState.typedCharacter((char) primaryCode, true); if (TextEntryState.getState() == TextEntryState.State.PUNCTUATION_AFTER_ACCEPTED - && primaryCode != KEYCODE_ENTER) { + && primaryCode != Keyboard.CODE_ENTER) { swapPunctuationAndSpace(); - } else if (isPredictionOn() && primaryCode == KEYCODE_SPACE) { + } else if (isPredictionOn() && primaryCode == Keyboard.CODE_SPACE) { doubleSpace(); } if (pickedDefault) { @@ -1629,7 +1626,7 @@ public class LatinIME extends InputMethodService // Fool the state watcher so that a subsequent backspace will not do a revert, unless // we just did a correction, in which case we need to stay in // TextEntryState.State.PICKED_SUGGESTION state. - TextEntryState.typedCharacter((char) KEYCODE_SPACE, true); + TextEntryState.typedCharacter((char) Keyboard.CODE_SPACE, true); setPunctuationSuggestions(); } else if (!showingAddToDictionaryHint) { // If we're not showing the "Touch again to save", then show corrections again. @@ -1857,7 +1854,7 @@ public class LatinIME extends InputMethodService } private void sendSpace() { - sendKeyChar((char)KEYCODE_SPACE); + sendKeyChar((char)Keyboard.CODE_SPACE); mKeyboardSwitcher.updateShiftState(); //onKey(KEY_SPACE[0], KEY_SPACE); } @@ -1930,9 +1927,9 @@ public class LatinIME extends InputMethodService playKeyClick(primaryCode); KeyboardSwitcher switcher = mKeyboardSwitcher; final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); - if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) { + if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { switcher.onPressShift(); - } else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) { + } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_MODE_CHANGE) { switcher.onPressSymbol(); } else { switcher.onOtherKeyPressed(); @@ -1945,9 +1942,9 @@ public class LatinIME extends InputMethodService // Reset any drag flags in the keyboard switcher.keyReleased(); final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); - if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) { + if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { switcher.onReleaseShift(); - } else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) { + } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_MODE_CHANGE) { switcher.onReleaseSymbol(); } } @@ -1984,13 +1981,13 @@ public class LatinIME extends InputMethodService // FIXME: These should be triggered after auto-repeat logic int sound = AudioManager.FX_KEYPRESS_STANDARD; switch (primaryCode) { - case Keyboard.KEYCODE_DELETE: + case Keyboard.CODE_DELETE: sound = AudioManager.FX_KEYPRESS_DELETE; break; - case KEYCODE_ENTER: + case Keyboard.CODE_ENTER: sound = AudioManager.FX_KEYPRESS_RETURN; break; - case KEYCODE_SPACE: + case Keyboard.CODE_SPACE: sound = AudioManager.FX_KEYPRESS_SPACEBAR; break; } diff --git a/java/src/com/android/inputmethod/latin/LatinIMESettings.java b/java/src/com/android/inputmethod/latin/LatinIMESettings.java index 187b6d394..3aa89dd59 100644 --- a/java/src/com/android/inputmethod/latin/LatinIMESettings.java +++ b/java/src/com/android/inputmethod/latin/LatinIMESettings.java @@ -48,7 +48,7 @@ public class LatinIMESettings extends PreferenceActivity private static final String VOICE_SETTINGS_KEY = "voice_mode"; private static final String PREF_AUTO_COMPLETION_THRESHOLD = "auto_completion_threshold"; private static final String PREF_BIGRAM_SUGGESTIONS = "bigram_suggestion"; - /* package */ static final String PREF_SETTINGS_KEY = "settings_key"; + public static final String PREF_SETTINGS_KEY = "settings_key"; /* package */ static final String PREF_VIBRATE_ON = "vibrate_on"; private static final String TAG = "LatinIMESettings"; diff --git a/java/src/com/android/inputmethod/latin/ModifierKeyState.java b/java/src/com/android/inputmethod/latin/ModifierKeyState.java deleted file mode 100644 index eb1204f70..000000000 --- a/java/src/com/android/inputmethod/latin/ModifierKeyState.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. - * - * 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.latin; - -import android.util.Log; - -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 PRESSING = 1; - protected static final int MOMENTARY = 2; - - protected final String mName; - protected int mState = RELEASING; - - public ModifierKeyState(String name) { - mName = name; - } - - public void onPress() { - final int oldState = mState; - mState = PRESSING; - if (DEBUG) - Log.d(TAG, mName + ".onPress: " + toString(oldState) + " > " + this); - } - - public void onRelease() { - final int oldState = mState; - mState = RELEASING; - if (DEBUG) - Log.d(TAG, mName + ".onRelease: " + toString(oldState) + " > " + this); - } - - public void onOtherKeyPressed() { - final int oldState = mState; - if (oldState == PRESSING) - mState = MOMENTARY; - if (DEBUG) - Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this); - } - - public boolean isReleasing() { - return mState == RELEASING; - } - - public boolean isMomentary() { - return mState == MOMENTARY; - } - - @Override - public String toString() { - return toString(mState); - } - - protected String toString(int state) { - switch (state) { - case RELEASING: return "RELEASING"; - case PRESSING: return "PRESSING"; - case MOMENTARY: return "MOMENTARY"; - default: return "UNKNOWN"; - } - } -} diff --git a/java/src/com/android/inputmethod/latin/ShiftKeyState.java b/java/src/com/android/inputmethod/latin/ShiftKeyState.java deleted file mode 100644 index 7412a566d..000000000 --- a/java/src/com/android/inputmethod/latin/ShiftKeyState.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. - * - * 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.latin; - -import android.util.Log; - -public class ShiftKeyState extends ModifierKeyState { - private static final int PRESSING_ON_SHIFTED = 3; // both temporary shifted & shift locked - private static final int IGNORING = 4; - - public ShiftKeyState(String name) { - super(name); - } - - @Override - public void onOtherKeyPressed() { - int oldState = mState; - if (oldState == PRESSING) { - mState = MOMENTARY; - } else if (oldState == PRESSING_ON_SHIFTED) { - mState = IGNORING; - } - if (DEBUG) - Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this); - } - - public void onPressOnShifted() { - int oldState = mState; - mState = PRESSING_ON_SHIFTED; - if (DEBUG) - Log.d(TAG, mName + ".onPressOnShifted: " + toString(oldState) + " > " + this); - } - - public boolean isPressingOnShifted() { - return mState == PRESSING_ON_SHIFTED; - } - - public boolean isIgnoring() { - return mState == IGNORING; - } - - @Override - public String toString() { - return toString(mState); - } - - @Override - protected String toString(int state) { - switch (state) { - case PRESSING_ON_SHIFTED: return "PRESSING_ON_SHIFTED"; - case IGNORING: return "IGNORING"; - default: return super.toString(state); - } - } -} diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index a98917689..3ee4eb891 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -16,7 +16,7 @@ package com.android.inputmethod.latin; -import com.android.inputmethod.keyboard.LatinKeyboard; +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.voice.SettingsUtil; import com.android.inputmethod.voice.VoiceIMEConnector; import com.android.inputmethod.voice.VoiceInput; @@ -198,7 +198,7 @@ public class SubtypeSwitcher { || VoiceIMEConnector.getInstance().needsToShowWarningDialog()) { if (mVoiceInput != null) { // TODO: Call proper function to trigger VoiceIME - mService.onKey(LatinKeyboard.KEYCODE_VOICE, null, 0, 0); + mService.onKey(Keyboard.CODE_VOICE, null, 0, 0); } } } else { @@ -351,7 +351,7 @@ public class SubtypeSwitcher { if (DBG) { Log.d(TAG, "Set and call voice input."); } - mService.onKey(LatinKeyboard.KEYCODE_VOICE, null, 0, 0); + mService.onKey(Keyboard.CODE_VOICE, null, 0, 0); return true; } } diff --git a/java/src/com/android/inputmethod/latin/TextEntryState.java b/java/src/com/android/inputmethod/latin/TextEntryState.java index 31a192bfe..34babdcb5 100644 --- a/java/src/com/android/inputmethod/latin/TextEntryState.java +++ b/java/src/com/android/inputmethod/latin/TextEntryState.java @@ -261,13 +261,13 @@ public class TextEntryState { } public static void keyPressedAt(Key key, int x, int y) { - if (LOGGING && sKeyLocationFile != null && key.codes[0] >= 32) { - String out = - "KEY: " + (char) key.codes[0] - + " X: " + x + if (LOGGING && sKeyLocationFile != null && key.mCodes[0] >= 32) { + String out = + "KEY: " + (char) key.mCodes[0] + + " X: " + x + " Y: " + y - + " MX: " + (key.x + key.width / 2) - + " MY: " + (key.y + key.height / 2) + + " MX: " + (key.mX + key.mWidth / 2) + + " MY: " + (key.mY + key.mHeight / 2) + "\n"; try { sKeyLocationFile.write(out.getBytes()); diff --git a/java/src/com/android/inputmethod/latin/Tutorial.java b/java/src/com/android/inputmethod/latin/Tutorial.java index bd069bd0d..20767de4d 100644 --- a/java/src/com/android/inputmethod/latin/Tutorial.java +++ b/java/src/com/android/inputmethod/latin/Tutorial.java @@ -16,6 +16,7 @@ package com.android.inputmethod.latin; +import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.LatinKeyboardView; import android.content.Context; diff --git a/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java b/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java index 73b3b19e3..7ad6c35a0 100644 --- a/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java +++ b/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java @@ -16,8 +16,8 @@ package com.android.inputmethod.voice; +import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.latin.EditingUtil; -import com.android.inputmethod.latin.KeyboardSwitcher; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinIME.UIHandler; import com.android.inputmethod.latin.R; -- cgit v1.2.3-83-g751a