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_delay_before_key_repeat_start">400</integer>
<integer name="config_key_repeat_interval">50</integer> <integer name="config_key_repeat_interval">50</integer>
<integer name="config_long_press_key_timeout">400</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> <integer name="config_multi_tap_key_timeout">800</integer>
<string-array name="auto_complete_threshold_values"> <string-array name="auto_complete_threshold_values">
<!-- Off, When auto completing setting is Off, this value is not used. --> <!-- 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. // Key events coming any faster than this are long-presses.
private static final int QUICK_PRESS = 200; private static final int QUICK_PRESS = 200;
static final int KEYCODE_ENTER = '\n'; public static final int KEYCODE_ENTER = '\n';
static final int KEYCODE_SPACE = ' '; public static final int KEYCODE_TAB = '\t';
static final int KEYCODE_PERIOD = '.'; public static final int KEYCODE_SPACE = ' ';
public static final int KEYCODE_PERIOD = '.';
// Contextual menu positions // Contextual menu positions
private static final int POS_METHOD = 0; private static final int POS_METHOD = 0;
@ -1190,8 +1191,7 @@ public class LatinIME extends InputMethodService
public void onKey(int primaryCode, int[] keyCodes, int x, int y) { public void onKey(int primaryCode, int[] keyCodes, int x, int y) {
long when = SystemClock.uptimeMillis(); long when = SystemClock.uptimeMillis();
if (primaryCode != BaseKeyboard.KEYCODE_DELETE || if (primaryCode != BaseKeyboard.KEYCODE_DELETE || when > mLastKeyTime + QUICK_PRESS) {
when > mLastKeyTime + QUICK_PRESS) {
mDeleteCount = 0; mDeleteCount = 0;
} }
mLastKeyTime = when; mLastKeyTime = when;
@ -1229,12 +1229,15 @@ public class LatinIME extends InputMethodService
case LatinKeyboardView.KEYCODE_PREV_LANGUAGE: case LatinKeyboardView.KEYCODE_PREV_LANGUAGE:
toggleLanguage(false, false); toggleLanguage(false, false);
break; break;
case LatinKeyboardView.KEYCODE_CAPSLOCK:
handleCapsLock();
break;
case LatinKeyboardView.KEYCODE_VOICE: case LatinKeyboardView.KEYCODE_VOICE:
if (VOICE_INSTALLED) { if (VOICE_INSTALLED) {
startListening(false /* was a button press, was not a swipe */); startListening(false /* was a button press, was not a swipe */);
} }
break; break;
case 9 /*Tab*/: case KEYCODE_TAB:
sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB);
break; break;
default: default:
@ -1363,24 +1366,37 @@ public class LatinIME extends InputMethodService
private void handleShiftInternal(boolean forceNormal) { private void handleShiftInternal(boolean forceNormal) {
mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE); mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE);
KeyboardSwitcher switcher = mKeyboardSwitcher; KeyboardSwitcher switcher = mKeyboardSwitcher;
LatinKeyboardView inputView = switcher.getInputView();
if (switcher.isAlphabetMode()) { if (switcher.isAlphabetMode()) {
LatinKeyboardView inputView = switcher.getInputView();
if (mCapsLock || forceNormal) { if (mCapsLock || forceNormal) {
mCapsLock = false; mCapsLock = false;
switcher.setShifted(false); switcher.setShifted(false);
} else if (inputView != null) { } else if (inputView != null) {
if (inputView.isShifted()) { switcher.setShifted(!inputView.isShifted());
mCapsLock = true;
switcher.setShiftLocked(true);
} else {
switcher.setShifted(true);
}
} }
} else { } else {
switcher.toggleShift(); 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) { private void abortCorrection(boolean force) {
if (force || TextEntryState.isCorrecting()) { if (force || TextEntryState.isCorrecting()) {
getCurrentInputConnection().finishComposingText(); getCurrentInputConnection().finishComposingText();
@ -2291,6 +2307,8 @@ public class LatinIME extends InputMethodService
final boolean distinctMultiTouch = mKeyboardSwitcher.hasDistinctMultitouch(); final boolean distinctMultiTouch = mKeyboardSwitcher.hasDistinctMultitouch();
if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) { if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) {
mShiftKeyState.onPress(); mShiftKeyState.onPress();
// Not in caps lock mode, shift key is in effect on pressed.
if (mKeyboardSwitcher.isAlphabetMode() && !mCapsLock)
handleShift(); handleShift();
} else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) { } else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) {
mSymbolKeyState.onPress(); mSymbolKeyState.onPress();
@ -2309,6 +2327,9 @@ public class LatinIME extends InputMethodService
if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) { if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) {
if (mShiftKeyState.isMomentary()) if (mShiftKeyState.isMomentary())
resetShift(); resetShift();
// In caps lock mode, shift key is in effect on released.
if (mKeyboardSwitcher.isAlphabetMode() && mCapsLock)
handleShift();
mShiftKeyState.onRelease(); mShiftKeyState.onRelease();
} else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) { } else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) {
if (mSymbolKeyState.isMomentary()) if (mSymbolKeyState.isMomentary())

View File

@ -236,6 +236,7 @@ public class LatinKeyboard extends BaseKeyboard {
} }
public void setShiftLocked(boolean shiftLocked) { public void setShiftLocked(boolean shiftLocked) {
// TODO: cleanup this method with BaseKeyboard.Key
for (final Key key : getShiftKeys()) { for (final Key key : getShiftKeys()) {
key.on = shiftLocked; key.on = shiftLocked;
key.icon = mShiftLockIcon; key.icon = mShiftLockIcon;
@ -249,6 +250,7 @@ public class LatinKeyboard extends BaseKeyboard {
@Override @Override
public boolean setShifted(boolean shiftState) { public boolean setShifted(boolean shiftState) {
// TODO: cleanup this method with BaseKeyboard.Key.
boolean shiftChanged = false; boolean shiftChanged = false;
if (getShiftKeys().size() > 0) { if (getShiftKeys().size() > 0) {
for (final Key key : getShiftKeys()) { 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_DISMISS_PREVIEW = 2;
private static final int MSG_REPEAT_KEY = 3; private static final int MSG_REPEAT_KEY = 3;
private static final int MSG_LONGPRESS_KEY = 4; private static final int MSG_LONGPRESS_KEY = 4;
private static final int MSG_LONGPRESS_SHIFT_KEY = 5;
private boolean mInKeyRepeat; private boolean mInKeyRepeat;
@ -284,6 +285,11 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
openPopupIfRequired(msg.arg1, tracker); openPopupIfRequired(msg.arg1, tracker);
break; 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); 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() { public void cancelKeyTimers() {
cancelKeyRepeatTimer(); cancelKeyRepeatTimer();
cancelLongPressTimer(); cancelLongPressTimer();
cancelLongPressShiftTimer();
} }
public void cancelAllMessages() { 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 drawableX = (key.width + padding.left - padding.right - drawableWidth) / 2;
int drawableY = (key.height + padding.top - padding.bottom - drawableHeight) / 2; int drawableY = (key.height + padding.top - padding.bottom - drawableHeight) / 2;
drawIcon(canvas, key.icon, drawableX, drawableY, drawableWidth, drawableHeight); drawIcon(canvas, key.icon, drawableX, drawableY, drawableWidth, drawableHeight);
} }
if (key.hintIcon != null && drawHintIcon) { if (key.hintIcon != null && drawHintIcon) {
int drawableWidth = key.width; int drawableWidth = key.width;
@ -924,7 +940,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
// TODO: clean up this method. // TODO: clean up this method.
private void dismissKeyPreview() { private void dismissKeyPreview() {
for (PointerTracker tracker : mPointerTrackers) for (PointerTracker tracker : mPointerTrackers)
tracker.updateKey(NOT_A_KEY); tracker.releaseKey();
showPreview(NOT_A_KEY, null); showPreview(NOT_A_KEY, null);
} }
@ -959,11 +975,8 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
// WindowManager.BadTokenException. // WindowManager.BadTokenException.
if (key == null || !mInForeground) if (key == null || !mInForeground)
return; return;
if (key.icon != null) { // What we show as preview should match what we show on key top in onBufferDraw().
mPreviewText.setCompoundDrawables(null, null, null, if (key.label != null) {
key.iconPreview != null ? key.iconPreview : key.icon);
mPreviewText.setText(null);
} else {
// TODO Should take care of temporaryShiftLabel here. // TODO Should take care of temporaryShiftLabel here.
mPreviewText.setCompoundDrawables(null, null, null, null); mPreviewText.setCompoundDrawables(null, null, null, null);
mPreviewText.setText(adjustCase(tracker.getPreviewText(key))); 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.setTextSize(TypedValue.COMPLEX_UNIT_PX, mPreviewTextSizeLarge);
mPreviewText.setTypeface(mKeyTextStyle); 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), mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
@ -1086,6 +1103,12 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
return result; 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) { private View inflateMiniKeyboardContainer(Key popupKey) {
int popupKeyboardId = popupKey.popupResId; int popupKeyboardId = popupKey.popupResId;
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService( LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(

View File

@ -32,12 +32,13 @@ import java.util.List;
public class LatinKeyboardView extends LatinKeyboardBaseView { public class LatinKeyboardView extends LatinKeyboardBaseView {
static final int KEYCODE_OPTIONS = -100; public static final int KEYCODE_OPTIONS = -100;
static final int KEYCODE_OPTIONS_LONGPRESS = -101; public static final int KEYCODE_OPTIONS_LONGPRESS = -101;
static final int KEYCODE_VOICE = -102; public static final int KEYCODE_VOICE = -102;
static final int KEYCODE_F1 = -103; public static final int KEYCODE_F1 = -103;
static final int KEYCODE_NEXT_LANGUAGE = -104; public static final int KEYCODE_NEXT_LANGUAGE = -104;
static final int KEYCODE_PREV_LANGUAGE = -105; public static final int KEYCODE_PREV_LANGUAGE = -105;
public static final int KEYCODE_CAPSLOCK = -106;
private BaseKeyboard mPhoneKeyboard; private BaseKeyboard mPhoneKeyboard;

View File

@ -40,6 +40,7 @@ public class PointerTracker {
// Timing constants // Timing constants
private final int mDelayBeforeKeyRepeatStart; private final int mDelayBeforeKeyRepeatStart;
private final int mLongPressKeyTimeout; private final int mLongPressKeyTimeout;
private final int mLongPressShiftKeyTimeout;
private final int mMultiTapKeyTimeout; private final int mMultiTapKeyTimeout;
// Miscellaneous constants // Miscellaneous constants
@ -175,6 +176,7 @@ public class PointerTracker {
mHasDistinctMultitouch = proxy.hasDistinctMultitouch(); mHasDistinctMultitouch = proxy.hasDistinctMultitouch();
mDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start); mDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start);
mLongPressKeyTimeout = res.getInteger(R.integer.config_long_press_key_timeout); 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); mMultiTapKeyTimeout = res.getInteger(R.integer.config_multi_tap_key_timeout);
resetMultiTap(); resetMultiTap();
} }
@ -223,9 +225,11 @@ public class PointerTracker {
return key != null && key.codes[0] == LatinIME.KEYCODE_SPACE; return key != null && key.codes[0] == LatinIME.KEYCODE_SPACE;
} }
public void updateKey(int keyIndex) { public void releaseKey() {
if (mKeyAlreadyProcessed) updateKeyGraphics(NOT_A_KEY);
return; }
private void updateKeyGraphics(int keyIndex) {
int oldKeyIndex = mPreviousKey; int oldKeyIndex = mPreviousKey;
mPreviousKey = keyIndex; mPreviousKey = keyIndex;
if (keyIndex != oldKeyIndex) { if (keyIndex != oldKeyIndex) {
@ -287,7 +291,7 @@ public class PointerTracker {
} }
startLongPressTimer(keyIndex); startLongPressTimer(keyIndex);
} }
showKeyPreviewAndUpdateKey(keyIndex); showKeyPreviewAndUpdateKeyGraphics(keyIndex);
} }
public void onMoveEvent(int x, int y, long eventTime) { public void onMoveEvent(int x, int y, long eventTime) {
@ -317,12 +321,13 @@ public class PointerTracker {
mHandler.cancelLongPressTimer(); mHandler.cancelLongPressTimer();
} }
} }
showKeyPreviewAndUpdateKey(mKeyState.getKeyIndex()); showKeyPreviewAndUpdateKeyGraphics(mKeyState.getKeyIndex());
} }
public void onUpEvent(int x, int y, long eventTime) { public void onUpEvent(int x, int y, long eventTime) {
if (DEBUG) if (DEBUG)
debugLog("onUpEvent :", x, y); debugLog("onUpEvent :", x, y);
showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY);
if (mKeyAlreadyProcessed) if (mKeyAlreadyProcessed)
return; return;
mHandler.cancelKeyTimers(); mHandler.cancelKeyTimers();
@ -334,7 +339,6 @@ public class PointerTracker {
x = mKeyState.getKeyX(); x = mKeyState.getKeyX();
y = mKeyState.getKeyY(); y = mKeyState.getKeyY();
} }
showKeyPreviewAndUpdateKey(NOT_A_KEY);
if (!mIsRepeatableKey) { if (!mIsRepeatableKey) {
detectAndSendKey(keyIndex, x, y, eventTime); detectAndSendKey(keyIndex, x, y, eventTime);
} }
@ -348,7 +352,7 @@ public class PointerTracker {
debugLog("onCancelEvt:", x, y); debugLog("onCancelEvt:", x, y);
mHandler.cancelKeyTimers(); mHandler.cancelKeyTimers();
mHandler.cancelPopupPreview(); mHandler.cancelPopupPreview();
showKeyPreviewAndUpdateKey(NOT_A_KEY); showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY);
int keyIndex = mKeyState.getKeyIndex(); int keyIndex = mKeyState.getKeyIndex();
if (isValidKeyIndex(keyIndex)) if (isValidKeyIndex(keyIndex))
mProxy.invalidateKey(mKeys[keyIndex]); mProxy.invalidateKey(mKeys[keyIndex]);
@ -409,8 +413,8 @@ public class PointerTracker {
return dx * dx + dy * dy; return dx * dx + dy * dy;
} }
private void showKeyPreviewAndUpdateKey(int keyIndex) { private void showKeyPreviewAndUpdateKeyGraphics(int keyIndex) {
updateKey(keyIndex); updateKeyGraphics(keyIndex);
// The modifier key, such as shift key, should not be shown as preview when multi-touch is // 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 // supported. On thge other hand, if multi-touch is not supported, the modifier key should
// be shown as preview. // be shown as preview.
@ -423,12 +427,18 @@ public class PointerTracker {
private void startLongPressTimer(int keyIndex) { private void startLongPressTimer(int keyIndex) {
Key key = getKey(keyIndex); Key key = getKey(keyIndex);
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, // If keyboard is in temporary upper case state and the key has temporary shift label,
// long press should not be started. // 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) if (isTemporaryUpperCase() && key.temporaryShiftLabel != null)
return; return;
mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this); mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this);
} }
}
private boolean isTemporaryUpperCase() { private boolean isTemporaryUpperCase() {
return mKeyboard instanceof LatinKeyboard return mKeyboard instanceof LatinKeyboard