From 717cef79ead5d63a01d09b47caab0a3d719c69df Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" <takaoka@google.com> Date: Tue, 26 Apr 2011 14:27:35 +0900 Subject: [PATCH] Fix quotation marks This change * Allows snap back from symbols shifted to symbol layout. * Add "left single", "right single", "single low" and "single high reversed" quotation marks to popup characters of "single quote". * Add "double low" and "double high reversed" quatation marks to popup characters of "double quote". * Add "prime" and "double prime" to popup characters of "degree". * Disable non-ASCII key of symbol more layout on passowrd input. Bug: 4345054 Bug: 4347045 Change-Id: I8168ce6a74a9536e4966f7f9d1099ac0132925c7 --- java/res/xml-xlarge/kbd_symbols.xml | 3 +- java/res/xml-xlarge/kbd_symbols_shift.xml | 3 +- java/res/xml/kbd_key_styles.xml | 23 ++++ java/res/xml/kbd_symbols.xml | 6 +- java/res/xml/kbd_symbols_shift.xml | 16 ++- java/res/xml/kbd_symbols_shift_row4.xml | 10 +- .../keyboard/KeyboardSwitcher.java | 127 +++++++++++++----- .../inputmethod/keyboard/PointerTracker.java | 2 +- 8 files changed, 146 insertions(+), 44 deletions(-) diff --git a/java/res/xml-xlarge/kbd_symbols.xml b/java/res/xml-xlarge/kbd_symbols.xml index 1061178e09..f1deae0f97 100644 --- a/java/res/xml-xlarge/kbd_symbols.xml +++ b/java/res/xml-xlarge/kbd_symbols.xml @@ -211,9 +211,10 @@ latin:keyLabel="-" /> </case> <default> + <!-- Note: DroidSans doesn't have double-high-reversed-quotation '\u201f' glyph. --> <Key latin:keyLabel=""" - latin:popupCharacters="“,â€,«,»,Ë" /> + latin:popupCharacters="“,â€,„,‟,«,»,‘,’,‚,‛" /> <Key latin:keyLabel="_" /> </default> diff --git a/java/res/xml-xlarge/kbd_symbols_shift.xml b/java/res/xml-xlarge/kbd_symbols_shift.xml index 8359b75714..cc23358a52 100644 --- a/java/res/xml-xlarge/kbd_symbols_shift.xml +++ b/java/res/xml-xlarge/kbd_symbols_shift.xml @@ -99,7 +99,8 @@ latin:popupCharacters="↑,↓,â†,→" /> <Key latin:keyStyle="nonPasswordSymbolKeyStyle" - latin:keyLabel="°" /> + latin:keyLabel="°" + latin:popupCharacters="′,″" /> <Key latin:keyStyle="nonPasswordSymbolKeyStyle" latin:keyLabel="±" diff --git a/java/res/xml/kbd_key_styles.xml b/java/res/xml/kbd_key_styles.xml index 4792e1f006..d4d25d4a29 100644 --- a/java/res/xml/kbd_key_styles.xml +++ b/java/res/xml/kbd_key_styles.xml @@ -312,4 +312,27 @@ latin:popupCharacters="@string/alternates_for_smiley" latin:maxPopupKeyboardColumn="5" latin:parentStyle="functionalKeyStyle" /> + <switch> + <case + latin:passwordInput="true" + > + <key-style + latin:styleName="nonPasswordSymbolKeyStyle" + latin:enabled="false" /> + <key-style + latin:styleName="nonPasswordFunctionalKeyStyle" + latin:enabled="false" + latin:parentStyle="functionalKeyStyle" /> + </case> + <!-- latin:passwordInput="false" --> + <default> + <key-style + latin:styleName="nonPasswordSymbolKeyStyle" + latin:enabled="true" /> + <key-style + latin:styleName="nonPasswordFunctionalKeyStyle" + latin:enabled="true" + latin:parentStyle="functionalKeyStyle" /> + </default> + </switch> </merge> \ No newline at end of file diff --git a/java/res/xml/kbd_symbols.xml b/java/res/xml/kbd_symbols.xml index 0b8b899696..9748bce8b4 100644 --- a/java/res/xml/kbd_symbols.xml +++ b/java/res/xml/kbd_symbols.xml @@ -105,12 +105,14 @@ <Key latin:keyLabel="!" latin:popupCharacters="¡" /> + <!-- Note: DroidSans doesn't have double-high-reversed-quotation '\u201f' glyph. --> <Key latin:keyLabel=""" - latin:popupCharacters="“,â€,«,»,Ë" /> + latin:popupCharacters="“,â€,„,‟,«,»" + latin:maxPopupKeyboardColumn="6" /> <Key latin:keyLabel="\'" - latin:popupCharacters="‘,’" /> + latin:popupCharacters="‘,’,‚,‛,´" /> <Key latin:keyLabel=":" /> <Key diff --git a/java/res/xml/kbd_symbols_shift.xml b/java/res/xml/kbd_symbols_shift.xml index 36f0c64a96..3978f17767 100644 --- a/java/res/xml/kbd_symbols_shift.xml +++ b/java/res/xml/kbd_symbols_shift.xml @@ -42,16 +42,21 @@ <Key latin:keyLabel="|" /> <Key + latin:keyStyle="nonPasswordSymbolKeyStyle" latin:keyLabel="•" latin:popupCharacters="♪,♥,â™ ,♦,♣" /> <Key + latin:keyStyle="nonPasswordSymbolKeyStyle" latin:keyLabel="√" /> <Key + latin:keyStyle="nonPasswordSymbolKeyStyle" latin:keyLabel="Ï€" latin:popupCharacters="Î " /> <Key + latin:keyStyle="nonPasswordSymbolKeyStyle" latin:keyLabel="÷" /> <Key + latin:keyStyle="nonPasswordSymbolKeyStyle" latin:keyLabel="×" /> <Key latin:keyLabel="{" /> @@ -64,13 +69,18 @@ latin:keyStyle="nonSpecialBackgroundTabKeyStyle" latin:keyEdgeFlags="left" /> <Key + latin:keyStyle="nonPasswordSymbolKeyStyle" latin:keyLabel="£" /> <Key + latin:keyStyle="nonPasswordSymbolKeyStyle" latin:keyLabel="¢" /> <Key + latin:keyStyle="nonPasswordSymbolKeyStyle" latin:keyLabel="€" /> <Key - latin:keyLabel="°" /> + latin:keyStyle="nonPasswordSymbolKeyStyle" + latin:keyLabel="°" + latin:popupCharacters="′,″" /> <Key latin:keyLabel="^" latin:popupCharacters="↑,↓,â†,→" /> @@ -92,12 +102,16 @@ latin:visualInsetsRight="1%p" latin:keyEdgeFlags="left" /> <Key + latin:keyStyle="nonPasswordSymbolKeyStyle" latin:keyLabel="â„¢" /> <Key + latin:keyStyle="nonPasswordSymbolKeyStyle" latin:keyLabel="®" /> <Key + latin:keyStyle="nonPasswordSymbolKeyStyle" latin:keyLabel="©" /> <Key + latin:keyStyle="nonPasswordSymbolKeyStyle" latin:keyLabel="¶" latin:popupCharacters="§" /> <Key diff --git a/java/res/xml/kbd_symbols_shift_row4.xml b/java/res/xml/kbd_symbols_shift_row4.xml index 9159bab24d..4f8567d58a 100644 --- a/java/res/xml/kbd_symbols_shift_row4.xml +++ b/java/res/xml/kbd_symbols_shift_row4.xml @@ -34,13 +34,14 @@ latin:keyEdgeFlags="left" /> <Key latin:keyLabel="„" - latin:keyStyle="functionalKeyStyle" /> + latin:popupCharacters="“,â€,„,‟,«,»,‘,’,‚,‛" + latin:keyStyle="nonPasswordFunctionalKeyStyle" /> <Key latin:keyStyle="spaceKeyStyle" latin:keyWidth="40%p" /> <Key latin:keyLabel="…" - latin:keyStyle="functionalKeyStyle" /> + latin:keyStyle="nonPasswordFunctionalKeyStyle" /> <switch> <case latin:mode="im" @@ -69,13 +70,14 @@ latin:keyStyle="settingsKeyStyle" /> <Key latin:keyLabel="„" - latin:keyStyle="functionalKeyStyle" /> + latin:popupCharacters="“,â€,„,‟,«,»,‘,’,‚,‛" + latin:keyStyle="nonPasswordFunctionalKeyStyle" /> <Key latin:keyStyle="spaceKeyStyle" latin:keyWidth="30%p" /> <Key latin:keyLabel="…" - latin:keyStyle="functionalKeyStyle" /> + latin:keyStyle="nonPasswordFunctionalKeyStyle" /> <switch> <case latin:mode="im" diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index e163457d8c..825b4659c7 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -57,6 +57,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private LatinKeyboardView mInputView; private LatinIME mInputMethodService; + // TODO: Combine these key state objects with auto mode switch state. private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift"); private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol"); @@ -75,13 +76,17 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private boolean mVoiceKeyEnabled; private boolean mVoiceButtonOnPrimary; - private static final int AUTO_MODE_SWITCH_STATE_ALPHA = 0; - private static final int AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN = 1; - private static final int AUTO_MODE_SWITCH_STATE_SYMBOL = 2; + // TODO: Encapsulate these state handling to separate class and combine with ShiftKeyState + // and ModifierKeyState. + private static final int SWITCH_STATE_ALPHA = 0; + private static final int SWITCH_STATE_SYMBOL_BEGIN = 1; + private static final int SWITCH_STATE_SYMBOL = 2; // The following states are used only on the distinct multi-touch panel devices. - private static final int AUTO_MODE_SWITCH_STATE_MOMENTARY = 3; - private static final int AUTO_MODE_SWITCH_STATE_CHORDING = 4; - private int mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; + private static final int SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL = 3; + private static final int SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE = 4; + private static final int SWITCH_STATE_CHORDING_ALPHA = 5; + private static final int SWITCH_STATE_CHORDING_SYMBOL = 6; + private int mSwitchState = SWITCH_STATE_ALPHA; // Indicates whether or not we have the settings key in option of settings private boolean mSettingsKeyEnabledInSettings; @@ -124,7 +129,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha public void loadKeyboard(EditorInfo attribute, boolean voiceKeyEnabled, boolean voiceButtonOnPrimary) { - mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; + mSwitchState = SWITCH_STATE_ALPHA; try { loadKeyboardInternal(attribute, voiceKeyEnabled, voiceButtonOnPrimary, false); } catch (RuntimeException e) { @@ -465,6 +470,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha // In symbol mode, just toggle symbol and symbol more keyboard. shiftKeyState.onPress(); toggleShift(); + mSwitchState = SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE; } } @@ -496,6 +502,12 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha // transited from automatic temporary upper case. toggleShift(); } + } else { + // In symbol mode, snap back to the previous keyboard mode if the user chords the shift + // key and another key, then releases the shift key. + if (mSwitchState == SWITCH_STATE_CHORDING_SYMBOL) { + toggleShift(); + } } shiftKeyState.onRelease(); } @@ -510,7 +522,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha + " symbolKeyState=" + mSymbolKeyState); changeKeyboardMode(); mSymbolKeyState.onPress(); - mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_MOMENTARY; + mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL; } public void onReleaseSymbol() { @@ -522,9 +534,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + " symbolKeyState=" + mSymbolKeyState); // Snap back to the previous keyboard mode if the user chords the mode change key and - // other key, then released the mode change key. - if (mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_CHORDING) + // another key, then releases the mode change key. + if (mSwitchState == SWITCH_STATE_CHORDING_ALPHA) { changeKeyboardMode(); + } mSymbolKeyState.onRelease(); } @@ -543,8 +556,13 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha public void onCancelInput() { // Snap back to the previous keyboard mode if the user cancels sliding input. - if (mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_MOMENTARY && getPointerCount() == 1) - changeKeyboardMode(); + if (getPointerCount() == 1) { + if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) { + changeKeyboardMode(); + } else if (mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE) { + toggleShift(); + } + } } private void toggleShiftInSymbol() { @@ -567,8 +585,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha setKeyboard(keyboard); } - public boolean isInMomentaryAutoModeSwitchState() { - return mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_MOMENTARY; + public boolean isInMomentarySwitchState() { + return mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL + || mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE; } public boolean isVibrateAndSoundFeedbackRequired() { @@ -582,9 +601,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private void toggleKeyboardMode() { loadKeyboardInternal(mAttribute, mVoiceKeyEnabled, mVoiceButtonOnPrimary, !mIsSymbols); if (mIsSymbols) { - mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN; + mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; } else { - mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; + mSwitchState = SWITCH_STATE_ALPHA; } } @@ -596,28 +615,52 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha return mInputView != null && mInputView.hasDistinctMultitouch(); } + private static boolean isSpaceCharacter(int c) { + return c == Keyboard.CODE_SPACE || c == Keyboard.CODE_ENTER; + } + + private static boolean isQuoteCharacter(int c) { + // Apostrophe, quotation mark. + if (c == '\'' || c == '"') + return true; + // \u2018: Left single quotation mark + // \u2019: Right single quotation mark + // \u201a: Single low-9 quotation mark + // \u201b: Single high-reversed-9 quotation mark + // \u201c: Left double quotation mark + // \u201d: Right double quotation mark + // \u201e: Double low-9 quotation mark + // \u201f: Double high-reversed-9 quotation mark + if (c >= '\u2018' && c <= '\u201f') + return true; + // \u00ab: Left-pointing double angle quotation mark + // \u00bb: Right-pointing double angle quotation mark + if (c == '\u00ab' || c == '\u00bb') + return true; + return false; + } + /** * Updates state machine to figure out when to automatically snap back to the previous mode. */ - public void onKey(int key) { + public void onKey(int code) { if (DEBUG_STATE) - Log.d(TAG, "onKey: code=" + key + " autoModeSwitchState=" + mAutoModeSwitchState + Log.d(TAG, "onKey: code=" + code + " switchState=" + mSwitchState + " pointers=" + getPointerCount()); - switch (mAutoModeSwitchState) { - case AUTO_MODE_SWITCH_STATE_MOMENTARY: + switch (mSwitchState) { + case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: // Only distinct multi touch devices can be in this state. // On non-distinct multi touch devices, mode change key is handled by // {@link LatinIME#onCodeInput}, not by {@link LatinIME#onPress} and - // {@link LatinIME#onRelease}. So, on such devices, {@link #mAutoModeSwitchState} starts - // from {@link #AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN}, or - // {@link #AUTO_MODE_SWITCH_STATE_ALPHA}, not from - // {@link #AUTO_MODE_SWITCH_STATE_MOMENTARY}. - if (key == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { + // {@link LatinIME#onRelease}. So, on such devices, {@link #mSwitchState} starts + // from {@link #SWITCH_STATE_SYMBOL_BEGIN}, or {@link #SWITCH_STATE_ALPHA}, not from + // {@link #SWITCH_STATE_MOMENTARY}. + if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { // Detected only the mode change key has been pressed, and then released. if (mIsSymbols) { - mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN; + mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; } else { - mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; + mSwitchState = SWITCH_STATE_ALPHA; } } else if (getPointerCount() == 1) { // Snap back to the previous keyboard mode if the user pressed the mode change key @@ -628,18 +671,34 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha } else { // Chording input is being started. The keyboard mode will be snapped back to the // previous mode in {@link onReleaseSymbol} when the mode change key is released. - mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_CHORDING; + mSwitchState = SWITCH_STATE_CHORDING_ALPHA; + } + break; + case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: + if (code == Keyboard.CODE_SHIFT) { + // Detected only the shift key has been pressed on symbol layout, and then released. + mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; + } else if (getPointerCount() == 1) { + // Snap back to the previous keyboard mode if the user pressed the shift key on + // symbol mode and slid to other key, then released the finger. + toggleShift(); + mSwitchState = SWITCH_STATE_SYMBOL; + } else { + // Chording input is being started. The keyboard mode will be snapped back to the + // previous mode in {@link onReleaseShift} when the shift key is released. + mSwitchState = SWITCH_STATE_CHORDING_SYMBOL; } break; - case AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN: - if (key != Keyboard.CODE_SPACE && key != Keyboard.CODE_ENTER && key >= 0) { - mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL; + case SWITCH_STATE_SYMBOL_BEGIN: + if (!isSpaceCharacter(code) && code >= 0) { + mSwitchState = SWITCH_STATE_SYMBOL; } break; - case AUTO_MODE_SWITCH_STATE_SYMBOL: + case SWITCH_STATE_SYMBOL: + case SWITCH_STATE_CHORDING_SYMBOL: // Snap back to alpha keyboard mode if user types one or more non-space/enter - // characters followed by a space/enter. - if (key == Keyboard.CODE_ENTER || key == Keyboard.CODE_SPACE) { + // characters followed by a space/enter or quotation mark. + if (isSpaceCharacter(code) || isQuoteCharacter(code)) { changeKeyboardMode(); } break; diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index e3161f6107..abd1ef286c 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -662,7 +662,7 @@ public class PointerTracker { // We need not start long press timer on the key which has manual temporary upper case // code defined and the keyboard is in manual temporary upper case mode. return; - } else if (mKeyboardSwitcher.isInMomentaryAutoModeSwitchState()) { + } else if (mKeyboardSwitcher.isInMomentarySwitchState()) { // We use longer timeout for sliding finger input started from the symbols mode key. mHandler.startLongPressTimer(mLongPressKeyTimeout * 3, keyIndex, this); } else { -- GitLab