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: I978cb30a0d05298274d8ab6541b91323a0fef211main
parent
3296411926
commit
4189eb2308
|
@ -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. -->
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue