Retain keyboard layout while orientation change

This change also changes the timimng that the window width is
registered.

Bug: 4311428
Change-Id: Ied6b1b43bfa16a85f0e05cd308ce919d5d65677e
main
Tadashi G. Takaoka 2011-07-29 10:45:37 -07:00
parent 047f63f559
commit 055054eef3
2 changed files with 119 additions and 24 deletions

View File

@ -82,6 +82,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
// system navigation bar. // system navigation bar.
private WindowWidthCache mWindowWidthCache; private WindowWidthCache mWindowWidthCache;
private KeyboardLayoutState mSavedKeyboardState = new KeyboardLayoutState();
/** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of /** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of
* what user actually typed. */ * what user actually typed. */
private boolean mIsAutoCorrectionActive; 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() { public static KeyboardSwitcher getInstance() {
return sInstance; return sInstance;
} }
@ -220,22 +267,34 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
} }
public void loadKeyboard(EditorInfo editorInfo, Settings.Values settingsValues) { public void loadKeyboard(EditorInfo editorInfo, Settings.Values settingsValues) {
mSwitchState = SWITCH_STATE_ALPHA;
try { try {
mMainKeyboardId = getKeyboardId(editorInfo, false, false, settingsValues); mMainKeyboardId = getKeyboardId(editorInfo, false, false, settingsValues);
mSymbolsKeyboardId = getKeyboardId(editorInfo, true, false, settingsValues); mSymbolsKeyboardId = getKeyboardId(editorInfo, true, false, settingsValues);
mSymbolsShiftedKeyboardId = getKeyboardId(editorInfo, true, true, settingsValues); mSymbolsShiftedKeyboardId = getKeyboardId(editorInfo, true, true, settingsValues);
setKeyboard(getKeyboard(mMainKeyboardId)); setKeyboard(getKeyboard(mSavedKeyboardState.getKeyboardId()));
updateShiftState();
} catch (RuntimeException e) { } catch (RuntimeException e) {
Log.w(TAG, "loading keyboard failed: " + mMainKeyboardId, e); Log.w(TAG, "loading keyboard failed: " + mMainKeyboardId, e);
LatinImeLogger.logOnException(mMainKeyboardId.toString(), e); LatinImeLogger.logOnException(mMainKeyboardId.toString(), e);
} }
} }
public KeyboardLayoutState getKeyboardState() {
return mSavedKeyboardState;
}
public void onFinishInputView() {
mIsAutoCorrectionActive = false;
}
public void onHideWindow() { public void onHideWindow() {
mIsAutoCorrectionActive = false; mIsAutoCorrectionActive = false;
} }
public void registerWindowWidth() {
mWindowWidthCache.registerWidth();
}
@SuppressWarnings("unused") @SuppressWarnings("unused")
public void onSizeChanged(int w, int h, int oldw, int oldh) { public void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO: This hack should be removed when display metric returns a proper width. // TODO: This hack should be removed when display metric returns a proper width.
@ -248,21 +307,41 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
return; return;
// Reload keyboard with new width. // Reload keyboard with new width.
final KeyboardId newId = mCurrentId.cloneWithNewGeometry(conf.orientation, width); final KeyboardId newId = mCurrentId.cloneWithNewGeometry(conf.orientation, width);
mInputMethodService.mHandler.postRestoreKeyboardLayout();
setKeyboard(getKeyboard(newId)); setKeyboard(getKeyboard(newId));
} }
private void setKeyboard(final Keyboard newKeyboard) { private void setKeyboard(final Keyboard keyboard) {
final Keyboard oldKeyboard = mKeyboardView.getKeyboard(); final Keyboard oldKeyboard = mKeyboardView.getKeyboard();
mKeyboardView.setKeyboard(newKeyboard); mKeyboardView.setKeyboard(keyboard);
mCurrentId = newKeyboard.mId; mCurrentId = keyboard.mId;
mSwitchState = getSwitchState(mCurrentId);
updateShiftLockState(keyboard);
mKeyboardView.setKeyPreviewPopupEnabled( mKeyboardView.setKeyPreviewPopupEnabled(
Settings.Values.isKeyPreviewPopupEnabled(mPrefs, mResources), Settings.Values.isKeyPreviewPopupEnabled(mPrefs, mResources),
Settings.Values.getKeyPreviewPopupDismissDelay(mPrefs, mResources)); Settings.Values.getKeyPreviewPopupDismissDelay(mPrefs, mResources));
final boolean localeChanged = (oldKeyboard == null) final boolean localeChanged = (oldKeyboard == null)
|| !newKeyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale); || !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged); 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) { private LatinKeyboard getKeyboard(KeyboardId id) {
final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id); final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id);
LatinKeyboard keyboard = (ref == null) ? null : ref.get(); LatinKeyboard keyboard = (ref == null) ? null : ref.get();
@ -605,7 +684,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
+ " symbolKeyState=" + mSymbolKeyState); + " symbolKeyState=" + mSymbolKeyState);
mShiftKeyState.onOtherKeyPressed(); mShiftKeyState.onOtherKeyPressed();
mSymbolKeyState.onOtherKeyPressed(); mSymbolKeyState.onOtherKeyPressed();
mWindowWidthCache.registerWidth();
} }
public void onCancelInput() { public void onCancelInput() {
@ -626,15 +704,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
if (mCurrentId.equals(mSymbolsKeyboardId) if (mCurrentId.equals(mSymbolsKeyboardId)
|| !mCurrentId.equals(mSymbolsShiftedKeyboardId)) { || !mCurrentId.equals(mSymbolsShiftedKeyboardId)) {
keyboard = getKeyboard(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 { } else {
keyboard = getKeyboard(mSymbolsKeyboardId); 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); setKeyboard(keyboard);
} }
@ -655,10 +726,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private void toggleKeyboardMode() { private void toggleKeyboardMode() {
if (mCurrentId.equals(mMainKeyboardId)) { if (mCurrentId.equals(mMainKeyboardId)) {
setKeyboard(getKeyboard(mSymbolsKeyboardId)); setKeyboard(getKeyboard(mSymbolsKeyboardId));
mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
} else { } else {
setKeyboard(getKeyboard(mMainKeyboardId)); 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.Keyboard;
import com.android.inputmethod.keyboard.KeyboardActionListener; import com.android.inputmethod.keyboard.KeyboardActionListener;
import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.KeyboardSwitcher.KeyboardLayoutState;
import com.android.inputmethod.keyboard.KeyboardView; import com.android.inputmethod.keyboard.KeyboardView;
import com.android.inputmethod.keyboard.LatinKeyboard; import com.android.inputmethod.keyboard.LatinKeyboard;
import com.android.inputmethod.keyboard.LatinKeyboardView; 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. // Key events coming any faster than this are long-presses.
private static final int QUICK_PRESS = 200; 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, * The name of the scheme used by the Package Manager to warn of a new package installation,
* replacement or removal. * 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_SET_BIGRAM_PREDICTIONS = 7;
private static final int MSG_CONFIRM_ORIENTATION_CHANGE = 8; private static final int MSG_CONFIRM_ORIENTATION_CHANGE = 8;
private static final int MSG_START_INPUT_VIEW = 9; private static final int MSG_START_INPUT_VIEW = 9;
private static final int MSG_RESTORE_KEYBOARD_LAYOUT = 10;
private static class OrientationChangeArgs { private static class OrientationChangeArgs {
public final int mOldWidth; public final int mOldWidth;
@ -302,6 +308,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
case MSG_START_INPUT_VIEW: case MSG_START_INPUT_VIEW:
latinIme.onStartInputView((EditorInfo)msg.obj, false); latinIme.onStartInputView((EditorInfo)msg.obj, false);
break; 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); 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) { private void postConfirmOrientationChange(OrientationChangeArgs args) {
removeMessages(MSG_CONFIRM_ORIENTATION_CHANGE); removeMessages(MSG_CONFIRM_ORIENTATION_CHANGE);
// Will confirm whether orientation change has finished or not after 2ms again. // Will confirm whether orientation change has finished or not again.
sendMessageDelayed(obtainMessage(MSG_CONFIRM_ORIENTATION_CHANGE, args), 2); sendMessageDelayed(obtainMessage(MSG_CONFIRM_ORIENTATION_CHANGE, args),
SCREEN_ORIENTATION_CHANGE_DETECTION_DELAY);
} }
public void startOrientationChanging(int oldw, int oldh) { public void startOrientationChanging(int oldw, int oldh) {
postConfirmOrientationChange(new OrientationChangeArgs(oldw, oldh)); postConfirmOrientationChange(new OrientationChangeArgs(oldw, oldh));
final LatinIME latinIme = getOuterInstance();
latinIme.mKeyboardSwitcher.getKeyboardState().save();
postRestoreKeyboardLayout();
} }
public boolean postStartInputView(EditorInfo attribute) { public boolean postStartInputView(EditorInfo attribute) {
@ -407,7 +432,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
removeMessages(MSG_START_INPUT_VIEW); removeMessages(MSG_START_INPUT_VIEW);
// Postpone onStartInputView 20ms afterward and see if orientation change has // Postpone onStartInputView 20ms afterward and see if orientation change has
// finished. // finished.
sendMessageDelayed(obtainMessage(MSG_START_INPUT_VIEW, attribute), 20); sendMessageDelayed(obtainMessage(MSG_START_INPUT_VIEW, attribute),
ACCUMULATE_START_INPUT_VIEW_DELAY);
return true; return true;
} }
return false; return false;
@ -596,6 +622,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override @Override
public void onStartInputView(EditorInfo attribute, boolean restarting) { public void onStartInputView(EditorInfo attribute, boolean restarting) {
mHandler.postRestoreKeyboardLayout();
if (mHandler.postStartInputView(attribute)) { if (mHandler.postStartInputView(attribute)) {
return; return;
} }
@ -649,7 +676,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (mSubtypeSwitcher.isKeyboardMode()) { if (mSubtypeSwitcher.isKeyboardMode()) {
switcher.loadKeyboard(attribute, mSettingsValues); switcher.loadKeyboard(attribute, mSettingsValues);
switcher.updateShiftState();
} }
if (mCandidateView != null) if (mCandidateView != null)
@ -738,7 +764,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
super.onFinishInput(); super.onFinishInput();
LatinImeLogger.commit(); LatinImeLogger.commit();
mKeyboardSwitcher.onAutoCorrectionStateChanged(false);
mVoiceProxy.flushVoiceInputLogs(mConfigurationChanging); mVoiceProxy.flushVoiceInputLogs(mConfigurationChanging);
@ -751,6 +776,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override @Override
public void onFinishInputView(boolean finishingInput) { public void onFinishInputView(boolean finishingInput) {
super.onFinishInputView(finishingInput); super.onFinishInputView(finishingInput);
mKeyboardSwitcher.onFinishInputView();
KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
if (inputView != null) inputView.cancelAllMessages(); if (inputView != null) inputView.cancelAllMessages();
// Remove pending messages related to update suggestions // Remove pending messages related to update suggestions
@ -1962,16 +1988,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettingsValues); mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettingsValues);
initSuggest(); initSuggest();
loadSettings(); loadSettings();
mKeyboardSwitcher.updateShiftState();
} }
@Override @Override
public void onPress(int primaryCode, boolean withSliding) { public void onPress(int primaryCode, boolean withSliding) {
if (mKeyboardSwitcher.isVibrateAndSoundFeedbackRequired()) { final KeyboardSwitcher switcher = mKeyboardSwitcher;
switcher.registerWindowWidth();
if (switcher.isVibrateAndSoundFeedbackRequired()) {
vibrate(); vibrate();
playKeyClick(primaryCode); playKeyClick(primaryCode);
} }
KeyboardSwitcher switcher = mKeyboardSwitcher;
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) {
switcher.onPressShift(withSliding); switcher.onPressShift(withSliding);