Revise caps lock sequences

This change also fixes that the popup preview of ALT on symbol
keyboard is not showing.

Bug: 3122877
Bug: 3127255
Change-Id: I978cb30a0d05298274d8ab6541b91323a0fef211
main
Tadashi G. Takaoka 2010-10-22 19:35:23 +09:00
parent 3296411926
commit 4189eb2308
6 changed files with 151 additions and 93 deletions

View File

@ -28,6 +28,7 @@
<integer name="config_delay_before_key_repeat_start">400</integer>
<integer name="config_key_repeat_interval">50</integer>
<integer name="config_long_press_key_timeout">400</integer>
<integer name="config_long_press_shift_key_timeout">1000</integer>
<integer name="config_multi_tap_key_timeout">800</integer>
<string-array name="auto_complete_threshold_values">
<!-- Off, When auto completing setting is Off, this value is not used. -->

View File

@ -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())

View File

@ -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()) {

View File

@ -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(

View File

@ -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;

View File

@ -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() {