diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index a1577e4d1..410d34b00 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -28,6 +28,7 @@
400
50
400
+ 1000
800
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index bb29e6367..3250cdd01 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -142,9 +142,10 @@ public class LatinIME extends InputMethodService
// Key events coming any faster than this are long-presses.
private static final int QUICK_PRESS = 200;
- static final int KEYCODE_ENTER = '\n';
- static final int KEYCODE_SPACE = ' ';
- static final int KEYCODE_PERIOD = '.';
+ 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;
@@ -1190,66 +1191,68 @@ public class LatinIME extends InputMethodService
public void onKey(int primaryCode, int[] keyCodes, int x, int y) {
long when = SystemClock.uptimeMillis();
- if (primaryCode != BaseKeyboard.KEYCODE_DELETE ||
- when > mLastKeyTime + QUICK_PRESS) {
+ if (primaryCode != BaseKeyboard.KEYCODE_DELETE || when > mLastKeyTime + QUICK_PRESS) {
mDeleteCount = 0;
}
mLastKeyTime = when;
final boolean distinctMultiTouch = mKeyboardSwitcher.hasDistinctMultitouch();
switch (primaryCode) {
- case BaseKeyboard.KEYCODE_DELETE:
- handleBackspace();
- mDeleteCount++;
- LatinImeLogger.logOnDelete();
- break;
- case BaseKeyboard.KEYCODE_SHIFT:
- // Shift key is handled in onPress() when device has distinct multi-touch panel.
- if (!distinctMultiTouch)
- handleShift();
- break;
- case BaseKeyboard.KEYCODE_MODE_CHANGE:
- // Symbol key is handled in onPress() when device has distinct multi-touch panel.
- if (!distinctMultiTouch)
- changeKeyboardMode();
- break;
- case BaseKeyboard.KEYCODE_CANCEL:
- if (!isShowingOptionDialog()) {
- handleClose();
- }
- break;
- case LatinKeyboardView.KEYCODE_OPTIONS:
- onOptionKeyPressed();
- break;
- case LatinKeyboardView.KEYCODE_OPTIONS_LONGPRESS:
- onOptionKeyLongPressed();
- break;
- case LatinKeyboardView.KEYCODE_NEXT_LANGUAGE:
- toggleLanguage(false, true);
- break;
- case LatinKeyboardView.KEYCODE_PREV_LANGUAGE:
- toggleLanguage(false, false);
- break;
- case LatinKeyboardView.KEYCODE_VOICE:
- if (VOICE_INSTALLED) {
- startListening(false /* was a button press, was not a swipe */);
- }
- break;
- case 9 /*Tab*/:
- sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB);
- break;
- default:
- if (primaryCode != KEYCODE_ENTER) {
- mJustAddedAutoSpace = false;
- }
- RingCharBuffer.getInstance().push((char)primaryCode, x, y);
- LatinImeLogger.logOnInputChar();
- if (isWordSeparator(primaryCode)) {
- handleSeparator(primaryCode);
- } else {
- handleCharacter(primaryCode, keyCodes);
- }
- // Cancel the just reverted state
- mJustRevertedSeparator = null;
+ case BaseKeyboard.KEYCODE_DELETE:
+ handleBackspace();
+ mDeleteCount++;
+ LatinImeLogger.logOnDelete();
+ break;
+ case BaseKeyboard.KEYCODE_SHIFT:
+ // Shift key is handled in onPress() when device has distinct multi-touch panel.
+ if (!distinctMultiTouch)
+ handleShift();
+ break;
+ case BaseKeyboard.KEYCODE_MODE_CHANGE:
+ // Symbol key is handled in onPress() when device has distinct multi-touch panel.
+ if (!distinctMultiTouch)
+ changeKeyboardMode();
+ break;
+ case BaseKeyboard.KEYCODE_CANCEL:
+ if (!isShowingOptionDialog()) {
+ handleClose();
+ }
+ break;
+ case LatinKeyboardView.KEYCODE_OPTIONS:
+ onOptionKeyPressed();
+ break;
+ case LatinKeyboardView.KEYCODE_OPTIONS_LONGPRESS:
+ onOptionKeyLongPressed();
+ break;
+ case LatinKeyboardView.KEYCODE_NEXT_LANGUAGE:
+ toggleLanguage(false, true);
+ break;
+ case LatinKeyboardView.KEYCODE_PREV_LANGUAGE:
+ toggleLanguage(false, false);
+ break;
+ case LatinKeyboardView.KEYCODE_CAPSLOCK:
+ handleCapsLock();
+ break;
+ case LatinKeyboardView.KEYCODE_VOICE:
+ if (VOICE_INSTALLED) {
+ startListening(false /* was a button press, was not a swipe */);
+ }
+ break;
+ case KEYCODE_TAB:
+ sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB);
+ break;
+ default:
+ if (primaryCode != KEYCODE_ENTER) {
+ mJustAddedAutoSpace = false;
+ }
+ RingCharBuffer.getInstance().push((char)primaryCode, x, y);
+ LatinImeLogger.logOnInputChar();
+ if (isWordSeparator(primaryCode)) {
+ handleSeparator(primaryCode);
+ } else {
+ handleCharacter(primaryCode, keyCodes);
+ }
+ // Cancel the just reverted state
+ mJustRevertedSeparator = null;
}
if (mKeyboardSwitcher.onKey(primaryCode)) {
changeKeyboardMode();
@@ -1363,24 +1366,37 @@ public class LatinIME extends InputMethodService
private void handleShiftInternal(boolean forceNormal) {
mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE);
KeyboardSwitcher switcher = mKeyboardSwitcher;
- LatinKeyboardView inputView = switcher.getInputView();
if (switcher.isAlphabetMode()) {
+ LatinKeyboardView inputView = switcher.getInputView();
if (mCapsLock || forceNormal) {
mCapsLock = false;
switcher.setShifted(false);
} else if (inputView != null) {
- if (inputView.isShifted()) {
- mCapsLock = true;
- switcher.setShiftLocked(true);
- } else {
- switcher.setShifted(true);
- }
+ switcher.setShifted(!inputView.isShifted());
}
} else {
switcher.toggleShift();
}
}
+ private void handleCapsLock() {
+ mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE);
+ KeyboardSwitcher switcher = mKeyboardSwitcher;
+ if (switcher.isAlphabetMode()) {
+ if (mCapsLock) {
+ mCapsLock = false;
+ // LatinKeyboard.setShifted(false) also disable shift locked state.
+ // Note: Caps lock LED is off when Key.on is false.
+ switcher.setShifted(false);
+ } else {
+ mCapsLock = true;
+ // LatinKeyboard.setShiftLocked(true) enable shift state too.
+ // Note: Caps lock LED is on when Key.on is true.
+ switcher.setShiftLocked(true);
+ }
+ }
+ }
+
private void abortCorrection(boolean force) {
if (force || TextEntryState.isCorrecting()) {
getCurrentInputConnection().finishComposingText();
@@ -2291,7 +2307,9 @@ public class LatinIME extends InputMethodService
final boolean distinctMultiTouch = mKeyboardSwitcher.hasDistinctMultitouch();
if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) {
mShiftKeyState.onPress();
- handleShift();
+ // Not in caps lock mode, shift key is in effect on pressed.
+ if (mKeyboardSwitcher.isAlphabetMode() && !mCapsLock)
+ handleShift();
} else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) {
mSymbolKeyState.onPress();
changeKeyboardMode();
@@ -2309,6 +2327,9 @@ public class LatinIME extends InputMethodService
if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) {
if (mShiftKeyState.isMomentary())
resetShift();
+ // In caps lock mode, shift key is in effect on released.
+ if (mKeyboardSwitcher.isAlphabetMode() && mCapsLock)
+ handleShift();
mShiftKeyState.onRelease();
} else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) {
if (mSymbolKeyState.isMomentary())
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java
index 37ce1e8e4..6494bdfca 100644
--- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java
+++ b/java/src/com/android/inputmethod/latin/LatinKeyboard.java
@@ -236,6 +236,7 @@ public class LatinKeyboard extends BaseKeyboard {
}
public void setShiftLocked(boolean shiftLocked) {
+ // TODO: cleanup this method with BaseKeyboard.Key
for (final Key key : getShiftKeys()) {
key.on = shiftLocked;
key.icon = mShiftLockIcon;
@@ -249,6 +250,7 @@ public class LatinKeyboard extends BaseKeyboard {
@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()) {
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
index 4e264e853..6b46ab838 100644
--- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
+++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
@@ -261,6 +261,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
private static final int MSG_DISMISS_PREVIEW = 2;
private static final int MSG_REPEAT_KEY = 3;
private static final int MSG_LONGPRESS_KEY = 4;
+ private static final int MSG_LONGPRESS_SHIFT_KEY = 5;
private boolean mInKeyRepeat;
@@ -284,6 +285,11 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
openPopupIfRequired(msg.arg1, tracker);
break;
}
+ case MSG_LONGPRESS_SHIFT_KEY: {
+ final PointerTracker tracker = (PointerTracker)msg.obj;
+ onLongPressShiftKey(tracker);
+ break;
+ }
}
}
@@ -335,9 +341,20 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
removeMessages(MSG_LONGPRESS_KEY);
}
+ public void startLongPressShiftTimer(long delay, int keyIndex, PointerTracker tracker) {
+ removeMessages(MSG_LONGPRESS_SHIFT_KEY);
+ sendMessageDelayed(
+ obtainMessage(MSG_LONGPRESS_SHIFT_KEY, keyIndex, 0, tracker), delay);
+ }
+
+ public void cancelLongPressShiftTimer() {
+ removeMessages(MSG_LONGPRESS_SHIFT_KEY);
+ }
+
public void cancelKeyTimers() {
cancelKeyRepeatTimer();
cancelLongPressTimer();
+ cancelLongPressShiftTimer();
}
public void cancelAllMessages() {
@@ -869,7 +886,6 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
int drawableX = (key.width + padding.left - padding.right - drawableWidth) / 2;
int drawableY = (key.height + padding.top - padding.bottom - drawableHeight) / 2;
drawIcon(canvas, key.icon, drawableX, drawableY, drawableWidth, drawableHeight);
-
}
if (key.hintIcon != null && drawHintIcon) {
int drawableWidth = key.width;
@@ -924,7 +940,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
// TODO: clean up this method.
private void dismissKeyPreview() {
for (PointerTracker tracker : mPointerTrackers)
- tracker.updateKey(NOT_A_KEY);
+ tracker.releaseKey();
showPreview(NOT_A_KEY, null);
}
@@ -959,11 +975,8 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
// WindowManager.BadTokenException.
if (key == null || !mInForeground)
return;
- if (key.icon != null) {
- mPreviewText.setCompoundDrawables(null, null, null,
- key.iconPreview != null ? key.iconPreview : key.icon);
- mPreviewText.setText(null);
- } else {
+ // What we show as preview should match what we show on key top in onBufferDraw().
+ if (key.label != null) {
// TODO Should take care of temporaryShiftLabel here.
mPreviewText.setCompoundDrawables(null, null, null, null);
mPreviewText.setText(adjustCase(tracker.getPreviewText(key)));
@@ -974,6 +987,10 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
mPreviewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mPreviewTextSizeLarge);
mPreviewText.setTypeface(mKeyTextStyle);
}
+ } else {
+ mPreviewText.setCompoundDrawables(null, null, null,
+ key.iconPreview != null ? key.iconPreview : key.icon);
+ mPreviewText.setText(null);
}
mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
@@ -1086,6 +1103,12 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
return result;
}
+ private void onLongPressShiftKey(PointerTracker tracker) {
+ tracker.setAlreadyProcessed();
+ mPointerQueue.remove(tracker);
+ mKeyboardActionListener.onKey(LatinKeyboardView.KEYCODE_CAPSLOCK, null, 0, 0);
+ }
+
private View inflateMiniKeyboardContainer(Key popupKey) {
int popupKeyboardId = popupKey.popupResId;
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java
index f3d045bec..35428997f 100644
--- a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java
@@ -32,12 +32,13 @@ import java.util.List;
public class LatinKeyboardView extends LatinKeyboardBaseView {
- static final int KEYCODE_OPTIONS = -100;
- static final int KEYCODE_OPTIONS_LONGPRESS = -101;
- static final int KEYCODE_VOICE = -102;
- static final int KEYCODE_F1 = -103;
- static final int KEYCODE_NEXT_LANGUAGE = -104;
- static final int KEYCODE_PREV_LANGUAGE = -105;
+ public static final int KEYCODE_OPTIONS = -100;
+ public static final int KEYCODE_OPTIONS_LONGPRESS = -101;
+ public static final int KEYCODE_VOICE = -102;
+ public static final int KEYCODE_F1 = -103;
+ public static final int KEYCODE_NEXT_LANGUAGE = -104;
+ public static final int KEYCODE_PREV_LANGUAGE = -105;
+ public static final int KEYCODE_CAPSLOCK = -106;
private BaseKeyboard mPhoneKeyboard;
diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java
index d1cdbfe26..8824db6e3 100644
--- a/java/src/com/android/inputmethod/latin/PointerTracker.java
+++ b/java/src/com/android/inputmethod/latin/PointerTracker.java
@@ -40,6 +40,7 @@ public class PointerTracker {
// Timing constants
private final int mDelayBeforeKeyRepeatStart;
private final int mLongPressKeyTimeout;
+ private final int mLongPressShiftKeyTimeout;
private final int mMultiTapKeyTimeout;
// Miscellaneous constants
@@ -175,6 +176,7 @@ public class PointerTracker {
mHasDistinctMultitouch = proxy.hasDistinctMultitouch();
mDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start);
mLongPressKeyTimeout = res.getInteger(R.integer.config_long_press_key_timeout);
+ mLongPressShiftKeyTimeout = res.getInteger(R.integer.config_long_press_shift_key_timeout);
mMultiTapKeyTimeout = res.getInteger(R.integer.config_multi_tap_key_timeout);
resetMultiTap();
}
@@ -223,9 +225,11 @@ public class PointerTracker {
return key != null && key.codes[0] == LatinIME.KEYCODE_SPACE;
}
- public void updateKey(int keyIndex) {
- if (mKeyAlreadyProcessed)
- return;
+ public void releaseKey() {
+ updateKeyGraphics(NOT_A_KEY);
+ }
+
+ private void updateKeyGraphics(int keyIndex) {
int oldKeyIndex = mPreviousKey;
mPreviousKey = keyIndex;
if (keyIndex != oldKeyIndex) {
@@ -287,7 +291,7 @@ public class PointerTracker {
}
startLongPressTimer(keyIndex);
}
- showKeyPreviewAndUpdateKey(keyIndex);
+ showKeyPreviewAndUpdateKeyGraphics(keyIndex);
}
public void onMoveEvent(int x, int y, long eventTime) {
@@ -317,12 +321,13 @@ public class PointerTracker {
mHandler.cancelLongPressTimer();
}
}
- showKeyPreviewAndUpdateKey(mKeyState.getKeyIndex());
+ showKeyPreviewAndUpdateKeyGraphics(mKeyState.getKeyIndex());
}
public void onUpEvent(int x, int y, long eventTime) {
if (DEBUG)
debugLog("onUpEvent :", x, y);
+ showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY);
if (mKeyAlreadyProcessed)
return;
mHandler.cancelKeyTimers();
@@ -334,7 +339,6 @@ public class PointerTracker {
x = mKeyState.getKeyX();
y = mKeyState.getKeyY();
}
- showKeyPreviewAndUpdateKey(NOT_A_KEY);
if (!mIsRepeatableKey) {
detectAndSendKey(keyIndex, x, y, eventTime);
}
@@ -348,7 +352,7 @@ public class PointerTracker {
debugLog("onCancelEvt:", x, y);
mHandler.cancelKeyTimers();
mHandler.cancelPopupPreview();
- showKeyPreviewAndUpdateKey(NOT_A_KEY);
+ showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY);
int keyIndex = mKeyState.getKeyIndex();
if (isValidKeyIndex(keyIndex))
mProxy.invalidateKey(mKeys[keyIndex]);
@@ -409,8 +413,8 @@ public class PointerTracker {
return dx * dx + dy * dy;
}
- private void showKeyPreviewAndUpdateKey(int keyIndex) {
- updateKey(keyIndex);
+ private void showKeyPreviewAndUpdateKeyGraphics(int keyIndex) {
+ updateKeyGraphics(keyIndex);
// The modifier key, such as shift key, should not be shown as preview when multi-touch is
// supported. On thge other hand, if multi-touch is not supported, the modifier key should
// be shown as preview.
@@ -423,11 +427,17 @@ public class PointerTracker {
private void startLongPressTimer(int keyIndex) {
Key key = getKey(keyIndex);
- // If keyboard is in temporary upper case state and the key has temporary shift label,
- // long press should not be started.
- if (isTemporaryUpperCase() && key.temporaryShiftLabel != null)
- return;
- mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this);
+ if (key.codes[0] == BaseKeyboard.KEYCODE_SHIFT) {
+ mHandler.startLongPressShiftTimer(mLongPressShiftKeyTimeout, keyIndex, this);
+ } else {
+ // If keyboard is in temporary upper case state and the key has temporary shift label,
+ // non-shift long press should not be started. On distinct multi touch device, when
+ // pressing shift key (in temporary upper case), hint icon should not be drawn on key
+ // top. So we should disable long press for such key.
+ if (isTemporaryUpperCase() && key.temporaryShiftLabel != null)
+ return;
+ mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this);
+ }
}
private boolean isTemporaryUpperCase() {