Merge "Retain keyboard layout while orientation change"

main
Tadashi G. Takaoka 2011-08-03 02:37:00 -07:00 committed by Android (Google) Code Review
commit eedfef0308
2 changed files with 119 additions and 24 deletions

View File

@ -82,6 +82,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
// system navigation bar.
private WindowWidthCache mWindowWidthCache;
private KeyboardLayoutState mSavedKeyboardState = new KeyboardLayoutState();
/** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of
* what user actually typed. */
private boolean mIsAutoCorrectionActive;
@ -174,6 +176,51 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
}
}
public class KeyboardLayoutState {
private boolean mIsValid;
private boolean mIsAlphabetMode;
private boolean mIsShiftLocked;
private boolean mIsShifted;
public boolean isValid() {
return mIsValid;
}
public void save() {
mIsAlphabetMode = isAlphabetMode();
mIsShiftLocked = mIsAlphabetMode && isShiftLocked();
mIsShifted = !mIsShiftLocked && isShiftedOrShiftLocked();
mIsValid = true;
}
public KeyboardId getKeyboardId() {
if (!mIsValid) return mMainKeyboardId;
if (mIsAlphabetMode) {
return mMainKeyboardId;
} else {
return mIsShifted ? mSymbolsShiftedKeyboardId : mSymbolsKeyboardId;
}
}
public void restore() {
if (!mIsValid) return;
mIsValid = false;
if (mIsAlphabetMode) {
final boolean isAlphabetMode = isAlphabetMode();
final boolean isShiftLocked = isAlphabetMode && isShiftLocked();
final boolean isShifted = !isShiftLocked && isShiftedOrShiftLocked();
if (mIsShiftLocked != isShiftLocked) {
toggleCapsLock();
} else if (mIsShifted != isShifted) {
onPressShift(false);
onReleaseShift(false);
}
}
}
}
public static KeyboardSwitcher getInstance() {
return sInstance;
}
@ -220,22 +267,34 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
}
public void loadKeyboard(EditorInfo editorInfo, Settings.Values settingsValues) {
mSwitchState = SWITCH_STATE_ALPHA;
try {
mMainKeyboardId = getKeyboardId(editorInfo, false, false, settingsValues);
mSymbolsKeyboardId = getKeyboardId(editorInfo, true, false, settingsValues);
mSymbolsShiftedKeyboardId = getKeyboardId(editorInfo, true, true, settingsValues);
setKeyboard(getKeyboard(mMainKeyboardId));
setKeyboard(getKeyboard(mSavedKeyboardState.getKeyboardId()));
updateShiftState();
} catch (RuntimeException e) {
Log.w(TAG, "loading keyboard failed: " + mMainKeyboardId, e);
LatinImeLogger.logOnException(mMainKeyboardId.toString(), e);
}
}
public KeyboardLayoutState getKeyboardState() {
return mSavedKeyboardState;
}
public void onFinishInputView() {
mIsAutoCorrectionActive = false;
}
public void onHideWindow() {
mIsAutoCorrectionActive = false;
}
public void registerWindowWidth() {
mWindowWidthCache.registerWidth();
}
@SuppressWarnings("unused")
public void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO: This hack should be removed when display metric returns a proper width.
@ -248,21 +307,41 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
return;
// Reload keyboard with new width.
final KeyboardId newId = mCurrentId.cloneWithNewGeometry(conf.orientation, width);
mInputMethodService.mHandler.postRestoreKeyboardLayout();
setKeyboard(getKeyboard(newId));
}
private void setKeyboard(final Keyboard newKeyboard) {
private void setKeyboard(final Keyboard keyboard) {
final Keyboard oldKeyboard = mKeyboardView.getKeyboard();
mKeyboardView.setKeyboard(newKeyboard);
mCurrentId = newKeyboard.mId;
mKeyboardView.setKeyboard(keyboard);
mCurrentId = keyboard.mId;
mSwitchState = getSwitchState(mCurrentId);
updateShiftLockState(keyboard);
mKeyboardView.setKeyPreviewPopupEnabled(
Settings.Values.isKeyPreviewPopupEnabled(mPrefs, mResources),
Settings.Values.getKeyPreviewPopupDismissDelay(mPrefs, mResources));
final boolean localeChanged = (oldKeyboard == null)
|| !newKeyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
|| !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged);
}
private int getSwitchState(KeyboardId id) {
return id.equals(mMainKeyboardId) ? SWITCH_STATE_ALPHA : SWITCH_STATE_SYMBOL_BEGIN;
}
private void updateShiftLockState(Keyboard keyboard) {
if (mCurrentId.equals(mSymbolsShiftedKeyboardId)) {
// Symbol keyboard may have an ALT key that has a caps lock style indicator (a.k.a.
// sticky shift key). To show or dismiss the indicator, we need to call setShiftLocked()
// that takes care of the current keyboard having such ALT key or not.
keyboard.setShiftLocked(keyboard.hasShiftLockKey());
} else if (mCurrentId.equals(mSymbolsKeyboardId)) {
// Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the
// indicator, we need to call setShiftLocked(false).
keyboard.setShiftLocked(false);
}
}
private LatinKeyboard getKeyboard(KeyboardId id) {
final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id);
LatinKeyboard keyboard = (ref == null) ? null : ref.get();
@ -605,7 +684,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
+ " symbolKeyState=" + mSymbolKeyState);
mShiftKeyState.onOtherKeyPressed();
mSymbolKeyState.onOtherKeyPressed();
mWindowWidthCache.registerWidth();
}
public void onCancelInput() {
@ -626,15 +704,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
if (mCurrentId.equals(mSymbolsKeyboardId)
|| !mCurrentId.equals(mSymbolsShiftedKeyboardId)) {
keyboard = getKeyboard(mSymbolsShiftedKeyboardId);
// Symbol keyboard may have an ALT key that has a caps lock style indicator (a.k.a.
// sticky shift key). To show or dismiss the indicator, we need to call setShiftLocked()
// that takes care of the current keyboard having such ALT key or not.
keyboard.setShiftLocked(keyboard.hasShiftLockKey());
} else {
keyboard = getKeyboard(mSymbolsKeyboardId);
// Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the
// indicator, we need to call setShiftLocked(false).
keyboard.setShiftLocked(false);
}
setKeyboard(keyboard);
}
@ -655,10 +726,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private void toggleKeyboardMode() {
if (mCurrentId.equals(mMainKeyboardId)) {
setKeyboard(getKeyboard(mSymbolsKeyboardId));
mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
} else {
setKeyboard(getKeyboard(mMainKeyboardId));
mSwitchState = SWITCH_STATE_ALPHA;
}
}

View File

@ -64,6 +64,7 @@ import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardActionListener;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.KeyboardSwitcher.KeyboardLayoutState;
import com.android.inputmethod.keyboard.KeyboardView;
import com.android.inputmethod.keyboard.LatinKeyboard;
import com.android.inputmethod.keyboard.LatinKeyboardView;
@ -112,6 +113,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Key events coming any faster than this are long-presses.
private static final int QUICK_PRESS = 200;
private static final int SCREEN_ORIENTATION_CHANGE_DETECTION_DELAY = 2;
private static final int ACCUMULATE_START_INPUT_VIEW_DELAY = 20;
private static final int RESTORE_KEYBOARD_STATE_DELAY = 200;
/**
* The name of the scheme used by the Package Manager to warn of a new package installation,
* replacement or removal.
@ -218,6 +223,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private static final int MSG_SET_BIGRAM_PREDICTIONS = 7;
private static final int MSG_CONFIRM_ORIENTATION_CHANGE = 8;
private static final int MSG_START_INPUT_VIEW = 9;
private static final int MSG_RESTORE_KEYBOARD_LAYOUT = 10;
private static class OrientationChangeArgs {
public final int mOldWidth;
@ -302,6 +308,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
case MSG_START_INPUT_VIEW:
latinIme.onStartInputView((EditorInfo)msg.obj, false);
break;
case MSG_RESTORE_KEYBOARD_LAYOUT:
removeMessages(MSG_UPDATE_SHIFT_STATE);
((KeyboardLayoutState)msg.obj).restore();
break;
}
}
@ -392,14 +402,29 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return hasMessages(MSG_SPACE_TYPED);
}
public void postRestoreKeyboardLayout() {
final LatinIME latinIme = getOuterInstance();
final KeyboardLayoutState state = latinIme.mKeyboardSwitcher.getKeyboardState();
if (state.isValid()) {
removeMessages(MSG_RESTORE_KEYBOARD_LAYOUT);
sendMessageDelayed(
obtainMessage(MSG_RESTORE_KEYBOARD_LAYOUT, state),
RESTORE_KEYBOARD_STATE_DELAY);
}
}
private void postConfirmOrientationChange(OrientationChangeArgs args) {
removeMessages(MSG_CONFIRM_ORIENTATION_CHANGE);
// Will confirm whether orientation change has finished or not after 2ms again.
sendMessageDelayed(obtainMessage(MSG_CONFIRM_ORIENTATION_CHANGE, args), 2);
// Will confirm whether orientation change has finished or not again.
sendMessageDelayed(obtainMessage(MSG_CONFIRM_ORIENTATION_CHANGE, args),
SCREEN_ORIENTATION_CHANGE_DETECTION_DELAY);
}
public void startOrientationChanging(int oldw, int oldh) {
postConfirmOrientationChange(new OrientationChangeArgs(oldw, oldh));
final LatinIME latinIme = getOuterInstance();
latinIme.mKeyboardSwitcher.getKeyboardState().save();
postRestoreKeyboardLayout();
}
public boolean postStartInputView(EditorInfo attribute) {
@ -407,7 +432,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
removeMessages(MSG_START_INPUT_VIEW);
// Postpone onStartInputView 20ms afterward and see if orientation change has
// finished.
sendMessageDelayed(obtainMessage(MSG_START_INPUT_VIEW, attribute), 20);
sendMessageDelayed(obtainMessage(MSG_START_INPUT_VIEW, attribute),
ACCUMULATE_START_INPUT_VIEW_DELAY);
return true;
}
return false;
@ -596,6 +622,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override
public void onStartInputView(EditorInfo attribute, boolean restarting) {
mHandler.postRestoreKeyboardLayout();
if (mHandler.postStartInputView(attribute)) {
return;
}
@ -649,7 +676,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (mSubtypeSwitcher.isKeyboardMode()) {
switcher.loadKeyboard(attribute, mSettingsValues);
switcher.updateShiftState();
}
if (mCandidateView != null)
@ -738,7 +764,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
super.onFinishInput();
LatinImeLogger.commit();
mKeyboardSwitcher.onAutoCorrectionStateChanged(false);
mVoiceProxy.flushVoiceInputLogs(mConfigurationChanging);
@ -751,6 +776,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override
public void onFinishInputView(boolean finishingInput) {
super.onFinishInputView(finishingInput);
mKeyboardSwitcher.onFinishInputView();
KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
if (inputView != null) inputView.cancelAllMessages();
// Remove pending messages related to update suggestions
@ -1962,16 +1988,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettingsValues);
initSuggest();
loadSettings();
mKeyboardSwitcher.updateShiftState();
}
@Override
public void onPress(int primaryCode, boolean withSliding) {
if (mKeyboardSwitcher.isVibrateAndSoundFeedbackRequired()) {
final KeyboardSwitcher switcher = mKeyboardSwitcher;
switcher.registerWindowWidth();
if (switcher.isVibrateAndSoundFeedbackRequired()) {
vibrate();
playKeyClick(primaryCode);
}
KeyboardSwitcher switcher = mKeyboardSwitcher;
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) {
switcher.onPressShift(withSliding);