aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/Android.mk14
-rw-r--r--java/AndroidManifest.xml5
-rw-r--r--java/proguard.flags2
-rw-r--r--java/res/layout/input_view.xml2
-rw-r--r--java/res/layout/more_suggestions.xml2
-rw-r--r--java/res/values-af/strings.xml4
-rw-r--r--java/res/values-am/strings.xml4
-rw-r--r--java/res/values-ar/strings.xml4
-rw-r--r--java/res/values-be/donottranslate-more-keys.xml (renamed from java/res/xml-hu/kbd_qwerty.xml)12
-rw-r--r--java/res/values-bg/strings.xml4
-rw-r--r--java/res/values-ca/strings.xml4
-rw-r--r--java/res/values-cs/strings.xml4
-rw-r--r--java/res/values-da/donottranslate-more-keys.xml1
-rw-r--r--java/res/values-da/strings.xml4
-rw-r--r--java/res/values-de/strings.xml4
-rw-r--r--java/res/values-el/strings.xml4
-rw-r--r--java/res/values-en-rGB/strings.xml4
-rw-r--r--java/res/values-es-rUS/strings.xml4
-rw-r--r--java/res/values-es/strings.xml4
-rw-r--r--java/res/values-et/donottranslate-more-keys.xml42
-rw-r--r--java/res/values-fa/strings.xml4
-rw-r--r--java/res/values-fi/donottranslate-more-keys.xml1
-rw-r--r--java/res/values-fi/strings.xml4
-rw-r--r--java/res/values-fr/strings.xml4
-rw-r--r--java/res/values-hi/strings.xml4
-rw-r--r--java/res/values-hr/strings.xml10
-rw-r--r--java/res/values-hu/strings.xml4
-rw-r--r--java/res/values-in/strings.xml4
-rw-r--r--java/res/values-it/strings.xml4
-rw-r--r--java/res/values-iw/strings.xml4
-rw-r--r--java/res/values-ja/strings.xml4
-rw-r--r--java/res/values-ko/strings.xml4
-rw-r--r--java/res/values-ky/donottranslate-more-keys.xml24
-rw-r--r--java/res/values-land/dimens.xml1
-rw-r--r--java/res/values-lt/donottranslate-more-keys.xml21
-rw-r--r--java/res/values-lt/strings.xml4
-rw-r--r--java/res/values-lv/donottranslate-more-keys.xml24
-rw-r--r--java/res/values-lv/strings.xml4
-rw-r--r--java/res/values-ms/strings.xml4
-rw-r--r--java/res/values-nb/donottranslate-more-keys.xml1
-rw-r--r--java/res/values-nb/strings.xml4
-rw-r--r--java/res/values-nl/strings.xml4
-rw-r--r--java/res/values-pl/strings.xml4
-rw-r--r--java/res/values-pt-rPT/strings.xml4
-rw-r--r--java/res/values-pt/strings.xml4
-rw-r--r--java/res/values-rm/strings.xml4
-rw-r--r--java/res/values-ro/donottranslate-more-keys.xml2
-rw-r--r--java/res/values-ro/strings.xml4
-rw-r--r--java/res/values-ru/donottranslate-more-keys.xml4
-rw-r--r--java/res/values-ru/strings.xml8
-rw-r--r--java/res/values-sk/donottranslate-more-keys.xml24
-rw-r--r--java/res/values-sk/strings.xml4
-rw-r--r--java/res/values-sl/donottranslate-more-keys.xml25
-rw-r--r--java/res/values-sl/strings.xml4
-rw-r--r--java/res/values-sr/strings.xml4
-rw-r--r--java/res/values-sv/donottranslate-more-keys.xml1
-rw-r--r--java/res/values-sv/strings.xml4
-rw-r--r--java/res/values-sw/strings.xml4
-rw-r--r--java/res/values-sw600dp-land/dimens.xml1
-rw-r--r--java/res/values-sw600dp/config.xml1
-rw-r--r--java/res/values-sw600dp/dimens.xml1
-rw-r--r--java/res/values-sw768dp-land/dimens.xml1
-rw-r--r--java/res/values-sw768dp/config.xml1
-rw-r--r--java/res/values-sw768dp/dimens.xml1
-rw-r--r--java/res/values-th/strings.xml4
-rw-r--r--java/res/values-tl/strings.xml4
-rw-r--r--java/res/values-tr/strings.xml4
-rw-r--r--java/res/values-uk/donottranslate-more-keys.xml23
-rw-r--r--java/res/values-uk/strings.xml4
-rw-r--r--java/res/values-vi/donottranslate-more-keys.xml28
-rw-r--r--java/res/values-vi/strings.xml4
-rw-r--r--java/res/values-zh-rCN/strings.xml4
-rw-r--r--java/res/values-zh-rTW/strings.xml6
-rw-r--r--java/res/values-zu/strings.xml4
-rw-r--r--java/res/values/attrs.xml86
-rw-r--r--java/res/values/config.xml6
-rw-r--r--java/res/values/dimens.xml1
-rw-r--r--java/res/values/donottranslate-more-keys.xml14
-rw-r--r--java/res/values/donottranslate.xml1
-rw-r--r--java/res/values/keyboard-icons-black.xml7
-rw-r--r--java/res/values/keyboard-icons-ics.xml9
-rw-r--r--java/res/values/keyboard-icons-white.xml8
-rw-r--r--java/res/values/keycodes.xml3
-rw-r--r--java/res/values/strings.xml10
-rw-r--r--java/res/values/styles.xml84
-rw-r--r--java/res/values/themes-basic-highcontrast.xml2
-rw-r--r--java/res/values/themes-basic.xml2
-rw-r--r--java/res/values/themes-gingerbread.xml2
-rw-r--r--java/res/values/themes-ics.xml2
-rw-r--r--java/res/values/themes-stone-bold.xml2
-rw-r--r--java/res/values/themes-stone.xml2
-rw-r--r--java/res/xml-ar/keyboard_set.xml42
-rw-r--r--java/res/xml-be/keyboard_set.xml42
-rw-r--r--java/res/xml-cs/keyboard_set.xml42
-rw-r--r--java/res/xml-da/kbd_qwerty.xml27
-rw-r--r--java/res/xml-da/keyboard_set.xml42
-rw-r--r--java/res/xml-de-rZZ/keyboard_set.xml42
-rw-r--r--java/res/xml-de/kbd_qwerty.xml27
-rw-r--r--java/res/xml-de/keyboard_set.xml42
-rw-r--r--java/res/xml-es/keyboard_set.xml42
-rw-r--r--java/res/xml-et/keyboard_set.xml42
-rw-r--r--java/res/xml-fi/keyboard_set.xml42
-rw-r--r--java/res/xml-fr-rCA/kbd_qwerty.xml27
-rw-r--r--java/res/xml-fr-rCA/keyboard_set.xml42
-rw-r--r--java/res/xml-fr-rCH/kbd_qwerty.xml27
-rw-r--r--java/res/xml-fr-rCH/keyboard_set.xml42
-rw-r--r--java/res/xml-fr/keyboard_set.xml42
-rw-r--r--java/res/xml-hr/kbd_qwerty.xml28
-rw-r--r--java/res/xml-hr/keyboard_set.xml42
-rw-r--r--java/res/xml-hu/keyboard_set.xml42
-rw-r--r--java/res/xml-iw/keyboard_set.xml42
-rw-r--r--java/res/xml-ky/keyboard_set.xml42
-rw-r--r--java/res/xml-nb/kbd_qwerty.xml27
-rw-r--r--java/res/xml-nb/keyboard_set.xml42
-rw-r--r--java/res/xml-pl/keyboard_set.xml42
-rw-r--r--java/res/xml-pt/kbd_qwerty.xml27
-rw-r--r--java/res/xml-pt/keyboard_set.xml42
-rw-r--r--java/res/xml-ro/keyboard_set.xml42
-rw-r--r--java/res/xml-ru/kbd_qwerty.xml27
-rw-r--r--java/res/xml-ru/keyboard_set.xml42
-rw-r--r--java/res/xml-sk/keyboard_set.xml42
-rw-r--r--java/res/xml-sl/keyboard_set.xml42
-rw-r--r--java/res/xml-sr/keyboard_set.xml42
-rw-r--r--java/res/xml-sv/kbd_qwerty.xml27
-rw-r--r--java/res/xml-sv/keyboard_set.xml42
-rw-r--r--java/res/xml-sw600dp-land/kbd_number.xml28
-rw-r--r--java/res/xml-sw600dp-land/kbd_phone.xml (renamed from java/res/xml-de-rZZ/kbd_qwerty.xml)5
-rw-r--r--java/res/xml-sw600dp-land/kbd_phone_shift.xml28
-rw-r--r--java/res/xml-sw600dp/kbd_key_styles.xml26
-rw-r--r--java/res/xml-sw600dp/kbd_number.xml186
-rw-r--r--java/res/xml-sw600dp/kbd_phone.xml100
-rw-r--r--java/res/xml-sw600dp/kbd_phone_shift.xml112
-rw-r--r--java/res/xml-sw600dp/kbd_qwerty_row4.xml2
-rw-r--r--java/res/xml-sw600dp/kbd_row3_comma_period.xml4
-rw-r--r--java/res/xml-sw600dp/kbd_row3_smiley.xml4
-rw-r--r--java/res/xml-sw600dp/kbd_row4_apostrophe_dash.xml6
-rw-r--r--java/res/xml-sw600dp/kbd_rows_arabic.xml4
-rw-r--r--java/res/xml-sw600dp/kbd_rows_azerty.xml4
-rw-r--r--java/res/xml-sw600dp/kbd_rows_hebrew.xml4
-rw-r--r--java/res/xml-sw600dp/kbd_rows_number.xml208
-rw-r--r--java/res/xml-sw600dp/kbd_rows_phone.xml122
-rw-r--r--java/res/xml-sw600dp/kbd_rows_phone_shift.xml132
-rw-r--r--java/res/xml-sw600dp/kbd_rows_qwertz.xml4
-rw-r--r--java/res/xml-sw600dp/kbd_rows_scandinavian.xml2
-rw-r--r--java/res/xml-sw600dp/kbd_rows_slavic.xml (renamed from java/res/xml-sw600dp/kbd_rows_russian.xml)22
-rw-r--r--java/res/xml-sw768dp-land/kbd_number.xml28
-rw-r--r--java/res/xml-sw768dp-land/kbd_phone.xml28
-rw-r--r--java/res/xml-sw768dp-land/kbd_phone_shift.xml28
-rw-r--r--java/res/xml-sw768dp/kbd_key_styles.xml44
-rw-r--r--java/res/xml-sw768dp/kbd_number.xml203
-rw-r--r--java/res/xml-sw768dp/kbd_phone.xml119
-rw-r--r--java/res/xml-sw768dp/kbd_phone_shift.xml133
-rw-r--r--java/res/xml-sw768dp/kbd_qwerty_row1.xml2
-rw-r--r--java/res/xml-sw768dp/kbd_qwerty_row2.xml2
-rw-r--r--java/res/xml-sw768dp/kbd_qwerty_row4.xml4
-rw-r--r--java/res/xml-sw768dp/kbd_row3_comma_period.xml4
-rw-r--r--java/res/xml-sw768dp/kbd_row4_apostrophe_dash.xml6
-rw-r--r--java/res/xml-sw768dp/kbd_rows_arabic.xml4
-rw-r--r--java/res/xml-sw768dp/kbd_rows_azerty.xml10
-rw-r--r--java/res/xml-sw768dp/kbd_rows_hebrew.xml4
-rw-r--r--java/res/xml-sw768dp/kbd_rows_number.xml227
-rw-r--r--java/res/xml-sw768dp/kbd_rows_phone.xml143
-rw-r--r--java/res/xml-sw768dp/kbd_rows_phone_shift.xml153
-rw-r--r--java/res/xml-sw768dp/kbd_rows_qwertz.xml6
-rw-r--r--java/res/xml-sw768dp/kbd_rows_scandinavian.xml6
-rw-r--r--java/res/xml-sw768dp/kbd_rows_serbian.xml4
-rw-r--r--java/res/xml-sw768dp/kbd_rows_slavic.xml (renamed from java/res/xml-sw768dp/kbd_rows_russian.xml)22
-rw-r--r--java/res/xml-sw768dp/kbd_rows_spanish.xml2
-rw-r--r--java/res/xml-sw768dp/kbd_rows_symbols.xml4
-rw-r--r--java/res/xml-sw768dp/kbd_rows_symbols_shift.xml4
-rw-r--r--java/res/xml-tr/kbd_qwerty.xml27
-rw-r--r--java/res/xml-tr/keyboard_set.xml42
-rw-r--r--java/res/xml-uk/keyboard_set.xml42
-rw-r--r--java/res/xml-vi/keyboard_set.xml42
-rw-r--r--java/res/xml/kbd_arabic.xml (renamed from java/res/xml-ar/kbd_qwerty.xml)1
-rw-r--r--java/res/xml/kbd_azerty.xml (renamed from java/res/xml-fr/kbd_qwerty.xml)3
-rw-r--r--java/res/xml/kbd_hebrew.xml (renamed from java/res/xml-iw/kbd_qwerty.xml)3
-rw-r--r--java/res/xml/kbd_key_styles.xml46
-rw-r--r--java/res/xml/kbd_numkey_styles.xml35
-rw-r--r--java/res/xml/kbd_qwerty.xml1
-rw-r--r--java/res/xml/kbd_qwertz.xml (renamed from java/res/xml-cs/kbd_qwerty.xml)1
-rw-r--r--java/res/xml/kbd_rows_phone_shift.xml11
-rw-r--r--java/res/xml/kbd_rows_scandinavian.xml5
-rw-r--r--java/res/xml/kbd_rows_slavic.xml (renamed from java/res/xml/kbd_rows_russian.xml)23
-rw-r--r--java/res/xml/kbd_scandinavian.xml (renamed from java/res/xml-fi/kbd_qwerty.xml)1
-rw-r--r--java/res/xml/kbd_serbian.xml (renamed from java/res/xml-sr/kbd_qwerty.xml)3
-rw-r--r--java/res/xml/kbd_settings_or_tab.xml3
-rw-r--r--java/res/xml/kbd_slavic.xml (renamed from java/res/xml-pl/kbd_qwerty.xml)5
-rw-r--r--java/res/xml/kbd_spanish.xml (renamed from java/res/xml-es/kbd_qwerty.xml)1
-rw-r--r--java/res/xml/kbd_symbols_shift_row4.xml4
-rw-r--r--java/res/xml/keyboard_set.xml42
-rw-r--r--java/res/xml/method.xml65
-rw-r--r--java/res/xml/spell_checker_settings.xml6
-rw-r--r--java/res/xml/spellchecker.xml15
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java25
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java9
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java32
-rw-r--r--java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java1
-rw-r--r--java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java28
-rw-r--r--java/src/com/android/inputmethod/compat/ArraysCompatUtils.java15
-rw-r--r--java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java3
-rw-r--r--java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java14
-rw-r--r--java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java43
-rw-r--r--java/src/com/android/inputmethod/deprecated/VoiceProxy.java10
-rw-r--r--java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java6
-rw-r--r--java/src/com/android/inputmethod/deprecated/voice/FieldContext.java4
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java264
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyDetector.java89
-rw-r--r--java/src/com/android/inputmethod/keyboard/Keyboard.java1152
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardId.java220
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSet.java316
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java701
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java147
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboard.java339
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java401
-rw-r--r--java/src/com/android/inputmethod/keyboard/MiniKeyboard.java8
-rw-r--r--java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java5
-rw-r--r--java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java23
-rw-r--r--java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java1
-rw-r--r--java/src/com/android/inputmethod/keyboard/PointerTracker.java386
-rw-r--r--java/src/com/android/inputmethod/keyboard/ProximityInfo.java133
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java51
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java893
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java109
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java190
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java7
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java526
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java4
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java51
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java2
-rw-r--r--java/src/com/android/inputmethod/latin/AutoCorrection.java7
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java26
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryCollection.java22
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableDictionary.java2
-rw-r--r--java/src/com/android/inputmethod/latin/InputAttributes.java117
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java1033
-rw-r--r--java/src/com/android/inputmethod/latin/LatinImeLogger.java19
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java333
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsValues.java340
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeSwitcher.java7
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java81
-rw-r--r--java/src/com/android/inputmethod/latin/TextEntryState.java237
-rw-r--r--java/src/com/android/inputmethod/latin/UserBigramDictionary.java10
-rw-r--r--java/src/com/android/inputmethod/latin/UserDictionary.java70
-rw-r--r--java/src/com/android/inputmethod/latin/UserUnigramDictionary.java12
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java280
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java252
-rw-r--r--java/src/com/android/inputmethod/latin/XmlParseUtils.java77
-rw-r--r--java/src/com/android/inputmethod/latin/define/JniLibName.java21
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java240
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java195
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java (renamed from java/src/com/android/inputmethod/latin/MoreSuggestions.java)19
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java (renamed from java/src/com/android/inputmethod/latin/MoreSuggestionsView.java)3
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java (renamed from java/src/com/android/inputmethod/latin/SuggestionsView.java)239
255 files changed, 8519 insertions, 5957 deletions
diff --git a/java/Android.mk b/java/Android.mk
index 43168e563..36ff506bf 100644
--- a/java/Android.mk
+++ b/java/Android.mk
@@ -1,3 +1,17 @@
+# Copyright (C) 2011 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml
index b0525326c..e663c90f2 100644
--- a/java/AndroidManifest.xml
+++ b/java/AndroidManifest.xml
@@ -5,16 +5,15 @@
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
- <uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
- <application android:label="@string/english_ime_name"
+ <application android:label="@string/aosp_android_keyboard_ime_name"
android:icon="@drawable/ic_ime_settings"
android:backupAgent="BackupAgent"
android:killAfterRestore="false">
<service android:name="LatinIME"
- android:label="@string/english_ime_name"
+ android:label="@string/aosp_android_keyboard_ime_name"
android:permission="android.permission.BIND_INPUT_METHOD">
<intent-filter>
<action android:name="android.view.InputMethod" />
diff --git a/java/proguard.flags b/java/proguard.flags
index 33af890ec..caf1ea183 100644
--- a/java/proguard.flags
+++ b/java/proguard.flags
@@ -35,6 +35,6 @@
*;
}
--keep class com.android.inputmethod.keyboard.internal.MiniKeyboardBuilder$MiniKeyboardParams {
+-keep class com.android.inputmethod.keyboard.MiniKeyboard$Builder$MiniKeyboardParams {
<init>(...);
}
diff --git a/java/res/layout/input_view.xml b/java/res/layout/input_view.xml
index 2e0cddc28..b9451f8ae 100644
--- a/java/res/layout/input_view.xml
+++ b/java/res/layout/input_view.xml
@@ -43,7 +43,7 @@
android:layout_width="@dimen/suggestions_strip_padding"
android:layout_height="@dimen/suggestions_strip_height"
style="?attr/suggestionsStripBackgroundStyle" />
- <com.android.inputmethod.latin.SuggestionsView
+ <com.android.inputmethod.latin.suggestions.SuggestionsView
android:id="@+id/suggestions_view"
android:layout_weight="1.0"
android:layout_width="0dp"
diff --git a/java/res/layout/more_suggestions.xml b/java/res/layout/more_suggestions.xml
index 6aa82e197..1e59b8931 100644
--- a/java/res/layout/more_suggestions.xml
+++ b/java/res/layout/more_suggestions.xml
@@ -24,7 +24,7 @@
android:orientation="horizontal"
style="?attr/miniKeyboardPanelStyle"
>
- <com.android.inputmethod.latin.MoreSuggestionsView
+ <com.android.inputmethod.latin.suggestions.MoreSuggestionsView
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
android:id="@+id/more_suggestions_view"
android:layout_alignParentBottom="true"
diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml
index 36c9d4bc4..e482d1384 100644
--- a/java/res/values-af/strings.xml
+++ b/java/res/values-af/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Invoeropsies"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android-korrigering"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Speltoetser se instellings"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Gebruik nabyheidsdata"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Gebruik \'n sleutelbordagtige nabyheidsalgoritme vir die speltoetser"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Soek kontakname op"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Speltoetser gebruik inskrywings uit jou kontaklys"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibreer met sleuteldruk"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Klank met sleuteldruk"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Opspring met sleuteldruk"</string>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index d5280bc64..288854d22 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"ግቤት አማራጮች"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"የAndroid ማስተካከያ"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"የፊደል አራሚ ቅንብሮች"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"የቀረቤታ ውሂብ ተጠቀም"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"ለፊደል አራሚ የሰሌዳ ቁልፍ አይነት የቀረበ ስልተ ቀመር ተጠቀም"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"የእውቅያ ስሞችን ተመልከት"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"ፊደል አራሚ ከእውቅያ ዝርዝርህ የገቡትን ይጠቀማል"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"በቁልፍመጫንጊዜ አንዝር"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"በቁልፍ መጫን ላይ የሚወጣ ድምፅ"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"ቁልፍ ጫን ላይ ብቅ ባይ"</string>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index dca73659a..1be9d0185 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"خيارات الإرسال"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"تصحيح Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"إعدادات التدقيق الإملائي"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"استخدام بيانات التقريب"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"استخدام خوارزمية تقريب شبيهة بلوحة المفاتيح لإجراء التدقيق الإملائي"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"بحث في أسماء جهات الاتصال"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"يستخدم المدقق الإملائي إدخالات من قائمة جهات الاتصال"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"اهتزاز عند ضغط مفتاح"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"صوت عند الضغط على مفتاح"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"انبثاق عند ضغط مفتاح"</string>
diff --git a/java/res/xml-hu/kbd_qwerty.xml b/java/res/values-be/donottranslate-more-keys.xml
index 3195d5b1f..28264c4ac 100644
--- a/java/res/xml-hu/kbd_qwerty.xml
+++ b/java/res/values-be/donottranslate-more-keys.xml
@@ -17,11 +17,7 @@
** limitations under the License.
*/
-->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="hu"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_qwertz" />
-</Keyboard>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keylabel_for_slavic_shcha">ў</string>
+ <string name="keylabel_for_slavic_i">i</string>
+</resources>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index 30fe132d8..41ef97a38 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Опции за въвеждане"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Корекция на Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Настройки за проверка на правописа"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Използване на близост"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Проверка на правописа: Използвайте алгоритъм за близост"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Търсене на имена"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"За проверка на правописа се ползват записи от списъка с контакти"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Да вибрира при натискане на клавиш"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Звук при натискане на клавиш"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Изскачащ прозорец при натискане на клавиш"</string>
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index a58d8faa9..5dc380590 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Opcions d\'entrada"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Correcció d\'Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Configuració de la correcció ortogràfica"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Utilitza les dades de proximitat"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Utilitza un algorisme de proximitat similar al teclat per comprovar l\'ortografia"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cerca noms de contactes"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"El corrector ortogràfic utilitza entrades de la llista de cont."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibra en prémer tecles"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"So en prémer una tecla"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Finestra emergent en prémer un botó"</string>
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index d57ccaa28..bc310765d 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti zadávání textu a dat"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Opravy Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Nastavení kontroly pravopisu"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Použít údaje o blízkosti"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Při kontrole pravopisu uvažovat blízkost písmen na klávesnici"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Vyhledat kontakty"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kontrola pravopisu používá záznamy z vašeho seznamu kontaktů."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Při stisku klávesy vibrovat"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Zvuk při stisku klávesy"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Zobrazit znaky při stisku klávesy"</string>
diff --git a/java/res/values-da/donottranslate-more-keys.xml b/java/res/values-da/donottranslate-more-keys.xml
index 12c1ebfe1..bed034d40 100644
--- a/java/res/values-da/donottranslate-more-keys.xml
+++ b/java/res/values-da/donottranslate-more-keys.xml
@@ -28,6 +28,7 @@
<string name="more_keys_for_y">6,ý,ÿ</string>
<string name="more_keys_for_d">ð</string>
<string name="more_keys_for_l">ł</string>
+ <string name="keylabel_for_scandinavia_row1_11">å</string>
<string name="keylabel_for_scandinavia_row2_10">æ</string>
<string name="keylabel_for_scandinavia_row2_11">ø</string>
<string name="more_keys_for_scandinavia_row2_10">ä</string>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index b91acaa90..7ae7b7e5a 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Indstillinger for input"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android-rettelse"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Indstillinger for stavekontrol"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Brug nærhedsdata"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Brug en tastaturlignende nærhedsalgoritme til stavekontrol"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Slå kontaktnavne op"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Stavekontrollen bruger poster fra listen over kontaktpersoner"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibration ved tastetryk"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Lyd ved tastetryk"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Pop op ved tastetryk"</string>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index d329f3271..1a4b36b95 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Eingabeoptionen"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Rechtschreibprüfung für Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Einstellungen für Rechtschreibprüfung"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Näherungsdaten verwenden"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Tastaturähnl. Abstandsalgorith. für Rechtschreibprüfung verwenden"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontaktnamen prüfen"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Rechtschreibprüfung verwendet Einträge aus Ihrer Kontaktliste."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Bei Tastendruck vibrieren"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Ton bei Tastendruck"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Pop-up bei Tastendruck"</string>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index 6fe191ee7..f19699b63 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Επιλογές εισόδου"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Διόρθωση Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Ρυθμίσεις ορθογραφικού ελέγχου"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Χρ. δεδ. εγγύτ."</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Χρησ. αλγόρ. εγγύτ. τύπου πληκτρ., για ορθ. έλεγχο"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Αναζήτηση ονομάτων επαφών"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Ο ορθογρ. έλεγχος χρησιμοπ. καταχωρίσεις από τη λίστα επαφών σας"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Δόνηση κατά το πάτημα πλήκτρων"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Ήχος κατά το πάτημα πλήκτρων"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Εμφάνιση με το πάτημα πλήκτρου"</string>
diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml
index a7d50860c..f8cf4dc6e 100644
--- a/java/res/values-en-rGB/strings.xml
+++ b/java/res/values-en-rGB/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Input options"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android correction"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Spellchecking settings"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Use proximity data"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Use a keyboard-like proximity algorithm for spellchecking"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Look up contact names"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Spell checker uses entries from your contact list"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrate on key-press"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Sound on key-press"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Pop-up on key press"</string>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index 95e309ff7..a40097188 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Opciones de entrada"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Corrector de Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Configuración del corrector ortográfico"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Utilizar datos de prox."</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Utilizar algoritmo de prox. de teclado para corrector ortográfico"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nombres contactos"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"El corrector ortográfico usa entradas de tu lista de contactos."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar al pulsar teclas"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Sonar al pulsar las teclas"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Aviso emergente al pulsar tecla"</string>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index fcd65e1fc..bd8bf019b 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Opciones introducción texto"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Corrector de Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Ajustes del corrector ortográfico"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Usar datos de proximidad"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Usar algoritmo de proximidad de teclado para corregir la ortografía"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nombres de contactos"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"El corrector ortográfico usa entradas de tu lista de contactos."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar al pulsar tecla"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Sonido al pulsar tecla"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Pop-up al pulsar tecla"</string>
diff --git a/java/res/values-et/donottranslate-more-keys.xml b/java/res/values-et/donottranslate-more-keys.xml
new file mode 100644
index 000000000..1011347cd
--- /dev/null
+++ b/java/res/values-et/donottranslate-more-keys.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="more_keys_for_a">ä,ā,à,á,â,ã,å,æ,ą</string>
+ <string name="more_keys_for_e">3,ē,è,ė,é,ê,ë,ę,ě</string>
+ <string name="more_keys_for_i">8,ī,ì,į,í,î,ï,ı</string>
+ <string name="more_keys_for_o">9,ö,õ,ò,ó,ô,œ,ő,ø</string>
+ <string name="more_keys_for_u">7,ü,ū,ų,ù,ú,û,ů,ű</string>
+ <string name="more_keys_for_s">š,ß,ś,ş</string>
+ <string name="more_keys_for_n">ņ,ñ,ń,ń</string>
+ <string name="more_keys_for_c">č,ç,ć</string>
+ <string name="more_keys_for_y">6,ý,ÿ</string>
+ <string name="more_keys_for_d">ď</string>
+ <string name="more_keys_for_r">4,ŗ,ř,ŕ</string>
+ <string name="more_keys_for_t">5,ţ,ť</string>
+ <string name="more_keys_for_z">ž,ż,ź</string>
+ <string name="more_keys_for_k">ķ</string>
+ <string name="more_keys_for_l">ļ,ł,ĺ,ľ</string>
+ <string name="more_keys_for_g">ģ,ğ</string>
+ <string name="keylabel_for_scandinavia_row1_11">ü</string>
+ <string name="keylabel_for_scandinavia_row2_10">ö</string>
+ <string name="keylabel_for_scandinavia_row2_11">ä</string>
+ <string name="more_keys_for_scandinavia_row2_10">õ</string>
+ <string name="more_keys_for_scandinavia_row2_11"></string>
+</resources>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index 7d8c1e941..782553197 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"گزینه های ورودی"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"تصحیح Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"تنظیمات غلط گیری املایی"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"استفاده از داده‌های مجاورت"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"استفاده از یک الگوریتم مجاورت مشابه صفحه کلید برای غلط گیری املایی"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"جستجوی نام مخاطبین"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"غلط‌گیر املا از ورودی‌های لیست مخاطبین شما استفاده میکند"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"لرزش با فشار کلید"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"صدا با فشار کلید"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"بازشدن با فشار کلید"</string>
diff --git a/java/res/values-fi/donottranslate-more-keys.xml b/java/res/values-fi/donottranslate-more-keys.xml
index df67c69ba..e1dfa2bcf 100644
--- a/java/res/values-fi/donottranslate-more-keys.xml
+++ b/java/res/values-fi/donottranslate-more-keys.xml
@@ -23,6 +23,7 @@
<string name="more_keys_for_u">7,ü</string>
<string name="more_keys_for_s">š,ß,ś</string>
<string name="more_keys_for_z">ž,ź,ż</string>
+ <string name="keylabel_for_scandinavia_row1_11">å</string>
<string name="keylabel_for_scandinavia_row2_10">ö</string>
<string name="keylabel_for_scandinavia_row2_11">ä</string>
<string name="more_keys_for_scandinavia_row2_10">ø</string>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index c77cd8107..de216af6a 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Syöttövalinnat"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android-korjaus"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Oikoluvun asetukset"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Käytä lähestymistietoja"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Käytä näppäimistön kaltaista lähestymisalgoritmia oikolukuun"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Hae kontaktien nimiä"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Oikeinkirjoituksen tarkistus käyttää kontaktiluettelosi tietoja."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Käytä värinää näppäimiä painettaessa"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Toista ääni näppäimiä painettaessa"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Ponnahdusikkuna painalluksella"</string>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index 7b89edd54..70e2772d4 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Options de saisie"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Correcteur Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Paramètre du correcteur orthographique"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Utiliser données proximité"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Utiliser algorithme de proximité clavier pour correcteur ortho"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Rechercher noms contacts"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Correcteur orthographique utilise entrées de liste de contacts."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrer à chaque touche"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Son à chaque touche"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Agrandir les caractères"</string>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index de95ab8d7..9397e1756 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"इनपुट विकल्‍प"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android correction"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"वर्तनी जांच सेटिंग"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"निकटस्थ डेटा उपयोग करें"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"वर्तनी जांचने के लि‍ए कीबोर्ड जैसे नि‍कटस्‍थ एल्‍गोरि‍दम का उपयोग करें"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"संपर्क नामों को खोजें"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"वर्तनी परीक्षक आपकी संपर्क सूची की प्रविष्टियों का उपयोग करता है"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"कुंजी दबाने पर कंपन करता है"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"कुंजी दबाने पर आवाज"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"कुंजी दबाने पर पॉपअप दिखाएं"</string>
diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml
index 30c20b3cc..c7e09878e 100644
--- a/java/res/values-hr/strings.xml
+++ b/java/res/values-hr/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Opcije ulaza"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Ispravak za Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Postavke provjere pravopisa"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Upotreba podataka blizine"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Za prov. pravopisa upotrijebi algoritam blizine kao na tipkovnici"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Potražite imena kontakata"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Provjera pravopisa upotrebljava unose iz vašeg popisa kontakata"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibracija pri pritisku na tipku"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Zvuk pri pritisku tipke"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Povećanja na pritisak tipke"</string>
@@ -35,7 +35,7 @@
<string name="misc_category" msgid="6894192814868233453">"Ostale opcije"</string>
<string name="advanced_settings" msgid="362895144495591463">"Napredne postavke"</string>
<string name="advanced_settings_summary" msgid="5193513161106637254">"Opcije za stručne korisnike"</string>
- <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Bez odgode klj. skočnih"</string>
+ <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Odgoda prikaza tipki"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez odgode"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Zadano"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Predlaži imena kontakata"</string>
@@ -52,7 +52,7 @@
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Uvijek sakrij"</string>
<string name="prefs_settings_key" msgid="4623341240804046498">"Prikaži tipku postavki"</string>
<string name="auto_correction" msgid="4979925752001319458">"Samoispravak"</string>
- <string name="auto_correction_summary" msgid="5625751551134658006">"Razm. i intrp. aut. ispr. kr. rči."</string>
+ <string name="auto_correction_summary" msgid="5625751551134658006">"Razmak i interpunkcija automatski ispravljaju krive riječi"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Isključeno"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Skromno"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresivno"</string>
@@ -132,7 +132,7 @@
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na glavnoj tipkovnici"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na tipkovnici simb."</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Isključeno"</string>
- <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mik. na gl. tipk."</string>
+ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon na gl. tipkovnici"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik. na tipk. simb."</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Glas. unos onemog."</string>
<string name="selectInputMethod" msgid="315076553378705821">"Odabir ulazne metode"</string>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index 180b6fcf9..e864c6715 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Beviteli beállítások"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android korrekció"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Helyesírás-ellenőrzés beállításai"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Közelségi adatok haszn."</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Billentyűzetszerű algoritmus a helyesírás-ellenőrzéshez"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Névjegyek keresése"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"A helyesírás-ellenőrző használja a névjegyek bejegyzéseit"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Rezgés billentyű megnyomása esetén"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Hangjelzés billentyű megnyomása esetén"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Legyen nagyobb billentyű lenyomásakor"</string>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index a023b6477..03f2adad6 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Opsi masukan"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Koreksi android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Setelan pemeriksaan ejaan"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Gunakan data kedekatan"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Gunakan algoritme kedekatan seperti keyboard untuk memeriksa ejaan"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cari nama kenalan"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Pemeriksa ejaan menggunakan entri dari daftar kenalan Anda"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Getar jika tombol ditekan"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Berbunyi jika tombol ditekan"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Muncul saat tombol ditekan"</string>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index 58c0e2c3b..a8206359e 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Opzioni inserimento"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Correzione Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Impostazioni di controllo ortografico"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Usa i dati di prossimità"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Usa algoritmo prossimità (come in tastiere) per controllo ortografico"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cerca in nomi contatti"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"La funzione di controllo ortografico usa voci dell\'elenco contatti"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrazione tasti"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Suono tasti"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Popup sui tasti"</string>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index 292517c68..c2743d94a 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"אפשרויות קלט"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"תיקון Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"הגדרות בדיקת איות"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"שימוש בנתוני הקירבה"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"השתמש באלגוריתם קירבה דמוי-מקלדת עבור בדיקת איות"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"חפש שמות של אנשי קשר"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"בודק האיות משתמש בערכים מרשימת אנשי הקשר שלך"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"רטט בלחיצה על מקשים"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"צלילים בעת לחיצה על מקשים"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"חלון קופץ בלחיצה על מקש"</string>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index 540bb4688..fc59a224d 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"入力オプション"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Androidスペルチェッカー"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"スペルチェックの設定"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"近接データを使用"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"スペルチェックでキーボードと同じような近接アルゴリズムを使用する"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"連絡先名の検索"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"スペルチェッカーでは連絡先リストのエントリを使用します"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"キー操作バイブ"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"キー操作音"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"キー押下時ポップアップ"</string>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index bc2b6289c..b0e9d3fbf 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"입력 옵션"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android 교정"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"맞춤법 검사 설정"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"근접 데이터 사용"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"맞춤법 검사에 대해 키보드와 유사한 근접 알고리즘 사용"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"연락처 이름 조회"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"맞춤법 검사기가 주소록의 항목을 사용합니다."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"키를 누를 때 진동 발생"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"키를 누를 때 소리 발생"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"키를 누를 때 팝업"</string>
diff --git a/java/res/values-ky/donottranslate-more-keys.xml b/java/res/values-ky/donottranslate-more-keys.xml
new file mode 100644
index 000000000..d56cde577
--- /dev/null
+++ b/java/res/values-ky/donottranslate-more-keys.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="more_keys_for_slavic_u">3,ү</string>
+ <string name="more_keys_for_slavic_en">6,ң</string>
+ <string name="more_keys_for_slavic_o">ө</string>
+</resources>
diff --git a/java/res/values-land/dimens.xml b/java/res/values-land/dimens.xml
index 4a5c5a44c..dcbfe463e 100644
--- a/java/res/values-land/dimens.xml
+++ b/java/res/values-land/dimens.xml
@@ -53,6 +53,7 @@
<fraction name="key_hint_label_ratio">52%</fraction>
<fraction name="key_uppercase_letter_ratio">40%</fraction>
<fraction name="key_preview_text_ratio">90%</fraction>
+ <fraction name="spacebar_text_ratio">40.000%</fraction>
<dimen name="key_preview_offset">0.08in</dimen>
<dimen name="key_preview_offset_ics">0.01in</dimen>
diff --git a/java/res/values-lt/donottranslate-more-keys.xml b/java/res/values-lt/donottranslate-more-keys.xml
index 6b81e4509..e36ce6a66 100644
--- a/java/res/values-lt/donottranslate-more-keys.xml
+++ b/java/res/values-lt/donottranslate-more-keys.xml
@@ -18,11 +18,20 @@
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="more_keys_for_a">ą,à,á,â,ä,æ,ã,å,ā</string>
- <string name="more_keys_for_e">3,ė,ę,è,é,ê,ë,ē</string>
- <string name="more_keys_for_i">8,į,î,ï,ì,í,ī</string>
- <string name="more_keys_for_u">7,ų,ū,û,ü,ù,ú</string>
- <string name="more_keys_for_s">š,ß,ś</string>
+ <string name="more_keys_for_a">ą,ä,ā,à,á,â,ã,å,æ</string>
+ <string name="more_keys_for_e">3,ė,ę,ē,è,é,ê,ë,ě</string>
+ <string name="more_keys_for_i">8,į,ī,ì,í,î,ï,ı</string>
+ <string name="more_keys_for_o">9,ö,õ,ò,ó,ô,œ,ő,ø</string>
+ <string name="more_keys_for_u">7,ū,ų,ü,ū,ù,ú,û,ů,ű</string>
+ <string name="more_keys_for_s">š,ß,ś,ş</string>
+ <string name="more_keys_for_n">ņ,ñ,ń,ń</string>
<string name="more_keys_for_c">č,ç,ć</string>
- <string name="more_keys_for_z">ž,ź,ż</string>
+ <string name="more_keys_for_y">6,ý,ÿ</string>
+ <string name="more_keys_for_d">ď</string>
+ <string name="more_keys_for_r">4,ŗ,ř,ŕ</string>
+ <string name="more_keys_for_t">5,ţ,ť</string>
+ <string name="more_keys_for_z">ž,ż,ź</string>
+ <string name="more_keys_for_k">ķ</string>
+ <string name="more_keys_for_l">ļ,ł,ĺ,ľ</string>
+ <string name="more_keys_for_g">ģ,ğ</string>
</resources>
diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml
index 6263f6706..4c11bc203 100644
--- a/java/res/values-lt/strings.xml
+++ b/java/res/values-lt/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Įvesties parinktys"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"„Android“ korekcijos"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Rašybos tikrinimo nustatymai"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Naudoti artimumo duomenis"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Naudokite klaviatūros tipo artimumo algoritmą rašybai patikrinti"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontaktų vardų paieška"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Rašybos tikrinimo progr. naudoja įrašus, esančius kontaktų sąraše"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibruoti, kai paspaudžiami klavišai"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Klavišo paspaudimo garsas"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Iššoka paspaudus klavišą"</string>
diff --git a/java/res/values-lv/donottranslate-more-keys.xml b/java/res/values-lv/donottranslate-more-keys.xml
index 77e1c26a0..8514e738d 100644
--- a/java/res/values-lv/donottranslate-more-keys.xml
+++ b/java/res/values-lv/donottranslate-more-keys.xml
@@ -18,16 +18,20 @@
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="more_keys_for_a">ā,à,á,â,ä,æ,ã,å</string>
- <string name="more_keys_for_e">3,ē,è,é,ê,ë,ę,ė</string>
- <string name="more_keys_for_i">8,ī,î,ï,ì,í,į</string>
- <string name="more_keys_for_u">7,ū,û,ü,ù,ú</string>
- <string name="more_keys_for_s">š,ß,ś</string>
- <string name="more_keys_for_n">ņ,ñ,ń</string>
+ <string name="more_keys_for_a">ā,à,á,â,ã,ä,å,æ,ą</string>
+ <string name="more_keys_for_e">3,ē,ė,è,é,ê,ë,ę,ě</string>
+ <string name="more_keys_for_i">8,ī,į,ì,í,î,ï,ı</string>
+ <string name="more_keys_for_o">9,ò,ó,ô,õ,ö,œ,ő,ø</string>
+ <string name="more_keys_for_u">7,ū,ų,ù,ú,û,ü,ů,ű</string>
+ <string name="more_keys_for_s">š,ß,ś,ş</string>
+ <string name="more_keys_for_n">ņ,ñ,ń,ń</string>
<string name="more_keys_for_c">č,ç,ć</string>
- <string name="more_keys_for_r">4,ŗ</string>
- <string name="more_keys_for_z">ž,ź,ż</string>
+ <string name="more_keys_for_y">6,ý,ÿ</string>
+ <string name="more_keys_for_d">ď</string>
+ <string name="more_keys_for_r">4,ŗ,ř,ŕ</string>
+ <string name="more_keys_for_t">5,ţ,ť</string>
+ <string name="more_keys_for_z">ž,ż,ź</string>
<string name="more_keys_for_k">ķ</string>
- <string name="more_keys_for_l">ļ,ł</string>
- <string name="more_keys_for_g">ģ</string>
+ <string name="more_keys_for_l">ļ,ł,ĺ,ľ</string>
+ <string name="more_keys_for_g">ģ,ğ</string>
</resources>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index af01d92f6..874ded10b 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Ievades opcijas"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android korekcija"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Pareizrakstības pārbaudes iestatījumi"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Tuvuma datu izmantošana"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Pareizrakstības pārbaudei izmantojiet tastatūrai līdzīgu tuvuma algoritmu."</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Meklēt kontaktp. vārdus"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Pareizrakst. pārbaudītājs lieto ierakstus no kontaktp. saraksta."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrēt, nospiežot taustiņu"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Skaņa, nospiežot taustiņu"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Nospiežot taustiņu, parādīt uznirstošo izvēlni"</string>
diff --git a/java/res/values-ms/strings.xml b/java/res/values-ms/strings.xml
index d6bf559e7..caee144be 100644
--- a/java/res/values-ms/strings.xml
+++ b/java/res/values-ms/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Pilihan input"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Pembetulan Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Tetapan penyemakan ejaan"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Gunakan data kehampiran"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Gunakan algoritma kehampiran ala papan kekunci untuk pemeriksaan ejaan"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cari nama kenalan"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Penyemak ejaan menggunakan entri dari senarai kenalan anda"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Getar pada tekanan kekunci"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Bunyi pada tekanan kekunci"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Pop timbul pada tekanan kunci"</string>
diff --git a/java/res/values-nb/donottranslate-more-keys.xml b/java/res/values-nb/donottranslate-more-keys.xml
index b98341c6a..e83d6b768 100644
--- a/java/res/values-nb/donottranslate-more-keys.xml
+++ b/java/res/values-nb/donottranslate-more-keys.xml
@@ -22,6 +22,7 @@
<string name="more_keys_for_e">3,é,è,ê,ë,ę,ė,ē</string>
<string name="more_keys_for_o">9,ô,ò,ó,ö,õ,œ,ō</string>
<string name="more_keys_for_u">7,ü,û,ù,ú,ū</string>
+ <string name="keylabel_for_scandinavia_row1_11">å</string>
<string name="keylabel_for_scandinavia_row2_10">ø</string>
<string name="keylabel_for_scandinavia_row2_11">æ</string>
<string name="more_keys_for_scandinavia_row2_10">ö</string>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index acd636bdd..5f20aac5f 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Inndataalternativer"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android-stavekontroll"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Innstillinger for stavekontroll"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Bruk nærhetsdata"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Bruk en tastaturlignende algoritme til stavekontroll"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Slå opp kontaktnavn"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Stavekontrollen bruker oppføringer fra kontaktlisten din"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrer ved tastetrykk"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Lyd ved tastetrykk"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Hurtigvindu ved tastetrykk"</string>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index 7f0ff7eaf..97bcd9051 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Invoeropties"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android-spellingcontrole"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Instellingen voor spellingcontrole"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Nabije toetsinfo gebr."</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Algoritme voor nabije toetsen gebruiken voor spellingcontrole"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Contactnamen opzoeken"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"De spellingcontrole gebruikt items uit uw contactenlijst"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Trillen bij toetsaanslag"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Geluid bij toetsaanslag"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Pop-up bij toetsaanslag"</string>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index a9a6a76b6..cde1009b7 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Opcje wprowadzania"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Korekta Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Ustawienia sprawdzania pisowni"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Użyj danych o klawiszach"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Przy sprawdzaniu pisowni używaj algorytmu uwzględniającego położenie klawiszy na klawiaturze"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Przeszukaj nazwy kontaktów"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Sprawdzanie pisowni bierze pod uwagę wpisy z listy kontaktów."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Wibracja przy naciśnięciu"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Dźwięk przy naciśnięciu"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Powiększ po naciśnięciu"</string>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index 0a30235f4..791d5f7e5 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Opções de introdução"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Correção do Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Definições da verificação ortográfica"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Utilizar dados de prox."</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Util. algoritmo de prox. semelhante a teclado para verif. ortog."</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Procurar nomes de contac."</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"O corretor ortográfico utiliza entradas da sua lista de contactos"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar ao primir as teclas"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Som ao premir as teclas"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Mostrar popup ao premir tecla"</string>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index 36a70daa6..50f538e94 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Opções de entrada"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Correção do Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Configurações de verificação ortográfica"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Usar dados de proximidade"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Usar algoritmo de prox. tipo teclado para verificação ortográfica"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nomes de contatos"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"O corretor ortográfico usa entradas de sua lista de contatos"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar ao tocar a tecla"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Som ao tocar a tecla"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Exibir pop-up ao digitar"</string>
diff --git a/java/res/values-rm/strings.xml b/java/res/values-rm/strings.xml
index 090f3fc47..5e121f451 100644
--- a/java/res/values-rm/strings.xml
+++ b/java/res/values-rm/strings.xml
@@ -28,9 +28,9 @@
<skip />
<!-- no translation found for android_spell_checker_settings (5822324635435443689) -->
<skip />
- <!-- no translation found for use_proximity_option_title (7469233942295924620) -->
+ <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) -->
<skip />
- <!-- no translation found for use_proximity_option_summary (2857708859847261945) -->
+ <!-- no translation found for use_contacts_for_spellchecking_option_summary (8754413382543307713) -->
<skip />
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar cun smatgar in buttun"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Tun cun smatgar in buttun"</string>
diff --git a/java/res/values-ro/donottranslate-more-keys.xml b/java/res/values-ro/donottranslate-more-keys.xml
index d7e6a171d..51df56099 100644
--- a/java/res/values-ro/donottranslate-more-keys.xml
+++ b/java/res/values-ro/donottranslate-more-keys.xml
@@ -18,7 +18,7 @@
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="more_keys_for_a">ă,â,à,á,ä,æ,ã,å,ā</string>
+ <string name="more_keys_for_a">â,ã,ă,à,á,ä,æ,å,ā</string>
<string name="more_keys_for_i">8,î,ï,ì,í,į,ī</string>
<string name="more_keys_for_s">ș,ß,ś,š</string>
<string name="more_keys_for_t">5,ț</string>
diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml
index c1dea5431..ba27c184a 100644
--- a/java/res/values-ro/strings.xml
+++ b/java/res/values-ro/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Opţiuni de introducere text"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Corecţie Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Setări de verificare ortografică"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Utiliz. datele de proxim."</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Utilizaţi un algor. de prox. similar tastat. pt. verif. ortograf."</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Verificare nume în agendă"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Verificatorul ortografic utilizează intrări din lista de contacte"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrare la apăsarea tastei"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Sunet la apăsarea tastei"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Fereastră pop-up la apăsarea tastei"</string>
diff --git a/java/res/values-ru/donottranslate-more-keys.xml b/java/res/values-ru/donottranslate-more-keys.xml
index f7e006e84..7ae9ffbda 100644
--- a/java/res/values-ru/donottranslate-more-keys.xml
+++ b/java/res/values-ru/donottranslate-more-keys.xml
@@ -18,7 +18,5 @@
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="more_keys_for_cyrillic_e">5,ё</string>
- <string name="more_keys_for_cyrillic_soft_sign">ъ</string>
- <string name="more_keys_for_cyrillic_ha">ъ</string>
+ <string name="more_keys_for_slavic_ye">5,ё</string>
</resources>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index 863c8a28c..c23b2c3c4 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Параметры ввода"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Исправления Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Настройка проверки правописания"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Алгоритм близости клавиш"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Использовать алгоритм близости клавиш для проверки правописания"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Поиск контактов"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Обращаться к списку контактов при проверке правописания"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Виброотклик клавиш"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Звук клавиш"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Увеличение нажатых"</string>
@@ -145,8 +145,8 @@
<string name="prefs_description_log" msgid="5827825607258246003">"Помогите усовершенствовать редактор способа ввода, разрешив отправку статистики и отчетов о сбоях в Google."</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Тема клавиатуры"</string>
<string name="subtype_de_qwerty" msgid="3358900499589259491">"Немецкая клавиатура QWERTY"</string>
- <string name="subtype_en_GB" msgid="88170601942311355">"Английский (Великобритания)"</string>
- <string name="subtype_en_US" msgid="6160452336634534239">"Английский (США)"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"английский (Великобритания)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"английский (США)"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Режим проверки удобства использования"</string>
<string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Настройки вибросигнала при нажатии клавиш"</string>
<string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Настройки громкости звука при нажатии клавиш"</string>
diff --git a/java/res/values-sk/donottranslate-more-keys.xml b/java/res/values-sk/donottranslate-more-keys.xml
index b73db0a46..b6b35c1a3 100644
--- a/java/res/values-sk/donottranslate-more-keys.xml
+++ b/java/res/values-sk/donottranslate-more-keys.xml
@@ -18,18 +18,20 @@
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="more_keys_for_a">ä,á,à,â,æ,ã,å,ā</string>
- <string name="more_keys_for_e">3,é,ě,è,ê,ë,ę,ė,ē</string>
- <string name="more_keys_for_i">8,í,î,ï,ì,į,ī</string>
- <string name="more_keys_for_o">9,ô,ó,ö,ò,õ,œ,ø,ō</string>
- <string name="more_keys_for_u">7,ú,ú,û,ü,ù,ū</string>
- <string name="more_keys_for_s">š,ß,ś</string>
- <string name="more_keys_for_n">ň,ñ,ń</string>
+ <string name="more_keys_for_a">á,ä,ā,à,â,ã,å,æ,ą</string>
+ <string name="more_keys_for_e">3,é,ě,ē,ė,è,ê,ë,ę</string>
+ <string name="more_keys_for_i">8,í,ī,į,ì,î,ï,ı</string>
+ <string name="more_keys_for_o">9,ô,ó,ö,ò,õ,œ,ő,ø</string>
+ <string name="more_keys_for_u">7,ú,ů,ü,ū,ų,ù,û,ű</string>
+ <string name="more_keys_for_s">š,ß,ś,ş</string>
+ <string name="more_keys_for_n">ň,ņ,ñ,ń,ń</string>
<string name="more_keys_for_c">č,ç,ć</string>
<string name="more_keys_for_y">6,ý,ÿ</string>
<string name="more_keys_for_d">ď</string>
- <string name="more_keys_for_r">4,ŕ,ř</string>
- <string name="more_keys_for_t">5,ť</string>
- <string name="more_keys_for_z">ž,ź,ż</string>
- <string name="more_keys_for_l">ľ,ĺ,ł</string>
+ <string name="more_keys_for_r">4,ŕ,ř,ŗ</string>
+ <string name="more_keys_for_t">5,ť,ţ</string>
+ <string name="more_keys_for_z">ž,ż,ź</string>
+ <string name="more_keys_for_k">ķ</string>
+ <string name="more_keys_for_l">ľ,ĺ,ļ,ł</string>
+ <string name="more_keys_for_g">ģ,ğ</string>
</resources>
diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml
index b7ab8f204..44d0af831 100644
--- a/java/res/values-sk/strings.xml
+++ b/java/res/values-sk/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti zadávania textu a údajov"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Opravy pravopisu Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Nastavenia kontroly pravopisu"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Použiť údaje o blízkosti"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Na kontr. pravopis. použiť algor. vzdialenosti ako pri kláves."</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Vyhľadať kontakty"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kontrola pravopisu používa záznamy z vášho zoznamu kontaktov"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Pri stlačení klávesu vibrovať"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Zvuk pri stlačení klávesu"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Zobraziť znaky pri stlačení klávesu"</string>
diff --git a/java/res/values-sl/donottranslate-more-keys.xml b/java/res/values-sl/donottranslate-more-keys.xml
new file mode 100644
index 000000000..b72c6799e
--- /dev/null
+++ b/java/res/values-sl/donottranslate-more-keys.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="more_keys_for_s">š</string>
+ <string name="more_keys_for_c">č,ć</string>
+ <string name="more_keys_for_d">đ</string>
+ <string name="more_keys_for_z">ž</string>
+</resources>
diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml
index d7f357aa0..ba3d0c6d2 100644
--- a/java/res/values-sl/strings.xml
+++ b/java/res/values-sl/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti vnosa"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Preverjanje črkovanja za Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Nastavitve preverjanja črkovanja"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Uporabi podatke bližine"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Uporaba algoritma za preverjanje črkovanja na podlagi bližine znakov na tipkovnici"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Iskanje imen stikov"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Črkovalnik uporablja vnose s seznama stikov"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibriranje ob pritisku tipke"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Zvok ob pritisku tipke"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Povečaj črko ob pritisku"</string>
diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml
index 0906fce6e..1d199b133 100644
--- a/java/res/values-sr/strings.xml
+++ b/java/res/values-sr/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Опције уноса"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android исправљање"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Подешавања провере правописа"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Употреба података близине"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Употреба алгоритма близине попут тастатуре за проверу правописа"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Потражи имена контаката"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Контролор правописа користи уносе са листе контаката"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Вибрирај на притисак тастера"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Звук на притисак тастера"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Искачући прозор приликом притиска тастера"</string>
diff --git a/java/res/values-sv/donottranslate-more-keys.xml b/java/res/values-sv/donottranslate-more-keys.xml
index 1fa29a83e..d391be5ab 100644
--- a/java/res/values-sv/donottranslate-more-keys.xml
+++ b/java/res/values-sv/donottranslate-more-keys.xml
@@ -22,6 +22,7 @@
<string name="more_keys_for_o">9,œ,ô,ò,ó,õ,ō</string>
<string name="more_keys_for_u">7,ü,û,ù,ú,ū</string>
<string name="more_keys_for_s">ß,ś,š</string>
+ <string name="keylabel_for_scandinavia_row1_11">å</string>
<string name="keylabel_for_scandinavia_row2_10">ö</string>
<string name="keylabel_for_scandinavia_row2_11">ä</string>
<string name="more_keys_for_scandinavia_row2_10">ø</string>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index 46760bbe2..a75736e93 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Inmatningsalternativ"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android-korrigering"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Inställningar för stavningskontroll"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Använd närhetsinformation"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Använd tangentbordsliknande närhetsalgoritm för stavningskontroll"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Sök namn på kontakter"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"I stavningskontrollen används poster från kontaktlistan"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrera vid tangenttryck"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Knappljud"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Popup vid knapptryck"</string>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index 822907b05..88ea85d63 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Chaguo za uingizaji"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Masahihisho ya Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Mipangilio ya kukagua sarufi"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Tumia data ya ukaribu"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Tumia kibodi kama ukaribu wa algorithmu kwa ukaguzi wa sarufi"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Angalia majina ya wasiliani"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kikagua tahajia hutumia ingizo kutoka kwa orodha yako ya anwani"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Tetema unabofya kitufe"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Toa sauti unapobofya kitufe"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Ibuka kitufe kinapobonyezwa"</string>
diff --git a/java/res/values-sw600dp-land/dimens.xml b/java/res/values-sw600dp-land/dimens.xml
index 1b8c8a64a..1c725a484 100644
--- a/java/res/values-sw600dp-land/dimens.xml
+++ b/java/res/values-sw600dp-land/dimens.xml
@@ -48,6 +48,7 @@
<fraction name="key_hint_letter_ratio">23%</fraction>
<fraction name="key_hint_label_ratio">34%</fraction>
<fraction name="key_uppercase_letter_ratio">29%</fraction>
+ <fraction name="spacebar_text_ratio">33.33%</fraction>
<dimen name="suggestions_strip_padding">40.0mm</dimen>
<integer name="max_more_suggestions_row">5</integer>
diff --git a/java/res/values-sw600dp/config.xml b/java/res/values-sw600dp/config.xml
index 1854a8696..1dd93121d 100644
--- a/java/res/values-sw600dp/config.xml
+++ b/java/res/values-sw600dp/config.xml
@@ -38,6 +38,5 @@
<integer name="config_long_press_space_key_timeout">0</integer>
<!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
<string name="config_default_keyboard_theme_id" translatable="false">5</string>
- <string name="config_text_size_of_language_on_spacebar" translatable="false">medium</string>
<integer name="config_max_more_keys_column">5</integer>
</resources>
diff --git a/java/res/values-sw600dp/dimens.xml b/java/res/values-sw600dp/dimens.xml
index 31830239d..e393be579 100644
--- a/java/res/values-sw600dp/dimens.xml
+++ b/java/res/values-sw600dp/dimens.xml
@@ -59,6 +59,7 @@
<fraction name="key_hint_label_ratio">28%</fraction>
<fraction name="key_uppercase_letter_ratio">26%</fraction>
<fraction name="key_preview_text_ratio">50%</fraction>
+ <fraction name="spacebar_text_ratio">32.14%</fraction>
<dimen name="key_preview_height">15.0mm</dimen>
<dimen name="key_preview_offset">0.1in</dimen>
diff --git a/java/res/values-sw768dp-land/dimens.xml b/java/res/values-sw768dp-land/dimens.xml
index 664e8c159..ef39f4393 100644
--- a/java/res/values-sw768dp-land/dimens.xml
+++ b/java/res/values-sw768dp-land/dimens.xml
@@ -52,6 +52,7 @@
<fraction name="key_hint_letter_ratio">23%</fraction>
<fraction name="key_hint_label_ratio">28%</fraction>
<fraction name="key_uppercase_letter_ratio">24%</fraction>
+ <fraction name="spacebar_text_ratio">24.00%</fraction>
<dimen name="key_preview_height">17.0mm</dimen>
<dimen name="key_preview_height_ics">26.5mm</dimen>
diff --git a/java/res/values-sw768dp/config.xml b/java/res/values-sw768dp/config.xml
index c25139a42..06553a7c9 100644
--- a/java/res/values-sw768dp/config.xml
+++ b/java/res/values-sw768dp/config.xml
@@ -36,7 +36,6 @@
<integer name="config_long_press_space_key_timeout">0</integer>
<!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
<string name="config_default_keyboard_theme_id" translatable="false">5</string>
- <string name="config_text_size_of_language_on_spacebar" translatable="false">medium</string>
<integer name="config_max_more_keys_column">5</integer>
<!-- Screen metrics for logging.
0 = "mdpi phone screen"
diff --git a/java/res/values-sw768dp/dimens.xml b/java/res/values-sw768dp/dimens.xml
index bb4937dd5..dbbd844f0 100644
--- a/java/res/values-sw768dp/dimens.xml
+++ b/java/res/values-sw768dp/dimens.xml
@@ -62,6 +62,7 @@
<fraction name="key_hint_label_ratio">28%</fraction>
<fraction name="key_uppercase_letter_ratio">26%</fraction>
<fraction name="key_preview_text_ratio">50%</fraction>
+ <fraction name="spacebar_text_ratio">29.03%</fraction>
<dimen name="key_preview_height">15.0mm</dimen>
<dimen name="key_preview_offset">0.1in</dimen>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index 53f56606c..1a3afafca 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"ตัวเลือกการป้อนข้อมูล"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"การแก้ไขของ Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"การตั้งค่าการตรวจสอบการสะกด"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"ใช้ข้อมูลที่ใกล้เคียง"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"ใช้อัลกอริทึมใกล้เคียงที่คล้ายกับแป้นพิมพ์สำหรับตรวจสอบการสะกด"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"ค้นหารายชื่อติดต่อ"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"เครื่องมือตรวจการสะกดใช้รายการจากรายชื่อติดต่อของคุณ"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"สั่นเมื่อกดปุ่ม"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"ส่งเสียงเมื่อกดปุ่ม"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"ป๊อปอัปเมื่อกดแป้น"</string>
diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml
index 701963f2a..3b4e4d964 100644
--- a/java/res/values-tl/strings.xml
+++ b/java/res/values-tl/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Mga pagpipilian sa input"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Pagwawasto sa Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Mga setting ng pang-check ng pagbabaybay"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Gamitin ang proximity data"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Gumamit ng proximity algorithm na tulad ng keyboard para sa pag-check ng pagbabaybay"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Maghanap pangalan contact"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Gumagamit pang-check pagbabaybay entry sa iyong listahan contact"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Mag-vibrate sa keypress"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Tunog sa keypress"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Popup sa keypress"</string>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index 4ae7d78c9..7ee12eb44 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Giriş seçenekleri"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android düzeltme"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Yazım denetimi ayarları"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Yakınlık verilri kullan"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Yazım denetimi içn klavye benzeri yakınlık algoritması kullan"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kişi adlarını denetle"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Yazım denetleyici, kişi listenizdeki girişleri kullanır"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Tuşa basıldığında titret"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Tuşa basıldığında ses çıkar"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Tuşa basıldığında pop-up aç"</string>
diff --git a/java/res/values-uk/donottranslate-more-keys.xml b/java/res/values-uk/donottranslate-more-keys.xml
new file mode 100644
index 000000000..4e7910128
--- /dev/null
+++ b/java/res/values-uk/donottranslate-more-keys.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keylabel_for_slavic_yery">і</string>
+ <string name="more_keys_for_slavic_yery">ї</string>
+</resources>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index 234a9c56a..ff1608f95 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Парам. введення"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Виправлення Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Налаштування перевірки орфографії"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Використ. дані близькості"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Для перевірки орфогр. викор. алгоритм близьк., аналог. клавіат."</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Шукати імена контактів"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Програма перевірки правопису використ. записи зі списку контактів"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Вібр при натиску клав."</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Звук при натиску клав."</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Сплив. при нат.клав."</string>
diff --git a/java/res/values-vi/donottranslate-more-keys.xml b/java/res/values-vi/donottranslate-more-keys.xml
new file mode 100644
index 000000000..97a7d79ae
--- /dev/null
+++ b/java/res/values-vi/donottranslate-more-keys.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="more_keys_for_a">à,á,ả,ã,ạ,ă,ằ,ắ,ẳ,ẵ,ặ,â,ầ,ấ,ẩ,ẫ,ậ</string>
+ <string name="more_keys_for_e">3,è,é,ẻ,ẽ,ẹ,ê,ề,ế,ể,ễ,ệ</string>
+ <string name="more_keys_for_i">8,ì,í,ỉ,ĩ,ị</string>
+ <string name="more_keys_for_o">9,ò,ó,ỏ,õ,ọ,ô,ồ,ố,ổ,ỗ,ộ,ơ,ờ,ớ,ở,ỡ,ợ</string>
+ <string name="more_keys_for_u">7,ù,ú,ủ,ũ,ụ,ư,ừ,ứ,ử,ữ,ự</string>
+ <string name="more_keys_for_y">6,ỳ,ý,ỷ,ỹ,ỵ</string>
+ <string name="more_keys_for_d">đ</string>
+</resources>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index e602b495a..d9c524eff 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Tùy chọn nhập"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Dịch vụ sửa chính tả của Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Cài đặt kiểm tra chính tả"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Sử dụng dữ liệu gần"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Dùng thuật toán gần, như của bàn phím để k.tra chính tả"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Tra cứu tên liên hệ"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Trình kiểm tra chính tả sử dụng các mục nhập từ danh sách liên hệ của bạn"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Rung khi nhấn phím"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Âm thanh khi nhấn phím"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Cửa sổ bật lên khi nhấn phím"</string>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index c3adf23c0..5162ea7e9 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"输入选项"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android 更正"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"拼写检查设置"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"使用邻近度数据"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"使用类似键盘的邻近度算法进行拼写检查"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"查找联系人姓名"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"拼写检查工具会使用您的联系人列表中的条目"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"按键时振动"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"按键时播放音效"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"按键时显示弹出窗口"</string>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index 8d60fb7cd..fdb11a006 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"輸入選項"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Android 拼字修正服務"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"拼字檢查設定"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"使用鄰近資料"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"運用類似鍵盤的鄰近演算法進行拼字檢查"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"查詢聯絡人姓名"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"拼字檢查程式使用您的聯絡人清單項目"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"按鍵時震動"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"按鍵時播放音效"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"按鍵時顯示彈出式視窗"</string>
@@ -50,7 +50,7 @@
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"一律顯示"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"以垂直模式顯示"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"永遠隱藏"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"顯示設定金鑰"</string>
+ <string name="prefs_settings_key" msgid="4623341240804046498">"顯示設定鍵"</string>
<string name="auto_correction" msgid="4979925752001319458">"自動修正"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"按空白鍵或標點符號時,自動修正前面的錯字"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"關閉"</string>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index 072d17cba..05da50c28 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -25,8 +25,8 @@
<string name="english_ime_input_options" msgid="3909945612939668554">"Okukhethwa kukho kokungenayo"</string>
<string name="spell_checker_service_name" msgid="2003013122022285508">"Ukulungisa kwe-Android"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Izilungiselelo zokuhlola ukupela"</string>
- <string name="use_proximity_option_title" msgid="7469233942295924620">"Sebenzisa imininingo ye-proximity"</string>
- <string name="use_proximity_option_summary" msgid="2857708859847261945">"Sebenzisa i-proximity algorithm efana ne-keyboard ukuhlola ukupela"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Bheka amagama woxhumana nabo"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Isihloli sokupela sisebenzisa okungenayo kusuka kuhlu lalabo oxhumana nabo"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Dlidlizelisa ngokucindezela inkinobho"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Umsindo wokucindezela ukhiye"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Ugaxekile ngokucindezela ukhiye"</string>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 0c9ca4f4a..9892d7835 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -18,10 +18,13 @@
<declare-styleable name="KeyboardTheme">
<!-- Keyboard style -->
<attr name="keyboardStyle" format="reference" />
+ <!-- TODO: Get rid of latinKeyboardStyle -->
<!-- LatinKeyboard style -->
<attr name="latinKeyboardStyle" format="reference" />
<!-- KeyboardView style -->
<attr name="keyboardViewStyle" format="reference" />
+ <!-- LatinKeyboardView style -->
+ <attr name="latinKeyboardViewStyle" format="reference" />
<!-- MiniKeyboard style -->
<attr name="miniKeyboardStyle" format="reference" />
<!-- MiniKeyboardView style -->
@@ -120,6 +123,15 @@
</attr>
</declare-styleable>
+ <declare-styleable name="LatinKeyboardView">
+ <attr name="autoCorrectionSpacebarLedEnabled" format="boolean" />
+ <attr name="autoCorrectionSpacebarLedIcon" format="reference" />
+ <!-- Size of the text for spacebar language label, in the proportion of key height. -->
+ <attr name="spacebarTextRatio" format="fraction" />
+ <attr name="spacebarTextColor" format="color" />
+ <attr name="spacebarTextShadowColor" format="color" />
+ </declare-styleable>
+
<declare-styleable name="SuggestionsView">
<attr name="suggestionStripOption" format="integer">
<!-- This should be aligned with SuggestionsViewParams.AUTO_CORRECT_* and etc. -->
@@ -127,9 +139,11 @@
<flag name="autoCorrectUnderline" value="0x02" />
<flag name="validTypedWordBold" value="0x04" />
</attr>
+ <attr name="colorValidTypedWord" format="color" />
<attr name="colorTypedWord" format="color" />
<attr name="colorAutoCorrect" format="color" />
<attr name="colorSuggested" format="color" />
+ <attr name="alphaValidTypedWord" format="integer" />
<attr name="alphaTypedWord" format="integer" />
<attr name="alphaAutoCorrect" format="integer" />
<attr name="alphaSuggested" format="integer" />
@@ -164,8 +178,6 @@
<attr name="verticalGap" format="dimension|fraction" />
<!-- More keys keyboard layout template -->
<attr name="moreKeysTemplate" format="reference" />
- <!-- Locale of the keyboard layout -->
- <attr name="keyboardLocale" format="string" />
<!-- True if the keyboard is Right-To-Left -->
<attr name="isRtlKeyboard" format="boolean" />
<!-- Icon set for key top and key preview. -->
@@ -178,13 +190,17 @@
<attr name="iconTabKey" format="reference" />
<attr name="iconShortcutKey" format="reference" />
<attr name="iconShortcutForLabel" format="reference" />
- <attr name="iconShiftedShiftKey" format="reference" />
+ <attr name="iconSpaceKeyForNumberLayout" format="reference" />
+ <attr name="iconShiftKeyShifted" format="reference" />
+ <attr name="iconDisabledShortcutKey" format="reference" />
<attr name="iconPreviewTabKey" format="reference" />
</declare-styleable>
<declare-styleable name="Keyboard_Key">
<!-- The unicode value that this key outputs. -->
<attr name="code" format="integer" />
+ <!-- The alternate unicode value that this key outputs while typing. -->
+ <attr name="altCode" format="integer" />
<!-- The keys to display in the more keys keyboard. -->
<attr name="moreKeys" format="string" />
<!-- Maximum column of more keys keyboard -->
@@ -196,17 +212,22 @@
<enum name="action" value="2" />
<enum name="sticky" value="3" />
</attr>
- <!-- Whether long-pressing on this key will make it repeat. -->
- <attr name="isRepeatable" format="boolean" />
+ <!-- The key action flags. -->
+ <attr name="keyActionFlags" format="integer">
+ <!-- This should be aligned with Key.ACTION_FLAGS_* -->
+ <flag name="isRepeatable" value="0x01" />
+ <flag name="noKeyPreview" value="0x02" />
+ <flag name="altCodeWhileTyping" value="0x04" />
+ </attr>
<!-- The string of characters to output when this key is pressed. -->
<attr name="keyOutputText" format="string" />
<!-- The label to display on the key. -->
<attr name="keyLabel" format="string" />
<!-- The hint label to display on the key in conjunction with the label. -->
<attr name="keyHintLabel" format="string" />
- <!-- The key label option. -->
- <attr name="keyLabelOption" format="integer">
- <!-- This should be aligned with Key.LABEL_OPTION_* -->
+ <!-- The key label flags. -->
+ <attr name="keyLabelFlags" format="integer">
+ <!-- This should be aligned with Key.LABEL_FLAGS__* -->
<flag name="alignLeft" value="0x01" />
<flag name="alignRight" value="0x02" />
<flag name="alignLeftOfCenter" value="0x08" />
@@ -224,31 +245,33 @@
</attr>
<!-- The icon to display on the key instead of the label. -->
<attr name="keyIcon" format="enum">
- <!-- This should be aligned with KeyboardIcons.ICON_* -->
+ <!-- This should be aligned with the KeyboardIcons.ICONS_TO_ATTRS_MAP -->
<enum name="iconShiftKey" value="1" />
<enum name="iconDeleteKey" value="2" />
+ <!-- This is also represented as "@icon/3" in keyboard layout XML. -->
<enum name="iconSettingsKey" value="3" />
<enum name="iconSpaceKey" value="4" />
<enum name="iconReturnKey" value="5" />
<enum name="iconSearchKey" value="6" />
+ <!-- This is also represented as "@icon/7" in keyboard layout XML. -->
<enum name="iconTabKey" value="7" />
<enum name="iconShortcutKey" value="8" />
<enum name="iconShortcutForLabel" value="9" />
+ <enum name="iconSpaceKeyForNumberLayout" value="10" />
+ <enum name="iconShiftKeyShifted" value="11" />
</attr>
- <!-- Shift key icon for shifted state -->
- <attr name="keyIconShifted" format="enum">
- <!-- This should be aligned with KeyboardIcons.ICON_SHIFTED_* -->
- <enum name="iconShiftedShiftKey" value="10" />
+ <!-- The icon for disabled key -->
+ <attr name="keyIconDisabled" format="enum">
+ <!-- This should be aligned with the KeyboardIcons.ICONS_TO_ATTRS_MAP -->
+ <enum name="iconDisabledShortcutKey" value="12" />
</attr>
<!-- The icon to show in the popup preview. -->
<attr name="keyIconPreview" format="enum">
- <!-- This should be aligned with KeyboardIcons.ICON_PREVIEW_* -->
- <enum name="iconPreviewTabKey" value="11" />
+ <!-- This should be aligned with the KeyboardIcons.ICONS_TO_ATTRS_MAP -->
+ <enum name="iconPreviewTabKey" value="13" />
</attr>
<!-- The key style to specify a set of key attributes defined by <key_style/> -->
<attr name="keyStyle" format="string" />
- <!-- The key is enabled and responds on press. -->
- <attr name="enabled" format="boolean" />
<!-- Visual insets -->
<attr name="visualInsetsLeft" format="dimension|fraction" />
<attr name="visualInsetsRight" format="dimension|fraction" />
@@ -316,11 +339,28 @@
<attr name="parentStyle" format="string" />
</declare-styleable>
- <declare-styleable name="LatinKeyboard">
- <attr name="autoCorrectionSpacebarLedEnabled" format="boolean" />
- <attr name="autoCorrectionSpacebarLedIcon" format="reference" />
- <attr name="disabledShortcutIcon" format="reference" />
- <attr name="spacebarTextColor" format="color" />
- <attr name="spacebarTextShadowColor" format="color" />
+ <declare-styleable name="KeyboardSet">
+ <!-- Locale of the keyboard layouts -->
+ <attr name="keyboardLocale" format="string" />
+ </declare-styleable>
+
+ <declare-styleable name="KeyboardSet_Element">
+ <!-- This should be aligned with KeyboardId.ELEMENT_* -->
+ <attr name="elementName" format="enum">
+ <enum name="alphabet" value="0" />
+ <!-- TODO: Implement alphabet variant shift keyboards
+ <enum name="alphabetManualTemporaryShift" value="1" />
+ <enum name="alphabetAutomaticTemporaryShift" value="2" />
+ <enum name="alphabetShiftLock" value="3" />
+ <enum name="alphabetShiftLockShift" value="4" />
+ -->
+ <enum name="symbols" value="5" />
+ <enum name="symbolsShift" value="6" />
+ <enum name="phone" value="7" />
+ <enum name="phoneShift" value="8" />
+ <enum name="number" value="9" />
+ </attr>
+ <attr name="elementKeyboard" format="reference" />
+ <!-- TODO: Add setShifted and setShiftLocked attribute. -->
</declare-styleable>
</resources>
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index 3f676ab25..55f35f0c5 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -38,7 +38,6 @@
<bool name="config_default_bigram_prediction">false</bool>
<bool name="config_default_sound_enabled">false</bool>
<bool name="config_default_vibration_enabled">true</bool>
- <bool name="config_auto_correction_spacebar_led_enabled">false</bool>
<!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false -->
<bool name="config_show_mini_keyboard_at_touched_point">false</bool>
<!-- The language is never displayed if == 0, always displayed if < 0 -->
@@ -67,7 +66,6 @@
<dimen name="config_touch_noise_threshold_distance">2.0mm</dimen>
<!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
<string name="config_default_keyboard_theme_id" translatable="false">5</string>
- <string name="config_text_size_of_language_on_spacebar" translatable="false">small</string>
<integer name="config_max_more_keys_column">5</integer>
<string-array name="auto_correction_threshold_values" translatable="false">
<!-- Off, When auto correction setting is Off, this value is not used. -->
@@ -81,8 +79,8 @@
will be subject to auto-correction. -->
<item>0</item>
</string-array>
- <!-- Threshold of the normalized score of the best suggestion for the spell checker to declare a word to be "likely" -->
- <string name="spellchecker_likely_threshold_value" translatable="false">0.11</string>
+ <!-- Threshold of the normalized score of the best suggestion for the spell checker to declare a word to be "recommended" -->
+ <string name="spellchecker_recommended_threshold_value" translatable="false">0.11</string>
<!-- Threshold of the normalized score of any dictionary lookup to be offered as a suggestion by the spell checker -->
<string name="spellchecker_suggestion_threshold_value" translatable="false">0.03</string>
<!-- Screen metrics for logging.
diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml
index 352141ca6..e46ff7718 100644
--- a/java/res/values/dimens.xml
+++ b/java/res/values/dimens.xml
@@ -66,6 +66,7 @@
<fraction name="key_hint_label_ratio">44%</fraction>
<fraction name="key_uppercase_letter_ratio">35%</fraction>
<fraction name="key_preview_text_ratio">82%</fraction>
+ <fraction name="spacebar_text_ratio">33.735%</fraction>
<dimen name="key_preview_height">80sp</dimen>
<dimen name="key_preview_offset">0.1in</dimen>
diff --git a/java/res/values/donottranslate-more-keys.xml b/java/res/values/donottranslate-more-keys.xml
index 6c7753999..3a3ea1e55 100644
--- a/java/res/values/donottranslate-more-keys.xml
+++ b/java/res/values/donottranslate-more-keys.xml
@@ -38,13 +38,21 @@
<string name="more_keys_for_g"></string>
<string name="more_keys_for_p">0</string>
<string name="more_keys_for_v"></string>
+ <string name="keylabel_for_scandinavia_row1_11"></string>
<string name="keylabel_for_scandinavia_row2_10"></string>
<string name="keylabel_for_scandinavia_row2_11"></string>
<string name="more_keys_for_scandinavia_row2_10"></string>
<string name="more_keys_for_scandinavia_row2_11"></string>
- <string name="more_keys_for_cyrillic_e"></string>
- <string name="more_keys_for_cyrillic_soft_sign"></string>
- <string name="more_keys_for_cyrillic_ha"></string>
+ <string name="keylabel_for_slavic_shcha">щ</string>
+ <string name="keylabel_for_slavic_yery">ы</string>
+ <string name="keylabel_for_slavic_i">и</string>
+ <string name="more_keys_for_slavic_u">3</string>
+ <string name="more_keys_for_slavic_ye">5</string>
+ <string name="more_keys_for_slavic_en">6</string>
+ <string name="more_keys_for_slavic_ha">ъ</string>
+ <string name="more_keys_for_slavic_yery"></string>
+ <string name="more_keys_for_slavic_o"></string>
+ <string name="more_keys_for_slavic_soft_sign">ъ</string>
<string name="more_keys_for_currency_dollar">¢,£,€,¥,₱</string>
<string name="more_keys_for_currency_euro">¢,£,$,¥,₱</string>
<string name="more_keys_for_currency_pound">¢,$,€,¥,₱</string>
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index aefaec9ef..1f7736d9c 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -166,4 +166,5 @@
<string name="dictionary_pack_package_name">com.google.android.inputmethod.latin.dictionarypack</string>
<string name="dictionary_pack_settings_activity">com.google.android.inputmethod.latin.dictionarypack.DictionarySettingsActivity</string>
<string name="settings_ms">ms</string>
+ <string name="settings_warning_researcher_mode">Attention! You are using the special keyboard for research purposes.</string>
</resources>
diff --git a/java/res/values/keyboard-icons-black.xml b/java/res/values/keyboard-icons-black.xml
index f767cb349..1c5a5f720 100644
--- a/java/res/values/keyboard-icons-black.xml
+++ b/java/res/values/keyboard-icons-black.xml
@@ -30,10 +30,9 @@
<item name="iconTabKey">@drawable/sym_bkeyboard_tab</item>
<item name="iconShortcutKey">@drawable/sym_bkeyboard_mic</item>
<item name="iconShortcutForLabel">@drawable/sym_bkeyboard_label_mic</item>
- <item name="iconShiftedShiftKey">@drawable/sym_bkeyboard_shift_locked</item>
+ <item name="iconSpaceKeyForNumberLayout">@drawable/sym_bkeyboard_space</item>
+ <item name="iconShiftKeyShifted">@drawable/sym_bkeyboard_shift_locked</item>
+ <item name="iconDisabledShortcutKey">@drawable/sym_bkeyboard_voice_off</item>
<item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item>
- <!-- LatinKeyboard icons -->
- <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
- <item name="disabledShortcutIcon">@drawable/sym_bkeyboard_voice_off</item>
</style>
</resources>
diff --git a/java/res/values/keyboard-icons-ics.xml b/java/res/values/keyboard-icons-ics.xml
index f1021433d..f68be5f1e 100644
--- a/java/res/values/keyboard-icons-ics.xml
+++ b/java/res/values/keyboard-icons-ics.xml
@@ -23,16 +23,15 @@
<item name="iconShiftKey">@drawable/sym_keyboard_shift_holo</item>
<item name="iconDeleteKey">@drawable/sym_keyboard_delete_holo</item>
<item name="iconSettingsKey">@drawable/sym_keyboard_settings_holo</item>
- <item name="iconSpaceKey">@drawable/sym_keyboard_space_holo</item>
+ <item name="iconSpaceKey">@null</item>
<item name="iconReturnKey">@drawable/sym_keyboard_return_holo</item>
<item name="iconSearchKey">@drawable/sym_keyboard_search_holo</item>
<item name="iconTabKey">@drawable/sym_keyboard_tab_holo</item>
<item name="iconShortcutKey">@drawable/sym_keyboard_voice_holo</item>
<item name="iconShortcutForLabel">@drawable/sym_keyboard_label_mic_holo</item>
- <item name="iconShiftedShiftKey">@drawable/sym_keyboard_shift_locked_holo</item>
+ <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space_holo</item>
+ <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked_holo</item>
+ <item name="iconDisabledShortcutKey">@drawable/sym_keyboard_voice_off_holo</item>
<item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item>
- <!-- LatinKeyboard icons -->
- <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led_holo</item>
- <item name="disabledShortcutIcon">@drawable/sym_keyboard_voice_off_holo</item>
</style>
</resources>
diff --git a/java/res/values/keyboard-icons-white.xml b/java/res/values/keyboard-icons-white.xml
index 07ece66b1..35197a1c0 100644
--- a/java/res/values/keyboard-icons-white.xml
+++ b/java/res/values/keyboard-icons-white.xml
@@ -26,10 +26,10 @@
<item name="iconTabKey">@drawable/sym_keyboard_tab</item>
<item name="iconShortcutKey">@drawable/sym_keyboard_mic</item>
<item name="iconShortcutForLabel">@drawable/sym_keyboard_label_mic</item>
- <item name="iconShiftedShiftKey">@drawable/sym_keyboard_shift_locked</item>
+ <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space</item>
+ <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked</item>
+ <!-- TODO: Needs non-holo disabled shortcut icon drawable -->
+ <item name="iconDisabledShortcutKey">@drawable/sym_keyboard_voice_off_holo</item>
<item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item>
- <!-- LatinKeyboard icons -->
- <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
- <item name="disabledShortcutIcon">@drawable/sym_keyboard_voice_off_holo</item>
</style>
</resources>
diff --git a/java/res/values/keycodes.xml b/java/res/values/keycodes.xml
index 59cc07531..b3f71d2bb 100644
--- a/java/res/values/keycodes.xml
+++ b/java/res/values/keycodes.xml
@@ -25,7 +25,10 @@
<integer name="key_space">32</integer>
<integer name="key_shift">-1</integer>
<integer name="key_switch_alpha_symbol">-2</integer>
+ <integer name="key_capslock">-3</integer>
+ <integer name="key_output_text">-4</integer>
<integer name="key_delete">-5</integer>
<integer name="key_settings">-6</integer>
<integer name="key_shortcut">-7</integer>
+ <integer name="key_unspecified">-9</integer>
</resources>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index e00547a62..d860a1b23 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -20,6 +20,8 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Title for Latin keyboard -->
<string name="english_ime_name">Android keyboard</string>
+ <!-- Application name for opensource Android keyboard. AOSP(Android Open Source Project) should not be translated. -->
+ <string name="aosp_android_keyboard_ime_name">Android keyboard (AOSP)</string>
<!-- Title for Latin keyboard settings activity / dialog -->
<string name="english_ime_settings">Android keyboard settings</string>
<!-- Title for Latin keyboard input options dialog [CHAR LIMIT=25] -->
@@ -31,11 +33,11 @@
<!-- Title for the spell checking service settings screen -->
<string name="android_spell_checker_settings">Spell checking settings</string>
- <!-- Title for the "use proximity" option for spell checking [CHAR LIMIT=25] -->
- <string name="use_proximity_option_title">Use proximity data</string>
+ <!-- Title for the spell checker option to turn on/off contact names lookup [CHAR LIMIT=25] -->
+ <string name="use_contacts_for_spellchecking_option_title">Look up contact names</string>
- <!-- Description for the "use proximity" option for spell checking [CHAR LIMIT=65] -->
- <string name="use_proximity_option_summary">Use a keyboard-like proximity algorithm for spell checking</string>
+ <!-- Description for the spell checker option to turn on/off contact names lookup. [CHAR LIMIT=65] -->
+ <string name="use_contacts_for_spellchecking_option_summary">Spell checker uses entries from your contact list</string>
<!-- Option to provide vibrate/haptic feedback on keypress -->
<string name="vibrate_on_keypress">Vibrate on keypress</string>
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index 43aa58388..c4e39e357 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -31,12 +31,6 @@
<item name="verticalGap">@fraction/key_bottom_gap</item>
<item name="maxMoreKeysColumn">@integer/config_max_more_keys_column</item>
</style>
- <style name="LatinKeyboard">
- <item name="autoCorrectionSpacebarLedEnabled">@bool/config_auto_correction_spacebar_led_enabled
- </item>
- <item name="spacebarTextColor">#FFC0C0C0</item>
- <item name="spacebarTextShadowColor">#80000000</item>
- </style>
<style name="KeyboardView">
<item name="android:background">@drawable/keyboard_background</item>
<item name="keyBackground">@drawable/btn_keyboard_key</item>
@@ -72,6 +66,15 @@
<item name="backgroundDimAmount">0.5</item>
</style>
<style
+ name="LatinKeyboardView"
+ parent="KeyboardView">
+ <item name="autoCorrectionSpacebarLedEnabled">true</item>
+ <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
+ <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item>
+ <item name="spacebarTextColor">#FFC0C0C0</item>
+ <item name="spacebarTextShadowColor">#80000000</item>
+ </style>
+ <style
name="MiniKeyboard"
parent="Keyboard"
>
@@ -98,7 +101,8 @@
name="SuggestionsViewStyle"
parent="SuggestionsStripBackgroundStyle"
>
- <item name="suggestionStripOption">autoCorrectBold</item>
+ <item name="suggestionStripOption">autoCorrectBold|validTypedWordBold</item>
+ <item name="colorValidTypedWord">#FFFCAE00</item>
<item name="colorTypedWord">@android:color/white</item>
<item name="colorAutoCorrect">#FFFCAE00</item>
<item name="colorSuggested">#FFFCAE00</item>
@@ -133,6 +137,16 @@
<item name="android:background">@android:color/black</item>
<item name="keyBackground">@drawable/btn_keyboard_key3</item>
</style>
+ <style
+ name="LatinKeyboardView.HighContrast"
+ parent="KeyboardView.HighContrast"
+ >
+ <item name="autoCorrectionSpacebarLedEnabled">true</item>
+ <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
+ <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item>
+ <item name="spacebarTextColor">#FFC0C0C0</item>
+ <item name="spacebarTextShadowColor">#80000000</item>
+ </style>
<!-- Theme "Stone" -->
<style
name="Keyboard.Stone"
@@ -146,13 +160,6 @@
<item name="verticalGap">@fraction/key_bottom_gap_stone</item>
</style>
<style
- name="LatinKeyboard.Stone"
- parent="LatinKeyboard"
- >
- <item name="spacebarTextColor">#FF000000</item>
- <item name="spacebarTextShadowColor">#D0FFFFFF</item>
- </style>
- <style
name="KeyboardView.Stone"
parent="KeyboardView"
>
@@ -166,6 +173,16 @@
<item name="shadowColor">#FFFFFFFF</item>
</style>
<style
+ name="LatinKeyboardView.Stone"
+ parent="KeyboardView.Stone"
+ >
+ <item name="autoCorrectionSpacebarLedEnabled">true</item>
+ <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
+ <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item>
+ <item name="spacebarTextColor">#FF000000</item>
+ <item name="spacebarTextShadowColor">#D0FFFFFF</item>
+ </style>
+ <style
name="MiniKeyboard.Stone"
parent="Keyboard.Stone"
>
@@ -194,6 +211,16 @@
>
<item name="keyTextStyle">bold</item>
</style>
+ <style
+ name="LatinKeyboardView.Stone.Bold"
+ parent="KeyboardView.Stone.Bold"
+ >
+ <item name="autoCorrectionSpacebarLedEnabled">true</item>
+ <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
+ <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item>
+ <item name="spacebarTextColor">#FF000000</item>
+ <item name="spacebarTextShadowColor">#D0FFFFFF</item>
+ </style>
<!-- Theme "Gingerbread" -->
<style
name="Keyboard.Gingerbread"
@@ -213,6 +240,16 @@
<item name="keyTextStyle">bold</item>
</style>
<style
+ name="LatinKeyboardView.Gingerbread"
+ parent="KeyboardView.Gingerbread"
+ >
+ <item name="autoCorrectionSpacebarLedEnabled">true</item>
+ <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
+ <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item>
+ <item name="spacebarTextColor">#FFC0C0C0</item>
+ <item name="spacebarTextShadowColor">#80000000</item>
+ </style>
+ <style
name="MiniKeyboard.Gingerbread"
parent="Keyboard.Gingerbread"
>
@@ -239,12 +276,6 @@
<item name="touchPositionCorrectionData">@array/touch_position_correction_data_ice_cream_sandwich</item>
</style>
<style
- name="LatinKeyboard.IceCreamSandwich"
- parent="LatinKeyboard"
- >
- <item name="disabledShortcutIcon">@drawable/sym_keyboard_voice_off_holo</item>
- </style>
- <style
name="KeyboardView.IceCreamSandwich"
parent="KeyboardView"
>
@@ -268,6 +299,16 @@
<item name="shadowRadius">0.0</item>
</style>
<style
+ name="LatinKeyboardView.IceCreamSandwich"
+ parent="KeyboardView.IceCreamSandwich"
+ >
+ <item name="autoCorrectionSpacebarLedEnabled">false</item>
+ <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led_holo</item>
+ <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item>
+ <item name="spacebarTextColor">#FFC0C0C0</item>
+ <item name="spacebarTextShadowColor">#80000000</item>
+ </style>
+ <style
name="MiniKeyboard.IceCreamSandwich"
parent="Keyboard.IceCreamSandwich"
>
@@ -296,11 +337,12 @@
>
<item name="suggestionStripOption">autoCorrectBold|validTypedWordBold</item>
<!-- android:color/holo_blue_light=#FF33B5E5 -->
+ <item name="colorValidTypedWord">@android:color/holo_blue_light</item>
<item name="colorTypedWord">@android:color/holo_blue_light</item>
<item name="colorAutoCorrect">@android:color/holo_blue_light</item>
<item name="colorSuggested">@android:color/holo_blue_light</item>
+ <item name="alphaValidTypedWord">85</item>
<item name="alphaTypedWord">85</item>
- <item name="alphaAutoCorrect">100</item>
<item name="alphaSuggested">70</item>
<item name="alphaObsoleted">70</item>
<item name="suggestionsCountInStrip">@integer/suggestions_count_in_strip</item>
diff --git a/java/res/values/themes-basic-highcontrast.xml b/java/res/values/themes-basic-highcontrast.xml
index abb7c8057..0062b2837 100644
--- a/java/res/values/themes-basic-highcontrast.xml
+++ b/java/res/values/themes-basic-highcontrast.xml
@@ -17,8 +17,8 @@
<resources>
<style name="KeyboardTheme.HighContrast" parent="KeyboardIcons">
<item name="keyboardStyle">@style/Keyboard.HighContrast</item>
- <item name="latinKeyboardStyle">@style/LatinKeyboard</item>
<item name="keyboardViewStyle">@style/KeyboardView.HighContrast</item>
+ <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.HighContrast</item>
<item name="miniKeyboardStyle">@style/MiniKeyboard</item>
<item name="miniKeyboardViewStyle">@style/MiniKeyboardView</item>
<item name="miniKeyboardPanelStyle">@style/MiniKeyboardPanelStyle</item>
diff --git a/java/res/values/themes-basic.xml b/java/res/values/themes-basic.xml
index ff9fed55f..0786e08fc 100644
--- a/java/res/values/themes-basic.xml
+++ b/java/res/values/themes-basic.xml
@@ -17,8 +17,8 @@
<resources>
<style name="KeyboardTheme" parent="KeyboardIcons">
<item name="keyboardStyle">@style/Keyboard</item>
- <item name="latinKeyboardStyle">@style/LatinKeyboard</item>
<item name="keyboardViewStyle">@style/KeyboardView</item>
+ <item name="latinKeyboardViewStyle">@style/LatinKeyboardView</item>
<item name="miniKeyboardStyle">@style/MiniKeyboard</item>
<item name="miniKeyboardViewStyle">@style/MiniKeyboardView</item>
<item name="miniKeyboardPanelStyle">@style/MiniKeyboardPanelStyle</item>
diff --git a/java/res/values/themes-gingerbread.xml b/java/res/values/themes-gingerbread.xml
index be853eb0f..44338d821 100644
--- a/java/res/values/themes-gingerbread.xml
+++ b/java/res/values/themes-gingerbread.xml
@@ -17,8 +17,8 @@
<resources>
<style name="KeyboardTheme.Gingerbread" parent="KeyboardIcons">
<item name="keyboardStyle">@style/Keyboard.Gingerbread</item>
- <item name="latinKeyboardStyle">@style/LatinKeyboard</item>
<item name="keyboardViewStyle">@style/KeyboardView.Gingerbread</item>
+ <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.Gingerbread</item>
<item name="miniKeyboardStyle">@style/MiniKeyboard.Gingerbread</item>
<item name="miniKeyboardViewStyle">@style/MiniKeyboardView.Gingerbread</item>
<item name="miniKeyboardPanelStyle">@style/MiniKeyboardPanelStyle</item>
diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml
index 618aaed79..dbc8f32e3 100644
--- a/java/res/values/themes-ics.xml
+++ b/java/res/values/themes-ics.xml
@@ -17,8 +17,8 @@
<resources>
<style name="KeyboardTheme.IceCreamSandwich" parent="KeyboardIcons.IceCreamSandwich">
<item name="keyboardStyle">@style/Keyboard.IceCreamSandwich</item>
- <item name="latinKeyboardStyle">@style/LatinKeyboard.IceCreamSandwich</item>
<item name="keyboardViewStyle">@style/KeyboardView.IceCreamSandwich</item>
+ <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.IceCreamSandwich</item>
<item name="miniKeyboardStyle">@style/MiniKeyboard.IceCreamSandwich</item>
<item name="miniKeyboardViewStyle">@style/MiniKeyboardView.IceCreamSandwich</item>
<item name="miniKeyboardPanelStyle">@style/MiniKeyboardPanelStyle.IceCreamSandwich</item>
diff --git a/java/res/values/themes-stone-bold.xml b/java/res/values/themes-stone-bold.xml
index 532a2985e..60f130d59 100644
--- a/java/res/values/themes-stone-bold.xml
+++ b/java/res/values/themes-stone-bold.xml
@@ -17,8 +17,8 @@
<resources>
<style name="KeyboardTheme.Stone.Bold" parent="KeyboardIcons.Black">
<item name="keyboardStyle">@style/Keyboard.Stone.Bold</item>
- <item name="latinKeyboardStyle">@style/LatinKeyboard.Stone</item>
<item name="keyboardViewStyle">@style/KeyboardView.Stone.Bold</item>
+ <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.Stone.Bold</item>
<item name="miniKeyboardStyle">@style/MiniKeyboard.Stone</item>
<item name="miniKeyboardViewStyle">@style/MiniKeyboardView.Stone</item>
<item name="miniKeyboardPanelStyle">@style/MiniKeyboardPanelStyle</item>
diff --git a/java/res/values/themes-stone.xml b/java/res/values/themes-stone.xml
index cb3edc58f..9aaca3a6c 100644
--- a/java/res/values/themes-stone.xml
+++ b/java/res/values/themes-stone.xml
@@ -17,8 +17,8 @@
<resources>
<style name="KeyboardTheme.Stone" parent="KeyboardIcons.Black">
<item name="keyboardStyle">@style/Keyboard.Stone</item>
- <item name="latinKeyboardStyle">@style/LatinKeyboard.Stone</item>
<item name="keyboardViewStyle">@style/KeyboardView.Stone</item>
+ <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.Stone</item>
<item name="miniKeyboardStyle">@style/MiniKeyboard.Stone</item>
<item name="miniKeyboardViewStyle">@style/MiniKeyboardView.Stone</item>
<item name="miniKeyboardPanelStyle">@style/MiniKeyboardPanelStyle</item>
diff --git a/java/res/xml-ar/keyboard_set.xml b/java/res/xml-ar/keyboard_set.xml
new file mode 100644
index 000000000..68dc34fe3
--- /dev/null
+++ b/java/res/xml-ar/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="ar" >
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_arabic" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-be/keyboard_set.xml b/java/res/xml-be/keyboard_set.xml
new file mode 100644
index 000000000..e5c6ba35a
--- /dev/null
+++ b/java/res/xml-be/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="be">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_slavic" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-cs/keyboard_set.xml b/java/res/xml-cs/keyboard_set.xml
new file mode 100644
index 000000000..94076d3e0
--- /dev/null
+++ b/java/res/xml-cs/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="cs">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwertz" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-da/kbd_qwerty.xml b/java/res/xml-da/kbd_qwerty.xml
deleted file mode 100644
index 37a50fdfd..000000000
--- a/java/res/xml-da/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="da"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_scandinavian" />
-</Keyboard>
diff --git a/java/res/xml-da/keyboard_set.xml b/java/res/xml-da/keyboard_set.xml
new file mode 100644
index 000000000..84d126dc2
--- /dev/null
+++ b/java/res/xml-da/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="da">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_scandinavian" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-de-rZZ/keyboard_set.xml b/java/res/xml-de-rZZ/keyboard_set.xml
new file mode 100644
index 000000000..230972998
--- /dev/null
+++ b/java/res/xml-de-rZZ/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="de">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwerty" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-de/kbd_qwerty.xml b/java/res/xml-de/kbd_qwerty.xml
deleted file mode 100644
index 89e10b26d..000000000
--- a/java/res/xml-de/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="de"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_qwertz" />
-</Keyboard>
diff --git a/java/res/xml-de/keyboard_set.xml b/java/res/xml-de/keyboard_set.xml
new file mode 100644
index 000000000..c17883620
--- /dev/null
+++ b/java/res/xml-de/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="de">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwertz" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-es/keyboard_set.xml b/java/res/xml-es/keyboard_set.xml
new file mode 100644
index 000000000..77f378637
--- /dev/null
+++ b/java/res/xml-es/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="es,es_US">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_spanish" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-et/keyboard_set.xml b/java/res/xml-et/keyboard_set.xml
new file mode 100644
index 000000000..304328a70
--- /dev/null
+++ b/java/res/xml-et/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="et">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_scandinavian" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-fi/keyboard_set.xml b/java/res/xml-fi/keyboard_set.xml
new file mode 100644
index 000000000..0c3a96d36
--- /dev/null
+++ b/java/res/xml-fi/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="fi">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_scandinavian" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-fr-rCA/kbd_qwerty.xml b/java/res/xml-fr-rCA/kbd_qwerty.xml
deleted file mode 100644
index 7bdfbadf1..000000000
--- a/java/res/xml-fr-rCA/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="fr_CA"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_qwerty" />
-</Keyboard>
diff --git a/java/res/xml-fr-rCA/keyboard_set.xml b/java/res/xml-fr-rCA/keyboard_set.xml
new file mode 100644
index 000000000..b3bb4cc12
--- /dev/null
+++ b/java/res/xml-fr-rCA/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="fr_CA">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwerty" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-fr-rCH/kbd_qwerty.xml b/java/res/xml-fr-rCH/kbd_qwerty.xml
deleted file mode 100644
index 41b701d83..000000000
--- a/java/res/xml-fr-rCH/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="fr_CH"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_qwertz" />
-</Keyboard>
diff --git a/java/res/xml-fr-rCH/keyboard_set.xml b/java/res/xml-fr-rCH/keyboard_set.xml
new file mode 100644
index 000000000..d6dcf7541
--- /dev/null
+++ b/java/res/xml-fr-rCH/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="fr_CH">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwertz" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-fr/keyboard_set.xml b/java/res/xml-fr/keyboard_set.xml
new file mode 100644
index 000000000..b94a3f252
--- /dev/null
+++ b/java/res/xml-fr/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="fr">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_azerty" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-hr/kbd_qwerty.xml b/java/res/xml-hr/kbd_qwerty.xml
deleted file mode 100644
index ca92e86a7..000000000
--- a/java/res/xml-hr/kbd_qwerty.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="hr"
->
- <!-- TODO: Dedicated Croatian layout especially for tablet. -->
- <include
- latin:keyboardLayout="@xml/kbd_rows_qwertz" />
-</Keyboard>
diff --git a/java/res/xml-hr/keyboard_set.xml b/java/res/xml-hr/keyboard_set.xml
new file mode 100644
index 000000000..1d8582c0a
--- /dev/null
+++ b/java/res/xml-hr/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="hr">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwertz" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-hu/keyboard_set.xml b/java/res/xml-hu/keyboard_set.xml
new file mode 100644
index 000000000..077111923
--- /dev/null
+++ b/java/res/xml-hu/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="hu">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwertz" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-iw/keyboard_set.xml b/java/res/xml-iw/keyboard_set.xml
new file mode 100644
index 000000000..ce25aae72
--- /dev/null
+++ b/java/res/xml-iw/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="iw">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_hebrew" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-ky/keyboard_set.xml b/java/res/xml-ky/keyboard_set.xml
new file mode 100644
index 000000000..7cdd0a169
--- /dev/null
+++ b/java/res/xml-ky/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="ky">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_slavic" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-nb/kbd_qwerty.xml b/java/res/xml-nb/kbd_qwerty.xml
deleted file mode 100644
index 1f4e86e89..000000000
--- a/java/res/xml-nb/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="nb"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_scandinavian" />
-</Keyboard>
diff --git a/java/res/xml-nb/keyboard_set.xml b/java/res/xml-nb/keyboard_set.xml
new file mode 100644
index 000000000..eacda8f87
--- /dev/null
+++ b/java/res/xml-nb/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="nb">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_scandinavian" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-pl/keyboard_set.xml b/java/res/xml-pl/keyboard_set.xml
new file mode 100644
index 000000000..89bd72f1a
--- /dev/null
+++ b/java/res/xml-pl/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="pl">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwerty" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-pt/kbd_qwerty.xml b/java/res/xml-pt/kbd_qwerty.xml
deleted file mode 100644
index f5dcbc61b..000000000
--- a/java/res/xml-pt/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="pt"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_qwerty" />
-</Keyboard>
diff --git a/java/res/xml-pt/keyboard_set.xml b/java/res/xml-pt/keyboard_set.xml
new file mode 100644
index 000000000..de31e0be5
--- /dev/null
+++ b/java/res/xml-pt/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="pt">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwerty" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-ro/keyboard_set.xml b/java/res/xml-ro/keyboard_set.xml
new file mode 100644
index 000000000..725cb52d2
--- /dev/null
+++ b/java/res/xml-ro/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="ro">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwerty" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-ru/kbd_qwerty.xml b/java/res/xml-ru/kbd_qwerty.xml
deleted file mode 100644
index aee1b1bfc..000000000
--- a/java/res/xml-ru/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="ru"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_russian" />
-</Keyboard>
diff --git a/java/res/xml-ru/keyboard_set.xml b/java/res/xml-ru/keyboard_set.xml
new file mode 100644
index 000000000..0a158d9cc
--- /dev/null
+++ b/java/res/xml-ru/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="ru">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_slavic" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-sk/keyboard_set.xml b/java/res/xml-sk/keyboard_set.xml
new file mode 100644
index 000000000..9df01dda6
--- /dev/null
+++ b/java/res/xml-sk/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="sk">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwerty" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-sl/keyboard_set.xml b/java/res/xml-sl/keyboard_set.xml
new file mode 100644
index 000000000..d2ec4c02d
--- /dev/null
+++ b/java/res/xml-sl/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="sl">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwerty" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-sr/keyboard_set.xml b/java/res/xml-sr/keyboard_set.xml
new file mode 100644
index 000000000..e72a0f23f
--- /dev/null
+++ b/java/res/xml-sr/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="sr">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_serbian" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-sv/kbd_qwerty.xml b/java/res/xml-sv/kbd_qwerty.xml
deleted file mode 100644
index e29d9abce..000000000
--- a/java/res/xml-sv/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="sv"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_scandinavian" />
-</Keyboard>
diff --git a/java/res/xml-sv/keyboard_set.xml b/java/res/xml-sv/keyboard_set.xml
new file mode 100644
index 000000000..df06aef68
--- /dev/null
+++ b/java/res/xml-sv/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="sv">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_scandinavian" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-sw600dp-land/kbd_number.xml b/java/res/xml-sw600dp-land/kbd_number.xml
new file mode 100644
index 000000000..7e3188b0f
--- /dev/null
+++ b/java/res/xml-sw600dp-land/kbd_number.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="15.00%p"
+>
+ <include
+ latin:keyboardLayout="@xml/kbd_rows_number" />
+</Keyboard>
diff --git a/java/res/xml-de-rZZ/kbd_qwerty.xml b/java/res/xml-sw600dp-land/kbd_phone.xml
index d5fd8ef7a..28df7efa3 100644
--- a/java/res/xml-de-rZZ/kbd_qwerty.xml
+++ b/java/res/xml-sw600dp-land/kbd_phone.xml
@@ -20,8 +20,9 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="de"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="15.00%p"
>
<include
- latin:keyboardLayout="@xml/kbd_rows_qwerty" />
+ latin:keyboardLayout="@xml/kbd_rows_phone" />
</Keyboard>
diff --git a/java/res/xml-sw600dp-land/kbd_phone_shift.xml b/java/res/xml-sw600dp-land/kbd_phone_shift.xml
new file mode 100644
index 000000000..daf1d18c5
--- /dev/null
+++ b/java/res/xml-sw600dp-land/kbd_phone_shift.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="15.00%p"
+>
+ <include
+ latin:keyboardLayout="@xml/kbd_rows_phone_shift" />
+</Keyboard>
diff --git a/java/res/xml-sw600dp/kbd_key_styles.xml b/java/res/xml-sw600dp/kbd_key_styles.xml
index 25fa8b265..ab90c9894 100644
--- a/java/res/xml-sw600dp/kbd_key_styles.xml
+++ b/java/res/xml-sw600dp/kbd_key_styles.xml
@@ -33,7 +33,7 @@
<default>
<key-style
latin:styleName="f2PopupStyle"
- latin:keyLabelOption="hasPopupHint"
+ latin:keyLabelFlags="hasPopupHint"
latin:moreKeys="\@icon/3|\@integer/key_settings"
latin:backgroundType="functional" />
</default>
@@ -43,41 +43,47 @@
latin:styleName="shiftKeyStyle"
latin:code="@integer/key_shift"
latin:keyIcon="iconShiftKey"
- latin:keyIconShifted="iconShiftedShiftKey"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="sticky" />
<key-style
latin:styleName="deleteKeyStyle"
latin:code="@integer/key_delete"
latin:keyIcon="iconDeleteKey"
- latin:backgroundType="functional"
- latin:isRepeatable="true" />
+ latin:keyActionFlags="isRepeatable|noKeyPreview"
+ latin:backgroundType="functional" />
<key-style
latin:styleName="returnKeyStyle"
latin:code="@integer/key_return"
latin:keyIcon="iconReturnKey"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="spaceKeyStyle"
- latin:code="@integer/key_space" />
+ latin:code="@integer/key_space"
+ latin:keyActionFlags="noKeyPreview" />
<key-style
latin:styleName="nonSpecialBackgroundSpaceKeyStyle"
- latin:code="@integer/key_space" />
+ latin:code="@integer/key_space"
+ latin:keyActionFlags="noKeyPreview" />
<key-style
latin:styleName="smileyKeyStyle"
latin:keyLabel=":-)"
latin:keyOutputText=":-) "
- latin:keyLabelOption="hasPopupHint"
+ latin:keyLabelFlags="hasPopupHint"
latin:moreKeys="@string/more_keys_for_smiley"
latin:maxMoreKeysColumn="5" />
<key-style
latin:styleName="shortcutKeyStyle"
latin:code="@integer/key_shortcut"
latin:keyIcon="iconShortcutKey"
+ latin:keyIconDisabled="iconDisabledShortcutKey"
+ latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
latin:parentStyle="f2PopupStyle" />
<key-style
latin:styleName="settingsKeyStyle"
latin:code="@integer/key_settings"
latin:keyIcon="iconSettingsKey"
+ latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
latin:backgroundType="functional" />
<key-style
latin:styleName="tabKeyStyle"
@@ -89,26 +95,30 @@
latin:styleName="toSymbolKeyStyle"
latin:code="@integer/key_switch_alpha_symbol"
latin:keyLabel="@string/label_to_symbol_key"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="toAlphaKeyStyle"
latin:code="@integer/key_switch_alpha_symbol"
latin:keyLabel="@string/label_to_alpha_key"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="toMoreSymbolKeyStyle"
latin:code="@integer/key_shift"
latin:keyLabel="@string/label_to_more_symbol_for_tablet_key"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="backFromMoreSymbolKeyStyle"
latin:code="@integer/key_shift"
latin:keyLabel="@string/label_to_symbol_key"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="comKeyStyle"
latin:keyLabel="@string/keylabel_for_popular_domain"
- latin:keyLabelOption="fontNormal|hasPopupHint"
+ latin:keyLabelFlags="fontNormal|hasPopupHint"
latin:keyOutputText="@string/keylabel_for_popular_domain"
latin:moreKeys="@string/more_keys_for_popular_domain" />
</merge>
diff --git a/java/res/xml-sw600dp/kbd_number.xml b/java/res/xml-sw600dp/kbd_number.xml
index 46114dedf..ad588d7ed 100644
--- a/java/res/xml-sw600dp/kbd_number.xml
+++ b/java/res/xml-sw600dp/kbd_number.xml
@@ -20,190 +20,8 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyWidth="16.75%p"
+ latin:keyWidth="15.00%p"
>
<include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <switch>
- <case
- latin:passwordInput="true"
- >
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="24.875%p" />
- <Key
- latin:keyStyle="num1KeyStyle" />
- <Key
- latin:keyStyle="num2KeyStyle" />
- <Key
- latin:keyStyle="num3KeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillRight" />
- </Row>
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="24.875%p" />
- <Key
- latin:keyStyle="num4KeyStyle" />
- <Key
- latin:keyStyle="num5KeyStyle" />
- <Key
- latin:keyStyle="num6KeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillRight" />
- </Row>
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="24.875%p" />
- <Key
- latin:keyStyle="num7KeyStyle" />
- <Key
- latin:keyStyle="num8KeyStyle" />
- <Key
- latin:keyStyle="num9KeyStyle" />
- <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
- <Spacer
- latin:keyWidth="0%p" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyWidth="11.00%p" />
- <Spacer
- latin:keyXPos="24.875%p" />
- <Key
- latin:keyStyle="num0KeyStyle" />
- <Spacer
- latin:keyXPos="-11.00%p"
- latin:keyWidth="0%p" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_f2" />
- </Row>
- </case>
- <!-- latin:passwordInput="false" -->
- <default>
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="11.00%p" />
- <Key
- latin:keyLabel="-"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="+"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="."
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="1"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="38.75%p" />
- <Key
- latin:keyLabel="2"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="3"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillBoth" />
- </Row>
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="11.00%p" />
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="/"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel=","
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="4"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="38.75%p" />
- <Key
- latin:keyLabel="5"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="6"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillBoth" />
- </Row>
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="11.00%p" />
- <Key
- latin:keyLabel="("
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel=")"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="="
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="7"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="38.75%p" />
- <Key
- latin:keyLabel="8"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="9"
- latin:keyStyle="numKeyStyle" />
- <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
- <Spacer
- latin:keyWidth="0%p" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyWidth="11.00%p" />
- <Key
- latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
- latin:keyWidth="27.75%p" />
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyXPos="38.75%p" />
- <Key
- latin:keyLabel="0"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="#"
- latin:keyStyle="numKeyStyle" />
- <Spacer
- latin:keyXPos="-11.00%p"
- latin:keyWidth="0%p" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_f2" />
- </Row>
- </default>
- </switch>
+ latin:keyboardLayout="@xml/kbd_rows_number" />
</Keyboard>
diff --git a/java/res/xml-sw600dp/kbd_phone.xml b/java/res/xml-sw600dp/kbd_phone.xml
index 303f8145b..ce769b8f7 100644
--- a/java/res/xml-sw600dp/kbd_phone.xml
+++ b/java/res/xml-sw600dp/kbd_phone.xml
@@ -20,104 +20,8 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyWidth="16.75%p"
+ latin:keyWidth="15.00%p"
>
<include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="15.625%p" />
- <Key
- latin:keyLabel="-"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="+"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyStyle="num1KeyStyle"
- latin:keyXPos="38.867%p" />
- <Key
- latin:keyStyle="num2KeyStyle" />
- <Key
- latin:keyStyle="num3KeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillBoth" />
- </Row>
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="15.625%p" />
- <Key
- latin:keyLabel=","
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="."
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyStyle="num4KeyStyle"
- latin:keyXPos="38.867%p" />
- <Key
- latin:keyStyle="num5KeyStyle" />
- <Key
- latin:keyStyle="num6KeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillBoth" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="toMoreSymbolKeyStyle"
- latin:keyWidth="11.0%p" />
- <Key
- latin:keyLabel="("
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="15.625%p"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel=")"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyStyle="num7KeyStyle"
- latin:keyXPos="38.867%p" />
- <Key
- latin:keyStyle="num8KeyStyle" />
- <Key
- latin:keyStyle="num9KeyStyle" />
- <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
- <Spacer
- latin:keyWidth="0%p" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyWidth="11.00%p" />
- <Key
- latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
- latin:keyXPos="15.625%p"
- latin:keyWidth="18.50%p" />
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyXPos="38.867%p" />
- <Key
- latin:keyStyle="num0KeyStyle" />
- <Key
- latin:keyLabel="#"
- latin:keyStyle="numKeyStyle" />
- <Spacer
- latin:keyXPos="-11.00%p"
- latin:keyWidth="0%p" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_f2" />
- </Row>
+ latin:keyboardLayout="@xml/kbd_rows_phone" />
</Keyboard>
diff --git a/java/res/xml-sw600dp/kbd_phone_shift.xml b/java/res/xml-sw600dp/kbd_phone_shift.xml
index 4c4f8ad12..3753deb8c 100644
--- a/java/res/xml-sw600dp/kbd_phone_shift.xml
+++ b/java/res/xml-sw600dp/kbd_phone_shift.xml
@@ -20,116 +20,8 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyWidth="16.75%p"
+ latin:keyWidth="15.00%p"
>
<include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="11.00%p" />
- <Key
- latin:keyLabel="-"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="+"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:code="44"
- latin:keyLabel="@string/label_pause_key"
- latin:keyLabelOption="followKeyHintLabelRatio|autoXScale"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyStyle="num1KeyStyle"
- latin:keyXPos="38.867%p" />
- <Key
- latin:keyStyle="num2KeyStyle" />
- <Key
- latin:keyStyle="num3KeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillBoth" />
- </Row>
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="11.00%p" />
- <Key
- latin:keyLabel=","
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="."
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:code="59"
- latin:keyLabel="@string/label_wait_key"
- latin:keyLabelOption="followKeyHintLabelRatio|autoXScale"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyStyle="num4KeyStyle"
- latin:keyXPos="38.867%p" />
- <Key
- latin:keyStyle="num5KeyStyle" />
- <Key
- latin:keyStyle="num6KeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillBoth" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="backFromMoreSymbolKeyStyle"
- latin:keyWidth="11.00%p" />
- <Key
- latin:keyLabel="("
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel=")"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="N"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyStyle="num7KeyStyle"
- latin:keyXPos="38.867%p" />
- <Key
- latin:keyStyle="num8KeyStyle" />
- <Key
- latin:keyStyle="num9KeyStyle" />
- <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
- <Spacer
- latin:keyWidth="0%p" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyWidth="11.00%p" />
- <Key
- latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
- latin:keyWidth="27.75%p" />
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyXPos="38.867%p" />
- <Key
- latin:keyStyle="num0KeyStyle" />
- <Key
- latin:keyLabel="#"
- latin:keyStyle="numKeyStyle" />
- <Spacer
- latin:keyXPos="-11.00%p"
- latin:keyWidth="0%p" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_f2" />
- </Row>
+ latin:keyboardLayout="@xml/kbd_rows_phone_shift" />
</Keyboard>
diff --git a/java/res/xml-sw600dp/kbd_qwerty_row4.xml b/java/res/xml-sw600dp/kbd_qwerty_row4.xml
index ef0292279..54ca22b67 100644
--- a/java/res/xml-sw600dp/kbd_qwerty_row4.xml
+++ b/java/res/xml-sw600dp/kbd_qwerty_row4.xml
@@ -45,7 +45,7 @@
<default>
<Key
latin:keyLabel="/"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="\@"
latin:moreKeys="\@" />
</default>
diff --git a/java/res/xml-sw600dp/kbd_row3_comma_period.xml b/java/res/xml-sw600dp/kbd_row3_comma_period.xml
index b84443078..6a95ca1a3 100644
--- a/java/res/xml-sw600dp/kbd_row3_comma_period.xml
+++ b/java/res/xml-sw600dp/kbd_row3_comma_period.xml
@@ -33,12 +33,12 @@
<default>
<Key
latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="!"
latin:moreKeys="!" />
<Key
latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="\?"
latin:moreKeys="\?" />
</default>
diff --git a/java/res/xml-sw600dp/kbd_row3_smiley.xml b/java/res/xml-sw600dp/kbd_row3_smiley.xml
index f9b647cdf..c94ec0cee 100644
--- a/java/res/xml-sw600dp/kbd_row3_smiley.xml
+++ b/java/res/xml-sw600dp/kbd_row3_smiley.xml
@@ -35,7 +35,7 @@
>
<Key
latin:keyLabel="-"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="_"
latin:moreKeys="_"
latin:keyXPos="-8.9%p"
@@ -46,7 +46,7 @@
>
<Key
latin:keyLabel=":"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="+"
latin:moreKeys="+"
latin:keyXPos="-8.9%p"
diff --git a/java/res/xml-sw600dp/kbd_row4_apostrophe_dash.xml b/java/res/xml-sw600dp/kbd_row4_apostrophe_dash.xml
index 9536e81da..4eb82d24a 100644
--- a/java/res/xml-sw600dp/kbd_row4_apostrophe_dash.xml
+++ b/java/res/xml-sw600dp/kbd_row4_apostrophe_dash.xml
@@ -33,14 +33,14 @@
>
<Key
latin:keyLabel="/"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel=":"
latin:moreKeys=":" />
</case>
<default>
<Key
latin:keyLabel="@string/keylabel_for_apostrophe"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="@string/keyhintlabel_for_apostrophe"
latin:moreKeys="@string/more_keys_for_apostrophe" />
</default>
@@ -55,7 +55,7 @@
<default>
<Key
latin:keyLabel="@string/keylabel_for_dash"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="@string/keyhintlabel_for_dash"
latin:moreKeys="@string/more_keys_for_dash" />
</default>
diff --git a/java/res/xml-sw600dp/kbd_rows_arabic.xml b/java/res/xml-sw600dp/kbd_rows_arabic.xml
index c2d3cd4cc..55c02f211 100644
--- a/java/res/xml-sw600dp/kbd_rows_arabic.xml
+++ b/java/res/xml-sw600dp/kbd_rows_arabic.xml
@@ -158,7 +158,7 @@
>
<Key
latin:keyLabel="-"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="_"
latin:moreKeys="_" />
</case>
@@ -167,7 +167,7 @@
>
<Key
latin:keyLabel=":"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="+"
latin:moreKeys="+" />
</case>
diff --git a/java/res/xml-sw600dp/kbd_rows_azerty.xml b/java/res/xml-sw600dp/kbd_rows_azerty.xml
index 8ae74557c..46967899b 100644
--- a/java/res/xml-sw600dp/kbd_rows_azerty.xml
+++ b/java/res/xml-sw600dp/kbd_rows_azerty.xml
@@ -132,12 +132,12 @@
<default>
<Key
latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="!"
latin:moreKeys="!" />
<Key
latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="\?"
latin:moreKeys="\?" />
</default>
diff --git a/java/res/xml-sw600dp/kbd_rows_hebrew.xml b/java/res/xml-sw600dp/kbd_rows_hebrew.xml
index a8adbd34c..4166745b7 100644
--- a/java/res/xml-sw600dp/kbd_rows_hebrew.xml
+++ b/java/res/xml-sw600dp/kbd_rows_hebrew.xml
@@ -94,7 +94,7 @@
>
<Key
latin:keyLabel="-"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="_"
latin:moreKeys="_"
latin:keyWidth="10.0%p" />
@@ -104,7 +104,7 @@
>
<Key
latin:keyLabel=":"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="+"
latin:moreKeys="+"
latin:keyWidth="10.0%p" />
diff --git a/java/res/xml-sw600dp/kbd_rows_number.xml b/java/res/xml-sw600dp/kbd_rows_number.xml
new file mode 100644
index 000000000..cfb24212b
--- /dev/null
+++ b/java/res/xml-sw600dp/kbd_rows_number.xml
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/kbd_key_styles" />
+ <include
+ latin:keyboardLayout="@xml/kbd_numkey_styles" />
+ <switch>
+ <case
+ latin:passwordInput="true"
+ >
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="27.50%p" />
+ <Key
+ latin:keyStyle="num1KeyStyle" />
+ <Key
+ latin:keyStyle="num2KeyStyle" />
+ <Key
+ latin:keyStyle="num3KeyStyle" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyXPos="-11.00%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="27.50%p" />
+ <Key
+ latin:keyStyle="num4KeyStyle" />
+ <Key
+ latin:keyStyle="num5KeyStyle" />
+ <Key
+ latin:keyStyle="num6KeyStyle" />
+ <Key
+ latin:keyStyle="returnKeyStyle"
+ latin:keyXPos="-11.00%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="27.50%p" />
+ <Key
+ latin:keyStyle="num7KeyStyle" />
+ <Key
+ latin:keyStyle="num8KeyStyle" />
+ <Key
+ latin:keyStyle="num9KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="0%p" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyWidth="11.00%p" />
+ <Key
+ latin:keyStyle="num0KeyStyle"
+ latin:keyXPos="42.50%p"/>
+ <Spacer
+ latin:keyXPos="-11.00%p"
+ latin:keyWidth="0%p" />
+ <include
+ latin:keyboardLayout="@xml/kbd_qwerty_f2" />
+ </Row>
+ </case>
+ <!-- latin:passwordInput="false" -->
+ <default>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="12.75%p" />
+ <Key
+ latin:keyLabel="-"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel="+"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel="."
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel="1"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="42.25%p" />
+ <Key
+ latin:keyLabel="2"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="3"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyXPos="-11.00%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="12.75%p" />
+ <Key
+ latin:keyStyle="numStarKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel="/"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel=","
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel="4"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="42.25%p" />
+ <Key
+ latin:keyLabel="5"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="6"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyStyle="returnKeyStyle"
+ latin:keyXPos="-11.00%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="12.75%p" />
+ <Key
+ latin:keyLabel="("
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel=")"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel="="
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel="7"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="42.25%p" />
+ <Key
+ latin:keyLabel="8"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="9"
+ latin:keyStyle="numKeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="0%p" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="numTabKeyStyle"
+ latin:keyWidth="11.00%p" />
+ <Key
+ latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
+ latin:keyWidth="27.75%p"
+ latin:keyXPos="12.75%p" />
+ <Key
+ latin:keyStyle="numStarKeyStyle"
+ latin:keyXPos="42.25%p" />
+ <Key
+ latin:keyLabel="0"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="#"
+ latin:keyStyle="numKeyStyle" />
+ <Spacer
+ latin:keyXPos="-11.00%p"
+ latin:keyWidth="0%p" />
+ <include
+ latin:keyboardLayout="@xml/kbd_qwerty_f2" />
+ </Row>
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/kbd_rows_phone.xml b/java/res/xml-sw600dp/kbd_rows_phone.xml
new file mode 100644
index 000000000..69d058fd8
--- /dev/null
+++ b/java/res/xml-sw600dp/kbd_rows_phone.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/kbd_key_styles" />
+ <include
+ latin:keyboardLayout="@xml/kbd_numkey_styles" />
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="17.375%p" />
+ <Key
+ latin:keyLabel="-"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel="+"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyStyle="num1KeyStyle"
+ latin:keyXPos="42.25%p" />
+ <Key
+ latin:keyStyle="num2KeyStyle" />
+ <Key
+ latin:keyStyle="num3KeyStyle" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyXPos="-11.00%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="17.375%p" />
+ <Key
+ latin:keyLabel=","
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel="."
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyStyle="num4KeyStyle"
+ latin:keyXPos="42.25%p" />
+ <Key
+ latin:keyStyle="num5KeyStyle" />
+ <Key
+ latin:keyStyle="num6KeyStyle" />
+ <Key
+ latin:keyStyle="returnKeyStyle"
+ latin:keyXPos="-11.00%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="toMoreSymbolKeyStyle"
+ latin:keyWidth="11.0%p" />
+ <Key
+ latin:keyLabel="("
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="17.375%p"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel=")"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyStyle="num7KeyStyle"
+ latin:keyXPos="42.25%p" />
+ <Key
+ latin:keyStyle="num8KeyStyle" />
+ <Key
+ latin:keyStyle="num9KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="0%p" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="numTabKeyStyle"
+ latin:keyWidth="11.00%p" />
+ <Key
+ latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
+ latin:keyWidth="18.50%p"
+ latin:keyXPos="17.375%p" />
+ <Key
+ latin:keyStyle="numStarKeyStyle"
+ latin:keyXPos="42.25%p" />
+ <Key
+ latin:keyStyle="num0KeyStyle" />
+ <Key
+ latin:keyLabel="#"
+ latin:keyStyle="numKeyStyle" />
+ <Spacer
+ latin:keyXPos="-11.00%p"
+ latin:keyWidth="0%p" />
+ <include
+ latin:keyboardLayout="@xml/kbd_qwerty_f2" />
+ </Row>
+</merge>
diff --git a/java/res/xml-sw600dp/kbd_rows_phone_shift.xml b/java/res/xml-sw600dp/kbd_rows_phone_shift.xml
new file mode 100644
index 000000000..04db6780f
--- /dev/null
+++ b/java/res/xml-sw600dp/kbd_rows_phone_shift.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/kbd_key_styles" />
+ <include
+ latin:keyboardLayout="@xml/kbd_numkey_styles" />
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="12.75%p" />
+ <Key
+ latin:keyLabel="-"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel="+"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyStyle="numPauseKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyStyle="num1KeyStyle"
+ latin:keyXPos="42.25%p" />
+ <Key
+ latin:keyStyle="num2KeyStyle" />
+ <Key
+ latin:keyStyle="num3KeyStyle" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyXPos="-11.00%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="12.75%p" />
+ <Key
+ latin:keyLabel=","
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel="."
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyStyle="numWaitKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyStyle="num4KeyStyle"
+ latin:keyXPos="42.25%p" />
+ <Key
+ latin:keyStyle="num5KeyStyle" />
+ <Key
+ latin:keyStyle="num6KeyStyle" />
+ <Key
+ latin:keyStyle="returnKeyStyle"
+ latin:keyXPos="-11.00%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="backFromMoreSymbolKeyStyle"
+ latin:keyWidth="11.00%p" />
+ <Key
+ latin:keyLabel="("
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p"
+ latin:keyXPos="12.75%p" />
+ <Key
+ latin:keyLabel=")"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyLabel="N"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="9.25%p" />
+ <Key
+ latin:keyStyle="num7KeyStyle"
+ latin:keyXPos="42.25%p" />
+ <Key
+ latin:keyStyle="num8KeyStyle" />
+ <Key
+ latin:keyStyle="num9KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="0%p" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="numTabKeyStyle"
+ latin:keyWidth="11.00%p" />
+ <Key
+ latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
+ latin:keyWidth="27.75%p"
+ latin:keyXPos="12.75%p" />
+ <Key
+ latin:keyStyle="numStarKeyStyle"
+ latin:keyXPos="42.25%p" />
+ <Key
+ latin:keyStyle="num0KeyStyle" />
+ <Key
+ latin:keyLabel="#"
+ latin:keyStyle="numKeyStyle" />
+ <Spacer
+ latin:keyXPos="-11.00%p"
+ latin:keyWidth="0%p" />
+ <include
+ latin:keyboardLayout="@xml/kbd_qwerty_f2" />
+ </Row>
+</merge>
diff --git a/java/res/xml-sw600dp/kbd_rows_qwertz.xml b/java/res/xml-sw600dp/kbd_rows_qwertz.xml
index 98667e09c..d7d13d5d1 100644
--- a/java/res/xml-sw600dp/kbd_rows_qwertz.xml
+++ b/java/res/xml-sw600dp/kbd_rows_qwertz.xml
@@ -99,12 +99,12 @@
<default>
<Key
latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="!"
latin:moreKeys="!" />
<Key
latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="\?"
latin:moreKeys="\?" />
</default>
diff --git a/java/res/xml-sw600dp/kbd_rows_scandinavian.xml b/java/res/xml-sw600dp/kbd_rows_scandinavian.xml
index 19fb5212b..6d14d89c2 100644
--- a/java/res/xml-sw600dp/kbd_rows_scandinavian.xml
+++ b/java/res/xml-sw600dp/kbd_rows_scandinavian.xml
@@ -57,7 +57,7 @@
latin:keyLabel="p"
latin:moreKeys="@string/more_keys_for_p" />
<Key
- latin:keyLabel="å" />
+ latin:keyLabel="@string/keylabel_for_scandinavia_row1_11" />
<Key
latin:keyStyle="deleteKeyStyle"
latin:keyXPos="-10.0%p"
diff --git a/java/res/xml-sw600dp/kbd_rows_russian.xml b/java/res/xml-sw600dp/kbd_rows_slavic.xml
index cc9ad3aa7..0a162058d 100644
--- a/java/res/xml-sw600dp/kbd_rows_russian.xml
+++ b/java/res/xml-sw600dp/kbd_rows_slavic.xml
@@ -31,20 +31,22 @@
<Key
latin:keyLabel="ц" />
<Key
- latin:keyLabel="у" />
+ latin:keyLabel="у"
+ latin:moreKeys="@string/more_keys_for_slavic_u" />
<Key
latin:keyLabel="к" />
<Key
latin:keyLabel="е"
- latin:moreKeys="@string/more_keys_for_cyrillic_e" />
+ latin:moreKeys="@string/more_keys_for_slavic_ye" />
<Key
- latin:keyLabel="н" />
+ latin:keyLabel="н"
+ latin:moreKeys="@string/more_keys_for_slavic_en" />
<Key
latin:keyLabel="г" />
<Key
latin:keyLabel="ш" />
<Key
- latin:keyLabel="щ" />
+ latin:keyLabel="@string/keylabel_for_slavic_shcha" />
<Key
latin:keyLabel="з" />
<Key
@@ -63,7 +65,8 @@
latin:keyLabel="ф"
latin:keyXPos="2.25%p" />
<Key
- latin:keyLabel="ы" />
+ latin:keyLabel="@string/keylabel_for_slavic_yery"
+ latin:moreKeys="@string/more_keys_for_slavic_yery" />
<Key
latin:keyLabel="в" />
<Key
@@ -73,7 +76,8 @@
<Key
latin:keyLabel="р" />
<Key
- latin:keyLabel="о" />
+ latin:keyLabel="о"
+ latin:moreKeys="@string/more_keys_for_slavic_o" />
<Key
latin:keyLabel="л" />
<Key
@@ -101,7 +105,7 @@
<Key
latin:keyLabel="м" />
<Key
- latin:keyLabel="и" />
+ latin:keyLabel="@string/keylabel_for_slavic_i" />
<Key
latin:keyLabel="т" />
<Key
@@ -122,12 +126,12 @@
<default>
<Key
latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="!"
latin:moreKeys="!" />
<Key
latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="\?"
latin:moreKeys="\?" />
</default>
diff --git a/java/res/xml-sw768dp-land/kbd_number.xml b/java/res/xml-sw768dp-land/kbd_number.xml
new file mode 100644
index 000000000..3106dc34e
--- /dev/null
+++ b/java/res/xml-sw768dp-land/kbd_number.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="13.250%p"
+>
+ <include
+ latin:keyboardLayout="@xml/kbd_rows_number" />
+</Keyboard>
diff --git a/java/res/xml-sw768dp-land/kbd_phone.xml b/java/res/xml-sw768dp-land/kbd_phone.xml
new file mode 100644
index 000000000..7c7af5739
--- /dev/null
+++ b/java/res/xml-sw768dp-land/kbd_phone.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="13.250%p"
+>
+ <include
+ latin:keyboardLayout="@xml/kbd_rows_phone" />
+</Keyboard>
diff --git a/java/res/xml-sw768dp-land/kbd_phone_shift.xml b/java/res/xml-sw768dp-land/kbd_phone_shift.xml
new file mode 100644
index 000000000..04b018cfe
--- /dev/null
+++ b/java/res/xml-sw768dp-land/kbd_phone_shift.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="13.250%p"
+>
+ <include
+ latin:keyboardLayout="@xml/kbd_rows_phone_shift" />
+</Keyboard>
diff --git a/java/res/xml-sw768dp/kbd_key_styles.xml b/java/res/xml-sw768dp/kbd_key_styles.xml
index f16f5b6af..72a1a4c77 100644
--- a/java/res/xml-sw768dp/kbd_key_styles.xml
+++ b/java/res/xml-sw768dp/kbd_key_styles.xml
@@ -25,76 +25,86 @@
latin:styleName="shiftKeyStyle"
latin:code="@integer/key_shift"
latin:keyIcon="iconShiftKey"
- latin:keyIconShifted="iconShiftedShiftKey"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="sticky" />
<key-style
latin:styleName="deleteKeyStyle"
latin:code="@integer/key_delete"
latin:keyIcon="iconDeleteKey"
- latin:backgroundType="functional"
- latin:isRepeatable="true" />
+ latin:keyActionFlags="isRepeatable|noKeyPreview"
+ latin:backgroundType="functional" />
<key-style
latin:styleName="returnKeyStyle"
latin:code="@integer/key_return"
latin:keyIcon="iconReturnKey"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="spaceKeyStyle"
- latin:code="@integer/key_space" />
+ latin:code="@integer/key_space"
+ latin:keyActionFlags="noKeyPreview" />
<key-style
latin:styleName="nonSpecialBackgroundSpaceKeyStyle"
- latin:code="@integer/key_space" />
+ latin:code="@integer/key_space"
+ latin:keyActionFlags="noKeyPreview" />
<key-style
latin:styleName="smileyKeyStyle"
latin:keyLabel=":-)"
latin:keyOutputText=":-) "
- latin:keyLabelOption="hasPopupHint"
+ latin:keyLabelFlags="hasPopupHint"
latin:moreKeys="@string/more_keys_for_smiley"
latin:maxMoreKeysColumn="5" />
<key-style
- latin:styleName="settingsKeyStyle"
- latin:code="@integer/key_settings"
- latin:keyIcon="iconSettingsKey"
- latin:backgroundType="functional" />
- <key-style
latin:styleName="shortcutKeyStyle"
latin:code="@integer/key_shortcut"
latin:keyIcon="iconShortcutKey"
+ latin:keyIconDisabled="iconDisabledShortcutKey"
+ latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="settingsKeyStyle"
+ latin:code="@integer/key_settings"
+ latin:keyIcon="iconSettingsKey"
+ latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
latin:backgroundType="functional" />
<key-style
latin:styleName="tabKeyStyle"
latin:code="@integer/key_tab"
latin:keyLabel="@string/label_tab_key"
- latin:keyLabelOption="fontNormal"
+ latin:keyLabelFlags="fontNormal"
latin:backgroundType="functional" />
<key-style
latin:styleName="toSymbolKeyStyle"
latin:code="@integer/key_switch_alpha_symbol"
latin:keyLabel="@string/label_to_symbol_key"
- latin:keyLabelOption="fontNormal"
+ latin:keyLabelFlags="fontNormal"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="toAlphaKeyStyle"
latin:code="@integer/key_switch_alpha_symbol"
latin:keyLabel="@string/label_to_alpha_key"
- latin:keyLabelOption="fontNormal"
+ latin:keyLabelFlags="fontNormal"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="toMoreSymbolKeyStyle"
latin:code="@integer/key_shift"
latin:keyLabel="@string/label_to_more_symbol_for_tablet_key"
- latin:keyLabelOption="fontNormal"
+ latin:keyLabelFlags="fontNormal"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="backFromMoreSymbolKeyStyle"
latin:code="@integer/key_shift"
latin:keyLabel="@string/label_to_symbol_key"
- latin:keyLabelOption="fontNormal"
+ latin:keyLabelFlags="fontNormal"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="comKeyStyle"
latin:keyLabel="@string/keylabel_for_popular_domain"
- latin:keyLabelOption="fontNormal|hasPopupHint"
+ latin:keyLabelFlags="fontNormal|hasPopupHint"
latin:keyOutputText="@string/keylabel_for_popular_domain"
latin:moreKeys="@string/more_keys_for_popular_domain" />
</merge>
diff --git a/java/res/xml-sw768dp/kbd_number.xml b/java/res/xml-sw768dp/kbd_number.xml
index 369e91a77..74ce854cf 100644
--- a/java/res/xml-sw768dp/kbd_number.xml
+++ b/java/res/xml-sw768dp/kbd_number.xml
@@ -23,206 +23,5 @@
latin:keyWidth="13.250%p"
>
<include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <switch>
- <case
- latin:passwordInput="true"
- >
- <Row>
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="11.172%p" />
- <Key
- latin:keyStyle="num1KeyStyle"
- latin:keyXPos="32.076%p" />
- <Key
- latin:keyStyle="num2KeyStyle" />
- <Key
- latin:keyStyle="num3KeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight" />
- </Row>
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="32.076%p" />
- <Key
- latin:keyStyle="num4KeyStyle" />
- <Key
- latin:keyStyle="num5KeyStyle" />
- <Key
- latin:keyStyle="num6KeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight" />
- </Row>
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="32.076%p" />
- <Key
- latin:keyStyle="num7KeyStyle" />
- <Key
- latin:keyStyle="num8KeyStyle" />
- <Key
- latin:keyStyle="num9KeyStyle" />
- <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
- <Spacer
- latin:keyWidth="0%p" />
- </Row>
- <Row>
- <Spacer
- latin:keyXPos="32.076%p" />
- <Key
- latin:keyStyle="num0KeyStyle" />
- <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
- <Spacer
- latin:keyWidth="0%p" />
- </Row>
- </case>
- <!-- latin:passwordInput="false" -->
- <default>
- <Row>
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="11.172%p" />
- <Key
- latin:keyLabel="-"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="13.829%p"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="+"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="."
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="1"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyLabel="2"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="3"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight" />
- </Row>
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="13.829%p" />
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="/"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel=","
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="4"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyLabel="5"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="6"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight" />
- </Row>
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="13.829%p" />
- <Key
- latin:keyLabel="("
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel=")"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="="
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="7"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyLabel="8"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="9"
- latin:keyStyle="numKeyStyle" />
- <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
- <Spacer
- latin:keyWidth="0%p" />
- </Row>
- <Row>
- <switch>
- <case latin:hasSettingsKey="true">
- <Key
- latin:keyStyle="settingsKeyStyle"
- latin:keyWidth="8.047%p" />
- </case>
- <default>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="8.047%p" />
- </default>
- </switch>
- <Key
- latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
- latin:keyXPos="13.829%p"
- latin:keyWidth="24.140%p" />
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyLabel="0"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="#"
- latin:keyStyle="numKeyStyle" />
- <switch>
- <case
- latin:shortcutKeyEnabled="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle"
- latin:keyXPos="-8.047%p"
- latin:keyWidth="fillRight" />
- </case>
- <default>
- <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
- <Spacer
- latin:keyWidth="0%p" />
- </default>
- </switch>
- </Row>
- </default>
- </switch>
+ latin:keyboardLayout="@xml/kbd_rows_number" />
</Keyboard>
diff --git a/java/res/xml-sw768dp/kbd_phone.xml b/java/res/xml-sw768dp/kbd_phone.xml
index e55b1841a..0a9b8b53a 100644
--- a/java/res/xml-sw768dp/kbd_phone.xml
+++ b/java/res/xml-sw768dp/kbd_phone.xml
@@ -23,122 +23,5 @@
latin:keyWidth="13.250%p"
>
<include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <Row>
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="11.172%p" />
- <Key
- latin:keyLabel="-"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="20.400%p"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="+"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyStyle="num1KeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyStyle="num2KeyStyle" />
- <Key
- latin:keyStyle="num3KeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="toMoreSymbolKeyStyle"
- latin:keyWidth="11.172%p" />
- <Key
- latin:keyLabel=","
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="20.400%p"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="."
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyStyle="num4KeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyStyle="num5KeyStyle" />
- <Key
- latin:keyStyle="num6KeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight" />
- </Row>
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="20.400%p" />
- <Key
- latin:keyLabel="("
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel=")"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyStyle="num7KeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyStyle="num8KeyStyle" />
- <Key
- latin:keyStyle="num9KeyStyle" />
- <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
- <Spacer
- latin:keyWidth="0%p" />
- </Row>
- <Row>
- <switch>
- <case latin:hasSettingsKey="true">
- <Key
- latin:keyStyle="settingsKeyStyle"
- latin:keyWidth="8.047%p" />
- </case>
- <default>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="8.047%p" />
- </default>
- </switch>
- <Key
- latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
- latin:keyXPos="20.400%p"
- latin:keyWidth="16.084%p" />
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyStyle="num0KeyStyle" />
- <Key
- latin:keyLabel="#"
- latin:keyStyle="numKeyStyle" />
- <switch>
- <case
- latin:shortcutKeyEnabled="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle"
- latin:keyXPos="-8.047%p"
- latin:keyWidth="fillRight" />
- </case>
- <default>
- <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
- <Spacer
- latin:keyWidth="0%p" />
- </default>
- </switch>
- </Row>
+ latin:keyboardLayout="@xml/kbd_rows_phone" />
</Keyboard>
diff --git a/java/res/xml-sw768dp/kbd_phone_shift.xml b/java/res/xml-sw768dp/kbd_phone_shift.xml
index 46f67d311..055d70cd2 100644
--- a/java/res/xml-sw768dp/kbd_phone_shift.xml
+++ b/java/res/xml-sw768dp/kbd_phone_shift.xml
@@ -23,136 +23,5 @@
latin:keyWidth="13.250%p"
>
<include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <Row>
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="11.172%p" />
- <Key
- latin:keyLabel="-"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="13.829%p"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="+"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:code="44"
- latin:keyLabel="@string/label_pause_key"
- latin:keyLabelOption="followKeyHintLabelRatio|autoXScale"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyStyle="num1KeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyStyle="num2KeyStyle" />
- <Key
- latin:keyStyle="num3KeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="backFromMoreSymbolKeyStyle"
- latin:keyWidth="11.172%p" />
- <Key
- latin:keyLabel=","
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="13.829%p"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="."
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:code="59"
- latin:keyLabel="@string/label_wait_key"
- latin:keyLabelOption="followKeyHintLabelRatio|autoXScale"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyStyle="num4KeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyStyle="num5KeyStyle" />
- <Key
- latin:keyStyle="num6KeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight" />
- </Row>
- <Row>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="13.829%p" />
- <Key
- latin:keyLabel="("
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel=")"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="N"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyStyle="num7KeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyStyle="num8KeyStyle" />
- <Key
- latin:keyStyle="num9KeyStyle" />
- <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
- <Spacer
- latin:keyWidth="0%p" />
- </Row>
- <Row>
- <switch>
- <case latin:hasSettingsKey="true">
- <Key
- latin:keyStyle="settingsKeyStyle"
- latin:keyWidth="8.047%p" />
- </case>
- <default>
- <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
- <Spacer
- latin:keyWidth="8.047%p" />
- </default>
- </switch>
- <Key
- latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
- latin:keyXPos="13.829%p"
- latin:keyWidth="24.140%p" />
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyStyle="num0KeyStyle" />
- <Key
- latin:keyLabel="#"
- latin:keyStyle="numKeyStyle" />
- <switch>
- <case
- latin:shortcutKeyEnabled="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle"
- latin:keyXPos="-8.047%p"
- latin:keyWidth="fillRight" />
- </case>
- <default>
- <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
- <Spacer
- latin:keyWidth="0%p" />
- </default>
- </switch>
- </Row>
+ latin:keyboardLayout="@xml/kbd_rows_phone_shift" />
</Keyboard>
diff --git a/java/res/xml-sw768dp/kbd_qwerty_row1.xml b/java/res/xml-sw768dp/kbd_qwerty_row1.xml
index 14b8bddfb..de9101331 100644
--- a/java/res/xml-sw768dp/kbd_qwerty_row1.xml
+++ b/java/res/xml-sw768dp/kbd_qwerty_row1.xml
@@ -26,7 +26,7 @@
>
<Key
latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="7.969%p" />
<Key
latin:keyLabel="q"
diff --git a/java/res/xml-sw768dp/kbd_qwerty_row2.xml b/java/res/xml-sw768dp/kbd_qwerty_row2.xml
index 2c312a328..1129ecdba 100644
--- a/java/res/xml-sw768dp/kbd_qwerty_row2.xml
+++ b/java/res/xml-sw768dp/kbd_qwerty_row2.xml
@@ -26,7 +26,7 @@
>
<Key
latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="11.172%p"/>
<Key
latin:keyLabel="a"
diff --git a/java/res/xml-sw768dp/kbd_qwerty_row4.xml b/java/res/xml-sw768dp/kbd_qwerty_row4.xml
index e35e47d83..1f00dff84 100644
--- a/java/res/xml-sw768dp/kbd_qwerty_row4.xml
+++ b/java/res/xml-sw768dp/kbd_qwerty_row4.xml
@@ -57,7 +57,7 @@
>
<Key
latin:keyLabel=":"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="+"
latin:moreKeys="+" />
</case>
@@ -76,7 +76,7 @@
<default>
<Key
latin:keyLabel="/"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="\@"
latin:moreKeys="\@" />
</default>
diff --git a/java/res/xml-sw768dp/kbd_row3_comma_period.xml b/java/res/xml-sw768dp/kbd_row3_comma_period.xml
index b84443078..6a95ca1a3 100644
--- a/java/res/xml-sw768dp/kbd_row3_comma_period.xml
+++ b/java/res/xml-sw768dp/kbd_row3_comma_period.xml
@@ -33,12 +33,12 @@
<default>
<Key
latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="!"
latin:moreKeys="!" />
<Key
latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="\?"
latin:moreKeys="\?" />
</default>
diff --git a/java/res/xml-sw768dp/kbd_row4_apostrophe_dash.xml b/java/res/xml-sw768dp/kbd_row4_apostrophe_dash.xml
index 9536e81da..4eb82d24a 100644
--- a/java/res/xml-sw768dp/kbd_row4_apostrophe_dash.xml
+++ b/java/res/xml-sw768dp/kbd_row4_apostrophe_dash.xml
@@ -33,14 +33,14 @@
>
<Key
latin:keyLabel="/"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel=":"
latin:moreKeys=":" />
</case>
<default>
<Key
latin:keyLabel="@string/keylabel_for_apostrophe"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="@string/keyhintlabel_for_apostrophe"
latin:moreKeys="@string/more_keys_for_apostrophe" />
</default>
@@ -55,7 +55,7 @@
<default>
<Key
latin:keyLabel="@string/keylabel_for_dash"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="@string/keyhintlabel_for_dash"
latin:moreKeys="@string/more_keys_for_dash" />
</default>
diff --git a/java/res/xml-sw768dp/kbd_rows_arabic.xml b/java/res/xml-sw768dp/kbd_rows_arabic.xml
index 7ec36fd94..412d5d98a 100644
--- a/java/res/xml-sw768dp/kbd_rows_arabic.xml
+++ b/java/res/xml-sw768dp/kbd_rows_arabic.xml
@@ -28,7 +28,7 @@
>
<Key
latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="7.500%p" />
<!-- \u0636: ARABIC LETTER DAD -->
<Key
@@ -84,7 +84,7 @@
>
<Key
latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="9.375%p" />
<!-- \u0634: ARABIC LETTER SHEEN
\u069c: ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE -->
diff --git a/java/res/xml-sw768dp/kbd_rows_azerty.xml b/java/res/xml-sw768dp/kbd_rows_azerty.xml
index 4659d9924..3edfb7e5b 100644
--- a/java/res/xml-sw768dp/kbd_rows_azerty.xml
+++ b/java/res/xml-sw768dp/kbd_rows_azerty.xml
@@ -28,7 +28,7 @@
>
<Key
latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="7.969%p" />
<Key
latin:keyLabel="a"
@@ -70,7 +70,7 @@
>
<Key
latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="10.167%p" />
<Key
latin:keyLabel="q"
@@ -127,7 +127,7 @@
latin:moreKeys="@string/more_keys_for_n" />
<Key
latin:keyLabel="\'"
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel=":"
latin:moreKeys=":" />
<switch>
@@ -142,12 +142,12 @@
<default>
<Key
latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="!"
latin:moreKeys="!" />
<Key
latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="\?"
latin:moreKeys="\?" />
</default>
diff --git a/java/res/xml-sw768dp/kbd_rows_hebrew.xml b/java/res/xml-sw768dp/kbd_rows_hebrew.xml
index 27b39d1ae..5f4b556b6 100644
--- a/java/res/xml-sw768dp/kbd_rows_hebrew.xml
+++ b/java/res/xml-sw768dp/kbd_rows_hebrew.xml
@@ -28,7 +28,7 @@
>
<Key
latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="7.969%p" />
<include
latin:keyboardLayout="@xml/kbd_row4_apostrophe_dash" />
@@ -58,7 +58,7 @@
>
<Key
latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="11.172%p" />
<Key
latin:keyLabel="ש" />
diff --git a/java/res/xml-sw768dp/kbd_rows_number.xml b/java/res/xml-sw768dp/kbd_rows_number.xml
new file mode 100644
index 000000000..1268987b5
--- /dev/null
+++ b/java/res/xml-sw768dp/kbd_rows_number.xml
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/kbd_key_styles" />
+ <include
+ latin:keyboardLayout="@xml/kbd_numkey_styles" />
+ <switch>
+ <case
+ latin:passwordInput="true"
+ >
+ <Row>
+ <Key
+ latin:keyStyle="numTabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <Key
+ latin:keyStyle="num1KeyStyle"
+ latin:keyXPos="32.076%p" />
+ <Key
+ latin:keyStyle="num2KeyStyle" />
+ <Key
+ latin:keyStyle="num3KeyStyle" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyXPos="-11.172%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="32.076%p" />
+ <Key
+ latin:keyStyle="num4KeyStyle" />
+ <Key
+ latin:keyStyle="num5KeyStyle" />
+ <Key
+ latin:keyStyle="num6KeyStyle" />
+ <Key
+ latin:keyStyle="returnKeyStyle"
+ latin:keyXPos="-11.172%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="32.076%p" />
+ <Key
+ latin:keyStyle="num7KeyStyle" />
+ <Key
+ latin:keyStyle="num8KeyStyle" />
+ <Key
+ latin:keyStyle="num9KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="0%p" />
+ </Row>
+ <Row>
+ <Spacer
+ latin:keyXPos="32.076%p" />
+ <Key
+ latin:keyStyle="num0KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="0%p" />
+ </Row>
+ </case>
+ <!-- latin:passwordInput="false" -->
+ <default>
+ <Row>
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <Key
+ latin:keyLabel="-"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="13.829%p"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel="+"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel="."
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel="1"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyLabel="2"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="3"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyXPos="-11.172%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="13.829%p" />
+ <Key
+ latin:keyStyle="numStarKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel="/"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel=","
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel="4"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyLabel="5"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="6"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyStyle="returnKeyStyle"
+ latin:keyXPos="-11.172%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="13.829%p" />
+ <Key
+ latin:keyLabel="("
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel=")"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel="="
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel="7"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyLabel="8"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="9"
+ latin:keyStyle="numKeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="0%p" />
+ </Row>
+ <Row>
+ <switch>
+ <case latin:hasSettingsKey="true">
+ <Key
+ latin:keyStyle="settingsKeyStyle"
+ latin:keyWidth="8.047%p" />
+ </case>
+ <default>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="8.047%p" />
+ </default>
+ </switch>
+ <Key
+ latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
+ latin:keyXPos="13.829%p"
+ latin:keyWidth="24.140%p" />
+ <Key
+ latin:keyStyle="numStarKeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyLabel="0"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="#"
+ latin:keyStyle="numKeyStyle" />
+ <switch>
+ <case
+ latin:shortcutKeyEnabled="true"
+ >
+ <Key
+ latin:keyStyle="shortcutKeyStyle"
+ latin:keyXPos="-8.047%p"
+ latin:keyWidth="fillRight" />
+ </case>
+ <default>
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="0%p" />
+ </default>
+ </switch>
+ </Row>
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw768dp/kbd_rows_phone.xml b/java/res/xml-sw768dp/kbd_rows_phone.xml
new file mode 100644
index 000000000..1320cf0ba
--- /dev/null
+++ b/java/res/xml-sw768dp/kbd_rows_phone.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/kbd_key_styles" />
+ <include
+ latin:keyboardLayout="@xml/kbd_numkey_styles" />
+ <Row>
+ <Key
+ latin:keyStyle="numTabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <Key
+ latin:keyLabel="-"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="20.400%p"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel="+"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyStyle="num1KeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyStyle="num2KeyStyle" />
+ <Key
+ latin:keyStyle="num3KeyStyle" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyXPos="-11.172%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="toMoreSymbolKeyStyle"
+ latin:keyWidth="11.172%p" />
+ <Key
+ latin:keyLabel=","
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="20.400%p"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel="."
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyStyle="num4KeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyStyle="num5KeyStyle" />
+ <Key
+ latin:keyStyle="num6KeyStyle" />
+ <Key
+ latin:keyStyle="returnKeyStyle"
+ latin:keyXPos="-11.172%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="20.400%p" />
+ <Key
+ latin:keyLabel="("
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel=")"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyStyle="num7KeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyStyle="num8KeyStyle" />
+ <Key
+ latin:keyStyle="num9KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="0%p" />
+ </Row>
+ <Row>
+ <switch>
+ <case latin:hasSettingsKey="true">
+ <Key
+ latin:keyStyle="settingsKeyStyle"
+ latin:keyWidth="8.047%p" />
+ </case>
+ <default>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="8.047%p" />
+ </default>
+ </switch>
+ <Key
+ latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
+ latin:keyXPos="20.400%p"
+ latin:keyWidth="16.084%p" />
+ <Key
+ latin:keyStyle="numStarKeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyStyle="num0KeyStyle" />
+ <Key
+ latin:keyLabel="#"
+ latin:keyStyle="numKeyStyle" />
+ <switch>
+ <case
+ latin:shortcutKeyEnabled="true"
+ >
+ <Key
+ latin:keyStyle="shortcutKeyStyle"
+ latin:keyXPos="-8.047%p"
+ latin:keyWidth="fillRight" />
+ </case>
+ <default>
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="0%p" />
+ </default>
+ </switch>
+ </Row>
+</merge>
diff --git a/java/res/xml-sw768dp/kbd_rows_phone_shift.xml b/java/res/xml-sw768dp/kbd_rows_phone_shift.xml
new file mode 100644
index 000000000..e749790a0
--- /dev/null
+++ b/java/res/xml-sw768dp/kbd_rows_phone_shift.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/kbd_key_styles" />
+ <include
+ latin:keyboardLayout="@xml/kbd_numkey_styles" />
+ <Row>
+ <Key
+ latin:keyStyle="numTabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <Key
+ latin:keyLabel="-"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="13.829%p"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel="+"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyStyle="numPauseKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyStyle="num1KeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyStyle="num2KeyStyle" />
+ <Key
+ latin:keyStyle="num3KeyStyle" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyXPos="-11.172%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="backFromMoreSymbolKeyStyle"
+ latin:keyWidth="11.172%p" />
+ <Key
+ latin:keyLabel=","
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="13.829%p"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel="."
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyStyle="numWaitKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyStyle="num4KeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyStyle="num5KeyStyle" />
+ <Key
+ latin:keyStyle="num6KeyStyle" />
+ <Key
+ latin:keyStyle="returnKeyStyle"
+ latin:keyXPos="-11.172%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="13.829%p" />
+ <Key
+ latin:keyLabel="("
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel=")"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyLabel="N"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyStyle="num7KeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyStyle="num8KeyStyle" />
+ <Key
+ latin:keyStyle="num9KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="0%p" />
+ </Row>
+ <Row>
+ <switch>
+ <case latin:hasSettingsKey="true">
+ <Key
+ latin:keyStyle="settingsKeyStyle"
+ latin:keyWidth="8.047%p" />
+ </case>
+ <default>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="8.047%p" />
+ </default>
+ </switch>
+ <Key
+ latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
+ latin:keyXPos="13.829%p"
+ latin:keyWidth="24.140%p" />
+ <Key
+ latin:keyStyle="numStarKeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyStyle="num0KeyStyle" />
+ <Key
+ latin:keyLabel="#"
+ latin:keyStyle="numKeyStyle" />
+ <switch>
+ <case
+ latin:shortcutKeyEnabled="true"
+ >
+ <Key
+ latin:keyStyle="shortcutKeyStyle"
+ latin:keyXPos="-8.047%p"
+ latin:keyWidth="fillRight" />
+ </case>
+ <default>
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="0%p" />
+ </default>
+ </switch>
+ </Row>
+</merge>
diff --git a/java/res/xml-sw768dp/kbd_rows_qwertz.xml b/java/res/xml-sw768dp/kbd_rows_qwertz.xml
index 82e0dd09c..3c02c8f62 100644
--- a/java/res/xml-sw768dp/kbd_rows_qwertz.xml
+++ b/java/res/xml-sw768dp/kbd_rows_qwertz.xml
@@ -28,7 +28,7 @@
>
<Key
latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="7.969%p" />
<Key
latin:keyLabel="q"
@@ -103,12 +103,12 @@
<default>
<Key
latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="!"
latin:moreKeys="!" />
<Key
latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
+ latin:keyLabelFlags="hasUppercaseLetter"
latin:keyHintLabel="\?"
latin:moreKeys="\?" />
</default>
diff --git a/java/res/xml-sw768dp/kbd_rows_scandinavian.xml b/java/res/xml-sw768dp/kbd_rows_scandinavian.xml
index b9d168036..334b76d6a 100644
--- a/java/res/xml-sw768dp/kbd_rows_scandinavian.xml
+++ b/java/res/xml-sw768dp/kbd_rows_scandinavian.xml
@@ -28,7 +28,7 @@
>
<Key
latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="7.500%p" />
<Key
latin:keyLabel="q"
@@ -61,7 +61,7 @@
latin:keyLabel="p"
latin:moreKeys="@string/more_keys_for_p" />
<Key
- latin:keyLabel="å" />
+ latin:keyLabel="@string/keylabel_for_scandinavia_row1_11" />
<Key
latin:keyStyle="deleteKeyStyle"
latin:keyXPos="-11.500%p"
@@ -72,7 +72,7 @@
>
<Key
latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="9.375%p" />
<Key
latin:keyLabel="a"
diff --git a/java/res/xml-sw768dp/kbd_rows_serbian.xml b/java/res/xml-sw768dp/kbd_rows_serbian.xml
index c07176ef6..0b1773e40 100644
--- a/java/res/xml-sw768dp/kbd_rows_serbian.xml
+++ b/java/res/xml-sw768dp/kbd_rows_serbian.xml
@@ -28,7 +28,7 @@
>
<Key
latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft" />
+ latin:keyLabelFlags="alignLeft" />
<Key
latin:keyLabel="љ" />
<Key
@@ -62,7 +62,7 @@
>
<Key
latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="11.172%p" />
<Key
latin:keyLabel="а" />
diff --git a/java/res/xml-sw768dp/kbd_rows_russian.xml b/java/res/xml-sw768dp/kbd_rows_slavic.xml
index e5f556958..4c9128d86 100644
--- a/java/res/xml-sw768dp/kbd_rows_russian.xml
+++ b/java/res/xml-sw768dp/kbd_rows_slavic.xml
@@ -28,26 +28,28 @@
>
<Key
latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft" />
+ latin:keyLabelFlags="alignLeft" />
<Key
latin:keyLabel="й" />
<Key
latin:keyLabel="ц" />
<Key
- latin:keyLabel="у" />
+ latin:keyLabel="у"
+ latin:moreKeys="@string/more_keys_for_slavic_u" />
<Key
latin:keyLabel="к" />
<Key
latin:keyLabel="е"
- latin:moreKeys="@string/more_keys_for_cyrillic_e" />
+ latin:moreKeys="@string/more_keys_for_slavic_ye" />
<Key
- latin:keyLabel="н" />
+ latin:keyLabel="н"
+ latin:moreKeys="@string/more_keys_for_slavic_en" />
<Key
latin:keyLabel="г" />
<Key
latin:keyLabel="ш" />
<Key
- latin:keyLabel="щ" />
+ latin:keyLabel="@string/keylabel_for_slavic_shcha" />
<Key
latin:keyLabel="з" />
<Key
@@ -63,12 +65,13 @@
>
<Key
latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="9.375%p" />
<Key
latin:keyLabel="ф" />
<Key
- latin:keyLabel="ы" />
+ latin:keyLabel="@string/keylabel_for_slavic_yery"
+ latin:moreKeys="@string/more_keys_for_slavic_yery" />
<Key
latin:keyLabel="в" />
<Key
@@ -78,7 +81,8 @@
<Key
latin:keyLabel="р" />
<Key
- latin:keyLabel="о" />
+ latin:keyLabel="о"
+ latin:moreKeys="@string/more_keys_for_slavic_o" />
<Key
latin:keyLabel="л" />
<Key
@@ -107,7 +111,7 @@
<Key
latin:keyLabel="м" />
<Key
- latin:keyLabel="и" />
+ latin:keyLabel="@string/keylabel_for_slavic_i" />
<Key
latin:keyLabel="т" />
<Key
diff --git a/java/res/xml-sw768dp/kbd_rows_spanish.xml b/java/res/xml-sw768dp/kbd_rows_spanish.xml
index c737f400a..7e543b2fb 100644
--- a/java/res/xml-sw768dp/kbd_rows_spanish.xml
+++ b/java/res/xml-sw768dp/kbd_rows_spanish.xml
@@ -30,7 +30,7 @@
>
<Key
latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="10.167%p" />
<Key
latin:keyLabel="a"
diff --git a/java/res/xml-sw768dp/kbd_rows_symbols.xml b/java/res/xml-sw768dp/kbd_rows_symbols.xml
index 987b10cdc..641fe1934 100644
--- a/java/res/xml-sw768dp/kbd_rows_symbols.xml
+++ b/java/res/xml-sw768dp/kbd_rows_symbols.xml
@@ -30,7 +30,7 @@
>
<Key
latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="7.969%p" />
<Key
latin:keyLabel="@string/keylabel_for_symbols_1"
@@ -72,7 +72,7 @@
>
<Key
latin:keyStyle="toAlphaKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="11.172%p" />
<Key
latin:keyLabel="#" />
diff --git a/java/res/xml-sw768dp/kbd_rows_symbols_shift.xml b/java/res/xml-sw768dp/kbd_rows_symbols_shift.xml
index 9a9c3a276..f6b47a86f 100644
--- a/java/res/xml-sw768dp/kbd_rows_symbols_shift.xml
+++ b/java/res/xml-sw768dp/kbd_rows_symbols_shift.xml
@@ -30,7 +30,7 @@
>
<Key
latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="7.969%p" />
<Key
latin:keyLabel="~" />
@@ -65,7 +65,7 @@
>
<Key
latin:keyStyle="toAlphaKeyStyle"
- latin:keyLabelOption="alignLeft"
+ latin:keyLabelFlags="alignLeft"
latin:keyWidth="11.172%p" />
<Key
latin:keyStyle="moreCurrency1KeyStyle" />
diff --git a/java/res/xml-tr/kbd_qwerty.xml b/java/res/xml-tr/kbd_qwerty.xml
deleted file mode 100644
index d2c38f60a..000000000
--- a/java/res/xml-tr/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="tr"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_qwerty" />
-</Keyboard>
diff --git a/java/res/xml-tr/keyboard_set.xml b/java/res/xml-tr/keyboard_set.xml
new file mode 100644
index 000000000..854ab8566
--- /dev/null
+++ b/java/res/xml-tr/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="tr">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwerty" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-uk/keyboard_set.xml b/java/res/xml-uk/keyboard_set.xml
new file mode 100644
index 000000000..e5ba43b23
--- /dev/null
+++ b/java/res/xml-uk/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="uk">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_slavic" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-vi/keyboard_set.xml b/java/res/xml-vi/keyboard_set.xml
new file mode 100644
index 000000000..7f4b25d9d
--- /dev/null
+++ b/java/res/xml-vi/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="vi">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwerty" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-ar/kbd_qwerty.xml b/java/res/xml/kbd_arabic.xml
index b26a938cc..91b22810b 100644
--- a/java/res/xml-ar/kbd_qwerty.xml
+++ b/java/res/xml/kbd_arabic.xml
@@ -20,7 +20,6 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="ar"
latin:isRtlKeyboard="true"
>
<include
diff --git a/java/res/xml-fr/kbd_qwerty.xml b/java/res/xml/kbd_azerty.xml
index 8c730a24f..3abaf648a 100644
--- a/java/res/xml-fr/kbd_qwerty.xml
+++ b/java/res/xml/kbd_azerty.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2008, The Android Open Source Project
+** Copyright 2011, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="fr"
>
<include
latin:keyboardLayout="@xml/kbd_rows_azerty" />
diff --git a/java/res/xml-iw/kbd_qwerty.xml b/java/res/xml/kbd_hebrew.xml
index 54cd4b5e9..f25aaddfa 100644
--- a/java/res/xml-iw/kbd_qwerty.xml
+++ b/java/res/xml/kbd_hebrew.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2010, The Android Open Source Project
+** Copyright 2011, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="iw"
latin:isRtlKeyboard="true"
>
<include
diff --git a/java/res/xml/kbd_key_styles.xml b/java/res/xml/kbd_key_styles.xml
index 453b05dff..7869d21d0 100644
--- a/java/res/xml/kbd_key_styles.xml
+++ b/java/res/xml/kbd_key_styles.xml
@@ -28,7 +28,7 @@
>
<key-style
latin:styleName="f1PopupStyle"
- latin:keyLabelOption="hasPopupHint"
+ latin:keyLabelFlags="hasPopupHint"
latin:moreKeys="@string/more_keys_for_f1"
latin:backgroundType="functional" />
</case>
@@ -38,7 +38,7 @@
>
<key-style
latin:styleName="f1PopupStyle"
- latin:keyLabelOption="hasPopupHint"
+ latin:keyLabelFlags="hasPopupHint"
latin:moreKeys="@string/more_keys_for_f1_settings"
latin:backgroundType="functional" />
</case>
@@ -48,7 +48,7 @@
>
<key-style
latin:styleName="f1PopupStyle"
- latin:keyLabelOption="hasPopupHint"
+ latin:keyLabelFlags="hasPopupHint"
latin:moreKeys="@string/more_keys_for_f1_navigate"
latin:backgroundType="functional" />
</case>
@@ -56,7 +56,7 @@
<default>
<key-style
latin:styleName="f1PopupStyle"
- latin:keyLabelOption="hasPopupHint"
+ latin:keyLabelFlags="hasPopupHint"
latin:moreKeys="@string/more_keys_for_f1"
latin:backgroundType="functional" />
</default>
@@ -66,14 +66,14 @@
latin:styleName="shiftKeyStyle"
latin:code="@integer/key_shift"
latin:keyIcon="iconShiftKey"
- latin:keyIconShifted="iconShiftedShiftKey"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="sticky" />
<key-style
latin:styleName="deleteKeyStyle"
latin:code="@integer/key_delete"
latin:keyIcon="iconDeleteKey"
- latin:backgroundType="functional"
- latin:isRepeatable="true" />
+ latin:keyActionFlags="isRepeatable|noKeyPreview"
+ latin:backgroundType="functional" />
<!-- Return key style -->
<switch>
<case
@@ -84,7 +84,7 @@
latin:styleName="returnKeyStyle"
latin:keyLabel=":-)"
latin:keyOutputText=":-) "
- latin:keyLabelOption="hasPopupHint"
+ latin:keyLabelFlags="hasPopupHint"
latin:moreKeys="@string/more_keys_for_smiley"
latin:maxMoreKeysColumn="5"
latin:backgroundType="functional" />
@@ -96,7 +96,8 @@
latin:styleName="returnKeyStyle"
latin:code="@integer/key_return"
latin:keyLabel="@string/label_go_key"
- latin:keyLabelOption="autoXScale"
+ latin:keyLabelFlags="autoXScale"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="action" />
</case>
<case
@@ -106,7 +107,8 @@
latin:styleName="returnKeyStyle"
latin:code="@integer/key_return"
latin:keyLabel="@string/label_next_key"
- latin:keyLabelOption="autoXScale"
+ latin:keyLabelFlags="autoXScale"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="action" />
</case>
<case
@@ -116,7 +118,8 @@
latin:styleName="returnKeyStyle"
latin:code="@integer/key_return"
latin:keyLabel="@string/label_done_key"
- latin:keyLabelOption="autoXScale"
+ latin:keyLabelFlags="autoXScale"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="action" />
</case>
<case
@@ -126,7 +129,8 @@
latin:styleName="returnKeyStyle"
latin:code="@integer/key_return"
latin:keyLabel="@string/label_send_key"
- latin:keyLabelOption="autoXScale"
+ latin:keyLabelFlags="autoXScale"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="action" />
</case>
<case
@@ -136,6 +140,8 @@
latin:styleName="returnKeyStyle"
latin:code="@integer/key_return"
latin:keyIcon="iconSearchKey"
+ latin:keyLabelFlags="autoXScale"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="action" />
</case>
<default>
@@ -143,22 +149,29 @@
latin:styleName="returnKeyStyle"
latin:code="@integer/key_return"
latin:keyIcon="iconReturnKey"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
</default>
</switch>
<key-style
latin:styleName="spaceKeyStyle"
latin:code="@integer/key_space"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="shortcutKeyStyle"
latin:code="@integer/key_shortcut"
latin:keyIcon="iconShortcutKey"
+ latin:keyIconDisabled="iconDisabledShortcutKey"
+ latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
+ latin:altCode="@integer/key_space"
latin:parentStyle="f1PopupStyle" />
<key-style
latin:styleName="settingsKeyStyle"
latin:code="@integer/key_settings"
latin:keyIcon="iconSettingsKey"
+ latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
+ latin:altCode="@integer/key_space"
latin:backgroundType="functional" />
<key-style
latin:styleName="tabKeyStyle"
@@ -186,7 +199,8 @@
latin:code="@integer/key_switch_alpha_symbol"
latin:keyIcon="iconShortcutForLabel"
latin:keyLabel="@string/label_to_symbol_with_microphone_key"
- latin:keyLabelOption="withIconRight"
+ latin:keyLabelFlags="withIconRight"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
</case>
<default>
@@ -194,6 +208,7 @@
latin:styleName="toSymbolKeyStyle"
latin:code="@integer/key_switch_alpha_symbol"
latin:keyLabel="@string/label_to_symbol_key"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
</default>
</switch>
@@ -201,22 +216,25 @@
latin:styleName="toAlphaKeyStyle"
latin:code="@integer/key_switch_alpha_symbol"
latin:keyLabel="@string/label_to_alpha_key"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="toMoreSymbolKeyStyle"
latin:code="@integer/key_shift"
latin:keyLabel="@string/label_to_more_symbol_key"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="backFromMoreSymbolKeyStyle"
latin:code="@integer/key_shift"
latin:keyLabel="@string/label_to_symbol_key"
+ latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="punctuationKeyStyle"
latin:keyLabel="."
latin:keyHintLabel="@string/keyhintlabel_for_punctuation"
- latin:keyLabelOption="hasPopupHint"
+ latin:keyLabelFlags="hasPopupHint"
latin:moreKeys="@string/more_keys_for_punctuation"
latin:maxMoreKeysColumn="@integer/mini_keyboard_column_for_punctuation"
latin:backgroundType="functional" />
diff --git a/java/res/xml/kbd_numkey_styles.xml b/java/res/xml/kbd_numkey_styles.xml
index 5d5439906..003165da8 100644
--- a/java/res/xml/kbd_numkey_styles.xml
+++ b/java/res/xml/kbd_numkey_styles.xml
@@ -22,18 +22,24 @@
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
>
<key-style
+ latin:styleName="numKeyBaseStyle"
+ latin:keyActionFlags="noKeyPreview" />
+ <key-style
latin:styleName="numKeyStyle"
- latin:keyLabelOption="largeLetter|followKeyLetterRatio" />
+ latin:keyLabelFlags="largeLetter|followKeyLetterRatio"
+ latin:parentStyle="numKeyBaseStyle" />
<key-style
latin:styleName="numModeKeyStyle"
- latin:keyLabelOption="fontNormal|followKeyLetterRatio" />
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio"
+ latin:parentStyle="numKeyBaseStyle" />
<key-style
latin:styleName="numFunctionalKeyStyle"
- latin:keyLabelOption="largeLetter|followKeyLetterRatio"
- latin:backgroundType="functional" />
+ latin:keyLabelFlags="largeLetter|followKeyLetterRatio"
+ latin:backgroundType="functional"
+ latin:parentStyle="numKeyBaseStyle" />
<key-style
latin:styleName="numberKeyStyle"
- latin:keyLabelOption="alignLeftOfCenter|hasHintLabel"
+ latin:keyLabelFlags="alignLeftOfCenter|hasHintLabel"
latin:parentStyle="numKeyStyle" />
<key-style
latin:styleName="num0KeyStyle"
@@ -100,7 +106,24 @@
latin:keyLabel="@string/label_to_phone_numeric_key"
latin:parentStyle="numModeKeyStyle" />
<key-style
+ latin:styleName="numPauseKeyStyle"
+ latin:code="44"
+ latin:keyLabel="@string/label_pause_key"
+ latin:keyLabelFlags="followKeyHintLabelRatio|autoXScale"
+ latin:parentStyle="numKeyBaseStyle" />
+ <key-style
+ latin:styleName="numWaitKeyStyle"
+ latin:code="59"
+ latin:keyLabel="@string/label_wait_key"
+ latin:keyLabelFlags="followKeyHintLabelRatio|autoXScale"
+ latin:parentStyle="numKeyBaseStyle" />
+ <key-style
+ latin:styleName="numTabKeyStyle"
+ latin:keyActionFlags="noKeyPreview"
+ latin:parentStyle="tabKeyStyle" />
+ <key-style
latin:styleName="numSpaceKeyStyle"
latin:code="@integer/key_space"
- latin:keyIcon="iconSpaceKey" />
+ latin:keyIcon="iconSpaceKeyForNumberLayout"
+ latin:parentStyle="numKeyBaseStyle" />
</merge>
diff --git a/java/res/xml/kbd_qwerty.xml b/java/res/xml/kbd_qwerty.xml
index 40917b921..ae0146c82 100644
--- a/java/res/xml/kbd_qwerty.xml
+++ b/java/res/xml/kbd_qwerty.xml
@@ -20,7 +20,6 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="en_GB,en_US"
>
<include
latin:keyboardLayout="@xml/kbd_rows_qwerty" />
diff --git a/java/res/xml-cs/kbd_qwerty.xml b/java/res/xml/kbd_qwertz.xml
index 9991ea2d2..5bcceb2f6 100644
--- a/java/res/xml-cs/kbd_qwerty.xml
+++ b/java/res/xml/kbd_qwertz.xml
@@ -20,7 +20,6 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="cs"
>
<include
latin:keyboardLayout="@xml/kbd_rows_qwertz" />
diff --git a/java/res/xml/kbd_rows_phone_shift.xml b/java/res/xml/kbd_rows_phone_shift.xml
index 3c283d3e6..b39e2da8d 100644
--- a/java/res/xml/kbd_rows_phone_shift.xml
+++ b/java/res/xml/kbd_rows_phone_shift.xml
@@ -42,13 +42,12 @@
</Row>
<Row>
<Key
- latin:keyLabel="N" />
+ latin:keyLabel="N"
+ latin:keyStyle="numKeyBaseStyle" />
<!-- Pause is a comma. Check PhoneNumberUtils.java to see if this
has changed. -->
<Key
- latin:code="44"
- latin:keyLabel="@string/label_pause_key"
- latin:keyLabelOption="followKeyHintLabelRatio|autoXScale" />
+ latin:keyStyle="numPauseKeyStyle" />
<Key
latin:keyLabel=","
latin:keyStyle="numKeyStyle" />
@@ -62,9 +61,7 @@
latin:keyStyle="numStarKeyStyle" />
<!-- Wait is a semicolon. -->
<Key
- latin:code="59"
- latin:keyLabel="@string/label_wait_key"
- latin:keyLabelOption="followKeyHintLabelRatio|autoXScale" />
+ latin:keyStyle="numWaitKeyStyle" />
<Key
latin:keyLabel="#"
latin:keyStyle="numKeyStyle" />
diff --git a/java/res/xml/kbd_rows_scandinavian.xml b/java/res/xml/kbd_rows_scandinavian.xml
index 4f138c514..eb32c0055 100644
--- a/java/res/xml/kbd_rows_scandinavian.xml
+++ b/java/res/xml/kbd_rows_scandinavian.xml
@@ -67,7 +67,7 @@
latin:keyHintLabel="0"
latin:moreKeys="@string/more_keys_for_p" />
<Key
- latin:keyLabel="å"
+ latin:keyLabel="@string/keylabel_for_scandinavia_row1_11"
latin:keyWidth="fillRight" />
</Row>
<Row
@@ -75,8 +75,7 @@
>
<Key
latin:keyLabel="a"
- latin:moreKeys="@string/more_keys_for_a"
- latin:keyWidth="8.75%p" />
+ latin:moreKeys="@string/more_keys_for_a" />
<Key
latin:keyLabel="s"
latin:moreKeys="@string/more_keys_for_s" />
diff --git a/java/res/xml/kbd_rows_russian.xml b/java/res/xml/kbd_rows_slavic.xml
index f1794e750..426be72dd 100644
--- a/java/res/xml/kbd_rows_russian.xml
+++ b/java/res/xml/kbd_rows_slavic.xml
@@ -37,7 +37,7 @@
<Key
latin:keyLabel="у"
latin:keyHintLabel="3"
- latin:moreKeys="3" />
+ latin:moreKeys="@string/more_keys_for_slavic_u" />
<Key
latin:keyLabel="к"
latin:keyHintLabel="4"
@@ -45,11 +45,11 @@
<Key
latin:keyLabel="е"
latin:keyHintLabel="5"
- latin:moreKeys="@string/more_keys_for_cyrillic_e" />
+ latin:moreKeys="@string/more_keys_for_slavic_ye" />
<Key
latin:keyLabel="н"
latin:keyHintLabel="6"
- latin:moreKeys="6" />
+ latin:moreKeys="@string/more_keys_for_slavic_en" />
<Key
latin:keyLabel="г"
latin:keyHintLabel="7"
@@ -59,7 +59,7 @@
latin:keyHintLabel="8"
latin:moreKeys="8" />
<Key
- latin:keyLabel="щ"
+ latin:keyLabel="@string/keylabel_for_slavic_shcha"
latin:keyHintLabel="9"
latin:moreKeys="9" />
<Key
@@ -68,17 +68,17 @@
latin:moreKeys="0" />
<Key
latin:keyLabel="х"
- latin:moreKeys="@string/more_keys_for_cyrillic_ha"
+ latin:moreKeys="@string/more_keys_for_slavic_ha"
latin:keyWidth="fillRight" />
</Row>
<Row
latin:keyWidth="9.091%p"
>
<Key
- latin:keyLabel="ф"
- latin:keyWidth="8.75%p" />
+ latin:keyLabel="ф" />
<Key
- latin:keyLabel="ы" />
+ latin:keyLabel="@string/keylabel_for_slavic_yery"
+ latin:moreKeys="@string/more_keys_for_slavic_yery" />
<Key
latin:keyLabel="в" />
<Key
@@ -88,7 +88,8 @@
<Key
latin:keyLabel="р" />
<Key
- latin:keyLabel="о" />
+ latin:keyLabel="о"
+ latin:moreKeys="@string/more_keys_for_slavic_o" />
<Key
latin:keyLabel="л" />
<Key
@@ -114,12 +115,12 @@
<Key
latin:keyLabel="м" />
<Key
- latin:keyLabel="и" />
+ latin:keyLabel="@string/keylabel_for_slavic_i" />
<Key
latin:keyLabel="т" />
<Key
latin:keyLabel="ь"
- latin:moreKeys="@string/more_keys_for_cyrillic_soft_sign" />
+ latin:moreKeys="@string/more_keys_for_slavic_soft_sign" />
<Key
latin:keyLabel="б" />
<Key
diff --git a/java/res/xml-fi/kbd_qwerty.xml b/java/res/xml/kbd_scandinavian.xml
index 75721e057..4caa9894c 100644
--- a/java/res/xml-fi/kbd_qwerty.xml
+++ b/java/res/xml/kbd_scandinavian.xml
@@ -20,7 +20,6 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="fi"
>
<include
latin:keyboardLayout="@xml/kbd_rows_scandinavian" />
diff --git a/java/res/xml-sr/kbd_qwerty.xml b/java/res/xml/kbd_serbian.xml
index 58fc187c2..40b719978 100644
--- a/java/res/xml-sr/kbd_qwerty.xml
+++ b/java/res/xml/kbd_serbian.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2008, The Android Open Source Project
+** Copyright 2011, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="sr"
>
<include
latin:keyboardLayout="@xml/kbd_rows_serbian" />
diff --git a/java/res/xml/kbd_settings_or_tab.xml b/java/res/xml/kbd_settings_or_tab.xml
index 4a8bcc7a6..2d35e3b4a 100644
--- a/java/res/xml/kbd_settings_or_tab.xml
+++ b/java/res/xml/kbd_settings_or_tab.xml
@@ -25,8 +25,11 @@
<case
latin:hasSettingsKey="true"
>
+ <!-- Because this settings key is not adjacent to the space key, this key should be
+ just ignored while typing (altCode=CODE_UNSPECIFIED). -->
<Key
latin:keyStyle="settingsKeyStyle"
+ latin:altCode="@integer/key_unspecified"
latin:keyWidth="9.2%p" />
</case>
<!-- hasSettingsKey="false" -->
diff --git a/java/res/xml-pl/kbd_qwerty.xml b/java/res/xml/kbd_slavic.xml
index 44312c52c..6207d2939 100644
--- a/java/res/xml-pl/kbd_qwerty.xml
+++ b/java/res/xml/kbd_slavic.xml
@@ -4,7 +4,7 @@
**
** Copyright 2011, The Android Open Source Project
**
-** Licensed under the Apache License, Version 2.0 (the "License");
+** Licensed under the Apache License, Version 2.0 (the "License"):
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
@@ -20,8 +20,7 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="pl"
>
<include
- latin:keyboardLayout="@xml/kbd_rows_qwerty" />
+ latin:keyboardLayout="@xml/kbd_rows_slavic" />
</Keyboard>
diff --git a/java/res/xml-es/kbd_qwerty.xml b/java/res/xml/kbd_spanish.xml
index 568f4d652..cfb8c6c27 100644
--- a/java/res/xml-es/kbd_qwerty.xml
+++ b/java/res/xml/kbd_spanish.xml
@@ -20,7 +20,6 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="es,es_US"
>
<include
latin:keyboardLayout="@xml/kbd_rows_spanish" />
diff --git a/java/res/xml/kbd_symbols_shift_row4.xml b/java/res/xml/kbd_symbols_shift_row4.xml
index 89e80e5f7..079112c78 100644
--- a/java/res/xml/kbd_symbols_shift_row4.xml
+++ b/java/res/xml/kbd_symbols_shift_row4.xml
@@ -33,7 +33,7 @@
latin:keyStyle="toAlphaKeyStyle"
latin:keyWidth="15%p" />
<!-- Note: Neither DroidSans nor Roboto have a glyph for ‟ Double high-reversed-9 quotation mark U+201F. -->
- <!-- latin:keyLabelOption="hasPopupHint" -->
+ <!-- latin:keyLabelFlags="hasPopupHint" -->
<!-- latin:moreKeys="‟" -->
<Key
latin:keyLabel="„"
@@ -56,7 +56,7 @@
<include
latin:keyboardLayout="@xml/kbd_settings_or_tab" />
<!-- Note: Neither DroidSans nor Roboto have a glyph for ‟ Double high-reversed-9 quotation mark U+201F. -->
- <!-- latin:keyLabelOption="hasPopupHint" -->
+ <!-- latin:keyLabelFlags="hasPopupHint" -->
<!-- latin:moreKeys="‟" -->
<Key
latin:keyLabel="„"
diff --git a/java/res/xml/keyboard_set.xml b/java/res/xml/keyboard_set.xml
new file mode 100644
index 000000000..96f352bb2
--- /dev/null
+++ b/java/res/xml/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardLocale="en_GB,en_US">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwerty" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShift"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneShift"
+ latin:elementKeyboard="@xml/kbd_phone_shift" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 6184add4d..a3b1d5859 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -20,7 +20,8 @@
<!-- The attributes in this XML file provide configuration information -->
<!-- for the Input Method Manager. -->
-<!-- Keyboard: en_US, en_GB, ar, cs, da, de, de(QWERTY), es, es_US, fi, fr, fr_CA, fr_CH, hr, hu, it, iw, nb, nl, pl, pt, ru, sr, sv, tr -->
+<!-- Keyboard: en_US, en_GB, ar, be, cs, da, de, de(QWERTY), es, es_US, et, fi, fr, fr_CA, fr_CH,
+ hr, hu, it, iw, ky, lt, lv, nb, nl, pl, pt, ro, ru, sk, sl, sr, sv, tr, uk, vi -->
<!-- TODO: use <lang>_keyboard icon instead of a common keyboard icon. -->
<!-- If IME doesn't have an applicable subtype, the first subtype will be used as a default
subtype.-->
@@ -31,7 +32,7 @@
android:label="@string/subtype_en_US"
android:imeSubtypeLocale="en_US"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection"
+ android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection,EnabledWhenDefaultIsNotAsciiCapable"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_en_GB"
@@ -47,6 +48,12 @@
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="be"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
android:imeSubtypeLocale="cs"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
@@ -77,6 +84,12 @@
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="et"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
android:imeSubtypeLocale="fi"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
@@ -126,6 +139,24 @@
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="ky"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="lt"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="lv"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
android:imeSubtypeLocale="nb"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
@@ -150,12 +181,30 @@
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="ro"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
android:imeSubtypeLocale="ru"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="sk"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="sl"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
android:imeSubtypeLocale="sr"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
@@ -172,4 +221,16 @@
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="uk"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="vi"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+ />
</input-method>
diff --git a/java/res/xml/spell_checker_settings.xml b/java/res/xml/spell_checker_settings.xml
index f402555c9..222b98b6b 100644
--- a/java/res/xml/spell_checker_settings.xml
+++ b/java/res/xml/spell_checker_settings.xml
@@ -18,9 +18,9 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/android_spell_checker_settings">
<CheckBoxPreference
- android:key="use_proximity"
- android:title="@string/use_proximity_option_title"
- android:summary="@string/use_proximity_option_summary"
+ android:key="pref_spellcheck_use_contacts"
+ android:title="@string/use_contacts_for_spellchecking_option_title"
+ android:summary="@string/use_contacts_for_spellchecking_option_summary"
android:persistent="true"
android:defaultValue="true" />
</PreferenceScreen>
diff --git a/java/res/xml/spellchecker.xml b/java/res/xml/spellchecker.xml
index 30fac5b20..b48dc52cd 100644
--- a/java/res/xml/spellchecker.xml
+++ b/java/res/xml/spellchecker.xml
@@ -21,7 +21,8 @@
<!-- for the spell checker -->
<spell-checker xmlns:android="http://schemas.android.com/apk/res/android"
- android:label="@string/spell_checker_service_name">
+ android:label="@string/spell_checker_service_name"
+ android:settingsActivity="com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsActivity">
<subtype
android:label="@string/subtype_generic"
android:subtypeLocale="en"
@@ -42,4 +43,16 @@
android:label="@string/subtype_generic"
android:subtypeLocale="es"
/>
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="ru"
+ />
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="cs"
+ />
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="nl"
+ />
</spell-checker>
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
index 46663327d..9caed00c9 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
@@ -17,7 +17,6 @@
package com.android.inputmethod.accessibility;
import android.content.Context;
-import android.content.SharedPreferences;
import android.inputmethodservice.InputMethodService;
import android.media.AudioManager;
import android.os.SystemClock;
@@ -55,15 +54,15 @@ public class AccessibilityUtils {
*/
private static final boolean ENABLE_ACCESSIBILITY = true;
- public static void init(InputMethodService inputMethod, SharedPreferences prefs) {
+ public static void init(InputMethodService inputMethod) {
if (!ENABLE_ACCESSIBILITY)
return;
// These only need to be initialized if the kill switch is off.
- sInstance.initInternal(inputMethod, prefs);
- KeyCodeDescriptionMapper.init(inputMethod, prefs);
- AccessibleInputMethodServiceProxy.init(inputMethod, prefs);
- AccessibleKeyboardViewProxy.init(inputMethod, prefs);
+ sInstance.initInternal(inputMethod);
+ KeyCodeDescriptionMapper.init();
+ AccessibleInputMethodServiceProxy.init(inputMethod);
+ AccessibleKeyboardViewProxy.init(inputMethod);
}
public static AccessibilityUtils getInstance() {
@@ -74,7 +73,7 @@ public class AccessibilityUtils {
// This class is not publicly instantiable.
}
- private void initInternal(Context context, SharedPreferences prefs) {
+ private void initInternal(Context context) {
mContext = context;
mAccessibilityManager = (AccessibilityManager) context
.getSystemService(Context.ACCESSIBILITY_SERVICE);
@@ -120,8 +119,8 @@ public class AccessibilityUtils {
*
* @return {@code true} if the device should obscure password characters.
*/
- public boolean shouldObscureInput(EditorInfo attribute) {
- if (attribute == null)
+ public boolean shouldObscureInput(EditorInfo editorInfo) {
+ if (editorInfo == null)
return false;
// The user can optionally force speaking passwords.
@@ -137,7 +136,7 @@ public class AccessibilityUtils {
return false;
// Don't speak if the IME is connected to a password field.
- return InputTypeCompatUtils.isPasswordInputType(attribute.inputType);
+ return InputTypeCompatUtils.isPasswordInputType(editorInfo.inputType);
}
/**
@@ -171,11 +170,11 @@ public class AccessibilityUtils {
* Handles speaking the "connect a headset to hear passwords" notification
* when connecting to a password field.
*
- * @param attribute The input connection's editor info attribute.
+ * @param editorInfo The input connection's editor info attribute.
* @param restarting Whether the connection is being restarted.
*/
- public void onStartInputViewInternal(EditorInfo attribute, boolean restarting) {
- if (shouldObscureInput(attribute)) {
+ public void onStartInputViewInternal(EditorInfo editorInfo, boolean restarting) {
+ if (shouldObscureInput(editorInfo)) {
final CharSequence text = mContext.getText(R.string.spoken_use_headphones);
speak(text);
}
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java
index 4ab9cb898..d834dd10b 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java
@@ -17,7 +17,6 @@
package com.android.inputmethod.accessibility;
import android.content.Context;
-import android.content.SharedPreferences;
import android.inputmethodservice.InputMethodService;
import android.media.AudioManager;
import android.os.Looper;
@@ -82,8 +81,8 @@ public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActi
}
}
- public static void init(InputMethodService inputMethod, SharedPreferences prefs) {
- sInstance.initInternal(inputMethod, prefs);
+ public static void init(InputMethodService inputMethod) {
+ sInstance.initInternal(inputMethod);
}
public static AccessibleInputMethodServiceProxy getInstance() {
@@ -94,7 +93,7 @@ public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActi
// Not publicly instantiable.
}
- private void initInternal(InputMethodService inputMethod, SharedPreferences prefs) {
+ private void initInternal(InputMethodService inputMethod) {
mInputMethod = inputMethod;
mVibrator = (Vibrator) inputMethod.getSystemService(Context.VIBRATOR_SERVICE);
mAudioManager = (AudioManager) inputMethod.getSystemService(Context.AUDIO_SERVICE);
@@ -125,8 +124,6 @@ public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActi
*/
@Override
public void onFlickGesture(int direction) {
- final int keyEventCode;
-
switch (direction) {
case FlickGestureDetector.FLICK_LEFT:
sendDownUpKeyEvents(KeyEvent.KEYCODE_DPAD_LEFT);
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
index cef82267f..9141daaee 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
@@ -17,7 +17,6 @@
package com.android.inputmethod.accessibility;
import android.content.Context;
-import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Paint;
import android.inputmethodservice.InputMethodService;
@@ -29,7 +28,6 @@ import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.compat.AccessibilityEventCompatUtils;
import com.android.inputmethod.compat.MotionEventCompatUtils;
import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.keyboard.KeyDetector;
import com.android.inputmethod.keyboard.LatinKeyboardView;
import com.android.inputmethod.keyboard.PointerTracker;
@@ -42,10 +40,10 @@ public class AccessibleKeyboardViewProxy {
private LatinKeyboardView mView;
private AccessibleKeyboardActionListener mListener;
- private int mLastHoverKeyIndex = KeyDetector.NOT_A_KEY;
+ private Key mLastHoverKey = null;
- public static void init(InputMethodService inputMethod, SharedPreferences prefs) {
- sInstance.initInternal(inputMethod, prefs);
+ public static void init(InputMethodService inputMethod) {
+ sInstance.initInternal(inputMethod);
sInstance.mListener = AccessibleInputMethodServiceProxy.getInstance();
}
@@ -61,7 +59,7 @@ public class AccessibleKeyboardViewProxy {
// Not publicly instantiable.
}
- private void initInternal(InputMethodService inputMethod, SharedPreferences prefs) {
+ private void initInternal(InputMethodService inputMethod) {
final Paint paint = new Paint();
paint.setTextAlign(Paint.Align.LEFT);
paint.setTextSize(14.0f);
@@ -72,8 +70,7 @@ public class AccessibleKeyboardViewProxy {
mGestureDetector = new KeyboardFlickGestureDetector(inputMethod);
}
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event,
- PointerTracker tracker) {
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
if (mView == null) {
Log.e(TAG, "No keyboard view set!");
return false;
@@ -81,7 +78,7 @@ public class AccessibleKeyboardViewProxy {
switch (event.getEventType()) {
case AccessibilityEventCompatUtils.TYPE_VIEW_HOVER_ENTER:
- final Key key = tracker.getKey(mLastHoverKeyIndex);
+ final Key key = mLastHoverKey;
if (key == null)
break;
@@ -130,12 +127,12 @@ public class AccessibleKeyboardViewProxy {
switch (event.getAction()) {
case MotionEventCompatUtils.ACTION_HOVER_ENTER:
case MotionEventCompatUtils.ACTION_HOVER_MOVE:
- final int keyIndex = tracker.getKeyIndexOn(x, y);
+ final Key key = tracker.getKeyOn(x, y);
- if (keyIndex != mLastHoverKeyIndex) {
- fireKeyHoverEvent(tracker, mLastHoverKeyIndex, false);
- mLastHoverKeyIndex = keyIndex;
- fireKeyHoverEvent(tracker, mLastHoverKeyIndex, true);
+ if (key != mLastHoverKey) {
+ fireKeyHoverEvent(mLastHoverKey, false);
+ mLastHoverKey = key;
+ fireKeyHoverEvent(mLastHoverKey, true);
}
return true;
@@ -144,7 +141,7 @@ public class AccessibleKeyboardViewProxy {
return false;
}
- private void fireKeyHoverEvent(PointerTracker tracker, int keyIndex, boolean entering) {
+ private void fireKeyHoverEvent(Key key, boolean entering) {
if (mListener == null) {
Log.e(TAG, "No accessible keyboard action listener set!");
return;
@@ -155,11 +152,6 @@ public class AccessibleKeyboardViewProxy {
return;
}
- if (keyIndex == KeyDetector.NOT_A_KEY)
- return;
-
- final Key key = tracker.getKey(keyIndex);
-
if (key == null)
return;
diff --git a/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java b/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java
index 9d99e3131..db12f76ad 100644
--- a/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java
+++ b/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java
@@ -126,7 +126,6 @@ public abstract class FlickGestureDetector {
}
final float distanceSquare = calculateDistanceSquare(mCachedHoverEnter, event);
- final long timeout = event.getEventTime() - mCachedHoverEnter.getEventTime();
switch (event.getAction()) {
case MotionEventCompatUtils.ACTION_HOVER_MOVE:
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index 7302830d4..efaf58fc2 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -17,7 +17,6 @@
package com.android.inputmethod.accessibility;
import android.content.Context;
-import android.content.SharedPreferences;
import android.text.TextUtils;
import com.android.inputmethod.keyboard.Key;
@@ -45,8 +44,8 @@ public class KeyCodeDescriptionMapper {
// Map of shift-locked key codes to spoken description resource IDs
private final HashMap<Integer, Integer> mShiftLockedKeyCodeMap;
- public static void init(Context context, SharedPreferences prefs) {
- sInstance.initInternal(context, prefs);
+ public static void init() {
+ sInstance.initInternal();
}
public static KeyCodeDescriptionMapper getInstance() {
@@ -60,7 +59,7 @@ public class KeyCodeDescriptionMapper {
mShiftLockedKeyCodeMap = new HashMap<Integer, Integer>();
}
- private void initInternal(Context context, SharedPreferences prefs) {
+ private void initInternal() {
// Manual label substitutions for key labels with no string resource
mKeyLabelMap.put(":-)", R.string.spoken_description_smiley);
@@ -136,16 +135,14 @@ public class KeyCodeDescriptionMapper {
if (!TextUtils.isEmpty(key.mLabel)) {
final String label = key.mLabel.toString().trim();
+ // First, attempt to map the label to a pre-defined description.
if (mKeyLabelMap.containsKey(label)) {
return context.getString(mKeyLabelMap.get(label));
- } else if (label.length() == 1
- || (keyboard.isManualTemporaryUpperCase() && !TextUtils
- .isEmpty(key.mHintLabel))) {
- return getDescriptionForKeyCode(context, keyboard, key, shouldObscure);
- } else {
- return label;
}
- } else if (key.mCode != Keyboard.CODE_DUMMY) {
+ }
+
+ // Just attempt to speak the description.
+ if (key.mCode != Keyboard.CODE_UNSPECIFIED) {
return getDescriptionForKeyCode(context, keyboard, key, shouldObscure);
}
@@ -187,11 +184,14 @@ public class KeyCodeDescriptionMapper {
* @return the key code for the specified key
*/
private int getCorrectKeyCode(Keyboard keyboard, Key key) {
- if (keyboard.isManualTemporaryUpperCase() && !TextUtils.isEmpty(key.mHintLabel)) {
+ // If keyboard is in manual temporary upper case state and key has
+ // manual temporary uppercase letter as key hint letter, alternate
+ // character code should be sent.
+ if (keyboard.isManualTemporaryUpperCase() && key.hasUppercaseLetter()
+ && !TextUtils.isEmpty(key.mHintLabel)) {
return key.mHintLabel.charAt(0);
- } else {
- return key.mCode;
}
+ return key.mCode;
}
/**
diff --git a/java/src/com/android/inputmethod/compat/ArraysCompatUtils.java b/java/src/com/android/inputmethod/compat/ArraysCompatUtils.java
index f6afbcfe2..011473bef 100644
--- a/java/src/com/android/inputmethod/compat/ArraysCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/ArraysCompatUtils.java
@@ -16,10 +16,14 @@
package com.android.inputmethod.compat;
+import android.util.Log;
+
import java.lang.reflect.Method;
import java.util.Arrays;
public class ArraysCompatUtils {
+ private static final String TAG = ArraysCompatUtils.class.getSimpleName();
+
private static final Method METHOD_Arrays_binarySearch = CompatUtils
.getMethod(Arrays.class, "binarySearch", int[].class, int.class, int.class, int.class);
@@ -33,8 +37,15 @@ public class ArraysCompatUtils {
}
}
- /* package */ static int compatBinarySearch(int[] array, int startIndex, int endIndex,
- int value) {
+ // TODO: Implement fast binary search
+ /* package for testing */
+ static int compatBinarySearch(int[] array, int startIndex, int endIndex, int value) {
+ // Output error log because this method has strict performance penalty.
+ // Note that this method has been called only from spell checker and spell checker exists
+ // only from IceCreamSandwich and after, so that there is no chance on pre-ICS device to
+ // invoke this method.
+ Log.e(TAG, "Invoked expensive binarySearch");
+
if (startIndex > endIndex) throw new IllegalArgumentException();
if (startIndex < 0 || endIndex > array.length) throw new ArrayIndexOutOfBoundsException();
diff --git a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
index 51dc4cd37..0e5f8c80a 100644
--- a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
@@ -153,8 +153,7 @@ public class InputMethodManagerCompatWrapper {
return Utils.getInputMethodInfo(this, mLatinImePackageName);
}
- @SuppressWarnings("unused")
- private InputMethodSubtypeCompatWrapper getLastResortSubtype(String mode) {
+ private static InputMethodSubtypeCompatWrapper getLastResortSubtype(String mode) {
if (VOICE_MODE.equals(mode) && !FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES)
return null;
Locale inputLocale = SubtypeSwitcher.getInstance().getInputLocale();
diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
index 161ef09b8..f476d83b4 100644
--- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
+++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
@@ -50,19 +50,19 @@ public class SuggestionSpanUtils {
.getConstructor(CLASS_SuggestionSpan, INPUT_TYPE_SuggestionSpan);
public static final Field FIELD_FLAG_AUTO_CORRECTION
= CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_AUTO_CORRECTION");
- public static final Field FIELD_SUGGESTION_MAX_SIZE
+ public static final Field FIELD_SUGGESTIONS_MAX_SIZE
= CompatUtils.getField(CLASS_SuggestionSpan, "SUGGESTIONS_MAX_SIZE");
public static final Integer OBJ_FLAG_AUTO_CORRECTION = (Integer) CompatUtils
.getFieldValue(null, null, FIELD_FLAG_AUTO_CORRECTION);;
- public static final Integer OBJ_SUGGESTION_MAX_SIZE = (Integer) CompatUtils
- .getFieldValue(null, null, FIELD_SUGGESTION_MAX_SIZE);;
+ public static final Integer OBJ_SUGGESTIONS_MAX_SIZE = (Integer) CompatUtils
+ .getFieldValue(null, null, FIELD_SUGGESTIONS_MAX_SIZE);;
static {
SUGGESTION_SPAN_IS_SUPPORTED =
CLASS_SuggestionSpan != null && CONSTRUCTOR_SuggestionSpan != null;
if (LatinImeLogger.sDBG) {
if (SUGGESTION_SPAN_IS_SUPPORTED
- && (OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTION_MAX_SIZE == null)) {
+ && (OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null)) {
throw new RuntimeException("Field is accidentially null.");
}
}
@@ -71,7 +71,7 @@ public class SuggestionSpanUtils {
public static CharSequence getTextWithAutoCorrectionIndicatorUnderline(
Context context, CharSequence text) {
if (TextUtils.isEmpty(text) || CONSTRUCTOR_SuggestionSpan == null
- || OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTION_MAX_SIZE == null) {
+ || OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null) {
return text;
}
final Spannable spannable = text instanceof Spannable
@@ -94,7 +94,7 @@ public class SuggestionSpanUtils {
if (TextUtils.isEmpty(pickedWord) || CONSTRUCTOR_SuggestionSpan == null
|| suggestedWords == null || suggestedWords.size() == 0
|| suggestedWords.getInfo(0).isObsoleteSuggestedWord()
- || OBJ_SUGGESTION_MAX_SIZE == null) {
+ || OBJ_SUGGESTIONS_MAX_SIZE == null) {
return pickedWord;
}
@@ -106,7 +106,7 @@ public class SuggestionSpanUtils {
}
final ArrayList<String> suggestionsList = new ArrayList<String>();
for (int i = 0; i < suggestedWords.size(); ++i) {
- if (suggestionsList.size() >= OBJ_SUGGESTION_MAX_SIZE) {
+ if (suggestionsList.size() >= OBJ_SUGGESTIONS_MAX_SIZE) {
break;
}
final CharSequence word = suggestedWords.getWord(i);
diff --git a/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java b/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java
new file mode 100644
index 000000000..6a0d4dd9e
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.compat;
+
+import android.view.textservice.SuggestionsInfo;
+
+import java.lang.reflect.Field;
+
+public class SuggestionsInfoCompatUtils {
+ private static final Field FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = CompatUtils.getField(
+ SuggestionsInfo.class, "RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS");
+ private static final Integer OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = (Integer) CompatUtils
+ .getFieldValue(null, null, FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS);;
+ private static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS =
+ OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS != null
+ ? OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS : 0;
+
+ private SuggestionsInfoCompatUtils() {
+ }
+
+ /**
+ * Returns the flag value of the attributes of the suggestions that can be obtained by
+ * {@link #getSuggestionsAttributes}: this tells that the text service thinks
+ * the result suggestions include highly recommended ones.
+ */
+ public static int getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS() {
+ return RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS;
+ }
+}
diff --git a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
index 3f8c2ef8f..a013ebca9 100644
--- a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
+++ b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
@@ -695,12 +695,12 @@ public class VoiceProxy implements VoiceInput.UiListener {
&& !mVoiceInput.isBlacklistedField(fieldContext);
}
- private boolean shouldShowVoiceButton(FieldContext fieldContext, EditorInfo attribute) {
+ private boolean shouldShowVoiceButton(FieldContext fieldContext, EditorInfo editorInfo) {
@SuppressWarnings("deprecation")
final boolean noMic = Utils.inPrivateImeOptions(null,
- LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, attribute)
+ LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)
|| Utils.inPrivateImeOptions(mService.getPackageName(),
- LatinIME.IME_OPTION_NO_MICROPHONE, attribute);
+ LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo);
return ENABLE_VOICE_BUTTON && fieldCanDoVoice(fieldContext) && !noMic
&& SpeechRecognizer.isRecognitionAvailable(mService);
}
@@ -709,7 +709,7 @@ public class VoiceProxy implements VoiceInput.UiListener {
return SpeechRecognizer.isRecognitionAvailable(context);
}
- public void loadSettings(EditorInfo attribute, SharedPreferences sp) {
+ public void loadSettings(EditorInfo editorInfo, SharedPreferences sp) {
if (!VOICE_INSTALLED) {
return;
}
@@ -723,7 +723,7 @@ public class VoiceProxy implements VoiceInput.UiListener {
final String voiceMode = sp.getString(PREF_VOICE_MODE,
mService.getString(R.string.voice_mode_main));
mVoiceButtonEnabled = !voiceMode.equals(mService.getString(R.string.voice_mode_off))
- && shouldShowVoiceButton(makeFieldContext(), attribute);
+ && shouldShowVoiceButton(makeFieldContext(), editorInfo);
mVoiceButtonOnPrimary = voiceMode.equals(mService.getString(R.string.voice_mode_main));
}
diff --git a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java b/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java
index dbe7aec6a..e75e14861 100644
--- a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java
+++ b/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java
@@ -17,7 +17,7 @@
package com.android.inputmethod.deprecated.languageswitcher;
import com.android.inputmethod.compat.SharedPreferencesCompat;
-import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
+import com.android.inputmethod.keyboard.KeyboardSet;
import com.android.inputmethod.latin.DictionaryFactory;
import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.R;
@@ -162,8 +162,8 @@ public class InputLanguageSelection extends PreferenceActivity {
try {
final String localeStr = locale.toString();
- final String[] layoutCountryCodes = KeyboardBuilder.parseKeyboardLocale(
- this, R.xml.kbd_qwerty).split(",", -1);
+ final String[] layoutCountryCodes = KeyboardSet.parseKeyboardLocale(
+ getResources(), R.xml.keyboard_set).split(",", -1);
if (!TextUtils.isEmpty(localeStr) && layoutCountryCodes.length > 0) {
for (String s : layoutCountryCodes) {
if (s.equals(localeStr)) {
diff --git a/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java b/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java
index 3c79cc218..fd2cf3d25 100644
--- a/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java
+++ b/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java
@@ -43,10 +43,10 @@ public class FieldContext {
Bundle mFieldInfo;
- public FieldContext(InputConnection conn, EditorInfo info,
+ public FieldContext(InputConnection conn, EditorInfo editorInfo,
String selectedLanguage, String[] enabledLanguages) {
mFieldInfo = new Bundle();
- addEditorInfoToBundle(info, mFieldInfo);
+ addEditorInfoToBundle(editorInfo, mFieldInfo);
addInputConnectionToBundle(conn, mFieldInfo);
addLanguageInfoToBundle(selectedLanguage, enabledLanguages, mFieldInfo);
if (DBG) Log.i("FieldContext", "Bundle = " + mFieldInfo.toString());
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index f1ae0b313..ebd61505d 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -22,19 +22,20 @@ import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
+import android.util.Log;
import android.util.Xml;
import com.android.inputmethod.keyboard.internal.KeyStyles;
import com.android.inputmethod.keyboard.internal.KeyStyles.KeyStyle;
-import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
-import com.android.inputmethod.keyboard.internal.KeyboardBuilder.ParseException;
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
-import com.android.inputmethod.keyboard.internal.KeyboardParams;
import com.android.inputmethod.keyboard.internal.MoreKeySpecParser;
import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.XmlParseUtils;
import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -42,36 +43,42 @@ import java.util.Map;
* Class for describing the position and characteristics of a single key in the keyboard.
*/
public class Key {
+ private static final String TAG = Key.class.getSimpleName();
+
/**
* The key code (unicode or custom code) that this key generates.
*/
public final int mCode;
+ public final int mAltCode;
/** Label to display */
public final CharSequence mLabel;
/** Hint label to display on the key in conjunction with the label */
public final CharSequence mHintLabel;
- /** Option of the label */
- private final int mLabelOption;
- private static final int LABEL_OPTION_ALIGN_LEFT = 0x01;
- private static final int LABEL_OPTION_ALIGN_RIGHT = 0x02;
- private static final int LABEL_OPTION_ALIGN_LEFT_OF_CENTER = 0x08;
- private static final int LABEL_OPTION_LARGE_LETTER = 0x10;
- private static final int LABEL_OPTION_FONT_NORMAL = 0x20;
- private static final int LABEL_OPTION_FONT_MONO_SPACE = 0x40;
- private static final int LABEL_OPTION_FOLLOW_KEY_LETTER_RATIO = 0x80;
- private static final int LABEL_OPTION_FOLLOW_KEY_HINT_LABEL_RATIO = 0x100;
- private static final int LABEL_OPTION_HAS_POPUP_HINT = 0x200;
- private static final int LABEL_OPTION_HAS_UPPERCASE_LETTER = 0x400;
- private static final int LABEL_OPTION_HAS_HINT_LABEL = 0x800;
- private static final int LABEL_OPTION_WITH_ICON_LEFT = 0x1000;
- private static final int LABEL_OPTION_WITH_ICON_RIGHT = 0x2000;
- private static final int LABEL_OPTION_AUTO_X_SCALE = 0x4000;
-
+ /** Flags of the label */
+ private final int mLabelFlags;
+ private static final int LABEL_FLAGS_ALIGN_LEFT = 0x01;
+ private static final int LABEL_FLAGS_ALIGN_RIGHT = 0x02;
+ private static final int LABEL_FLAGS_ALIGN_LEFT_OF_CENTER = 0x08;
+ private static final int LABEL_FLAGS_LARGE_LETTER = 0x10;
+ private static final int LABEL_FLAGS_FONT_NORMAL = 0x20;
+ private static final int LABEL_FLAGS_FONT_MONO_SPACE = 0x40;
+ private static final int LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO = 0x80;
+ private static final int LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO = 0x100;
+ private static final int LABEL_FLAGS_HAS_POPUP_HINT = 0x200;
+ private static final int LABEL_FLAGS_HAS_UPPERCASE_LETTER = 0x400;
+ private static final int LABEL_FLAGS_HAS_HINT_LABEL = 0x800;
+ private static final int LABEL_FLAGS_WITH_ICON_LEFT = 0x1000;
+ private static final int LABEL_FLAGS_WITH_ICON_RIGHT = 0x2000;
+ private static final int LABEL_FLAGS_AUTO_X_SCALE = 0x4000;
+
+ // TODO: These icon references could be int (icon attribute id)
/** Icon to display instead of a label. Icon takes precedence over a label */
private Drawable mIcon;
+ /** Icon for disabled state */
+ private Drawable mDisabledIcon;
/** Preview version of the icon, for the preview popup */
- private Drawable mPreviewIcon;
+ public final Drawable mPreviewIcon;
/** Width of the key, not including the gap */
public final int mWidth;
@@ -105,8 +112,12 @@ public class Key {
public static final int BACKGROUND_TYPE_ACTION = 2;
public static final int BACKGROUND_TYPE_STICKY = 3;
- /** Whether this key repeats itself when held down */
- public final boolean mRepeatable;
+ private final int mActionFlags;
+ private static final int ACTION_FLAGS_IS_REPEATABLE = 0x01;
+ private static final int ACTION_FLAGS_NO_KEY_PREVIEW = 0x02;
+ private static final int ACTION_FLAGS_ALT_CODE_WHILE_TYPING = 0x04;
+
+ private final int mHashCode;
/** The current pressed state of this key */
private boolean mPressed;
@@ -114,8 +125,6 @@ public class Key {
private boolean mHighlightOn;
/** Key is enabled and responds on press */
private boolean mEnabled = true;
- /** Whether this key needs to show the "..." popup hint for special purposes */
- private boolean mNeedsSpecialPopupHint;
// RTL parenthesis character swapping map.
private static final Map<Integer, Integer> sRtlParenthesisMap = new HashMap<Integer, Integer>();
@@ -151,19 +160,19 @@ public class Key {
}
}
- private static int getCode(Resources res, KeyboardParams params, String moreKeySpec) {
+ private static int getCode(Resources res, Keyboard.Params params, String moreKeySpec) {
return getRtlParenthesisCode(
MoreKeySpecParser.getCode(res, moreKeySpec), params.mIsRtlKeyboard);
}
- private static Drawable getIcon(KeyboardParams params, String moreKeySpec) {
- return params.mIconsSet.getIcon(MoreKeySpecParser.getIconId(moreKeySpec));
+ private static Drawable getIcon(Keyboard.Params params, String moreKeySpec) {
+ return params.mIconsSet.getIconByIconId(MoreKeySpecParser.getIconId(moreKeySpec));
}
/**
* This constructor is being used only for key in more keys keyboard.
*/
- public Key(Resources res, KeyboardParams params, String moreKeySpec,
+ public Key(Resources res, Keyboard.Params params, String moreKeySpec,
int x, int y, int width, int height) {
this(params, MoreKeySpecParser.getLabel(moreKeySpec), null, getIcon(params, moreKeySpec),
getCode(res, params, moreKeySpec), MoreKeySpecParser.getOutputText(moreKeySpec),
@@ -173,7 +182,7 @@ public class Key {
/**
* This constructor is being used only for key in popup suggestions pane.
*/
- public Key(KeyboardParams params, CharSequence label, CharSequence hintLabel, Drawable icon,
+ public Key(Keyboard.Params params, CharSequence label, CharSequence hintLabel, Drawable icon,
int code, CharSequence outputText, int x, int y, int width, int height) {
mHeight = height - params.mVerticalGap;
mHorizontalGap = params.mHorizontalGap;
@@ -181,19 +190,24 @@ public class Key {
mVisualInsetsLeft = mVisualInsetsRight = 0;
mWidth = width - mHorizontalGap;
mHintLabel = hintLabel;
- mLabelOption = 0;
+ mLabelFlags = 0;
mBackgroundType = BACKGROUND_TYPE_NORMAL;
- mRepeatable = false;
+ mActionFlags = 0;
mMoreKeys = null;
mMaxMoreKeysColumn = 0;
mLabel = label;
mOutputText = outputText;
mCode = code;
+ mAltCode = Keyboard.CODE_UNSPECIFIED;
mIcon = icon;
+ mDisabledIcon = null;
+ mPreviewIcon = null;
// Horizontal gap is divided equally to both sides of the key.
mX = x + mHorizontalGap / 2;
mY = y;
mHitBox.set(x, y, x + width + 1, y + height);
+
+ mHashCode = hashCode(this);
}
/**
@@ -205,9 +219,10 @@ public class Key {
* this key.
* @param parser the XML parser containing the attributes for this key
* @param keyStyles active key styles set
+ * @throws XmlPullParserException
*/
- public Key(Resources res, KeyboardParams params, KeyboardBuilder.Row row,
- XmlPullParser parser, KeyStyles keyStyles) {
+ public Key(Resources res, Keyboard.Params params, Keyboard.Builder.Row row,
+ XmlPullParser parser, KeyStyles keyStyles) throws XmlPullParserException {
final float horizontalGap = isSpacer() ? 0 : params.mHorizontalGap;
final int keyHeight = row.mRowHeight;
mVerticalGap = params.mVerticalGap;
@@ -221,9 +236,10 @@ public class Key {
String styleName = keyAttr.getString(R.styleable.Keyboard_Key_keyStyle);
style = keyStyles.getKeyStyle(styleName);
if (style == null)
- throw new ParseException("Unknown key style: " + styleName, parser);
+ throw new XmlParseUtils.ParseException(
+ "Unknown key style: " + styleName, parser);
} else {
- style = keyStyles.getEmptyKeyStyle();
+ style = KeyStyles.getEmptyKeyStyle();
}
final float keyXPos = row.getKeyX(keyAttr);
@@ -254,58 +270,107 @@ public class Key {
mBackgroundType = style.getInt(keyAttr,
R.styleable.Keyboard_Key_backgroundType, BACKGROUND_TYPE_NORMAL);
- mRepeatable = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isRepeatable, false);
- mEnabled = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_enabled, true);
+ mActionFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyActionFlags, 0);
final KeyboardIconsSet iconsSet = params.mIconsSet;
- mVisualInsetsLeft = (int) KeyboardBuilder.getDimensionOrFraction(keyAttr,
+ mVisualInsetsLeft = (int) Keyboard.Builder.getDimensionOrFraction(keyAttr,
R.styleable.Keyboard_Key_visualInsetsLeft, params.mBaseWidth, 0);
- mVisualInsetsRight = (int) KeyboardBuilder.getDimensionOrFraction(keyAttr,
+ mVisualInsetsRight = (int) Keyboard.Builder.getDimensionOrFraction(keyAttr,
R.styleable.Keyboard_Key_visualInsetsRight, params.mBaseWidth, 0);
- mPreviewIcon = iconsSet.getIcon(style.getInt(keyAttr,
+ mPreviewIcon = iconsSet.getIconByIconId(style.getInt(keyAttr,
R.styleable.Keyboard_Key_keyIconPreview, KeyboardIconsSet.ICON_UNDEFINED));
- mIcon = iconsSet.getIcon(style.getInt(keyAttr, R.styleable.Keyboard_Key_keyIcon,
- KeyboardIconsSet.ICON_UNDEFINED));
- final int shiftedIconId = style.getInt(keyAttr, R.styleable.Keyboard_Key_keyIconShifted,
- KeyboardIconsSet.ICON_UNDEFINED);
- if (shiftedIconId != KeyboardIconsSet.ICON_UNDEFINED) {
- final Drawable shiftedIcon = iconsSet.getIcon(shiftedIconId);
- params.addShiftedIcon(this, shiftedIcon);
- }
+ mIcon = iconsSet.getIconByIconId(style.getInt(keyAttr,
+ R.styleable.Keyboard_Key_keyIcon, KeyboardIconsSet.ICON_UNDEFINED));
+ mDisabledIcon = iconsSet.getIconByIconId(style.getInt(keyAttr,
+ R.styleable.Keyboard_Key_keyIconDisabled, KeyboardIconsSet.ICON_UNDEFINED));
mHintLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
mLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyLabel);
- mLabelOption = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelOption, 0);
+ mLabelFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags, 0);
mOutputText = style.getText(keyAttr, R.styleable.Keyboard_Key_keyOutputText);
// Choose the first letter of the label as primary code if not
// specified.
final int code = style.getInt(keyAttr, R.styleable.Keyboard_Key_code,
Keyboard.CODE_UNSPECIFIED);
- if (code == Keyboard.CODE_UNSPECIFIED && !TextUtils.isEmpty(mLabel)) {
+ if (code == Keyboard.CODE_UNSPECIFIED && mOutputText == null
+ && !TextUtils.isEmpty(mLabel)) {
+ if (mLabel.length() != 1) {
+ Log.w(TAG, "Label is not a single letter: label=" + mLabel);
+ }
final int firstChar = mLabel.charAt(0);
mCode = getRtlParenthesisCode(firstChar, params.mIsRtlKeyboard);
- } else if (code != Keyboard.CODE_UNSPECIFIED) {
- mCode = code;
+ } else if (code == Keyboard.CODE_UNSPECIFIED && mOutputText != null) {
+ mCode = Keyboard.CODE_OUTPUT_TEXT;
} else {
- mCode = Keyboard.CODE_DUMMY;
+ mCode = code;
}
+ mAltCode = style.getInt(keyAttr,
+ R.styleable.Keyboard_Key_altCode, Keyboard.CODE_UNSPECIFIED);
+ mHashCode = hashCode(this);
keyAttr.recycle();
}
- public void markAsLeftEdge(KeyboardParams params) {
+ private static int hashCode(Key key) {
+ return Arrays.hashCode(new Object[] {
+ key.mX,
+ key.mY,
+ key.mWidth,
+ key.mHeight,
+ key.mCode,
+ key.mLabel,
+ key.mHintLabel,
+ // Key can be distinguishable without the following members.
+ // key.mAltCode,
+ // key.mOutputText,
+ // key.mActionFlags,
+ // key.mLabelFlags,
+ // key.mIcon,
+ // key.mPreviewIcon,
+ // key.mBackgroundType,
+ // key.mHorizontalGap,
+ // key.mVerticalGap,
+ // key.mVisualInsetLeft,
+ // key.mVisualInsetRight,
+ // Arrays.hashCode(key.mMoreKeys),
+ // key.mMaxMoreKeysColumn,
+ });
+ }
+
+ private boolean equals(Key o) {
+ if (this == o) return true;
+ return o.mX == mX
+ && o.mY == mY
+ && o.mWidth == mWidth
+ && o.mHeight == mHeight
+ && o.mCode == mCode
+ && TextUtils.equals(o.mLabel, mLabel)
+ && TextUtils.equals(o.mHintLabel, mHintLabel);
+ }
+
+ @Override
+ public int hashCode() {
+ return mHashCode;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof Key && equals((Key)o);
+ }
+
+ public void markAsLeftEdge(Keyboard.Params params) {
mHitBox.left = params.mHorizontalEdgesPadding;
}
- public void markAsRightEdge(KeyboardParams params) {
+ public void markAsRightEdge(Keyboard.Params params) {
mHitBox.right = params.mOccupiedWidth - params.mHorizontalEdgesPadding;
}
- public void markAsTopEdge(KeyboardParams params) {
+ public void markAsTopEdge(Keyboard.Params params) {
mHitBox.top = params.mTopPadding;
}
- public void markAsBottomEdge(KeyboardParams params) {
+ public void markAsBottomEdge(Keyboard.Params params) {
mHitBox.bottom = params.mOccupiedHeight + params.mBottomPadding;
}
@@ -317,11 +382,31 @@ public class Key {
return false;
}
+ public boolean isShift() {
+ return mCode == Keyboard.CODE_SHIFT;
+ }
+
+ public boolean isModifier() {
+ return mCode == Keyboard.CODE_SHIFT || mCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL;
+ }
+
+ public boolean isRepeatable() {
+ return (mActionFlags & ACTION_FLAGS_IS_REPEATABLE) != 0;
+ }
+
+ public boolean noKeyPreview() {
+ return (mActionFlags & ACTION_FLAGS_NO_KEY_PREVIEW) != 0;
+ }
+
+ public boolean altCodeWhileTyping() {
+ return (mActionFlags & ACTION_FLAGS_ALT_CODE_WHILE_TYPING) != 0;
+ }
+
public Typeface selectTypeface(Typeface defaultTypeface) {
// TODO: Handle "bold" here too?
- if ((mLabelOption & LABEL_OPTION_FONT_NORMAL) != 0) {
+ if ((mLabelFlags & LABEL_FLAGS_FONT_NORMAL) != 0) {
return Typeface.DEFAULT;
- } else if ((mLabelOption & LABEL_OPTION_FONT_MONO_SPACE) != 0) {
+ } else if ((mLabelFlags & LABEL_FLAGS_FONT_MONO_SPACE) != 0) {
return Typeface.MONOSPACE;
} else {
return defaultTypeface;
@@ -330,12 +415,12 @@ public class Key {
public int selectTextSize(int letter, int largeLetter, int label, int hintLabel) {
if (mLabel.length() > 1
- && (mLabelOption & (LABEL_OPTION_FOLLOW_KEY_LETTER_RATIO
- | LABEL_OPTION_FOLLOW_KEY_HINT_LABEL_RATIO)) == 0) {
+ && (mLabelFlags & (LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO
+ | LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO)) == 0) {
return label;
- } else if ((mLabelOption & LABEL_OPTION_FOLLOW_KEY_HINT_LABEL_RATIO) != 0) {
+ } else if ((mLabelFlags & LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO) != 0) {
return hintLabel;
- } else if ((mLabelOption & LABEL_OPTION_LARGE_LETTER) != 0) {
+ } else if ((mLabelFlags & LABEL_FLAGS_LARGE_LETTER) != 0) {
return largeLetter;
} else {
return letter;
@@ -343,65 +428,50 @@ public class Key {
}
public boolean isAlignLeft() {
- return (mLabelOption & LABEL_OPTION_ALIGN_LEFT) != 0;
+ return (mLabelFlags & LABEL_FLAGS_ALIGN_LEFT) != 0;
}
public boolean isAlignRight() {
- return (mLabelOption & LABEL_OPTION_ALIGN_RIGHT) != 0;
+ return (mLabelFlags & LABEL_FLAGS_ALIGN_RIGHT) != 0;
}
public boolean isAlignLeftOfCenter() {
- return (mLabelOption & LABEL_OPTION_ALIGN_LEFT_OF_CENTER) != 0;
+ return (mLabelFlags & LABEL_FLAGS_ALIGN_LEFT_OF_CENTER) != 0;
}
public boolean hasPopupHint() {
- return (mLabelOption & LABEL_OPTION_HAS_POPUP_HINT) != 0;
- }
-
- public void setNeedsSpecialPopupHint(boolean needsSpecialPopupHint) {
- mNeedsSpecialPopupHint = needsSpecialPopupHint;
- }
-
- public boolean needsSpecialPopupHint() {
- return mNeedsSpecialPopupHint;
+ return (mLabelFlags & LABEL_FLAGS_HAS_POPUP_HINT) != 0;
}
public boolean hasUppercaseLetter() {
- return (mLabelOption & LABEL_OPTION_HAS_UPPERCASE_LETTER) != 0;
+ return (mLabelFlags & LABEL_FLAGS_HAS_UPPERCASE_LETTER) != 0;
}
public boolean hasHintLabel() {
- return (mLabelOption & LABEL_OPTION_HAS_HINT_LABEL) != 0;
+ return (mLabelFlags & LABEL_FLAGS_HAS_HINT_LABEL) != 0;
}
public boolean hasLabelWithIconLeft() {
- return (mLabelOption & LABEL_OPTION_WITH_ICON_LEFT) != 0;
+ return (mLabelFlags & LABEL_FLAGS_WITH_ICON_LEFT) != 0;
}
public boolean hasLabelWithIconRight() {
- return (mLabelOption & LABEL_OPTION_WITH_ICON_RIGHT) != 0;
+ return (mLabelFlags & LABEL_FLAGS_WITH_ICON_RIGHT) != 0;
}
public boolean needsXScale() {
- return (mLabelOption & LABEL_OPTION_AUTO_X_SCALE) != 0;
+ return (mLabelFlags & LABEL_FLAGS_AUTO_X_SCALE) != 0;
}
public Drawable getIcon() {
- return mIcon;
- }
-
- public Drawable getPreviewIcon() {
- return mPreviewIcon;
+ return mEnabled ? mIcon : mDisabledIcon;
}
+ // TODO: Get rid of this method.
public void setIcon(Drawable icon) {
mIcon = icon;
}
- public void setPreviewIcon(Drawable icon) {
- mPreviewIcon = icon;
- }
-
/**
* Informs the key that it has been pressed, in case it needs to change its appearance or
* state.
@@ -436,9 +506,9 @@ public class Key {
* Detects if a point falls on this key.
* @param x the x-coordinate of the point
* @param y the y-coordinate of the point
- * @return whether or not the point falls on the key. If the key is attached to an edge, it will
- * assume that all points between the key and the edge are considered to be on the key.
- * @see {@link #markAsLeftEdge(KeyboardParams)} etc.
+ * @return whether or not the point falls on the key. If the key is attached to an edge, it
+ * will assume that all points between the key and the edge are considered to be on the key.
+ * @see #markAsLeftEdge(Keyboard.Params) etc.
*/
public boolean isOnKey(int x, int y) {
return mHitBox.contains(x, y);
@@ -536,16 +606,16 @@ public class Key {
}
public static class Spacer extends Key {
- public Spacer(Resources res, KeyboardParams params, KeyboardBuilder.Row row,
- XmlPullParser parser, KeyStyles keyStyles) {
+ public Spacer(Resources res, Keyboard.Params params, Keyboard.Builder.Row row,
+ XmlPullParser parser, KeyStyles keyStyles) throws XmlPullParserException {
super(res, params, row, parser, keyStyles);
}
/**
* This constructor is being used only for divider in more keys keyboard.
*/
- public Spacer(KeyboardParams params, Drawable icon, int x, int y, int width, int height) {
- super(params, null, null, icon, Keyboard.CODE_DUMMY, null, x, y, width, height);
+ public Spacer(Keyboard.Params params, Drawable icon, int x, int y, int width, int height) {
+ super(params, null, null, icon, Keyboard.CODE_UNSPECIFIED, null, x, y, width, height);
}
@Override
diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
index 3298c41cf..0d271625b 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
@@ -19,14 +19,12 @@ package com.android.inputmethod.keyboard;
import android.util.Log;
import java.util.Arrays;
-import java.util.List;
public class KeyDetector {
private static final String TAG = KeyDetector.class.getSimpleName();
private static final boolean DEBUG = false;
public static final int NOT_A_CODE = -1;
- public static final int NOT_A_KEY = -1;
private final int mKeyHysteresisDistanceSquared;
@@ -39,7 +37,7 @@ public class KeyDetector {
// working area
private static final int MAX_NEARBY_KEYS = 12;
private final int[] mDistances = new int[MAX_NEARBY_KEYS];
- private final int[] mIndices = new int[MAX_NEARBY_KEYS];
+ private final Key[] mNeighborKeys = new Key[MAX_NEARBY_KEYS];
/**
* This class handles key detection.
@@ -96,22 +94,22 @@ public class KeyDetector {
}
/**
- * Computes maximum size of the array that can contain all nearby key indices returned by
- * {@link #getKeyIndexAndNearbyCodes}.
+ * Computes maximum size of the array that can contain all nearby key codes returned by
+ * {@link #getKeyAndNearbyCodes}.
*
- * @return Returns maximum size of the array that can contain all nearby key indices returned
- * by {@link #getKeyIndexAndNearbyCodes}.
+ * @return Returns maximum size of the array that can contain all nearby key codes returned
+ * by {@link #getKeyAndNearbyCodes}.
*/
protected int getMaxNearbyKeys() {
return MAX_NEARBY_KEYS;
}
/**
- * Allocates array that can hold all key indices returned by {@link #getKeyIndexAndNearbyCodes}
+ * Allocates array that can hold all key codes returned by {@link #getKeyAndNearbyCodes}
* method. The maximum size of the array should be computed by {@link #getMaxNearbyKeys}.
*
- * @return Allocates and returns an array that can hold all key indices returned by
- * {@link #getKeyIndexAndNearbyCodes} method. All elements in the returned array are
+ * @return Allocates and returns an array that can hold all key codes returned by
+ * {@link #getKeyAndNearbyCodes} method. All elements in the returned array are
* initialized by {@link #NOT_A_CODE} value.
*/
public int[] newCodeArray() {
@@ -122,7 +120,7 @@ public class KeyDetector {
private void initializeNearbyKeys() {
Arrays.fill(mDistances, Integer.MAX_VALUE);
- Arrays.fill(mIndices, NOT_A_KEY);
+ Arrays.fill(mNeighborKeys, null);
}
/**
@@ -130,14 +128,14 @@ public class KeyDetector {
* If the distance of two keys are the same, the key which the point is on should be considered
* as a closer one.
*
- * @param keyIndex index of the key.
+ * @param key the key to be inserted into the nearby keys buffer.
* @param distance distance between the key's edge and user touched point.
* @param isOnKey true if the point is on the key.
* @return order of the key in the nearby buffer, 0 if it is the nearest key.
*/
- private int sortNearbyKeys(int keyIndex, int distance, boolean isOnKey) {
+ private int sortNearbyKeys(Key key, int distance, boolean isOnKey) {
final int[] distances = mDistances;
- final int[] indices = mIndices;
+ final Key[] neighborKeys = mNeighborKeys;
for (int insertPos = 0; insertPos < distances.length; insertPos++) {
final int comparingDistance = distances[insertPos];
if (distance < comparingDistance || (distance == comparingDistance && isOnKey)) {
@@ -145,11 +143,11 @@ public class KeyDetector {
if (nextPos < distances.length) {
System.arraycopy(distances, insertPos, distances, nextPos,
distances.length - nextPos);
- System.arraycopy(indices, insertPos, indices, nextPos,
- indices.length - nextPos);
+ System.arraycopy(neighborKeys, insertPos, neighborKeys, nextPos,
+ neighborKeys.length - nextPos);
}
distances[insertPos] = distance;
- indices[insertPos] = keyIndex;
+ neighborKeys[insertPos] = key;
return insertPos;
}
}
@@ -157,21 +155,20 @@ public class KeyDetector {
}
private void getNearbyKeyCodes(final int[] allCodes) {
- final List<Key> keys = getKeyboard().mKeys;
- final int[] indices = mIndices;
+ final Key[] neighborKeys = mNeighborKeys;
// allCodes[0] should always have the key code even if it is a non-letter key.
- if (indices[0] == NOT_A_KEY) {
+ if (neighborKeys[0] == null) {
allCodes[0] = NOT_A_CODE;
return;
}
int numCodes = 0;
- for (int j = 0; j < indices.length && numCodes < allCodes.length; j++) {
- final int index = indices[j];
- if (index == NOT_A_KEY)
+ for (int j = 0; j < neighborKeys.length && numCodes < allCodes.length; j++) {
+ final Key key = neighborKeys[j];
+ if (key == null)
break;
- final int code = keys.get(index).mCode;
+ final int code = key.mCode;
// filter out a non-letter key from nearby keys
if (code < Keyboard.CODE_SPACE)
continue;
@@ -180,31 +177,30 @@ public class KeyDetector {
}
/**
- * Finds all possible nearby key indices around a touch event point and returns the nearest key
- * index. The algorithm to determine the nearby keys depends on the threshold set by
+ * Finds all possible nearby key codes around a touch event point and returns the nearest key.
+ * The algorithm to determine the nearby keys depends on the threshold set by
* {@link #setProximityThreshold(int)} and the mode set by
* {@link #setProximityCorrectionEnabled(boolean)}.
*
* @param x The x-coordinate of a touch point
* @param y The y-coordinate of a touch point
- * @param allCodes All nearby key code except functional key are returned in this array
- * @return The nearest key index
+ * @param allCodes All nearby key codes except functional key are returned in this array
+ * @return The nearest key
*/
- public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) {
- final List<Key> keys = getKeyboard().mKeys;
+ public Key getKeyAndNearbyCodes(int x, int y, final int[] allCodes) {
final int touchX = getTouchX(x);
final int touchY = getTouchY(y);
initializeNearbyKeys();
- int primaryIndex = NOT_A_KEY;
- for (final int index : mKeyboard.getNearestKeys(touchX, touchY)) {
- final Key key = keys.get(index);
+ Key primaryKey = null;
+ for (final Key key: mKeyboard.getNearestKeys(touchX, touchY)) {
final boolean isOnKey = key.isOnKey(touchX, touchY);
final int distance = key.squaredDistanceToEdge(touchX, touchY);
if (isOnKey || (mProximityCorrectOn && distance < mProximityThresholdSquare)) {
- final int insertedPosition = sortNearbyKeys(index, distance, isOnKey);
- if (insertedPosition == 0 && isOnKey)
- primaryIndex = index;
+ final int insertedPosition = sortNearbyKeys(key, distance, isOnKey);
+ if (insertedPosition == 0 && isOnKey) {
+ primaryKey = key;
+ }
}
}
@@ -212,12 +208,25 @@ public class KeyDetector {
getNearbyKeyCodes(allCodes);
if (DEBUG) {
Log.d(TAG, "x=" + x + " y=" + y
- + " primary="
- + (primaryIndex == NOT_A_KEY ? "none" : keys.get(primaryIndex).mCode)
- + " codes=" + Arrays.toString(allCodes));
+ + " primary=" + printableCode(primaryKey)
+ + " codes=" + printableCodes(allCodes));
}
}
- return primaryIndex;
+ return primaryKey;
+ }
+
+ public static String printableCode(Key key) {
+ return key != null ? Keyboard.printableCode(key.mCode) : "none";
+ }
+
+ public static String printableCodes(int[] codes) {
+ final StringBuilder sb = new StringBuilder();
+ for (final int code : codes) {
+ if (code == NOT_A_CODE) break;
+ if (sb.length() > 0) sb.append(", ");
+ sb.append(code);
+ }
+ return "[" + sb + "]";
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 4578507fc..c1d024cef 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -16,15 +16,33 @@
package com.android.inputmethod.keyboard;
-import android.graphics.drawable.Drawable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
+import android.util.Xml;
+import android.view.InflateException;
+import com.android.inputmethod.compat.EditorInfoCompatUtils;
+import com.android.inputmethod.keyboard.internal.KeyStyles;
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
-import com.android.inputmethod.keyboard.internal.KeyboardParams;
import com.android.inputmethod.keyboard.internal.KeyboardShiftState;
+import com.android.inputmethod.latin.LatinImeLogger;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.XmlParseUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.Arrays;
import java.util.Collections;
-import java.util.List;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -47,7 +65,11 @@ import java.util.Set;
* </pre>
*/
public class Keyboard {
- /** Some common keys code. These should be aligned with values/keycodes.xml */
+ private static final String TAG = Keyboard.class.getSimpleName();
+
+ /** Some common keys code. Must be positive.
+ * These should be aligned with values/keycodes.xml
+ */
public static final int CODE_ENTER = '\n';
public static final int CODE_TAB = '\t';
public static final int CODE_SPACE = ' ';
@@ -64,20 +86,20 @@ public class Keyboard {
public static final int CODE_CLOSING_ANGLE_BRACKET = '>';
public static final int CODE_DIGIT0 = '0';
public static final int CODE_PLUS = '+';
+ private static final int MINIMUM_LETTER_CODE = CODE_TAB;
-
- /** Special keys code. These should be aligned with values/keycodes.xml */
- public static final int CODE_DUMMY = 0;
+ /** Special keys code. Must be negative.
+ * These should be aligned with values/keycodes.xml
+ */
public static final int CODE_SHIFT = -1;
public static final int CODE_SWITCH_ALPHA_SYMBOL = -2;
public static final int CODE_CAPSLOCK = -3;
- public static final int CODE_CANCEL = -4;
+ public static final int CODE_OUTPUT_TEXT = -4;
public static final int CODE_DELETE = -5;
public static final int CODE_SETTINGS = -6;
public static final int CODE_SHORTCUT = -7;
- public static final int CODE_HAPTIC_AND_AUDIO_FEEDBACK_ONLY = -98;
// Code value representing the code is not specified.
- public static final int CODE_UNSPECIFIED = -99;
+ public static final int CODE_UNSPECIFIED = -9;
public final KeyboardId mId;
public final int mThemeId;
@@ -105,18 +127,19 @@ public class Keyboard {
public final boolean mIsRtlKeyboard;
/** List of keys and icons in this keyboard */
- public final List<Key> mKeys;
- public final List<Key> mShiftKeys;
+ public final Set<Key> mKeys;
+ public final Set<Key> mShiftKeys;
public final Set<Key> mShiftLockKeys;
- public final Map<Key, Drawable> mShiftedIcons;
- public final Map<Key, Drawable> mUnshiftedIcons;
public final KeyboardIconsSet mIconsSet;
- private final KeyboardShiftState mShiftState = new KeyboardShiftState();
+ private final Map<Integer, Key> mKeyCache = new HashMap<Integer, Key>();
private final ProximityInfo mProximityInfo;
- public Keyboard(KeyboardParams params) {
+ // TODO: Remove this variable.
+ private final KeyboardShiftState mShiftState = new KeyboardShiftState();
+
+ public Keyboard(Params params) {
mId = params.mId;
mThemeId = params.mThemeId;
mOccupiedHeight = params.mOccupiedHeight;
@@ -130,11 +153,9 @@ public class Keyboard {
mTopPadding = params.mTopPadding;
mVerticalGap = params.mVerticalGap;
- mKeys = Collections.unmodifiableList(params.mKeys);
- mShiftKeys = Collections.unmodifiableList(params.mShiftKeys);
+ mKeys = Collections.unmodifiableSet(params.mKeys);
+ mShiftKeys = Collections.unmodifiableSet(params.mShiftKeys);
mShiftLockKeys = Collections.unmodifiableSet(params.mShiftLockKeys);
- mShiftedIcons = Collections.unmodifiableMap(params.mShiftedIcons);
- mUnshiftedIcons = Collections.unmodifiableMap(params.mUnshiftedIcons);
mIconsSet = params.mIconsSet;
mProximityInfo = new ProximityInfo(
@@ -146,111 +167,1084 @@ public class Keyboard {
return mProximityInfo;
}
- public boolean hasShiftLockKey() {
+ public Key getKey(int code) {
+ if (code == CODE_UNSPECIFIED) {
+ return null;
+ }
+ final Integer keyCode = code;
+ if (mKeyCache.containsKey(keyCode)) {
+ return mKeyCache.get(keyCode);
+ }
+
+ for (final Key key : mKeys) {
+ if (key.mCode == code) {
+ mKeyCache.put(keyCode, key);
+ return key;
+ }
+ }
+ mKeyCache.put(keyCode, null);
+ return null;
+ }
+
+ // TODO: Remove this method.
+ boolean hasShiftLockKey() {
return !mShiftLockKeys.isEmpty();
}
- public boolean setShiftLocked(boolean newShiftLockState) {
+ // TODO: Remove this method.
+ void setShiftLocked(boolean newShiftLockState) {
for (final Key key : mShiftLockKeys) {
// To represent "shift locked" state. The highlight is handled by background image that
// might be a StateListDrawable.
key.setHighlightOn(newShiftLockState);
- // To represent "shifted" state. The key might have a shifted icon.
- if (newShiftLockState && mShiftedIcons.containsKey(key)) {
- key.setIcon(mShiftedIcons.get(key));
- } else {
- key.setIcon(mUnshiftedIcons.get(key));
- }
+ final int attrId = newShiftLockState
+ ? R.styleable.Keyboard_iconShiftKeyShifted
+ : R.styleable.Keyboard_iconShiftKey;
+ key.setIcon(mIconsSet.getIconByAttrId(attrId));
}
mShiftState.setShiftLocked(newShiftLockState);
- return true;
}
+ // TODO: Move this method to KeyboardId.
public boolean isShiftLocked() {
return mShiftState.isShiftLocked();
}
- public boolean isShiftLockShifted() {
- return mShiftState.isShiftLockShifted();
- }
-
- public boolean setShifted(boolean newShiftState) {
+ private void setShiftKeyGraphics(boolean newShiftState) {
+ if (mShiftState.isShiftLocked()) {
+ return;
+ }
for (final Key key : mShiftKeys) {
- if (!newShiftState && !mShiftState.isShiftLocked()) {
- key.setIcon(mUnshiftedIcons.get(key));
- } else if (newShiftState && !mShiftState.isShiftedOrShiftLocked()) {
- key.setIcon(mShiftedIcons.get(key));
- }
+ final int attrId = newShiftState
+ ? R.styleable.Keyboard_iconShiftKeyShifted
+ : R.styleable.Keyboard_iconShiftKey;
+ key.setIcon(mIconsSet.getIconByAttrId(attrId));
}
- return mShiftState.setShifted(newShiftState);
}
+ // TODO: Remove this method.
+ void setShifted(boolean newShiftState) {
+ setShiftKeyGraphics(newShiftState);
+ mShiftState.setShifted(newShiftState);
+ }
+
+ // TODO: Move this method to KeyboardId.
public boolean isShiftedOrShiftLocked() {
return mShiftState.isShiftedOrShiftLocked();
}
- public void setAutomaticTemporaryUpperCase() {
- setShifted(true);
+ // TODO: Remove this method
+ void setAutomaticTemporaryUpperCase() {
+ setShiftKeyGraphics(true);
mShiftState.setAutomaticTemporaryUpperCase();
}
- public boolean isAutomaticTemporaryUpperCase() {
- return isAlphaKeyboard() && mShiftState.isAutomaticTemporaryUpperCase();
- }
-
+ // TODO: Move this method to KeyboardId.
public boolean isManualTemporaryUpperCase() {
- return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCase();
+ return mShiftState.isManualTemporaryUpperCase();
}
- public boolean isManualTemporaryUpperCaseFromAuto() {
- return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCaseFromAuto();
+ // TODO: Remove this method.
+ public CharSequence adjustLabelCase(CharSequence label) {
+ if (mId.isAlphabetKeyboard() && isShiftedOrShiftLocked() && !TextUtils.isEmpty(label)
+ && label.length() < 3 && Character.isLowerCase(label.charAt(0))) {
+ return label.toString().toUpperCase(mId.mLocale);
+ }
+ return label;
}
- public KeyboardShiftState getKeyboardShiftState() {
- return mShiftState;
+ public static boolean isLetterCode(int code) {
+ return code >= MINIMUM_LETTER_CODE;
}
- public boolean isAlphaKeyboard() {
- return mId.isAlphabetKeyboard();
- }
+ public static class Params {
+ public KeyboardId mId;
+ public int mThemeId;
- public boolean isPhoneKeyboard() {
- return mId.isPhoneKeyboard();
- }
+ /** Total height and width of the keyboard, including the paddings and keys */
+ public int mOccupiedHeight;
+ public int mOccupiedWidth;
- public boolean isNumberKeyboard() {
- return mId.isNumberKeyboard();
- }
+ /** Base height and width of the keyboard used to calculate rows' or keys' heights and
+ * widths
+ */
+ public int mBaseHeight;
+ public int mBaseWidth;
- public CharSequence adjustLabelCase(CharSequence label) {
- if (isShiftedOrShiftLocked() && !TextUtils.isEmpty(label) && label.length() < 3
- && Character.isLowerCase(label.charAt(0))) {
- return label.toString().toUpperCase(mId.mLocale);
+ public int mTopPadding;
+ public int mBottomPadding;
+ public int mHorizontalEdgesPadding;
+ public int mHorizontalCenterPadding;
+
+ public int mDefaultRowHeight;
+ public int mDefaultKeyWidth;
+ public int mHorizontalGap;
+ public int mVerticalGap;
+
+ public boolean mIsRtlKeyboard;
+ public int mMoreKeysTemplate;
+ public int mMaxMiniKeyboardColumn;
+
+ public int GRID_WIDTH;
+ public int GRID_HEIGHT;
+
+ public final Set<Key> mKeys = new HashSet<Key>();
+ public final Set<Key> mShiftKeys = new HashSet<Key>();
+ public final Set<Key> mShiftLockKeys = new HashSet<Key>();
+ public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet();
+
+ public int mMostCommonKeyHeight = 0;
+ public int mMostCommonKeyWidth = 0;
+
+ public final TouchPositionCorrection mTouchPositionCorrection =
+ new TouchPositionCorrection();
+
+ public static class TouchPositionCorrection {
+ private static final int TOUCH_POSITION_CORRECTION_RECORD_SIZE = 3;
+
+ public boolean mEnabled;
+ public float[] mXs;
+ public float[] mYs;
+ public float[] mRadii;
+
+ public void load(String[] data) {
+ final int dataLength = data.length;
+ if (dataLength % TOUCH_POSITION_CORRECTION_RECORD_SIZE != 0) {
+ if (LatinImeLogger.sDBG)
+ throw new RuntimeException(
+ "the size of touch position correction data is invalid");
+ return;
+ }
+
+ final int length = dataLength / TOUCH_POSITION_CORRECTION_RECORD_SIZE;
+ mXs = new float[length];
+ mYs = new float[length];
+ mRadii = new float[length];
+ try {
+ for (int i = 0; i < dataLength; ++i) {
+ final int type = i % TOUCH_POSITION_CORRECTION_RECORD_SIZE;
+ final int index = i / TOUCH_POSITION_CORRECTION_RECORD_SIZE;
+ final float value = Float.parseFloat(data[i]);
+ if (type == 0) {
+ mXs[index] = value;
+ } else if (type == 1) {
+ mYs[index] = value;
+ } else {
+ mRadii[index] = value;
+ }
+ }
+ } catch (NumberFormatException e) {
+ if (LatinImeLogger.sDBG) {
+ throw new RuntimeException(
+ "the number format for touch position correction data is invalid");
+ }
+ mXs = null;
+ mYs = null;
+ mRadii = null;
+ }
+ }
+
+ public void setEnabled(boolean enabled) {
+ mEnabled = enabled;
+ }
+
+ public boolean isValid() {
+ return mEnabled && mXs != null && mYs != null && mRadii != null
+ && mXs.length > 0 && mYs.length > 0 && mRadii.length > 0;
+ }
+ }
+
+ protected void clearKeys() {
+ mKeys.clear();
+ mShiftKeys.clear();
+ mShiftLockKeys.clear();
+ clearHistogram();
+ }
+
+ public void onAddKey(Key key) {
+ mKeys.add(key);
+ updateHistogram(key);
+ if (key.mCode == Keyboard.CODE_SHIFT) {
+ mShiftKeys.add(key);
+ if (key.isSticky()) {
+ mShiftLockKeys.add(key);
+ }
+ }
+ }
+
+ private int mMaxHeightCount = 0;
+ private int mMaxWidthCount = 0;
+ private final Map<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>();
+ private final Map<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>();
+
+ private void clearHistogram() {
+ mMostCommonKeyHeight = 0;
+ mMaxHeightCount = 0;
+ mHeightHistogram.clear();
+
+ mMaxWidthCount = 0;
+ mMostCommonKeyWidth = 0;
+ mWidthHistogram.clear();
+ }
+
+ private static int updateHistogramCounter(Map<Integer, Integer> histogram, Integer key) {
+ final int count = (histogram.containsKey(key) ? histogram.get(key) : 0) + 1;
+ histogram.put(key, count);
+ return count;
+ }
+
+ private void updateHistogram(Key key) {
+ final Integer height = key.mHeight + key.mVerticalGap;
+ final int heightCount = updateHistogramCounter(mHeightHistogram, height);
+ if (heightCount > mMaxHeightCount) {
+ mMaxHeightCount = heightCount;
+ mMostCommonKeyHeight = height;
+ }
+
+ final Integer width = key.mWidth + key.mHorizontalGap;
+ final int widthCount = updateHistogramCounter(mWidthHistogram, width);
+ if (widthCount > mMaxWidthCount) {
+ mMaxWidthCount = widthCount;
+ mMostCommonKeyWidth = width;
+ }
}
- return label;
}
/**
- * Returns the indices of the keys that are closest to the given point.
+ * Returns the array of the keys that are closest to the given point.
* @param x the x-coordinate of the point
* @param y the y-coordinate of the point
- * @return the array of integer indices for the nearest keys to the given point. If the given
+ * @return the array of the nearest keys to the given point. If the given
* point is out of range, then an array of size zero is returned.
*/
- public int[] getNearestKeys(int x, int y) {
- return mProximityInfo.getNearestKeys(x, y);
+ public Key[] getNearestKeys(int x, int y) {
+ // Avoid dead pixels at edges of the keyboard
+ final int adjustedX = Math.max(0, Math.min(x, mOccupiedWidth - 1));
+ final int adjustedY = Math.max(0, Math.min(y, mOccupiedHeight - 1));
+ return mProximityInfo.getNearestKeys(adjustedX, adjustedY);
+ }
+
+ public static String printableCode(int code) {
+ switch (code) {
+ case CODE_SHIFT: return "shift";
+ case CODE_SWITCH_ALPHA_SYMBOL: return "symbol";
+ case CODE_CAPSLOCK: return "capslock";
+ case CODE_OUTPUT_TEXT: return "text";
+ case CODE_DELETE: return "delete";
+ case CODE_SHORTCUT: return "shortcut";
+ case CODE_UNSPECIFIED: return "unspec";
+ default:
+ if (code < 0) Log.w(TAG, "Unknow negative key code=" + code);
+ if (code < 0x100) return String.format("\\u%02x", code);
+ return String.format("\\u04x", code);
+ }
}
- public static String themeName(int themeId) {
- // This should be aligned with theme-*.xml resource files' themeId attribute.
- switch (themeId) {
- case 0: return "Basic";
- case 1: return "BasicHighContrast";
- case 5: return "IceCreamSandwich";
- case 6: return "Stone";
- case 7: return "StoneBold";
- case 8: return "GingerBread";
- default: return null;
+ /**
+ * Keyboard Building helper.
+ *
+ * This class parses Keyboard XML file and eventually build a Keyboard.
+ * The Keyboard XML file looks like:
+ * <pre>
+ * &gt;!-- xml/keyboard.xml --&lt;
+ * &gt;Keyboard keyboard_attributes*&lt;
+ * &gt;!-- Keyboard Content --&lt;
+ * &gt;Row row_attributes*&lt;
+ * &gt;!-- Row Content --&lt;
+ * &gt;Key key_attributes* /&lt;
+ * &gt;Spacer horizontalGap="0.2in" /&lt;
+ * &gt;include keyboardLayout="@xml/other_keys"&lt;
+ * ...
+ * &gt;/Row&lt;
+ * &gt;include keyboardLayout="@xml/other_rows"&lt;
+ * ...
+ * &gt;/Keyboard&lt;
+ * </pre>
+ * The XML file which is included in other file must have &gt;merge&lt; as root element,
+ * such as:
+ * <pre>
+ * &gt;!-- xml/other_keys.xml --&lt;
+ * &gt;merge&lt;
+ * &gt;Key key_attributes* /&lt;
+ * ...
+ * &gt;/merge&lt;
+ * </pre>
+ * and
+ * <pre>
+ * &gt;!-- xml/other_rows.xml --&lt;
+ * &gt;merge&lt;
+ * &gt;Row row_attributes*&lt;
+ * &gt;Key key_attributes* /&lt;
+ * &gt;/Row&lt;
+ * ...
+ * &gt;/merge&lt;
+ * </pre>
+ * You can also use switch-case-default tags to select Rows and Keys.
+ * <pre>
+ * &gt;switch&lt;
+ * &gt;case case_attribute*&lt;
+ * &gt;!-- Any valid tags at switch position --&lt;
+ * &gt;/case&lt;
+ * ...
+ * &gt;default&lt;
+ * &gt;!-- Any valid tags at switch position --&lt;
+ * &gt;/default&lt;
+ * &gt;/switch&lt;
+ * </pre>
+ * You can declare Key style and specify styles within Key tags.
+ * <pre>
+ * &gt;switch&lt;
+ * &gt;case mode="email"&lt;
+ * &gt;key-style styleName="f1-key" parentStyle="modifier-key"
+ * keyLabel=".com"
+ * /&lt;
+ * &gt;/case&lt;
+ * &gt;case mode="url"&lt;
+ * &gt;key-style styleName="f1-key" parentStyle="modifier-key"
+ * keyLabel="http://"
+ * /&lt;
+ * &gt;/case&lt;
+ * &gt;/switch&lt;
+ * ...
+ * &gt;Key keyStyle="shift-key" ... /&lt;
+ * </pre>
+ */
+
+ public static class Builder<KP extends Params> {
+ private static final String TAG = Builder.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
+ // Keyboard XML Tags
+ private static final String TAG_KEYBOARD = "Keyboard";
+ private static final String TAG_ROW = "Row";
+ private static final String TAG_KEY = "Key";
+ private static final String TAG_SPACER = "Spacer";
+ private static final String TAG_INCLUDE = "include";
+ private static final String TAG_MERGE = "merge";
+ private static final String TAG_SWITCH = "switch";
+ private static final String TAG_CASE = "case";
+ private static final String TAG_DEFAULT = "default";
+ public static final String TAG_KEY_STYLE = "key-style";
+
+ private static final int DEFAULT_KEYBOARD_COLUMNS = 10;
+ private static final int DEFAULT_KEYBOARD_ROWS = 4;
+
+ protected final KP mParams;
+ protected final Context mContext;
+ protected final Resources mResources;
+ private final DisplayMetrics mDisplayMetrics;
+
+ private int mCurrentY = 0;
+ private Row mCurrentRow = null;
+ private boolean mLeftEdge;
+ private boolean mTopEdge;
+ private Key mRightEdgeKey = null;
+ private final KeyStyles mKeyStyles = new KeyStyles();
+
+ /**
+ * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate.
+ * Some of the key size defaults can be overridden per row from what the {@link Keyboard}
+ * defines.
+ */
+ public static class Row {
+ // keyWidth enum constants
+ private static final int KEYWIDTH_NOT_ENUM = 0;
+ private static final int KEYWIDTH_FILL_RIGHT = -1;
+ private static final int KEYWIDTH_FILL_BOTH = -2;
+
+ private final Params mParams;
+ /** Default width of a key in this row. */
+ public final float mDefaultKeyWidth;
+ /** Default height of a key in this row. */
+ public final int mRowHeight;
+
+ private final int mCurrentY;
+ // Will be updated by {@link Key}'s constructor.
+ private float mCurrentX;
+
+ public Row(Resources res, Params params, XmlPullParser parser, int y) {
+ mParams = params;
+ TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard);
+ mRowHeight = (int)Builder.getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_rowHeight,
+ params.mBaseHeight, params.mDefaultRowHeight);
+ keyboardAttr.recycle();
+ TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard_Key);
+ mDefaultKeyWidth = Builder.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_keyWidth,
+ params.mBaseWidth, params.mDefaultKeyWidth);
+ keyAttr.recycle();
+
+ mCurrentY = y;
+ mCurrentX = 0.0f;
+ }
+
+ public void setXPos(float keyXPos) {
+ mCurrentX = keyXPos;
+ }
+
+ public void advanceXPos(float width) {
+ mCurrentX += width;
+ }
+
+ public int getKeyY() {
+ return mCurrentY;
+ }
+
+ public float getKeyX(TypedArray keyAttr) {
+ final int widthType = Builder.getEnumValue(keyAttr,
+ R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
+ if (widthType == KEYWIDTH_FILL_BOTH) {
+ // If keyWidth is fillBoth, the key width should start right after the nearest
+ // key on the left hand side.
+ return mCurrentX;
+ }
+
+ final int keyboardRightEdge = mParams.mOccupiedWidth
+ - mParams.mHorizontalEdgesPadding;
+ if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyXPos)) {
+ final float keyXPos = Builder.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_keyXPos, mParams.mBaseWidth, 0);
+ if (keyXPos < 0) {
+ // If keyXPos is negative, the actual x-coordinate will be
+ // keyboardWidth + keyXPos.
+ // keyXPos shouldn't be less than mCurrentX because drawable area for this
+ // key starts at mCurrentX. Or, this key will overlaps the adjacent key on
+ // its left hand side.
+ return Math.max(keyXPos + keyboardRightEdge, mCurrentX);
+ } else {
+ return keyXPos + mParams.mHorizontalEdgesPadding;
+ }
+ }
+ return mCurrentX;
+ }
+
+ public float getKeyWidth(TypedArray keyAttr, float keyXPos) {
+ final int widthType = Builder.getEnumValue(keyAttr,
+ R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
+ switch (widthType) {
+ case KEYWIDTH_FILL_RIGHT:
+ case KEYWIDTH_FILL_BOTH:
+ final int keyboardRightEdge =
+ mParams.mOccupiedWidth - mParams.mHorizontalEdgesPadding;
+ // If keyWidth is fillRight, the actual key width will be determined to fill
+ // out the area up to the right edge of the keyboard.
+ // If keyWidth is fillBoth, the actual key width will be determined to fill out
+ // the area between the nearest key on the left hand side and the right edge of
+ // the keyboard.
+ return keyboardRightEdge - keyXPos;
+ default: // KEYWIDTH_NOT_ENUM
+ return Builder.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_keyWidth,
+ mParams.mBaseWidth, mDefaultKeyWidth);
+ }
+ }
+ }
+
+ public Builder(Context context, KP params) {
+ mContext = context;
+ final Resources res = context.getResources();
+ mResources = res;
+ mDisplayMetrics = res.getDisplayMetrics();
+
+ mParams = params;
+
+ setTouchPositionCorrectionData(context, params);
+
+ params.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
+ params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
+ }
+
+ private static void setTouchPositionCorrectionData(Context context, Params params) {
+ final TypedArray a = context.obtainStyledAttributes(
+ null, R.styleable.Keyboard, R.attr.keyboardStyle, 0);
+ params.mThemeId = a.getInt(R.styleable.Keyboard_themeId, 0);
+ final int resourceId = a.getResourceId(
+ R.styleable.Keyboard_touchPositionCorrectionData, 0);
+ a.recycle();
+ if (resourceId == 0) {
+ if (LatinImeLogger.sDBG)
+ throw new RuntimeException("touchPositionCorrectionData is not defined");
+ return;
+ }
+
+ final String[] data = context.getResources().getStringArray(resourceId);
+ params.mTouchPositionCorrection.load(data);
+ }
+
+ public Builder<KP> load(int xmlId, KeyboardId id) {
+ mParams.mId = id;
+ final XmlResourceParser parser = mResources.getXml(xmlId);
+ try {
+ parseKeyboard(parser);
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "keyboard XML parse error: " + e);
+ throw new IllegalArgumentException(e);
+ } catch (IOException e) {
+ Log.w(TAG, "keyboard XML parse error: " + e);
+ throw new RuntimeException(e);
+ } finally {
+ parser.close();
+ }
+ return this;
+ }
+
+ public void setTouchPositionCorrectionEnabled(boolean enabled) {
+ mParams.mTouchPositionCorrection.setEnabled(enabled);
+ }
+
+ public Keyboard build() {
+ return new Keyboard(mParams);
+ }
+
+ private void parseKeyboard(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ if (DEBUG) Log.d(TAG, String.format("<%s> %s", TAG_KEYBOARD, mParams.mId));
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_KEYBOARD.equals(tag)) {
+ parseKeyboardAttributes(parser);
+ startKeyboard();
+ parseKeyboardContent(parser, false);
+ break;
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD);
+ }
+ }
+ }
+ }
+
+ private void parseKeyboardAttributes(XmlPullParser parser) {
+ final int displayWidth = mDisplayMetrics.widthPixels;
+ final TypedArray keyboardAttr = mContext.obtainStyledAttributes(
+ Xml.asAttributeSet(parser), R.styleable.Keyboard, R.attr.keyboardStyle,
+ R.style.Keyboard);
+ final TypedArray keyAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard_Key);
+ try {
+ final int displayHeight = mDisplayMetrics.heightPixels;
+ final int keyboardHeight = (int)keyboardAttr.getDimension(
+ R.styleable.Keyboard_keyboardHeight, displayHeight / 2);
+ final int maxKeyboardHeight = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_maxKeyboardHeight, displayHeight, displayHeight / 2);
+ int minKeyboardHeight = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_minKeyboardHeight, displayHeight, displayHeight / 2);
+ if (minKeyboardHeight < 0) {
+ // Specified fraction was negative, so it should be calculated against display
+ // width.
+ minKeyboardHeight = -(int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_minKeyboardHeight, displayWidth, displayWidth / 2);
+ }
+ final Params params = mParams;
+ // Keyboard height will not exceed maxKeyboardHeight and will not be less than
+ // minKeyboardHeight.
+ params.mOccupiedHeight = Math.max(
+ Math.min(keyboardHeight, maxKeyboardHeight), minKeyboardHeight);
+ params.mOccupiedWidth = params.mId.mWidth;
+ params.mTopPadding = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_keyboardTopPadding, params.mOccupiedHeight, 0);
+ params.mBottomPadding = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_keyboardBottomPadding, params.mOccupiedHeight, 0);
+ params.mHorizontalEdgesPadding = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_keyboardHorizontalEdgesPadding,
+ mParams.mOccupiedWidth, 0);
+
+ params.mBaseWidth = params.mOccupiedWidth - params.mHorizontalEdgesPadding * 2
+ - params.mHorizontalCenterPadding;
+ params.mDefaultKeyWidth = (int)getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_keyWidth, params.mBaseWidth,
+ params.mBaseWidth / DEFAULT_KEYBOARD_COLUMNS);
+ params.mHorizontalGap = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_horizontalGap, params.mBaseWidth, 0);
+ params.mVerticalGap = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_verticalGap, params.mOccupiedHeight, 0);
+ params.mBaseHeight = params.mOccupiedHeight - params.mTopPadding
+ - params.mBottomPadding + params.mVerticalGap;
+ params.mDefaultRowHeight = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_rowHeight, params.mBaseHeight,
+ params.mBaseHeight / DEFAULT_KEYBOARD_ROWS);
+
+ params.mIsRtlKeyboard = keyboardAttr.getBoolean(
+ R.styleable.Keyboard_isRtlKeyboard, false);
+ params.mMoreKeysTemplate = keyboardAttr.getResourceId(
+ R.styleable.Keyboard_moreKeysTemplate, 0);
+ params.mMaxMiniKeyboardColumn = keyAttr.getInt(
+ R.styleable.Keyboard_Key_maxMoreKeysColumn, 5);
+
+ params.mIconsSet.loadIcons(keyboardAttr);
+ } finally {
+ keyAttr.recycle();
+ keyboardAttr.recycle();
+ }
+ }
+
+ private void parseKeyboardContent(XmlPullParser parser, boolean skip)
+ throws XmlPullParserException, IOException {
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_ROW.equals(tag)) {
+ Row row = parseRowAttributes(parser);
+ if (DEBUG) Log.d(TAG, String.format("<%s>", TAG_ROW));
+ if (!skip)
+ startRow(row);
+ parseRowContent(parser, row, skip);
+ } else if (TAG_INCLUDE.equals(tag)) {
+ parseIncludeKeyboardContent(parser, skip);
+ } else if (TAG_SWITCH.equals(tag)) {
+ parseSwitchKeyboardContent(parser, skip);
+ } else if (TAG_KEY_STYLE.equals(tag)) {
+ parseKeyStyle(parser, skip);
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_ROW);
+ }
+ } else if (event == XmlPullParser.END_TAG) {
+ final String tag = parser.getName();
+ if (TAG_KEYBOARD.equals(tag)) {
+ endKeyboard();
+ break;
+ } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag)
+ || TAG_MERGE.equals(tag)) {
+ if (DEBUG) Log.d(TAG, String.format("</%s>", tag));
+ break;
+ } else if (TAG_KEY_STYLE.equals(tag)) {
+ continue;
+ } else {
+ throw new XmlParseUtils.IllegalEndTag(parser, TAG_ROW);
+ }
+ }
+ }
+ }
+
+ private Row parseRowAttributes(XmlPullParser parser) throws XmlPullParserException {
+ final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard);
+ try {
+ if (a.hasValue(R.styleable.Keyboard_horizontalGap))
+ throw new XmlParseUtils.IllegalAttribute(parser, "horizontalGap");
+ if (a.hasValue(R.styleable.Keyboard_verticalGap))
+ throw new XmlParseUtils.IllegalAttribute(parser, "verticalGap");
+ return new Row(mResources, mParams, parser, mCurrentY);
+ } finally {
+ a.recycle();
+ }
+ }
+
+ private void parseRowContent(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_KEY.equals(tag)) {
+ parseKey(parser, row, skip);
+ } else if (TAG_SPACER.equals(tag)) {
+ parseSpacer(parser, row, skip);
+ } else if (TAG_INCLUDE.equals(tag)) {
+ parseIncludeRowContent(parser, row, skip);
+ } else if (TAG_SWITCH.equals(tag)) {
+ parseSwitchRowContent(parser, row, skip);
+ } else if (TAG_KEY_STYLE.equals(tag)) {
+ parseKeyStyle(parser, skip);
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEY);
+ }
+ } else if (event == XmlPullParser.END_TAG) {
+ final String tag = parser.getName();
+ if (TAG_ROW.equals(tag)) {
+ if (DEBUG) Log.d(TAG, String.format("</%s>", TAG_ROW));
+ if (!skip)
+ endRow(row);
+ break;
+ } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag)
+ || TAG_MERGE.equals(tag)) {
+ if (DEBUG) Log.d(TAG, String.format("</%s>", tag));
+ break;
+ } else if (TAG_KEY_STYLE.equals(tag)) {
+ continue;
+ } else {
+ throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEY);
+ }
+ }
+ }
+ }
+
+ private void parseKey(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ if (skip) {
+ XmlParseUtils.checkEndTag(TAG_KEY, parser);
+ } else {
+ final Key key = new Key(mResources, mParams, row, parser, mKeyStyles);
+ if (DEBUG) Log.d(TAG, String.format("<%s%s keyLabel=%s code=%d moreKeys=%s />",
+ TAG_KEY, (key.isEnabled() ? "" : " disabled"), key.mLabel, key.mCode,
+ Arrays.toString(key.mMoreKeys)));
+ XmlParseUtils.checkEndTag(TAG_KEY, parser);
+ endKey(key);
+ }
+ }
+
+ private void parseSpacer(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ if (skip) {
+ XmlParseUtils.checkEndTag(TAG_SPACER, parser);
+ } else {
+ final Key.Spacer spacer = new Key.Spacer(
+ mResources, mParams, row, parser, mKeyStyles);
+ if (DEBUG) Log.d(TAG, String.format("<%s />", TAG_SPACER));
+ XmlParseUtils.checkEndTag(TAG_SPACER, parser);
+ endKey(spacer);
+ }
+ }
+
+ private void parseIncludeKeyboardContent(XmlPullParser parser, boolean skip)
+ throws XmlPullParserException, IOException {
+ parseIncludeInternal(parser, null, skip);
+ }
+
+ private void parseIncludeRowContent(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ parseIncludeInternal(parser, row, skip);
+ }
+
+ private void parseIncludeInternal(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ if (skip) {
+ XmlParseUtils.checkEndTag(TAG_INCLUDE, parser);
+ } else {
+ final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard_Include);
+ int keyboardLayout = 0;
+ try {
+ XmlParseUtils.checkAttributeExists(a,
+ R.styleable.Keyboard_Include_keyboardLayout, "keyboardLayout",
+ TAG_INCLUDE, parser);
+ keyboardLayout = a.getResourceId(
+ R.styleable.Keyboard_Include_keyboardLayout, 0);
+ } finally {
+ a.recycle();
+ }
+
+ XmlParseUtils.checkEndTag(TAG_INCLUDE, parser);
+ if (DEBUG) Log.d(TAG, String.format("<%s keyboardLayout=%s />",
+ TAG_INCLUDE, mResources.getResourceEntryName(keyboardLayout)));
+ final XmlResourceParser parserForInclude = mResources.getXml(keyboardLayout);
+ try {
+ parseMerge(parserForInclude, row, skip);
+ } finally {
+ parserForInclude.close();
+ }
+ }
+ }
+
+ private void parseMerge(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_MERGE.equals(tag)) {
+ if (row == null) {
+ parseKeyboardContent(parser, skip);
+ } else {
+ parseRowContent(parser, row, skip);
+ }
+ break;
+ } else {
+ throw new XmlParseUtils.ParseException(
+ "Included keyboard layout must have <merge> root element", parser);
+ }
+ }
+ }
+ }
+
+ private void parseSwitchKeyboardContent(XmlPullParser parser, boolean skip)
+ throws XmlPullParserException, IOException {
+ parseSwitchInternal(parser, null, skip);
+ }
+
+ private void parseSwitchRowContent(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ parseSwitchInternal(parser, row, skip);
+ }
+
+ private void parseSwitchInternal(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ if (DEBUG) Log.d(TAG, String.format("<%s> %s", TAG_SWITCH, mParams.mId));
+ boolean selected = false;
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_CASE.equals(tag)) {
+ selected |= parseCase(parser, row, selected ? true : skip);
+ } else if (TAG_DEFAULT.equals(tag)) {
+ selected |= parseDefault(parser, row, selected ? true : skip);
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEY);
+ }
+ } else if (event == XmlPullParser.END_TAG) {
+ final String tag = parser.getName();
+ if (TAG_SWITCH.equals(tag)) {
+ if (DEBUG) Log.d(TAG, String.format("</%s>", TAG_SWITCH));
+ break;
+ } else {
+ throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEY);
+ }
+ }
+ }
+ }
+
+ private boolean parseCase(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ final boolean selected = parseCaseCondition(parser);
+ if (row == null) {
+ // Processing Rows.
+ parseKeyboardContent(parser, selected ? skip : true);
+ } else {
+ // Processing Keys.
+ parseRowContent(parser, row, selected ? skip : true);
+ }
+ return selected;
+ }
+
+ private boolean parseCaseCondition(XmlPullParser parser) {
+ final KeyboardId id = mParams.mId;
+ if (id == null)
+ return true;
+
+ final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard_Case);
+ try {
+ final boolean modeMatched = matchTypedValue(a,
+ R.styleable.Keyboard_Case_mode, id.mMode, KeyboardId.modeName(id.mMode));
+ final boolean navigateActionMatched = matchBoolean(a,
+ R.styleable.Keyboard_Case_navigateAction, id.navigateAction());
+ final boolean passwordInputMatched = matchBoolean(a,
+ R.styleable.Keyboard_Case_passwordInput, id.passwordInput());
+ final boolean hasSettingsKeyMatched = matchBoolean(a,
+ R.styleable.Keyboard_Case_hasSettingsKey, id.hasSettingsKey());
+ final boolean f2KeyModeMatched = matchInteger(a,
+ R.styleable.Keyboard_Case_f2KeyMode, id.f2KeyMode());
+ final boolean clobberSettingsKeyMatched = matchBoolean(a,
+ R.styleable.Keyboard_Case_clobberSettingsKey, id.mClobberSettingsKey);
+ final boolean shortcutKeyEnabledMatched = matchBoolean(a,
+ R.styleable.Keyboard_Case_shortcutKeyEnabled, id.mShortcutKeyEnabled);
+ final boolean hasShortcutKeyMatched = matchBoolean(a,
+ R.styleable.Keyboard_Case_hasShortcutKey, id.mHasShortcutKey);
+ // As noted at {@link KeyboardId} class, we are interested only in enum value
+ // masked by {@link android.view.inputmethod.EditorInfo#IME_MASK_ACTION} and
+ // {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ENTER_ACTION}. So matching
+ // this attribute with id.mImeOptions as integer value is enough for our purpose.
+ final boolean imeActionMatched = matchInteger(a,
+ R.styleable.Keyboard_Case_imeAction, id.imeAction());
+ final boolean localeCodeMatched = matchString(a,
+ R.styleable.Keyboard_Case_localeCode, id.mLocale.toString());
+ final boolean languageCodeMatched = matchString(a,
+ R.styleable.Keyboard_Case_languageCode, id.mLocale.getLanguage());
+ final boolean countryCodeMatched = matchString(a,
+ R.styleable.Keyboard_Case_countryCode, id.mLocale.getCountry());
+ final boolean selected = modeMatched && navigateActionMatched
+ && passwordInputMatched && hasSettingsKeyMatched && f2KeyModeMatched
+ && clobberSettingsKeyMatched && shortcutKeyEnabledMatched
+ && hasShortcutKeyMatched && imeActionMatched && localeCodeMatched
+ && languageCodeMatched && countryCodeMatched;
+
+ if (DEBUG) Log.d(TAG, String.format("<%s%s%s%s%s%s%s%s%s%s%s%s%s> %s", TAG_CASE,
+ textAttr(a.getString(R.styleable.Keyboard_Case_mode), "mode"),
+ booleanAttr(a, R.styleable.Keyboard_Case_navigateAction, "navigateAction"),
+ booleanAttr(a, R.styleable.Keyboard_Case_passwordInput, "passwordInput"),
+ booleanAttr(a, R.styleable.Keyboard_Case_hasSettingsKey, "hasSettingsKey"),
+ textAttr(KeyboardId.f2KeyModeName(
+ a.getInt(R.styleable.Keyboard_Case_f2KeyMode, -1)), "f2KeyMode"),
+ booleanAttr(a, R.styleable.Keyboard_Case_clobberSettingsKey,
+ "clobberSettingsKey"),
+ booleanAttr(a, R.styleable.Keyboard_Case_shortcutKeyEnabled,
+ "shortcutKeyEnabled"),
+ booleanAttr(a, R.styleable.Keyboard_Case_hasShortcutKey, "hasShortcutKey"),
+ textAttr(EditorInfoCompatUtils.imeOptionsName(
+ a.getInt(R.styleable.Keyboard_Case_imeAction, -1)), "imeAction"),
+ textAttr(a.getString(R.styleable.Keyboard_Case_localeCode), "localeCode"),
+ textAttr(a.getString(R.styleable.Keyboard_Case_languageCode),
+ "languageCode"),
+ textAttr(a.getString(R.styleable.Keyboard_Case_countryCode), "countryCode"),
+ Boolean.toString(selected)));
+
+ return selected;
+ } finally {
+ a.recycle();
+ }
+ }
+
+ private static boolean matchInteger(TypedArray a, int index, int value) {
+ // If <case> does not have "index" attribute, that means this <case> is wild-card for
+ // the attribute.
+ return !a.hasValue(index) || a.getInt(index, 0) == value;
+ }
+
+ private static boolean matchBoolean(TypedArray a, int index, boolean value) {
+ // If <case> does not have "index" attribute, that means this <case> is wild-card for
+ // the attribute.
+ return !a.hasValue(index) || a.getBoolean(index, false) == value;
+ }
+
+ private static boolean matchString(TypedArray a, int index, String value) {
+ // If <case> does not have "index" attribute, that means this <case> is wild-card for
+ // the attribute.
+ return !a.hasValue(index)
+ || stringArrayContains(a.getString(index).split("\\|"), value);
+ }
+
+ private static boolean matchTypedValue(TypedArray a, int index, int intValue,
+ String strValue) {
+ // If <case> does not have "index" attribute, that means this <case> is wild-card for
+ // the attribute.
+ final TypedValue v = a.peekValue(index);
+ if (v == null)
+ return true;
+
+ if (isIntegerValue(v)) {
+ return intValue == a.getInt(index, 0);
+ } else if (isStringValue(v)) {
+ return stringArrayContains(a.getString(index).split("\\|"), strValue);
+ }
+ return false;
+ }
+
+ private static boolean stringArrayContains(String[] array, String value) {
+ for (final String elem : array) {
+ if (elem.equals(value))
+ return true;
+ }
+ return false;
+ }
+
+ private boolean parseDefault(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ if (DEBUG) Log.d(TAG, String.format("<%s>", TAG_DEFAULT));
+ if (row == null) {
+ parseKeyboardContent(parser, skip);
+ } else {
+ parseRowContent(parser, row, skip);
+ }
+ return true;
+ }
+
+ private void parseKeyStyle(XmlPullParser parser, boolean skip)
+ throws XmlPullParserException {
+ TypedArray keyStyleAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard_KeyStyle);
+ TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard_Key);
+ try {
+ if (!keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_styleName))
+ throw new XmlParseUtils.ParseException("<" + TAG_KEY_STYLE
+ + "/> needs styleName attribute", parser);
+ if (!skip)
+ mKeyStyles.parseKeyStyleAttributes(keyStyleAttr, keyAttrs, parser);
+ } finally {
+ keyStyleAttr.recycle();
+ keyAttrs.recycle();
+ }
+ }
+
+ private void startKeyboard() {
+ mCurrentY += mParams.mTopPadding;
+ mTopEdge = true;
+ }
+
+ private void startRow(Row row) {
+ addEdgeSpace(mParams.mHorizontalEdgesPadding, row);
+ mCurrentRow = row;
+ mLeftEdge = true;
+ mRightEdgeKey = null;
+ }
+
+ private void endRow(Row row) {
+ if (mCurrentRow == null)
+ throw new InflateException("orphant end row tag");
+ if (mRightEdgeKey != null) {
+ mRightEdgeKey.markAsRightEdge(mParams);
+ mRightEdgeKey = null;
+ }
+ addEdgeSpace(mParams.mHorizontalEdgesPadding, row);
+ mCurrentY += row.mRowHeight;
+ mCurrentRow = null;
+ mTopEdge = false;
+ }
+
+ private void endKey(Key key) {
+ mParams.onAddKey(key);
+ if (mLeftEdge) {
+ key.markAsLeftEdge(mParams);
+ mLeftEdge = false;
+ }
+ if (mTopEdge) {
+ key.markAsTopEdge(mParams);
+ }
+ mRightEdgeKey = key;
+ }
+
+ private void endKeyboard() {
+ // nothing to do here.
+ }
+
+ private void addEdgeSpace(float width, Row row) {
+ row.advanceXPos(width);
+ mLeftEdge = false;
+ mRightEdgeKey = null;
+ }
+
+ public static float getDimensionOrFraction(TypedArray a, int index, int base,
+ float defValue) {
+ final TypedValue value = a.peekValue(index);
+ if (value == null)
+ return defValue;
+ if (isFractionValue(value)) {
+ return a.getFraction(index, base, base, defValue);
+ } else if (isDimensionValue(value)) {
+ return a.getDimension(index, defValue);
+ }
+ return defValue;
+ }
+
+ public static int getEnumValue(TypedArray a, int index, int defValue) {
+ final TypedValue value = a.peekValue(index);
+ if (value == null)
+ return defValue;
+ if (isIntegerValue(value)) {
+ return a.getInt(index, defValue);
+ }
+ return defValue;
+ }
+
+ private static boolean isFractionValue(TypedValue v) {
+ return v.type == TypedValue.TYPE_FRACTION;
+ }
+
+ private static boolean isDimensionValue(TypedValue v) {
+ return v.type == TypedValue.TYPE_DIMENSION;
+ }
+
+ private static boolean isIntegerValue(TypedValue v) {
+ return v.type >= TypedValue.TYPE_FIRST_INT && v.type <= TypedValue.TYPE_LAST_INT;
+ }
+
+ private static boolean isStringValue(TypedValue v) {
+ return v.type == TypedValue.TYPE_STRING;
+ }
+
+ private static String textAttr(String value, String name) {
+ return value != null ? String.format(" %s=%s", name, value) : "";
+ }
+
+ private static String booleanAttr(TypedArray a, int index, String name) {
+ return a.hasValue(index)
+ ? String.format(" %s=%s", name, a.getBoolean(index, false)) : "";
}
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index 2e4988fb0..d95c3b3af 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -16,15 +16,16 @@
package com.android.inputmethod.keyboard;
+import android.text.TextUtils;
import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.compat.EditorInfoCompatUtils;
import com.android.inputmethod.compat.InputTypeCompatUtils;
-import com.android.inputmethod.latin.R;
import java.util.Arrays;
import java.util.Locale;
+// TODO: Move to com.android.inputmethod.keyboard.internal package.
/**
* Represents the parameters necessary to construct a new LatinKeyboard,
* which also serve as a unique identifier for each keyboard type.
@@ -37,104 +38,143 @@ public class KeyboardId {
public static final int MODE_PHONE = 4;
public static final int MODE_NUMBER = 5;
- public static final int F2KEY_MODE_NONE = 0;
- public static final int F2KEY_MODE_SETTINGS = 1;
- public static final int F2KEY_MODE_SHORTCUT_IME = 2;
- public static final int F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS = 3;
+ public static final int ELEMENT_ALPHABET = 0;
+ /* TODO: Implement alphabet variant shift keyboard.
+ public static final int ELEMENT_ALPHABET_MANUAL_TEMPORARY_SHIFT = 1;
+ public static final int ELEMENT_ALPHABET_AUTOMATIC_TEMPORARY_SHIFT = 2;
+ public static final int ELEMENT_ALPHABET_SHIFT_LOCK = 3;
+ public static final int ELEMENT_ALPHABET_SHIFT_LOCK_SHIFT = 4;
+ */
+ public static final int ELEMENT_SYMBOLS = 5;
+ public static final int ELEMENT_SYMBOLS_SHIFT = 6;
+ public static final int ELEMENT_PHONE = 7;
+ public static final int ELEMENT_PHONE_SHIFT = 8;
+ public static final int ELEMENT_NUMBER = 9;
+
+ private static final int F2KEY_MODE_NONE = 0;
+ private static final int F2KEY_MODE_SETTINGS = 1;
+ private static final int F2KEY_MODE_SHORTCUT_IME = 2;
+ private static final int F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS = 3;
public final Locale mLocale;
public final int mOrientation;
public final int mWidth;
public final int mMode;
- public final int mXmlId;
- public final boolean mNavigateAction;
- public final boolean mPasswordInput;
- // TODO: Clean up these booleans and modes.
- public final boolean mHasSettingsKey;
- public final int mF2KeyMode;
+ public final int mElementState;
+ private final int mInputType;
+ private final int mImeOptions;
+ private final boolean mSettingsKeyEnabled;
public final boolean mClobberSettingsKey;
public final boolean mShortcutKeyEnabled;
public final boolean mHasShortcutKey;
- public final int mImeAction;
-
- public final String mXmlName;
- public final EditorInfo mAttribute;
private final int mHashCode;
- public KeyboardId(String xmlName, int xmlId, Locale locale, int orientation, int width,
- int mode, EditorInfo attribute, boolean hasSettingsKey, int f2KeyMode,
- boolean clobberSettingsKey, boolean shortcutKeyEnabled, boolean hasShortcutKey) {
- final int inputType = (attribute != null) ? attribute.inputType : 0;
- final int imeOptions = (attribute != null) ? attribute.imeOptions : 0;
+ public KeyboardId(int elementState, Locale locale, int orientation, int width, int mode,
+ int inputType, int imeOptions, boolean settingsKeyEnabled, boolean clobberSettingsKey,
+ boolean shortcutKeyEnabled, boolean hasShortcutKey) {
this.mLocale = locale;
this.mOrientation = orientation;
this.mWidth = width;
this.mMode = mode;
- this.mXmlId = xmlId;
- // Note: Turn off checking navigation flag to show TAB key for now.
- this.mNavigateAction = InputTypeCompatUtils.isWebInputType(inputType);
-// || EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions)
-// || EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions);
- this.mPasswordInput = InputTypeCompatUtils.isPasswordInputType(inputType)
- || InputTypeCompatUtils.isVisiblePasswordInputType(inputType);
- this.mHasSettingsKey = hasSettingsKey;
- this.mF2KeyMode = f2KeyMode;
+ this.mElementState = elementState;
+ this.mInputType = inputType;
+ this.mImeOptions = imeOptions;
+ this.mSettingsKeyEnabled = settingsKeyEnabled;
this.mClobberSettingsKey = clobberSettingsKey;
this.mShortcutKeyEnabled = shortcutKeyEnabled;
this.mHasShortcutKey = hasShortcutKey;
- // We are interested only in {@link EditorInfo#IME_MASK_ACTION} enum value and
- // {@link EditorInfo#IME_FLAG_NO_ENTER_ACTION}.
- this.mImeAction = imeOptions & (
- EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
- this.mXmlName = xmlName;
- this.mAttribute = attribute;
-
- this.mHashCode = Arrays.hashCode(new Object[] {
- locale,
- orientation,
- width,
- mode,
- xmlId,
- mNavigateAction,
- mPasswordInput,
- hasSettingsKey,
- f2KeyMode,
- clobberSettingsKey,
- shortcutKeyEnabled,
- hasShortcutKey,
- mImeAction,
- });
+ this.mHashCode = hashCode(this);
}
- public KeyboardId cloneWithNewXml(String xmlName, int xmlId) {
- return new KeyboardId(xmlName, xmlId, mLocale, mOrientation, mWidth, mMode, mAttribute,
- false, F2KEY_MODE_NONE, false, false, false);
+ private static int hashCode(KeyboardId id) {
+ return Arrays.hashCode(new Object[] {
+ id.mOrientation,
+ id.mElementState,
+ id.mMode,
+ id.mWidth,
+ id.navigateAction(),
+ id.passwordInput(),
+ id.mSettingsKeyEnabled,
+ id.mClobberSettingsKey,
+ id.mShortcutKeyEnabled,
+ id.mHasShortcutKey,
+ id.imeAction(),
+ id.mLocale
+ });
}
- public int getXmlId() {
- return mXmlId;
+ private boolean equals(KeyboardId other) {
+ if (other == this)
+ return true;
+ return other.mOrientation == this.mOrientation
+ && other.mElementState == this.mElementState
+ && other.mMode == this.mMode
+ && other.mWidth == this.mWidth
+ && other.navigateAction() == this.navigateAction()
+ && other.passwordInput() == this.passwordInput()
+ && other.mSettingsKeyEnabled == this.mSettingsKeyEnabled
+ && other.mClobberSettingsKey == this.mClobberSettingsKey
+ && other.mShortcutKeyEnabled == this.mShortcutKeyEnabled
+ && other.mHasShortcutKey == this.mHasShortcutKey
+ && other.imeAction() == this.imeAction()
+ && other.mLocale.equals(this.mLocale);
}
public boolean isAlphabetKeyboard() {
- return mXmlId == R.xml.kbd_qwerty;
+ return mElementState < ELEMENT_SYMBOLS;
}
public boolean isSymbolsKeyboard() {
- return mXmlId == R.xml.kbd_symbols || mXmlId == R.xml.kbd_symbols_shift;
+ return mElementState == ELEMENT_SYMBOLS || mElementState == ELEMENT_SYMBOLS_SHIFT;
}
public boolean isPhoneKeyboard() {
- return mMode == MODE_PHONE;
+ return mElementState == ELEMENT_PHONE || mElementState == ELEMENT_PHONE_SHIFT;
}
public boolean isPhoneShiftKeyboard() {
- return mXmlId == R.xml.kbd_phone_shift;
+ return mElementState == ELEMENT_PHONE_SHIFT;
+ }
+
+ public boolean navigateAction() {
+ // Note: Turn off checking navigation flag to show TAB key for now.
+ boolean navigateAction = InputTypeCompatUtils.isWebInputType(mInputType);
+// || EditorInfoCompatUtils.hasFlagNavigateNext(mImeOptions)
+// || EditorInfoCompatUtils.hasFlagNavigatePrevious(mImeOptions);
+ return navigateAction;
+ }
+
+ public boolean passwordInput() {
+ return InputTypeCompatUtils.isPasswordInputType(mInputType)
+ || InputTypeCompatUtils.isVisiblePasswordInputType(mInputType);
+ }
+
+ public int imeAction() {
+ // We are interested only in {@link EditorInfo#IME_MASK_ACTION} enum value and
+ // {@link EditorInfo#IME_FLAG_NO_ENTER_ACTION}.
+ return mImeOptions & (
+ EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
+ }
+
+ public boolean hasSettingsKey() {
+ return mSettingsKeyEnabled && !mClobberSettingsKey;
}
- public boolean isNumberKeyboard() {
- return mMode == MODE_NUMBER;
+ public int f2KeyMode() {
+ if (mClobberSettingsKey) {
+ // Never shows the Settings key
+ return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
+ }
+
+ if (mSettingsKeyEnabled) {
+ return KeyboardId.F2KEY_MODE_SETTINGS;
+ } else {
+ // It should be alright to fall back to the Settings key on 7-inch layouts
+ // even when the Settings key is not explicitly enabled.
+ return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
+ }
}
@Override
@@ -142,22 +182,6 @@ public class KeyboardId {
return other instanceof KeyboardId && equals((KeyboardId) other);
}
- private boolean equals(KeyboardId other) {
- return other.mLocale.equals(this.mLocale)
- && other.mOrientation == this.mOrientation
- && other.mWidth == this.mWidth
- && other.mMode == this.mMode
- && other.mXmlId == this.mXmlId
- && other.mNavigateAction == this.mNavigateAction
- && other.mPasswordInput == this.mPasswordInput
- && other.mHasSettingsKey == this.mHasSettingsKey
- && other.mF2KeyMode == this.mF2KeyMode
- && other.mClobberSettingsKey == this.mClobberSettingsKey
- && other.mShortcutKeyEnabled == this.mShortcutKeyEnabled
- && other.mHasShortcutKey == this.mHasShortcutKey
- && other.mImeAction == this.mImeAction;
- }
-
@Override
public int hashCode() {
return mHashCode;
@@ -165,22 +189,48 @@ public class KeyboardId {
@Override
public String toString() {
- return String.format("[%s.xml %s %s%d %s %s %s%s%s%s%s%s%s]",
- mXmlName,
+ return String.format("[%s %s %s%d %s %s %s%s%s%s%s%s%s]",
+ elementStateToString(mElementState),
mLocale,
(mOrientation == 1 ? "port" : "land"), mWidth,
modeName(mMode),
- EditorInfoCompatUtils.imeOptionsName(mImeAction),
- f2KeyModeName(mF2KeyMode),
+ EditorInfoCompatUtils.imeOptionsName(imeAction()),
+ f2KeyModeName(f2KeyMode()),
(mClobberSettingsKey ? " clobberSettingsKey" : ""),
- (mNavigateAction ? " navigateAction" : ""),
- (mPasswordInput ? " passwordInput" : ""),
- (mHasSettingsKey ? " hasSettingsKey" : ""),
+ (navigateAction() ? " navigateAction" : ""),
+ (passwordInput() ? " passwordInput" : ""),
+ (hasSettingsKey() ? " hasSettingsKey" : ""),
(mShortcutKeyEnabled ? " shortcutKeyEnabled" : ""),
(mHasShortcutKey ? " hasShortcutKey" : "")
);
}
+ public static boolean equivalentEditorInfoForKeyboard(EditorInfo a, EditorInfo b) {
+ if (a == null && b == null) return true;
+ if (a == null || b == null) return false;
+ return a.inputType == b.inputType
+ && a.imeOptions == b.imeOptions
+ && TextUtils.equals(a.privateImeOptions, b.privateImeOptions);
+ }
+
+ public static String elementStateToString(int elementState) {
+ switch (elementState) {
+ case ELEMENT_ALPHABET: return "alphabet";
+ /* TODO: Implement alphabet variant shift keyboard.
+ case ELEMENT_ALPHABET_MANUAL_TEMPORARY_SHIFT: return "alphabetManualTemporaryShift";
+ case ELEMENT_ALPHABET_AUTOMATIC_TEMPORARY_SHIFT: return "alphabetAutomaticTemporaryShift";
+ case ELEMENT_ALPHABET_SHIFT_LOCK: return "alphabetShiftLock";
+ case ELEMENT_ALPHABET_SHIFT_LOCK_SHIFT: return "alphabetShiftLockShift";
+ */
+ case ELEMENT_SYMBOLS: return "symbols";
+ case ELEMENT_SYMBOLS_SHIFT: return "symbolsShift";
+ case ELEMENT_PHONE: return "phone";
+ case ELEMENT_PHONE_SHIFT: return "phoneShift";
+ case ELEMENT_NUMBER: return "number";
+ default: return null;
+ }
+ }
+
public static String modeName(int mode) {
switch (mode) {
case MODE_TEXT: return "text";
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
new file mode 100644
index 000000000..a2e784c99
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.keyboard;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.util.Log;
+import android.util.Xml;
+import android.view.inputmethod.EditorInfo;
+
+import com.android.inputmethod.latin.LatinIME;
+import com.android.inputmethod.latin.LatinImeLogger;
+import com.android.inputmethod.latin.LocaleUtils;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.SettingsValues;
+import com.android.inputmethod.latin.SubtypeSwitcher;
+import com.android.inputmethod.latin.Utils;
+import com.android.inputmethod.latin.XmlParseUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
+import java.util.Locale;
+
+/**
+ * This class represents a set of keyboards. Each of them represents a different keyboard
+ * specific to a keyboard state, such as alphabet, symbols, and so on. Layouts in the same
+ * {@link KeyboardSet} are related to each other.
+ * A {@link KeyboardSet} needs to be created for each {@link android.view.inputmethod.EditorInfo}.
+ */
+public class KeyboardSet {
+ private static final String TAG = KeyboardSet.class.getSimpleName();
+ private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG;
+
+ private static final String TAG_KEYBOARD_SET = TAG;
+ private static final String TAG_ELEMENT = "Element";
+
+ private final Context mContext;
+ private final Params mParams;
+
+ private static class Params {
+ int mMode;
+ int mInputType;
+ int mImeOptions;
+ boolean mSettingsKeyEnabled;
+ boolean mVoiceKeyEnabled;
+ boolean mVoiceKeyOnMain;
+ boolean mNoSettingsKey;
+ Locale mLocale;
+ int mOrientation;
+ int mWidth;
+ final HashMap<Integer, Integer> mElementKeyboards = new HashMap<Integer, Integer>();
+ Params() {}
+ }
+
+ private static final HashMap<KeyboardId, SoftReference<Keyboard>> sKeyboardCache =
+ new HashMap<KeyboardId, SoftReference<Keyboard>>();
+
+ public static void clearKeyboardCache() {
+ sKeyboardCache.clear();
+ }
+
+ private KeyboardSet(Context context, Params params) {
+ mContext = context;
+ mParams = params;
+ }
+
+ public Keyboard getMainKeyboard() {
+ return getKeyboard(false, false);
+ }
+
+ public Keyboard getSymbolsKeyboard() {
+ return getKeyboard(true, false);
+ }
+
+ public Keyboard getSymbolsShiftedKeyboard() {
+ final Keyboard keyboard = getKeyboard(true, true);
+ // TODO: Remove this logic once we introduce initial keyboard shift state attribute.
+ // Symbol shift keyboard may have a shift 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 shift key or not.
+ keyboard.setShiftLocked(keyboard.hasShiftLockKey());
+ return keyboard;
+ }
+
+ private Keyboard getKeyboard(boolean isSymbols, boolean isShift) {
+ final int elementState = Builder.getElementState(mParams.mMode, isSymbols, isShift);
+ final int xmlId = mParams.mElementKeyboards.get(elementState);
+ final KeyboardId id = Builder.getKeyboardId(elementState, isSymbols, mParams);
+ final Keyboard keyboard = getKeyboard(mContext, xmlId, id);
+ return keyboard;
+ }
+
+ public KeyboardId getMainKeyboardId() {
+ final int elementState = Builder.getElementState(mParams.mMode, false, false);
+ return Builder.getKeyboardId(elementState, false, mParams);
+ }
+
+ private static Keyboard getKeyboard(Context context, int xmlId, KeyboardId id) {
+ final Resources res = context.getResources();
+ final SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance();
+ final SoftReference<Keyboard> ref = sKeyboardCache.get(id);
+ Keyboard keyboard = (ref == null) ? null : ref.get();
+ if (keyboard == null) {
+ final Locale savedLocale = LocaleUtils.setSystemLocale(res, id.mLocale);
+ try {
+ final Keyboard.Builder<Keyboard.Params> builder =
+ new Keyboard.Builder<Keyboard.Params>(context, new Keyboard.Params());
+ builder.load(xmlId, id);
+ builder.setTouchPositionCorrectionEnabled(
+ subtypeSwitcher.currentSubtypeContainsExtraValueKey(
+ LatinIME.SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION));
+ keyboard = builder.build();
+ } finally {
+ LocaleUtils.setSystemLocale(res, savedLocale);
+ }
+ sKeyboardCache.put(id, new SoftReference<Keyboard>(keyboard));
+
+ if (DEBUG_CACHE) {
+ Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": "
+ + ((ref == null) ? "LOAD" : "GCed") + " id=" + id);
+ }
+ } else if (DEBUG_CACHE) {
+ Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": HIT id=" + id);
+ }
+
+ // TODO: Remove setShiftLocked and setShift calls.
+ keyboard.setShiftLocked(false);
+ keyboard.setShifted(false);
+ return keyboard;
+ }
+
+ public static class Builder {
+ private final Context mContext;
+ private final Resources mResources;
+
+ private final Params mParams = new Params();
+
+ public Builder(Context context, EditorInfo editorInfo, SettingsValues settingsValues) {
+ mContext = context;
+ mResources = context.getResources();
+ final SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance();
+ final String packageName = context.getPackageName();
+ final Params params = mParams;
+
+ params.mMode = Utils.getKeyboardMode(editorInfo);
+ if (editorInfo != null) {
+ params.mInputType = editorInfo.inputType;
+ params.mImeOptions = editorInfo.imeOptions;
+ }
+ params.mSettingsKeyEnabled = settingsValues.isSettingsKeyEnabled();
+ @SuppressWarnings("deprecation")
+ final boolean noMicrophone = Utils.inPrivateImeOptions(
+ packageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo)
+ || Utils.inPrivateImeOptions(
+ null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo);
+ params.mVoiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo) && !noMicrophone;
+ params.mVoiceKeyOnMain = settingsValues.isVoiceKeyOnMain();
+ params.mNoSettingsKey = Utils.inPrivateImeOptions(
+ packageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo);
+ final boolean forceAscii = Utils.inPrivateImeOptions(
+ packageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo);
+ final boolean asciiCapable = subtypeSwitcher.currentSubtypeContainsExtraValueKey(
+ LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE);
+ params.mLocale = (forceAscii && !asciiCapable)
+ ? Locale.US : subtypeSwitcher.getInputLocale();
+ params.mOrientation = mResources.getConfiguration().orientation;
+ params.mWidth = mResources.getDisplayMetrics().widthPixels;
+ }
+
+ public KeyboardSet build() {
+ final Locale savedLocale = LocaleUtils.setSystemLocale(mResources, mParams.mLocale);
+ try {
+ parseKeyboardSet(mResources, R.xml.keyboard_set);
+ } catch (Exception e) {
+ //
+ } finally {
+ LocaleUtils.setSystemLocale(mResources, savedLocale);
+ }
+ return new KeyboardSet(mContext, mParams);
+ }
+
+ // TODO: Move this method to KeyboardSet
+ static KeyboardId getKeyboardId(int elementState, boolean isSymbols, Params params) {
+ final boolean hasShortcutKey = params.mVoiceKeyEnabled
+ && (isSymbols != params.mVoiceKeyOnMain);
+ return new KeyboardId(elementState, params.mLocale, params.mOrientation, params.mWidth,
+ params.mMode, params.mInputType, params.mImeOptions, params.mSettingsKeyEnabled,
+ params.mNoSettingsKey, params.mVoiceKeyEnabled, hasShortcutKey);
+ }
+
+ // TODO: Move this method to KeyboardSet
+ static int getElementState(int mode, boolean isSymbols, boolean isShift) {
+ switch (mode) {
+ case KeyboardId.MODE_PHONE:
+ return (isSymbols && isShift)
+ ? KeyboardId.ELEMENT_PHONE_SHIFT : KeyboardId.ELEMENT_PHONE;
+ case KeyboardId.MODE_NUMBER:
+ return KeyboardId.ELEMENT_NUMBER;
+ default:
+ if (isSymbols) {
+ return isShift ? KeyboardId.ELEMENT_SYMBOLS_SHIFT : KeyboardId.ELEMENT_SYMBOLS;
+ }
+ return KeyboardId.ELEMENT_ALPHABET;
+ }
+ }
+
+ private void parseKeyboardSet(Resources res, int resId) throws XmlPullParserException,
+ IOException {
+ final XmlResourceParser parser = res.getXml(resId);
+ try {
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_KEYBOARD_SET.equals(tag)) {
+ parseKeyboardSetContent(parser);
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET);
+ }
+ }
+ }
+ } finally {
+ parser.close();
+ }
+ }
+
+ private void parseKeyboardSetContent(XmlPullParser parser) throws XmlPullParserException,
+ IOException {
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_ELEMENT.equals(tag)) {
+ parseKeyboardSetElement(parser);
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET);
+ }
+ } else if (event == XmlPullParser.END_TAG) {
+ final String tag = parser.getName();
+ if (TAG_KEYBOARD_SET.equals(tag)) {
+ break;
+ } else {
+ throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEYBOARD_SET);
+ }
+ }
+ }
+ }
+
+ private void parseKeyboardSetElement(XmlPullParser parser) throws XmlPullParserException,
+ IOException {
+ final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.KeyboardSet_Element);
+ try {
+ XmlParseUtils.checkAttributeExists(a,
+ R.styleable.KeyboardSet_Element_elementName, "elementName",
+ TAG_ELEMENT, parser);
+ XmlParseUtils.checkAttributeExists(a,
+ R.styleable.KeyboardSet_Element_elementKeyboard, "elementKeyboard",
+ TAG_ELEMENT, parser);
+ XmlParseUtils.checkEndTag(TAG_ELEMENT, parser);
+
+ final int elementName = a.getInt(
+ R.styleable.KeyboardSet_Element_elementName, 0);
+ final int elementKeyboard = a.getResourceId(
+ R.styleable.KeyboardSet_Element_elementKeyboard, 0);
+ mParams.mElementKeyboards.put(elementName, elementKeyboard);
+ } finally {
+ a.recycle();
+ }
+ }
+ }
+
+ public static String parseKeyboardLocale(Resources res, int resId)
+ throws XmlPullParserException, IOException {
+ final XmlPullParser parser = res.getXml(resId);
+ if (parser == null)
+ return "";
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_KEYBOARD_SET.equals(tag)) {
+ final TypedArray keyboardSetAttr = res.obtainAttributes(
+ Xml.asAttributeSet(parser), R.styleable.KeyboardSet);
+ final String locale = keyboardSetAttr.getString(
+ R.styleable.KeyboardSet_keyboardLocale);
+ keyboardSetAttr.recycle();
+ return locale;
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET);
+ }
+ }
+ }
+ return "";
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index ac718fc62..e5097152b 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -18,10 +18,7 @@ package com.android.inputmethod.keyboard;
import android.content.Context;
import android.content.SharedPreferences;
-import android.content.res.Configuration;
import android.content.res.Resources;
-import android.text.TextUtils;
-import android.util.DisplayMetrics;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.InflateException;
@@ -30,25 +27,19 @@ import android.view.View;
import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
-import com.android.inputmethod.keyboard.internal.ModifierKeyState;
-import com.android.inputmethod.keyboard.internal.ShiftKeyState;
+import com.android.inputmethod.keyboard.internal.KeyboardState;
import com.android.inputmethod.latin.InputView;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
-import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.Settings;
+import com.android.inputmethod.latin.SettingsValues;
import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.Utils;
-import java.lang.ref.SoftReference;
-import java.util.HashMap;
-import java.util.Locale;
-
-public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener {
+public class KeyboardSwitcher implements KeyboardState.SwitchActions,
+ SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = KeyboardSwitcher.class.getSimpleName();
- private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG;
- public static final boolean DEBUG_STATE = false;
public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20110916";
private static final int[] KEYBOARD_THEMES = {
@@ -66,95 +57,21 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private InputView mCurrentInputView;
private LatinKeyboardView mKeyboardView;
private LatinIME mInputMethodService;
- private String mPackageName;
private Resources mResources;
- // TODO: Combine these key state objects with auto mode switch state.
- private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift");
- private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol");
-
- private KeyboardId mMainKeyboardId;
- private KeyboardId mSymbolsKeyboardId;
- private KeyboardId mSymbolsShiftedKeyboardId;
-
- private KeyboardId mCurrentId;
- private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache =
- new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
+ private KeyboardState mState;
- private KeyboardLayoutState mSavedKeyboardState = new KeyboardLayoutState();
+ private KeyboardSet mKeyboardSet;
/** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of
* what user actually typed. */
private boolean mIsAutoCorrectionActive;
- // 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 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;
-
- private static String mLayoutSwitchBackSymbols;
-
private int mThemeIndex = -1;
private Context mThemeContext;
private static final KeyboardSwitcher sInstance = new KeyboardSwitcher();
- private class KeyboardLayoutState {
- private boolean mIsValid;
- private boolean mIsAlphabetMode;
- private boolean mIsShiftLocked;
- private boolean mIsShifted;
-
- public void save() {
- if (mCurrentId == null) {
- return;
- }
- mIsAlphabetMode = isAlphabetMode();
- if (mIsAlphabetMode) {
- mIsShiftLocked = isShiftLocked();
- mIsShifted = !mIsShiftLocked && isShiftedOrShiftLocked();
- } else {
- mIsShiftLocked = false;
- mIsShifted = mCurrentId.equals(mSymbolsShiftedKeyboardId);
- }
- 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;
}
@@ -169,10 +86,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private void initInternal(LatinIME ims, SharedPreferences prefs) {
mInputMethodService = ims;
- mPackageName = ims.getPackageName();
mResources = ims.getResources();
mPrefs = prefs;
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
+ mState = new KeyboardState(this);
setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs));
prefs.registerOnSharedPreferenceChangeListener(this);
}
@@ -195,26 +112,35 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
if (mThemeIndex != themeIndex) {
mThemeIndex = themeIndex;
mThemeContext = new ContextThemeWrapper(context, KEYBOARD_THEMES[themeIndex]);
- mKeyboardCache.clear();
+ KeyboardSet.clearKeyboardCache();
}
}
- public void loadKeyboard(EditorInfo editorInfo, Settings.Values settingsValues) {
+ public void loadKeyboard(EditorInfo editorInfo, SettingsValues settingsValues) {
+ mKeyboardSet = new KeyboardSet.Builder(mThemeContext, editorInfo, settingsValues)
+ .build();
+ final KeyboardId mainKeyboardId = mKeyboardSet.getMainKeyboardId();
try {
- mMainKeyboardId = getKeyboardId(editorInfo, false, false, settingsValues);
- mSymbolsKeyboardId = getKeyboardId(editorInfo, true, false, settingsValues);
- mSymbolsShiftedKeyboardId = getKeyboardId(editorInfo, true, true, settingsValues);
- mLayoutSwitchBackSymbols = mResources.getString(R.string.layout_switch_back_symbols);
- setKeyboard(getKeyboard(mSavedKeyboardState.getKeyboardId()));
- mSavedKeyboardState.restore();
+ mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols),
+ hasDistinctMultitouch());
} catch (RuntimeException e) {
- Log.w(TAG, "loading keyboard failed: " + mMainKeyboardId, e);
- LatinImeLogger.logOnException(mMainKeyboardId.toString(), e);
+ Log.w(TAG, "loading keyboard failed: " + mainKeyboardId, e);
+ LatinImeLogger.logOnException(mainKeyboardId.toString(), e);
+ return;
+ }
+ // TODO: Should get rid of this special case handling for Phone Number layouts once we
+ // have separate layouts with unique KeyboardIds for alphabet and alphabet-shifted
+ // respectively.
+ if (mainKeyboardId.isPhoneKeyboard()) {
+ mState.onToggleAlphabetAndSymbols();
}
+ updateShiftState();
}
public void saveKeyboardState() {
- mSavedKeyboardState.save();
+ if (isKeyboardAvailable()) {
+ mState.onSaveKeyboardState();
+ }
}
public void onFinishInputView() {
@@ -229,132 +155,38 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
final Keyboard oldKeyboard = mKeyboardView.getKeyboard();
mKeyboardView.setKeyboard(keyboard);
mCurrentInputView.setKeyboardGeometry(keyboard.mTopPadding);
- mCurrentId = keyboard.mId;
- mSwitchState = getSwitchState(mCurrentId);
- updateShiftLockState(keyboard);
mKeyboardView.setKeyPreviewPopupEnabled(
- Settings.Values.isKeyPreviewPopupEnabled(mPrefs, mResources),
- Settings.Values.getKeyPreviewPopupDismissDelay(mPrefs, mResources));
+ SettingsValues.isKeyPreviewPopupEnabled(mPrefs, mResources),
+ SettingsValues.getKeyPreviewPopupDismissDelay(mPrefs, mResources));
+ mKeyboardView.updateAutoCorrectionState(mIsAutoCorrectionActive);
+ // If the cached keyboard had been switched to another keyboard while the language was
+ // displayed on its spacebar, it might have had arbitrary text fade factor. In such
+ // case, we should reset the text fade factor. It is also applicable to shortcut key.
+ mKeyboardView.updateSpacebar(0.0f,
+ mSubtypeSwitcher.needsToDisplayLanguage(keyboard.mId.mLocale));
+ mKeyboardView.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady());
final boolean localeChanged = (oldKeyboard == null)
|| !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged);
- updateShiftState();
- }
-
- 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);
- }
+ public boolean isAlphabetMode() {
+ final Keyboard keyboard = getKeyboard();
+ return keyboard != null && keyboard.mId.isAlphabetKeyboard();
}
- private LatinKeyboard getKeyboard(KeyboardId id) {
- final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id);
- LatinKeyboard keyboard = (ref == null) ? null : ref.get();
- if (keyboard == null) {
- final Locale savedLocale = LocaleUtils.setSystemLocale(mResources, id.mLocale);
- try {
- final LatinKeyboard.Builder builder = new LatinKeyboard.Builder(mThemeContext);
- builder.load(id);
- builder.setTouchPositionCorrectionEnabled(
- mSubtypeSwitcher.currentSubtypeContainsExtraValueKey(
- LatinIME.SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION));
- keyboard = builder.build();
- } finally {
- LocaleUtils.setSystemLocale(mResources, savedLocale);
- }
- mKeyboardCache.put(id, new SoftReference<LatinKeyboard>(keyboard));
-
- if (DEBUG_CACHE) {
- Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": "
- + ((ref == null) ? "LOAD" : "GCed") + " id=" + id
- + " theme=" + Keyboard.themeName(keyboard.mThemeId));
- }
- } else if (DEBUG_CACHE) {
- Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id
- + " theme=" + Keyboard.themeName(keyboard.mThemeId));
- }
-
- keyboard.onAutoCorrectionStateChanged(mIsAutoCorrectionActive);
- keyboard.setShiftLocked(false);
- keyboard.setShifted(false);
- // If the cached keyboard had been switched to another keyboard while the language was
- // displayed on its spacebar, it might have had arbitrary text fade factor. In such case,
- // we should reset the text fade factor. It is also applicable to shortcut key.
- keyboard.setSpacebarTextFadeFactor(0.0f, null);
- keyboard.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady(), null);
- return keyboard;
- }
-
- private KeyboardId getKeyboardId(EditorInfo editorInfo, final boolean isSymbols,
- final boolean isShift, Settings.Values settingsValues) {
- final int mode = Utils.getKeyboardMode(editorInfo);
- final int xmlId;
- switch (mode) {
- case KeyboardId.MODE_PHONE:
- xmlId = (isSymbols && isShift) ? R.xml.kbd_phone_shift : R.xml.kbd_phone;
- break;
- case KeyboardId.MODE_NUMBER:
- xmlId = R.xml.kbd_number;
- break;
- default:
- if (isSymbols) {
- xmlId = isShift ? R.xml.kbd_symbols_shift : R.xml.kbd_symbols;
- } else {
- xmlId = R.xml.kbd_qwerty;
- }
- break;
- }
-
- final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled();
- @SuppressWarnings("deprecation")
- final boolean noMicrophone = Utils.inPrivateImeOptions(
- mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo)
- || Utils.inPrivateImeOptions(
- null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo);
- final boolean voiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo)
- && !noMicrophone;
- final boolean voiceKeyOnMain = settingsValues.isVoiceKeyOnMain();
- final boolean noSettingsKey = Utils.inPrivateImeOptions(
- mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo);
- final boolean hasSettingsKey = settingsKeyEnabled && !noSettingsKey;
- final int f2KeyMode = getF2KeyMode(settingsKeyEnabled, noSettingsKey);
- final boolean hasShortcutKey = voiceKeyEnabled && (isSymbols != voiceKeyOnMain);
- final boolean forceAscii = Utils.inPrivateImeOptions(
- mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo);
- final boolean asciiCapable = mSubtypeSwitcher.currentSubtypeContainsExtraValueKey(
- LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE);
- final Locale locale = (forceAscii && !asciiCapable)
- ? Locale.US : mSubtypeSwitcher.getInputLocale();
- final Configuration conf = mResources.getConfiguration();
- final DisplayMetrics dm = mResources.getDisplayMetrics();
-
- return new KeyboardId(
- mResources.getResourceEntryName(xmlId), xmlId, locale, conf.orientation,
- dm.widthPixels, mode, editorInfo, hasSettingsKey, f2KeyMode, noSettingsKey,
- voiceKeyEnabled, hasShortcutKey);
- }
-
- public int getKeyboardMode() {
- return mCurrentId != null ? mCurrentId.mMode : KeyboardId.MODE_TEXT;
+ public boolean isInputViewShown() {
+ return mCurrentInputView != null && mCurrentInputView.isShown();
}
- public boolean isAlphabetMode() {
- return mCurrentId != null && mCurrentId.isAlphabetKeyboard();
+ public boolean isShiftedOrShiftLocked() {
+ final Keyboard keyboard = getKeyboard();
+ return keyboard != null && keyboard.isShiftedOrShiftLocked();
}
- public boolean isInputViewShown() {
- return mCurrentInputView != null && mCurrentInputView.isShown();
+ public boolean isManualTemporaryUpperCase() {
+ final Keyboard keyboard = getKeyboard();
+ return keyboard != null && keyboard.isManualTemporaryUpperCase();
}
public boolean isKeyboardAvailable() {
@@ -363,77 +195,50 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
return false;
}
- public LatinKeyboard getLatinKeyboard() {
+ public Keyboard getKeyboard() {
if (mKeyboardView != null) {
- final Keyboard keyboard = mKeyboardView.getKeyboard();
- if (keyboard instanceof LatinKeyboard)
- return (LatinKeyboard)keyboard;
+ return mKeyboardView.getKeyboard();
}
return null;
}
- public boolean isShiftedOrShiftLocked() {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null)
- return latinKeyboard.isShiftedOrShiftLocked();
- return false;
- }
-
- public boolean isShiftLocked() {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null)
- return latinKeyboard.isShiftLocked();
- return false;
- }
-
- private boolean isShiftLockShifted() {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null)
- return latinKeyboard.isShiftLockShifted();
- return false;
- }
-
- public boolean isAutomaticTemporaryUpperCase() {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null)
- return latinKeyboard.isAutomaticTemporaryUpperCase();
- return false;
- }
-
- public boolean isManualTemporaryUpperCase() {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null)
- return latinKeyboard.isManualTemporaryUpperCase();
- return false;
- }
-
- private boolean isManualTemporaryUpperCaseFromAuto() {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null)
- return latinKeyboard.isManualTemporaryUpperCaseFromAuto();
- return false;
- }
-
- private void setManualTemporaryUpperCase(boolean shifted) {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null) {
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void setShifted(int shiftMode) {
+ mInputMethodService.mHandler.cancelUpdateShiftState();
+ Keyboard keyboard = getKeyboard();
+ if (keyboard == null)
+ return;
+ if (shiftMode == AUTOMATIC_SHIFT) {
+ keyboard.setAutomaticTemporaryUpperCase();
+ } else {
+ final boolean shifted = (shiftMode == MANUAL_SHIFT);
// On non-distinct multi touch panel device, we should also turn off the shift locked
// state when shift key is pressed to go to normal mode.
- // On the other hand, on distinct multi touch panel device, turning off the shift locked
- // state with shift key pressing is handled by onReleaseShift().
- if (!hasDistinctMultitouch() && !shifted && latinKeyboard.isShiftLocked()) {
- latinKeyboard.setShiftLocked(false);
- }
- if (latinKeyboard.setShifted(shifted)) {
- mKeyboardView.invalidateAllKeys();
+ // On the other hand, on distinct multi touch panel device, turning off the shift
+ // locked state with shift key pressing is handled by onReleaseShift().
+ if (!hasDistinctMultitouch() && !shifted && mState.isShiftLocked()) {
+ keyboard.setShiftLocked(false);
}
+ keyboard.setShifted(shifted);
}
+ mKeyboardView.invalidateAllKeys();
}
- private void setShiftLocked(boolean shiftLocked) {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null && latinKeyboard.setShiftLocked(shiftLocked)) {
- mKeyboardView.invalidateAllKeys();
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void setShiftLocked(boolean shiftLocked) {
+ mInputMethodService.mHandler.cancelUpdateShiftState();
+ Keyboard keyboard = getKeyboard();
+ if (keyboard == null)
+ return;
+ keyboard.setShiftLocked(shiftLocked);
+ mKeyboardView.invalidateAllKeys();
+ if (!shiftLocked) {
+ // To be able to turn off caps lock by "double tap" on shift key, we should ignore
+ // the second tap of the "double tap" from now for a while because we just have
+ // already turned off caps lock above.
+ mKeyboardView.startIgnoringDoubleTap();
}
}
@@ -441,320 +246,93 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
* Toggle keyboard shift state triggered by user touch event.
*/
public void toggleShift() {
- mInputMethodService.mHandler.cancelUpdateShiftState();
- if (DEBUG_STATE)
- Log.d(TAG, "toggleShift:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " shiftKeyState=" + mShiftKeyState);
- if (isAlphabetMode()) {
- setManualTemporaryUpperCase(!isShiftedOrShiftLocked());
- } else {
- toggleShiftInSymbol();
- }
+ mState.onToggleShift();
}
+ /**
+ * Toggle caps lock state triggered by user touch event.
+ */
public void toggleCapsLock() {
- mInputMethodService.mHandler.cancelUpdateShiftState();
- if (DEBUG_STATE)
- Log.d(TAG, "toggleCapsLock:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " shiftKeyState=" + mShiftKeyState);
- if (isAlphabetMode()) {
- if (isShiftLocked()) {
- // Shift key is long pressed while caps lock state, we will toggle back to normal
- // state. And mark as if shift key is released.
- setShiftLocked(false);
- mShiftKeyState.onRelease();
- } else {
- setShiftLocked(true);
- }
- }
+ mState.onToggleCapsLock();
}
- private void setAutomaticTemporaryUpperCase() {
- if (mKeyboardView == null) return;
- final Keyboard keyboard = mKeyboardView.getKeyboard();
- if (keyboard == null) return;
- keyboard.setAutomaticTemporaryUpperCase();
- mKeyboardView.invalidateAllKeys();
+ /**
+ * Toggle between alphabet and symbols modes triggered by user touch event.
+ */
+ public void toggleAlphabetAndSymbols() {
+ mState.onToggleAlphabetAndSymbols();
}
/**
* Update keyboard shift state triggered by connected EditText status change.
*/
public void updateShiftState() {
- final ShiftKeyState shiftKeyState = mShiftKeyState;
- if (DEBUG_STATE)
- Log.d(TAG, "updateShiftState:"
- + " autoCaps=" + mInputMethodService.getCurrentAutoCapsState()
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " shiftKeyState=" + shiftKeyState
- + " isAlphabetMode=" + isAlphabetMode()
- + " isShiftLocked=" + isShiftLocked());
- if (isAlphabetMode()) {
- if (!isShiftLocked() && !shiftKeyState.isIgnoring()) {
- if (shiftKeyState.isReleasing() && mInputMethodService.getCurrentAutoCapsState()) {
- // Only when shift key is releasing, automatic temporary upper case will be set.
- setAutomaticTemporaryUpperCase();
- } else {
- setManualTemporaryUpperCase(shiftKeyState.isMomentary());
- }
- }
- } else {
- // In symbol keyboard mode, we should clear shift key state because only alphabet
- // keyboard has shift key.
- shiftKeyState.onRelease();
- }
- }
-
- public void changeKeyboardMode() {
- if (DEBUG_STATE)
- Log.d(TAG, "changeKeyboardMode:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " shiftKeyState=" + mShiftKeyState);
- toggleKeyboardMode();
- if (isShiftLocked() && isAlphabetMode())
- setShiftLocked(true);
- updateShiftState();
+ mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState());
}
public void onPressShift(boolean withSliding) {
- if (!isKeyboardAvailable())
- return;
- ShiftKeyState shiftKeyState = mShiftKeyState;
- if (DEBUG_STATE)
- Log.d(TAG, "onPressShift:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding);
- if (isAlphabetMode()) {
- if (isShiftLocked()) {
- // Shift key is pressed while caps lock state, we will treat this state as shifted
- // caps lock state and mark as if shift key pressed while normal state.
- shiftKeyState.onPress();
- setManualTemporaryUpperCase(true);
- } else if (isAutomaticTemporaryUpperCase()) {
- // Shift key is pressed while automatic temporary upper case, we have to move to
- // manual temporary upper case.
- shiftKeyState.onPress();
- setManualTemporaryUpperCase(true);
- } else if (isShiftedOrShiftLocked()) {
- // In manual upper case state, we just record shift key has been pressing while
- // shifted state.
- shiftKeyState.onPressOnShifted();
- } else {
- // In base layout, chording or manual temporary upper case mode is started.
- shiftKeyState.onPress();
- toggleShift();
- }
- } else {
- // In symbol mode, just toggle symbol and symbol more keyboard.
- shiftKeyState.onPress();
- toggleShift();
- mSwitchState = SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE;
- }
+ mState.onPressShift(withSliding);
}
public void onReleaseShift(boolean withSliding) {
- if (!isKeyboardAvailable())
- return;
- ShiftKeyState shiftKeyState = mShiftKeyState;
- if (DEBUG_STATE)
- Log.d(TAG, "onReleaseShift:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding);
- if (isAlphabetMode()) {
- if (shiftKeyState.isMomentary()) {
- // After chording input while normal state.
- toggleShift();
- } else if (isShiftLocked() && !isShiftLockShifted() && shiftKeyState.isPressing()
- && !withSliding) {
- // Shift has been long pressed, ignore this release.
- } else if (isShiftLocked() && !shiftKeyState.isIgnoring() && !withSliding) {
- // Shift has been pressed without chording while caps lock state.
- toggleCapsLock();
- // To be able to turn off caps lock by "double tap" on shift key, we should ignore
- // the second tap of the "double tap" from now for a while because we just have
- // already turned off caps lock above.
- mKeyboardView.startIgnoringDoubleTap();
- } else if (isShiftedOrShiftLocked() && shiftKeyState.isPressingOnShifted()
- && !withSliding) {
- // Shift has been pressed without chording while shifted state.
- toggleShift();
- } else if (isManualTemporaryUpperCaseFromAuto() && shiftKeyState.isPressing()
- && !withSliding) {
- // Shift has been pressed without chording while manual temporary upper case
- // 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();
+ mState.onReleaseShift(withSliding);
}
public void onPressSymbol() {
- if (DEBUG_STATE)
- Log.d(TAG, "onPressSymbol:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " symbolKeyState=" + mSymbolKeyState);
- changeKeyboardMode();
- mSymbolKeyState.onPress();
- mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL;
+ mState.onPressSymbol();
}
public void onReleaseSymbol() {
- if (DEBUG_STATE)
- Log.d(TAG, "onReleaseSymbol:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " symbolKeyState=" + mSymbolKeyState);
- // Snap back to the previous keyboard mode if the user chords the mode change key and
- // another key, then releases the mode change key.
- if (mSwitchState == SWITCH_STATE_CHORDING_ALPHA) {
- changeKeyboardMode();
- }
- mSymbolKeyState.onRelease();
+ mState.onReleaseSymbol();
}
public void onOtherKeyPressed() {
- if (DEBUG_STATE)
- Log.d(TAG, "onOtherKeyPressed:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " shiftKeyState=" + mShiftKeyState
- + " symbolKeyState=" + mSymbolKeyState);
- mShiftKeyState.onOtherKeyPressed();
- mSymbolKeyState.onOtherKeyPressed();
+ mState.onOtherKeyPressed();
}
public void onCancelInput() {
- // Snap back to the previous keyboard mode if the user cancels sliding input.
- if (getPointerCount() == 1) {
- if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) {
- changeKeyboardMode();
- } else if (mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE) {
- toggleShift();
- }
- }
+ mState.onCancelInput(isSinglePointer());
}
- private void toggleShiftInSymbol() {
- if (isAlphabetMode())
- return;
- final LatinKeyboard keyboard;
- if (mCurrentId.equals(mSymbolsKeyboardId)
- || !mCurrentId.equals(mSymbolsShiftedKeyboardId)) {
- keyboard = getKeyboard(mSymbolsShiftedKeyboardId);
- } else {
- keyboard = getKeyboard(mSymbolsKeyboardId);
- }
- setKeyboard(keyboard);
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void setSymbolsKeyboard() {
+ setKeyboard(mKeyboardSet.getSymbolsKeyboard());
+ }
+
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void setAlphabetKeyboard() {
+ setKeyboard(mKeyboardSet.getMainKeyboard());
+ }
+
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void setSymbolsShiftedKeyboard() {
+ setKeyboard(mKeyboardSet.getSymbolsShiftedKeyboard());
}
public boolean isInMomentarySwitchState() {
- return mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL
- || mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE;
+ return mState.isInMomentarySwitchState();
}
public boolean isVibrateAndSoundFeedbackRequired() {
return mKeyboardView != null && !mKeyboardView.isInSlidingKeyInput();
}
- private int getPointerCount() {
- return mKeyboardView == null ? 0 : mKeyboardView.getPointerCount();
- }
-
- private void toggleKeyboardMode() {
- if (mCurrentId.equals(mMainKeyboardId)) {
- setKeyboard(getKeyboard(mSymbolsKeyboardId));
- } else {
- setKeyboard(getKeyboard(mMainKeyboardId));
- }
+ private boolean isSinglePointer() {
+ return mKeyboardView != null && mKeyboardView.getPointerCount() == 1;
}
public boolean hasDistinctMultitouch() {
return mKeyboardView != null && mKeyboardView.hasDistinctMultitouch();
}
- private static boolean isSpaceCharacter(int c) {
- return c == Keyboard.CODE_SPACE || c == Keyboard.CODE_ENTER;
- }
-
- private static boolean isLayoutSwitchBackCharacter(int c) {
- if (TextUtils.isEmpty(mLayoutSwitchBackSymbols)) return false;
- if (mLayoutSwitchBackSymbols.indexOf(c) >= 0) return true;
- return false;
- }
-
/**
* Updates state machine to figure out when to automatically snap back to the previous mode.
*/
- public void onKey(int code) {
- if (DEBUG_STATE)
- Log.d(TAG, "onKey: code=" + code + " switchState=" + mSwitchState
- + " pointers=" + getPointerCount());
- 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 #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 (mCurrentId.equals(mMainKeyboardId)) {
- mSwitchState = SWITCH_STATE_ALPHA;
- } else {
- mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
- }
- } else if (getPointerCount() == 1) {
- // Snap back to the previous keyboard mode if the user pressed the mode change key
- // and slid to other key, then released the finger.
- // If the user cancels the sliding input, snapping back to the previous keyboard
- // mode is handled by {@link #onCancelInput}.
- changeKeyboardMode();
- } 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.
- 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 SWITCH_STATE_SYMBOL_BEGIN:
- if (!isSpaceCharacter(code) && code >= 0) {
- mSwitchState = SWITCH_STATE_SYMBOL;
- }
- // Snap back to alpha keyboard mode immediately if user types a quote character.
- if (isLayoutSwitchBackCharacter(code)) {
- changeKeyboardMode();
- }
- break;
- 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 or a quote character.
- if (isSpaceCharacter(code) || isLayoutSwitchBackCharacter(code)) {
- changeKeyboardMode();
- }
- break;
- }
+ public void onCodeInput(int code) {
+ mState.onCodeInput(code, isSinglePointer(), mInputMethodService.getCurrentAutoCapsState());
}
public LatinKeyboardView getKeyboardView() {
@@ -804,13 +382,14 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
}
private void postSetInputView(final View newInputView) {
- mInputMethodService.mHandler.post(new Runnable() {
+ final LatinIME latinIme = mInputMethodService;
+ latinIme.mHandler.post(new Runnable() {
@Override
public void run() {
if (newInputView != null) {
- mInputMethodService.setInputView(newInputView);
+ latinIme.setInputView(newInputView);
}
- mInputMethodService.updateInputViewShown();
+ latinIme.updateInputViewShown();
}
});
}
@@ -825,31 +404,31 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
}
}
+ public void onNetworkStateChanged() {
+ if (mKeyboardView != null) {
+ mKeyboardView.updateShortcutKey(SubtypeSwitcher.getInstance().isShortcutImeReady());
+ }
+ }
+
public void onAutoCorrectionStateChanged(boolean isAutoCorrection) {
if (mIsAutoCorrectionActive != isAutoCorrection) {
mIsAutoCorrectionActive = isAutoCorrection;
- final LatinKeyboard keyboard = getLatinKeyboard();
- if (keyboard != null && keyboard.needsAutoCorrectionSpacebarLed()) {
- final Key invalidatedKey = keyboard.onAutoCorrectionStateChanged(isAutoCorrection);
- final LatinKeyboardView keyboardView = getKeyboardView();
- if (keyboardView != null)
- keyboardView.invalidateKey(invalidatedKey);
+ if (mKeyboardView != null) {
+ mKeyboardView.updateAutoCorrectionState(isAutoCorrection);
}
}
}
- private static int getF2KeyMode(boolean settingsKeyEnabled, boolean noSettingsKey) {
- if (noSettingsKey) {
- // Never shows the Settings key
- return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
- }
-
- if (settingsKeyEnabled) {
- return KeyboardId.F2KEY_MODE_SETTINGS;
- } else {
- // It should be alright to fall back to the Settings key on 7-inch layouts
- // even when the Settings key is not explicitly enabled.
- return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
+ private static String themeName(int themeId) {
+ // This should be aligned with theme-*.xml resource files' themeId attribute.
+ switch (themeId) {
+ case 0: return "Basic";
+ case 1: return "BasicHighContrast";
+ case 5: return "IceCreamSandwich";
+ case 6: return "Stone";
+ case 7: return "StoneBold";
+ case 8: return "GingerBread";
+ default: return null;
}
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 04e672590..abc220e34 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -148,7 +148,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
final PointerTracker tracker = (PointerTracker) msg.obj;
switch (msg.what) {
case MSG_SHOW_KEY_PREVIEW:
- keyboardView.showKey(msg.arg1, tracker);
+ keyboardView.showKey(tracker);
break;
case MSG_DISMISS_KEY_PREVIEW:
tracker.getKeyPreviewText().setVisibility(View.INVISIBLE);
@@ -156,16 +156,15 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
}
- public void showKeyPreview(long delay, int keyIndex, PointerTracker tracker) {
+ public void showKeyPreview(long delay, PointerTracker tracker) {
removeMessages(MSG_SHOW_KEY_PREVIEW);
final KeyboardView keyboardView = getOuterInstance();
if (keyboardView == null) return;
if (tracker.getKeyPreviewText().getVisibility() == VISIBLE || delay == 0) {
// Show right away, if it's already visible and finger is moving around
- keyboardView.showKey(keyIndex, tracker);
+ keyboardView.showKey(tracker);
} else {
- sendMessageDelayed(
- obtainMessage(MSG_SHOW_KEY_PREVIEW, keyIndex, 0, tracker), delay);
+ sendMessageDelayed(obtainMessage(MSG_SHOW_KEY_PREVIEW, tracker), delay);
}
}
@@ -195,7 +194,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
}
- private static class KeyDrawParams {
+ /* package */ static class KeyDrawParams {
// XML attributes
public final int mKeyTextColor;
public final int mKeyTextInactivatedColor;
@@ -284,7 +283,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
}
- protected static class KeyPreviewDrawParams {
+ /* package */ static class KeyPreviewDrawParams {
// XML attributes.
public final Drawable mPreviewBackground;
public final Drawable mPreviewLeftBackground;
@@ -475,7 +474,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
if (mKeyboard == null) return;
- final boolean isManualTemporaryUpperCase = mKeyboard.isManualTemporaryUpperCase();
final KeyDrawParams params = mKeyDrawParams;
if (mInvalidatedKey != null && mInvalidatedKeyRect.contains(mDirtyRect)) {
// Draw a single key.
@@ -483,8 +481,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
+ getPaddingLeft();
final int keyDrawY = mInvalidatedKey.mY + getPaddingTop();
canvas.translate(keyDrawX, keyDrawY);
- onBufferDrawKey(mInvalidatedKey, mKeyboard, canvas, mPaint, params,
- isManualTemporaryUpperCase);
+ onDrawKey(mInvalidatedKey, canvas, mPaint, params);
canvas.translate(-keyDrawX, -keyDrawY);
} else {
// Draw all keys.
@@ -492,7 +489,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
final int keyDrawX = key.mX + key.mVisualInsetsLeft + getPaddingLeft();
final int keyDrawY = key.mY + getPaddingTop();
canvas.translate(keyDrawX, keyDrawY);
- onBufferDrawKey(key, mKeyboard, canvas, mPaint, params, isManualTemporaryUpperCase);
+ onDrawKey(key, canvas, mPaint, params);
canvas.translate(-keyDrawX, -keyDrawY);
}
}
@@ -515,38 +512,43 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
}
- private static void onBufferDrawKey(final Key key, final Keyboard keyboard, final Canvas canvas,
- Paint paint, KeyDrawParams params, boolean isManualTemporaryUpperCase) {
- final boolean debugShowAlign = LatinImeLogger.sVISUALDEBUG;
- // Draw key background.
- if (!key.isSpacer()) {
- final int bgWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight
- + params.mPadding.left + params.mPadding.right;
- final int bgHeight = key.mHeight + params.mPadding.top + params.mPadding.bottom;
- final int bgX = -params.mPadding.left;
- final int bgY = -params.mPadding.top;
- final int[] drawableState = key.getCurrentDrawableState();
- final Drawable background = params.mKeyBackground;
- background.setState(drawableState);
- final Rect bounds = background.getBounds();
- if (bgWidth != bounds.right || bgHeight != bounds.bottom) {
- background.setBounds(0, 0, bgWidth, bgHeight);
- }
- canvas.translate(bgX, bgY);
- background.draw(canvas);
- if (debugShowAlign) {
- drawRectangle(canvas, 0, 0, bgWidth, bgHeight, 0x80c00000, new Paint());
- }
- canvas.translate(-bgX, -bgY);
+ private void onDrawKey(Key key, Canvas canvas, Paint paint, KeyDrawParams params) {
+ if (key.isSpacer()) return;
+ onDrawKeyBackground(key, canvas, params);
+ onDrawKeyTopVisuals(key, canvas, paint, params);
+ }
+
+ // Draw key background.
+ /* package */ void onDrawKeyBackground(Key key, Canvas canvas, KeyDrawParams params) {
+ final int bgWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight
+ + params.mPadding.left + params.mPadding.right;
+ final int bgHeight = key.mHeight + params.mPadding.top + params.mPadding.bottom;
+ final int bgX = -params.mPadding.left;
+ final int bgY = -params.mPadding.top;
+ final int[] drawableState = key.getCurrentDrawableState();
+ final Drawable background = params.mKeyBackground;
+ background.setState(drawableState);
+ final Rect bounds = background.getBounds();
+ if (bgWidth != bounds.right || bgHeight != bounds.bottom) {
+ background.setBounds(0, 0, bgWidth, bgHeight);
+ }
+ canvas.translate(bgX, bgY);
+ background.draw(canvas);
+ if (LatinImeLogger.sVISUALDEBUG) {
+ drawRectangle(canvas, 0, 0, bgWidth, bgHeight, 0x80c00000, new Paint());
}
+ canvas.translate(-bgX, -bgY);
+ }
- // Draw key top visuals.
+ // Draw key top visuals.
+ /* package */ void onDrawKeyTopVisuals(Key key, Canvas canvas, Paint paint,
+ KeyDrawParams params) {
final int keyWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight;
final int keyHeight = key.mHeight;
final float centerX = keyWidth * 0.5f;
final float centerY = keyHeight * 0.5f;
- if (debugShowAlign) {
+ if (LatinImeLogger.sVISUALDEBUG) {
drawRectangle(canvas, 0, 0, keyWidth, keyHeight, 0x800000c0, new Paint());
}
@@ -555,7 +557,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
float positionX = centerX;
if (key.mLabel != null) {
// Switch the character to uppercase if shift is pressed
- final CharSequence label = keyboard.adjustLabelCase(key.mLabel);
+ final CharSequence label = mKeyboard.adjustLabelCase(key.mLabel);
// For characters, use large font. For labels like "Done", use smaller font.
paint.setTypeface(key.selectTypeface(params.mKeyTextStyle));
final int labelSize = key.selectTextSize(params.mKeyLetterSize,
@@ -598,7 +600,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
Math.min(1.0f, (keyWidth * MAX_LABEL_RATIO) / getLabelWidth(label, paint)));
}
- if (key.hasUppercaseLetter() && isManualTemporaryUpperCase) {
+ if (key.hasUppercaseLetter() && mKeyboard.isManualTemporaryUpperCase()) {
paint.setColor(params.mKeyTextInactivatedColor);
} else {
paint.setColor(params.mKeyTextColor);
@@ -628,7 +630,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
}
- if (debugShowAlign) {
+ if (LatinImeLogger.sVISUALDEBUG) {
final Paint line = new Paint();
drawHorizontalLine(canvas, baseline, keyWidth, 0xc0008000, line);
drawVerticalLine(canvas, positionX, keyHeight, 0xc0800080, line);
@@ -645,7 +647,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
hintSize = params.mKeyHintLabelSize;
paint.setTypeface(Typeface.DEFAULT);
} else if (key.hasUppercaseLetter()) {
- hintColor = isManualTemporaryUpperCase
+ hintColor = mKeyboard.isManualTemporaryUpperCase()
? params.mKeyUppercaseLetterActivatedColor
: params.mKeyUppercaseLetterInactivatedColor;
hintSize = params.mKeyUppercaseLetterSize;
@@ -678,7 +680,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
canvas.drawText(hint, 0, hint.length(), hintX, hintY, paint);
- if (debugShowAlign) {
+ if (LatinImeLogger.sVISUALDEBUG) {
final Paint line = new Paint();
drawHorizontalLine(canvas, (int)hintY, keyWidth, 0xc0808000, line);
drawVerticalLine(canvas, (int)hintX, keyHeight, 0xc0808000, line);
@@ -703,29 +705,35 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight);
- if (debugShowAlign) {
+ if (LatinImeLogger.sVISUALDEBUG) {
final Paint line = new Paint();
drawVerticalLine(canvas, alignX, keyHeight, 0xc0800080, line);
drawRectangle(canvas, iconX, iconY, iconWidth, iconHeight, 0x80c00000, line);
}
}
- // Draw popup hint "..." at the bottom right corner of the key.
- if ((key.hasPopupHint() && key.mMoreKeys != null && key.mMoreKeys.length > 0)
- || key.needsSpecialPopupHint()) {
- paint.setTextSize(params.mKeyHintLetterSize);
- paint.setColor(params.mKeyHintLabelColor);
- paint.setTextAlign(Align.CENTER);
- final float hintX = keyWidth - params.mKeyHintLetterPadding
- - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
- final float hintY = keyHeight - params.mKeyPopupHintLetterPadding;
- canvas.drawText(POPUP_HINT_CHAR, hintX, hintY, paint);
+ if (key.hasPopupHint() && key.mMoreKeys != null && key.mMoreKeys.length > 0) {
+ drawKeyPopupHint(key, canvas, paint, params);
+ }
+ }
- if (debugShowAlign) {
- final Paint line = new Paint();
- drawHorizontalLine(canvas, (int)hintY, keyWidth, 0xc0808000, line);
- drawVerticalLine(canvas, (int)hintX, keyHeight, 0xc0808000, line);
- }
+ // Draw popup hint "..." at the bottom right corner of the key.
+ /* package */ void drawKeyPopupHint(Key key, Canvas canvas, Paint paint, KeyDrawParams params) {
+ final int keyWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight;
+ final int keyHeight = key.mHeight;
+
+ paint.setTextSize(params.mKeyHintLetterSize);
+ paint.setColor(params.mKeyHintLabelColor);
+ paint.setTextAlign(Align.CENTER);
+ final float hintX = keyWidth - params.mKeyHintLetterPadding
+ - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
+ final float hintY = keyHeight - params.mKeyPopupHintLetterPadding;
+ canvas.drawText(POPUP_HINT_CHAR, hintX, hintY, paint);
+
+ if (LatinImeLogger.sVISUALDEBUG) {
+ final Paint line = new Paint();
+ drawHorizontalLine(canvas, (int)hintY, keyWidth, 0xc0808000, line);
+ drawVerticalLine(canvas, (int)hintX, keyHeight, 0xc0808000, line);
}
}
@@ -830,9 +838,9 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
@Override
- public void showKeyPreview(int keyIndex, PointerTracker tracker) {
+ public void showKeyPreview(PointerTracker tracker) {
if (mShowKeyPreviewPopup) {
- mDrawingHandler.showKeyPreview(mDelayBeforePreview, keyIndex, tracker);
+ mDrawingHandler.showKeyPreview(mDelayBeforePreview, tracker);
}
}
@@ -858,7 +866,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
keyPreview, FrameLayoutCompatUtils.newLayoutParam(mPreviewPlacer, 0, 0));
}
- private void showKey(final int keyIndex, PointerTracker tracker) {
+ private void showKey(PointerTracker tracker) {
final TextView previewText = tracker.getKeyPreviewText();
// If the key preview has no parent view yet, add it to the ViewGroup which can place
// key preview absolutely in SoftInputWindow.
@@ -867,8 +875,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
mDrawingHandler.cancelDismissKeyPreview(tracker);
- final Key key = tracker.getKey(keyIndex);
- // If keyIndex is invalid or IME is already closed, we must not show key preview.
+ final Key key = tracker.getKey();
+ // If key is invalid or IME is already closed, we must not show key preview.
// Trying to show key preview while root window is closed causes
// WindowManager.BadTokenException.
if (key == null)
@@ -890,7 +898,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
previewText.setText(mKeyboard.adjustLabelCase(key.mLabel));
} else {
- final Drawable previewIcon = key.getPreviewIcon();
+ final Drawable previewIcon = key.mPreviewIcon;
previewText.setCompoundDrawables(null, null, null,
previewIcon != null ? previewIcon : key.getIcon());
previewText.setText(null);
@@ -906,12 +914,16 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
int previewX = keyDrawX - (previewWidth - keyDrawWidth) / 2 + params.mCoordinates[0];
final int previewY = key.mY - previewHeight
+ params.mCoordinates[1] + params.mPreviewOffset;
- if (previewX < 0 && params.mPreviewLeftBackground != null) {
- previewText.setBackgroundDrawable(params.mPreviewLeftBackground);
+ if (previewX < 0) {
previewX = 0;
- } else if (previewX + previewWidth > getWidth() && params.mPreviewRightBackground != null) {
- previewText.setBackgroundDrawable(params.mPreviewRightBackground);
+ if (params.mPreviewLeftBackground != null) {
+ previewText.setBackgroundDrawable(params.mPreviewLeftBackground);
+ }
+ } else if (previewX > getWidth() - previewWidth) {
previewX = getWidth() - previewWidth;
+ if (params.mPreviewRightBackground != null) {
+ previewText.setBackgroundDrawable(params.mPreviewRightBackground);
+ }
}
// Set the preview background state
@@ -932,6 +944,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
public void invalidateAllKeys() {
mDirtyRect.union(0, 0, getWidth(), getHeight());
mBufferNeedsUpdate = true;
+ mInvalidatedKey = null;
invalidate();
}
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
deleted file mode 100644
index 762039625..000000000
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.keyboard;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.Resources.Theme;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-
-import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
-import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
-import com.android.inputmethod.keyboard.internal.KeyboardParams;
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SubtypeSwitcher;
-import com.android.inputmethod.latin.Utils;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Locale;
-
-// TODO: We should remove this class
-public class LatinKeyboard extends Keyboard {
- private static final int SPACE_LED_LENGTH_PERCENT = 80;
-
- private final Resources mRes;
- private final Theme mTheme;
- private final SubtypeSwitcher mSubtypeSwitcher = SubtypeSwitcher.getInstance();
-
- /* Space key and its icons, drawables and colors. */
- private final Key mSpaceKey;
- private final Drawable mSpaceIcon;
- private final boolean mAutoCorrectionSpacebarLedEnabled;
- private final Drawable mAutoCorrectionSpacebarLedIcon;
- private final int mSpacebarTextColor;
- private final int mSpacebarTextShadowColor;
- private float mSpacebarTextFadeFactor = 0.0f;
- private final HashMap<Integer, BitmapDrawable> mSpaceDrawableCache =
- new HashMap<Integer, BitmapDrawable>();
- private final boolean mIsSpacebarTriggeringPopupByLongPress;
-
- /* Shortcut key and its icons if available */
- private final Key mShortcutKey;
- private final Drawable mEnabledShortcutIcon;
- private final Drawable mDisabledShortcutIcon;
-
- // Height in space key the language name will be drawn. (proportional to space key height)
- public static final float SPACEBAR_LANGUAGE_BASELINE = 0.6f;
- // If the full language name needs to be smaller than this value to be drawn on space key,
- // its short language name will be used instead.
- private static final float MINIMUM_SCALE_OF_LANGUAGE_NAME = 0.8f;
-
- private static final String SMALL_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR = "small";
- private static final String MEDIUM_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR = "medium";
-
- private LatinKeyboard(Context context, LatinKeyboardParams params) {
- super(params);
- mRes = context.getResources();
- mTheme = context.getTheme();
-
- // The index of space key is available only after Keyboard constructor has finished.
- mSpaceKey = params.mSpaceKey;
- mSpaceIcon = (mSpaceKey != null) ? mSpaceKey.getIcon() : null;
-
- mShortcutKey = params.mShortcutKey;
- mEnabledShortcutIcon = (mShortcutKey != null) ? mShortcutKey.getIcon() : null;
- final int longPressSpaceKeyTimeout =
- mRes.getInteger(R.integer.config_long_press_space_key_timeout);
- mIsSpacebarTriggeringPopupByLongPress = (longPressSpaceKeyTimeout > 0);
-
- final TypedArray a = context.obtainStyledAttributes(
- null, R.styleable.LatinKeyboard, R.attr.latinKeyboardStyle, R.style.LatinKeyboard);
- mAutoCorrectionSpacebarLedEnabled = a.getBoolean(
- R.styleable.LatinKeyboard_autoCorrectionSpacebarLedEnabled, false);
- mAutoCorrectionSpacebarLedIcon = a.getDrawable(
- R.styleable.LatinKeyboard_autoCorrectionSpacebarLedIcon);
- mDisabledShortcutIcon = a.getDrawable(R.styleable.LatinKeyboard_disabledShortcutIcon);
- mSpacebarTextColor = a.getColor(R.styleable.LatinKeyboard_spacebarTextColor, 0);
- mSpacebarTextShadowColor = a.getColor(
- R.styleable.LatinKeyboard_spacebarTextShadowColor, 0);
- a.recycle();
- }
-
- private static class LatinKeyboardParams extends KeyboardParams {
- public Key mSpaceKey = null;
- public Key mShortcutKey = null;
-
- @Override
- public void onAddKey(Key key) {
- super.onAddKey(key);
-
- switch (key.mCode) {
- case Keyboard.CODE_SPACE:
- mSpaceKey = key;
- break;
- case Keyboard.CODE_SHORTCUT:
- mShortcutKey = key;
- break;
- }
- }
- }
-
- public static class Builder extends KeyboardBuilder<LatinKeyboardParams> {
- public Builder(Context context) {
- super(context, new LatinKeyboardParams());
- }
-
- @Override
- public Builder load(KeyboardId id) {
- super.load(id);
- return this;
- }
-
- @Override
- public LatinKeyboard build() {
- return new LatinKeyboard(mContext, mParams);
- }
- }
-
- public void setSpacebarTextFadeFactor(float fadeFactor, KeyboardView view) {
- mSpacebarTextFadeFactor = fadeFactor;
- updateSpacebarForLocale(false);
- if (view != null)
- view.invalidateKey(mSpaceKey);
- }
-
- private static int getSpacebarTextColor(int color, float fadeFactor) {
- final int newColor = Color.argb((int)(Color.alpha(color) * fadeFactor),
- Color.red(color), Color.green(color), Color.blue(color));
- return newColor;
- }
-
- public void updateShortcutKey(boolean available, KeyboardView view) {
- if (mShortcutKey == null)
- return;
- mShortcutKey.setEnabled(available);
- mShortcutKey.setIcon(available ? mEnabledShortcutIcon : mDisabledShortcutIcon);
- if (view != null)
- view.invalidateKey(mShortcutKey);
- }
-
- public boolean needsAutoCorrectionSpacebarLed() {
- return mAutoCorrectionSpacebarLedEnabled;
- }
-
- /**
- * @return a key which should be invalidated.
- */
- public Key onAutoCorrectionStateChanged(boolean isAutoCorrection) {
- updateSpacebarForLocale(isAutoCorrection);
- return mSpaceKey;
- }
-
- @Override
- public CharSequence adjustLabelCase(CharSequence label) {
- if (isAlphaKeyboard() && isShiftedOrShiftLocked() && !TextUtils.isEmpty(label)
- && label.length() < 3 && Character.isLowerCase(label.charAt(0))) {
- return label.toString().toUpperCase(mId.mLocale);
- }
- return label;
- }
-
- private void updateSpacebarForLocale(boolean isAutoCorrection) {
- if (mSpaceKey == null) return;
- final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance();
- if (imm == null) return;
- // The "..." popup hint for triggering something by a long-pressing the spacebar
- final boolean shouldShowInputMethodPicker = mIsSpacebarTriggeringPopupByLongPress
- && Utils.hasMultipleEnabledIMEsOrSubtypes(imm, true /* include aux subtypes */);
- mSpaceKey.setNeedsSpecialPopupHint(shouldShowInputMethodPicker);
- // If application locales are explicitly selected.
- if (mSubtypeSwitcher.needsToDisplayLanguage(mId.mLocale)) {
- mSpaceKey.setIcon(getSpaceDrawable(mId.mLocale, isAutoCorrection));
- } else if (isAutoCorrection) {
- mSpaceKey.setIcon(getSpaceDrawable(null, true));
- } else {
- mSpaceKey.setIcon(mSpaceIcon);
- }
- }
-
- // Compute width of text with specified text size using paint.
- private static int getTextWidth(Paint paint, String text, float textSize, Rect bounds) {
- paint.setTextSize(textSize);
- paint.getTextBounds(text, 0, text.length(), bounds);
- return bounds.width();
- }
-
- // Layout local language name and left and right arrow on spacebar.
- private static String layoutSpacebar(Paint paint, Locale locale, int width,
- float origTextSize) {
- final Rect bounds = new Rect();
-
- // Estimate appropriate language name text size to fit in maxTextWidth.
- String language = Utils.getFullDisplayName(locale, true);
- int textWidth = getTextWidth(paint, language, origTextSize, bounds);
- // Assuming text width and text size are proportional to each other.
- float textSize = origTextSize * Math.min(width / textWidth, 1.0f);
- // allow variable text size
- textWidth = getTextWidth(paint, language, textSize, bounds);
- // If text size goes too small or text does not fit, use middle or short name
- final boolean useMiddleName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME)
- || (textWidth > width);
-
- final boolean useShortName;
- if (useMiddleName) {
- language = Utils.getMiddleDisplayLanguage(locale);
- textWidth = getTextWidth(paint, language, origTextSize, bounds);
- textSize = origTextSize * Math.min(width / textWidth, 1.0f);
- useShortName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME)
- || (textWidth > width);
- } else {
- useShortName = false;
- }
-
- if (useShortName) {
- language = Utils.getShortDisplayLanguage(locale);
- textWidth = getTextWidth(paint, language, origTextSize, bounds);
- textSize = origTextSize * Math.min(width / textWidth, 1.0f);
- }
- paint.setTextSize(textSize);
-
- return language;
- }
-
- private BitmapDrawable getSpaceDrawable(Locale locale, boolean isAutoCorrection) {
- final Integer hashCode = Arrays.hashCode(
- new Object[] { locale, isAutoCorrection, mSpacebarTextFadeFactor });
- final BitmapDrawable cached = mSpaceDrawableCache.get(hashCode);
- if (cached != null) {
- return cached;
- }
- final BitmapDrawable drawable = new BitmapDrawable(mRes, drawSpacebar(
- locale, isAutoCorrection, mSpacebarTextFadeFactor));
- mSpaceDrawableCache.put(hashCode, drawable);
- return drawable;
- }
-
- private Bitmap drawSpacebar(Locale inputLocale, boolean isAutoCorrection,
- float textFadeFactor) {
- final int width = mSpaceKey.mWidth;
- final int height = mSpaceIcon != null ? mSpaceIcon.getIntrinsicHeight() : mSpaceKey.mHeight;
- final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- final Canvas canvas = new Canvas(buffer);
- final Resources res = mRes;
- canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
-
- // If application locales are explicitly selected.
- if (inputLocale != null) {
- final Paint paint = new Paint();
- paint.setAntiAlias(true);
- paint.setTextAlign(Align.CENTER);
-
- final String textSizeOfLanguageOnSpacebar = res.getString(
- R.string.config_text_size_of_language_on_spacebar,
- SMALL_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR);
- final int textStyle;
- final int defaultTextSize;
- if (MEDIUM_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR.equals(textSizeOfLanguageOnSpacebar)) {
- textStyle = android.R.style.TextAppearance_Medium;
- defaultTextSize = 18;
- } else {
- textStyle = android.R.style.TextAppearance_Small;
- defaultTextSize = 14;
- }
-
- final String language = layoutSpacebar(paint, inputLocale, width, getTextSizeFromTheme(
- mTheme, textStyle, defaultTextSize));
-
- // Draw language text with shadow
- // In case there is no space icon, we will place the language text at the center of
- // spacebar.
- final float descent = paint.descent();
- final float textHeight = -paint.ascent() + descent;
- final float baseline = (mSpaceIcon != null) ? height * SPACEBAR_LANGUAGE_BASELINE
- : height / 2 + textHeight / 2;
- paint.setColor(getSpacebarTextColor(mSpacebarTextShadowColor, textFadeFactor));
- canvas.drawText(language, width / 2, baseline - descent - 1, paint);
- paint.setColor(getSpacebarTextColor(mSpacebarTextColor, textFadeFactor));
- canvas.drawText(language, width / 2, baseline - descent, paint);
- }
-
- // Draw the spacebar icon at the bottom
- if (isAutoCorrection) {
- final int iconWidth = width * SPACE_LED_LENGTH_PERCENT / 100;
- final int iconHeight = mAutoCorrectionSpacebarLedIcon.getIntrinsicHeight();
- int x = (width - iconWidth) / 2;
- int y = height - iconHeight;
- mAutoCorrectionSpacebarLedIcon.setBounds(x, y, x + iconWidth, y + iconHeight);
- mAutoCorrectionSpacebarLedIcon.draw(canvas);
- } else if (mSpaceIcon != null) {
- final int iconWidth = mSpaceIcon.getIntrinsicWidth();
- final int iconHeight = mSpaceIcon.getIntrinsicHeight();
- int x = (width - iconWidth) / 2;
- int y = height - iconHeight;
- mSpaceIcon.setBounds(x, y, x + iconWidth, y + iconHeight);
- mSpaceIcon.draw(canvas);
- }
- return buffer;
- }
-
- @Override
- public int[] getNearestKeys(int x, int y) {
- // Avoid dead pixels at edges of the keyboard
- return super.getNearestKeys(Math.max(0, Math.min(x, mOccupiedWidth - 1)),
- Math.max(0, Math.min(y, mOccupiedHeight - 1)));
- }
-
- private static final int[] ATTR_TEXT_SIZE = { android.R.attr.textSize };
-
- public static int getTextSizeFromTheme(Theme theme, int style, int defValue) {
- final TypedArray a = theme.obtainStyledAttributes(style, ATTR_TEXT_SIZE);
- final int textSize = a.getDimensionPixelSize(a.getResourceId(0, 0), defValue);
- a.recycle();
- return textSize;
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 6ce3876b6..3433cd455 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -19,9 +19,18 @@ package com.android.inputmethod.keyboard;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
import android.os.Message;
-import android.os.SystemClock;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
@@ -39,10 +48,15 @@ import com.android.inputmethod.deprecated.VoiceProxy;
import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy;
import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
import com.android.inputmethod.latin.LatinIME;
+import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
import com.android.inputmethod.latin.Utils;
+import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Locale;
import java.util.WeakHashMap;
/**
@@ -58,11 +72,39 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
private static final boolean ENABLE_CAPSLOCK_BY_DOUBLETAP = true;
+ /* Space key and its icons, drawables and colors. */
+ private Key mSpaceKey;
+ private Drawable mSpaceIcon;
+ private final boolean mIsSpacebarTriggeringPopupByLongPress;
+ private static final int SPACE_LED_LENGTH_PERCENT = 80;
+ private final boolean mAutoCorrectionSpacebarLedEnabled;
+ private final Drawable mAutoCorrectionSpacebarLedIcon;
+ private final float mSpacebarTextRatio;
+ private float mSpacebarTextSize;
+ private final int mSpacebarTextColor;
+ private final int mSpacebarTextShadowColor;
+ private final HashMap<Integer, BitmapDrawable> mSpacebarDrawableCache =
+ new HashMap<Integer, BitmapDrawable>();
+
+ private boolean mAutoCorrectionSpacebarLedOn;
+ private boolean mNeedsToDisplayLanguage;
+ private Locale mSpacebarLocale;
+ private float mSpacebarTextFadeFactor = 0.0f;
+
+ // Height in space key the language name will be drawn. (proportional to space key height)
+ public static final float SPACEBAR_LANGUAGE_BASELINE = 0.6f;
+ // If the full language name needs to be smaller than this value to be drawn on space key,
+ // its short language name will be used instead.
+ private static final float MINIMUM_SCALE_OF_LANGUAGE_NAME = 0.8f;
+
private final SuddenJumpingTouchEventHandler mTouchScreenRegulator;
// Timing constants
private final int mKeyRepeatInterval;
+ // TODO: Kill process when the usability study mode was changed.
+ private static final boolean ENABLE_USABILITY_STUDY_LOG = LatinImeLogger.sUsabilityStudy;
+
// Mini keyboard
private PopupWindow mMoreKeysWindow;
private MoreKeysPanel mMoreKeysPanel;
@@ -75,7 +117,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
private final boolean mHasDistinctMultitouch;
private int mOldPointerCount = 1;
- private int mOldKeyIndex;
+ private Key mOldKey;
private final boolean mConfigShowMiniKeyboardAtTouchedPoint;
protected KeyDetector mKeyDetector;
@@ -90,6 +132,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
private static final int MSG_REPEAT_KEY = 1;
private static final int MSG_LONGPRESS_KEY = 2;
private static final int MSG_IGNORE_DOUBLE_TAP = 3;
+ private static final int MSG_KEY_TYPED = 4;
private boolean mInKeyRepeat;
@@ -103,19 +146,19 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
final PointerTracker tracker = (PointerTracker) msg.obj;
switch (msg.what) {
case MSG_REPEAT_KEY:
- tracker.onRepeatKey(msg.arg1);
- startKeyRepeatTimer(keyboardView.mKeyRepeatInterval, msg.arg1, tracker);
+ tracker.onRepeatKey(tracker.getKey());
+ startKeyRepeatTimer(keyboardView.mKeyRepeatInterval, tracker);
break;
case MSG_LONGPRESS_KEY:
- keyboardView.openMiniKeyboardIfRequired(msg.arg1, tracker);
+ keyboardView.openMiniKeyboardIfRequired(tracker.getKey(), tracker);
break;
}
}
@Override
- public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker) {
+ public void startKeyRepeatTimer(long delay, PointerTracker tracker) {
mInKeyRepeat = true;
- sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, keyIndex, 0, tracker), delay);
+ sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, tracker), delay);
}
public void cancelKeyRepeatTimer() {
@@ -128,9 +171,9 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
}
@Override
- public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker) {
+ public void startLongPressTimer(long delay, PointerTracker tracker) {
cancelLongPressTimer();
- sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, keyIndex, 0, tracker), delay);
+ sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, tracker), delay);
}
@Override
@@ -139,6 +182,17 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
}
@Override
+ public void startKeyTypedTimer(long delay) {
+ removeMessages(MSG_KEY_TYPED);
+ sendMessageDelayed(obtainMessage(MSG_KEY_TYPED), delay);
+ }
+
+ @Override
+ public boolean isTyping() {
+ return hasMessages(MSG_KEY_TYPED);
+ }
+
+ @Override
public void cancelKeyTimers() {
cancelKeyRepeatTimer();
cancelLongPressTimer();
@@ -165,13 +219,13 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
@Override
public boolean onDoubleTap(MotionEvent firstDown) {
final Keyboard keyboard = getKeyboard();
- if (ENABLE_CAPSLOCK_BY_DOUBLETAP && keyboard instanceof LatinKeyboard
- && ((LatinKeyboard) keyboard).isAlphaKeyboard()) {
+ if (ENABLE_CAPSLOCK_BY_DOUBLETAP && keyboard.mId.isAlphabetKeyboard()) {
final int pointerIndex = firstDown.getActionIndex();
final int id = firstDown.getPointerId(pointerIndex);
final PointerTracker tracker = getPointerTracker(id);
+ final Key key = tracker.getKeyOn((int)firstDown.getX(), (int)firstDown.getY());
// If the first down event is on shift key.
- if (tracker.isOnShiftKey((int) firstDown.getX(), (int) firstDown.getY())) {
+ if (key != null && key.isShift()) {
mProcessingShiftDoubleTapEvent = true;
return true;
}
@@ -188,12 +242,13 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
final int pointerIndex = secondDown.getActionIndex();
final int id = secondDown.getPointerId(pointerIndex);
final PointerTracker tracker = getPointerTracker(id);
+ final Key key = tracker.getKeyOn((int)secondDown.getX(), (int)secondDown.getY());
// If the second down event is also on shift key.
- if (tracker.isOnShiftKey((int) secondDown.getX(), (int) secondDown.getY())) {
+ if (key != null && key.isShift()) {
// Detected a double tap on shift key. If we are in the ignoring double tap
// mode, it means we have already turned off caps lock in
// {@link KeyboardSwitcher#onReleaseShift} .
- onDoubleTapShiftKey(tracker, mKeyTimerHandler.isIgnoringDoubleTap());
+ onDoubleTapShiftKey(mKeyTimerHandler.isIgnoringDoubleTap());
return true;
}
// Otherwise these events should not be handled as double tap.
@@ -204,7 +259,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
}
public LatinKeyboardView(Context context, AttributeSet attrs) {
- this(context, attrs, R.attr.keyboardViewStyle);
+ this(context, attrs, R.attr.latinKeyboardViewStyle);
}
public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) {
@@ -228,6 +283,23 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval);
PointerTracker.init(mHasDistinctMultitouch, getContext());
+
+ final int longPressSpaceKeyTimeout =
+ res.getInteger(R.integer.config_long_press_space_key_timeout);
+ mIsSpacebarTriggeringPopupByLongPress = (longPressSpaceKeyTimeout > 0);
+
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.LatinKeyboardView, defStyle, R.style.LatinKeyboardView);
+ mAutoCorrectionSpacebarLedEnabled = a.getBoolean(
+ R.styleable.LatinKeyboardView_autoCorrectionSpacebarLedEnabled, false);
+ mAutoCorrectionSpacebarLedIcon = a.getDrawable(
+ R.styleable.LatinKeyboardView_autoCorrectionSpacebarLedIcon);
+ mSpacebarTextRatio = a.getFraction(R.styleable.LatinKeyboardView_spacebarTextRatio,
+ 1000, 1000, 1) / 1000.0f;
+ mSpacebarTextColor = a.getColor(R.styleable.LatinKeyboardView_spacebarTextColor, 0);
+ mSpacebarTextShadowColor = a.getColor(
+ R.styleable.LatinKeyboardView_spacebarTextShadowColor, 0);
+ a.recycle();
}
public void startIgnoringDoubleTap() {
@@ -264,20 +336,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
return mKeyTimerHandler;
}
- @Override
- public void setKeyPreviewPopupEnabled(boolean previewEnabled, int delay) {
- final Keyboard keyboard = getKeyboard();
- if (keyboard instanceof LatinKeyboard) {
- final LatinKeyboard latinKeyboard = (LatinKeyboard)keyboard;
- if (latinKeyboard.isPhoneKeyboard() || latinKeyboard.isNumberKeyboard()) {
- // Phone and number keyboard never shows popup preview.
- super.setKeyPreviewPopupEnabled(false, delay);
- return;
- }
- }
- super.setKeyPreviewPopupEnabled(previewEnabled, delay);
- }
-
/**
* Attaches a keyboard to this view. The keyboard can be switched at any time and the
* view will re-layout itself to accommodate the keyboard.
@@ -296,6 +354,13 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
PointerTracker.setKeyDetector(mKeyDetector);
mTouchScreenRegulator.setKeyboard(keyboard);
mMoreKeysPanelCache.clear();
+
+ mSpaceKey = keyboard.getKey(Keyboard.CODE_SPACE);
+ mSpaceIcon = keyboard.mIconsSet.getIconByAttrId(R.styleable.Keyboard_iconSpaceKey);
+ final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
+ mSpacebarTextSize = keyHeight * mSpacebarTextRatio;
+ mSpacebarLocale = keyboard.mId.mLocale;
+ clearSpacebarDrawableCache();
}
/**
@@ -329,7 +394,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
super.cancelAllMessages();
}
- private boolean openMiniKeyboardIfRequired(int keyIndex, PointerTracker tracker) {
+ private boolean openMiniKeyboardIfRequired(Key parentKey, PointerTracker tracker) {
// Check if we have a popup layout specified first.
if (mMoreKeysLayout == 0) {
return false;
@@ -338,20 +403,20 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
// Check if we are already displaying popup panel.
if (mMoreKeysPanel != null)
return false;
- final Key parentKey = tracker.getKey(keyIndex);
if (parentKey == null)
return false;
return onLongPress(parentKey, tracker);
}
- private void onDoubleTapShiftKey(@SuppressWarnings("unused") PointerTracker tracker,
- final boolean ignore) {
+ private void onDoubleTapShiftKey(final boolean ignore) {
// When shift key is double tapped, the first tap is correctly processed as usual tap. And
// the second tap is treated as this double tap event, so that we need not mark tracker
// calling setAlreadyProcessed() nor remove the tracker from mPointerQueue.
- final int primaryCode = ignore ? Keyboard.CODE_HAPTIC_AND_AUDIO_FEEDBACK_ONLY
- : Keyboard.CODE_CAPSLOCK;
- invokeCodeInput(primaryCode);
+ if (ignore) {
+ mKeyboardActionListener.onCustomRequest(LatinIME.CODE_HAPTIC_AND_AUDIO_FEEDBACK);
+ } else {
+ mKeyboardActionListener.onCodeInput(Keyboard.CODE_CAPSLOCK, null, 0, 0);
+ }
}
// This default implementation returns a more keys panel.
@@ -374,15 +439,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
return miniKeyboardView;
}
- public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboard oldKeyboard) {
- final Keyboard keyboard = getKeyboard();
- // We should not set text fade factor to the keyboard which does not display the language on
- // its spacebar.
- if (keyboard instanceof LatinKeyboard && keyboard == oldKeyboard) {
- ((LatinKeyboard)keyboard).setSpacebarTextFadeFactor(fadeFactor, this);
- }
- }
-
/**
* Called when a key is long pressed. By default this will open mini keyboard associated
* with this key.
@@ -394,34 +450,28 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
protected boolean onLongPress(Key parentKey, PointerTracker tracker) {
final int primaryCode = parentKey.mCode;
final Keyboard keyboard = getKeyboard();
- if (keyboard instanceof LatinKeyboard) {
- final LatinKeyboard latinKeyboard = (LatinKeyboard) keyboard;
- if (primaryCode == Keyboard.CODE_DIGIT0 && latinKeyboard.isPhoneKeyboard()) {
- tracker.onLongPressed();
- // Long pressing on 0 in phone number keypad gives you a '+'.
- invokeCodeInput(Keyboard.CODE_PLUS);
- invokeReleaseKey(primaryCode);
- return true;
- }
- if (primaryCode == Keyboard.CODE_SHIFT && latinKeyboard.isAlphaKeyboard()) {
- tracker.onLongPressed();
- invokeCodeInput(Keyboard.CODE_CAPSLOCK);
- invokeReleaseKey(primaryCode);
- return true;
- }
+ if (primaryCode == Keyboard.CODE_DIGIT0 && keyboard.mId.isPhoneKeyboard()) {
+ tracker.onLongPressed();
+ // Long pressing on 0 in phone number keypad gives you a '+'.
+ invokeCodeInput(Keyboard.CODE_PLUS);
+ invokeReleaseKey(primaryCode);
+ return true;
}
- if (primaryCode == Keyboard.CODE_SETTINGS || primaryCode == Keyboard.CODE_SPACE) {
- // Both long pressing settings key and space key invoke IME switcher dialog.
+ if (primaryCode == Keyboard.CODE_SHIFT && keyboard.mId.isAlphabetKeyboard()) {
+ tracker.onLongPressed();
+ invokeCodeInput(Keyboard.CODE_CAPSLOCK);
+ invokeReleaseKey(primaryCode);
+ return true;
+ }
+ if (primaryCode == Keyboard.CODE_SPACE) {
+ // Long pressing the space key invokes IME switcher dialog.
if (invokeCustomRequest(LatinIME.CODE_SHOW_INPUT_METHOD_PICKER)) {
tracker.onLongPressed();
invokeReleaseKey(primaryCode);
return true;
- } else {
- return openMoreKeysPanel(parentKey, tracker);
}
- } else {
- return openMoreKeysPanel(parentKey, tracker);
}
+ return openMoreKeysPanel(parentKey, tracker);
}
private boolean invokeCustomRequest(int code) {
@@ -463,8 +513,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
this, this, pointX, pointY, mMoreKeysWindow, getKeyboardActionListener());
final int translatedX = moreKeysPanel.translateX(tracker.getLastX());
final int translatedY = moreKeysPanel.translateY(tracker.getLastY());
- tracker.onShowMoreKeysPanel(
- translatedX, translatedY, SystemClock.uptimeMillis(), moreKeysPanel);
+ tracker.onShowMoreKeysPanel(translatedX, translatedY, moreKeysPanel);
dimEntireKeyboard(true);
return true;
}
@@ -527,6 +576,33 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
x = (int)me.getX(index);
y = (int)me.getY(index);
}
+ if (ENABLE_USABILITY_STUDY_LOG) {
+ final String eventTag;
+ switch (action) {
+ case MotionEvent.ACTION_UP:
+ eventTag = "[Up]";
+ break;
+ case MotionEvent.ACTION_DOWN:
+ eventTag = "[Down]";
+ break;
+ case MotionEvent.ACTION_POINTER_UP:
+ eventTag = "[PointerUp]";
+ break;
+ case MotionEvent.ACTION_POINTER_DOWN:
+ eventTag = "[PointerDown]";
+ break;
+ case MotionEvent.ACTION_MOVE: // Skip this as being logged below
+ eventTag = "";
+ break;
+ default:
+ eventTag = "[Action" + action + "]";
+ break;
+ }
+ if (!TextUtils.isEmpty(eventTag)) {
+ UsabilityStudyLogUtils.getInstance().write(
+ eventTag + eventTime + "," + id + "," + x + "," + y + "\t\t");
+ }
+ }
if (mKeyTimerHandler.isInKeyRepeat()) {
final PointerTracker tracker = getPointerTracker(id);
@@ -548,8 +624,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
// Multi-touch to single touch transition.
// Send a down event for the latest pointer if the key is different from the
// previous key.
- final int newKeyIndex = tracker.getKeyIndexOn(x, y);
- if (mOldKeyIndex != newKeyIndex) {
+ final Key newKey = tracker.getKeyOn(x, y);
+ if (mOldKey != newKey) {
tracker.onDownEvent(x, y, eventTime, this);
if (action == MotionEvent.ACTION_UP)
tracker.onUpEvent(x, y, eventTime);
@@ -559,7 +635,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
// Send an up event for the last pointer.
final int lastX = tracker.getLastX();
final int lastY = tracker.getLastY();
- mOldKeyIndex = tracker.getKeyIndexOn(lastX, lastY);
+ mOldKey = tracker.getKeyOn(lastX, lastY);
tracker.onUpEvent(lastX, lastY, eventTime);
} else if (pointerCount == 1 && oldPointerCount == 1) {
tracker.processMotionEvent(action, x, y, eventTime, this);
@@ -583,6 +659,10 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
py = (int)me.getY(i);
}
tracker.onMoveEvent(px, py, eventTime);
+ if (ENABLE_USABILITY_STUDY_LOG) {
+ UsabilityStudyLogUtils.getInstance().write("[Move]" + eventTime + ","
+ + me.getPointerId(i) + "," + px + "," + py + "\t\t");
+ }
}
} else {
getPointerTracker(id).processMotionEvent(action, x, y, eventTime, this);
@@ -637,9 +717,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) {
- final PointerTracker tracker = getPointerTracker(0);
return AccessibleKeyboardViewProxy.getInstance().dispatchPopulateAccessibilityEvent(
- event, tracker) || super.dispatchPopulateAccessibilityEvent(event);
+ event) || super.dispatchPopulateAccessibilityEvent(event);
}
return super.dispatchPopulateAccessibilityEvent(event);
@@ -663,4 +742,180 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
// Reflection doesn't support calling superclass methods.
return false;
}
+
+ public void updateShortcutKey(boolean available) {
+ final Keyboard keyboard = getKeyboard();
+ if (keyboard == null) return;
+ final Key shortcutKey = keyboard.getKey(Keyboard.CODE_SHORTCUT);
+ if (shortcutKey == null) return;
+ shortcutKey.setEnabled(available);
+ invalidateKey(shortcutKey);
+ }
+
+ public void updateSpacebar(float fadeFactor, boolean needsToDisplayLanguage) {
+ mSpacebarTextFadeFactor = fadeFactor;
+ mNeedsToDisplayLanguage = needsToDisplayLanguage;
+ updateSpacebarIcon();
+ invalidateKey(mSpaceKey);
+ }
+
+ public void updateAutoCorrectionState(boolean isAutoCorrection) {
+ if (!mAutoCorrectionSpacebarLedEnabled) return;
+ mAutoCorrectionSpacebarLedOn = isAutoCorrection;
+ updateSpacebarIcon();
+ invalidateKey(mSpaceKey);
+ }
+
+ @Override
+ /* package */ void onDrawKeyTopVisuals(Key key, Canvas canvas, Paint paint,
+ KeyDrawParams params) {
+ super.onDrawKeyTopVisuals(key, canvas, paint, params);
+
+ if (key.mCode == Keyboard.CODE_SPACE) {
+ // Whether space key needs to show the "..." popup hint for special purposes
+ if (mIsSpacebarTriggeringPopupByLongPress
+ && Utils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) {
+ super.drawKeyPopupHint(key, canvas, paint, params);
+ }
+ }
+ }
+
+ // TODO: Get rid of this method and draw spacebar locale and auto correction spacebar LED
+ // in onDrawKeyTopVisuals.
+ private void updateSpacebarIcon() {
+ if (mSpaceKey == null) return;
+ if (mNeedsToDisplayLanguage) {
+ mSpaceKey.setIcon(getSpaceDrawable(mSpacebarLocale));
+ } else if (mAutoCorrectionSpacebarLedOn) {
+ mSpaceKey.setIcon(getSpaceDrawable(null));
+ } else {
+ mSpaceKey.setIcon(mSpaceIcon);
+ }
+ }
+
+ private static int getSpacebarTextColor(int color, float fadeFactor) {
+ final int newColor = Color.argb((int)(Color.alpha(color) * fadeFactor),
+ Color.red(color), Color.green(color), Color.blue(color));
+ return newColor;
+ }
+
+ // Compute width of text with specified text size using paint.
+ private static int getTextWidth(Paint paint, String text, float textSize, Rect bounds) {
+ paint.setTextSize(textSize);
+ paint.getTextBounds(text, 0, text.length(), bounds);
+ return bounds.width();
+ }
+
+ // Layout local language name and left and right arrow on spacebar.
+ private static String layoutSpacebar(Paint paint, Locale locale, int width,
+ float origTextSize) {
+ final Rect bounds = new Rect();
+
+ // Estimate appropriate language name text size to fit in maxTextWidth.
+ String language = Utils.getFullDisplayName(locale, true);
+ int textWidth = getTextWidth(paint, language, origTextSize, bounds);
+ // Assuming text width and text size are proportional to each other.
+ float textSize = origTextSize * Math.min(width / textWidth, 1.0f);
+ // allow variable text size
+ textWidth = getTextWidth(paint, language, textSize, bounds);
+ // If text size goes too small or text does not fit, use middle or short name
+ final boolean useMiddleName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME)
+ || (textWidth > width);
+
+ final boolean useShortName;
+ if (useMiddleName) {
+ language = Utils.getMiddleDisplayLanguage(locale);
+ textWidth = getTextWidth(paint, language, origTextSize, bounds);
+ textSize = origTextSize * Math.min(width / textWidth, 1.0f);
+ useShortName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME)
+ || (textWidth > width);
+ } else {
+ useShortName = false;
+ }
+
+ if (useShortName) {
+ language = Utils.getShortDisplayLanguage(locale);
+ textWidth = getTextWidth(paint, language, origTextSize, bounds);
+ textSize = origTextSize * Math.min(width / textWidth, 1.0f);
+ }
+ paint.setTextSize(textSize);
+
+ return language;
+ }
+
+ private Integer getSpaceDrawableKey(Locale locale) {
+ return Arrays.hashCode(new Object[] {
+ locale,
+ mAutoCorrectionSpacebarLedOn,
+ mSpacebarTextFadeFactor
+ });
+ }
+
+ private void clearSpacebarDrawableCache() {
+ for (final BitmapDrawable drawable : mSpacebarDrawableCache.values()) {
+ final Bitmap bitmap = drawable.getBitmap();
+ bitmap.recycle();
+ }
+ mSpacebarDrawableCache.clear();
+ }
+
+ private BitmapDrawable getSpaceDrawable(Locale locale) {
+ final Integer hashCode = getSpaceDrawableKey(locale);
+ final BitmapDrawable cached = mSpacebarDrawableCache.get(hashCode);
+ if (cached != null) {
+ return cached;
+ }
+ final BitmapDrawable drawable = new BitmapDrawable(getResources(), drawSpacebar(
+ locale, mAutoCorrectionSpacebarLedOn, mSpacebarTextFadeFactor));
+ mSpacebarDrawableCache.put(hashCode, drawable);
+ return drawable;
+ }
+
+ private Bitmap drawSpacebar(Locale inputLocale, boolean isAutoCorrection,
+ float textFadeFactor) {
+ final int width = mSpaceKey.mWidth;
+ final int height = mSpaceIcon != null ? mSpaceIcon.getIntrinsicHeight() : mSpaceKey.mHeight;
+ final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(buffer);
+ canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
+
+ // If application locales are explicitly selected.
+ if (inputLocale != null) {
+ final Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setTextAlign(Align.CENTER);
+
+ final String language = layoutSpacebar(paint, inputLocale, width, mSpacebarTextSize);
+
+ // Draw language text with shadow
+ // In case there is no space icon, we will place the language text at the center of
+ // spacebar.
+ final float descent = paint.descent();
+ final float textHeight = -paint.ascent() + descent;
+ final float baseline = (mSpaceIcon != null) ? height * SPACEBAR_LANGUAGE_BASELINE
+ : height / 2 + textHeight / 2;
+ paint.setColor(getSpacebarTextColor(mSpacebarTextShadowColor, textFadeFactor));
+ canvas.drawText(language, width / 2, baseline - descent - 1, paint);
+ paint.setColor(getSpacebarTextColor(mSpacebarTextColor, textFadeFactor));
+ canvas.drawText(language, width / 2, baseline - descent, paint);
+ }
+
+ // Draw the spacebar icon at the bottom
+ if (isAutoCorrection) {
+ final int iconWidth = width * SPACE_LED_LENGTH_PERCENT / 100;
+ final int iconHeight = mAutoCorrectionSpacebarLedIcon.getIntrinsicHeight();
+ int x = (width - iconWidth) / 2;
+ int y = height - iconHeight;
+ mAutoCorrectionSpacebarLedIcon.setBounds(x, y, x + iconWidth, y + iconHeight);
+ mAutoCorrectionSpacebarLedIcon.draw(canvas);
+ } else if (mSpaceIcon != null) {
+ final int iconWidth = mSpaceIcon.getIntrinsicWidth();
+ final int iconHeight = mSpaceIcon.getIntrinsicHeight();
+ int x = (width - iconWidth) / 2;
+ int y = height - iconHeight;
+ mSpaceIcon.setBounds(x, y, x + iconWidth, y + iconHeight);
+ mSpaceIcon.draw(canvas);
+ }
+ return buffer;
+ }
}
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
index ac9290bfd..548b5ea85 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
@@ -18,8 +18,6 @@ package com.android.inputmethod.keyboard;
import android.graphics.Paint;
-import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
-import com.android.inputmethod.keyboard.internal.KeyboardParams;
import com.android.inputmethod.keyboard.internal.MoreKeySpecParser;
import com.android.inputmethod.latin.R;
@@ -35,10 +33,10 @@ public class MiniKeyboard extends Keyboard {
return mDefaultKeyCoordX;
}
- public static class Builder extends KeyboardBuilder<Builder.MiniKeyboardParams> {
+ public static class Builder extends Keyboard.Builder<Builder.MiniKeyboardParams> {
private final CharSequence[] mMoreKeys;
- public static class MiniKeyboardParams extends KeyboardParams {
+ public static class MiniKeyboardParams extends Keyboard.Params {
/* package */int mTopRowAdjustment;
public int mNumRows;
public int mNumColumns;
@@ -207,7 +205,7 @@ public class MiniKeyboard extends Keyboard {
public Builder(KeyboardView view, int xmlId, Key parentKey, Keyboard parentKeyboard) {
super(view.getContext(), new MiniKeyboardParams());
- load(parentKeyboard.mId.cloneWithNewXml(mResources.getResourceEntryName(xmlId), xmlId));
+ load(xmlId, parentKeyboard.mId);
// TODO: Mini keyboard's vertical gap is currently calculated heuristically.
// Should revise the algorithm.
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java
index f2c5b7b49..8e9929681 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java
@@ -132,9 +132,8 @@ public class MiniKeyboardView extends KeyboardView implements MoreKeysPanel {
@Override
public void setShifted(boolean shifted) {
final Keyboard keyboard = getKeyboard();
- if (keyboard.setShifted(shifted)) {
- invalidateAllKeys();
- }
+ keyboard.setShifted(shifted);
+ invalidateAllKeys();
}
@Override
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java
index d20204611..742ee98d7 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java
@@ -16,8 +16,6 @@
package com.android.inputmethod.keyboard;
-import java.util.List;
-
public class MoreKeysDetector extends KeyDetector {
private final int mSlideAllowanceSquare;
private final int mSlideAllowanceSquareTop;
@@ -41,24 +39,23 @@ public class MoreKeysDetector extends KeyDetector {
}
@Override
- public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) {
- final List<Key> keys = getKeyboard().mKeys;
+ public Key getKeyAndNearbyCodes(int x, int y, final int[] allCodes) {
final int touchX = getTouchX(x);
final int touchY = getTouchY(y);
- int nearestIndex = NOT_A_KEY;
+ Key nearestKey = null;
int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
- final int keyCount = keys.size();
- for (int index = 0; index < keyCount; index++) {
- final int dist = keys.get(index).squaredDistanceToEdge(touchX, touchY);
+ for (final Key key : getKeyboard().mKeys) {
+ final int dist = key.squaredDistanceToEdge(touchX, touchY);
if (dist < nearestDist) {
- nearestIndex = index;
+ nearestKey = key;
nearestDist = dist;
}
}
- if (allCodes != null && nearestIndex != NOT_A_KEY)
- allCodes[0] = keys.get(nearestIndex).mCode;
- return nearestIndex;
+ if (allCodes != null && nearestKey != null) {
+ allCodes[0] = nearestKey.mCode;
+ }
+ return nearestKey;
}
-} \ No newline at end of file
+}
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java b/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java
index 6314a99db..a3ff37269 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java
@@ -24,6 +24,7 @@ public interface MoreKeysPanel extends PointerTracker.KeyEventHandler {
public boolean dismissMoreKeysPanel();
}
+ // TODO: Remove this method.
public void setShifted(boolean shifted);
/**
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 198e06aab..2183e8ed6 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.keyboard;
import android.content.Context;
import android.content.res.Resources;
+import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;
@@ -27,8 +28,8 @@ import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
+import java.util.Set;
public class PointerTracker {
private static final String TAG = PointerTracker.class.getSimpleName();
@@ -67,22 +68,28 @@ public class PointerTracker {
public interface DrawingProxy extends MoreKeysPanel.Controller {
public void invalidateKey(Key key);
public TextView inflateKeyPreviewText();
- public void showKeyPreview(int keyIndex, PointerTracker tracker);
+ public void showKeyPreview(PointerTracker tracker);
public void cancelShowKeyPreview(PointerTracker tracker);
public void dismissKeyPreview(PointerTracker tracker);
}
public interface TimerProxy {
- public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker);
- public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker);
+ public void startKeyTypedTimer(long delay);
+ public boolean isTyping();
+ public void startKeyRepeatTimer(long delay, PointerTracker tracker);
+ public void startLongPressTimer(long delay, PointerTracker tracker);
public void cancelLongPressTimer();
public void cancelKeyTimers();
public static class Adapter implements TimerProxy {
@Override
- public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker) {}
+ public void startKeyTypedTimer(long delay) {}
@Override
- public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker) {}
+ public boolean isTyping() { return false; }
+ @Override
+ public void startKeyRepeatTimer(long delay, PointerTracker tracker) {}
+ @Override
+ public void startLongPressTimer(long delay, PointerTracker tracker) {}
@Override
public void cancelLongPressTimer() {}
@Override
@@ -97,6 +104,7 @@ public class PointerTracker {
private static int sLongPressKeyTimeout;
private static int sLongPressShiftKeyTimeout;
private static int sLongPressSpaceKeyTimeout;
+ private static int sIgnoreSpecialKeyTimeout;
private static int sTouchNoiseThresholdMillis;
private static int sTouchNoiseThresholdDistanceSquared;
@@ -111,7 +119,7 @@ public class PointerTracker {
private KeyboardActionListener mListener = EMPTY_LISTENER;
private Keyboard mKeyboard;
- private List<Key> mKeys;
+ private Set<Key> mKeys;
private int mKeyQuarterWidthSquared;
private final TextView mKeyPreviewText;
@@ -119,9 +127,9 @@ public class PointerTracker {
private long mDownTime;
private long mUpTime;
- // The current key index where this pointer is.
- private int mKeyIndex = KeyDetector.NOT_A_KEY;
- // The position where mKeyIndex was recognized for the first time.
+ // The current key where this pointer is.
+ private Key mCurrentKey = null;
+ // The position where the current key was recognized for the first time.
private int mKeyX;
private int mKeyY;
@@ -167,7 +175,9 @@ public class PointerTracker {
sLongPressKeyTimeout = res.getInteger(R.integer.config_long_press_key_timeout);
sLongPressShiftKeyTimeout = res.getInteger(R.integer.config_long_press_shift_key_timeout);
sLongPressSpaceKeyTimeout = res.getInteger(R.integer.config_long_press_space_key_timeout);
+ sIgnoreSpecialKeyTimeout = res.getInteger(R.integer.config_ignore_special_key_timeout);
sTouchNoiseThresholdMillis = res.getInteger(R.integer.config_touch_noise_threshold_millis);
+
final float touchNoiseThresholdDistance = res.getDimension(
R.dimen.config_touch_noise_threshold_distance);
sTouchNoiseThresholdDistanceSquared = (int)(
@@ -207,7 +217,7 @@ public class PointerTracker {
public static void dismissAllKeyPreviews() {
for (final PointerTracker tracker : sTrackers) {
- tracker.setReleasedKeyGraphics(tracker.mKeyIndex);
+ tracker.setReleasedKeyGraphics(tracker.mCurrentKey);
}
}
@@ -228,12 +238,15 @@ public class PointerTracker {
// Returns true if keyboard has been changed by this callback.
private boolean callListenerOnPressAndCheckKeyboardLayoutChange(Key key, boolean withSliding) {
- final boolean ignoreModifierKey = mIgnoreModifierKey && isModifierCode(key.mCode);
- if (DEBUG_LISTENER)
- Log.d(TAG, "onPress : " + keyCodePrintable(key.mCode) + " sliding=" + withSliding
- + " ignoreModifier=" + ignoreModifierKey);
- if (ignoreModifierKey)
+ final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier();
+ if (DEBUG_LISTENER) {
+ Log.d(TAG, "onPress : " + KeyDetector.printableCode(key)
+ + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey
+ + " enabled=" + key.isEnabled());
+ }
+ if (ignoreModifierKey) {
return false;
+ }
if (key.isEnabled()) {
mListener.onPress(key.mCode, withSliding);
final boolean keyboardLayoutHasBeenChanged = mKeyboardLayoutHasBeenChanged;
@@ -246,35 +259,45 @@ public class PointerTracker {
// Note that we need primaryCode argument because the keyboard may in shifted state and the
// primaryCode is different from {@link Key#mCode}.
private void callListenerOnCodeInput(Key key, int primaryCode, int[] keyCodes, int x, int y) {
- final boolean ignoreModifierKey = mIgnoreModifierKey && isModifierCode(key.mCode);
- if (DEBUG_LISTENER)
- Log.d(TAG, "onCodeInput: " + keyCodePrintable(primaryCode)
- + " codes="+ Arrays.toString(keyCodes) + " x=" + x + " y=" + y
- + " ignoreModifier=" + ignoreModifierKey);
- if (ignoreModifierKey)
+ final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier();
+ final boolean alterCode = key.altCodeWhileTyping() && mTimerProxy.isTyping();
+ final int code = alterCode ? key.mAltCode : primaryCode;
+ if (DEBUG_LISTENER) {
+ Log.d(TAG, "onCodeInput: " + Keyboard.printableCode(code) + " text=" + key.mOutputText
+ + " codes="+ KeyDetector.printableCodes(keyCodes) + " x=" + x + " y=" + y
+ + " ignoreModifier=" + ignoreModifierKey + " alterCode=" + alterCode
+ + " enabled=" + key.isEnabled());
+ }
+ if (ignoreModifierKey) {
return;
- if (key.isEnabled())
- mListener.onCodeInput(primaryCode, keyCodes, x, y);
- }
-
- private void callListenerOnTextInput(Key key) {
- if (DEBUG_LISTENER)
- Log.d(TAG, "onTextInput: text=" + key.mOutputText);
- if (key.isEnabled())
- mListener.onTextInput(key.mOutputText);
+ }
+ if (key.isEnabled()) {
+ if (code == Keyboard.CODE_OUTPUT_TEXT) {
+ mListener.onTextInput(key.mOutputText);
+ } else if (code != Keyboard.CODE_UNSPECIFIED) {
+ mListener.onCodeInput(code, keyCodes, x, y);
+ }
+ if (!key.altCodeWhileTyping() && !key.isModifier()) {
+ mTimerProxy.startKeyTypedTimer(sIgnoreSpecialKeyTimeout);
+ }
+ }
}
// Note that we need primaryCode argument because the keyboard may in shifted state and the
// primaryCode is different from {@link Key#mCode}.
private void callListenerOnRelease(Key key, int primaryCode, boolean withSliding) {
- final boolean ignoreModifierKey = mIgnoreModifierKey && isModifierCode(key.mCode);
- if (DEBUG_LISTENER)
- Log.d(TAG, "onRelease : " + keyCodePrintable(primaryCode) + " sliding="
- + withSliding + " ignoreModifier=" + ignoreModifierKey);
- if (ignoreModifierKey)
+ final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier();
+ if (DEBUG_LISTENER) {
+ Log.d(TAG, "onRelease : " + Keyboard.printableCode(primaryCode)
+ + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey
+ + " enabled="+ key.isEnabled());
+ }
+ if (ignoreModifierKey) {
return;
- if (key.isEnabled())
+ }
+ if (key.isEnabled()) {
mListener.onRelease(primaryCode, withSliding);
+ }
}
private void callListenerOnCancelInput() {
@@ -295,71 +318,69 @@ public class PointerTracker {
return mIsInSlidingKeyInput;
}
- private boolean isValidKeyIndex(int keyIndex) {
- return keyIndex >= 0 && keyIndex < mKeys.size();
- }
-
- public Key getKey(int keyIndex) {
- return isValidKeyIndex(keyIndex) ? mKeys.get(keyIndex) : null;
- }
-
- private static boolean isModifierCode(int primaryCode) {
- return primaryCode == Keyboard.CODE_SHIFT
- || primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL;
- }
-
- private boolean isModifierInternal(int keyIndex) {
- final Key key = getKey(keyIndex);
- return key == null ? false : isModifierCode(key.mCode);
+ public Key getKey() {
+ return mCurrentKey;
}
public boolean isModifier() {
- return isModifierInternal(mKeyIndex);
- }
-
- private boolean isOnModifierKey(int x, int y) {
- return isModifierInternal(mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null));
- }
-
- public boolean isOnShiftKey(int x, int y) {
- final Key key = getKey(mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null));
- return key != null && key.mCode == Keyboard.CODE_SHIFT;
+ return mCurrentKey != null && mCurrentKey.isModifier();
}
- public int getKeyIndexOn(int x, int y) {
- return mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
+ public Key getKeyOn(int x, int y) {
+ return mKeyDetector.getKeyAndNearbyCodes(x, y, null);
}
- private void setReleasedKeyGraphics(int keyIndex) {
+ private void setReleasedKeyGraphics(Key key) {
mDrawingProxy.dismissKeyPreview(this);
- final Key key = getKey(keyIndex);
if (key != null && key.isEnabled()) {
key.onReleased();
mDrawingProxy.invalidateKey(key);
+
+ if (key.isShift()) {
+ for (final Key shiftKey : mKeyboard.mShiftKeys) {
+ if (shiftKey != key) {
+ shiftKey.onReleased();
+ mDrawingProxy.invalidateKey(shiftKey);
+ }
+ }
+ }
+
+ if (key.altCodeWhileTyping()) {
+ final Key altKey = mKeyboard.getKey(key.mAltCode);
+ if (altKey != null) {
+ altKey.onReleased();
+ mDrawingProxy.invalidateKey(altKey);
+ }
+ }
}
}
- private void setPressedKeyGraphics(int keyIndex) {
- final Key key = getKey(keyIndex);
+ private void setPressedKeyGraphics(Key key) {
if (key != null && key.isEnabled()) {
- if (isKeyPreviewRequired(key)) {
- mDrawingProxy.showKeyPreview(keyIndex, this);
+ if (!key.noKeyPreview()) {
+ mDrawingProxy.showKeyPreview(this);
}
key.onPressed();
mDrawingProxy.invalidateKey(key);
- }
- }
- // The modifier key, such as shift key, should not show its key preview.
- private static boolean isKeyPreviewRequired(Key key) {
- final int code = key.mCode;
- // TODO: Stop hard-coding these key codes here, and add a new key attribute of a key.
- if (code == Keyboard.CODE_SPACE || code == Keyboard.CODE_ENTER
- || code == Keyboard.CODE_DELETE || isModifierCode(code)
- || code == Keyboard.CODE_SETTINGS || code == Keyboard.CODE_SHORTCUT) {
- return false;
+ if (key.isShift()) {
+ for (final Key shiftKey : mKeyboard.mShiftKeys) {
+ if (shiftKey != key) {
+ shiftKey.onPressed();
+ mDrawingProxy.invalidateKey(shiftKey);
+ }
+ }
+ }
+
+ if (key.altCodeWhileTyping() && mTimerProxy.isTyping()) {
+ final Key altKey = mKeyboard.getKey(key.mAltCode);
+ if (altKey != null) {
+ // TODO: Show altKey's preview.
+ altKey.onPressed();
+ mDrawingProxy.invalidateKey(altKey);
+ }
+ }
}
- return true;
}
public int getLastX() {
@@ -374,31 +395,31 @@ public class PointerTracker {
return mDownTime;
}
- private int onDownKey(int x, int y, long eventTime) {
+ private Key onDownKey(int x, int y, long eventTime) {
mDownTime = eventTime;
return onMoveToNewKey(onMoveKeyInternal(x, y), x, y);
}
- private int onMoveKeyInternal(int x, int y) {
+ private Key onMoveKeyInternal(int x, int y) {
mLastX = x;
mLastY = y;
- return mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
+ return mKeyDetector.getKeyAndNearbyCodes(x, y, null);
}
- private int onMoveKey(int x, int y) {
+ private Key onMoveKey(int x, int y) {
return onMoveKeyInternal(x, y);
}
- private int onMoveToNewKey(int keyIndex, int x, int y) {
- mKeyIndex = keyIndex;
+ private Key onMoveToNewKey(Key newKey, int x, int y) {
+ mCurrentKey = newKey;
mKeyX = x;
mKeyY = y;
- return keyIndex;
+ return newKey;
}
- private int onUpKey(int x, int y, long eventTime) {
+ private Key onUpKey(int x, int y, long eventTime) {
mUpTime = eventTime;
- mKeyIndex = KeyDetector.NOT_A_KEY;
+ mCurrentKey = null;
return onMoveKeyInternal(x, y);
}
@@ -447,7 +468,8 @@ public class PointerTracker {
final PointerTrackerQueue queue = sPointerTrackerQueue;
if (queue != null) {
- if (isOnModifierKey(x, y)) {
+ final Key key = getKeyOn(x, y);
+ if (key != null && key.isModifier()) {
// Before processing a down event of modifier key, all pointers already being
// tracked should be released.
queue.releaseAllPointers(eventTime);
@@ -458,32 +480,35 @@ public class PointerTracker {
}
private void onDownEventInternal(int x, int y, long eventTime) {
- int keyIndex = onDownKey(x, y, eventTime);
+ Key key = onDownKey(x, y, eventTime);
// Sliding key is allowed when 1) enabled by configuration, 2) this pointer starts sliding
// from modifier key, or 3) this pointer's KeyDetector always allows sliding input.
- mIsAllowedSlidingKeyInput = sConfigSlidingKeyInputEnabled || isModifierInternal(keyIndex)
+ mIsAllowedSlidingKeyInput = sConfigSlidingKeyInputEnabled
+ || (key != null && key.isModifier())
|| mKeyDetector.alwaysAllowsSlidingInput();
mKeyboardLayoutHasBeenChanged = false;
mKeyAlreadyProcessed = false;
mIsRepeatableKey = false;
mIsInSlidingKeyInput = false;
mIgnoreModifierKey = false;
- if (isValidKeyIndex(keyIndex)) {
+ if (key != null) {
// This onPress call may have changed keyboard layout. Those cases are detected at
- // {@link #setKeyboard}. In those cases, we should update keyIndex according to the new
+ // {@link #setKeyboard}. In those cases, we should update key according to the new
// keyboard layout.
- if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), false))
- keyIndex = onDownKey(x, y, eventTime);
+ if (callListenerOnPressAndCheckKeyboardLayoutChange(key, false)) {
+ key = onDownKey(x, y, eventTime);
+ }
- startRepeatKey(keyIndex);
- startLongPressTimer(keyIndex);
- setPressedKeyGraphics(keyIndex);
+ startRepeatKey(key);
+ startLongPressTimer(key);
+ setPressedKeyGraphics(key);
}
}
private void startSlidingKeyInput(Key key) {
- if (!mIsInSlidingKeyInput)
- mIgnoreModifierKey = isModifierCode(key.mCode);
+ if (!mIsInSlidingKeyInput) {
+ mIgnoreModifierKey = key.isModifier();
+ }
mIsInSlidingKeyInput = true;
}
@@ -495,39 +520,40 @@ public class PointerTracker {
final int lastX = mLastX;
final int lastY = mLastY;
- final int oldKeyIndex = mKeyIndex;
- final Key oldKey = getKey(oldKeyIndex);
- int keyIndex = onMoveKey(x, y);
- if (isValidKeyIndex(keyIndex)) {
+ final Key oldKey = mCurrentKey;
+ Key key = onMoveKey(x, y);
+ if (key != null) {
if (oldKey == null) {
// The pointer has been slid in to the new key, but the finger was not on any keys.
// In this case, we must call onPress() to notify that the new key is being pressed.
// This onPress call may have changed keyboard layout. Those cases are detected at
- // {@link #setKeyboard}. In those cases, we should update keyIndex according to the
+ // {@link #setKeyboard}. In those cases, we should update key according to the
// new keyboard layout.
- if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), true))
- keyIndex = onMoveKey(x, y);
- onMoveToNewKey(keyIndex, x, y);
- startLongPressTimer(keyIndex);
- setPressedKeyGraphics(keyIndex);
- } else if (isMajorEnoughMoveToBeOnNewKey(x, y, keyIndex)) {
+ if (callListenerOnPressAndCheckKeyboardLayoutChange(key, true)) {
+ key = onMoveKey(x, y);
+ }
+ onMoveToNewKey(key, x, y);
+ startLongPressTimer(key);
+ setPressedKeyGraphics(key);
+ } else if (isMajorEnoughMoveToBeOnNewKey(x, y, key)) {
// The pointer has been slid in to the new key from the previous key, we must call
// onRelease() first to notify that the previous key has been released, then call
// onPress() to notify that the new key is being pressed.
- setReleasedKeyGraphics(oldKeyIndex);
+ setReleasedKeyGraphics(oldKey);
callListenerOnRelease(oldKey, oldKey.mCode, true);
startSlidingKeyInput(oldKey);
mTimerProxy.cancelKeyTimers();
- startRepeatKey(keyIndex);
+ startRepeatKey(key);
if (mIsAllowedSlidingKeyInput) {
// This onPress call may have changed keyboard layout. Those cases are detected
- // at {@link #setKeyboard}. In those cases, we should update keyIndex according
+ // at {@link #setKeyboard}. In those cases, we should update key according
// to the new keyboard layout.
- if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), true))
- keyIndex = onMoveKey(x, y);
- onMoveToNewKey(keyIndex, x, y);
- startLongPressTimer(keyIndex);
- setPressedKeyGraphics(keyIndex);
+ if (callListenerOnPressAndCheckKeyboardLayoutChange(key, true)) {
+ key = onMoveKey(x, y);
+ }
+ onMoveToNewKey(key, x, y);
+ startLongPressTimer(key);
+ setPressedKeyGraphics(key);
} else {
// HACK: On some devices, quick successive touches may be translated to sudden
// move by touch panel firmware. This hack detects the case and translates the
@@ -543,20 +569,20 @@ public class PointerTracker {
onDownEventInternal(x, y, eventTime);
} else {
mKeyAlreadyProcessed = true;
- setReleasedKeyGraphics(oldKeyIndex);
+ setReleasedKeyGraphics(oldKey);
}
}
}
} else {
- if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, keyIndex)) {
+ if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, key)) {
// The pointer has been slid out from the previous key, we must call onRelease() to
// notify that the previous key has been released.
- setReleasedKeyGraphics(oldKeyIndex);
+ setReleasedKeyGraphics(oldKey);
callListenerOnRelease(oldKey, oldKey.mCode, true);
startSlidingKeyInput(oldKey);
mTimerProxy.cancelLongPressTimer();
if (mIsAllowedSlidingKeyInput) {
- onMoveToNewKey(keyIndex, x, y);
+ onMoveToNewKey(key, x, y);
} else {
mKeyAlreadyProcessed = true;
}
@@ -570,7 +596,7 @@ public class PointerTracker {
final PointerTrackerQueue queue = sPointerTrackerQueue;
if (queue != null) {
- if (isModifier()) {
+ if (mCurrentKey != null && mCurrentKey.isModifier()) {
// Before processing an up event of modifier key, all pointers already being
// tracked should be released.
queue.releaseAllPointersExcept(this, eventTime);
@@ -605,8 +631,8 @@ public class PointerTracker {
keyX = mKeyX;
keyY = mKeyY;
}
- final int keyIndex = onUpKey(keyX, keyY, eventTime);
- setReleasedKeyGraphics(keyIndex);
+ final Key key = onUpKey(keyX, keyY, eventTime);
+ setReleasedKeyGraphics(key);
if (mIsShowingMoreKeysPanel) {
mDrawingProxy.dismissMoreKeysPanel();
mIsShowingMoreKeysPanel = false;
@@ -614,19 +640,19 @@ public class PointerTracker {
if (mKeyAlreadyProcessed)
return;
if (!mIsRepeatableKey) {
- detectAndSendKey(keyIndex, keyX, keyY);
+ detectAndSendKey(key, keyX, keyY);
}
}
- public void onShowMoreKeysPanel(int x, int y, long eventTime, KeyEventHandler handler) {
+ public void onShowMoreKeysPanel(int x, int y, KeyEventHandler handler) {
onLongPressed();
- onDownEvent(x, y, eventTime, handler);
+ onDownEvent(x, y, SystemClock.uptimeMillis(), handler);
mIsShowingMoreKeysPanel = true;
}
public void onLongPressed() {
mKeyAlreadyProcessed = true;
- setReleasedKeyGraphics(mKeyIndex);
+ setReleasedKeyGraphics(mCurrentKey);
final PointerTrackerQueue queue = sPointerTrackerQueue;
if (queue != null) {
queue.remove(this);
@@ -648,7 +674,7 @@ public class PointerTracker {
private void onCancelEventInternal() {
mTimerProxy.cancelKeyTimers();
mDrawingProxy.cancelShowKeyPreview(this);
- setReleasedKeyGraphics(mKeyIndex);
+ setReleasedKeyGraphics(mCurrentKey);
mIsInSlidingKeyInput = false;
if (mIsShowingMoreKeysPanel) {
mDrawingProxy.dismissMoreKeysPanel();
@@ -656,48 +682,45 @@ public class PointerTracker {
}
}
- private void startRepeatKey(int keyIndex) {
- final Key key = getKey(keyIndex);
- if (key != null && key.mRepeatable) {
- onRepeatKey(keyIndex);
- mTimerProxy.startKeyRepeatTimer(sDelayBeforeKeyRepeatStart, keyIndex, this);
+ private void startRepeatKey(Key key) {
+ if (key != null && key.isRepeatable()) {
+ onRepeatKey(key);
+ mTimerProxy.startKeyRepeatTimer(sDelayBeforeKeyRepeatStart, this);
mIsRepeatableKey = true;
} else {
mIsRepeatableKey = false;
}
}
- public void onRepeatKey(int keyIndex) {
- Key key = getKey(keyIndex);
+ public void onRepeatKey(Key key) {
if (key != null) {
- detectAndSendKey(keyIndex, key.mX, key.mY);
+ detectAndSendKey(key, key.mX, key.mY);
}
}
- private boolean isMajorEnoughMoveToBeOnNewKey(int x, int y, int newKey) {
+ private boolean isMajorEnoughMoveToBeOnNewKey(int x, int y, Key newKey) {
if (mKeys == null || mKeyDetector == null)
throw new NullPointerException("keyboard and/or key detector not set");
- int curKey = mKeyIndex;
+ Key curKey = mCurrentKey;
if (newKey == curKey) {
return false;
- } else if (isValidKeyIndex(curKey)) {
- return mKeys.get(curKey).squaredDistanceToEdge(x, y)
+ } else if (curKey != null) {
+ return curKey.squaredDistanceToEdge(x, y)
>= mKeyDetector.getKeyHysteresisDistanceSquared();
} else {
return true;
}
}
- private void startLongPressTimer(int keyIndex) {
- Key key = getKey(keyIndex);
+ private void startLongPressTimer(Key key) {
if (key == null) return;
if (key.mCode == Keyboard.CODE_SHIFT) {
if (sLongPressShiftKeyTimeout > 0) {
- mTimerProxy.startLongPressTimer(sLongPressShiftKeyTimeout, keyIndex, this);
+ mTimerProxy.startLongPressTimer(sLongPressShiftKeyTimeout, this);
}
} else if (key.mCode == Keyboard.CODE_SPACE) {
if (sLongPressSpaceKeyTimeout > 0) {
- mTimerProxy.startLongPressTimer(sLongPressSpaceKeyTimeout, keyIndex, this);
+ mTimerProxy.startLongPressTimer(sLongPressSpaceKeyTimeout, this);
}
} else if (key.hasUppercaseLetter() && mKeyboard.isManualTemporaryUpperCase()) {
// We need not start long press timer on the key which has manual temporary upper case
@@ -705,59 +728,48 @@ public class PointerTracker {
return;
} else if (sKeyboardSwitcher.isInMomentarySwitchState()) {
// We use longer timeout for sliding finger input started from the symbols mode key.
- mTimerProxy.startLongPressTimer(sLongPressKeyTimeout * 3, keyIndex, this);
+ mTimerProxy.startLongPressTimer(sLongPressKeyTimeout * 3, this);
} else {
- mTimerProxy.startLongPressTimer(sLongPressKeyTimeout, keyIndex, this);
+ mTimerProxy.startLongPressTimer(sLongPressKeyTimeout, this);
}
}
- private void detectAndSendKey(int index, int x, int y) {
- final Key key = getKey(index);
+ private void detectAndSendKey(Key key, int x, int y) {
if (key == null) {
callListenerOnCancelInput();
return;
}
- if (key.mOutputText != null) {
- callListenerOnTextInput(key);
- callListenerOnRelease(key, key.mCode, false);
- } else {
- int code = key.mCode;
- final int[] codes = mKeyDetector.newCodeArray();
- mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes);
-
- // If keyboard is in manual temporary upper case state and key has manual temporary
- // uppercase letter as key hint letter, alternate character code should be sent.
- if (mKeyboard.isManualTemporaryUpperCase() && key.hasUppercaseLetter()) {
- code = key.mHintLabel.charAt(0);
- codes[0] = code;
- }
- // Swap the first and second values in the codes array if the primary code is not the
- // first value but the second value in the array. This happens when key debouncing is
- // in effect.
- if (codes.length >= 2 && codes[0] != code && codes[1] == code) {
- codes[1] = codes[0];
- codes[0] = code;
- }
- callListenerOnCodeInput(key, code, codes, x, y);
- callListenerOnRelease(key, code, false);
+ int code = key.mCode;
+ final int[] codes = mKeyDetector.newCodeArray();
+ mKeyDetector.getKeyAndNearbyCodes(x, y, codes);
+
+ // If keyboard is in manual temporary upper case state and key has manual temporary
+ // uppercase letter as key hint letter, alternate character code should be sent.
+ if (mKeyboard.isManualTemporaryUpperCase() && key.hasUppercaseLetter()) {
+ code = key.mHintLabel.charAt(0);
+ codes[0] = code;
}
+
+ // Swap the first and second values in the codes array if the primary code is not the
+ // first value but the second value in the array. This happens when key debouncing is
+ // in effect.
+ if (codes.length >= 2 && codes[0] != code && codes[1] == code) {
+ codes[1] = codes[0];
+ codes[0] = code;
+ }
+ callListenerOnCodeInput(key, code, codes, x, y);
+ callListenerOnRelease(key, code, false);
}
private long mPreviousEventTime;
private void printTouchEvent(String title, int x, int y, long eventTime) {
- final int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
- final Key key = getKey(keyIndex);
- final String code = (key == null) ? "----" : keyCodePrintable(key.mCode);
+ final Key key = mKeyDetector.getKeyAndNearbyCodes(x, y, null);
+ final String code = KeyDetector.printableCode(key);
final long delta = eventTime - mPreviousEventTime;
- Log.d(TAG, String.format("%s%s[%d] %4d %4d %5d %3d(%s)", title,
- (mKeyAlreadyProcessed ? "-" : " "), mPointerId, x, y, delta, keyIndex, code));
+ Log.d(TAG, String.format("%s%s[%d] %4d %4d %5d %s", title,
+ (mKeyAlreadyProcessed ? "-" : " "), mPointerId, x, y, delta, code));
mPreviousEventTime = eventTime;
}
-
- private static String keyCodePrintable(int primaryCode) {
- final String modifier = isModifierCode(primaryCode) ? " modifier" : "";
- return String.format((primaryCode < 0) ? "%4d" : "0x%02x", primaryCode) + modifier;
- }
}
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index 2a25d0ca7..c1dae0601 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -18,19 +18,19 @@ package com.android.inputmethod.keyboard;
import android.graphics.Rect;
-import com.android.inputmethod.keyboard.internal.KeyboardParams.TouchPositionCorrection;
+import com.android.inputmethod.keyboard.Keyboard.Params.TouchPositionCorrection;
import com.android.inputmethod.latin.Utils;
import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo;
import java.util.Arrays;
import java.util.Collections;
-import java.util.List;
+import java.util.Set;
public class ProximityInfo {
public static final int MAX_PROXIMITY_CHARS_SIZE = 16;
/** Number of key widths from current touch point to search for nearest keys. */
private static float SEARCH_DISTANCE = 1.2f;
- private static final int[] EMPTY_INT_ARRAY = new int[0];
+ private static final Key[] EMPTY_KEY_ARRAY = new Key[0];
private final int mKeyHeight;
private final int mGridWidth;
@@ -41,10 +41,10 @@ public class ProximityInfo {
// TODO: Find a proper name for mKeyboardMinWidth
private final int mKeyboardMinWidth;
private final int mKeyboardHeight;
- private final int[][] mGridNeighbors;
+ private final Key[][] mGridNeighbors;
ProximityInfo(int gridWidth, int gridHeight, int minWidth, int height, int keyWidth,
- int keyHeight, List<Key> keys, TouchPositionCorrection touchPositionCorrection) {
+ int keyHeight, Set<Key> keys, TouchPositionCorrection touchPositionCorrection) {
mGridWidth = gridWidth;
mGridHeight = gridHeight;
mGridSize = mGridWidth * mGridHeight;
@@ -53,7 +53,7 @@ public class ProximityInfo {
mKeyboardMinWidth = minWidth;
mKeyboardHeight = height;
mKeyHeight = keyHeight;
- mGridNeighbors = new int[mGridSize][];
+ mGridNeighbors = new Key[mGridSize][];
if (minWidth == 0 || height == 0) {
// No proximity required. Keyboard might be mini keyboard.
return;
@@ -62,40 +62,40 @@ public class ProximityInfo {
}
public static ProximityInfo createDummyProximityInfo() {
- return new ProximityInfo(1, 1, 1, 1, 1, 1, Collections.<Key>emptyList(), null);
+ return new ProximityInfo(1, 1, 1, 1, 1, 1, Collections.<Key>emptySet(), null);
}
- public static ProximityInfo createSpellCheckerProximityInfo() {
+ public static ProximityInfo createSpellCheckerProximityInfo(final int[] proximity) {
final ProximityInfo spellCheckerProximityInfo = createDummyProximityInfo();
spellCheckerProximityInfo.mNativeProximityInfo =
spellCheckerProximityInfo.setProximityInfoNative(
SpellCheckerProximityInfo.ROW_SIZE,
- 480, 300, 10, 3, SpellCheckerProximityInfo.PROXIMITY,
+ 480, 300, 11, 3, proximity,
0, null, null, null, null, null, null, null, null);
return spellCheckerProximityInfo;
}
- private int mNativeProximityInfo;
+ private long mNativeProximityInfo;
static {
Utils.loadNativeLibrary();
}
- private native int setProximityInfoNative(int maxProximityCharsSize, int displayWidth,
+ private native long setProximityInfoNative(int maxProximityCharsSize, int displayWidth,
int displayHeight, int gridWidth, int gridHeight, int[] proximityCharsArray,
int keyCount, int[] keyXCoordinates, int[] keyYCoordinates,
int[] keyWidths, int[] keyHeights, int[] keyCharCodes,
float[] sweetSpotCenterX, float[] sweetSpotCenterY, float[] sweetSpotRadii);
- private native void releaseProximityInfoNative(int nativeProximityInfo);
+ private native void releaseProximityInfoNative(long nativeProximityInfo);
- private final void setProximityInfo(int[][] gridNeighborKeyIndexes, int keyboardWidth,
- int keyboardHeight, List<Key> keys,
+ private final void setProximityInfo(Key[][] gridNeighborKeys, int keyboardWidth,
+ int keyboardHeight, Set<Key> keys,
TouchPositionCorrection touchPositionCorrection) {
- int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE];
+ final int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE];
Arrays.fill(proximityCharsArray, KeyDetector.NOT_A_CODE);
for (int i = 0; i < mGridSize; ++i) {
- final int proximityCharsLength = gridNeighborKeyIndexes[i].length;
+ final int proximityCharsLength = gridNeighborKeys[i].length;
for (int j = 0; j < proximityCharsLength; ++j) {
proximityCharsArray[i * MAX_PROXIMITY_CHARS_SIZE + j] =
- keys.get(gridNeighborKeyIndexes[i][j]).mCode;
+ gridNeighborKeys[i][j].mCode;
}
}
final int keyCount = keys.size();
@@ -104,25 +104,45 @@ public class ProximityInfo {
final int[] keyWidths = new int[keyCount];
final int[] keyHeights = new int[keyCount];
final int[] keyCharCodes = new int[keyCount];
- for (int i = 0; i < keyCount; ++i) {
- final Key key = keys.get(i);
+ final float[] sweetSpotCenterXs;
+ final float[] sweetSpotCenterYs;
+ final float[] sweetSpotRadii;
+ final boolean calculateSweetSpotParams;
+ if (touchPositionCorrection != null && touchPositionCorrection.isValid()) {
+ sweetSpotCenterXs = new float[keyCount];
+ sweetSpotCenterYs = new float[keyCount];
+ sweetSpotRadii = new float[keyCount];
+ calculateSweetSpotParams = true;
+ } else {
+ sweetSpotCenterXs = sweetSpotCenterYs = sweetSpotRadii = null;
+ calculateSweetSpotParams = false;
+ }
+
+ int i = 0;
+ for (final Key key : keys) {
keyXCoordinates[i] = key.mX;
keyYCoordinates[i] = key.mY;
keyWidths[i] = key.mWidth;
keyHeights[i] = key.mHeight;
keyCharCodes[i] = key.mCode;
- }
-
- float[] sweetSpotCenterXs = null;
- float[] sweetSpotCenterYs = null;
- float[] sweetSpotRadii = null;
-
- if (touchPositionCorrection != null && touchPositionCorrection.isValid()) {
- sweetSpotCenterXs = new float[keyCount];
- sweetSpotCenterYs = new float[keyCount];
- sweetSpotRadii = new float[keyCount];
- calculateSweetSpot(keys, touchPositionCorrection,
- sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii);
+ if (calculateSweetSpotParams) {
+ final Rect hitBox = key.mHitBox;
+ final int row = hitBox.top / mKeyHeight;
+ if (row < touchPositionCorrection.mRadii.length) {
+ final float hitBoxCenterX = (hitBox.left + hitBox.right) * 0.5f;
+ final float hitBoxCenterY = (hitBox.top + hitBox.bottom) * 0.5f;
+ final float hitBoxWidth = hitBox.right - hitBox.left;
+ final float hitBoxHeight = hitBox.bottom - hitBox.top;
+ final float x = touchPositionCorrection.mXs[row];
+ final float y = touchPositionCorrection.mYs[row];
+ final float radius = touchPositionCorrection.mRadii[row];
+ sweetSpotCenterXs[i] = hitBoxCenterX + x * hitBoxWidth;
+ sweetSpotCenterYs[i] = hitBoxCenterY + y * hitBoxHeight;
+ sweetSpotRadii[i] = radius * (float)Math.sqrt(
+ hitBoxWidth * hitBoxWidth + hitBoxHeight * hitBoxHeight);
+ }
+ }
+ i++;
}
mNativeProximityInfo = setProximityInfoNative(MAX_PROXIMITY_CHARS_SIZE,
@@ -131,33 +151,7 @@ public class ProximityInfo {
sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii);
}
- private void calculateSweetSpot(List<Key> keys, TouchPositionCorrection touchPositionCorrection,
- float[] sweetSpotCenterXs, float[] sweetSpotCenterYs, float[] sweetSpotRadii) {
- final int keyCount = keys.size();
- final float[] xs = touchPositionCorrection.mXs;
- final float[] ys = touchPositionCorrection.mYs;
- final float[] radii = touchPositionCorrection.mRadii;
- for (int i = 0; i < keyCount; ++i) {
- final Key key = keys.get(i);
- final Rect hitBox = key.mHitBox;
- final int row = hitBox.top / mKeyHeight;
- if (row < radii.length) {
- final float hitBoxCenterX = (hitBox.left + hitBox.right) * 0.5f;
- final float hitBoxCenterY = (hitBox.top + hitBox.bottom) * 0.5f;
- final float hitBoxWidth = hitBox.right - hitBox.left;
- final float hitBoxHeight = hitBox.bottom - hitBox.top;
- final float x = xs[row];
- final float y = ys[row];
- final float radius = radii[row];
- sweetSpotCenterXs[i] = hitBoxCenterX + x * hitBoxWidth;
- sweetSpotCenterYs[i] = hitBoxCenterY + y * hitBoxHeight;
- sweetSpotRadii[i] = radius
- * (float)Math.sqrt(hitBoxWidth * hitBoxWidth + hitBoxHeight * hitBoxHeight);
- }
- }
- }
-
- public int getNativeProximityInfo() {
+ public long getNativeProximityInfo() {
return mNativeProximityInfo;
}
@@ -173,12 +167,12 @@ public class ProximityInfo {
}
}
- private void computeNearestNeighbors(int defaultWidth, List<Key> keys,
+ private void computeNearestNeighbors(int defaultWidth, Set<Key> keys,
TouchPositionCorrection touchPositionCorrection) {
final int thresholdBase = (int) (defaultWidth * SEARCH_DISTANCE);
final int threshold = thresholdBase * thresholdBase;
// Round-up so we don't have any pixels outside the grid
- final int[] indices = new int[keys.size()];
+ final Key[] neighborKeys = new Key[keys.size()];
final int gridWidth = mGridWidth * mCellWidth;
final int gridHeight = mGridHeight * mCellHeight;
for (int x = 0; x < gridWidth; x += mCellWidth) {
@@ -186,24 +180,23 @@ public class ProximityInfo {
final int centerX = x + mCellWidth / 2;
final int centerY = y + mCellHeight / 2;
int count = 0;
- for (int i = 0; i < keys.size(); i++) {
- final Key key = keys.get(i);
+ for (final Key key : keys) {
if (key.isSpacer()) continue;
- if (key.squaredDistanceToEdge(centerX, centerY) < threshold)
- indices[count++] = i;
+ if (key.squaredDistanceToEdge(centerX, centerY) < threshold) {
+ neighborKeys[count++] = key;
+ }
}
- final int[] cell = new int[count];
- System.arraycopy(indices, 0, cell, 0, count);
- mGridNeighbors[(y / mCellHeight) * mGridWidth + (x / mCellWidth)] = cell;
+ mGridNeighbors[(y / mCellHeight) * mGridWidth + (x / mCellWidth)] =
+ Arrays.copyOfRange(neighborKeys, 0, count);
}
}
setProximityInfo(mGridNeighbors, mKeyboardMinWidth, mKeyboardHeight, keys,
touchPositionCorrection);
}
- public int[] getNearestKeys(int x, int y) {
+ public Key[] getNearestKeys(int x, int y) {
if (mGridNeighbors == null) {
- return EMPTY_INT_ARRAY;
+ return EMPTY_KEY_ARRAY;
}
if (x >= 0 && x < mKeyboardMinWidth && y >= 0 && y < mKeyboardHeight) {
int index = (y / mCellHeight) * mGridWidth + (x / mCellWidth);
@@ -211,6 +204,6 @@ public class ProximityInfo {
return mGridNeighbors[index];
}
}
- return EMPTY_INT_ARRAY;
+ return EMPTY_KEY_ARRAY;
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
index b385b7a04..5dd8340fc 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
@@ -19,10 +19,12 @@ package com.android.inputmethod.keyboard.internal;
import android.content.res.TypedArray;
import android.util.Log;
-import com.android.inputmethod.keyboard.internal.KeyboardBuilder.ParseException;
+import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.XmlParseUtils;
import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
import java.util.ArrayList;
import java.util.HashMap;
@@ -40,11 +42,10 @@ public class KeyStyles {
public CharSequence getText(TypedArray a, int index);
public int getInt(TypedArray a, int index, int defaultValue);
public int getFlag(TypedArray a, int index, int defaultValue);
- public boolean getBoolean(TypedArray a, int index, boolean defaultValue);
}
/* package */ static class EmptyKeyStyle implements KeyStyle {
- private EmptyKeyStyle() {
+ EmptyKeyStyle() {
// Nothing to do.
}
@@ -68,11 +69,6 @@ public class KeyStyles {
return a.getInt(index, defaultValue);
}
- @Override
- public boolean getBoolean(TypedArray a, int index, boolean defaultValue) {
- return a.getBoolean(index, defaultValue);
- }
-
protected static CharSequence[] parseTextArray(TypedArray a, int index) {
if (!a.hasValue(index))
return null;
@@ -124,7 +120,7 @@ public class KeyStyles {
}
}
- private static class DeclaredKeyStyle extends EmptyKeyStyle {
+ /* package */ static class DeclaredKeyStyle extends EmptyKeyStyle {
private final HashMap<Integer, Object> mAttributes = new HashMap<Integer, Object>();
@Override
@@ -151,31 +147,25 @@ public class KeyStyles {
return super.getFlag(a, index, defaultValue) | (value != null ? value : 0);
}
- @Override
- public boolean getBoolean(TypedArray a, int index, boolean defaultValue) {
- final Boolean value = (Boolean)mAttributes.get(index);
- return super.getBoolean(a, index, (value != null) ? value : defaultValue);
- }
-
- private DeclaredKeyStyle() {
+ DeclaredKeyStyle() {
super();
}
- private void parseKeyStyleAttributes(TypedArray keyAttr) {
+ void parseKeyStyleAttributes(TypedArray keyAttr) {
// TODO: Currently not all Key attributes can be declared as style.
readInt(keyAttr, R.styleable.Keyboard_Key_code);
+ readInt(keyAttr, R.styleable.Keyboard_Key_altCode);
readText(keyAttr, R.styleable.Keyboard_Key_keyLabel);
readText(keyAttr, R.styleable.Keyboard_Key_keyOutputText);
readText(keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
readTextArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
- readFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelOption);
+ readFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags);
readInt(keyAttr, R.styleable.Keyboard_Key_keyIcon);
+ readInt(keyAttr, R.styleable.Keyboard_Key_keyIconDisabled);
readInt(keyAttr, R.styleable.Keyboard_Key_keyIconPreview);
- readInt(keyAttr, R.styleable.Keyboard_Key_keyIconShifted);
readInt(keyAttr, R.styleable.Keyboard_Key_maxMoreKeysColumn);
readInt(keyAttr, R.styleable.Keyboard_Key_backgroundType);
- readBoolean(keyAttr, R.styleable.Keyboard_Key_isRepeatable);
- readBoolean(keyAttr, R.styleable.Keyboard_Key_enabled);
+ readFlag(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
}
private void readText(TypedArray a, int index) {
@@ -194,29 +184,25 @@ public class KeyStyles {
mAttributes.put(index, a.getInt(index, 0) | (value != null ? value : 0));
}
- private void readBoolean(TypedArray a, int index) {
- if (a.hasValue(index))
- mAttributes.put(index, a.getBoolean(index, false));
- }
-
private void readTextArray(TypedArray a, int index) {
final CharSequence[] value = parseTextArray(a, index);
if (value != null)
mAttributes.put(index, value);
}
- private void addParent(DeclaredKeyStyle parentStyle) {
+ void addParent(DeclaredKeyStyle parentStyle) {
mAttributes.putAll(parentStyle.mAttributes);
}
}
public void parseKeyStyleAttributes(TypedArray keyStyleAttr, TypedArray keyAttrs,
- XmlPullParser parser) {
+ XmlPullParser parser) throws XmlPullParserException {
final String styleName = keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_styleName);
if (DEBUG) Log.d(TAG, String.format("<%s styleName=%s />",
- KeyboardBuilder.TAG_KEY_STYLE, styleName));
+ Keyboard.Builder.TAG_KEY_STYLE, styleName));
if (mStyles.containsKey(styleName))
- throw new ParseException("duplicate key style declared: " + styleName, parser);
+ throw new XmlParseUtils.ParseException(
+ "duplicate key style declared: " + styleName, parser);
final DeclaredKeyStyle style = new DeclaredKeyStyle();
if (keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_parentStyle)) {
@@ -224,7 +210,8 @@ public class KeyStyles {
R.styleable.Keyboard_KeyStyle_parentStyle);
final DeclaredKeyStyle parent = mStyles.get(parentStyle);
if (parent == null)
- throw new ParseException("Unknown parentStyle " + parentStyle, parser);
+ throw new XmlParseUtils.ParseException(
+ "Unknown parentStyle " + parentStyle, parser);
style.addParent(parent);
}
style.parseKeyStyleAttributes(keyAttrs);
@@ -235,7 +222,7 @@ public class KeyStyles {
return mStyles.get(styleName);
}
- public KeyStyle getEmptyKeyStyle() {
+ public static KeyStyle getEmptyKeyStyle() {
return EMPTY_KEY_STYLE;
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
deleted file mode 100644
index de64639b0..000000000
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ /dev/null
@@ -1,893 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.keyboard.internal;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.TypedValue;
-import android.util.Xml;
-import android.view.InflateException;
-
-import com.android.inputmethod.compat.EditorInfoCompatUtils;
-import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.latin.LatinImeLogger;
-import com.android.inputmethod.latin.R;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.Arrays;
-
-/**
- * Keyboard Building helper.
- *
- * This class parses Keyboard XML file and eventually build a Keyboard.
- * The Keyboard XML file looks like:
- * <pre>
- * &gt;!-- xml/keyboard.xml --&lt;
- * &gt;Keyboard keyboard_attributes*&lt;
- * &gt;!-- Keyboard Content --&lt;
- * &gt;Row row_attributes*&lt;
- * &gt;!-- Row Content --&lt;
- * &gt;Key key_attributes* /&lt;
- * &gt;Spacer horizontalGap="0.2in" /&lt;
- * &gt;include keyboardLayout="@xml/other_keys"&lt;
- * ...
- * &gt;/Row&lt;
- * &gt;include keyboardLayout="@xml/other_rows"&lt;
- * ...
- * &gt;/Keyboard&lt;
- * </pre>
- * The XML file which is included in other file must have &gt;merge&lt; as root element, such as:
- * <pre>
- * &gt;!-- xml/other_keys.xml --&lt;
- * &gt;merge&lt;
- * &gt;Key key_attributes* /&lt;
- * ...
- * &gt;/merge&lt;
- * </pre>
- * and
- * <pre>
- * &gt;!-- xml/other_rows.xml --&lt;
- * &gt;merge&lt;
- * &gt;Row row_attributes*&lt;
- * &gt;Key key_attributes* /&lt;
- * &gt;/Row&lt;
- * ...
- * &gt;/merge&lt;
- * </pre>
- * You can also use switch-case-default tags to select Rows and Keys.
- * <pre>
- * &gt;switch&lt;
- * &gt;case case_attribute*&lt;
- * &gt;!-- Any valid tags at switch position --&lt;
- * &gt;/case&lt;
- * ...
- * &gt;default&lt;
- * &gt;!-- Any valid tags at switch position --&lt;
- * &gt;/default&lt;
- * &gt;/switch&lt;
- * </pre>
- * You can declare Key style and specify styles within Key tags.
- * <pre>
- * &gt;switch&lt;
- * &gt;case mode="email"&lt;
- * &gt;key-style styleName="f1-key" parentStyle="modifier-key"
- * keyLabel=".com"
- * /&lt;
- * &gt;/case&lt;
- * &gt;case mode="url"&lt;
- * &gt;key-style styleName="f1-key" parentStyle="modifier-key"
- * keyLabel="http://"
- * /&lt;
- * &gt;/case&lt;
- * &gt;/switch&lt;
- * ...
- * &gt;Key keyStyle="shift-key" ... /&lt;
- * </pre>
- */
-
-public class KeyboardBuilder<KP extends KeyboardParams> {
- private static final String TAG = KeyboardBuilder.class.getSimpleName();
- private static final boolean DEBUG = false;
-
- // Keyboard XML Tags
- private static final String TAG_KEYBOARD = "Keyboard";
- private static final String TAG_ROW = "Row";
- private static final String TAG_KEY = "Key";
- private static final String TAG_SPACER = "Spacer";
- private static final String TAG_INCLUDE = "include";
- private static final String TAG_MERGE = "merge";
- private static final String TAG_SWITCH = "switch";
- private static final String TAG_CASE = "case";
- private static final String TAG_DEFAULT = "default";
- public static final String TAG_KEY_STYLE = "key-style";
-
- private static final int DEFAULT_KEYBOARD_COLUMNS = 10;
- private static final int DEFAULT_KEYBOARD_ROWS = 4;
-
- protected final KP mParams;
- protected final Context mContext;
- protected final Resources mResources;
- private final DisplayMetrics mDisplayMetrics;
-
- private int mCurrentY = 0;
- private Row mCurrentRow = null;
- private boolean mLeftEdge;
- private boolean mTopEdge;
- private Key mRightEdgeKey = null;
- private final KeyStyles mKeyStyles = new KeyStyles();
-
- /**
- * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate.
- * Some of the key size defaults can be overridden per row from what the {@link Keyboard}
- * defines.
- */
- public static class Row {
- // keyWidth enum constants
- private static final int KEYWIDTH_NOT_ENUM = 0;
- private static final int KEYWIDTH_FILL_RIGHT = -1;
- private static final int KEYWIDTH_FILL_BOTH = -2;
-
- private final KeyboardParams mParams;
- /** Default width of a key in this row. */
- public final float mDefaultKeyWidth;
- /** Default height of a key in this row. */
- public final int mRowHeight;
-
- private final int mCurrentY;
- // Will be updated by {@link Key}'s constructor.
- private float mCurrentX;
-
- public Row(Resources res, KeyboardParams params, XmlPullParser parser, int y) {
- mParams = params;
- TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard);
- mRowHeight = (int)KeyboardBuilder.getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_rowHeight, params.mBaseHeight, params.mDefaultRowHeight);
- keyboardAttr.recycle();
- TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard_Key);
- mDefaultKeyWidth = KeyboardBuilder.getDimensionOrFraction(keyAttr,
- R.styleable.Keyboard_Key_keyWidth, params.mBaseWidth, params.mDefaultKeyWidth);
- keyAttr.recycle();
-
- mCurrentY = y;
- mCurrentX = 0.0f;
- }
-
- public void setXPos(float keyXPos) {
- mCurrentX = keyXPos;
- }
-
- public void advanceXPos(float width) {
- mCurrentX += width;
- }
-
- public int getKeyY() {
- return mCurrentY;
- }
-
- public float getKeyX(TypedArray keyAttr) {
- final int widthType = KeyboardBuilder.getEnumValue(keyAttr,
- R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
- if (widthType == KEYWIDTH_FILL_BOTH) {
- // If keyWidth is fillBoth, the key width should start right after the nearest key
- // on the left hand side.
- return mCurrentX;
- }
-
- final int keyboardRightEdge = mParams.mOccupiedWidth - mParams.mHorizontalEdgesPadding;
- if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyXPos)) {
- final float keyXPos = KeyboardBuilder.getDimensionOrFraction(keyAttr,
- R.styleable.Keyboard_Key_keyXPos, mParams.mBaseWidth, 0);
- if (keyXPos < 0) {
- // If keyXPos is negative, the actual x-coordinate will be
- // keyboardWidth + keyXPos.
- // keyXPos shouldn't be less than mCurrentX because drawable area for this key
- // starts at mCurrentX. Or, this key will overlaps the adjacent key on its left
- // hand side.
- return Math.max(keyXPos + keyboardRightEdge, mCurrentX);
- } else {
- return keyXPos + mParams.mHorizontalEdgesPadding;
- }
- }
- return mCurrentX;
- }
-
- public float getKeyWidth(TypedArray keyAttr, float keyXPos) {
- final int widthType = KeyboardBuilder.getEnumValue(keyAttr,
- R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
- switch (widthType) {
- case KEYWIDTH_FILL_RIGHT:
- case KEYWIDTH_FILL_BOTH:
- final int keyboardRightEdge =
- mParams.mOccupiedWidth - mParams.mHorizontalEdgesPadding;
- // If keyWidth is fillRight, the actual key width will be determined to fill out the
- // area up to the right edge of the keyboard.
- // If keyWidth is fillBoth, the actual key width will be determined to fill out the
- // area between the nearest key on the left hand side and the right edge of the
- // keyboard.
- return keyboardRightEdge - keyXPos;
- default: // KEYWIDTH_NOT_ENUM
- return KeyboardBuilder.getDimensionOrFraction(keyAttr,
- R.styleable.Keyboard_Key_keyWidth, mParams.mBaseWidth, mDefaultKeyWidth);
- }
- }
- }
-
- public KeyboardBuilder(Context context, KP params) {
- mContext = context;
- final Resources res = context.getResources();
- mResources = res;
- mDisplayMetrics = res.getDisplayMetrics();
-
- mParams = params;
-
- setTouchPositionCorrectionData(context, params);
-
- params.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
- params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
- }
-
- private static void setTouchPositionCorrectionData(Context context, KeyboardParams params) {
- final TypedArray a = context.obtainStyledAttributes(
- null, R.styleable.Keyboard, R.attr.keyboardStyle, 0);
- params.mThemeId = a.getInt(R.styleable.Keyboard_themeId, 0);
- final int resourceId = a.getResourceId(R.styleable.Keyboard_touchPositionCorrectionData, 0);
- a.recycle();
- if (resourceId == 0) {
- if (LatinImeLogger.sDBG)
- throw new RuntimeException("touchPositionCorrectionData is not defined");
- return;
- }
-
- final String[] data = context.getResources().getStringArray(resourceId);
- params.mTouchPositionCorrection.load(data);
- }
-
- public KeyboardBuilder<KP> load(KeyboardId id) {
- mParams.mId = id;
- final XmlResourceParser parser = mResources.getXml(id.getXmlId());
- try {
- parseKeyboard(parser);
- } catch (XmlPullParserException e) {
- Log.w(TAG, "keyboard XML parse error: " + e);
- throw new IllegalArgumentException(e);
- } catch (IOException e) {
- Log.w(TAG, "keyboard XML parse error: " + e);
- throw new RuntimeException(e);
- } finally {
- parser.close();
- }
- return this;
- }
-
- public void setTouchPositionCorrectionEnabled(boolean enabled) {
- mParams.mTouchPositionCorrection.setEnabled(enabled);
- }
-
- public Keyboard build() {
- return new Keyboard(mParams);
- }
-
- private void parseKeyboard(XmlResourceParser parser)
- throws XmlPullParserException, IOException {
- if (DEBUG) Log.d(TAG, String.format("<%s> %s", TAG_KEYBOARD, mParams.mId));
- int event;
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final String tag = parser.getName();
- if (TAG_KEYBOARD.equals(tag)) {
- parseKeyboardAttributes(parser);
- startKeyboard();
- parseKeyboardContent(parser, false);
- break;
- } else {
- throw new IllegalStartTag(parser, TAG_KEYBOARD);
- }
- }
- }
- }
-
- public static String parseKeyboardLocale(
- Context context, int resId) throws XmlPullParserException, IOException {
- final Resources res = context.getResources();
- final XmlPullParser parser = res.getXml(resId);
- if (parser == null) return "";
- int event;
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final String tag = parser.getName();
- if (TAG_KEYBOARD.equals(tag)) {
- final TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard);
- final String locale = keyboardAttr.getString(
- R.styleable.Keyboard_keyboardLocale);
- keyboardAttr.recycle();
- return locale;
- } else {
- throw new IllegalStartTag(parser, TAG_KEYBOARD);
- }
- }
- }
- return "";
- }
-
- private void parseKeyboardAttributes(XmlPullParser parser) {
- final int displayWidth = mDisplayMetrics.widthPixels;
- final TypedArray keyboardAttr = mContext.obtainStyledAttributes(
- Xml.asAttributeSet(parser), R.styleable.Keyboard, R.attr.keyboardStyle,
- R.style.Keyboard);
- final TypedArray keyAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard_Key);
- try {
- final int displayHeight = mDisplayMetrics.heightPixels;
- final int keyboardHeight = (int)keyboardAttr.getDimension(
- R.styleable.Keyboard_keyboardHeight, displayHeight / 2);
- final int maxKeyboardHeight = (int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_maxKeyboardHeight, displayHeight, displayHeight / 2);
- int minKeyboardHeight = (int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_minKeyboardHeight, displayHeight, displayHeight / 2);
- if (minKeyboardHeight < 0) {
- // Specified fraction was negative, so it should be calculated against display
- // width.
- minKeyboardHeight = -(int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_minKeyboardHeight, displayWidth, displayWidth / 2);
- }
- final KeyboardParams params = mParams;
- // Keyboard height will not exceed maxKeyboardHeight and will not be less than
- // minKeyboardHeight.
- params.mOccupiedHeight = Math.max(
- Math.min(keyboardHeight, maxKeyboardHeight), minKeyboardHeight);
- params.mOccupiedWidth = params.mId.mWidth;
- params.mTopPadding = (int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_keyboardTopPadding, params.mOccupiedHeight, 0);
- params.mBottomPadding = (int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_keyboardBottomPadding, params.mOccupiedHeight, 0);
- params.mHorizontalEdgesPadding = (int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_keyboardHorizontalEdgesPadding, mParams.mOccupiedWidth, 0);
-
- params.mBaseWidth = params.mOccupiedWidth - params.mHorizontalEdgesPadding * 2
- - params.mHorizontalCenterPadding;
- params.mDefaultKeyWidth = (int)getDimensionOrFraction(keyAttr,
- R.styleable.Keyboard_Key_keyWidth, params.mBaseWidth,
- params.mBaseWidth / DEFAULT_KEYBOARD_COLUMNS);
- params.mHorizontalGap = (int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_horizontalGap, params.mBaseWidth, 0);
- params.mVerticalGap = (int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_verticalGap, params.mOccupiedHeight, 0);
- params.mBaseHeight = params.mOccupiedHeight - params.mTopPadding
- - params.mBottomPadding + params.mVerticalGap;
- params.mDefaultRowHeight = (int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_rowHeight, params.mBaseHeight,
- params.mBaseHeight / DEFAULT_KEYBOARD_ROWS);
-
- params.mIsRtlKeyboard = keyboardAttr.getBoolean(
- R.styleable.Keyboard_isRtlKeyboard, false);
- params.mMoreKeysTemplate = keyboardAttr.getResourceId(
- R.styleable.Keyboard_moreKeysTemplate, 0);
- params.mMaxMiniKeyboardColumn = keyAttr.getInt(
- R.styleable.Keyboard_Key_maxMoreKeysColumn, 5);
-
- params.mIconsSet.loadIcons(keyboardAttr);
- } finally {
- keyAttr.recycle();
- keyboardAttr.recycle();
- }
- }
-
- private void parseKeyboardContent(XmlPullParser parser, boolean skip)
- throws XmlPullParserException, IOException {
- int event;
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final String tag = parser.getName();
- if (TAG_ROW.equals(tag)) {
- Row row = parseRowAttributes(parser);
- if (DEBUG) Log.d(TAG, String.format("<%s>", TAG_ROW));
- if (!skip)
- startRow(row);
- parseRowContent(parser, row, skip);
- } else if (TAG_INCLUDE.equals(tag)) {
- parseIncludeKeyboardContent(parser, skip);
- } else if (TAG_SWITCH.equals(tag)) {
- parseSwitchKeyboardContent(parser, skip);
- } else if (TAG_KEY_STYLE.equals(tag)) {
- parseKeyStyle(parser, skip);
- } else {
- throw new IllegalStartTag(parser, TAG_ROW);
- }
- } else if (event == XmlPullParser.END_TAG) {
- final String tag = parser.getName();
- if (TAG_KEYBOARD.equals(tag)) {
- endKeyboard();
- break;
- } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag)
- || TAG_MERGE.equals(tag)) {
- if (DEBUG) Log.d(TAG, String.format("</%s>", tag));
- break;
- } else if (TAG_KEY_STYLE.equals(tag)) {
- continue;
- } else {
- throw new IllegalEndTag(parser, TAG_ROW);
- }
- }
- }
- }
-
- private Row parseRowAttributes(XmlPullParser parser) {
- final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard);
- try {
- if (a.hasValue(R.styleable.Keyboard_horizontalGap))
- throw new IllegalAttribute(parser, "horizontalGap");
- if (a.hasValue(R.styleable.Keyboard_verticalGap))
- throw new IllegalAttribute(parser, "verticalGap");
- return new Row(mResources, mParams, parser, mCurrentY);
- } finally {
- a.recycle();
- }
- }
-
- private void parseRowContent(XmlPullParser parser, Row row, boolean skip)
- throws XmlPullParserException, IOException {
- int event;
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final String tag = parser.getName();
- if (TAG_KEY.equals(tag)) {
- parseKey(parser, row, skip);
- } else if (TAG_SPACER.equals(tag)) {
- parseSpacer(parser, row, skip);
- } else if (TAG_INCLUDE.equals(tag)) {
- parseIncludeRowContent(parser, row, skip);
- } else if (TAG_SWITCH.equals(tag)) {
- parseSwitchRowContent(parser, row, skip);
- } else if (TAG_KEY_STYLE.equals(tag)) {
- parseKeyStyle(parser, skip);
- } else {
- throw new IllegalStartTag(parser, TAG_KEY);
- }
- } else if (event == XmlPullParser.END_TAG) {
- final String tag = parser.getName();
- if (TAG_ROW.equals(tag)) {
- if (DEBUG) Log.d(TAG, String.format("</%s>", TAG_ROW));
- if (!skip)
- endRow(row);
- break;
- } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag)
- || TAG_MERGE.equals(tag)) {
- if (DEBUG) Log.d(TAG, String.format("</%s>", tag));
- break;
- } else if (TAG_KEY_STYLE.equals(tag)) {
- continue;
- } else {
- throw new IllegalEndTag(parser, TAG_KEY);
- }
- }
- }
- }
-
- private void parseKey(XmlPullParser parser, Row row, boolean skip)
- throws XmlPullParserException, IOException {
- if (skip) {
- checkEndTag(TAG_KEY, parser);
- } else {
- final Key key = new Key(mResources, mParams, row, parser, mKeyStyles);
- if (DEBUG) Log.d(TAG, String.format("<%s%s keyLabel=%s code=%d moreKeys=%s />",
- TAG_KEY, (key.isEnabled() ? "" : " disabled"), key.mLabel, key.mCode,
- Arrays.toString(key.mMoreKeys)));
- checkEndTag(TAG_KEY, parser);
- endKey(key);
- }
- }
-
- private void parseSpacer(XmlPullParser parser, Row row, boolean skip)
- throws XmlPullParserException, IOException {
- if (skip) {
- checkEndTag(TAG_SPACER, parser);
- } else {
- final Key.Spacer spacer = new Key.Spacer(mResources, mParams, row, parser, mKeyStyles);
- if (DEBUG) Log.d(TAG, String.format("<%s />", TAG_SPACER));
- checkEndTag(TAG_SPACER, parser);
- endKey(spacer);
- }
- }
-
- private void parseIncludeKeyboardContent(XmlPullParser parser, boolean skip)
- throws XmlPullParserException, IOException {
- parseIncludeInternal(parser, null, skip);
- }
-
- private void parseIncludeRowContent(XmlPullParser parser, Row row, boolean skip)
- throws XmlPullParserException, IOException {
- parseIncludeInternal(parser, row, skip);
- }
-
- private void parseIncludeInternal(XmlPullParser parser, Row row, boolean skip)
- throws XmlPullParserException, IOException {
- if (skip) {
- checkEndTag(TAG_INCLUDE, parser);
- } else {
- final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard_Include);
- final int keyboardLayout = a.getResourceId(
- R.styleable.Keyboard_Include_keyboardLayout, 0);
- a.recycle();
-
- checkEndTag(TAG_INCLUDE, parser);
- if (keyboardLayout == 0)
- throw new ParseException("No keyboardLayout attribute in <include/>", parser);
- if (DEBUG) Log.d(TAG, String.format("<%s keyboardLayout=%s />",
- TAG_INCLUDE, mResources.getResourceEntryName(keyboardLayout)));
- final XmlResourceParser parserForInclude = mResources.getXml(keyboardLayout);
- try {
- parseMerge(parserForInclude, row, skip);
- } finally {
- parserForInclude.close();
- }
- }
- }
-
- private void parseMerge(XmlPullParser parser, Row row, boolean skip)
- throws XmlPullParserException, IOException {
- int event;
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final String tag = parser.getName();
- if (TAG_MERGE.equals(tag)) {
- if (row == null) {
- parseKeyboardContent(parser, skip);
- } else {
- parseRowContent(parser, row, skip);
- }
- break;
- } else {
- throw new ParseException(
- "Included keyboard layout must have <merge> root element", parser);
- }
- }
- }
- }
-
- private void parseSwitchKeyboardContent(XmlPullParser parser, boolean skip)
- throws XmlPullParserException, IOException {
- parseSwitchInternal(parser, null, skip);
- }
-
- private void parseSwitchRowContent(XmlPullParser parser, Row row, boolean skip)
- throws XmlPullParserException, IOException {
- parseSwitchInternal(parser, row, skip);
- }
-
- private void parseSwitchInternal(XmlPullParser parser, Row row, boolean skip)
- throws XmlPullParserException, IOException {
- if (DEBUG) Log.d(TAG, String.format("<%s> %s", TAG_SWITCH, mParams.mId));
- boolean selected = false;
- int event;
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final String tag = parser.getName();
- if (TAG_CASE.equals(tag)) {
- selected |= parseCase(parser, row, selected ? true : skip);
- } else if (TAG_DEFAULT.equals(tag)) {
- selected |= parseDefault(parser, row, selected ? true : skip);
- } else {
- throw new IllegalStartTag(parser, TAG_KEY);
- }
- } else if (event == XmlPullParser.END_TAG) {
- final String tag = parser.getName();
- if (TAG_SWITCH.equals(tag)) {
- if (DEBUG) Log.d(TAG, String.format("</%s>", TAG_SWITCH));
- break;
- } else {
- throw new IllegalEndTag(parser, TAG_KEY);
- }
- }
- }
- }
-
- private boolean parseCase(XmlPullParser parser, Row row, boolean skip)
- throws XmlPullParserException, IOException {
- final boolean selected = parseCaseCondition(parser);
- if (row == null) {
- // Processing Rows.
- parseKeyboardContent(parser, selected ? skip : true);
- } else {
- // Processing Keys.
- parseRowContent(parser, row, selected ? skip : true);
- }
- return selected;
- }
-
- private boolean parseCaseCondition(XmlPullParser parser) {
- final KeyboardId id = mParams.mId;
- if (id == null)
- return true;
-
- final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard_Case);
- try {
- final boolean modeMatched = matchTypedValue(a,
- R.styleable.Keyboard_Case_mode, id.mMode, KeyboardId.modeName(id.mMode));
- final boolean navigateActionMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_navigateAction, id.mNavigateAction);
- final boolean passwordInputMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_passwordInput, id.mPasswordInput);
- final boolean hasSettingsKeyMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_hasSettingsKey, id.mHasSettingsKey);
- final boolean f2KeyModeMatched = matchInteger(a,
- R.styleable.Keyboard_Case_f2KeyMode, id.mF2KeyMode);
- final boolean clobberSettingsKeyMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_clobberSettingsKey, id.mClobberSettingsKey);
- final boolean shortcutKeyEnabledMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_shortcutKeyEnabled, id.mShortcutKeyEnabled);
- final boolean hasShortcutKeyMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_hasShortcutKey, id.mHasShortcutKey);
- // As noted at {@link KeyboardId} class, we are interested only in enum value masked by
- // {@link android.view.inputmethod.EditorInfo#IME_MASK_ACTION} and
- // {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ENTER_ACTION}. So matching
- // this attribute with id.mImeOptions as integer value is enough for our purpose.
- final boolean imeActionMatched = matchInteger(a,
- R.styleable.Keyboard_Case_imeAction, id.mImeAction);
- final boolean localeCodeMatched = matchString(a,
- R.styleable.Keyboard_Case_localeCode, id.mLocale.toString());
- final boolean languageCodeMatched = matchString(a,
- R.styleable.Keyboard_Case_languageCode, id.mLocale.getLanguage());
- final boolean countryCodeMatched = matchString(a,
- R.styleable.Keyboard_Case_countryCode, id.mLocale.getCountry());
- final boolean selected = modeMatched && navigateActionMatched && passwordInputMatched
- && hasSettingsKeyMatched && f2KeyModeMatched && clobberSettingsKeyMatched
- && shortcutKeyEnabledMatched && hasShortcutKeyMatched && imeActionMatched &&
- localeCodeMatched && languageCodeMatched && countryCodeMatched;
-
- if (DEBUG) Log.d(TAG, String.format("<%s%s%s%s%s%s%s%s%s%s%s%s%s> %s", TAG_CASE,
- textAttr(a.getString(R.styleable.Keyboard_Case_mode), "mode"),
- booleanAttr(a, R.styleable.Keyboard_Case_navigateAction, "navigateAction"),
- booleanAttr(a, R.styleable.Keyboard_Case_passwordInput, "passwordInput"),
- booleanAttr(a, R.styleable.Keyboard_Case_hasSettingsKey, "hasSettingsKey"),
- textAttr(KeyboardId.f2KeyModeName(
- a.getInt(R.styleable.Keyboard_Case_f2KeyMode, -1)), "f2KeyMode"),
- booleanAttr(a, R.styleable.Keyboard_Case_clobberSettingsKey,
- "clobberSettingsKey"),
- booleanAttr(
- a, R.styleable.Keyboard_Case_shortcutKeyEnabled, "shortcutKeyEnabled"),
- booleanAttr(a, R.styleable.Keyboard_Case_hasShortcutKey, "hasShortcutKey"),
- textAttr(EditorInfoCompatUtils.imeOptionsName(
- a.getInt(R.styleable.Keyboard_Case_imeAction, -1)), "imeAction"),
- textAttr(a.getString(R.styleable.Keyboard_Case_localeCode), "localeCode"),
- textAttr(a.getString(R.styleable.Keyboard_Case_languageCode), "languageCode"),
- textAttr(a.getString(R.styleable.Keyboard_Case_countryCode), "countryCode"),
- Boolean.toString(selected)));
-
- return selected;
- } finally {
- a.recycle();
- }
- }
-
- private static boolean matchInteger(TypedArray a, int index, int value) {
- // If <case> does not have "index" attribute, that means this <case> is wild-card for the
- // attribute.
- return !a.hasValue(index) || a.getInt(index, 0) == value;
- }
-
- private static boolean matchBoolean(TypedArray a, int index, boolean value) {
- // If <case> does not have "index" attribute, that means this <case> is wild-card for the
- // attribute.
- return !a.hasValue(index) || a.getBoolean(index, false) == value;
- }
-
- private static boolean matchString(TypedArray a, int index, String value) {
- // If <case> does not have "index" attribute, that means this <case> is wild-card for the
- // attribute.
- return !a.hasValue(index) || stringArrayContains(a.getString(index).split("\\|"), value);
- }
-
- private static boolean matchTypedValue(TypedArray a, int index, int intValue, String strValue) {
- // If <case> does not have "index" attribute, that means this <case> is wild-card for the
- // attribute.
- final TypedValue v = a.peekValue(index);
- if (v == null)
- return true;
-
- if (isIntegerValue(v)) {
- return intValue == a.getInt(index, 0);
- } else if (isStringValue(v)) {
- return stringArrayContains(a.getString(index).split("\\|"), strValue);
- }
- return false;
- }
-
- private static boolean stringArrayContains(String[] array, String value) {
- for (final String elem : array) {
- if (elem.equals(value))
- return true;
- }
- return false;
- }
-
- private boolean parseDefault(XmlPullParser parser, Row row, boolean skip)
- throws XmlPullParserException, IOException {
- if (DEBUG) Log.d(TAG, String.format("<%s>", TAG_DEFAULT));
- if (row == null) {
- parseKeyboardContent(parser, skip);
- } else {
- parseRowContent(parser, row, skip);
- }
- return true;
- }
-
- private void parseKeyStyle(XmlPullParser parser, boolean skip) {
- TypedArray keyStyleAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard_KeyStyle);
- TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard_Key);
- try {
- if (!keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_styleName))
- throw new ParseException("<" + TAG_KEY_STYLE
- + "/> needs styleName attribute", parser);
- if (!skip)
- mKeyStyles.parseKeyStyleAttributes(keyStyleAttr, keyAttrs, parser);
- } finally {
- keyStyleAttr.recycle();
- keyAttrs.recycle();
- }
- }
-
- private static void checkEndTag(String tag, XmlPullParser parser)
- throws XmlPullParserException, IOException {
- if (parser.next() == XmlPullParser.END_TAG && tag.equals(parser.getName()))
- return;
- throw new NonEmptyTag(tag, parser);
- }
-
- private void startKeyboard() {
- mCurrentY += mParams.mTopPadding;
- mTopEdge = true;
- }
-
- private void startRow(Row row) {
- addEdgeSpace(mParams.mHorizontalEdgesPadding, row);
- mCurrentRow = row;
- mLeftEdge = true;
- mRightEdgeKey = null;
- }
-
- private void endRow(Row row) {
- if (mCurrentRow == null)
- throw new InflateException("orphant end row tag");
- if (mRightEdgeKey != null) {
- mRightEdgeKey.markAsRightEdge(mParams);
- mRightEdgeKey = null;
- }
- addEdgeSpace(mParams.mHorizontalEdgesPadding, row);
- mCurrentY += row.mRowHeight;
- mCurrentRow = null;
- mTopEdge = false;
- }
-
- private void endKey(Key key) {
- mParams.onAddKey(key);
- if (mLeftEdge) {
- key.markAsLeftEdge(mParams);
- mLeftEdge = false;
- }
- if (mTopEdge) {
- key.markAsTopEdge(mParams);
- }
- mRightEdgeKey = key;
- }
-
- private void endKeyboard() {
- }
-
- private void addEdgeSpace(float width, Row row) {
- row.advanceXPos(width);
- mLeftEdge = false;
- mRightEdgeKey = null;
- }
-
- public static float getDimensionOrFraction(TypedArray a, int index, int base, float defValue) {
- final TypedValue value = a.peekValue(index);
- if (value == null)
- return defValue;
- if (isFractionValue(value)) {
- return a.getFraction(index, base, base, defValue);
- } else if (isDimensionValue(value)) {
- return a.getDimension(index, defValue);
- }
- return defValue;
- }
-
- public static int getEnumValue(TypedArray a, int index, int defValue) {
- final TypedValue value = a.peekValue(index);
- if (value == null)
- return defValue;
- if (isIntegerValue(value)) {
- return a.getInt(index, defValue);
- }
- return defValue;
- }
-
- private static boolean isFractionValue(TypedValue v) {
- return v.type == TypedValue.TYPE_FRACTION;
- }
-
- private static boolean isDimensionValue(TypedValue v) {
- return v.type == TypedValue.TYPE_DIMENSION;
- }
-
- private static boolean isIntegerValue(TypedValue v) {
- return v.type >= TypedValue.TYPE_FIRST_INT && v.type <= TypedValue.TYPE_LAST_INT;
- }
-
- private static boolean isStringValue(TypedValue v) {
- return v.type == TypedValue.TYPE_STRING;
- }
-
- @SuppressWarnings("serial")
- public static class ParseException extends InflateException {
- public ParseException(String msg, XmlPullParser parser) {
- super(msg + " at line " + parser.getLineNumber());
- }
- }
-
- @SuppressWarnings("serial")
- private static class IllegalStartTag extends ParseException {
- public IllegalStartTag(XmlPullParser parser, String parent) {
- super("Illegal start tag " + parser.getName() + " in " + parent, parser);
- }
- }
-
- @SuppressWarnings("serial")
- private static class IllegalEndTag extends ParseException {
- public IllegalEndTag(XmlPullParser parser, String parent) {
- super("Illegal end tag " + parser.getName() + " in " + parent, parser);
- }
- }
-
- @SuppressWarnings("serial")
- private static class IllegalAttribute extends ParseException {
- public IllegalAttribute(XmlPullParser parser, String attribute) {
- super("Tag " + parser.getName() + " has illegal attribute " + attribute, parser);
- }
- }
-
- @SuppressWarnings("serial")
- private static class NonEmptyTag extends ParseException {
- public NonEmptyTag(String tag, XmlPullParser parser) {
- super(tag + " must be empty tag", parser);
- }
- }
-
- private static String textAttr(String value, String name) {
- return value != null ? String.format(" %s=%s", name, value) : "";
- }
-
- private static String booleanAttr(TypedArray a, int index, String name) {
- return a.hasValue(index) ? String.format(" %s=%s", name, a.getBoolean(index, false)) : "";
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index faa5f86f2..6313a61b5 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -23,80 +23,75 @@ import android.util.Log;
import com.android.inputmethod.latin.R;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
public class KeyboardIconsSet {
private static final String TAG = KeyboardIconsSet.class.getSimpleName();
public static final int ICON_UNDEFINED = 0;
- // This should be aligned with Keyboard.keyIcon enum.
- private static final int ICON_SHIFT_KEY = 1;
- private static final int ICON_DELETE_KEY = 2;
- private static final int ICON_SETTINGS_KEY = 3; // This is also represented as "@icon/3" in XML.
- private static final int ICON_SPACE_KEY = 4;
- private static final int ICON_RETURN_KEY = 5;
- private static final int ICON_SEARCH_KEY = 6;
- private static final int ICON_TAB_KEY = 7; // This is also represented as "@icon/7" in XML.
- private static final int ICON_SHORTCUT_KEY = 8;
- private static final int ICON_SHORTCUT_FOR_LABEL = 9;
- // This should be aligned with Keyboard.keyIconShifted enum.
- private static final int ICON_SHIFTED_SHIFT_KEY = 10;
- // This should be aligned with Keyboard.keyIconPreview enum.
- private static final int ICON_PREVIEW_TAB_KEY = 11;
+ private final Map<Integer, Drawable> mIcons = new HashMap<Integer, Drawable>();
- private static final int ICON_LAST = 11;
+ // The key value should be aligned with the enum value of Keyboard.icon*.
+ private static final Map<Integer, Integer> ICONS_TO_ATTRS_MAP = new HashMap<Integer, Integer>();
+ private static final Collection<Integer> VALID_ATTRS;
- private final Drawable mIcons[] = new Drawable[ICON_LAST + 1];
+ static {
+ addIconIdMap(1, R.styleable.Keyboard_iconShiftKey);
+ addIconIdMap(2, R.styleable.Keyboard_iconDeleteKey);
+ // This is also represented as "@icon/3" in keyboard layout XML.
+ addIconIdMap(3, R.styleable.Keyboard_iconSettingsKey);
+ addIconIdMap(4, R.styleable.Keyboard_iconSpaceKey);
+ addIconIdMap(5, R.styleable.Keyboard_iconReturnKey);
+ addIconIdMap(6, R.styleable.Keyboard_iconSearchKey);
+ // This is also represented as "@icon/7" in keyboard layout XML.
+ addIconIdMap(7, R.styleable.Keyboard_iconTabKey);
+ addIconIdMap(8, R.styleable.Keyboard_iconShortcutKey);
+ addIconIdMap(9, R.styleable.Keyboard_iconShortcutForLabel);
+ addIconIdMap(10, R.styleable.Keyboard_iconSpaceKeyForNumberLayout);
+ addIconIdMap(11, R.styleable.Keyboard_iconShiftKeyShifted);
+ addIconIdMap(12, R.styleable.Keyboard_iconDisabledShortcutKey);
+ addIconIdMap(13, R.styleable.Keyboard_iconPreviewTabKey);
+ VALID_ATTRS = ICONS_TO_ATTRS_MAP.values();
+ }
- private static final int getIconId(final int attrIndex) {
- switch (attrIndex) {
- case R.styleable.Keyboard_iconShiftKey:
- return ICON_SHIFT_KEY;
- case R.styleable.Keyboard_iconDeleteKey:
- return ICON_DELETE_KEY;
- case R.styleable.Keyboard_iconSettingsKey:
- return ICON_SETTINGS_KEY;
- case R.styleable.Keyboard_iconSpaceKey:
- return ICON_SPACE_KEY;
- case R.styleable.Keyboard_iconReturnKey:
- return ICON_RETURN_KEY;
- case R.styleable.Keyboard_iconSearchKey:
- return ICON_SEARCH_KEY;
- case R.styleable.Keyboard_iconTabKey:
- return ICON_TAB_KEY;
- case R.styleable.Keyboard_iconShortcutKey:
- return ICON_SHORTCUT_KEY;
- case R.styleable.Keyboard_iconShortcutForLabel:
- return ICON_SHORTCUT_FOR_LABEL;
- case R.styleable.Keyboard_iconShiftedShiftKey:
- return ICON_SHIFTED_SHIFT_KEY;
- case R.styleable.Keyboard_iconPreviewTabKey:
- return ICON_PREVIEW_TAB_KEY;
- default:
- return ICON_UNDEFINED;
- }
+ private static void addIconIdMap(int iconId, int attrId) {
+ ICONS_TO_ATTRS_MAP.put(iconId, attrId);
}
public void loadIcons(final TypedArray keyboardAttrs) {
- final int count = keyboardAttrs.getIndexCount();
- for (int i = 0; i < count; i++) {
- final int attrIndex = keyboardAttrs.getIndex(i);
- final int iconId = getIconId(attrIndex);
- if (iconId != ICON_UNDEFINED) {
- try {
- mIcons[iconId] = setDefaultBounds(keyboardAttrs.getDrawable(attrIndex));
- } catch (Resources.NotFoundException e) {
- Log.w(TAG, "Drawable resource for icon #" + iconId + " not found");
- }
+ for (final Integer attrId : VALID_ATTRS) {
+ try {
+ final Drawable icon = keyboardAttrs.getDrawable(attrId);
+ if (icon == null) continue;
+ setDefaultBounds(icon);
+ mIcons.put(attrId, icon);
+ } catch (Resources.NotFoundException e) {
+ Log.w(TAG, "Drawable resource for icon #"
+ + keyboardAttrs.getResources().getResourceEntryName(attrId)
+ + " not found");
}
}
}
- public Drawable getIcon(final int iconId) {
- if (iconId == ICON_UNDEFINED)
+ public Drawable getIconByIconId(final Integer iconId) {
+ if (iconId == ICON_UNDEFINED) {
return null;
- if (iconId < 0 || iconId >= mIcons.length)
+ }
+ final Integer attrId = ICONS_TO_ATTRS_MAP.get(iconId);
+ if (attrId == null) {
throw new IllegalArgumentException("icon id is out of range: " + iconId);
- return mIcons[iconId];
+ }
+ return getIconByAttrId(attrId);
+ }
+
+ public Drawable getIconByAttrId(final Integer attrId) {
+ if (!VALID_ATTRS.contains(attrId)) {
+ throw new IllegalArgumentException("unknown icon attribute id: " + attrId);
+ }
+ return mIcons.get(attrId);
}
private static Drawable setDefaultBounds(final Drawable icon) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
deleted file mode 100644
index 64cd37c4b..000000000
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.keyboard.internal;
-
-import android.graphics.drawable.Drawable;
-
-import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.latin.LatinImeLogger;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-public class KeyboardParams {
- public KeyboardId mId;
- public int mThemeId;
-
- /** Total height and width of the keyboard, including the paddings and keys */
- public int mOccupiedHeight;
- public int mOccupiedWidth;
-
- /** Base height and width of the keyboard used to calculate rows' or keys' heights and widths */
- public int mBaseHeight;
- public int mBaseWidth;
-
- public int mTopPadding;
- public int mBottomPadding;
- public int mHorizontalEdgesPadding;
- public int mHorizontalCenterPadding;
-
- public int mDefaultRowHeight;
- public int mDefaultKeyWidth;
- public int mHorizontalGap;
- public int mVerticalGap;
-
- public boolean mIsRtlKeyboard;
- public int mMoreKeysTemplate;
- public int mMaxMiniKeyboardColumn;
-
- public int GRID_WIDTH;
- public int GRID_HEIGHT;
-
- public final List<Key> mKeys = new ArrayList<Key>();
- public final List<Key> mShiftKeys = new ArrayList<Key>();
- public final Set<Key> mShiftLockKeys = new HashSet<Key>();
- public final Map<Key, Drawable> mShiftedIcons = new HashMap<Key, Drawable>();
- public final Map<Key, Drawable> mUnshiftedIcons = new HashMap<Key, Drawable>();
- public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet();
-
- public int mMostCommonKeyHeight = 0;
- public int mMostCommonKeyWidth = 0;
-
- public final TouchPositionCorrection mTouchPositionCorrection = new TouchPositionCorrection();
-
- public static class TouchPositionCorrection {
- private static final int TOUCH_POSITION_CORRECTION_RECORD_SIZE = 3;
-
- public boolean mEnabled;
- public float[] mXs;
- public float[] mYs;
- public float[] mRadii;
-
- public void load(String[] data) {
- final int dataLength = data.length;
- if (dataLength % TOUCH_POSITION_CORRECTION_RECORD_SIZE != 0) {
- if (LatinImeLogger.sDBG)
- throw new RuntimeException(
- "the size of touch position correction data is invalid");
- return;
- }
-
- final int length = dataLength / TOUCH_POSITION_CORRECTION_RECORD_SIZE;
- mXs = new float[length];
- mYs = new float[length];
- mRadii = new float[length];
- try {
- for (int i = 0; i < dataLength; ++i) {
- final int type = i % TOUCH_POSITION_CORRECTION_RECORD_SIZE;
- final int index = i / TOUCH_POSITION_CORRECTION_RECORD_SIZE;
- final float value = Float.parseFloat(data[i]);
- if (type == 0) {
- mXs[index] = value;
- } else if (type == 1) {
- mYs[index] = value;
- } else {
- mRadii[index] = value;
- }
- }
- } catch (NumberFormatException e) {
- if (LatinImeLogger.sDBG) {
- throw new RuntimeException(
- "the number format for touch position correction data is invalid");
- }
- mXs = null;
- mYs = null;
- mRadii = null;
- }
- }
-
- public void setEnabled(boolean enabled) {
- mEnabled = enabled;
- }
-
- public boolean isValid() {
- return mEnabled && mXs != null && mYs != null && mRadii != null
- && mXs.length > 0 && mYs.length > 0 && mRadii.length > 0;
- }
- }
-
- protected void clearKeys() {
- mKeys.clear();
- mShiftKeys.clear();
- mShiftLockKeys.clear();
- mShiftedIcons.clear();
- mUnshiftedIcons.clear();
- clearHistogram();
- }
-
- public void onAddKey(Key key) {
- mKeys.add(key);
- updateHistogram(key);
- if (key.mCode == Keyboard.CODE_SHIFT) {
- mShiftKeys.add(key);
- if (key.isSticky()) {
- mShiftLockKeys.add(key);
- }
- }
- }
-
- public void addShiftedIcon(Key key, Drawable icon) {
- mUnshiftedIcons.put(key, key.getIcon());
- mShiftedIcons.put(key, icon);
- }
-
- private int mMaxHeightCount = 0;
- private int mMaxWidthCount = 0;
- private final Map<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>();
- private final Map<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>();
-
- private void clearHistogram() {
- mMostCommonKeyHeight = 0;
- mMaxHeightCount = 0;
- mHeightHistogram.clear();
-
- mMaxWidthCount = 0;
- mMostCommonKeyWidth = 0;
- mWidthHistogram.clear();
- }
-
- private static int updateHistogramCounter(Map<Integer, Integer> histogram, Integer key) {
- final int count = (histogram.containsKey(key) ? histogram.get(key) : 0) + 1;
- histogram.put(key, count);
- return count;
- }
-
- private void updateHistogram(Key key) {
- final Integer height = key.mHeight + key.mVerticalGap;
- final int heightCount = updateHistogramCounter(mHeightHistogram, height);
- if (heightCount > mMaxHeightCount) {
- mMaxHeightCount = heightCount;
- mMostCommonKeyHeight = height;
- }
-
- final Integer width = key.mWidth + key.mHorizontalGap;
- final int widthCount = updateHistogramCounter(mWidthHistogram, width);
- if (widthCount > mMaxWidthCount) {
- mMaxWidthCount = widthCount;
- mMostCommonKeyWidth = width;
- }
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java
index 28a53cedc..11fb91a8c 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java
@@ -18,11 +18,9 @@ package com.android.inputmethod.keyboard.internal;
import android.util.Log;
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
-
public class KeyboardShiftState {
private static final String TAG = KeyboardShiftState.class.getSimpleName();
- private static final boolean DEBUG = KeyboardSwitcher.DEBUG_STATE;
+ private static final boolean DEBUG = false;
private static final int NORMAL = 0;
private static final int MANUAL_SHIFTED = 1;
@@ -33,7 +31,7 @@ public class KeyboardShiftState {
private int mState = NORMAL;
- public boolean setShifted(boolean newShiftState) {
+ public void setShifted(boolean newShiftState) {
final int oldState = mState;
if (newShiftState) {
switch (oldState) {
@@ -61,7 +59,6 @@ public class KeyboardShiftState {
}
if (DEBUG)
Log.d(TAG, "setShifted(" + newShiftState + "): " + toString(oldState) + " > " + this);
- return mState != oldState;
}
public void setShiftLocked(boolean newShiftLockState) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
new file mode 100644
index 000000000..f54bdbb05
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.inputmethod.keyboard.Keyboard;
+
+// TODO: Add unit tests
+/**
+ * Keyboard state machine.
+ *
+ * This class contains all keyboard state transition logic.
+ *
+ * The input events are {@link #onLoadKeyboard(String, boolean)}, {@link #onSaveKeyboardState()},
+ * {@link #onPressShift(boolean)}, {@link #onReleaseShift(boolean)}, {@link #onPressSymbol()},
+ * {@link #onReleaseSymbol()}, {@link #onOtherKeyPressed()},
+ * {@link #onCodeInput(int, boolean, boolean)}, {@link #onCancelInput(boolean)},
+ * {@link #onUpdateShiftState(boolean)}, {@link #onToggleShift()}, {@link #onToggleCapsLock()},
+ * and {@link #onToggleAlphabetAndSymbols()}.
+ *
+ * The actions are {@link SwitchActions}'s methods.
+ */
+public class KeyboardState {
+ private static final String TAG = KeyboardState.class.getSimpleName();
+ private static final boolean DEBUG_STATE = false;
+
+ public interface SwitchActions {
+ public void setAlphabetKeyboard();
+
+ public static final int UNSHIFT = 0;
+ public static final int MANUAL_SHIFT = 1;
+ public static final int AUTOMATIC_SHIFT = 2;
+ public void setShifted(int shiftMode);
+
+ public void setShiftLocked(boolean shiftLocked);
+
+ public void setSymbolsKeyboard();
+
+ public void setSymbolsShiftedKeyboard();
+ }
+
+ private KeyboardShiftState mKeyboardShiftState = new KeyboardShiftState();
+
+ private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift");
+ private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol");
+
+ 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 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;
+
+ private String mLayoutSwitchBackSymbols;
+ private boolean mHasDistinctMultitouch;
+
+ private final SwitchActions mSwitchActions;
+
+ private boolean mIsAlphabetMode;
+ private boolean mIsSymbolShifted;
+
+ private final SavedKeyboardState mSavedKeyboardState = new SavedKeyboardState();
+ private boolean mPrevMainKeyboardWasShiftLocked;
+
+ static class SavedKeyboardState {
+ public boolean mIsValid;
+ public boolean mIsAlphabetMode;
+ public boolean mIsShiftLocked;
+ public boolean mIsShifted;
+ }
+
+ public KeyboardState(SwitchActions switchActions) {
+ mSwitchActions = switchActions;
+ }
+
+ public void onLoadKeyboard(String layoutSwitchBackSymbols, boolean hasDistinctMultitouch) {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "onLoadKeyboard");
+ }
+ mLayoutSwitchBackSymbols = layoutSwitchBackSymbols;
+ mHasDistinctMultitouch = hasDistinctMultitouch;
+ mKeyboardShiftState.setShifted(false);
+ mKeyboardShiftState.setShiftLocked(false);
+ mShiftKeyState.onRelease();
+ mSymbolKeyState.onRelease();
+ mPrevMainKeyboardWasShiftLocked = false;
+ onRestoreKeyboardState();
+ }
+
+ public void onSaveKeyboardState() {
+ final SavedKeyboardState state = mSavedKeyboardState;
+ state.mIsAlphabetMode = mIsAlphabetMode;
+ if (mIsAlphabetMode) {
+ state.mIsShiftLocked = mKeyboardShiftState.isShiftLocked();
+ state.mIsShifted = !state.mIsShiftLocked
+ && mKeyboardShiftState.isShiftedOrShiftLocked();
+ } else {
+ state.mIsShiftLocked = false;
+ state.mIsShifted = mIsSymbolShifted;
+ }
+ state.mIsValid = true;
+ if (DEBUG_STATE) {
+ Log.d(TAG, "onSaveKeyboardState: alphabet=" + state.mIsAlphabetMode
+ + " shiftLocked=" + state.mIsShiftLocked + " shift=" + state.mIsShifted);
+ }
+ }
+
+ private void onRestoreKeyboardState() {
+ final SavedKeyboardState state = mSavedKeyboardState;
+ if (DEBUG_STATE) {
+ Log.d(TAG, "onRestoreKeyboardState: valid=" + state.mIsValid
+ + " alphabet=" + state.mIsAlphabetMode
+ + " shiftLocked=" + state.mIsShiftLocked + " shift=" + state.mIsShifted);
+ }
+ if (!state.mIsValid || state.mIsAlphabetMode) {
+ setAlphabetKeyboard();
+ } else {
+ if (state.mIsShifted) {
+ setSymbolsShiftedKeyboard();
+ } else {
+ setSymbolsKeyboard();
+ }
+ }
+
+ if (!state.mIsValid) return;
+ state.mIsValid = false;
+
+ if (state.mIsAlphabetMode) {
+ setShiftLocked(state.mIsShiftLocked);
+ if (!state.mIsShiftLocked) {
+ setShifted(state.mIsShifted ? SwitchActions.MANUAL_SHIFT : SwitchActions.UNSHIFT);
+ }
+ }
+ }
+
+ // TODO: Remove this method.
+ public boolean isShiftLocked() {
+ return mKeyboardShiftState.isShiftLocked();
+ }
+
+ private void setShifted(int shiftMode) {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode));
+ }
+ if (shiftMode == SwitchActions.AUTOMATIC_SHIFT) {
+ mKeyboardShiftState.setAutomaticTemporaryUpperCase();
+ } else {
+ // TODO: Duplicated logic in KeyboardSwitcher#setShifted()
+ final boolean shifted = (shiftMode == SwitchActions.MANUAL_SHIFT);
+ // On non-distinct multi touch panel device, we should also turn off the shift locked
+ // state when shift key is pressed to go to normal mode.
+ // On the other hand, on distinct multi touch panel device, turning off the shift
+ // locked state with shift key pressing is handled by onReleaseShift().
+ if (!mHasDistinctMultitouch && !shifted && mKeyboardShiftState.isShiftLocked()) {
+ mKeyboardShiftState.setShiftLocked(false);
+ }
+ mKeyboardShiftState.setShifted(shifted);
+ }
+ mSwitchActions.setShifted(shiftMode);
+ }
+
+ private void setShiftLocked(boolean shiftLocked) {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked);
+ }
+ mKeyboardShiftState.setShiftLocked(shiftLocked);
+ mSwitchActions.setShiftLocked(shiftLocked);
+ }
+
+ private void toggleAlphabetAndSymbols() {
+ if (mIsAlphabetMode) {
+ setSymbolsKeyboard();
+ } else {
+ setAlphabetKeyboard();
+ }
+ }
+
+ private void toggleShiftInSymbols() {
+ if (mIsSymbolShifted) {
+ setSymbolsKeyboard();
+ } else {
+ setSymbolsShiftedKeyboard();
+ }
+ }
+
+ private void setAlphabetKeyboard() {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "setAlphabetKeyboard");
+ }
+ mSwitchActions.setAlphabetKeyboard();
+ mIsAlphabetMode = true;
+ mIsSymbolShifted = false;
+ mSwitchState = SWITCH_STATE_ALPHA;
+ setShiftLocked(mPrevMainKeyboardWasShiftLocked);
+ mPrevMainKeyboardWasShiftLocked = false;
+ }
+
+ private void setSymbolsKeyboard() {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "setSymbolsKeyboard");
+ }
+ mPrevMainKeyboardWasShiftLocked = mKeyboardShiftState.isShiftLocked();
+ mSwitchActions.setSymbolsKeyboard();
+ mIsAlphabetMode = false;
+ mIsSymbolShifted = false;
+ mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
+ }
+
+ private void setSymbolsShiftedKeyboard() {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "setSymbolsShiftedKeyboard");
+ }
+ mSwitchActions.setSymbolsShiftedKeyboard();
+ mIsAlphabetMode = false;
+ mIsSymbolShifted = true;
+ mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
+ }
+
+ public void onPressSymbol() {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "onPressSymbol: " + this);
+ }
+ toggleAlphabetAndSymbols();
+ mSymbolKeyState.onPress();
+ mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL;
+ }
+
+ public void onReleaseSymbol() {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "onReleaseSymbol: " + this);
+ }
+ // Snap back to the previous keyboard mode if the user chords the mode change key and
+ // another key, then releases the mode change key.
+ if (mSwitchState == SWITCH_STATE_CHORDING_ALPHA) {
+ toggleAlphabetAndSymbols();
+ }
+ mSymbolKeyState.onRelease();
+ }
+
+ public void onOtherKeyPressed() {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "onOtherKeyPressed: " + this);
+ }
+ mShiftKeyState.onOtherKeyPressed();
+ mSymbolKeyState.onOtherKeyPressed();
+ }
+
+ public void onUpdateShiftState(boolean autoCaps) {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this);
+ }
+ onUpdateShiftStateInternal(autoCaps);
+ }
+
+ private void onUpdateShiftStateInternal(boolean autoCaps) {
+ if (mIsAlphabetMode) {
+ if (!mKeyboardShiftState.isShiftLocked() && !mShiftKeyState.isIgnoring()) {
+ if (mShiftKeyState.isReleasing() && autoCaps) {
+ // Only when shift key is releasing, automatic temporary upper case will be set.
+ setShifted(SwitchActions.AUTOMATIC_SHIFT);
+ } else {
+ setShifted(mShiftKeyState.isMomentary()
+ ? SwitchActions.MANUAL_SHIFT : SwitchActions.UNSHIFT);
+ }
+ }
+ } else {
+ // In symbol keyboard mode, we should clear shift key state because only alphabet
+ // keyboard has shift key.
+ mSymbolKeyState.onRelease();
+ }
+ }
+
+ public void onPressShift(boolean withSliding) {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "onPressShift: sliding=" + withSliding + " " + this);
+ }
+ if (mIsAlphabetMode) {
+ if (mKeyboardShiftState.isShiftLocked()) {
+ // Shift key is pressed while caps lock state, we will treat this state as shifted
+ // caps lock state and mark as if shift key pressed while normal state.
+ setShifted(SwitchActions.MANUAL_SHIFT);
+ mShiftKeyState.onPress();
+ } else if (mKeyboardShiftState.isAutomaticTemporaryUpperCase()) {
+ // Shift key is pressed while automatic temporary upper case, we have to move to
+ // manual temporary upper case.
+ setShifted(SwitchActions.MANUAL_SHIFT);
+ mShiftKeyState.onPress();
+ } else if (mKeyboardShiftState.isShiftedOrShiftLocked()) {
+ // In manual upper case state, we just record shift key has been pressing while
+ // shifted state.
+ mShiftKeyState.onPressOnShifted();
+ } else {
+ // In base layout, chording or manual temporary upper case mode is started.
+ setShifted(SwitchActions.MANUAL_SHIFT);
+ mShiftKeyState.onPress();
+ }
+ } else {
+ // In symbol mode, just toggle symbol and symbol more keyboard.
+ toggleShiftInSymbols();
+ mSwitchState = SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE;
+ mShiftKeyState.onPress();
+ }
+ }
+
+ public void onReleaseShift(boolean withSliding) {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "onReleaseShift: sliding=" + withSliding + " " + this);
+ }
+ if (mIsAlphabetMode) {
+ final boolean isShiftLocked = mKeyboardShiftState.isShiftLocked();
+ if (mShiftKeyState.isMomentary()) {
+ // After chording input while normal state.
+ setShifted(SwitchActions.UNSHIFT);
+ } else if (isShiftLocked && !mKeyboardShiftState.isShiftLockShifted()
+ && (mShiftKeyState.isPressing() || mShiftKeyState.isPressingOnShifted())
+ && !withSliding) {
+ // Shift has been long pressed, ignore this release.
+ } else if (isShiftLocked && !mShiftKeyState.isIgnoring() && !withSliding) {
+ // Shift has been pressed without chording while caps lock state.
+ setShiftLocked(false);
+ } else if (mKeyboardShiftState.isShiftedOrShiftLocked()
+ && mShiftKeyState.isPressingOnShifted() && !withSliding) {
+ // Shift has been pressed without chording while shifted state.
+ setShifted(SwitchActions.UNSHIFT);
+ } else if (mKeyboardShiftState.isManualTemporaryUpperCaseFromAuto()
+ && mShiftKeyState.isPressing() && !withSliding) {
+ // Shift has been pressed without chording while manual temporary upper case
+ // transited from automatic temporary upper case.
+ setShifted(SwitchActions.UNSHIFT);
+ }
+ } 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) {
+ toggleShiftInSymbols();
+ }
+ }
+ mShiftKeyState.onRelease();
+ }
+
+ public void onCancelInput(boolean isSinglePointer) {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "onCancelInput: isSinglePointer=" + isSinglePointer + " " + this);
+ }
+ // Snap back to the previous keyboard mode if the user cancels sliding input.
+ if (isSinglePointer) {
+ if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) {
+ toggleAlphabetAndSymbols();
+ } else if (mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE) {
+ toggleShiftInSymbols();
+ }
+ }
+ }
+
+ public boolean isInMomentarySwitchState() {
+ return mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL
+ || mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE;
+ }
+
+ private static boolean isSpaceCharacter(int c) {
+ return c == Keyboard.CODE_SPACE || c == Keyboard.CODE_ENTER;
+ }
+
+ private boolean isLayoutSwitchBackCharacter(int c) {
+ if (TextUtils.isEmpty(mLayoutSwitchBackSymbols)) return false;
+ if (mLayoutSwitchBackSymbols.indexOf(c) >= 0) return true;
+ return false;
+ }
+
+ public void onCodeInput(int code, boolean isSinglePointer, boolean autoCaps) {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "onCodeInput: code=" + code + " isSinglePointer=" + isSinglePointer
+ + " autoCaps=" + autoCaps + " " + this);
+ }
+ 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 #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 (mIsAlphabetMode) {
+ mSwitchState = SWITCH_STATE_ALPHA;
+ } else {
+ mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
+ }
+ } else if (isSinglePointer) {
+ // Snap back to the previous keyboard mode if the user pressed the mode change key
+ // and slid to other key, then released the finger.
+ // If the user cancels the sliding input, snapping back to the previous keyboard
+ // mode is handled by {@link #onCancelInput}.
+ toggleAlphabetAndSymbols();
+ } 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.
+ 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 (isSinglePointer) {
+ // 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.
+ toggleShiftInSymbols();
+ 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 SWITCH_STATE_SYMBOL_BEGIN:
+ if (!isSpaceCharacter(code) && (Keyboard.isLetterCode(code)
+ || code == Keyboard.CODE_OUTPUT_TEXT)) {
+ mSwitchState = SWITCH_STATE_SYMBOL;
+ }
+ // Snap back to alpha keyboard mode immediately if user types a quote character.
+ if (isLayoutSwitchBackCharacter(code)) {
+ setAlphabetKeyboard();
+ }
+ break;
+ 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 or a quote character.
+ if (isSpaceCharacter(code) || isLayoutSwitchBackCharacter(code)) {
+ setAlphabetKeyboard();
+ }
+ break;
+ }
+
+ // If the code is a letter, update keyboard shift state.
+ if (Keyboard.isLetterCode(code)) {
+ onUpdateShiftStateInternal(autoCaps);
+ }
+ }
+
+ public void onToggleShift() {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "onToggleShift: " + this);
+ }
+ if (mIsAlphabetMode) {
+ setShifted(mKeyboardShiftState.isShiftedOrShiftLocked()
+ ? SwitchActions.UNSHIFT : SwitchActions.MANUAL_SHIFT);
+ } else {
+ toggleShiftInSymbols();
+ }
+ }
+
+ public void onToggleCapsLock() {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "onToggleCapsLock: " + this);
+ }
+ if (mIsAlphabetMode) {
+ if (mKeyboardShiftState.isShiftLocked()) {
+ setShiftLocked(false);
+ // Shift key is long pressed while caps lock state, we will toggle back to normal
+ // state. And mark as if shift key is released.
+ mShiftKeyState.onRelease();
+ } else {
+ setShiftLocked(true);
+ }
+ }
+ }
+
+ public void onToggleAlphabetAndSymbols() {
+ if (DEBUG_STATE) {
+ Log.d(TAG, "onToggleAlphabetAndSymbols: " + this);
+ }
+ toggleAlphabetAndSymbols();
+ }
+
+ private static String shiftModeToString(int shiftMode) {
+ switch (shiftMode) {
+ case SwitchActions.UNSHIFT: return "UNSHIFT";
+ case SwitchActions.MANUAL_SHIFT: return "MANUAL";
+ case SwitchActions.AUTOMATIC_SHIFT: return "AUTOMATIC";
+ default: return null;
+ }
+ }
+
+ private static String switchStateToString(int switchState) {
+ switch (switchState) {
+ case SWITCH_STATE_ALPHA: return "ALPHA";
+ case SWITCH_STATE_SYMBOL_BEGIN: return "SYMBOL-BEGIN";
+ case SWITCH_STATE_SYMBOL: return "SYMBOL";
+ case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: return "MOMENTARY-ALPHA-SYMBOL";
+ case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: return "MOMENTARY-SYMBOL-MORE";
+ case SWITCH_STATE_CHORDING_ALPHA: return "CHORDING-ALPHA";
+ case SWITCH_STATE_CHORDING_SYMBOL: return "CHORDING-SYMBOL";
+ default: return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "[keyboard=" + mKeyboardShiftState
+ + " shift=" + mShiftKeyState
+ + " symbol=" + mSymbolKeyState
+ + " switch=" + switchStateToString(mSwitchState) + "]";
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java b/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java
index dae73c4e4..f95c91636 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java
@@ -18,11 +18,9 @@ package com.android.inputmethod.keyboard.internal;
import android.util.Log;
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
-
-public class ModifierKeyState {
+/* package */ class ModifierKeyState {
protected static final String TAG = "ModifierKeyState";
- protected static final boolean DEBUG = KeyboardSwitcher.DEBUG_STATE;
+ protected static final boolean DEBUG = false;
protected static final int RELEASING = 0;
protected static final int PRESSING = 1;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java
index a490b0ad6..93be31ed9 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java
@@ -148,12 +148,12 @@ public class MoreKeySpecParser {
return code;
}
if (indexOfLabelEnd(moreKeySpec, 0) > 0)
- return Keyboard.CODE_DUMMY;
+ return Keyboard.CODE_UNSPECIFIED;
final String label = getLabel(moreKeySpec);
// Code is automatically generated for one letter label.
if (label != null && label.length() == 1)
return label.charAt(0);
- return Keyboard.CODE_DUMMY;
+ return Keyboard.CODE_UNSPECIFIED;
}
public static int getIconId(String moreKeySpec) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
index 08e7a7a4e..d9181f786 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.keyboard.internal;
import com.android.inputmethod.keyboard.PointerTracker;
+import java.util.Iterator;
import java.util.LinkedList;
public class PointerTrackerQueue {
@@ -27,18 +28,23 @@ public class PointerTrackerQueue {
mQueue.add(tracker);
}
+ public synchronized void remove(PointerTracker tracker) {
+ mQueue.remove(tracker);
+ }
+
public synchronized void releaseAllPointersOlderThan(PointerTracker tracker, long eventTime) {
- if (mQueue.lastIndexOf(tracker) < 0) {
+ if (!mQueue.contains(tracker)) {
return;
}
- final LinkedList<PointerTracker> queue = mQueue;
- int oldestPos = 0;
- for (PointerTracker t = queue.get(oldestPos); t != tracker; t = queue.get(oldestPos)) {
- if (t.isModifier()) {
- oldestPos++;
- } else {
+ final Iterator<PointerTracker> it = mQueue.iterator();
+ while (it.hasNext()) {
+ final PointerTracker t = it.next();
+ if (t == tracker) {
+ break;
+ }
+ if (!t.isModifier()) {
t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime);
- queue.remove(oldestPos);
+ it.remove();
}
}
}
@@ -48,22 +54,16 @@ public class PointerTrackerQueue {
}
public synchronized void releaseAllPointersExcept(PointerTracker tracker, long eventTime) {
- for (PointerTracker t : mQueue) {
- if (t == tracker) {
- continue;
+ final Iterator<PointerTracker> it = mQueue.iterator();
+ while (it.hasNext()) {
+ final PointerTracker t = it.next();
+ if (t != tracker) {
+ t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime);
+ it.remove();
}
- t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime);
- }
- mQueue.clear();
- if (tracker != null) {
- mQueue.add(tracker);
}
}
- public synchronized void remove(PointerTracker tracker) {
- mQueue.remove(tracker);
- }
-
public synchronized boolean isAnyInSlidingKeyInput() {
for (final PointerTracker tracker : mQueue) {
if (tracker.isInSlidingKeyInput()) {
@@ -75,13 +75,12 @@ public class PointerTrackerQueue {
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("[");
- for (PointerTracker tracker : mQueue) {
- if (sb.length() > 1)
+ final StringBuilder sb = new StringBuilder();
+ for (final PointerTracker tracker : mQueue) {
+ if (sb.length() > 0)
sb.append(" ");
- sb.append(String.format("%d", tracker.mPointerId));
+ sb.append(tracker.mPointerId);
}
- sb.append("]");
- return sb.toString();
+ return "[" + sb + "]";
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java b/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java
index 6617b917f..6f54b4f23 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java
@@ -18,7 +18,7 @@ package com.android.inputmethod.keyboard.internal;
import android.util.Log;
-public class ShiftKeyState extends ModifierKeyState {
+/* package */ class ShiftKeyState extends ModifierKeyState {
private static final int PRESSING_ON_SHIFTED = 3; // both temporary shifted & shift locked
private static final int IGNORING = 4;
diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java
index 485ec511f..e5eb15938 100644
--- a/java/src/com/android/inputmethod/latin/AutoCorrection.java
+++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java
@@ -98,7 +98,7 @@ public class AutoCorrection {
return whiteListedWord != null;
}
- private boolean hasAutoCorrectionForTypedWord(Map<String, Dictionary> dictionaries,
+ private static boolean hasAutoCorrectionForTypedWord(Map<String, Dictionary> dictionaries,
WordComposer wordComposer, ArrayList<CharSequence> suggestions, CharSequence typedWord,
int correctionMode) {
if (TextUtils.isEmpty(typedWord)) return false;
@@ -118,8 +118,9 @@ public class AutoCorrection {
final int autoCorrectionSuggestionScore = sortedScores[0];
// TODO: when the normalized score of the first suggestion is nearly equals to
// the normalized score of the second suggestion, behave less aggressive.
- mNormalizedScore = Utils.calcNormalizedScore(
- typedWord,autoCorrectionSuggestion, autoCorrectionSuggestionScore);
+ mNormalizedScore = BinaryDictionary.calcNormalizedScore(
+ typedWord.toString(), autoCorrectionSuggestion.toString(),
+ autoCorrectionSuggestionScore);
if (DBG) {
Log.d(TAG, "Normalized " + typedWord + "," + autoCorrectionSuggestion + ","
+ autoCorrectionSuggestionScore + ", " + mNormalizedScore
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index b9fd57434..3692ac179 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -46,7 +46,7 @@ public class BinaryDictionary extends Dictionary {
private static final int TYPED_LETTER_MULTIPLIER = 2;
private int mDicTypeId;
- private int mNativeDict;
+ private long mNativeDict;
private final int[] mInputCodes = new int[MAX_WORD_LENGTH * MAX_PROXIMITY_CHARS_SIZE];
private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS];
private final char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS];
@@ -107,17 +107,21 @@ public class BinaryDictionary extends Dictionary {
Utils.loadNativeLibrary();
}
- private native int openNative(String sourceDir, long dictOffset, long dictSize,
+ private native long openNative(String sourceDir, long dictOffset, long dictSize,
int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength,
int maxWords, int maxAlternatives);
- private native void closeNative(int dict);
- private native boolean isValidWordNative(int nativeData, char[] word, int wordLength);
- private native int getSuggestionsNative(int dict, int proximityInfo, int[] xCoordinates,
+ private native void closeNative(long dict);
+ private native boolean isValidWordNative(long dict, char[] word, int wordLength);
+ private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates,
int[] yCoordinates, int[] inputCodes, int codesSize, int flags, char[] outputChars,
int[] scores);
- private native int getBigramsNative(int dict, char[] prevWord, int prevWordLength,
+ private native int getBigramsNative(long dict, char[] prevWord, int prevWordLength,
int[] inputCodes, int inputCodesLength, char[] outputChars, int[] scores,
int maxWordLength, int maxBigrams, int maxAlternatives);
+ private static native double calcNormalizedScoreNative(
+ char[] before, int beforeLength, char[] after, int afterLength, int score);
+ private static native int editDistanceNative(
+ char[] before, int beforeLength, char[] after, int afterLength);
private final void loadDictionary(String path, long startOffset, long length) {
mNativeDict = openNative(path, startOffset, length,
@@ -211,6 +215,16 @@ public class BinaryDictionary extends Dictionary {
mFlags, outputChars, scores);
}
+ public static double calcNormalizedScore(String before, String after, int score) {
+ return calcNormalizedScoreNative(before.toCharArray(), before.length(),
+ after.toCharArray(), after.length(), score);
+ }
+
+ public static int editDistance(String before, String after) {
+ return editDistanceNative(
+ before.toCharArray(), before.length(), after.toCharArray(), after.length());
+ }
+
@Override
public boolean isValidWord(CharSequence word) {
if (word == null) return false;
diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
index 739153044..c19a5a718 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
@@ -18,6 +18,8 @@ package com.android.inputmethod.latin;
import com.android.inputmethod.keyboard.ProximityInfo;
+import android.util.Log;
+
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -27,7 +29,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
* Class for a collection of dictionaries that behave like one dictionary.
*/
public class DictionaryCollection extends Dictionary {
-
+ private final String TAG = DictionaryCollection.class.getSimpleName();
protected final List<Dictionary> mDictionaries;
public DictionaryCollection() {
@@ -75,7 +77,21 @@ public class DictionaryCollection extends Dictionary {
dict.close();
}
- public void addDictionary(Dictionary newDict) {
- if (null != newDict) mDictionaries.add(newDict);
+ // Warning: this is not thread-safe. Take necessary precaution when calling.
+ public void addDictionary(final Dictionary newDict) {
+ if (null == newDict) return;
+ if (mDictionaries.contains(newDict)) {
+ Log.w(TAG, "This collection already contains this dictionary: " + newDict);
+ }
+ mDictionaries.add(newDict);
+ }
+
+ // Warning: this is not thread-safe. Take necessary precaution when calling.
+ public void removeDictionary(final Dictionary dict) {
+ if (mDictionaries.contains(dict)) {
+ mDictionaries.remove(dict);
+ } else {
+ Log.w(TAG, "This collection does not contain this dictionary: " + dict);
+ }
}
}
diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
index cad69bb0e..7eec8e2ca 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
@@ -51,6 +51,7 @@ public class ExpandableDictionary extends Dictionary {
private Object mUpdatingLock = new Object();
private static class Node {
+ Node() {}
char mCode;
int mFrequency;
boolean mTerminal;
@@ -547,6 +548,7 @@ public class ExpandableDictionary extends Dictionary {
}
private class LoadDictionaryTask extends Thread {
+ LoadDictionaryTask() {}
@Override
public void run() {
loadDictionaryAsync();
diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java
new file mode 100644
index 000000000..f5cf953c4
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/InputAttributes.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.text.InputType;
+import android.util.Log;
+import android.view.inputmethod.EditorInfo;
+
+import com.android.inputmethod.compat.InputTypeCompatUtils;
+
+/**
+ * Class to hold attributes of the input field.
+ */
+public class InputAttributes {
+ private final String TAG = InputAttributes.class.getSimpleName();
+
+ final public boolean mInsertSpaceOnPickSuggestionManually;
+ final public boolean mInputTypeNoAutoCorrect;
+ final public boolean mIsSettingsSuggestionStripOn;
+ final public boolean mApplicationSpecifiedCompletionOn;
+
+ public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode) {
+ final int inputType = null != editorInfo ? editorInfo.inputType : 0;
+ final int inputClass = inputType & InputType.TYPE_MASK_CLASS;
+ if (inputClass != InputType.TYPE_CLASS_TEXT) {
+ // If we are not looking at a TYPE_CLASS_TEXT field, the following strange
+ // cases may arise, so we do a couple sanity checks for them. If it's a
+ // TYPE_CLASS_TEXT field, these special cases cannot happen, by construction
+ // of the flags.
+ if (null == editorInfo) {
+ Log.w(TAG, "No editor info for this field. Bug?");
+ } else if (InputType.TYPE_NULL == inputType) {
+ // TODO: We should honor TYPE_NULL specification.
+ Log.i(TAG, "InputType.TYPE_NULL is specified");
+ } else if (inputClass == 0) {
+ // TODO: is this check still necessary?
+ Log.w(TAG, String.format("Unexpected input class: inputType=0x%08x"
+ + " imeOptions=0x%08x",
+ inputType, editorInfo.imeOptions));
+ }
+ mInsertSpaceOnPickSuggestionManually = false;
+ mIsSettingsSuggestionStripOn = false;
+ mInputTypeNoAutoCorrect = false;
+ mApplicationSpecifiedCompletionOn = false;
+ } else {
+ final int variation = inputType & InputType.TYPE_MASK_VARIATION;
+ final boolean flagNoSuggestions =
+ 0 != (inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
+ final boolean flagMultiLine =
+ 0 != (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE);
+ final boolean flagAutoCorrect =
+ 0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
+ final boolean flagAutoComplete =
+ 0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
+
+ // Make sure that passwords are not displayed in {@link SuggestionsView}.
+ if (InputTypeCompatUtils.isPasswordInputType(inputType)
+ || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)
+ || InputTypeCompatUtils.isEmailVariation(variation)
+ || InputType.TYPE_TEXT_VARIATION_URI == variation
+ || InputType.TYPE_TEXT_VARIATION_FILTER == variation
+ || flagNoSuggestions
+ || flagAutoComplete) {
+ mIsSettingsSuggestionStripOn = false;
+ } else {
+ mIsSettingsSuggestionStripOn = true;
+ }
+
+ if (InputTypeCompatUtils.isEmailVariation(variation)
+ || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) {
+ // The point in turning this off is that we don't want to insert a space after
+ // a name when filling a form: we can't delete trailing spaces when changing fields
+ mInsertSpaceOnPickSuggestionManually = false;
+ } else {
+ mInsertSpaceOnPickSuggestionManually = true;
+ }
+
+ // If it's a browser edit field and auto correct is not ON explicitly, then
+ // disable auto correction, but keep suggestions on.
+ // If NO_SUGGESTIONS is set, don't do prediction.
+ // If it's not multiline and the autoCorrect flag is not set, then don't correct
+ if ((variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT
+ && !flagAutoCorrect)
+ || flagNoSuggestions
+ || (!flagAutoCorrect && !flagMultiLine)) {
+ mInputTypeNoAutoCorrect = true;
+ } else {
+ mInputTypeNoAutoCorrect = false;
+ }
+
+ mApplicationSpecifiedCompletionOn = flagAutoComplete && isFullscreenMode;
+ }
+ }
+
+ // Pretty print
+ @Override
+ public String toString() {
+ return "\n mInsertSpaceOnPickSuggestionManually = " + mInsertSpaceOnPickSuggestionManually
+ + "\n mInputTypeNoAutoCorrect = " + mInputTypeNoAutoCorrect
+ + "\n mIsSettingsSuggestionStripOn = " + mIsSettingsSuggestionStripOn
+ + "\n mApplicationSpecifiedCompletionOn = " + mApplicationSpecifiedCompletionOn;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 9c321bcb9..59de798d8 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -62,10 +62,11 @@ import com.android.inputmethod.deprecated.VoiceProxy;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardActionListener;
+import com.android.inputmethod.keyboard.KeyboardId;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.KeyboardView;
-import com.android.inputmethod.keyboard.LatinKeyboard;
import com.android.inputmethod.keyboard.LatinKeyboardView;
+import com.android.inputmethod.latin.suggestions.SuggestionsView;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -77,7 +78,6 @@ import java.util.Locale;
public class LatinIME extends InputMethodServiceCompatWrapper implements KeyboardActionListener,
SuggestionsView.Listener {
private static final String TAG = LatinIME.class.getSimpleName();
- private static final boolean PERF_DEBUG = false;
private static final boolean TRACE = false;
private static boolean DEBUG;
@@ -143,6 +143,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
*/
private static final String SCHEME_PACKAGE = "package";
+ // TODO: migrate this to SettingsValues
private int mSuggestionVisibility;
private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE
= R.string.prefs_suggestion_visibility_show_value;
@@ -157,7 +158,24 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
SUGGESTION_VISIBILILTY_HIDE_VALUE
};
- private Settings.Values mSettingsValues;
+ // Magic space: a space that should disappear on space/apostrophe insertion, move after the
+ // punctuation on punctuation insertion, and become a real space on alpha char insertion.
+ // Weak space: a space that should be swapped only by suggestion strip punctuation.
+ // Double space: the state where the user pressed space twice quickly, which LatinIME
+ // resolved as period-space. Undoing this converts the period to a space.
+ // Swap punctuation: the state where a (weak or magic) space and a punctuation from the
+ // suggestion strip have just been swapped. Undoing this swaps them back.
+ private static final int SPACE_STATE_NONE = 0;
+ private static final int SPACE_STATE_DOUBLE = 1;
+ private static final int SPACE_STATE_SWAP_PUNCTUATION = 2;
+ private static final int SPACE_STATE_MAGIC = 3;
+ private static final int SPACE_STATE_WEAK = 4;
+
+ // Current space state of the input method. This can be any of the above constants.
+ private int mSpaceState;
+
+ private SettingsValues mSettingsValues;
+ private InputAttributes mInputAttributes;
private View mExtractArea;
private View mKeyPreviewBackingView;
@@ -169,7 +187,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private InputMethodManagerCompatWrapper mImm;
private Resources mResources;
private SharedPreferences mPrefs;
- private String mInputMethodId;
private KeyboardSwitcher mKeyboardSwitcher;
private SubtypeSwitcher mSubtypeSwitcher;
private VoiceProxy mVoiceProxy;
@@ -177,28 +194,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private UserDictionary mUserDictionary;
private UserBigramDictionary mUserBigramDictionary;
private UserUnigramDictionary mUserUnigramDictionary;
- private boolean mIsUserDictionaryAvaliable;
-
- // TODO: Create an inner class to group options and pseudo-options to improve readability.
- // These variables are initialized according to the {@link EditorInfo#inputType}.
- private boolean mInsertSpaceOnPickSuggestionManually;
- private boolean mInputTypeNoAutoCorrect;
- private boolean mIsSettingsSuggestionStripOn;
- private boolean mApplicationSpecifiedCompletionOn;
+ private boolean mIsUserDictionaryAvailable;
- private final StringBuilder mComposingStringBuilder = new StringBuilder();
private WordComposer mWordComposer = new WordComposer();
- private CharSequence mBestWord;
- private boolean mHasUncommittedTypedChars;
- // Magic space: a space that should disappear on space/apostrophe insertion, move after the
- // punctuation on punctuation insertion, and become a real space on alpha char insertion.
- private boolean mJustAddedMagicSpace; // This indicates whether the last char is a magic space.
- // This indicates whether the last keypress resulted in processing of double space replacement
- // with period-space.
- private boolean mJustReplacedDoubleSpace;
private int mCorrectionMode;
- private int mCommittedLength;
// Keep track of the last selection range to decide if we need to show word alternatives
private int mLastSelectionStart;
private int mLastSelectionEnd;
@@ -210,11 +210,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private long mLastKeyTime;
private AudioManager mAudioManager;
- private float mFxVolume = -1.0f; // default volume
private boolean mSilentModeOn; // System-wide current configuration
private VibratorCompatWrapper mVibrator;
- private long mKeypressVibrationDuration = -1;
// TODO: Move this flag to VoiceProxy
private boolean mConfigurationChanging;
@@ -241,9 +239,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 3;
private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 4;
private static final int MSG_SPACE_TYPED = 5;
- private static final int MSG_KEY_TYPED = 6;
- private static final int MSG_SET_BIGRAM_PREDICTIONS = 7;
- private static final int MSG_PENDING_IMS_CALLBACK = 8;
+ private static final int MSG_SET_BIGRAM_PREDICTIONS = 6;
+ private static final int MSG_PENDING_IMS_CALLBACK = 7;
private int mDelayBeforeFadeoutLanguageOnSpacebar;
private int mDelayUpdateSuggestions;
@@ -251,7 +248,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private int mDurationOfFadeoutLanguageOnSpacebar;
private float mFinalFadeoutFactorOfLanguageOnSpacebar;
private long mDoubleSpacesTurnIntoPeriodTimeout;
- private long mIgnoreSpecialKeyTimeout;
public UIHandler(LatinIME outerInstance) {
super(outerInstance);
@@ -271,8 +267,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
R.integer.config_final_fadeout_percentage_of_language_on_spacebar) / 100.0f;
mDoubleSpacesTurnIntoPeriodTimeout = res.getInteger(
R.integer.config_double_spaces_turn_into_period_timeout);
- mIgnoreSpecialKeyTimeout = res.getInteger(
- R.integer.config_ignore_special_key_timeout);
}
@Override
@@ -295,19 +289,15 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|| (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked()));
break;
case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR:
- if (inputView != null) {
- inputView.setSpacebarTextFadeFactor(
- (1.0f + mFinalFadeoutFactorOfLanguageOnSpacebar) / 2,
- (LatinKeyboard)msg.obj);
- }
+ setSpacebarTextFadeFactor(inputView,
+ (1.0f + mFinalFadeoutFactorOfLanguageOnSpacebar) / 2,
+ (Keyboard)msg.obj);
sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj),
mDurationOfFadeoutLanguageOnSpacebar);
break;
case MSG_DISMISS_LANGUAGE_ON_SPACEBAR:
- if (inputView != null) {
- inputView.setSpacebarTextFadeFactor(mFinalFadeoutFactorOfLanguageOnSpacebar,
- (LatinKeyboard)msg.obj);
- }
+ setSpacebarTextFadeFactor(inputView, mFinalFadeoutFactorOfLanguageOnSpacebar,
+ (Keyboard)msg.obj);
break;
}
}
@@ -347,21 +337,32 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
sendMessage(obtainMessage(MSG_VOICE_RESULTS));
}
+ private static void setSpacebarTextFadeFactor(LatinKeyboardView inputView,
+ float fadeFactor, Keyboard oldKeyboard) {
+ if (inputView == null) return;
+ final Keyboard keyboard = inputView.getKeyboard();
+ if (keyboard == oldKeyboard) {
+ inputView.updateSpacebar(fadeFactor,
+ SubtypeSwitcher.getInstance().needsToDisplayLanguage(
+ keyboard.mId.mLocale));
+ }
+ }
+
public void startDisplayLanguageOnSpacebar(boolean localeChanged) {
final LatinIME latinIme = getOuterInstance();
removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR);
removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR);
final LatinKeyboardView inputView = latinIme.mKeyboardSwitcher.getKeyboardView();
if (inputView != null) {
- final LatinKeyboard keyboard = latinIme.mKeyboardSwitcher.getLatinKeyboard();
+ final Keyboard keyboard = latinIme.mKeyboardSwitcher.getKeyboard();
// The language is always displayed when the delay is negative.
final boolean needsToDisplayLanguage = localeChanged
|| mDelayBeforeFadeoutLanguageOnSpacebar < 0;
// The language is never displayed when the delay is zero.
if (mDelayBeforeFadeoutLanguageOnSpacebar != 0) {
- inputView.setSpacebarTextFadeFactor(needsToDisplayLanguage ? 1.0f
- : mFinalFadeoutFactorOfLanguageOnSpacebar,
- keyboard);
+ setSpacebarTextFadeFactor(inputView,
+ needsToDisplayLanguage ? 1.0f : mFinalFadeoutFactorOfLanguageOnSpacebar,
+ keyboard);
}
// The fadeout animation will start when the delay is positive.
if (localeChanged && mDelayBeforeFadeoutLanguageOnSpacebar > 0) {
@@ -384,21 +385,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return hasMessages(MSG_SPACE_TYPED);
}
- public void startKeyTypedTimer() {
- removeMessages(MSG_KEY_TYPED);
- sendMessageDelayed(obtainMessage(MSG_KEY_TYPED), mIgnoreSpecialKeyTimeout);
- }
-
- public boolean isIgnoringSpecialKey() {
- return hasMessages(MSG_KEY_TYPED);
- }
-
// Working variables for the following methods.
private boolean mIsOrientationChanging;
private boolean mPendingSuccesiveImsCallback;
private boolean mHasPendingStartInput;
private boolean mHasPendingFinishInputView;
private boolean mHasPendingFinishInput;
+ private EditorInfo mAppliedEditorInfo;
public void startOrientationChanging() {
removeMessages(MSG_PENDING_IMS_CALLBACK);
@@ -416,18 +409,18 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mHasPendingStartInput = false;
}
- private void executePendingImsCallback(LatinIME latinIme, EditorInfo attribute,
+ private void executePendingImsCallback(LatinIME latinIme, EditorInfo editorInfo,
boolean restarting) {
if (mHasPendingFinishInputView)
latinIme.onFinishInputViewInternal(mHasPendingFinishInput);
if (mHasPendingFinishInput)
latinIme.onFinishInputInternal();
if (mHasPendingStartInput)
- latinIme.onStartInputInternal(attribute, restarting);
+ latinIme.onStartInputInternal(editorInfo, restarting);
resetPendingImsCallback();
}
- public void onStartInput(EditorInfo attribute, boolean restarting) {
+ public void onStartInput(EditorInfo editorInfo, boolean restarting) {
if (hasMessages(MSG_PENDING_IMS_CALLBACK)) {
// Typically this is the second onStartInput after orientation changed.
mHasPendingStartInput = true;
@@ -438,27 +431,29 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mPendingSuccesiveImsCallback = true;
}
final LatinIME latinIme = getOuterInstance();
- executePendingImsCallback(latinIme, attribute, restarting);
- latinIme.onStartInputInternal(attribute, restarting);
+ executePendingImsCallback(latinIme, editorInfo, restarting);
+ latinIme.onStartInputInternal(editorInfo, restarting);
}
}
- public void onStartInputView(EditorInfo attribute, boolean restarting) {
- if (hasMessages(MSG_PENDING_IMS_CALLBACK)) {
- // Typically this is the second onStartInputView after orientation changed.
- resetPendingImsCallback();
- } else {
- if (mPendingSuccesiveImsCallback) {
- // This is the first onStartInputView after orientation changed.
- mPendingSuccesiveImsCallback = false;
- resetPendingImsCallback();
- sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK),
- PENDING_IMS_CALLBACK_DURATION);
- }
- final LatinIME latinIme = getOuterInstance();
- executePendingImsCallback(latinIme, attribute, restarting);
- latinIme.onStartInputViewInternal(attribute, restarting);
- }
+ public void onStartInputView(EditorInfo editorInfo, boolean restarting) {
+ if (hasMessages(MSG_PENDING_IMS_CALLBACK)
+ && KeyboardId.equivalentEditorInfoForKeyboard(editorInfo, mAppliedEditorInfo)) {
+ // Typically this is the second onStartInputView after orientation changed.
+ resetPendingImsCallback();
+ } else {
+ if (mPendingSuccesiveImsCallback) {
+ // This is the first onStartInputView after orientation changed.
+ mPendingSuccesiveImsCallback = false;
+ resetPendingImsCallback();
+ sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK),
+ PENDING_IMS_CALLBACK_DURATION);
+ }
+ final LatinIME latinIme = getOuterInstance();
+ executePendingImsCallback(latinIme, editorInfo, restarting);
+ latinIme.onStartInputViewInternal(editorInfo, restarting);
+ mAppliedEditorInfo = editorInfo;
+ }
}
public void onFinishInputView(boolean finishingInput) {
@@ -468,6 +463,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} else {
final LatinIME latinIme = getOuterInstance();
latinIme.onFinishInputViewInternal(finishingInput);
+ mAppliedEditorInfo = null;
}
}
@@ -492,12 +488,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
InputMethodManagerCompatWrapper.init(this);
SubtypeSwitcher.init(this);
KeyboardSwitcher.init(this, prefs);
- AccessibilityUtils.init(this, prefs);
+ AccessibilityUtils.init(this);
super.onCreate();
mImm = InputMethodManagerCompatWrapper.getInstance();
- mInputMethodId = Utils.getInputMethodId(mImm, getPackageName());
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
mVibrator = VibratorCompatWrapper.getInstance(this);
@@ -509,6 +504,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
loadSettings();
+ // TODO: remove the following when it's not needed by updateCorrectionMode() any more
+ mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */);
Utils.GCUtils.getInstance().reset();
boolean tryGC = true;
for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
@@ -546,10 +543,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
/* package */ void loadSettings() {
if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
if (null == mSubtypeSwitcher) mSubtypeSwitcher = SubtypeSwitcher.getInstance();
- mSettingsValues = new Settings.Values(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr());
+ mSettingsValues = new SettingsValues(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr());
resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
- updateSoundEffectVolume();
- updateKeypressVibrationDuration();
}
private void initSuggest() {
@@ -574,7 +569,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mUserDictionary = new UserDictionary(this, localeStr);
mSuggest.setUserDictionary(mUserDictionary);
- mIsUserDictionaryAvaliable = mUserDictionary.isEnabled();
+ mIsUserDictionaryAvailable = mUserDictionary.isEnabled();
resetContactsDictionary(oldContactsDictionary);
@@ -695,13 +690,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
@Override
- public void onStartInput(EditorInfo attribute, boolean restarting) {
- mHandler.onStartInput(attribute, restarting);
+ public void onStartInput(EditorInfo editorInfo, boolean restarting) {
+ mHandler.onStartInput(editorInfo, restarting);
}
@Override
- public void onStartInputView(EditorInfo attribute, boolean restarting) {
- mHandler.onStartInputView(attribute, restarting);
+ public void onStartInputView(EditorInfo editorInfo, boolean restarting) {
+ mHandler.onStartInputView(editorInfo, restarting);
}
@Override
@@ -714,20 +709,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mHandler.onFinishInput();
}
- private void onStartInputInternal(EditorInfo attribute, boolean restarting) {
- super.onStartInput(attribute, restarting);
+ private void onStartInputInternal(EditorInfo editorInfo, boolean restarting) {
+ super.onStartInput(editorInfo, restarting);
}
- private void onStartInputViewInternal(EditorInfo attribute, boolean restarting) {
- super.onStartInputView(attribute, restarting);
+ private void onStartInputViewInternal(EditorInfo editorInfo, boolean restarting) {
+ super.onStartInputView(editorInfo, restarting);
final KeyboardSwitcher switcher = mKeyboardSwitcher;
LatinKeyboardView inputView = switcher.getKeyboardView();
if (DEBUG) {
- Log.d(TAG, "onStartInputView: attribute:" + ((attribute == null) ? "none"
+ Log.d(TAG, "onStartInputView: editorInfo:" + ((editorInfo == null) ? "none"
: String.format("inputType=0x%08x imeOptions=0x%08x",
- attribute.inputType, attribute.imeOptions)));
+ editorInfo.inputType, editorInfo.imeOptions)));
}
+ LatinImeLogger.onStartInputView(editorInfo);
// In landscape mode, this method gets called without the input view being created.
if (inputView == null) {
return;
@@ -736,47 +732,44 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Forward this event to the accessibility utilities, if enabled.
final AccessibilityUtils accessUtils = AccessibilityUtils.getInstance();
if (accessUtils.isTouchExplorationEnabled()) {
- accessUtils.onStartInputViewInternal(attribute, restarting);
+ accessUtils.onStartInputViewInternal(editorInfo, restarting);
}
mSubtypeSwitcher.updateParametersOnStartInputView();
- TextEntryState.reset();
-
// Most such things we decide below in initializeInputAttributesAndGetMode, but we need to
// know now whether this is a password text field, because we need to know now whether we
// want to enable the voice button.
final VoiceProxy voiceIme = mVoiceProxy;
- final int inputType = (attribute != null) ? attribute.inputType : 0;
+ final int inputType = (editorInfo != null) ? editorInfo.inputType : 0;
voiceIme.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(inputType)
|| InputTypeCompatUtils.isVisiblePasswordInputType(inputType));
// The EditorInfo might have a flag that affects fullscreen mode.
// Note: This call should be done by InputMethodService?
updateFullscreenMode();
- initializeInputAttributes(attribute);
+ mInputAttributes = new InputAttributes(editorInfo, isFullscreenMode());
+ mApplicationSpecifiedCompletions = null;
inputView.closing();
mEnteredText = null;
- mComposingStringBuilder.setLength(0);
- mHasUncommittedTypedChars = false;
+ mWordComposer.reset();
mDeleteCount = 0;
- mJustAddedMagicSpace = false;
- mJustReplacedDoubleSpace = false;
+ mSpaceState = SPACE_STATE_NONE;
loadSettings();
updateCorrectionMode();
- updateSuggestionVisibility(mPrefs, mResources);
+ updateSuggestionVisibility(mResources);
if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) {
mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold);
}
- mVoiceProxy.loadSettings(attribute, mPrefs);
+ mVoiceProxy.loadSettings(editorInfo, mPrefs);
// This will work only when the subtype is not supported.
LanguageSwitcherProxy.loadSettings();
if (mSubtypeSwitcher.isKeyboardMode()) {
- switcher.loadKeyboard(attribute, mSettingsValues);
+ switcher.loadKeyboard(editorInfo, mSettingsValues);
}
if (mSuggestionsView != null)
@@ -785,6 +778,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
isSuggestionsStripVisible(), /* needsInputViewShown */ false);
// Delay updating suggestions because keyboard input view may not be shown at this point.
mHandler.postUpdateSuggestions();
+ mHandler.cancelDoubleSpacesTimer();
inputView.setKeyPreviewPopupEnabled(mSettingsValues.mKeyPreviewPopupOn,
mSettingsValues.mKeyPreviewPopupDismissDelay);
@@ -795,73 +789,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
}
- private void initializeInputAttributes(EditorInfo attribute) {
- if (attribute == null)
- return;
- final int inputType = attribute.inputType;
- if (inputType == InputType.TYPE_NULL) {
- // TODO: We should honor TYPE_NULL specification.
- Log.i(TAG, "InputType.TYPE_NULL is specified");
- }
- final int inputClass = inputType & InputType.TYPE_MASK_CLASS;
- final int variation = inputType & InputType.TYPE_MASK_VARIATION;
- if (inputClass == 0) {
- Log.w(TAG, String.format("Unexpected input class: inputType=0x%08x imeOptions=0x%08x",
- inputType, attribute.imeOptions));
- }
-
- mInsertSpaceOnPickSuggestionManually = false;
- mInputTypeNoAutoCorrect = false;
- mIsSettingsSuggestionStripOn = false;
- mApplicationSpecifiedCompletionOn = false;
- mApplicationSpecifiedCompletions = null;
-
- if (inputClass == InputType.TYPE_CLASS_TEXT) {
- mIsSettingsSuggestionStripOn = true;
- // Make sure that passwords are not displayed in {@link SuggestionsView}.
- if (InputTypeCompatUtils.isPasswordInputType(inputType)
- || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)) {
- mIsSettingsSuggestionStripOn = false;
- }
- if (InputTypeCompatUtils.isEmailVariation(variation)
- || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) {
- // The point in turning this off is that we don't want to insert a space after
- // a name when filling a form: we can't delete trailing spaces when changing fields
- mInsertSpaceOnPickSuggestionManually = false;
- } else {
- mInsertSpaceOnPickSuggestionManually = true;
- }
- if (InputTypeCompatUtils.isEmailVariation(variation)) {
- mIsSettingsSuggestionStripOn = false;
- } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) {
- mIsSettingsSuggestionStripOn = false;
- } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) {
- mIsSettingsSuggestionStripOn = false;
- } else if (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) {
- // If it's a browser edit field and auto correct is not ON explicitly, then
- // disable auto correction, but keep suggestions on.
- if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) {
- mInputTypeNoAutoCorrect = true;
- }
- }
-
- // If NO_SUGGESTIONS is set, don't do prediction.
- if ((inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) {
- mIsSettingsSuggestionStripOn = false;
- mInputTypeNoAutoCorrect = true;
- }
- // If it's not multiline and the autoCorrect flag is not set, then don't correct
- if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0
- && (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) {
- mInputTypeNoAutoCorrect = true;
- }
- if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
- mIsSettingsSuggestionStripOn = false;
- mApplicationSpecifiedCompletionOn = isFullscreenMode();
- }
- }
- }
-
@Override
public void onWindowHidden() {
super.onWindowHidden();
@@ -923,12 +850,22 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|| newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart;
final boolean candidatesCleared = candidatesStart == -1 && candidatesEnd == -1;
if (!mExpectingUpdateSelection) {
- if (((mComposingStringBuilder.length() > 0 && mHasUncommittedTypedChars)
+ // TAKE CARE: there is a race condition when we enter this test even when the user
+ // did not explicitly move the cursor. This happens when typing fast, where two keys
+ // turn this flag on in succession and both onUpdateSelection() calls arrive after
+ // the second one - the first call successfully avoids this test, but the second one
+ // enters. For the moment we rely on candidatesCleared to further reduce the impact.
+ if (SPACE_STATE_WEAK == mSpaceState) {
+ // Test for no WEAK_SPACE action because there is a race condition that may end up
+ // in coming here on a normal key press. We set this to NONE because after
+ // a cursor move, we don't want the suggestion strip to swap the space with the
+ // newly inserted punctuation.
+ mSpaceState = SPACE_STATE_NONE;
+ }
+ if (((mWordComposer.isComposingWord())
|| mVoiceProxy.isVoiceInputHighlighted())
&& (selectionChanged || candidatesCleared)) {
- mComposingStringBuilder.setLength(0);
- mHasUncommittedTypedChars = false;
- TextEntryState.reset();
+ mWordComposer.reset();
updateSuggestions();
final InputConnection ic = getCurrentInputConnection();
if (ic != null) {
@@ -936,26 +873,23 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
mComposingStateManager.onFinishComposingText();
mVoiceProxy.setVoiceInputHighlighted(false);
- } else if (!mHasUncommittedTypedChars) {
- TextEntryState.reset();
+ } else if (!mWordComposer.isComposingWord()) {
+ mWordComposer.reset();
updateSuggestions();
}
- mJustAddedMagicSpace = false; // The user moved the cursor.
- mJustReplacedDoubleSpace = false;
}
mExpectingUpdateSelection = false;
mHandler.postUpdateShiftKeyState();
+ // TODO: Decide to call restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() or not
+ // here. It would probably be too expensive to call directly here but we may want to post a
+ // message to delay it. The point would be to unify behavior between backspace to the
+ // end of a word and manually put the pointer at the end of the word.
// Make a note of the cursor position
mLastSelectionStart = newSelStart;
mLastSelectionEnd = newSelEnd;
}
- public void setLastSelection(int start, int end) {
- mLastSelectionStart = start;
- mLastSelectionEnd = end;
- }
-
/**
* This is called when the user has clicked on the extracted text view,
* when running in fullscreen mode. The default implementation hides
@@ -1011,7 +945,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
}
- if (mApplicationSpecifiedCompletionOn) {
+ if (mInputAttributes.mApplicationSpecifiedCompletionOn) {
mApplicationSpecifiedCompletions = applicationSpecifiedCompletions;
if (applicationSpecifiedCompletions == null) {
clearSuggestions();
@@ -1024,7 +958,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
.setHasMinimalSuggestion(false);
// When in fullscreen mode, show completions generated by the application
setSuggestions(builder.build());
- mBestWord = null;
+ mWordComposer.deleteAutoCorrection();
setSuggestionStripShown(true);
}
}
@@ -1085,8 +1019,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override
public boolean onEvaluateFullscreenMode() {
- return super.onEvaluateFullscreenMode()
- && mResources.getBoolean(R.bool.config_use_fullscreen_mode);
+ return super.onEvaluateFullscreenMode() && mSettingsValues.mUseFullScreenMode;
}
@Override
@@ -1142,15 +1075,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
public void commitTyped(final InputConnection ic) {
- if (!mHasUncommittedTypedChars) return;
- mHasUncommittedTypedChars = false;
- if (mComposingStringBuilder.length() > 0) {
+ if (!mWordComposer.isComposingWord()) return;
+ final CharSequence typedWord = mWordComposer.getTypedWord();
+ mWordComposer.onCommitWord(WordComposer.COMMIT_TYPE_USER_TYPED_WORD);
+ if (typedWord.length() > 0) {
if (ic != null) {
- ic.commitText(mComposingStringBuilder, 1);
+ ic.commitText(typedWord, 1);
}
- mCommittedLength = mComposingStringBuilder.length();
- TextEntryState.acceptedTyped(mComposingStringBuilder);
- addToUserUnigramAndBigramDictionaries(mComposingStringBuilder,
+ addToUserUnigramAndBigramDictionaries(typedWord,
UserUnigramDictionary.FREQUENCY_FOR_TYPED);
}
updateSuggestions();
@@ -1166,25 +1098,22 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return false;
}
- private void swapSwapperAndSpace() {
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
+ // "ic" may be null
+ private void swapSwapperAndSpaceWhileInBatchEdit(final InputConnection ic) {
+ if (null == ic) return;
CharSequence lastTwo = ic.getTextBeforeCursor(2, 0);
// It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called.
if (lastTwo != null && lastTwo.length() == 2
&& lastTwo.charAt(0) == Keyboard.CODE_SPACE) {
- ic.beginBatchEdit();
ic.deleteSurroundingText(2, 0);
ic.commitText(lastTwo.charAt(1) + " ", 1);
- ic.endBatchEdit();
mKeyboardSwitcher.updateShiftState();
}
}
- private void maybeDoubleSpace() {
- if (mCorrectionMode == Suggest.CORRECTION_NONE) return;
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
+ private boolean maybeDoubleSpaceWhileInBatchEdit(final InputConnection ic) {
+ if (mCorrectionMode == Suggest.CORRECTION_NONE) return false;
+ if (ic == null) return false;
final CharSequence lastThree = ic.getTextBeforeCursor(3, 0);
if (lastThree != null && lastThree.length() == 3
&& Utils.canBeFollowedByPeriod(lastThree.charAt(0))
@@ -1192,22 +1121,19 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
&& lastThree.charAt(2) == Keyboard.CODE_SPACE
&& mHandler.isAcceptingDoubleSpaces()) {
mHandler.cancelDoubleSpacesTimer();
- ic.beginBatchEdit();
ic.deleteSurroundingText(2, 0);
ic.commitText(". ", 1);
- ic.endBatchEdit();
mKeyboardSwitcher.updateShiftState();
- mJustReplacedDoubleSpace = true;
- } else {
- mHandler.startDoubleSpacesTimer();
+ return true;
}
+ return false;
}
- // "ic" must not null
- private void maybeRemovePreviousPeriod(final InputConnection ic, CharSequence text) {
+ // "ic" must not be null
+ private static void maybeRemovePreviousPeriod(final InputConnection ic, CharSequence text) {
// When the text's first character is '.', remove the previous period
// if there is one.
- CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
+ final CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
if (lastOne != null && lastOne.length() == 1
&& lastOne.charAt(0) == Keyboard.CODE_PERIOD
&& text.charAt(0) == Keyboard.CODE_PERIOD) {
@@ -1215,11 +1141,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
- private void removeTrailingSpace() {
- final InputConnection ic = getCurrentInputConnection();
+ // "ic" may be null
+ private static void removeTrailingSpaceWhileInBatchEdit(final InputConnection ic) {
if (ic == null) return;
-
- CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
+ final CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
if (lastOne != null && lastOne.length() == 1
&& lastOne.charAt(0) == Keyboard.CODE_SPACE) {
ic.deleteSurroundingText(1, 0);
@@ -1235,19 +1160,15 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return true;
}
- private boolean isAlphabet(int code) {
- if (Character.isLetter(code)) {
- return true;
- } else {
- return false;
- }
+ private static boolean isAlphabet(int code) {
+ return Character.isLetter(code);
}
private void onSettingsKeyPressed() {
if (isShowingOptionDialog()) return;
if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) {
showSubtypeSelectorAndSettings();
- } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm, false /* exclude aux subtypes */)) {
+ } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(false /* exclude aux subtypes */)) {
showOptionsMenu();
} else {
launchSettings();
@@ -1256,17 +1177,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Virtual codes representing custom requests. These are used in onCustomRequest() below.
public static final int CODE_SHOW_INPUT_METHOD_PICKER = 1;
+ public static final int CODE_HAPTIC_AND_AUDIO_FEEDBACK = 2;
@Override
public boolean onCustomRequest(int requestCode) {
if (isShowingOptionDialog()) return false;
switch (requestCode) {
case CODE_SHOW_INPUT_METHOD_PICKER:
- if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm, true /* include aux subtypes */)) {
+ if (Utils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) {
mImm.showInputMethodPicker();
return true;
}
return false;
+ case CODE_HAPTIC_AND_AUDIO_FEEDBACK:
+ hapticAndAudioFeedback(Keyboard.CODE_UNSPECIFIED);
+ return true;
}
return false;
}
@@ -1275,6 +1200,29 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return mOptionsDialog != null && mOptionsDialog.isShowing();
}
+ private void insertPunctuationFromSuggestionStrip(final InputConnection ic, final int code) {
+ final CharSequence beforeText = ic != null ? ic.getTextBeforeCursor(1, 0) : null;
+ final int toLeft = TextUtils.isEmpty(beforeText) ? 0 : beforeText.charAt(0);
+ final boolean shouldRegisterSwapPunctuation;
+ // If we have a space left of the cursor and it's a weak or a magic space, then we should
+ // swap it, and override the space state with SPACESTATE_SWAP_PUNCTUATION.
+ // To swap it, we fool handleSeparator to think the previous space state was a
+ // magic space.
+ if (Keyboard.CODE_SPACE == toLeft && mSpaceState == SPACE_STATE_WEAK
+ && mSettingsValues.isMagicSpaceSwapper(code)) {
+ mSpaceState = SPACE_STATE_MAGIC;
+ shouldRegisterSwapPunctuation = true;
+ } else {
+ shouldRegisterSwapPunctuation = false;
+ }
+ onCodeInput(code, new int[] { code },
+ KeyboardActionListener.NOT_A_TOUCH_COORDINATE,
+ KeyboardActionListener.NOT_A_TOUCH_COORDINATE);
+ if (shouldRegisterSwapPunctuation) {
+ mSpaceState = SPACE_STATE_SWAP_PUNCTUATION;
+ }
+ }
+
// Implementation of {@link KeyboardActionListener}.
@Override
public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) {
@@ -1285,12 +1233,22 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mLastKeyTime = when;
final KeyboardSwitcher switcher = mKeyboardSwitcher;
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
- final boolean lastStateOfJustReplacedDoubleSpace = mJustReplacedDoubleSpace;
- mJustReplacedDoubleSpace = false;
- boolean shouldStartKeyTypedTimer = true;
+ // The space state depends only on the last character pressed and its own previous
+ // state. Here, we revert the space state to neutral if the key is actually modifying
+ // the input contents (any non-shift key), which is what we should do for
+ // all inputs that do not result in a special state. Each character handling is then
+ // free to override the state as they see fit.
+ final int spaceState = mSpaceState;
+
+ // TODO: Consolidate the double space timer, mLastKeyTime, and the space state.
+ if (primaryCode != Keyboard.CODE_SPACE) {
+ mHandler.cancelDoubleSpacesTimer();
+ }
+
switch (primaryCode) {
case Keyboard.CODE_DELETE:
- handleBackspace(lastStateOfJustReplacedDoubleSpace);
+ mSpaceState = SPACE_STATE_NONE;
+ handleBackspace(spaceState);
mDeleteCount++;
mExpectingUpdateSelection = true;
LatinImeLogger.logOnDelete();
@@ -1300,39 +1258,22 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (!distinctMultiTouch) {
switcher.toggleShift();
}
- shouldStartKeyTypedTimer = false;
break;
case Keyboard.CODE_SWITCH_ALPHA_SYMBOL:
// Symbol key is handled in onPress() when device has distinct multi-touch panel.
if (!distinctMultiTouch) {
- switcher.changeKeyboardMode();
- }
- shouldStartKeyTypedTimer = false;
- break;
- case Keyboard.CODE_CANCEL:
- if (!isShowingOptionDialog()) {
- handleClose();
+ switcher.toggleAlphabetAndSymbols();
}
break;
case Keyboard.CODE_SETTINGS:
- if (!mHandler.isIgnoringSpecialKey()) {
- onSettingsKeyPressed();
- }
- shouldStartKeyTypedTimer = false;
+ onSettingsKeyPressed();
break;
case Keyboard.CODE_CAPSLOCK:
switcher.toggleCapsLock();
- //$FALL-THROUGH$
- case Keyboard.CODE_HAPTIC_AND_AUDIO_FEEDBACK_ONLY:
- // Dummy code for haptic and audio feedbacks.
- vibrate();
- playKeyClick(primaryCode);
+ hapticAndAudioFeedback(primaryCode);
break;
case Keyboard.CODE_SHORTCUT:
- if (!mHandler.isIgnoringSpecialKey()) {
- mSubtypeSwitcher.switchToShortcutIME();
- }
- shouldStartKeyTypedTimer = false;
+ mSubtypeSwitcher.switchToShortcutIME();
break;
case Keyboard.CODE_TAB:
handleTab();
@@ -1346,20 +1287,18 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// To sum it up: do not update mExpectingUpdateSelection here.
break;
default:
+ mSpaceState = SPACE_STATE_NONE;
if (mSettingsValues.isWordSeparator(primaryCode)) {
- handleSeparator(primaryCode, x, y);
+ handleSeparator(primaryCode, x, y, spaceState);
} else {
- handleCharacter(primaryCode, keyCodes, x, y);
+ handleCharacter(primaryCode, keyCodes, x, y, spaceState);
}
mExpectingUpdateSelection = true;
break;
}
- switcher.onKey(primaryCode);
+ switcher.onCodeInput(primaryCode);
// Reset after any single keystroke
mEnteredText = null;
- if (shouldStartKeyTypedTimer) {
- mHandler.startKeyTypedTimer();
- }
}
@Override
@@ -1373,10 +1312,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
ic.commitText(text, 1);
ic.endBatchEdit();
mKeyboardSwitcher.updateShiftState();
- mKeyboardSwitcher.onKey(Keyboard.CODE_DUMMY);
- mJustAddedMagicSpace = false;
+ mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT);
+ mSpaceState = SPACE_STATE_NONE;
mEnteredText = text;
- mHandler.startKeyTypedTimer();
+ mWordComposer.reset();
}
@Override
@@ -1385,60 +1324,70 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mKeyboardSwitcher.onCancelInput();
}
- private void handleBackspace(boolean justReplacedDoubleSpace) {
+ private void handleBackspace(final int spaceState) {
if (mVoiceProxy.logAndRevertVoiceInput()) return;
-
final InputConnection ic = getCurrentInputConnection();
if (ic == null) return;
ic.beginBatchEdit();
+ handleBackspaceWhileInBatchEdit(spaceState, ic);
+ ic.endBatchEdit();
+ }
+ // "ic" may not be null.
+ private void handleBackspaceWhileInBatchEdit(final int spaceState, final InputConnection ic) {
mVoiceProxy.handleBackspace();
- final boolean deleteChar = !mHasUncommittedTypedChars;
- if (mHasUncommittedTypedChars) {
- final int length = mComposingStringBuilder.length();
+ // In many cases, we may have to put the keyboard in auto-shift state again.
+ mHandler.postUpdateShiftKeyState();
+
+ if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) {
+ // Cancel multi-character input: remove the text we just entered.
+ // This is triggered on backspace after a key that inputs multiple characters,
+ // like the smiley key or the .com key.
+ ic.deleteSurroundingText(mEnteredText.length(), 0);
+ // If we have mEnteredText, then we know that mHasUncommittedTypedChars == false.
+ // In addition we know that spaceState is false, and that we should not be
+ // reverting any autocorrect at this point. So we can safely return.
+ return;
+ }
+
+ if (mWordComposer.isComposingWord()) {
+ final int length = mWordComposer.size();
if (length > 0) {
- mComposingStringBuilder.delete(length - 1, length);
mWordComposer.deleteLast();
- final CharSequence textWithUnderline =
- mComposingStateManager.isAutoCorrectionIndicatorOn()
- ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(
- this, mComposingStringBuilder)
- : mComposingStringBuilder;
- ic.setComposingText(textWithUnderline, 1);
- if (mComposingStringBuilder.length() == 0) {
- mHasUncommittedTypedChars = false;
- }
- if (1 == length) {
- // 1 == length means we are about to erase the last character of the word,
- // so we can show bigrams.
+ ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
+ // If we have deleted the last remaining character of a word, then we are not
+ // isComposingWord() any more.
+ if (!mWordComposer.isComposingWord()) {
+ // Not composing word any more, so we can show bigrams.
mHandler.postUpdateBigramPredictions();
} else {
- // length > 1, so we still have letters to deduce a suggestion from.
+ // Still composing a word, so we still have letters to deduce a suggestion from.
mHandler.postUpdateSuggestions();
}
} else {
ic.deleteSurroundingText(1, 0);
}
- }
- mHandler.postUpdateShiftKeyState();
-
- TextEntryState.backspace();
- if (TextEntryState.isUndoCommit()) {
- revertLastWord(ic);
- ic.endBatchEdit();
- return;
- }
- if (justReplacedDoubleSpace) {
- if (revertDoubleSpace(ic)) {
- ic.endBatchEdit();
+ } else {
+ if (mWordComposer.didAutoCorrectToAnotherWord()) {
+ Utils.Stats.onAutoCorrectionCancellation();
+ cancelAutoCorrect(ic);
return;
}
- }
- if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) {
- ic.deleteSurroundingText(mEnteredText.length(), 0);
- } else if (deleteChar) {
+ if (SPACE_STATE_DOUBLE == spaceState) {
+ if (revertDoubleSpace(ic)) {
+ // No need to reset mSpaceState, it has already be done (that's why we
+ // receive it as a parameter)
+ return;
+ }
+ } else if (SPACE_STATE_SWAP_PUNCTUATION == spaceState) {
+ if (revertSwapPunctuation(ic)) {
+ // Likewise
+ return;
+ }
+ }
+
if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) {
// Go back to the suggestion mode if the user canceled the
// "Touch again to save".
@@ -1447,15 +1396,15 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// different behavior only in the case of picking the first
// suggestion (typed word). It's intentional to have made this
// inconsistent with backspacing after selecting other suggestions.
- revertLastWord(ic);
+ restartSuggestionsOnManuallyPickedTypedWord(ic);
} else {
- sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
+ ic.deleteSurroundingText(1, 0);
if (mDeleteCount > DELETE_ACCELERATE_AT) {
- sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
+ ic.deleteSurroundingText(1, 0);
}
+ restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(ic);
}
}
- ic.endBatchEdit();
}
private void handleTab() {
@@ -1481,19 +1430,34 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
- private void handleCharacter(int primaryCode, int[] keyCodes, int x, int y) {
+ private void handleCharacter(final int primaryCode, final int[] keyCodes, final int x,
+ final int y, final int spaceState) {
mVoiceProxy.handleCharacter();
+ final InputConnection ic = getCurrentInputConnection();
+ if (null != ic) ic.beginBatchEdit();
+ // TODO: if ic is null, does it make any sense to call this?
+ handleCharacterWhileInBatchEdit(primaryCode, keyCodes, x, y, spaceState, ic);
+ if (null != ic) ic.endBatchEdit();
+ }
- if (mJustAddedMagicSpace && mSettingsValues.isMagicSpaceStripper(primaryCode)) {
- removeTrailingSpace();
+ // "ic" may be null without this crashing, but the behavior will be really strange
+ private void handleCharacterWhileInBatchEdit(final int primaryCode, final int[] keyCodes,
+ final int x, final int y, final int spaceState, final InputConnection ic) {
+ if (SPACE_STATE_MAGIC == spaceState
+ && mSettingsValues.isMagicSpaceStripper(primaryCode)) {
+ if (null != ic) removeTrailingSpaceWhileInBatchEdit(ic);
}
+ boolean isComposingWord = mWordComposer.isComposingWord();
int code = primaryCode;
if ((isAlphabet(code) || mSettingsValues.isSymbolExcludedFromWordSeparators(code))
&& isSuggestionsRequested() && !isCursorTouchingWord()) {
- if (!mHasUncommittedTypedChars) {
- mHasUncommittedTypedChars = true;
- mComposingStringBuilder.setLength(0);
+ if (!isComposingWord) {
+ // Reset entirely the composing state anyway, then start composing a new word unless
+ // the character is a single quote. The idea here is, single quote is not a
+ // separator and it should be treated as a normal character, except in the first
+ // position where it should not start composing a word.
+ isComposingWord = (Keyboard.CODE_SINGLE_QUOTE != code);
mWordComposer.reset();
clearSuggestions();
mComposingStateManager.onFinishComposingText();
@@ -1520,39 +1484,34 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
}
- if (mHasUncommittedTypedChars) {
- mComposingStringBuilder.append((char) code);
+ if (isComposingWord) {
mWordComposer.add(code, keyCodes, x, y);
- final InputConnection ic = getCurrentInputConnection();
if (ic != null) {
// If it's the first letter, make note of auto-caps state
if (mWordComposer.size() == 1) {
mWordComposer.setAutoCapitalized(getCurrentAutoCapsState());
mComposingStateManager.onStartComposingText();
}
- final CharSequence textWithUnderline =
- mComposingStateManager.isAutoCorrectionIndicatorOn()
- ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(
- this, mComposingStringBuilder)
- : mComposingStringBuilder;
- ic.setComposingText(textWithUnderline, 1);
+ ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
}
mHandler.postUpdateSuggestions();
} else {
sendKeyChar((char)code);
}
- if (mJustAddedMagicSpace && mSettingsValues.isMagicSpaceSwapper(primaryCode)) {
- swapSwapperAndSpace();
- } else {
- mJustAddedMagicSpace = false;
+ if (SPACE_STATE_MAGIC == spaceState
+ && mSettingsValues.isMagicSpaceSwapper(primaryCode)) {
+ if (null != ic) swapSwapperAndSpaceWhileInBatchEdit(ic);
}
- switcher.updateShiftState();
- if (LatinIME.PERF_DEBUG) measureCps();
- TextEntryState.typedCharacter((char) code, mSettingsValues.isWordSeparator(code), x, y);
+ if (mSettingsValues.isWordSeparator(code)) {
+ Utils.Stats.onSeparator((char)code, x, y);
+ } else {
+ Utils.Stats.onNonSeparator((char)code, x, y);
+ }
}
- private void handleSeparator(int primaryCode, int x, int y) {
+ private void handleSeparator(final int primaryCode, final int x, final int y,
+ final int spaceState) {
mVoiceProxy.handleSeparator();
mComposingStateManager.onFinishComposingText();
@@ -1562,69 +1521,83 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mHandler.postUpdateSuggestions();
}
- boolean pickedDefault = false;
// Handle separator
final InputConnection ic = getCurrentInputConnection();
if (ic != null) {
ic.beginBatchEdit();
}
- if (mHasUncommittedTypedChars) {
+ if (mWordComposer.isComposingWord()) {
// In certain languages where single quote is a separator, it's better
// not to auto correct, but accept the typed word. For instance,
// in Italian dov' should not be expanded to dove' because the elision
// requires the last vowel to be removed.
final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled
- && !mInputTypeNoAutoCorrect;
+ && !mInputAttributes.mInputTypeNoAutoCorrect;
if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) {
- pickedDefault = pickDefaultSuggestion(primaryCode);
+ commitCurrentAutoCorrection(primaryCode, ic);
} else {
commitTyped(ic);
}
}
- if (mJustAddedMagicSpace) {
+ final boolean swapMagicSpace;
+ if (Keyboard.CODE_ENTER == primaryCode && (SPACE_STATE_MAGIC == spaceState
+ || SPACE_STATE_SWAP_PUNCTUATION == spaceState)) {
+ removeTrailingSpaceWhileInBatchEdit(ic);
+ swapMagicSpace = false;
+ } else if (SPACE_STATE_MAGIC == spaceState) {
if (mSettingsValues.isMagicSpaceSwapper(primaryCode)) {
- sendKeyChar((char)primaryCode);
- swapSwapperAndSpace();
+ swapMagicSpace = true;
} else {
- if (mSettingsValues.isMagicSpaceStripper(primaryCode)) removeTrailingSpace();
- sendKeyChar((char)primaryCode);
- mJustAddedMagicSpace = false;
+ swapMagicSpace = false;
+ if (mSettingsValues.isMagicSpaceStripper(primaryCode)) {
+ removeTrailingSpaceWhileInBatchEdit(ic);
+ }
}
} else {
- sendKeyChar((char)primaryCode);
+ swapMagicSpace = false;
}
- if (isSuggestionsRequested() && primaryCode == Keyboard.CODE_SPACE) {
- maybeDoubleSpace();
- }
-
- TextEntryState.typedCharacter((char) primaryCode, true, x, y);
+ sendKeyChar((char)primaryCode);
- if (pickedDefault) {
- CharSequence typedWord = mWordComposer.getTypedWord();
- TextEntryState.backToAcceptedDefault(typedWord);
- if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) {
- InputConnectionCompatUtils.commitCorrection(
- ic, mLastSelectionEnd - typedWord.length(), typedWord, mBestWord);
- }
- }
if (Keyboard.CODE_SPACE == primaryCode) {
+ if (isSuggestionsRequested()) {
+ if (maybeDoubleSpaceWhileInBatchEdit(ic)) {
+ mSpaceState = SPACE_STATE_DOUBLE;
+ } else if (!isShowingPunctuationList()) {
+ mSpaceState = SPACE_STATE_WEAK;
+ }
+ }
+
+ mHandler.startDoubleSpacesTimer();
if (!isCursorTouchingWord()) {
mHandler.cancelUpdateSuggestions();
mHandler.postUpdateBigramPredictions();
}
} else {
+ if (swapMagicSpace) {
+ swapSwapperAndSpaceWhileInBatchEdit(ic);
+ mSpaceState = SPACE_STATE_MAGIC;
+ }
+
// Set punctuation right away. onUpdateSelection will fire but tests whether it is
// already displayed or not, so it's okay.
setPunctuationSuggestions();
}
- mKeyboardSwitcher.updateShiftState();
+
+ Utils.Stats.onSeparator((char)primaryCode, x, y);
+
if (ic != null) {
ic.endBatchEdit();
}
}
+ private CharSequence getTextWithUnderline(final CharSequence text) {
+ return mComposingStateManager.isAutoCorrectionIndicatorOn()
+ ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(this, text)
+ : mWordComposer.getTypedWord();
+ }
+
private void handleClose() {
commitTyped(getCurrentInputConnection());
mVoiceProxy.handleClose();
@@ -1635,7 +1608,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
public boolean isSuggestionsRequested() {
- return mIsSettingsSuggestionStripOn
+ return mInputAttributes.mIsSettingsSuggestionStripOn
&& (mCorrectionMode > 0 || isShowingSuggestionsStrip());
}
@@ -1653,11 +1626,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
public boolean isSuggestionsStripVisible() {
if (mSuggestionsView == null)
return false;
- if (mSuggestionsView.isShowingAddToDictionaryHint() || TextEntryState.isRecorrecting())
+ if (mSuggestionsView.isShowingAddToDictionaryHint())
return true;
if (!isShowingSuggestionsStrip())
return false;
- if (mApplicationSpecifiedCompletionOn)
+ if (mInputAttributes.mApplicationSpecifiedCompletionOn)
return true;
return isSuggestionsRequested();
}
@@ -1698,18 +1671,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mComposingStateManager.isAutoCorrectionIndicatorOn();
final boolean newAutoCorrectionIndicator = Utils.willAutoCorrect(words);
if (oldAutoCorrectionIndicator != newAutoCorrectionIndicator) {
- if (LatinImeLogger.sDBG) {
+ mComposingStateManager.setAutoCorrectionIndicatorOn(newAutoCorrectionIndicator);
+ if (DEBUG) {
Log.d(TAG, "Flip the indicator. " + oldAutoCorrectionIndicator
+ " -> " + newAutoCorrectionIndicator);
+ if (newAutoCorrectionIndicator
+ != mComposingStateManager.isAutoCorrectionIndicatorOn()) {
+ throw new RuntimeException("Couldn't flip the indicator! We are not "
+ + "composing a word right now.");
+ }
}
- final CharSequence textWithUnderline = newAutoCorrectionIndicator
- ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(
- this, mComposingStringBuilder)
- : mComposingStringBuilder;
+ final CharSequence textWithUnderline =
+ getTextWithUnderline(mWordComposer.getTypedWord());
if (!TextUtils.isEmpty(textWithUnderline)) {
ic.setComposingText(textWithUnderline, 1);
}
- mComposingStateManager.setAutoCorrectionIndicatorOn(newAutoCorrectionIndicator);
}
}
}
@@ -1724,12 +1700,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mHandler.cancelUpdateSuggestions();
mHandler.cancelUpdateBigramPredictions();
- if (!mHasUncommittedTypedChars) {
+ if (!mWordComposer.isComposingWord()) {
setPunctuationSuggestions();
return;
}
- final WordComposer wordComposer = mWordComposer;
// TODO: May need a better way of retrieving previous word
final InputConnection ic = getCurrentInputConnection();
final CharSequence prevWord;
@@ -1739,26 +1714,35 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators);
}
// getSuggestedWordBuilder handles gracefully a null value of prevWord
- final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(
- wordComposer, prevWord, mKeyboardSwitcher.getLatinKeyboard().getProximityInfo());
+ final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(mWordComposer,
+ prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), mCorrectionMode);
- boolean autoCorrectionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection();
- final CharSequence typedWord = wordComposer.getTypedWord();
+ boolean autoCorrectionAvailable = !mInputAttributes.mInputTypeNoAutoCorrect
+ && mSuggest.hasAutoCorrection();
+ final CharSequence typedWord = mWordComposer.getTypedWord();
// Here, we want to promote a whitelisted word if exists.
// TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid"
// but still autocorrected from - in the case the whitelist only capitalizes the word.
// The whitelist should be case-insensitive, so it's not possible to be consistent with
// a boolean flag. Right now this is handled with a slight hack in
// WhitelistDictionary#shouldForciblyAutoCorrectFrom.
+ final int quotesCount = mWordComposer.trailingSingleQuotesCount();
final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected(
- mSuggest.getUnigramDictionaries(), typedWord, preferCapitalization());
+ mSuggest.getUnigramDictionaries(),
+ // If the typed string ends with a single quote, for dictionary lookup purposes
+ // we behave as if the single quote was not here. Here, we are looking up the
+ // typed string in the dictionary (to avoid autocorrecting from an existing
+ // word, so for consistency this lookup should be made WITHOUT the trailing
+ // single quote.
+ quotesCount > 0
+ ? typedWord.subSequence(0, typedWord.length() - quotesCount) : typedWord,
+ preferCapitalization());
if (mCorrectionMode == Suggest.CORRECTION_FULL
|| mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) {
autoCorrectionAvailable |= (!allowsToBeAutoCorrected);
}
// Don't auto-correct words with multiple capital letter
- autoCorrectionAvailable &= !wordComposer.isMostlyCaps();
- autoCorrectionAvailable &= !TextEntryState.isRecorrecting();
+ autoCorrectionAvailable &= !mWordComposer.isMostlyCaps();
// Basically, we update the suggestion strip only when suggestion count > 1. However,
// there is an exception: We update the suggestion strip whenever typed word's length
@@ -1794,34 +1778,46 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
setSuggestions(suggestedWords);
if (suggestedWords.size() > 0) {
if (shouldBlockAutoCorrectionBySafetyNet) {
- mBestWord = typedWord;
+ mWordComposer.setAutoCorrection(typedWord);
} else if (suggestedWords.hasAutoCorrectionWord()) {
- mBestWord = suggestedWords.getWord(1);
+ mWordComposer.setAutoCorrection(suggestedWords.getWord(1));
} else {
- mBestWord = typedWord;
+ mWordComposer.setAutoCorrection(typedWord);
}
} else {
- mBestWord = null;
+ // TODO: replace with mWordComposer.deleteAutoCorrection()?
+ mWordComposer.setAutoCorrection(null);
}
setSuggestionStripShown(isSuggestionsStripVisible());
}
- private boolean pickDefaultSuggestion(int separatorCode) {
+ private void commitCurrentAutoCorrection(final int separatorCodePoint,
+ final InputConnection ic) {
// Complete any pending suggestions query first
if (mHandler.hasPendingUpdateSuggestions()) {
mHandler.cancelUpdateSuggestions();
updateSuggestions();
}
- if (mBestWord != null && mBestWord.length() > 0) {
- TextEntryState.acceptedDefault(mWordComposer.getTypedWord(), mBestWord, separatorCode);
+ final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull();
+ if (autoCorrection != null) {
+ final String typedWord = mWordComposer.getTypedWord();
+ if (TextUtils.isEmpty(typedWord)) {
+ throw new RuntimeException("We have an auto-correction but the typed word "
+ + "is empty? Impossible! I must commit suicide.");
+ }
+ Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint);
mExpectingUpdateSelection = true;
- commitBestWord(mBestWord);
+ commitChosenWord(autoCorrection, WordComposer.COMMIT_TYPE_DECIDED_WORD);
// Add the word to the user unigram dictionary if it's not a known word
- addToUserUnigramAndBigramDictionaries(mBestWord,
+ addToUserUnigramAndBigramDictionaries(autoCorrection,
UserUnigramDictionary.FREQUENCY_FOR_TYPED);
- return true;
+ if (!typedWord.equals(autoCorrection) && null != ic) {
+ // This will make the correction flash for a short while as a visual clue
+ // to the user that auto-correction happened.
+ InputConnectionCompatUtils.commitCorrection(ic,
+ mLastSelectionEnd - typedWord.length(), typedWord, autoCorrection);
+ }
}
- return false;
}
@Override
@@ -1831,18 +1827,17 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion,
mSettingsValues.mWordSeparators);
- final boolean recorrecting = TextEntryState.isRecorrecting();
final InputConnection ic = getCurrentInputConnection();
if (ic != null) {
ic.beginBatchEdit();
}
- if (mApplicationSpecifiedCompletionOn && mApplicationSpecifiedCompletions != null
+ if (mInputAttributes.mApplicationSpecifiedCompletionOn
+ && mApplicationSpecifiedCompletions != null
&& index >= 0 && index < mApplicationSpecifiedCompletions.length) {
if (ic != null) {
final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index];
ic.commitCompletion(completionInfo);
}
- mCommittedLength = suggestion.length();
if (mSuggestionsView != null) {
mSuggestionsView.clear();
}
@@ -1861,36 +1856,24 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
LatinImeLogger.logOnManualSuggestion(
"", suggestion.toString(), index, suggestions.mWords);
// Find out whether the previous character is a space. If it is, as a special case
- // for punctuation entered through the suggestion strip, it should be considered
- // a magic space even if it was a normal space. This is meant to help in case the user
+ // for punctuation entered through the suggestion strip, it should be swapped
+ // if it was a magic or a weak space. This is meant to help in case the user
// pressed space on purpose of displaying the suggestion strip punctuation.
final int rawPrimaryCode = suggestion.charAt(0);
// Maybe apply the "bidi mirrored" conversions for parentheses
- final LatinKeyboard keyboard = mKeyboardSwitcher.getLatinKeyboard();
+ final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
final boolean isRtl = keyboard != null && keyboard.mIsRtlKeyboard;
final int primaryCode = Key.getRtlParenthesisCode(rawPrimaryCode, isRtl);
- final CharSequence beforeText = ic != null ? ic.getTextBeforeCursor(1, 0) : "";
- final int toLeft = (ic == null || TextUtils.isEmpty(beforeText))
- ? 0 : beforeText.charAt(0);
- final boolean oldMagicSpace = mJustAddedMagicSpace;
- if (Keyboard.CODE_SPACE == toLeft) mJustAddedMagicSpace = true;
- onCodeInput(primaryCode, new int[] { primaryCode },
- KeyboardActionListener.NOT_A_TOUCH_COORDINATE,
- KeyboardActionListener.NOT_A_TOUCH_COORDINATE);
- mJustAddedMagicSpace = oldMagicSpace;
+ insertPunctuationFromSuggestionStrip(ic, primaryCode);
+ // TODO: the following endBatchEdit seems useless, check
if (ic != null) {
ic.endBatchEdit();
}
return;
}
- if (!mHasUncommittedTypedChars) {
- // If we are not composing a word, then it was a suggestion inferred from
- // context - no user input. We should reset the word composer.
- mWordComposer.reset();
- }
mExpectingUpdateSelection = true;
- commitBestWord(suggestion);
+ commitChosenWord(suggestion, WordComposer.COMMIT_TYPE_MANUAL_PICK);
// Add the word to the auto dictionary if it's not a known word
if (index == 0) {
addToUserUnigramAndBigramDictionaries(suggestion,
@@ -1898,11 +1881,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} else {
addToOnlyBigramDictionary(suggestion, 1);
}
- LatinImeLogger.logOnManualSuggestion(mComposingStringBuilder.toString(),
+ // TODO: the following is fishy, because it seems there may be cases where we are not
+ // composing a word at all. Maybe throw an exception if !mWordComposer.isComposingWord() ?
+ LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(),
suggestion.toString(), index, suggestions.mWords);
- TextEntryState.acceptedSuggestion(mComposingStringBuilder.toString(), suggestion);
// Follow it with a space
- if (mInsertSpaceOnPickSuggestionManually && !recorrecting) {
+ if (mInputAttributes.mInsertSpaceOnPickSuggestionManually) {
sendMagicSpace();
}
@@ -1922,13 +1906,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|| !AutoCorrection.isValidWord(
mSuggest.getUnigramDictionaries(), suggestion, true));
- if (!recorrecting) {
- // Fool the state watcher so that a subsequent backspace will not do a revert, unless
- // we just did a correction, in which case we need to stay in
- // TextEntryState.State.PICKED_SUGGESTION state.
- TextEntryState.typedCharacter((char) Keyboard.CODE_SPACE, true,
- WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
- }
+ Utils.Stats.onSeparator((char)Keyboard.CODE_SPACE, WordComposer.NOT_A_COORDINATE,
+ WordComposer.NOT_A_COORDINATE);
if (!showingAddToDictionaryHint) {
// If we're not showing the "Touch again to save", then show corrections again.
// In case the cursor position doesn't change, make sure we show the suggestions again.
@@ -1938,8 +1917,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// take a noticeable delay to update them which may feel uneasy.
}
if (showingAddToDictionaryHint) {
- if (mIsUserDictionaryAvaliable) {
- mSuggestionsView.showAddToDictionaryHint(suggestion);
+ if (mIsUserDictionaryAvailable) {
+ mSuggestionsView.showAddToDictionaryHint(
+ suggestion, mSettingsValues.mHintToSaveText);
} else {
mHandler.postUpdateSuggestions();
}
@@ -1952,7 +1932,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
/**
* Commits the chosen word to the text field and saves it for later retrieval.
*/
- private void commitBestWord(CharSequence bestWord) {
+ private void commitChosenWord(final CharSequence bestWord, final int commitType) {
final KeyboardSwitcher switcher = mKeyboardSwitcher;
if (!switcher.isKeyboardAvailable())
return;
@@ -1967,8 +1947,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
ic.commitText(bestWord, 1);
}
}
- mHasUncommittedTypedChars = false;
- mCommittedLength = bestWord.length();
+ // TODO: figure out here if this is an auto-correct or if the best word is actually
+ // what user typed. Note: currently this is done much later in
+ // WordComposer#didAutoCorrectToAnotherWord by string equality of the remembered
+ // strings.
+ mWordComposer.onCommitWord(commitType);
}
private static final WordComposer sEmptyWordComposer = new WordComposer();
@@ -1984,7 +1967,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(),
mSettingsValues.mWordSeparators);
SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(sEmptyWordComposer,
- prevWord, mKeyboardSwitcher.getLatinKeyboard().getProximityInfo());
+ prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), mCorrectionMode);
if (builder.size() > 0) {
// Explicitly supply an empty typed word (the no-second-arg version of
@@ -2070,54 +2053,125 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return false;
}
- // "ic" must not null
- private boolean sameAsTextBeforeCursor(final InputConnection ic, CharSequence text) {
+ // "ic" must not be null
+ private static boolean sameAsTextBeforeCursor(final InputConnection ic, CharSequence text) {
CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0);
return TextUtils.equals(text, beforeText);
}
- // "ic" must not null
- private void revertLastWord(final InputConnection ic) {
- if (mHasUncommittedTypedChars || mComposingStringBuilder.length() <= 0) {
- sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
- return;
- }
+ // "ic" must not be null
+ /**
+ * Check if the cursor is actually at the end of a word. If so, restart suggestions on this
+ * word, else do nothing.
+ */
+ private void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(
+ final InputConnection ic) {
+ // Bail out if the cursor is not at the end of a word (cursor must be preceded by
+ // non-whitespace, non-separator, non-start-of-text)
+ // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here.
+ final CharSequence textBeforeCursor = ic.getTextBeforeCursor(1, 0);
+ if (TextUtils.isEmpty(textBeforeCursor)
+ || mSettingsValues.isWordSeparator(textBeforeCursor.charAt(0))) return;
+
+ // Bail out if the cursor is in the middle of a word (cursor must be followed by whitespace,
+ // separator or end of line/text)
+ // Example: "test|"<EOL> "te|st" get rejected here
+ final CharSequence textAfterCursor = ic.getTextAfterCursor(1, 0);
+ if (!TextUtils.isEmpty(textAfterCursor)
+ && !mSettingsValues.isWordSeparator(textAfterCursor.charAt(0))) return;
+
+ // Bail out if word before cursor is 0-length or a single non letter (like an apostrophe)
+ // Example: " '|" gets rejected here but "I'|" and "I|" are okay
+ final CharSequence word = EditingUtils.getWordAtCursor(ic, mSettingsValues.mWordSeparators);
+ if (TextUtils.isEmpty(word)) return;
+ if (word.length() == 1 && !Character.isLetter(word.charAt(0))) return;
+
+ // Okay, we are at the end of a word. Restart suggestions.
+ restartSuggestionsOnWordBeforeCursor(ic, word);
+ }
+
+ // "ic" must not be null
+ private void restartSuggestionsOnWordBeforeCursor(final InputConnection ic,
+ final CharSequence word) {
+ mWordComposer.setComposingWord(word, mKeyboardSwitcher.getKeyboard());
+ mComposingStateManager.onStartComposingText();
+ ic.deleteSurroundingText(word.length(), 0);
+ ic.setComposingText(word, 1);
+ mHandler.postUpdateSuggestions();
+ }
+ // "ic" must not be null
+ private void cancelAutoCorrect(final InputConnection ic) {
+ mWordComposer.resumeSuggestionOnKeptWord();
+ final String originallyTypedWord = mWordComposer.getTypedWord();
+ final CharSequence autoCorrectedTo = mWordComposer.getAutoCorrectionOrNull();
+ final int cancelLength = autoCorrectedTo.length();
final CharSequence separator = ic.getTextBeforeCursor(1, 0);
- ic.deleteSurroundingText(1, 0);
- final CharSequence textToTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0);
- ic.deleteSurroundingText(mCommittedLength, 0);
-
- // Re-insert "separator" only when the deleted character was word separator and the
- // composing text wasn't equal to the auto-corrected text which can be found before
- // the cursor.
- if (!TextUtils.isEmpty(separator)
- && mSettingsValues.isWordSeparator(separator.charAt(0))
- && !TextUtils.equals(mComposingStringBuilder, textToTheLeft)) {
- ic.commitText(mComposingStringBuilder, 1);
- TextEntryState.acceptedTyped(mComposingStringBuilder);
- ic.commitText(separator, 1);
- TextEntryState.typedCharacter(separator.charAt(0), true,
- WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
- // Clear composing text
- mComposingStringBuilder.setLength(0);
- } else {
- mHasUncommittedTypedChars = true;
- ic.setComposingText(mComposingStringBuilder, 1);
- TextEntryState.backspace();
+ if (DEBUG) {
+ final String wordBeforeCursor =
+ ic.getTextBeforeCursor(cancelLength + 1, 0).subSequence(0, cancelLength)
+ .toString();
+ if (!autoCorrectedTo.equals(wordBeforeCursor)) {
+ throw new RuntimeException("cancelAutoCorrect check failed: we thought we were "
+ + "reverting \"" + autoCorrectedTo
+ + "\", but before the cursor we found \"" + wordBeforeCursor + "\"");
+ }
+ if (originallyTypedWord.equals(wordBeforeCursor)) {
+ throw new RuntimeException("cancelAutoCorrect check failed: we wanted to cancel "
+ + "auto correction and revert to \"" + originallyTypedWord
+ + "\" but we found this very string before the cursor");
+ }
}
+ ic.deleteSurroundingText(cancelLength + 1, 0);
+ ic.commitText(originallyTypedWord, 1);
+ // Re-insert the separator
+ ic.commitText(separator, 1);
+ mWordComposer.deleteAutoCorrection();
+ mWordComposer.onCommitWord(WordComposer.COMMIT_TYPE_CANCEL_AUTO_CORRECT);
+ Utils.Stats.onSeparator(separator.charAt(0), WordComposer.NOT_A_COORDINATE,
+ WordComposer.NOT_A_COORDINATE);
mHandler.cancelUpdateBigramPredictions();
mHandler.postUpdateSuggestions();
}
- // "ic" must not null
+ // "ic" must not be null
+ private void restartSuggestionsOnManuallyPickedTypedWord(final InputConnection ic) {
+ final int restartLength = mWordComposer.size();
+ if (DEBUG) {
+ final String wordBeforeCursor =
+ ic.getTextBeforeCursor(restartLength + 1, 0).subSequence(0, restartLength)
+ .toString();
+ if (!mWordComposer.getTypedWord().equals(wordBeforeCursor)) {
+ throw new RuntimeException("restartSuggestionsOnManuallyPickedTypedWord "
+ + "check failed: we thought we were reverting \""
+ + mWordComposer.getTypedWord()
+ + "\", but before the cursor we found \""
+ + wordBeforeCursor + "\"");
+ }
+ }
+ ic.deleteSurroundingText(restartLength + 1, 0);
+
+ // Note: this relies on the last word still being held in the WordComposer
+ // Note: in the interest of code simplicity, we may want to just call
+ // restartSuggestionsOnWordBeforeCursorIfAtEndOfWord instead, but retrieving
+ // the old WordComposer allows to reuse the actual typed coordinates.
+ mWordComposer.resumeSuggestionOnKeptWord();
+ ic.setComposingText(mWordComposer.getTypedWord(), 1);
+ mHandler.cancelUpdateBigramPredictions();
+ mHandler.postUpdateSuggestions();
+ }
+
+ // "ic" must not be null
private boolean revertDoubleSpace(final InputConnection ic) {
mHandler.cancelDoubleSpacesTimer();
// Here we test whether we indeed have a period and a space before us. This should not
// be needed, but it's there just in case something went wrong.
final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0);
- if (!". ".equals(textBeforeCursor))
- return false;
+ if (!". ".equals(textBeforeCursor)) {
+ // We should not have come here if we aren't just after a ". ".
+ throw new RuntimeException("Tried to revert double-space combo but we didn't find "
+ + "\". \" just before the cursor.");
+ }
ic.beginBatchEdit();
ic.deleteSurroundingText(2, 0);
ic.commitText(" ", 1);
@@ -2125,13 +2179,31 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return true;
}
+ private static boolean revertSwapPunctuation(final InputConnection ic) {
+ // Here we test whether we indeed have a space and something else before us. This should not
+ // be needed, but it's there just in case something went wrong.
+ final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0);
+ // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to
+ // enter surrogate pairs this code will have been removed.
+ if (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1)) {
+ // We should not have come here if the text before the cursor is not a space.
+ throw new RuntimeException("Tried to revert a swap of punctuation but we didn't "
+ + "find a space just before the cursor.");
+ }
+ ic.beginBatchEdit();
+ ic.deleteSurroundingText(2, 0);
+ ic.commitText(" " + textBeforeCursor.subSequence(0, 1), 1);
+ ic.endBatchEdit();
+ return true;
+ }
+
public boolean isWordSeparator(int code) {
return mSettingsValues.isWordSeparator(code);
}
private void sendMagicSpace() {
sendKeyChar((char)Keyboard.CODE_SPACE);
- mJustAddedMagicSpace = true;
+ mSpaceState = SPACE_STATE_MAGIC;
mKeyboardSwitcher.updateShiftState();
}
@@ -2157,12 +2229,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
loadSettings();
}
+ private void hapticAndAudioFeedback(int primaryCode) {
+ vibrate();
+ playKeyClick(primaryCode);
+ }
+
@Override
public void onPress(int primaryCode, boolean withSliding) {
final KeyboardSwitcher switcher = mKeyboardSwitcher;
if (switcher.isVibrateAndSoundFeedbackRequired()) {
- vibrate();
- playKeyClick(primaryCode);
+ hapticAndAudioFeedback(primaryCode);
}
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) {
@@ -2200,11 +2276,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
};
- // update keypress sound volume
- private void updateSoundEffectVolume() {
- mFxVolume = Utils.getCurrentKeypressSoundVolume(mPrefs, mResources);
- }
-
// update flags for silent mode
private void updateRingerMode() {
if (mAudioManager == null) {
@@ -2214,10 +2285,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mSilentModeOn = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL);
}
- private void updateKeypressVibrationDuration() {
- mKeypressVibrationDuration = Utils.getCurrentVibrationDuration(mPrefs, mResources);
- }
-
private void playKeyClick(int primaryCode) {
// if mAudioManager is null, we don't have the ringer state yet
// mAudioManager will be set by updateRingerMode
@@ -2242,7 +2309,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
sound = AudioManager.FX_KEYPRESS_STANDARD;
break;
}
- mAudioManager.playSoundEffect(sound, mFxVolume);
+ mAudioManager.playSoundEffect(sound, mSettingsValues.mFxVolume);
}
}
@@ -2250,7 +2317,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (!mSettingsValues.mVibrateOn) {
return;
}
- if (mKeypressVibrationDuration < 0) {
+ if (mSettingsValues.mKeypressVibrationDuration < 0) {
// Go ahead with the system default
LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
if (inputView != null) {
@@ -2259,12 +2326,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
}
} else if (mVibrator != null) {
- mVibrator.vibrate(mKeypressVibrationDuration);
+ mVibrator.vibrate(mSettingsValues.mKeypressVibrationDuration);
}
}
- public WordComposer getCurrentWord() {
- return mWordComposer;
+ public boolean isAutoCapitalized() {
+ return mWordComposer.isAutoCapitalized();
}
boolean isSoundOn() {
@@ -2274,22 +2341,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private void updateCorrectionMode() {
// TODO: cleanup messy flags
final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled
- && !mInputTypeNoAutoCorrect;
- mCorrectionMode = (shouldAutoCorrect && mSettingsValues.mAutoCorrectEnabled)
- ? Suggest.CORRECTION_FULL
- : (shouldAutoCorrect ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE);
- mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect
- && mSettingsValues.mAutoCorrectEnabled)
+ && !mInputAttributes.mInputTypeNoAutoCorrect;
+ mCorrectionMode = shouldAutoCorrect ? Suggest.CORRECTION_FULL : Suggest.CORRECTION_NONE;
+ mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect)
? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode;
- if (mSuggest != null) {
- mSuggest.setCorrectionMode(mCorrectionMode);
- }
}
- private void updateSuggestionVisibility(final SharedPreferences prefs, final Resources res) {
- final String suggestionVisiblityStr = prefs.getString(
- Settings.PREF_SHOW_SUGGESTIONS_SETTING,
- res.getString(R.string.prefs_suggestion_visibility_default_value));
+ private void updateSuggestionVisibility(final Resources res) {
+ final String suggestionVisiblityStr = mSettingsValues.mShowSuggestionsSetting;
for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) {
if (suggestionVisiblityStr.equals(res.getString(visibility))) {
mSuggestionVisibility = visibility;
@@ -2328,7 +2387,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
switch (position) {
case 0:
Intent intent = CompatUtils.getInputLanguageSelectionIntent(
- mInputMethodId, Intent.FLAG_ACTIVITY_NEW_TASK
+ Utils.getInputMethodId(mImm, getPackageName()),
+ Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
@@ -2377,35 +2437,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final Printer p = new PrintWriterPrinter(fout);
p.println("LatinIME state :");
- p.println(" Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode());
- p.println(" mComposingStringBuilder=" + mComposingStringBuilder.toString());
- p.println(" mIsSuggestionsRequested=" + mIsSettingsSuggestionStripOn);
+ final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
+ final int keyboardMode = keyboard != null ? keyboard.mId.mMode : -1;
+ p.println(" Keyboard mode = " + keyboardMode);
+ p.println(" mIsSuggestionsRequested=" + mInputAttributes.mIsSettingsSuggestionStripOn);
p.println(" mCorrectionMode=" + mCorrectionMode);
- p.println(" mHasUncommittedTypedChars=" + mHasUncommittedTypedChars);
+ p.println(" isComposingWord=" + mWordComposer.isComposingWord());
p.println(" mAutoCorrectEnabled=" + mSettingsValues.mAutoCorrectEnabled);
- p.println(" mInsertSpaceOnPickSuggestionManually=" + mInsertSpaceOnPickSuggestionManually);
- p.println(" mApplicationSpecifiedCompletionOn=" + mApplicationSpecifiedCompletionOn);
- p.println(" TextEntryState.state=" + TextEntryState.getState());
p.println(" mSoundOn=" + mSettingsValues.mSoundOn);
p.println(" mVibrateOn=" + mSettingsValues.mVibrateOn);
p.println(" mKeyPreviewPopupOn=" + mSettingsValues.mKeyPreviewPopupOn);
- }
-
- // Characters per second measurement
-
- private long mLastCpsTime;
- private static final int CPS_BUFFER_SIZE = 16;
- private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE];
- private int mCpsIndex;
-
- private void measureCps() {
- long now = System.currentTimeMillis();
- if (mLastCpsTime == 0) mLastCpsTime = now - 100; // Initial
- mCpsIntervals[mCpsIndex] = now - mLastCpsTime;
- mLastCpsTime = now;
- mCpsIndex = (mCpsIndex + 1) % CPS_BUFFER_SIZE;
- long total = 0;
- for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i];
- System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total));
+ p.println(" mInputAttributes=" + mInputAttributes.toString());
}
}
diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
index ae8eb374b..6f1adfe71 100644
--- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java
+++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
@@ -16,11 +16,12 @@
package com.android.inputmethod.latin;
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.latin.Dictionary.DataType;
-
import android.content.Context;
import android.content.SharedPreferences;
+import android.view.inputmethod.EditorInfo;
+
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.Dictionary.DataType;
import java.util.List;
@@ -28,12 +29,13 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
public static boolean sDBG = false;
public static boolean sVISUALDEBUG = false;
+ public static boolean sUsabilityStudy = false;
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
}
- public static void init(Context context, SharedPreferences prefs) {
+ public static void init(LatinIME context, SharedPreferences prefs) {
}
public static void commit() {
@@ -44,7 +46,7 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
public static void logOnManualSuggestion(
String before, String after, int position, List<CharSequence> suggestions) {
- }
+ }
public static void logOnAutoCorrection(String before, String after, int separatorCode) {
}
@@ -67,6 +69,9 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
public static void logOnWarning(String warning) {
}
+ public static void onStartInputView(EditorInfo editorInfo) {
+ }
+
public static void onStartSuggestion(CharSequence previousWords) {
}
@@ -78,4 +83,8 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
public static void onPrintAllUsabilityStudyLogs() {
}
+
+ public static boolean isResearcherPackage(Context context) {
+ return false;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 773efe709..5af21452a 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -38,7 +38,6 @@ import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.View;
-import android.view.inputmethod.EditorInfo;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
@@ -46,12 +45,10 @@ import android.widget.TextView;
import com.android.inputmethod.compat.CompatUtils;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.compat.InputMethodServiceCompatWrapper;
-import com.android.inputmethod.compat.InputTypeCompatUtils;
import com.android.inputmethod.compat.VibratorCompatWrapper;
import com.android.inputmethod.deprecated.VoiceProxy;
import com.android.inputmethodcommon.InputMethodSettingsActivity;
-import java.util.Arrays;
import java.util.Locale;
public class Settings extends InputMethodSettingsActivity
@@ -61,255 +58,39 @@ public class Settings extends InputMethodSettingsActivity
public static final boolean ENABLE_EXPERIMENTAL_SETTINGS = false;
- public static final String PREF_GENERAL_SETTINGS_KEY = "general_settings";
+ // In the same order as xml/prefs.xml
+ public static final String PREF_GENERAL_SETTINGS = "general_settings";
+ public static final String PREF_SUBTYPES_SETTINGS = "subtype_settings";
+ public static final String PREF_AUTO_CAP = "auto_cap";
public static final String PREF_VIBRATE_ON = "vibrate_on";
public static final String PREF_SOUND_ON = "sound_on";
- public static final String PREF_KEY_PREVIEW_POPUP_ON = "popup_on";
- public static final String PREF_AUTO_CAP = "auto_cap";
+ public static final String PREF_POPUP_ON = "popup_on";
public static final String PREF_SHOW_SETTINGS_KEY = "show_settings_key";
- public static final String PREF_VOICE_SETTINGS_KEY = "voice_mode";
- public static final String PREF_INPUT_LANGUAGE = "input_language";
- public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
- public static final String PREF_SUBTYPES = "subtype_settings";
-
+ public static final String PREF_VOICE_MODE = "voice_mode";
+ public static final String PREF_CORRECTION_SETTINGS = "correction_settings";
public static final String PREF_CONFIGURE_DICTIONARIES_KEY = "configure_dictionaries_key";
- public static final String PREF_CORRECTION_SETTINGS_KEY = "correction_settings";
- public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting";
public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold";
- public static final String PREF_DEBUG_SETTINGS = "debug_settings";
-
- public static final String PREF_BIGRAM_SUGGESTIONS = "bigram_suggestion";
- public static final String PREF_BIGRAM_PREDICTIONS = "bigram_prediction";
-
- public static final String PREF_MISC_SETTINGS_KEY = "misc_settings";
-
+ public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting";
+ public static final String PREF_MISC_SETTINGS = "misc_settings";
+ public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
+ public static final String PREF_ADVANCED_SETTINGS = "pref_advanced_settings";
public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY =
"pref_key_preview_popup_dismiss_delay";
- public static final String PREF_KEY_USE_CONTACTS_DICT =
- "pref_key_use_contacts_dict";
- public static final String PREF_KEY_ENABLE_SPAN_INSERT =
- "enable_span_insert";
-
- public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
-
- public static final String PREF_KEYPRESS_VIBRATION_DURATION_SETTINGS =
+ public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict";
+ public static final String PREF_BIGRAM_SUGGESTION = "bigram_suggestion";
+ public static final String PREF_BIGRAM_PREDICTIONS = "bigram_prediction";
+ public static final String PREF_KEY_ENABLE_SPAN_INSERT = "enable_span_insert";
+ public static final String PREF_VIBRATION_DURATION_SETTINGS =
"pref_vibration_duration_settings";
-
public static final String PREF_KEYPRESS_SOUND_VOLUME =
"pref_keypress_sound_volume";
- // Dialog ids
- private static final int VOICE_INPUT_CONFIRM_DIALOG = 0;
-
- public static class Values {
- // From resources:
- public final int mDelayUpdateOldSuggestions;
- public final String mWordSeparators;
- public final String mMagicSpaceStrippers;
- public final String mMagicSpaceSwappers;
- public final String mSuggestPuncs;
- public final SuggestedWords mSuggestPuncList;
- private final String mSymbolsExcludedFromWordSeparators;
-
- // From preferences:
- public final boolean mSoundOn; // Sound setting private to Latin IME (see mSilentModeOn)
- public final boolean mVibrateOn;
- public final boolean mKeyPreviewPopupOn;
- public final int mKeyPreviewPopupDismissDelay;
- public final boolean mAutoCap;
- public final boolean mAutoCorrectEnabled;
- public final double mAutoCorrectionThreshold;
- // Suggestion: use bigrams to adjust scores of suggestions obtained from unigram dictionary
- public final boolean mBigramSuggestionEnabled;
- // Prediction: use bigrams to predict the next word when there is no input for it yet
- public final boolean mBigramPredictionEnabled;
- public final boolean mUseContactsDict;
- public final boolean mEnableSuggestionSpanInsertion;
-
- private final boolean mShowSettingsKey;
- private final boolean mVoiceKeyEnabled;
- private final boolean mVoiceKeyOnMain;
-
- public Values(final SharedPreferences prefs, final Context context,
- final String localeStr) {
- final Resources res = context.getResources();
- final Locale savedLocale;
- if (null != localeStr) {
- final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr);
- savedLocale = LocaleUtils.setSystemLocale(res, keyboardLocale);
- } else {
- savedLocale = null;
- }
-
- // Get the resources
- mDelayUpdateOldSuggestions = res.getInteger(
- R.integer.config_delay_update_old_suggestions);
- mMagicSpaceStrippers = res.getString(R.string.magic_space_stripping_symbols);
- mMagicSpaceSwappers = res.getString(R.string.magic_space_swapping_symbols);
- String wordSeparators = mMagicSpaceStrippers + mMagicSpaceSwappers
- + res.getString(R.string.magic_space_promoting_symbols);
- final String symbolsExcludedFromWordSeparators =
- res.getString(R.string.symbols_excluded_from_word_separators);
- for (int i = symbolsExcludedFromWordSeparators.length() - 1; i >= 0; --i) {
- wordSeparators = wordSeparators.replace(
- symbolsExcludedFromWordSeparators.substring(i, i + 1), "");
- }
- mSymbolsExcludedFromWordSeparators = symbolsExcludedFromWordSeparators;
- mWordSeparators = wordSeparators;
- mSuggestPuncs = res.getString(R.string.suggested_punctuations);
- // TODO: it would be nice not to recreate this each time we change the configuration
- mSuggestPuncList = createSuggestPuncList(mSuggestPuncs);
-
- // Get the settings preferences
- final boolean hasVibrator = VibratorCompatWrapper.getInstance(context).hasVibrator();
- mVibrateOn = hasVibrator && prefs.getBoolean(Settings.PREF_VIBRATE_ON,
- res.getBoolean(R.bool.config_default_vibration_enabled));
- mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON,
- res.getBoolean(R.bool.config_default_sound_enabled));
- mKeyPreviewPopupOn = isKeyPreviewPopupEnabled(prefs, res);
- mKeyPreviewPopupDismissDelay = getKeyPreviewPopupDismissDelay(prefs, res);
- mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true);
- mAutoCorrectEnabled = isAutoCorrectEnabled(prefs, res);
- mBigramSuggestionEnabled = mAutoCorrectEnabled
- && isBigramSuggestionEnabled(prefs, res, mAutoCorrectEnabled);
- mBigramPredictionEnabled = mBigramSuggestionEnabled
- && isBigramPredictionEnabled(prefs, res);
- mAutoCorrectionThreshold = getAutoCorrectionThreshold(prefs, res);
- mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true);
- mEnableSuggestionSpanInsertion =
- prefs.getBoolean(Settings.PREF_KEY_ENABLE_SPAN_INSERT, true);
- final boolean defaultShowSettingsKey = res.getBoolean(
- R.bool.config_default_show_settings_key);
- mShowSettingsKey = isShowSettingsKeyOption(res)
- ? prefs.getBoolean(Settings.PREF_SHOW_SETTINGS_KEY, defaultShowSettingsKey)
- : defaultShowSettingsKey;
- final String voiceModeMain = res.getString(R.string.voice_mode_main);
- final String voiceModeOff = res.getString(R.string.voice_mode_off);
- final String voiceMode = prefs.getString(PREF_VOICE_SETTINGS_KEY, voiceModeMain);
- mVoiceKeyEnabled = voiceMode != null && !voiceMode.equals(voiceModeOff);
- mVoiceKeyOnMain = voiceMode != null && voiceMode.equals(voiceModeMain);
-
- LocaleUtils.setSystemLocale(res, savedLocale);
- }
- public boolean isSuggestedPunctuation(int code) {
- return mSuggestPuncs.contains(String.valueOf((char)code));
- }
-
- public boolean isWordSeparator(int code) {
- return mWordSeparators.contains(String.valueOf((char)code));
- }
-
- public boolean isSymbolExcludedFromWordSeparators(int code) {
- return mSymbolsExcludedFromWordSeparators.contains(String.valueOf((char)code));
- }
-
- public boolean isMagicSpaceStripper(int code) {
- return mMagicSpaceStrippers.contains(String.valueOf((char)code));
- }
-
- public boolean isMagicSpaceSwapper(int code) {
- return mMagicSpaceSwappers.contains(String.valueOf((char)code));
- }
-
- private static boolean isAutoCorrectEnabled(SharedPreferences sp, Resources resources) {
- final String currentAutoCorrectionSetting = sp.getString(
- Settings.PREF_AUTO_CORRECTION_THRESHOLD,
- resources.getString(R.string.auto_correction_threshold_mode_index_modest));
- final String autoCorrectionOff = resources.getString(
- R.string.auto_correction_threshold_mode_index_off);
- return !currentAutoCorrectionSetting.equals(autoCorrectionOff);
- }
-
- // Public to access from KeyboardSwitcher. Should it have access to some
- // process-global instance instead?
- public static boolean isKeyPreviewPopupEnabled(SharedPreferences sp, Resources resources) {
- final boolean showPopupOption = resources.getBoolean(
- R.bool.config_enable_show_popup_on_keypress_option);
- if (!showPopupOption) return resources.getBoolean(R.bool.config_default_popup_preview);
- return sp.getBoolean(Settings.PREF_KEY_PREVIEW_POPUP_ON,
- resources.getBoolean(R.bool.config_default_popup_preview));
- }
-
- // Likewise
- public static int getKeyPreviewPopupDismissDelay(SharedPreferences sp,
- Resources resources) {
- return Integer.parseInt(sp.getString(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
- Integer.toString(resources.getInteger(R.integer.config_delay_after_preview))));
- }
-
- private static boolean isBigramSuggestionEnabled(SharedPreferences sp, Resources resources,
- boolean autoCorrectEnabled) {
- final boolean showBigramSuggestionsOption = resources.getBoolean(
- R.bool.config_enable_bigram_suggestions_option);
- if (!showBigramSuggestionsOption) {
- return autoCorrectEnabled;
- }
- return sp.getBoolean(Settings.PREF_BIGRAM_SUGGESTIONS, resources.getBoolean(
- R.bool.config_default_bigram_suggestions));
- }
-
- private static boolean isBigramPredictionEnabled(SharedPreferences sp,
- Resources resources) {
- return sp.getBoolean(Settings.PREF_BIGRAM_PREDICTIONS, resources.getBoolean(
- R.bool.config_default_bigram_prediction));
- }
-
- private static double getAutoCorrectionThreshold(SharedPreferences sp,
- Resources resources) {
- final String currentAutoCorrectionSetting = sp.getString(
- Settings.PREF_AUTO_CORRECTION_THRESHOLD,
- resources.getString(R.string.auto_correction_threshold_mode_index_modest));
- final String[] autoCorrectionThresholdValues = resources.getStringArray(
- R.array.auto_correction_threshold_values);
- // When autoCorrectionThreshold is greater than 1.0, it's like auto correction is off.
- double autoCorrectionThreshold = Double.MAX_VALUE;
- try {
- final int arrayIndex = Integer.valueOf(currentAutoCorrectionSetting);
- if (arrayIndex >= 0 && arrayIndex < autoCorrectionThresholdValues.length) {
- autoCorrectionThreshold = Double.parseDouble(
- autoCorrectionThresholdValues[arrayIndex]);
- }
- } catch (NumberFormatException e) {
- // Whenever the threshold settings are correct, never come here.
- autoCorrectionThreshold = Double.MAX_VALUE;
- Log.w(TAG, "Cannot load auto correction threshold setting."
- + " currentAutoCorrectionSetting: " + currentAutoCorrectionSetting
- + ", autoCorrectionThresholdValues: "
- + Arrays.toString(autoCorrectionThresholdValues));
- }
- return autoCorrectionThreshold;
- }
-
- private static SuggestedWords createSuggestPuncList(final String puncs) {
- SuggestedWords.Builder builder = new SuggestedWords.Builder();
- if (puncs != null) {
- for (int i = 0; i < puncs.length(); i++) {
- builder.addWord(puncs.subSequence(i, i + 1));
- }
- }
- return builder.setIsPunctuationSuggestions().build();
- }
-
- public static boolean isShowSettingsKeyOption(final Resources resources) {
- return resources.getBoolean(R.bool.config_enable_show_settings_key_option);
-
- }
-
- public boolean isSettingsKeyEnabled() {
- return mShowSettingsKey;
- }
-
- public boolean isVoiceKeyEnabled(EditorInfo attribute) {
- final boolean shortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled();
- final int inputType = (attribute != null) ? attribute.inputType : 0;
- return shortcutImeEnabled && mVoiceKeyEnabled
- && !InputTypeCompatUtils.isPasswordInputType(inputType);
- }
+ public static final String PREF_INPUT_LANGUAGE = "input_language";
+ public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
+ public static final String PREF_DEBUG_SETTINGS = "debug_settings";
- public boolean isVoiceKeyOnMain() {
- return mVoiceKeyOnMain;
- }
- }
+ // Dialog ids
+ private static final int VOICE_INPUT_CONFIRM_DIALOG = 0;
private PreferenceScreen mInputLanguageSelection;
private PreferenceScreen mKeypressVibrationDurationSettingsPref;
@@ -363,9 +144,9 @@ public class Settings extends InputMethodSettingsActivity
final Context context = getActivityInternal();
addPreferencesFromResource(R.xml.prefs);
- mInputLanguageSelection = (PreferenceScreen) findPreference(PREF_SUBTYPES);
+ mInputLanguageSelection = (PreferenceScreen) findPreference(PREF_SUBTYPES_SETTINGS);
mInputLanguageSelection.setOnPreferenceClickListener(this);
- mVoicePreference = (ListPreference) findPreference(PREF_VOICE_SETTINGS_KEY);
+ mVoicePreference = (ListPreference) findPreference(PREF_VOICE_MODE);
mShowSettingsKeyPreference = (CheckBoxPreference) findPreference(PREF_SHOW_SETTINGS_KEY);
mShowCorrectionSuggestionsPreference =
(ListPreference) findPreference(PREF_SHOW_SUGGESTIONS_SETTING);
@@ -373,12 +154,12 @@ public class Settings extends InputMethodSettingsActivity
prefs.registerOnSharedPreferenceChangeListener(this);
mVoiceModeOff = getString(R.string.voice_mode_off);
- mVoiceOn = !(prefs.getString(PREF_VOICE_SETTINGS_KEY, mVoiceModeOff)
+ mVoiceOn = !(prefs.getString(PREF_VOICE_MODE, mVoiceModeOff)
.equals(mVoiceModeOff));
mAutoCorrectionThresholdPreference =
(ListPreference) findPreference(PREF_AUTO_CORRECTION_THRESHOLD);
- mBigramSuggestion = (CheckBoxPreference) findPreference(PREF_BIGRAM_SUGGESTIONS);
+ mBigramSuggestion = (CheckBoxPreference) findPreference(PREF_BIGRAM_SUGGESTION);
mBigramPrediction = (CheckBoxPreference) findPreference(PREF_BIGRAM_PREDICTIONS);
mDebugSettingsPreference = findPreference(PREF_DEBUG_SETTINGS);
if (mDebugSettingsPreference != null) {
@@ -391,13 +172,13 @@ public class Settings extends InputMethodSettingsActivity
ensureConsistencyOfAutoCorrectionSettings();
final PreferenceGroup generalSettings =
- (PreferenceGroup) findPreference(PREF_GENERAL_SETTINGS_KEY);
+ (PreferenceGroup) findPreference(PREF_GENERAL_SETTINGS);
final PreferenceGroup textCorrectionGroup =
- (PreferenceGroup) findPreference(PREF_CORRECTION_SETTINGS_KEY);
+ (PreferenceGroup) findPreference(PREF_CORRECTION_SETTINGS);
final PreferenceGroup miscSettings =
- (PreferenceGroup) findPreference(PREF_MISC_SETTINGS_KEY);
+ (PreferenceGroup) findPreference(PREF_MISC_SETTINGS);
- if (!Values.isShowSettingsKeyOption(res)) {
+ if (!SettingsValues.isShowSettingsKeyOptionEnabled(res)) {
generalSettings.removePreference(mShowSettingsKeyPreference);
}
@@ -412,13 +193,13 @@ public class Settings extends InputMethodSettingsActivity
}
if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) {
- generalSettings.removePreference(findPreference(PREF_SUBTYPES));
+ generalSettings.removePreference(findPreference(PREF_SUBTYPES_SETTINGS));
}
final boolean showPopupOption = res.getBoolean(
R.bool.config_enable_show_popup_on_keypress_option);
if (!showPopupOption) {
- generalSettings.removePreference(findPreference(PREF_KEY_PREVIEW_POPUP_ON));
+ generalSettings.removePreference(findPreference(PREF_POPUP_ON));
}
final boolean showBigramSuggestionsOption = res.getBoolean(
@@ -444,7 +225,8 @@ public class Settings extends InputMethodSettingsActivity
if (null == mKeyPreviewPopupDismissDelay.getValue()) {
mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
}
- mKeyPreviewPopupDismissDelay.setEnabled(Values.isKeyPreviewPopupEnabled(prefs, res));
+ mKeyPreviewPopupDismissDelay.setEnabled(
+ SettingsValues.isKeyPreviewPopupEnabled(prefs, res));
final PreferenceScreen dictionaryLink =
(PreferenceScreen) findPreference(PREF_CONFIGURE_DICTIONARIES_KEY);
@@ -455,17 +237,26 @@ public class Settings extends InputMethodSettingsActivity
textCorrectionGroup.removePreference(dictionaryLink);
}
- final boolean showUsabilityModeStudyOption = res.getBoolean(
- R.bool.config_enable_usability_study_mode_option);
- if (!showUsabilityModeStudyOption || !ENABLE_EXPERIMENTAL_SETTINGS) {
- final Preference pref = findPreference(PREF_USABILITY_STUDY_MODE);
- if (pref != null) {
- miscSettings.removePreference(pref);
+ final boolean isResearcherPackage = LatinImeLogger.isResearcherPackage(this);
+ final boolean showUsabilityStudyModeOption =
+ res.getBoolean(R.bool.config_enable_usability_study_mode_option)
+ || isResearcherPackage || ENABLE_EXPERIMENTAL_SETTINGS;
+ final Preference usabilityStudyPref = findPreference(PREF_USABILITY_STUDY_MODE);
+ if (!showUsabilityStudyModeOption) {
+ if (usabilityStudyPref != null) {
+ miscSettings.removePreference(usabilityStudyPref);
+ }
+ }
+ if (isResearcherPackage) {
+ if (usabilityStudyPref instanceof CheckBoxPreference) {
+ CheckBoxPreference checkbox = (CheckBoxPreference)usabilityStudyPref;
+ checkbox.setChecked(prefs.getBoolean(PREF_USABILITY_STUDY_MODE, true));
+ checkbox.setSummary(R.string.settings_warning_researcher_mode);
}
}
mKeypressVibrationDurationSettingsPref =
- (PreferenceScreen) findPreference(PREF_KEYPRESS_VIBRATION_DURATION_SETTINGS);
+ (PreferenceScreen) findPreference(PREF_VIBRATION_DURATION_SETTINGS);
if (mKeypressVibrationDurationSettingsPref != null) {
mKeypressVibrationDurationSettingsPref.setOnPreferenceClickListener(
new OnPreferenceClickListener() {
@@ -521,20 +312,20 @@ public class Settings extends InputMethodSettingsActivity
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
(new BackupManager(getActivityInternal())).dataChanged();
// If turning on voice input, show dialog
- if (key.equals(PREF_VOICE_SETTINGS_KEY) && !mVoiceOn) {
- if (!prefs.getString(PREF_VOICE_SETTINGS_KEY, mVoiceModeOff)
+ if (key.equals(PREF_VOICE_MODE) && !mVoiceOn) {
+ if (!prefs.getString(PREF_VOICE_MODE, mVoiceModeOff)
.equals(mVoiceModeOff)) {
showVoiceConfirmation();
}
- } else if (key.equals(PREF_KEY_PREVIEW_POPUP_ON)) {
+ } else if (key.equals(PREF_POPUP_ON)) {
final ListPreference popupDismissDelay =
(ListPreference)findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
if (null != popupDismissDelay) {
- popupDismissDelay.setEnabled(prefs.getBoolean(PREF_KEY_PREVIEW_POPUP_ON, true));
+ popupDismissDelay.setEnabled(prefs.getBoolean(PREF_POPUP_ON, true));
}
}
ensureConsistencyOfAutoCorrectionSettings();
- mVoiceOn = !(prefs.getString(PREF_VOICE_SETTINGS_KEY, mVoiceModeOff)
+ mVoiceOn = !(prefs.getString(PREF_VOICE_MODE, mVoiceModeOff)
.equals(mVoiceModeOff));
updateVoiceModeSummary();
updateShowCorrectionSuggestionsSummary();
@@ -660,7 +451,7 @@ public class Settings extends InputMethodSettingsActivity
SharedPreferences sp, Resources res) {
if (mKeypressVibrationDurationSettingsPref != null) {
mKeypressVibrationDurationSettingsPref.setSummary(
- Utils.getCurrentVibrationDuration(sp, res)
+ SettingsValues.getCurrentVibrationDuration(sp, res)
+ res.getString(R.string.settings_ms));
}
}
@@ -676,7 +467,7 @@ public class Settings extends InputMethodSettingsActivity
public void onClick(DialogInterface dialog, int whichButton) {
final int ms = Integer.valueOf(
mKeypressVibrationDurationSettingsTextView.getText().toString());
- sp.edit().putInt(Settings.PREF_KEYPRESS_VIBRATION_DURATION_SETTINGS, ms).apply();
+ sp.edit().putInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, ms).apply();
updateKeypressVibrationDurationSettingsSummary(sp, res);
}
});
@@ -688,7 +479,7 @@ public class Settings extends InputMethodSettingsActivity
});
final View v = context.getLayoutInflater().inflate(
R.layout.vibration_settings_dialog, null);
- final int currentMs = Utils.getCurrentVibrationDuration(
+ final int currentMs = SettingsValues.getCurrentVibrationDuration(
getPreferenceManager().getSharedPreferences(), getResources());
mKeypressVibrationDurationSettingsTextView = (TextView)v.findViewById(R.id.vibration_value);
final SeekBar sb = (SeekBar)v.findViewById(R.id.vibration_settings);
@@ -717,8 +508,8 @@ public class Settings extends InputMethodSettingsActivity
private void updateKeypressSoundVolumeSummary(SharedPreferences sp, Resources res) {
if (mKeypressSoundVolumeSettingsPref != null) {
- mKeypressSoundVolumeSettingsPref.setSummary(
- String.valueOf((int)(Utils.getCurrentKeypressSoundVolume(sp, res) * 100)));
+ mKeypressSoundVolumeSettingsPref.setSummary(String.valueOf(
+ (int)(SettingsValues.getCurrentKeypressSoundVolume(sp, res) * 100)));
}
}
@@ -747,8 +538,8 @@ public class Settings extends InputMethodSettingsActivity
});
final View v = context.getLayoutInflater().inflate(
R.layout.sound_effect_volume_dialog, null);
- final int currentVolumeInt = (int)(Utils.getCurrentKeypressSoundVolume(
- getPreferenceManager().getSharedPreferences(), getResources()) * 100);
+ final int currentVolumeInt =
+ (int)(SettingsValues.getCurrentKeypressSoundVolume(sp, res) * 100);
mKeypressSoundVolumeSettingsTextView =
(TextView)v.findViewById(R.id.sound_effect_volume_value);
final SeekBar sb = (SeekBar)v.findViewById(R.id.sound_effect_volume_bar);
@@ -774,4 +565,4 @@ public class Settings extends InputMethodSettingsActivity
builder.setView(v);
builder.create().show();
}
-} \ No newline at end of file
+}
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
new file mode 100644
index 000000000..83b27f7fe
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.os.Build;
+import android.util.Log;
+import android.view.inputmethod.EditorInfo;
+
+import com.android.inputmethod.compat.InputTypeCompatUtils;
+import com.android.inputmethod.compat.VibratorCompatWrapper;
+
+import java.util.Arrays;
+import java.util.Locale;
+
+public class SettingsValues {
+ private static final String TAG = SettingsValues.class.getSimpleName();
+
+ // From resources:
+ public final int mDelayUpdateOldSuggestions;
+ public final String mMagicSpaceStrippers;
+ public final String mMagicSpaceSwappers;
+ public final String mSuggestPuncs;
+ public final SuggestedWords mSuggestPuncList;
+ private final String mSymbolsExcludedFromWordSeparators;
+ public final String mWordSeparators;
+ public final CharSequence mHintToSaveText;
+ public final boolean mUseFullScreenMode;
+
+ // From preferences, in the same order as xml/prefs.xml:
+ public final boolean mAutoCap;
+ public final boolean mVibrateOn;
+ public final boolean mSoundOn;
+ public final boolean mKeyPreviewPopupOn;
+ private final boolean mShowSettingsKey;
+ private final String mVoiceMode;
+ private final String mAutoCorrectionThresholdRawValue;
+ public final String mShowSuggestionsSetting;
+ @SuppressWarnings("unused") // TODO: Use this
+ private final boolean mUsabilityStudyMode;
+ @SuppressWarnings("unused") // TODO: Use this
+ private final String mKeyPreviewPopupDismissDelayRawValue;
+ public final boolean mUseContactsDict;
+ // Suggestion: use bigrams to adjust scores of suggestions obtained from unigram dictionary
+ public final boolean mBigramSuggestionEnabled;
+ // Prediction: use bigrams to predict the next word when there is no input for it yet
+ public final boolean mBigramPredictionEnabled;
+ public final boolean mEnableSuggestionSpanInsertion;
+ @SuppressWarnings("unused") // TODO: Use this
+ private final int mVibrationDurationSettingsRawValue;
+ @SuppressWarnings("unused") // TODO: Use this
+ private final float mKeypressSoundVolumeRawValue;
+
+ // Deduced settings
+ public final int mKeypressVibrationDuration;
+ public final float mFxVolume;
+ public final int mKeyPreviewPopupDismissDelay;
+ public final boolean mAutoCorrectEnabled;
+ public final double mAutoCorrectionThreshold;
+ private final boolean mVoiceKeyEnabled;
+ private final boolean mVoiceKeyOnMain;
+
+ public SettingsValues(final SharedPreferences prefs, final Context context,
+ final String localeStr) {
+ final Resources res = context.getResources();
+ final Locale savedLocale;
+ if (null != localeStr) {
+ final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr);
+ savedLocale = LocaleUtils.setSystemLocale(res, keyboardLocale);
+ } else {
+ savedLocale = null;
+ }
+
+ // Get the resources
+ mDelayUpdateOldSuggestions = res.getInteger(R.integer.config_delay_update_old_suggestions);
+ mMagicSpaceStrippers = res.getString(R.string.magic_space_stripping_symbols);
+ mMagicSpaceSwappers = res.getString(R.string.magic_space_swapping_symbols);
+ if (LatinImeLogger.sDBG) {
+ for (int i = 0; i < mMagicSpaceStrippers.length(); ++i) {
+ if (isMagicSpaceSwapper(mMagicSpaceStrippers.codePointAt(i))) {
+ throw new RuntimeException("Char code " + mMagicSpaceStrippers.codePointAt(i)
+ + " is both a magic space swapper and stripper.");
+ }
+ }
+ }
+ mSuggestPuncs = res.getString(R.string.suggested_punctuations);
+ // TODO: it would be nice not to recreate this each time we change the configuration
+ mSuggestPuncList = createSuggestPuncList(mSuggestPuncs);
+ mSymbolsExcludedFromWordSeparators =
+ res.getString(R.string.symbols_excluded_from_word_separators);
+ mWordSeparators = createWordSeparators(mMagicSpaceStrippers, mMagicSpaceSwappers,
+ mSymbolsExcludedFromWordSeparators, res);
+ mHintToSaveText = context.getText(R.string.hint_add_to_dictionary);
+ mUseFullScreenMode = res.getBoolean(R.bool.config_use_fullscreen_mode);
+
+ // Get the settings preferences
+ mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true);
+ mVibrateOn = isVibrateOn(context, prefs, res);
+ mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON,
+ res.getBoolean(R.bool.config_default_sound_enabled));
+ mKeyPreviewPopupOn = isKeyPreviewPopupEnabled(prefs, res);
+ mShowSettingsKey = isSettingsKeyShown(prefs, res);
+ final String voiceModeMain = res.getString(R.string.voice_mode_main);
+ final String voiceModeOff = res.getString(R.string.voice_mode_off);
+ mVoiceMode = prefs.getString(Settings.PREF_VOICE_MODE, voiceModeMain);
+ mAutoCorrectionThresholdRawValue = prefs.getString(Settings.PREF_AUTO_CORRECTION_THRESHOLD,
+ res.getString(R.string.auto_correction_threshold_mode_index_modest));
+ mShowSuggestionsSetting = prefs.getString(Settings.PREF_SHOW_SUGGESTIONS_SETTING,
+ res.getString(R.string.prefs_suggestion_visibility_default_value));
+ mUsabilityStudyMode = getUsabilityStudyMode(prefs);
+ mKeyPreviewPopupDismissDelayRawValue = prefs.getString(
+ Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
+ Integer.toString(res.getInteger(R.integer.config_delay_after_preview)));
+ mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true);
+ mAutoCorrectEnabled = isAutoCorrectEnabled(res, mAutoCorrectionThresholdRawValue);
+ mBigramSuggestionEnabled = mAutoCorrectEnabled
+ && isBigramSuggestionEnabled(prefs, res, mAutoCorrectEnabled);
+ mBigramPredictionEnabled = mBigramSuggestionEnabled
+ && isBigramPredictionEnabled(prefs, res);
+ mEnableSuggestionSpanInsertion =
+ prefs.getBoolean(Settings.PREF_KEY_ENABLE_SPAN_INSERT, true);
+ mVibrationDurationSettingsRawValue =
+ prefs.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1);
+ mKeypressSoundVolumeRawValue = prefs.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f);
+
+ // Compute other readable settings
+ mKeypressVibrationDuration = getCurrentVibrationDuration(prefs, res);
+ mFxVolume = getCurrentKeypressSoundVolume(prefs, res);
+ mKeyPreviewPopupDismissDelay = getKeyPreviewPopupDismissDelay(prefs, res);
+ mAutoCorrectionThreshold = getAutoCorrectionThreshold(res,
+ mAutoCorrectionThresholdRawValue);
+ mVoiceKeyEnabled = mVoiceMode != null && !mVoiceMode.equals(voiceModeOff);
+ mVoiceKeyOnMain = mVoiceMode != null && mVoiceMode.equals(voiceModeMain);
+
+ LocaleUtils.setSystemLocale(res, savedLocale);
+ }
+
+ // Helper functions to create member values.
+ private static SuggestedWords createSuggestPuncList(final String puncs) {
+ SuggestedWords.Builder builder = new SuggestedWords.Builder();
+ if (puncs != null) {
+ for (int i = 0; i < puncs.length(); i++) {
+ builder.addWord(puncs.subSequence(i, i + 1));
+ }
+ }
+ return builder.setIsPunctuationSuggestions().build();
+ }
+
+ private static String createWordSeparators(final String magicSpaceStrippers,
+ final String magicSpaceSwappers, final String symbolsExcludedFromWordSeparators,
+ final Resources res) {
+ String wordSeparators = magicSpaceStrippers + magicSpaceSwappers
+ + res.getString(R.string.magic_space_promoting_symbols);
+ for (int i = symbolsExcludedFromWordSeparators.length() - 1; i >= 0; --i) {
+ wordSeparators = wordSeparators.replace(
+ symbolsExcludedFromWordSeparators.substring(i, i + 1), "");
+ }
+ return wordSeparators;
+ }
+
+ private static boolean isSettingsKeyShown(final SharedPreferences prefs, final Resources res) {
+ final boolean defaultShowSettingsKey = res.getBoolean(
+ R.bool.config_default_show_settings_key);
+ return isShowSettingsKeyOptionEnabled(res)
+ ? prefs.getBoolean(Settings.PREF_SHOW_SETTINGS_KEY, defaultShowSettingsKey)
+ : defaultShowSettingsKey;
+ }
+
+ public static boolean isShowSettingsKeyOptionEnabled(final Resources resources) {
+ // TODO: Read this once and for all into a public final member
+ return resources.getBoolean(R.bool.config_enable_show_settings_key_option);
+ }
+
+ private static boolean isVibrateOn(final Context context, final SharedPreferences prefs,
+ final Resources res) {
+ final boolean hasVibrator = VibratorCompatWrapper.getInstance(context).hasVibrator();
+ return hasVibrator && prefs.getBoolean(Settings.PREF_VIBRATE_ON,
+ res.getBoolean(R.bool.config_default_vibration_enabled));
+ }
+
+ public boolean isSuggestedPunctuation(int code) {
+ return mSuggestPuncs.contains(String.valueOf((char)code));
+ }
+
+ public boolean isWordSeparator(int code) {
+ return mWordSeparators.contains(String.valueOf((char)code));
+ }
+
+ public boolean isSymbolExcludedFromWordSeparators(int code) {
+ return mSymbolsExcludedFromWordSeparators.contains(String.valueOf((char)code));
+ }
+
+ public boolean isMagicSpaceStripper(int code) {
+ return mMagicSpaceStrippers.contains(String.valueOf((char)code));
+ }
+
+ public boolean isMagicSpaceSwapper(int code) {
+ return mMagicSpaceSwappers.contains(String.valueOf((char)code));
+ }
+
+ private static boolean isAutoCorrectEnabled(final Resources resources,
+ final String currentAutoCorrectionSetting) {
+ final String autoCorrectionOff = resources.getString(
+ R.string.auto_correction_threshold_mode_index_off);
+ return !currentAutoCorrectionSetting.equals(autoCorrectionOff);
+ }
+
+ // Public to access from KeyboardSwitcher. Should it have access to some
+ // process-global instance instead?
+ public static boolean isKeyPreviewPopupEnabled(SharedPreferences sp, Resources resources) {
+ final boolean showPopupOption = resources.getBoolean(
+ R.bool.config_enable_show_popup_on_keypress_option);
+ if (!showPopupOption) return resources.getBoolean(R.bool.config_default_popup_preview);
+ return sp.getBoolean(Settings.PREF_POPUP_ON,
+ resources.getBoolean(R.bool.config_default_popup_preview));
+ }
+
+ // Likewise
+ public static int getKeyPreviewPopupDismissDelay(SharedPreferences sp,
+ Resources resources) {
+ // TODO: use mKeyPreviewPopupDismissDelayRawValue instead of reading it again here.
+ return Integer.parseInt(sp.getString(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
+ Integer.toString(resources.getInteger(R.integer.config_delay_after_preview))));
+ }
+
+ private static boolean isBigramSuggestionEnabled(final SharedPreferences sp,
+ final Resources resources, final boolean autoCorrectEnabled) {
+ final boolean showBigramSuggestionsOption = resources.getBoolean(
+ R.bool.config_enable_bigram_suggestions_option);
+ if (!showBigramSuggestionsOption) {
+ return autoCorrectEnabled;
+ }
+ return sp.getBoolean(Settings.PREF_BIGRAM_SUGGESTION, resources.getBoolean(
+ R.bool.config_default_bigram_suggestions));
+ }
+
+ private static boolean isBigramPredictionEnabled(final SharedPreferences sp,
+ final Resources resources) {
+ return sp.getBoolean(Settings.PREF_BIGRAM_PREDICTIONS, resources.getBoolean(
+ R.bool.config_default_bigram_prediction));
+ }
+
+ private static double getAutoCorrectionThreshold(final Resources resources,
+ final String currentAutoCorrectionSetting) {
+ final String[] autoCorrectionThresholdValues = resources.getStringArray(
+ R.array.auto_correction_threshold_values);
+ // When autoCorrectionThreshold is greater than 1.0, it's like auto correction is off.
+ double autoCorrectionThreshold = Double.MAX_VALUE;
+ try {
+ final int arrayIndex = Integer.valueOf(currentAutoCorrectionSetting);
+ if (arrayIndex >= 0 && arrayIndex < autoCorrectionThresholdValues.length) {
+ autoCorrectionThreshold = Double.parseDouble(
+ autoCorrectionThresholdValues[arrayIndex]);
+ }
+ } catch (NumberFormatException e) {
+ // Whenever the threshold settings are correct, never come here.
+ autoCorrectionThreshold = Double.MAX_VALUE;
+ Log.w(TAG, "Cannot load auto correction threshold setting."
+ + " currentAutoCorrectionSetting: " + currentAutoCorrectionSetting
+ + ", autoCorrectionThresholdValues: "
+ + Arrays.toString(autoCorrectionThresholdValues));
+ }
+ return autoCorrectionThreshold;
+ }
+
+ public boolean isSettingsKeyEnabled() {
+ return mShowSettingsKey;
+ }
+
+ public boolean isVoiceKeyEnabled(final EditorInfo editorInfo) {
+ final boolean shortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled();
+ final int inputType = (editorInfo != null) ? editorInfo.inputType : 0;
+ return shortcutImeEnabled && mVoiceKeyEnabled
+ && !InputTypeCompatUtils.isPasswordInputType(inputType);
+ }
+
+ public boolean isVoiceKeyOnMain() {
+ return mVoiceKeyOnMain;
+ }
+
+ // Accessed from the settings interface, hence public
+ public static float getCurrentKeypressSoundVolume(final SharedPreferences sp,
+ final Resources res) {
+ // TODO: use mVibrationDurationSettingsRawValue instead of reading it again here
+ final float volume = sp.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f);
+ if (volume >= 0) {
+ return volume;
+ }
+
+ final String[] volumePerHardwareList = res.getStringArray(R.array.keypress_volumes);
+ final String hardwarePrefix = Build.HARDWARE + ",";
+ for (final String element : volumePerHardwareList) {
+ if (element.startsWith(hardwarePrefix)) {
+ return Float.parseFloat(element.substring(element.lastIndexOf(',') + 1));
+ }
+ }
+ return -1.0f;
+ }
+
+ // Likewise
+ public static int getCurrentVibrationDuration(final SharedPreferences sp,
+ final Resources res) {
+ // TODO: use mKeypressVibrationDuration instead of reading it again here
+ final int ms = sp.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1);
+ if (ms >= 0) {
+ return ms;
+ }
+ final String[] durationPerHardwareList = res.getStringArray(
+ R.array.keypress_vibration_durations);
+ final String hardwarePrefix = Build.HARDWARE + ",";
+ for (final String element : durationPerHardwareList) {
+ if (element.startsWith(hardwarePrefix)) {
+ return (int)Long.parseLong(element.substring(element.lastIndexOf(',') + 1));
+ }
+ }
+ return -1;
+ }
+
+ // Likewise
+ public static boolean getUsabilityStudyMode(final SharedPreferences prefs) {
+ // TODO: use mUsabilityStudyMode instead of reading it again here
+ return prefs.getBoolean(Settings.PREF_USABILITY_STUDY_MODE, true);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 8a4862094..42111822d 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -35,7 +35,6 @@ import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper;
import com.android.inputmethod.deprecated.VoiceProxy;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import com.android.inputmethod.keyboard.LatinKeyboard;
import java.util.ArrayList;
import java.util.Arrays;
@@ -421,11 +420,7 @@ public class SubtypeSwitcher {
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
mIsNetworkConnected = !noConnection;
- final KeyboardSwitcher switcher = KeyboardSwitcher.getInstance();
- final LatinKeyboard keyboard = switcher.getLatinKeyboard();
- if (keyboard != null) {
- keyboard.updateShortcutKey(isShortcutImeReady(), switcher.getKeyboardView());
- }
+ KeyboardSwitcher.getInstance().onNetworkStateChanged();
}
//////////////////////////////////
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index caa5aac51..e9ca390d3 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
+import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.ProximityInfo;
import java.io.File;
@@ -42,9 +43,8 @@ public class Suggest implements Dictionary.WordCallback {
public static final int APPROX_MAX_WORD_LENGTH = 32;
public static final int CORRECTION_NONE = 0;
- public static final int CORRECTION_BASIC = 1;
- public static final int CORRECTION_FULL = 2;
- public static final int CORRECTION_FULL_BIGRAM = 3;
+ public static final int CORRECTION_FULL = 1;
+ public static final int CORRECTION_FULL_BIGRAM = 2;
/**
* Words that appear in both bigram and unigram data gets multiplier ranging from
@@ -101,13 +101,12 @@ public class Suggest implements Dictionary.WordCallback {
private ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>();
ArrayList<CharSequence> mBigramSuggestions = new ArrayList<CharSequence>();
- private CharSequence mTypedWord;
+ private CharSequence mConsideredWord;
// TODO: Remove these member variables by passing more context to addWord() callback method
private boolean mIsFirstCharCapitalized;
private boolean mIsAllUpperCase;
-
- private int mCorrectionMode = CORRECTION_BASIC;
+ private int mTrailingSingleQuotesCount;
public Suggest(final Context context, final int dictionaryResId, final Locale locale) {
initAsynchronously(context, dictionaryResId, locale);
@@ -144,7 +143,7 @@ public class Suggest implements Dictionary.WordCallback {
initWhitelistAndAutocorrectAndPool(context, locale);
}
- private void addOrReplaceDictionary(Map<String, Dictionary> dictionaries, String key,
+ private static void addOrReplaceDictionary(Map<String, Dictionary> dictionaries, String key,
Dictionary dict) {
final Dictionary oldDict = (dict == null)
? dictionaries.remove(key)
@@ -169,14 +168,6 @@ public class Suggest implements Dictionary.WordCallback {
}.start();
}
- public int getCorrectionMode() {
- return mCorrectionMode;
- }
-
- public void setCorrectionMode(int mode) {
- mCorrectionMode = mode;
- }
-
// The main dictionary could have been loaded asynchronously. Don't cache the return value
// of this method.
public boolean hasMainDictionary() {
@@ -255,9 +246,10 @@ public class Suggest implements Dictionary.WordCallback {
* @return suggested words object.
*/
public SuggestedWords getSuggestions(final WordComposer wordComposer,
- final CharSequence prevWordForBigram, final ProximityInfo proximityInfo) {
+ final CharSequence prevWordForBigram, final ProximityInfo proximityInfo,
+ final int correctionMode) {
return getSuggestedWordBuilder(wordComposer, prevWordForBigram,
- proximityInfo).build();
+ proximityInfo, correctionMode).build();
}
private CharSequence capitalizeWord(boolean all, boolean first, CharSequence word) {
@@ -290,25 +282,27 @@ public class Suggest implements Dictionary.WordCallback {
// TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder
public SuggestedWords.Builder getSuggestedWordBuilder(
final WordComposer wordComposer, CharSequence prevWordForBigram,
- final ProximityInfo proximityInfo) {
+ final ProximityInfo proximityInfo, final int correctionMode) {
LatinImeLogger.onStartSuggestion(prevWordForBigram);
mAutoCorrection.init();
mIsFirstCharCapitalized = wordComposer.isFirstCharCapitalized();
mIsAllUpperCase = wordComposer.isAllUpperCase();
+ mTrailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount();
collectGarbage(mSuggestions, mPrefMaxSuggestions);
Arrays.fill(mScores, 0);
- // Save a lowercase version of the original word
- String typedWord = wordComposer.getTypedWord();
+ final String typedWord = wordComposer.getTypedWord();
+ final String consideredWord = mTrailingSingleQuotesCount > 0
+ ? typedWord.substring(0, typedWord.length() - mTrailingSingleQuotesCount)
+ : typedWord;
if (typedWord != null) {
// Treating USER_TYPED as UNIGRAM suggestion for logging now.
LatinImeLogger.onAddSuggestedWord(typedWord, Suggest.DIC_USER_TYPED,
Dictionary.DataType.UNIGRAM);
}
- mTypedWord = typedWord;
+ mConsideredWord = consideredWord;
- if (wordComposer.size() <= 1 && (mCorrectionMode == CORRECTION_FULL_BIGRAM
- || mCorrectionMode == CORRECTION_BASIC)) {
+ if (wordComposer.size() <= 1 && (correctionMode == CORRECTION_FULL_BIGRAM)) {
// At first character typed, search only the bigrams
Arrays.fill(mBigramScores, 0);
collectGarbage(mBigramSuggestions, PREF_MAX_BIGRAMS);
@@ -321,7 +315,7 @@ public class Suggest implements Dictionary.WordCallback {
for (final Dictionary dictionary : mBigramDictionaries.values()) {
dictionary.getBigrams(wordComposer, prevWordForBigram, this);
}
- if (TextUtils.isEmpty(typedWord)) {
+ if (TextUtils.isEmpty(consideredWord)) {
// Nothing entered: return all bigrams for the previous word
int insertCount = Math.min(mBigramSuggestions.size(), mPrefMaxSuggestions);
for (int i = 0; i < insertCount; ++i) {
@@ -330,7 +324,7 @@ public class Suggest implements Dictionary.WordCallback {
} else {
// Word entered: return only bigrams that match the first char of the typed word
@SuppressWarnings("null")
- final char currentChar = typedWord.charAt(0);
+ final char currentChar = consideredWord.charAt(0);
// TODO: Must pay attention to locale when changing case.
final char currentCharUpper = Character.toUpperCase(currentChar);
int count = 0;
@@ -354,24 +348,41 @@ public class Suggest implements Dictionary.WordCallback {
if (key.equals(DICT_KEY_USER_UNIGRAM) || key.equals(DICT_KEY_WHITELIST))
continue;
final Dictionary dictionary = mUnigramDictionaries.get(key);
- dictionary.getWords(wordComposer, this, proximityInfo);
+ if (mTrailingSingleQuotesCount > 0) {
+ final WordComposer tmpWordComposer = new WordComposer(wordComposer);
+ for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) {
+ tmpWordComposer.deleteLast();
+ }
+ dictionary.getWords(tmpWordComposer, this, proximityInfo);
+ } else {
+ dictionary.getWords(wordComposer, this, proximityInfo);
+ }
}
}
- final String typedWordString = typedWord == null ? null : typedWord.toString();
+ final String consideredWordString =
+ consideredWord == null ? null : consideredWord.toString();
CharSequence whitelistedWord = capitalizeWord(mIsAllUpperCase, mIsFirstCharCapitalized,
- mWhiteListDictionary.getWhitelistedWord(typedWordString));
+ mWhiteListDictionary.getWhitelistedWord(consideredWordString));
mAutoCorrection.updateAutoCorrectionStatus(mUnigramDictionaries, wordComposer,
- mSuggestions, mScores, typedWord, mAutoCorrectionThreshold, mCorrectionMode,
+ mSuggestions, mScores, consideredWord, mAutoCorrectionThreshold, correctionMode,
whitelistedWord);
if (whitelistedWord != null) {
- mSuggestions.add(0, whitelistedWord);
+ if (mTrailingSingleQuotesCount > 0) {
+ final StringBuilder sb = new StringBuilder(whitelistedWord);
+ for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) {
+ sb.appendCodePoint(Keyboard.CODE_SINGLE_QUOTE);
+ }
+ mSuggestions.add(0, sb.toString());
+ } else {
+ mSuggestions.add(0, whitelistedWord);
+ }
}
if (typedWord != null) {
- mSuggestions.add(0, typedWordString);
+ mSuggestions.add(0, typedWord.toString());
}
Utils.removeDupes(mSuggestions);
@@ -424,7 +435,7 @@ public class Suggest implements Dictionary.WordCallback {
int pos = 0;
// Check if it's the same word, only caps are different
- if (Utils.equalsIgnoreCase(mTypedWord, word, offset, length)) {
+ if (Utils.equalsIgnoreCase(mConsideredWord, word, offset, length)) {
// TODO: remove this surrounding if clause and move this logic to
// getSuggestedWordBuilder.
if (suggestions.size() > 0) {
@@ -486,6 +497,9 @@ public class Suggest implements Dictionary.WordCallback {
} else {
sb.append(word, offset, length);
}
+ for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) {
+ sb.appendCodePoint(Keyboard.CODE_SINGLE_QUOTE);
+ }
suggestions.add(pos, sb);
if (suggestions.size() > prefMaxSuggestions) {
final CharSequence garbage = suggestions.remove(prefMaxSuggestions);
@@ -518,7 +532,8 @@ public class Suggest implements Dictionary.WordCallback {
return -1;
}
- private void collectGarbage(ArrayList<CharSequence> suggestions, int prefMaxSuggestions) {
+ private static void collectGarbage(ArrayList<CharSequence> suggestions,
+ int prefMaxSuggestions) {
int poolSize = StringBuilderPool.getSize();
int garbageSize = suggestions.size();
while (poolSize < prefMaxSuggestions && garbageSize > 0) {
diff --git a/java/src/com/android/inputmethod/latin/TextEntryState.java b/java/src/com/android/inputmethod/latin/TextEntryState.java
deleted file mode 100644
index 79b3bdebb..000000000
--- a/java/src/com/android/inputmethod/latin/TextEntryState.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.latin;
-
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.latin.Utils.RingCharBuffer;
-
-import android.util.Log;
-
-public class TextEntryState {
- private static final String TAG = TextEntryState.class.getSimpleName();
- private static final boolean DEBUG = false;
-
- private static final int UNKNOWN = 0;
- private static final int START = 1;
- private static final int IN_WORD = 2;
- private static final int ACCEPTED_DEFAULT = 3;
- private static final int PICKED_SUGGESTION = 4;
- private static final int PUNCTUATION_AFTER_WORD = 5;
- private static final int PUNCTUATION_AFTER_ACCEPTED = 6;
- private static final int SPACE_AFTER_ACCEPTED = 7;
- private static final int SPACE_AFTER_PICKED = 8;
- private static final int UNDO_COMMIT = 9;
- private static final int RECORRECTING = 10;
- private static final int PICKED_RECORRECTION = 11;
-
- private static int sState = UNKNOWN;
- private static int sPreviousState = UNKNOWN;
-
- private static void setState(final int newState) {
- sPreviousState = sState;
- sState = newState;
- }
-
- public static void acceptedDefault(CharSequence typedWord, CharSequence actualWord,
- int separatorCode) {
- if (typedWord == null) return;
- setState(ACCEPTED_DEFAULT);
- LatinImeLogger.logOnAutoCorrection(
- typedWord.toString(), actualWord.toString(), separatorCode);
- if (DEBUG)
- displayState("acceptedDefault", "typedWord", typedWord, "actualWord", actualWord);
- }
-
- // State.ACCEPTED_DEFAULT will be changed to other sub-states
- // (see "case ACCEPTED_DEFAULT" in typedCharacter() below),
- // and should be restored back to State.ACCEPTED_DEFAULT after processing for each sub-state.
- public static void backToAcceptedDefault(CharSequence typedWord) {
- if (typedWord == null) return;
- switch (sState) {
- case SPACE_AFTER_ACCEPTED:
- case PUNCTUATION_AFTER_ACCEPTED:
- case IN_WORD:
- setState(ACCEPTED_DEFAULT);
- break;
- default:
- break;
- }
- if (DEBUG) displayState("backToAcceptedDefault", "typedWord", typedWord);
- }
-
- public static void acceptedTyped(CharSequence typedWord) {
- setState(PICKED_SUGGESTION);
- if (DEBUG) displayState("acceptedTyped", "typedWord", typedWord);
- }
-
- public static void acceptedSuggestion(CharSequence typedWord, CharSequence actualWord) {
- if (sState == RECORRECTING || sState == PICKED_RECORRECTION) {
- setState(PICKED_RECORRECTION);
- } else {
- setState(PICKED_SUGGESTION);
- }
- if (DEBUG)
- displayState("acceptedSuggestion", "typedWord", typedWord, "actualWord", actualWord);
- }
-
- public static void selectedForRecorrection() {
- setState(RECORRECTING);
- if (DEBUG) displayState("selectedForRecorrection");
- }
-
- public static void onAbortRecorrection() {
- if (sState == RECORRECTING || sState == PICKED_RECORRECTION) {
- setState(START);
- }
- if (DEBUG) displayState("onAbortRecorrection");
- }
-
- public static void typedCharacter(char c, boolean isSeparator, int x, int y) {
- final boolean isSpace = (c == Keyboard.CODE_SPACE);
- switch (sState) {
- case IN_WORD:
- if (isSpace || isSeparator) {
- setState(START);
- } else {
- // State hasn't changed.
- }
- break;
- case ACCEPTED_DEFAULT:
- case SPACE_AFTER_PICKED:
- case PUNCTUATION_AFTER_ACCEPTED:
- if (isSpace) {
- setState(SPACE_AFTER_ACCEPTED);
- } else if (isSeparator) {
- // Swap
- setState(PUNCTUATION_AFTER_ACCEPTED);
- } else {
- setState(IN_WORD);
- }
- break;
- case PICKED_SUGGESTION:
- case PICKED_RECORRECTION:
- if (isSpace) {
- setState(SPACE_AFTER_PICKED);
- } else if (isSeparator) {
- // Swap
- setState(PUNCTUATION_AFTER_ACCEPTED);
- } else {
- setState(IN_WORD);
- }
- break;
- case START:
- case UNKNOWN:
- case SPACE_AFTER_ACCEPTED:
- case PUNCTUATION_AFTER_WORD:
- if (!isSpace && !isSeparator) {
- setState(IN_WORD);
- } else {
- setState(START);
- }
- break;
- case UNDO_COMMIT:
- if (isSpace || isSeparator) {
- setState(START);
- } else {
- setState(IN_WORD);
- }
- break;
- case RECORRECTING:
- setState(START);
- break;
- }
- RingCharBuffer.getInstance().push(c, x, y);
- if (isSeparator) {
- LatinImeLogger.logOnInputSeparator();
- } else {
- LatinImeLogger.logOnInputChar();
- }
- if (DEBUG) displayState("typedCharacter", "char", c, "isSeparator", isSeparator);
- }
-
- public static void backspace() {
- if (sState == ACCEPTED_DEFAULT) {
- setState(UNDO_COMMIT);
- LatinImeLogger.logOnAutoCorrectionCancelled();
- } else if (sState == UNDO_COMMIT) {
- setState(IN_WORD);
- }
- if (DEBUG) displayState("backspace");
- }
-
- public static void reset() {
- setState(START);
- if (DEBUG) displayState("reset");
- }
-
- public static boolean isAcceptedDefault() {
- return sState == ACCEPTED_DEFAULT;
- }
-
- public static boolean isSpaceAfterPicked() {
- return sState == SPACE_AFTER_PICKED;
- }
-
- public static boolean isUndoCommit() {
- return sState == UNDO_COMMIT;
- }
-
- public static boolean isPunctuationAfterAccepted() {
- return sState == PUNCTUATION_AFTER_ACCEPTED;
- }
-
- public static boolean isRecorrecting() {
- return sState == RECORRECTING || sState == PICKED_RECORRECTION;
- }
-
- public static String getState() {
- return stateName(sState);
- }
-
- private static String stateName(int state) {
- switch (state) {
- case START: return "START";
- case IN_WORD: return "IN_WORD";
- case ACCEPTED_DEFAULT: return "ACCEPTED_DEFAULT";
- case PICKED_SUGGESTION: return "PICKED_SUGGESTION";
- case PUNCTUATION_AFTER_WORD: return "PUNCTUATION_AFTER_WORD";
- case PUNCTUATION_AFTER_ACCEPTED: return "PUNCTUATION_AFTER_ACCEPTED";
- case SPACE_AFTER_ACCEPTED: return "SPACE_AFTER_ACCEPTED";
- case SPACE_AFTER_PICKED: return "SPACE_AFTER_PICKED";
- case UNDO_COMMIT: return "UNDO_COMMIT";
- case RECORRECTING: return "RECORRECTING";
- case PICKED_RECORRECTION: return "PICKED_RECORRECTION";
- default: return "UNKNOWN";
- }
- }
-
- private static void displayState(String title, Object ... args) {
- final StringBuilder sb = new StringBuilder(title);
- sb.append(':');
- for (int i = 0; i < args.length; i += 2) {
- sb.append(' ');
- sb.append(args[i]);
- sb.append('=');
- sb.append(args[i+1].toString());
- }
- sb.append(" state=");
- sb.append(stateName(sState));
- sb.append(" previous=");
- sb.append(stateName(sPreviousState));
- Log.d(TAG, sb.toString());
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
index 9e656675e..f80534cb5 100644
--- a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
@@ -159,7 +159,7 @@ public class UserBigramDictionary extends ExpandableDictionary {
*/
public int addBigrams(String word1, String word2) {
// remove caps if second word is autocapitalized
- if (mIme != null && mIme.getCurrentWord().isAutoCapitalized()) {
+ if (mIme != null && mIme.isAutoCapitalized()) {
word2 = Character.toLowerCase(word2.charAt(0)) + word2.substring(1);
}
// Do not insert a word as a bigram of itself
@@ -238,7 +238,7 @@ public class UserBigramDictionary extends ExpandableDictionary {
/**
* Query the database
*/
- private Cursor query(String selection, String[] selectionArgs) {
+ private static Cursor query(String selection, String[] selectionArgs) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
// main INNER JOIN frequency ON (main._id=freq.pair_id)
@@ -310,7 +310,7 @@ public class UserBigramDictionary extends ExpandableDictionary {
}
/** Prune any old data if the database is getting too big. */
- private void checkPruneData(SQLiteDatabase db) {
+ private static void checkPruneData(SQLiteDatabase db) {
db.execSQL("PRAGMA foreign_keys = ON;");
Cursor c = db.query(FREQ_TABLE_NAME, new String[] { FREQ_COLUMN_PAIR_ID },
null, null, null, null, null);
@@ -380,7 +380,7 @@ public class UserBigramDictionary extends ExpandableDictionary {
return null;
}
- private ContentValues getContentValues(String word1, String word2, String locale) {
+ private static ContentValues getContentValues(String word1, String word2, String locale) {
ContentValues values = new ContentValues(3);
values.put(MAIN_COLUMN_WORD1, word1);
values.put(MAIN_COLUMN_WORD2, word2);
@@ -388,7 +388,7 @@ public class UserBigramDictionary extends ExpandableDictionary {
return values;
}
- private ContentValues getFrequencyContentValues(int pairId, int frequency) {
+ private static ContentValues getFrequencyContentValues(int pairId, int frequency) {
ContentValues values = new ContentValues(2);
values.put(FREQ_COLUMN_PAIR_ID, pairId);
values.put(FREQ_COLUMN_FREQUENCY, frequency);
diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java
index 0bbbf3995..6d6296e10 100644
--- a/java/src/com/android/inputmethod/latin/UserDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserDictionary.java
@@ -18,12 +18,10 @@ package com.android.inputmethod.latin;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
-import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
-import android.net.Uri;
-import android.os.RemoteException;
import android.provider.UserDictionary.Words;
import android.text.TextUtils;
@@ -38,11 +36,9 @@ public class UserDictionary extends ExpandableDictionary {
Words.FREQUENCY,
};
- private static final String[] PROJECTION_ADD = {
- Words._ID,
- Words.FREQUENCY,
- Words.LOCALE,
- };
+ // This is not exported by the framework so we pretty much have to write it here verbatim
+ private static final String ACTION_USER_DICTIONARY_INSERT =
+ "com.android.settings.USER_DICTIONARY_INSERT";
private ContentObserver mObserver;
final private String mLocale;
@@ -134,7 +130,11 @@ public class UserDictionary extends ExpandableDictionary {
final Cursor cursor = getContext().getContentResolver()
.query(Words.CONTENT_URI, PROJECTION_QUERY, request.toString(),
requestArguments, null);
- addWords(cursor);
+ try {
+ addWords(cursor);
+ } finally {
+ if (null != cursor) cursor.close();
+ }
}
public boolean isEnabled() {
@@ -160,54 +160,19 @@ public class UserDictionary extends ExpandableDictionary {
public synchronized void addWord(final String word, final int frequency) {
// Force load the dictionary here synchronously
if (getRequiresReload()) loadDictionaryAsync();
+ // TODO: do something for the UI. With the following, any sufficiently long word will
+ // look like it will go to the user dictionary but it won't.
// Safeguard against adding long words. Can cause stack overflow.
if (word.length() >= getMaxWordLength()) return;
super.addWord(word, frequency);
- // Update the user dictionary provider
- final ContentValues values = new ContentValues(5);
- values.put(Words.WORD, word);
- values.put(Words.FREQUENCY, frequency);
- values.put(Words.LOCALE, mLocale);
- values.put(Words.APP_ID, 0);
-
- final ContentResolver contentResolver = getContext().getContentResolver();
- final ContentProviderClient client =
- contentResolver.acquireContentProviderClient(Words.CONTENT_URI);
- if (null == client) return;
- new Thread("addWord") {
- @Override
- public void run() {
- Cursor cursor = null;
- try {
- cursor = client.query(Words.CONTENT_URI, PROJECTION_ADD,
- "word=? and ((locale IS NULL) or (locale=?))",
- new String[] { word, mLocale }, null);
- if (cursor != null && cursor.moveToFirst()) {
- final String locale = cursor.getString(cursor.getColumnIndex(Words.LOCALE));
- // If locale is null, we will not override the entry.
- if (locale != null && locale.equals(mLocale.toString())) {
- final long id = cursor.getLong(cursor.getColumnIndex(Words._ID));
- final Uri uri =
- Uri.withAppendedPath(Words.CONTENT_URI, Long.toString(id));
- // Update the entry with new frequency value.
- client.update(uri, values, null, null);
- }
- } else {
- // Insert new entry.
- client.insert(Words.CONTENT_URI, values);
- }
- } catch (RemoteException e) {
- // If we come here, the activity is already about to be killed, and we
- // have no means of contacting the content provider any more.
- // See ContentResolver#insert, inside the catch(){}
- } finally {
- if (null != cursor) cursor.close();
- client.release();
- }
- }
- }.start();
+ // TODO: Add an argument to the intent to specify the frequency.
+ Intent intent = new Intent(ACTION_USER_DICTIONARY_INSERT);
+ intent.putExtra(Words.WORD, word);
+ intent.putExtra(Words.LOCALE, mLocale);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getContext().startActivity(intent);
// In case the above does a synchronous callback of the change observer
setRequiresReload(false);
@@ -242,6 +207,5 @@ public class UserDictionary extends ExpandableDictionary {
cursor.moveToNext();
}
}
- cursor.close();
}
}
diff --git a/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java b/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java
index e41230b3c..a7f57ae46 100644
--- a/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java
@@ -149,7 +149,7 @@ public class UserUnigramDictionary extends ExpandableDictionary {
final int length = word.length();
// Don't add very short or very long words.
if (length < 2 || length > getMaxWordLength()) return;
- if (mIme.getCurrentWord().isAutoCapitalized()) {
+ if (mIme.isAutoCapitalized()) {
// Remove caps before adding
word = Character.toLowerCase(word.charAt(0)) + word.substring(1);
}
@@ -172,7 +172,7 @@ public class UserUnigramDictionary extends ExpandableDictionary {
// Nothing pending? Return
if (mPendingWrites.isEmpty()) return;
// Create a background thread to write the pending entries
- new UpdateDbTask(getContext(), sOpenHelper, mPendingWrites, mLocale).execute();
+ new UpdateDbTask(sOpenHelper, mPendingWrites, mLocale).execute();
// Create a new map for writing new entries into while the old one is written to db
mPendingWrites = new HashMap<String, Integer>();
}
@@ -206,7 +206,7 @@ public class UserUnigramDictionary extends ExpandableDictionary {
}
}
- private Cursor query(String selection, String[] selectionArgs) {
+ private static Cursor query(String selection, String[] selectionArgs) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(USER_UNIGRAM_DICT_TABLE_NAME);
qb.setProjectionMap(sDictProjectionMap);
@@ -227,8 +227,8 @@ public class UserUnigramDictionary extends ExpandableDictionary {
private final DatabaseHelper mDbHelper;
private final String mLocale;
- public UpdateDbTask(@SuppressWarnings("unused") Context context, DatabaseHelper openHelper,
- HashMap<String, Integer> pendingWrites, String locale) {
+ public UpdateDbTask(DatabaseHelper openHelper, HashMap<String, Integer> pendingWrites,
+ String locale) {
mMap = pendingWrites;
mLocale = locale;
mDbHelper = openHelper;
@@ -251,7 +251,7 @@ public class UserUnigramDictionary extends ExpandableDictionary {
return null;
}
- private ContentValues getContentValues(String word, int frequency, String locale) {
+ private static ContentValues getContentValues(String word, int frequency, String locale) {
ContentValues values = new ContentValues(4);
values.put(COLUMN_WORD, word);
values.put(COLUMN_FREQUENCY, frequency);
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index b29ff1975..38148438b 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -16,12 +16,22 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.compat.InputMethodInfoCompatWrapper;
+import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
+import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper;
+import com.android.inputmethod.compat.InputTypeCompatUtils;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.latin.define.JniLibName;
+
import android.content.Context;
-import android.content.SharedPreferences;
+import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.inputmethodservice.InputMethodService;
+import android.net.Uri;
import android.os.AsyncTask;
-import android.os.Build;
+import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
@@ -31,20 +41,15 @@ import android.text.format.DateUtils;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
-import com.android.inputmethod.compat.InputMethodInfoCompatWrapper;
-import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
-import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper;
-import com.android.inputmethod.compat.InputTypeCompatUtils;
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.KeyboardId;
-
import java.io.BufferedReader;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
+import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
@@ -113,8 +118,9 @@ public class Utils {
}
public static boolean hasMultipleEnabledIMEsOrSubtypes(
- final InputMethodManagerCompatWrapper imm,
final boolean shouldIncludeAuxiliarySubtypes) {
+ final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance();
+ if (imm == null) return false;
final List<InputMethodInfoCompatWrapper> enabledImis = imm.getEnabledInputMethodList();
// Number of the filtered IMEs
@@ -185,7 +191,8 @@ public class Utils {
final int typedWordLength = typedWord.length();
final int maxEditDistanceOfNativeDictionary =
(typedWordLength < 5 ? 2 : typedWordLength / 2) + 1;
- final int distance = Utils.editDistance(typedWord, suggestionWord);
+ final int distance = BinaryDictionary.editDistance(
+ typedWord.toString(), suggestionWord.toString());
if (DBG) {
Log.d(TAG, "Autocorrected edit distance = " + distance
+ ", " + maxEditDistanceOfNativeDictionary);
@@ -242,7 +249,7 @@ public class Utils {
UsabilityStudyLogUtils.getInstance().init(context);
return sRingCharBuffer;
}
- private int normalize(int in) {
+ private static int normalize(int in) {
int ret = in % BUFSIZE;
return ret < 0 ? ret + BUFSIZE : ret;
}
@@ -317,49 +324,6 @@ public class Utils {
}
}
-
- /* Damerau-Levenshtein distance */
- public static int editDistance(CharSequence s, CharSequence t) {
- if (s == null || t == null) {
- throw new IllegalArgumentException("editDistance: Arguments should not be null.");
- }
- final int sl = s.length();
- final int tl = t.length();
- int[][] dp = new int [sl + 1][tl + 1];
- for (int i = 0; i <= sl; i++) {
- dp[i][0] = i;
- }
- for (int j = 0; j <= tl; j++) {
- dp[0][j] = j;
- }
- for (int i = 0; i < sl; ++i) {
- for (int j = 0; j < tl; ++j) {
- final char sc = Character.toLowerCase(s.charAt(i));
- final char tc = Character.toLowerCase(t.charAt(j));
- final int cost = sc == tc ? 0 : 1;
- dp[i + 1][j + 1] = Math.min(
- dp[i][j + 1] + 1, Math.min(dp[i + 1][j] + 1, dp[i][j] + cost));
- // Overwrite for transposition cases
- if (i > 0 && j > 0
- && sc == Character.toLowerCase(t.charAt(j - 1))
- && tc == Character.toLowerCase(s.charAt(i - 1))) {
- dp[i + 1][j + 1] = Math.min(dp[i + 1][j + 1], dp[i - 1][j - 1] + cost);
- }
- }
- }
- if (DBG_EDIT_DISTANCE) {
- Log.d(TAG, "editDistance:" + s + "," + t);
- for (int i = 0; i < dp.length; ++i) {
- StringBuffer sb = new StringBuffer();
- for (int j = 0; j < dp[i].length; ++j) {
- sb.append(dp[i][j]).append(',');
- }
- Log.d(TAG, i + ":" + sb.toString());
- }
- }
- return dp[sl][tl];
- }
-
// Get the current stack trace
public static String getStackTrace() {
StringBuilder sb = new StringBuilder();
@@ -373,55 +337,6 @@ public class Utils {
return sb.toString();
}
- // In dictionary.cpp, getSuggestion() method,
- // suggestion scores are computed using the below formula.
- // original score
- // := pow(mTypedLetterMultiplier (this is defined 2),
- // (the number of matched characters between typed word and suggested word))
- // * (individual word's score which defined in the unigram dictionary,
- // and this score is defined in range [0, 255].)
- // Then, the following processing is applied.
- // - If the dictionary word is matched up to the point of the user entry
- // (full match up to min(before.length(), after.length())
- // => Then multiply by FULL_MATCHED_WORDS_PROMOTION_RATE (this is defined 1.2)
- // - If the word is a true full match except for differences in accents or
- // capitalization, then treat it as if the score was 255.
- // - If before.length() == after.length()
- // => multiply by mFullWordMultiplier (this is defined 2))
- // So, maximum original score is pow(2, min(before.length(), after.length())) * 255 * 2 * 1.2
- // For historical reasons we ignore the 1.2 modifier (because the measure for a good
- // autocorrection threshold was done at a time when it didn't exist). This doesn't change
- // the result.
- // So, we can normalize original score by dividing pow(2, min(b.l(),a.l())) * 255 * 2.
- private static final int MAX_INITIAL_SCORE = 255;
- private static final int TYPED_LETTER_MULTIPLIER = 2;
- private static final int FULL_WORD_MULTIPLIER = 2;
- private static final int S_INT_MAX = 2147483647;
- public static double calcNormalizedScore(CharSequence before, CharSequence after, int score) {
- final int beforeLength = before.length();
- final int afterLength = after.length();
- if (beforeLength == 0 || afterLength == 0) return 0;
- final int distance = editDistance(before, after);
- // If afterLength < beforeLength, the algorithm is suggesting a word by excessive character
- // correction.
- int spaceCount = 0;
- for (int i = 0; i < afterLength; ++i) {
- if (after.charAt(i) == Keyboard.CODE_SPACE) {
- ++spaceCount;
- }
- }
- if (spaceCount == afterLength) return 0;
- final double maximumScore = score == S_INT_MAX ? S_INT_MAX : MAX_INITIAL_SCORE
- * Math.pow(
- TYPED_LETTER_MULTIPLIER, Math.min(beforeLength, afterLength - spaceCount))
- * FULL_WORD_MULTIPLIER;
- // add a weight based on edit distance.
- // distance <= max(afterLength, beforeLength) == afterLength,
- // so, 0 <= distance / afterLength <= 1
- final double weight = 1.0 - (double) distance / afterLength;
- return (score / maximumScore) * weight;
- }
-
public static class UsabilityStudyLogUtils {
private static final String USABILITY_TAG = UsabilityStudyLogUtils.class.getSimpleName();
private static final String FILENAME = "log.txt";
@@ -465,7 +380,7 @@ public class Utils {
}
}
- public void writeBackSpace() {
+ public static void writeBackSpace() {
UsabilityStudyLogUtils.getInstance().write("<backspace>\t0\t0");
}
@@ -504,32 +419,89 @@ public class Utils {
});
}
- public void printAll() {
+ private synchronized String getBufferedLogs() {
+ mWriter.flush();
+ StringBuilder sb = new StringBuilder();
+ BufferedReader br = getBufferedReader();
+ String line;
+ try {
+ while ((line = br.readLine()) != null) {
+ sb.append('\n');
+ sb.append(line);
+ }
+ } catch (IOException e) {
+ Log.e(USABILITY_TAG, "Can't read log file.");
+ } finally {
+ if (LatinImeLogger.sDBG) {
+ Log.d(USABILITY_TAG, "Got all buffered logs\n" + sb.toString());
+ }
+ try {
+ br.close();
+ } catch (IOException e) {
+ // ignore.
+ }
+ }
+ return sb.toString();
+ }
+
+ public void emailResearcherLogsAll() {
mLoggingHandler.post(new Runnable() {
@Override
public void run() {
+ final Date date = new Date();
+ date.setTime(System.currentTimeMillis());
+ final String currentDateTimeString =
+ new SimpleDateFormat("yyyyMMdd-HHmmssZ").format(date);
+ if (mFile == null) {
+ Log.w(USABILITY_TAG, "No internal log file found.");
+ return;
+ }
+ if (mIms.checkCallingOrSelfPermission(
+ android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ != PackageManager.PERMISSION_GRANTED) {
+ Log.w(USABILITY_TAG, "Doesn't have the permission WRITE_EXTERNAL_STORAGE");
+ return;
+ }
mWriter.flush();
- StringBuilder sb = new StringBuilder();
- BufferedReader br = getBufferedReader();
- String line;
+ final String destPath = Environment.getExternalStorageDirectory()
+ + "/research-" + currentDateTimeString + ".log";
+ final File destFile = new File(destPath);
try {
- while ((line = br.readLine()) != null) {
- sb.append('\n');
- sb.append(line);
- }
- } catch (IOException e) {
- Log.e(USABILITY_TAG, "Can't read log file.");
- } finally {
- if (LatinImeLogger.sDBG) {
- Log.d(USABILITY_TAG, "output all logs\n" + sb.toString());
- }
- mIms.getCurrentInputConnection().commitText(sb.toString(), 0);
- try {
- br.close();
- } catch (IOException e) {
- // ignore.
- }
+ final FileChannel src = (new FileInputStream(mFile)).getChannel();
+ final FileChannel dest = (new FileOutputStream(destFile)).getChannel();
+ src.transferTo(0, src.size(), dest);
+ src.close();
+ dest.close();
+ } catch (FileNotFoundException e1) {
+ Log.w(USABILITY_TAG, e1);
+ return;
+ } catch (IOException e2) {
+ Log.w(USABILITY_TAG, e2);
+ return;
}
+ if (destFile == null || !destFile.exists()) {
+ Log.w(USABILITY_TAG, "Dest file doesn't exist.");
+ return;
+ }
+ final Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ if (LatinImeLogger.sDBG) {
+ Log.d(USABILITY_TAG, "Destination file URI is " + destFile.toURI());
+ }
+ intent.setType("text/plain");
+ intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + destPath));
+ intent.putExtra(Intent.EXTRA_SUBJECT,
+ "[Research Logs] " + currentDateTimeString);
+ mIms.startActivity(intent);
+ }
+ });
+ }
+
+ public void printAll() {
+ mLoggingHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mIms.getCurrentInputConnection().commitText(getBufferedLogs(), 0);
}
});
}
@@ -630,9 +602,13 @@ public class Utils {
public static void loadNativeLibrary() {
try {
- System.loadLibrary("jni_latinime");
+ System.loadLibrary(JniLibName.JNI_LIB_NAME);
} catch (UnsatisfiedLinkError ule) {
- Log.e(TAG, "Could not load native library jni_latinime");
+ Log.e(TAG, "Could not load native library " + JniLibName.JNI_LIB_NAME);
+ if (LatinImeLogger.sDBG) {
+ throw new RuntimeException(
+ "Could not load native library " + JniLibName.JNI_LIB_NAME);
+ }
}
}
@@ -778,40 +754,32 @@ public class Utils {
return s.toUpperCase(locale).charAt(0) + s.substring(1);
}
- public static int getCurrentVibrationDuration(SharedPreferences sp, Resources res) {
- final int ms = sp.getInt(Settings.PREF_KEYPRESS_VIBRATION_DURATION_SETTINGS, -1);
- if (ms >= 0) {
- return ms;
- }
- final String[] durationPerHardwareList = res.getStringArray(
- R.array.keypress_vibration_durations);
- final String hardwarePrefix = Build.HARDWARE + ",";
- for (final String element : durationPerHardwareList) {
- if (element.startsWith(hardwarePrefix)) {
- return (int)Long.parseLong(element.substring(element.lastIndexOf(',') + 1));
- }
- }
- return -1;
+ public static boolean willAutoCorrect(SuggestedWords suggestions) {
+ return !suggestions.mTypedWordValid && suggestions.mHasAutoCorrectionCandidate
+ && !suggestions.shouldBlockAutoCorrection();
}
- public static float getCurrentKeypressSoundVolume(SharedPreferences sp, Resources res) {
- final float volume = sp.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f);
- if (volume >= 0) {
- return volume;
+ public static class Stats {
+ public static void onNonSeparator(final char code, final int x,
+ final int y) {
+ RingCharBuffer.getInstance().push(code, x, y);
+ LatinImeLogger.logOnInputChar();
}
- final String[] volumePerHardwareList = res.getStringArray(R.array.keypress_volumes);
- final String hardwarePrefix = Build.HARDWARE + ",";
- for (final String element : volumePerHardwareList) {
- if (element.startsWith(hardwarePrefix)) {
- return Float.parseFloat(element.substring(element.lastIndexOf(',') + 1));
- }
+ public static void onSeparator(final char code, final int x,
+ final int y) {
+ RingCharBuffer.getInstance().push(code, x, y);
+ LatinImeLogger.logOnInputSeparator();
}
- return -1.0f;
- }
- public static boolean willAutoCorrect(SuggestedWords suggestions) {
- return !suggestions.mTypedWordValid && suggestions.mHasAutoCorrectionCandidate
- && !suggestions.shouldBlockAutoCorrection();
+ public static void onAutoCorrection(final String typedWord, final String correctedWord,
+ final int separatorCode) {
+ if (TextUtils.isEmpty(typedWord)) return;
+ LatinImeLogger.logOnAutoCorrection(typedWord, correctedWord, separatorCode);
+ }
+
+ public static void onAutoCorrectionCancellation() {
+ LatinImeLogger.logOnAutoCorrectionCancelled();
+ }
}
}
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index adc5637f6..e95dcfdc9 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -16,9 +16,14 @@
package com.android.inputmethod.latin;
+import android.text.TextUtils;
+
+import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.KeyDetector;
+import com.android.inputmethod.keyboard.Keyboard;
import java.util.ArrayList;
+import java.util.Arrays;
/**
* A place to store the currently composing word with information such as adjacent key codes as well
@@ -28,31 +33,75 @@ public class WordComposer {
public static final int NOT_A_CODE = KeyDetector.NOT_A_CODE;
public static final int NOT_A_COORDINATE = -1;
- /**
- * The list of unicode values for each keystroke (including surrounding keys)
- */
- private ArrayList<int[]> mCodes;
+ // TODO: Straighten out commit behavior so that the flags here are more understandable,
+ // and possibly adjust their names.
+ // COMMIT_TYPE_USER_TYPED_WORD is used when the word committed is the exact typed word, with
+ // no hinting from the IME. It happens when some external event happens (rotating the device,
+ // for example) or when auto-correction is off by settings or editor attributes.
+ public static final int COMMIT_TYPE_USER_TYPED_WORD = 0;
+ // COMMIT_TYPE_MANUAL_PICK is used when the user pressed a field in the suggestion strip.
+ public static final int COMMIT_TYPE_MANUAL_PICK = 1;
+ // COMMIT_TYPE_DECIDED_WORD is used when the IME commits the word it decided was best
+ // for the current user input. It may be different from what the user typed (true auto-correct)
+ // or it may be exactly what the user typed if it's in the dictionary or the IME does not have
+ // enough confidence in any suggestion to auto-correct (auto-correct to typed word).
+ public static final int COMMIT_TYPE_DECIDED_WORD = 2;
+ // COMMIT_TYPE_CANCEL_AUTO_CORRECT is used upon committing back the old word upon cancelling
+ // an auto-correction.
+ public static final int COMMIT_TYPE_CANCEL_AUTO_CORRECT = 3;
- private int[] mXCoordinates;
- private int[] mYCoordinates;
+ // Storage for all the info about the current input.
+ private static class CharacterStore {
+ /**
+ * The list of unicode values for each keystroke (including surrounding keys)
+ */
+ ArrayList<int[]> mCodes;
+ int[] mXCoordinates;
+ int[] mYCoordinates;
+ StringBuilder mTypedWord;
+ CharSequence mAutoCorrection;
+ CharacterStore() {
+ final int N = BinaryDictionary.MAX_WORD_LENGTH;
+ mCodes = new ArrayList<int[]>(N);
+ mTypedWord = new StringBuilder(N);
+ mXCoordinates = new int[N];
+ mYCoordinates = new int[N];
+ mAutoCorrection = null;
+ }
+ CharacterStore(final CharacterStore that) {
+ mCodes = new ArrayList<int[]>(that.mCodes);
+ mTypedWord = new StringBuilder(that.mTypedWord);
+ mXCoordinates = Arrays.copyOf(that.mXCoordinates, that.mXCoordinates.length);
+ mYCoordinates = Arrays.copyOf(that.mYCoordinates, that.mYCoordinates.length);
+ }
+ void reset() {
+ // For better performance than creating a new character store.
+ mCodes.clear();
+ mTypedWord.setLength(0);
+ mAutoCorrection = null;
+ }
+ }
- private StringBuilder mTypedWord;
+ // The currently typing word. May not be null.
+ private CharacterStore mCurrentWord;
+ // The information being kept for resuming suggestion. May be null if wiped.
+ private CharacterStore mCommittedWordSavedForSuggestionResuming;
private int mCapsCount;
private boolean mAutoCapitalized;
-
+ // Cache this value for performance
+ private int mTrailingSingleQuotesCount;
+
/**
* Whether the user chose to capitalize the first char of the word.
*/
private boolean mIsFirstCharCapitalized;
public WordComposer() {
- final int N = BinaryDictionary.MAX_WORD_LENGTH;
- mCodes = new ArrayList<int[]>(N);
- mTypedWord = new StringBuilder(N);
- mXCoordinates = new int[N];
- mYCoordinates = new int[N];
+ mCurrentWord = new CharacterStore();
+ mCommittedWordSavedForSuggestionResuming = null;
+ mTrailingSingleQuotesCount = 0;
}
public WordComposer(WordComposer source) {
@@ -60,23 +109,23 @@ public class WordComposer {
}
public void init(WordComposer source) {
- mCodes = new ArrayList<int[]>(source.mCodes);
- mTypedWord = new StringBuilder(source.mTypedWord);
- mXCoordinates = source.mXCoordinates;
- mYCoordinates = source.mYCoordinates;
+ mCurrentWord = new CharacterStore(source.mCurrentWord);
+ mCommittedWordSavedForSuggestionResuming = source.mCommittedWordSavedForSuggestionResuming;
mCapsCount = source.mCapsCount;
mIsFirstCharCapitalized = source.mIsFirstCharCapitalized;
mAutoCapitalized = source.mAutoCapitalized;
+ mTrailingSingleQuotesCount = source.mTrailingSingleQuotesCount;
}
/**
* Clear out the keys registered so far.
*/
public void reset() {
- mCodes.clear();
- mTypedWord.setLength(0);
+ mCurrentWord.reset();
+ mCommittedWordSavedForSuggestionResuming = null;
mCapsCount = 0;
mIsFirstCharCapitalized = false;
+ mTrailingSingleQuotesCount = 0;
}
/**
@@ -84,7 +133,11 @@ public class WordComposer {
* @return the number of keystrokes
*/
public final int size() {
- return mTypedWord.length();
+ return mCurrentWord.mTypedWord.length();
+ }
+
+ public final boolean isComposingWord() {
+ return size() > 0;
}
/**
@@ -93,15 +146,15 @@ public class WordComposer {
* @return the unicode for the pressed and surrounding keys
*/
public int[] getCodesAt(int index) {
- return mCodes.get(index);
+ return mCurrentWord.mCodes.get(index);
}
public int[] getXCoordinates() {
- return mXCoordinates;
+ return mCurrentWord.mXCoordinates;
}
public int[] getYCoordinates() {
- return mYCoordinates;
+ return mCurrentWord.mYCoordinates;
}
private static boolean isFirstCharCapitalized(int index, int codePoint, boolean previous) {
@@ -116,16 +169,67 @@ public class WordComposer {
*/
public void add(int primaryCode, int[] codes, int x, int y) {
final int newIndex = size();
- mTypedWord.append((char) primaryCode);
+ mCurrentWord.mTypedWord.append((char) primaryCode);
correctPrimaryJuxtapos(primaryCode, codes);
- mCodes.add(codes);
+ mCurrentWord.mCodes.add(codes);
if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) {
- mXCoordinates[newIndex] = x;
- mYCoordinates[newIndex] = y;
+ mCurrentWord.mXCoordinates[newIndex] = x;
+ mCurrentWord.mYCoordinates[newIndex] = y;
}
mIsFirstCharCapitalized = isFirstCharCapitalized(
newIndex, primaryCode, mIsFirstCharCapitalized);
if (Character.isUpperCase(primaryCode)) mCapsCount++;
+ if (Keyboard.CODE_SINGLE_QUOTE == primaryCode) {
+ ++mTrailingSingleQuotesCount;
+ } else {
+ mTrailingSingleQuotesCount = 0;
+ }
+ mCurrentWord.mAutoCorrection = null;
+ }
+
+ /**
+ * Internal method to retrieve reasonable proximity info for a character.
+ */
+ private void addKeyInfo(final int codePoint, final Keyboard keyboard,
+ final KeyDetector keyDetector) {
+ for (final Key key : keyboard.mKeys) {
+ if (key.mCode == codePoint) {
+ final int x = key.mX + key.mWidth / 2;
+ final int y = key.mY + key.mHeight / 2;
+ final int[] codes = keyDetector.newCodeArray();
+ keyDetector.getKeyAndNearbyCodes(x, y, codes);
+ add(codePoint, codes, x, y);
+ return;
+ }
+ }
+ add(codePoint, new int[] { codePoint },
+ WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
+ }
+
+ /**
+ * Set the currently composing word to the one passed as an argument.
+ * This will register NOT_A_COORDINATE for X and Ys, and use the passed keyboard for proximity.
+ */
+ public void setComposingWord(final CharSequence word, final Keyboard keyboard,
+ final KeyDetector keyDetector) {
+ reset();
+ final int length = word.length();
+ for (int i = 0; i < length; ++i) {
+ int codePoint = word.charAt(i);
+ addKeyInfo(codePoint, keyboard, keyDetector);
+ }
+ mCommittedWordSavedForSuggestionResuming = null;
+ }
+
+ /**
+ * Shortcut for the above method, this will create a new KeyDetector for the passed keyboard.
+ */
+ public void setComposingWord(final CharSequence word, final Keyboard keyboard) {
+ final KeyDetector keyDetector = new KeyDetector(0);
+ keyDetector.setKeyboard(keyboard, 0, 0);
+ keyDetector.setProximityCorrectionEnabled(true);
+ keyDetector.setProximityThreshold(keyboard.mMostCommonKeyWidth);
+ setComposingWord(word, keyboard, keyDetector);
}
/**
@@ -135,7 +239,7 @@ public class WordComposer {
* @param primaryCode the preferred character
* @param codes array of codes based on distance from touch point
*/
- private void correctPrimaryJuxtapos(int primaryCode, int[] codes) {
+ private static void correctPrimaryJuxtapos(int primaryCode, int[] codes) {
if (codes.length < 2) return;
if (codes[0] > 0 && codes[1] > 0 && codes[0] != primaryCode && codes[1] == primaryCode) {
codes[1] = codes[0];
@@ -150,25 +254,31 @@ public class WordComposer {
final int size = size();
if (size > 0) {
final int lastPos = size - 1;
- char lastChar = mTypedWord.charAt(lastPos);
- mCodes.remove(lastPos);
- mTypedWord.deleteCharAt(lastPos);
+ char lastChar = mCurrentWord.mTypedWord.charAt(lastPos);
+ mCurrentWord.mCodes.remove(lastPos);
+ mCurrentWord.mTypedWord.deleteCharAt(lastPos);
if (Character.isUpperCase(lastChar)) mCapsCount--;
}
if (size() == 0) {
mIsFirstCharCapitalized = false;
}
+ if (mTrailingSingleQuotesCount > 0) {
+ --mTrailingSingleQuotesCount;
+ } else {
+ for (int i = mCurrentWord.mTypedWord.length() - 1; i >= 0; --i) {
+ if (Keyboard.CODE_SINGLE_QUOTE != mCurrentWord.mTypedWord.codePointAt(i)) break;
+ ++mTrailingSingleQuotesCount;
+ }
+ }
+ mCurrentWord.mAutoCorrection = null;
}
/**
* Returns the word as it was typed, without any correction applied.
- * @return the word that was typed so far
+ * @return the word that was typed so far. Never returns null.
*/
public String getTypedWord() {
- if (size() == 0) {
- return null;
- }
- return mTypedWord.toString();
+ return mCurrentWord.mTypedWord.toString();
}
/**
@@ -179,6 +289,10 @@ public class WordComposer {
return mIsFirstCharCapitalized;
}
+ public int trailingSingleQuotesCount() {
+ return mTrailingSingleQuotesCount;
+ }
+
/**
* Whether or not all of the user typed chars are upper case
* @return true if all user typed chars are upper case, false otherwise
@@ -194,7 +308,7 @@ public class WordComposer {
return mCapsCount > 1;
}
- /**
+ /**
* Saves the reason why the word is capitalized - whether it was automatic or
* due to the user hitting shift in the middle of a sentence.
* @param auto whether it was an automatic capitalization due to start of sentence
@@ -210,4 +324,62 @@ public class WordComposer {
public boolean isAutoCapitalized() {
return mAutoCapitalized;
}
+
+ /**
+ * Sets the auto-correction for this word.
+ */
+ public void setAutoCorrection(final CharSequence correction) {
+ mCurrentWord.mAutoCorrection = correction;
+ }
+
+ /**
+ * Remove any auto-correction that may have been set.
+ */
+ public void deleteAutoCorrection() {
+ mCurrentWord.mAutoCorrection = null;
+ }
+
+ /**
+ * @return the auto-correction for this word, or null if none.
+ */
+ public CharSequence getAutoCorrectionOrNull() {
+ return mCurrentWord.mAutoCorrection;
+ }
+
+ // `type' should be one of the COMMIT_TYPE_* constants above.
+ public void onCommitWord(final int type) {
+ mCommittedWordSavedForSuggestionResuming = mCurrentWord;
+ // Note: currently, we come here whenever we commit a word. If it's any *other* kind than
+ // DECIDED_WORD, we should reset mAutoCorrection so that we don't attempt to cancel later.
+ // If it's a DECIDED_WORD, it may be an actual auto-correction by the IME, or what the user
+ // typed because the IME decided *not* to auto-correct for whatever reason.
+ // Ideally we would also null it when it was a DECIDED_WORD that was not an auto-correct.
+ // As it happens these two cases should behave differently, because the former can be
+ // canceled while the latter can't. Currently, we figure this out in
+ // #didAutoCorrectToAnotherWord with #equals(). It would be marginally cleaner to do it
+ // here, but it would be slower (since we would #equals() for each commit, instead of
+ // only on cancel), and ultimately we want to figure it out even earlier anyway.
+ if (type != COMMIT_TYPE_DECIDED_WORD) {
+ // Only ever revert an auto-correct.
+ mCommittedWordSavedForSuggestionResuming.mAutoCorrection = null;
+ }
+ // TODO: improve performance by swapping buffers instead of creating a new object.
+ mCurrentWord = new CharacterStore();
+ }
+
+ public boolean hasWordKeptForSuggestionResuming() {
+ return null != mCommittedWordSavedForSuggestionResuming;
+ }
+
+ public void resumeSuggestionOnKeptWord() {
+ mCurrentWord = mCommittedWordSavedForSuggestionResuming;
+ mCommittedWordSavedForSuggestionResuming = null;
+ }
+
+ public boolean didAutoCorrectToAnotherWord() {
+ return null != mCommittedWordSavedForSuggestionResuming
+ && !TextUtils.isEmpty(mCommittedWordSavedForSuggestionResuming.mAutoCorrection)
+ && !TextUtils.equals(mCommittedWordSavedForSuggestionResuming.mTypedWord,
+ mCommittedWordSavedForSuggestionResuming.mAutoCorrection);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/XmlParseUtils.java b/java/src/com/android/inputmethod/latin/XmlParseUtils.java
new file mode 100644
index 000000000..d747a024c
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/XmlParseUtils.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.res.TypedArray;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+public class XmlParseUtils {
+ @SuppressWarnings("serial")
+ public static class ParseException extends XmlPullParserException {
+ public ParseException(String msg, XmlPullParser parser) {
+ super(msg + " at line " + parser.getLineNumber()
+ + ", column " + parser.getColumnNumber());
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class IllegalStartTag extends ParseException {
+ public IllegalStartTag(XmlPullParser parser, String parent) {
+ super("Illegal start tag " + parser.getName() + " in " + parent, parser);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class IllegalEndTag extends ParseException {
+ public IllegalEndTag(XmlPullParser parser, String parent) {
+ super("Illegal end tag " + parser.getName() + " in " + parent, parser);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class IllegalAttribute extends ParseException {
+ public IllegalAttribute(XmlPullParser parser, String attribute) {
+ super("Tag " + parser.getName() + " has illegal attribute " + attribute, parser);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class NonEmptyTag extends ParseException{
+ public NonEmptyTag(String tag, XmlPullParser parser) {
+ super(tag + " must be empty tag", parser);
+ }
+ }
+
+ public static void checkEndTag(String tag, XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ if (parser.next() == XmlPullParser.END_TAG && tag.equals(parser.getName()))
+ return;
+ throw new NonEmptyTag(tag, parser);
+ }
+
+ public static void checkAttributeExists(TypedArray attr, int attrId, String attrName,
+ String tag, XmlPullParser parser) throws XmlPullParserException {
+ if (attr.hasValue(attrId))
+ return;
+ throw new ParseException(
+ "No " + attrName + " attribute found in <" + tag + "/>", parser);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/define/JniLibName.java b/java/src/com/android/inputmethod/latin/define/JniLibName.java
new file mode 100644
index 000000000..3e94a3c07
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/define/JniLibName.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.define;
+
+public class JniLibName {
+ public static final String JNI_LIB_NAME = "jni_latinime";
+}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 095c2c51c..39e47f661 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -17,7 +17,9 @@
package com.android.inputmethod.latin.spellcheck;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.res.Resources;
+import android.preference.PreferenceManager;
import android.service.textservice.SpellCheckerService;
import android.text.TextUtils;
import android.util.Log;
@@ -25,6 +27,7 @@ import android.view.textservice.SuggestionsInfo;
import android.view.textservice.TextInfo;
import com.android.inputmethod.compat.ArraysCompatUtils;
+import com.android.inputmethod.compat.SuggestionsInfoCompatUtils;
import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.BinaryDictionary;
import com.android.inputmethod.latin.Dictionary;
@@ -41,21 +44,27 @@ import com.android.inputmethod.latin.Utils;
import com.android.inputmethod.latin.WhitelistDictionary;
import com.android.inputmethod.latin.WordComposer;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
+import java.util.HashSet;
/**
* Service for spell checking, using LatinIME's dictionaries and mechanisms.
*/
-public class AndroidSpellCheckerService extends SpellCheckerService {
+public class AndroidSpellCheckerService extends SpellCheckerService
+ implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = AndroidSpellCheckerService.class.getSimpleName();
private static final boolean DBG = false;
private static final int POOL_SIZE = 2;
+ public static final String PREF_USE_CONTACTS_KEY = "pref_spellcheck_use_contacts";
+
private static final int CAPITALIZE_NONE = 0; // No caps, or mixed case
private static final int CAPITALIZE_FIRST = 1; // First only
private static final int CAPITALIZE_ALL = 2; // All caps
@@ -82,15 +91,100 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
// The threshold for a candidate to be offered as a suggestion.
private double mSuggestionThreshold;
- // The threshold for a suggestion to be considered "likely".
- private double mLikelyThreshold;
+ // The threshold for a suggestion to be considered "recommended".
+ private double mRecommendedThreshold;
+ // Whether to use the contacts dictionary
+ private boolean mUseContactsDictionary;
+ private final Object mUseContactsLock = new Object();
+
+ private final HashSet<WeakReference<DictionaryCollection>> mDictionaryCollectionsList =
+ new HashSet<WeakReference<DictionaryCollection>>();
+
+ public static final int SCRIPT_LATIN = 0;
+ public static final int SCRIPT_CYRILLIC = 1;
+ private static final TreeMap<String, Integer> mLanguageToScript;
+ static {
+ // List of the supported languages and their associated script. We won't check
+ // words written in another script than the selected script, because we know we
+ // don't have those in our dictionary so we will underline everything and we
+ // will never have any suggestions, so it makes no sense checking them.
+ mLanguageToScript = new TreeMap<String, Integer>();
+ mLanguageToScript.put("en", SCRIPT_LATIN);
+ mLanguageToScript.put("fr", SCRIPT_LATIN);
+ mLanguageToScript.put("de", SCRIPT_LATIN);
+ mLanguageToScript.put("nl", SCRIPT_LATIN);
+ mLanguageToScript.put("cs", SCRIPT_LATIN);
+ mLanguageToScript.put("es", SCRIPT_LATIN);
+ mLanguageToScript.put("it", SCRIPT_LATIN);
+ mLanguageToScript.put("ru", SCRIPT_CYRILLIC);
+ }
@Override public void onCreate() {
super.onCreate();
mSuggestionThreshold =
Double.parseDouble(getString(R.string.spellchecker_suggestion_threshold_value));
- mLikelyThreshold =
- Double.parseDouble(getString(R.string.spellchecker_likely_threshold_value));
+ mRecommendedThreshold =
+ Double.parseDouble(getString(R.string.spellchecker_recommended_threshold_value));
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.registerOnSharedPreferenceChangeListener(this);
+ onSharedPreferenceChanged(prefs, PREF_USE_CONTACTS_KEY);
+ }
+
+ private static int getScriptFromLocale(final Locale locale) {
+ final Integer script = mLanguageToScript.get(locale.getLanguage());
+ if (null == script) {
+ throw new RuntimeException("We have been called with an unsupported language: \""
+ + locale.getLanguage() + "\". Framework bug?");
+ }
+ return script;
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
+ if (!PREF_USE_CONTACTS_KEY.equals(key)) return;
+ synchronized(mUseContactsLock) {
+ mUseContactsDictionary = prefs.getBoolean(PREF_USE_CONTACTS_KEY, true);
+ if (mUseContactsDictionary) {
+ startUsingContactsDictionaryLocked();
+ } else {
+ stopUsingContactsDictionaryLocked();
+ }
+ }
+ }
+
+ private void startUsingContactsDictionaryLocked() {
+ if (null == mContactsDictionary) {
+ mContactsDictionary = new SynchronouslyLoadedContactsDictionary(this);
+ }
+ final Iterator<WeakReference<DictionaryCollection>> iterator =
+ mDictionaryCollectionsList.iterator();
+ while (iterator.hasNext()) {
+ final WeakReference<DictionaryCollection> dictRef = iterator.next();
+ final DictionaryCollection dict = dictRef.get();
+ if (null == dict) {
+ iterator.remove();
+ } else {
+ dict.addDictionary(mContactsDictionary);
+ }
+ }
+ }
+
+ private void stopUsingContactsDictionaryLocked() {
+ if (null == mContactsDictionary) return;
+ final SynchronouslyLoadedContactsDictionary contactsDict = mContactsDictionary;
+ mContactsDictionary = null;
+ final Iterator<WeakReference<DictionaryCollection>> iterator =
+ mDictionaryCollectionsList.iterator();
+ while (iterator.hasNext()) {
+ final WeakReference<DictionaryCollection> dictRef = iterator.next();
+ final DictionaryCollection dict = dictRef.get();
+ if (null == dict) {
+ iterator.remove();
+ } else {
+ dict.removeDictionary(contactsDict);
+ }
+ }
+ contactsDict.close();
}
@Override
@@ -110,10 +204,11 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
private static class SuggestionsGatherer implements WordCallback {
public static class Result {
public final String[] mSuggestions;
- public final boolean mHasLikelySuggestions;
- public Result(final String[] gatheredSuggestions, final boolean hasLikelySuggestions) {
+ public final boolean mHasRecommendedSuggestions;
+ public Result(final String[] gatheredSuggestions,
+ final boolean hasRecommendedSuggestions) {
mSuggestions = gatheredSuggestions;
- mHasLikelySuggestions = hasLikelySuggestions;
+ mHasRecommendedSuggestions = hasRecommendedSuggestions;
}
}
@@ -121,7 +216,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
private final int[] mScores;
private final String mOriginalText;
private final double mSuggestionThreshold;
- private final double mLikelyThreshold;
+ private final double mRecommendedThreshold;
private final int mMaxLength;
private int mLength = 0;
@@ -131,10 +226,10 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
private int mBestScore = Integer.MIN_VALUE; // As small as possible
SuggestionsGatherer(final String originalText, final double suggestionThreshold,
- final double likelyThreshold, final int maxLength) {
+ final double recommendedThreshold, final int maxLength) {
mOriginalText = originalText;
mSuggestionThreshold = suggestionThreshold;
- mLikelyThreshold = likelyThreshold;
+ mRecommendedThreshold = recommendedThreshold;
mMaxLength = maxLength;
mSuggestions = new ArrayList<CharSequence>(maxLength + 1);
mScores = new int[mMaxLength];
@@ -175,7 +270,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
// make the threshold.
final String wordString = new String(word, wordOffset, wordLength);
final double normalizedScore =
- Utils.calcNormalizedScore(mOriginalText, wordString, score);
+ BinaryDictionary.calcNormalizedScore(mOriginalText, wordString, score);
if (normalizedScore < mSuggestionThreshold) {
if (DBG) Log.i(TAG, wordString + " does not make the score threshold");
return true;
@@ -198,19 +293,19 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
public Result getResults(final int capitalizeType, final Locale locale) {
final String[] gatheredSuggestions;
- final boolean hasLikelySuggestions;
+ final boolean hasRecommendedSuggestions;
if (0 == mLength) {
// Either we found no suggestions, or we found some BUT the max length was 0.
// If we found some mBestSuggestion will not be null. If it is null, then
// we found none, regardless of the max length.
if (null == mBestSuggestion) {
gatheredSuggestions = null;
- hasLikelySuggestions = false;
+ hasRecommendedSuggestions = false;
} else {
gatheredSuggestions = EMPTY_STRING_ARRAY;
- final double normalizedScore =
- Utils.calcNormalizedScore(mOriginalText, mBestSuggestion, mBestScore);
- hasLikelySuggestions = (normalizedScore > mLikelyThreshold);
+ final double normalizedScore = BinaryDictionary.calcNormalizedScore(
+ mOriginalText, mBestSuggestion, mBestScore);
+ hasRecommendedSuggestions = (normalizedScore > mRecommendedThreshold);
}
} else {
if (DBG) {
@@ -243,16 +338,17 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
final int bestScore = mScores[mLength - 1];
final CharSequence bestSuggestion = mSuggestions.get(0);
final double normalizedScore =
- Utils.calcNormalizedScore(mOriginalText, bestSuggestion, bestScore);
- hasLikelySuggestions = (normalizedScore > mLikelyThreshold);
+ BinaryDictionary.calcNormalizedScore(
+ mOriginalText, bestSuggestion.toString(), bestScore);
+ hasRecommendedSuggestions = (normalizedScore > mRecommendedThreshold);
if (DBG) {
Log.i(TAG, "Best suggestion : " + bestSuggestion + ", score " + bestScore);
Log.i(TAG, "Normalized score = " + normalizedScore
- + " (threshold " + mLikelyThreshold
- + ") => hasLikelySuggestions = " + hasLikelySuggestions);
+ + " (threshold " + mRecommendedThreshold
+ + ") => hasRecommendedSuggestions = " + hasRecommendedSuggestions);
}
}
- return new Result(gatheredSuggestions, hasLikelySuggestions);
+ return new Result(gatheredSuggestions, hasRecommendedSuggestions);
}
}
@@ -273,13 +369,15 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
for (Dictionary dict : oldWhitelistDictionaries.values()) {
dict.close();
}
- if (null != mContactsDictionary) {
- // The synchronously loaded contacts dictionary should have been in one
- // or several pools, but it is shielded against multiple closing and it's
- // safe to call it several times.
- final SynchronouslyLoadedContactsDictionary dictToClose = mContactsDictionary;
- mContactsDictionary = null;
- dictToClose.close();
+ synchronized(mUseContactsLock) {
+ if (null != mContactsDictionary) {
+ // The synchronously loaded contacts dictionary should have been in one
+ // or several pools, but it is shielded against multiple closing and it's
+ // safe to call it several times.
+ final SynchronouslyLoadedContactsDictionary dictToClose = mContactsDictionary;
+ mContactsDictionary = null;
+ dictToClose.close();
+ }
}
return false;
}
@@ -295,7 +393,9 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
}
public DictAndProximity createDictAndProximity(final Locale locale) {
- final ProximityInfo proximityInfo = ProximityInfo.createSpellCheckerProximityInfo();
+ final int script = getScriptFromLocale(locale);
+ final ProximityInfo proximityInfo = ProximityInfo.createSpellCheckerProximityInfo(
+ SpellCheckerProximityInfo.getProximityForScript(script));
final Resources resources = getResources();
final int fallbackResourceId = Utils.getMainDictionaryResourceId(resources);
final DictionaryCollection dictionaryCollection =
@@ -314,11 +414,16 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
mWhitelistDictionaries.put(localeStr, whitelistDictionary);
}
dictionaryCollection.addDictionary(whitelistDictionary);
- if (null == mContactsDictionary) {
- mContactsDictionary = new SynchronouslyLoadedContactsDictionary(this);
+ synchronized(mUseContactsLock) {
+ if (mUseContactsDictionary) {
+ if (null == mContactsDictionary) {
+ mContactsDictionary = new SynchronouslyLoadedContactsDictionary(this);
+ }
+ }
+ dictionaryCollection.addDictionary(mContactsDictionary);
+ mDictionaryCollectionsList.add(
+ new WeakReference<DictionaryCollection>(dictionaryCollection));
}
- // TODO: add a setting to use or not contacts when checking spelling
- dictionaryCollection.addDictionary(mContactsDictionary);
return new DictAndProximity(dictionaryCollection, proximityInfo);
}
@@ -346,6 +451,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
private DictionaryPool mDictionaryPool;
// Likewise
private Locale mLocale;
+ // Cache this for performance
+ private int mScript; // One of SCRIPT_LATIN or SCRIPT_CYRILLIC for now.
private final AndroidSpellCheckerService mService;
@@ -358,17 +465,51 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
final String localeString = getLocale();
mDictionaryPool = mService.getDictionaryPool(localeString);
mLocale = LocaleUtils.constructLocaleFromString(localeString);
+ mScript = getScriptFromLocale(mLocale);
+ }
+
+ /*
+ * Returns whether the code point is a letter that makes sense for the specified
+ * locale for this spell checker.
+ * The dictionaries supported by Latin IME are described in res/xml/spellchecker.xml
+ * and is limited to EFIGS languages and Russian.
+ * Hence at the moment this explicitly tests for Cyrillic characters or Latin characters
+ * as appropriate, and explicitly excludes CJK, Arabic and Hebrew characters.
+ */
+ private static boolean isLetterCheckableByLanguage(final int codePoint,
+ final int script) {
+ switch (script) {
+ case SCRIPT_LATIN:
+ // Our supported latin script dictionaries (EFIGS) at the moment only include
+ // characters in the C0, C1, Latin Extended A and B, IPA extensions unicode
+ // blocks. As it happens, those are back-to-back in the code range 0x40 to 0x2AF,
+ // so the below is a very efficient way to test for it. As for the 0-0x3F, it's
+ // excluded from isLetter anyway.
+ return codePoint <= 0x2AF && Character.isLetter(codePoint);
+ case SCRIPT_CYRILLIC:
+ // All Cyrillic characters are in the 400~52F block. There are some in the upper
+ // Unicode range, but they are archaic characters that are not used in modern
+ // russian and are not used by our dictionary.
+ return codePoint >= 0x400 && codePoint <= 0x52F && Character.isLetter(codePoint);
+ default:
+ // Should never come here
+ throw new RuntimeException("Impossible value of script: " + script);
+ }
}
/**
* Finds out whether a particular string should be filtered out of spell checking.
*
- * This will loosely match URLs, numbers, symbols.
+ * This will loosely match URLs, numbers, symbols. To avoid always underlining words that
+ * we know we will never recognize, this accepts a script identifier that should be one
+ * of the SCRIPT_* constants defined above, to rule out quickly characters from very
+ * different languages.
*
* @param text the string to evaluate.
+ * @param script the identifier for the script this spell checker recognizes
* @return true if we should filter this text out, false otherwise
*/
- private boolean shouldFilterOut(final String text) {
+ private static boolean shouldFilterOut(final String text, final int script) {
if (TextUtils.isEmpty(text) || text.length() <= 1) return true;
// TODO: check if an equivalent processing can't be done more quickly with a
@@ -376,7 +517,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
// Filter by first letter
final int firstCodePoint = text.codePointAt(0);
// Filter out words that don't start with a letter or an apostrophe
- if (!Character.isLetter(firstCodePoint)
+ if (!isLetterCheckableByLanguage(firstCodePoint, script)
&& '\'' != firstCodePoint) return true;
// Filter contents
@@ -389,7 +530,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
// words or a URI - in either case we don't want to spell check that
if ('@' == codePoint
|| '/' == codePoint) return true;
- if (Character.isLetter(codePoint)) ++letterCount;
+ if (isLetterCheckableByLanguage(codePoint, script)) ++letterCount;
}
// Guestimate heuristic: perform spell checking if at least 3/4 of the characters
// in this word are letters
@@ -408,7 +549,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
try {
final String text = textInfo.getText();
- if (shouldFilterOut(text)) {
+ if (shouldFilterOut(text, mScript)) {
DictAndProximity dictInfo = null;
try {
dictInfo = mDictionaryPool.takeOrGetNull();
@@ -426,17 +567,23 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
// TODO: Don't gather suggestions if the limit is <= 0 unless necessary
final SuggestionsGatherer suggestionsGatherer = new SuggestionsGatherer(text,
- mService.mSuggestionThreshold, mService.mLikelyThreshold, suggestionsLimit);
+ mService.mSuggestionThreshold, mService.mRecommendedThreshold,
+ suggestionsLimit);
final WordComposer composer = new WordComposer();
final int length = text.length();
for (int i = 0; i < length; ++i) {
final int character = text.codePointAt(i);
- final int proximityIndex = SpellCheckerProximityInfo.getIndexOf(character);
+ final int proximityIndex =
+ SpellCheckerProximityInfo.getIndexOfCodeForScript(character, mScript);
final int[] proximities;
if (-1 == proximityIndex) {
proximities = new int[] { character };
} else {
- proximities = Arrays.copyOfRange(SpellCheckerProximityInfo.PROXIMITY,
+ // TODO: an initial examination seems to reveal this is actually used
+ // read-only. It should be possible to compute the arrays statically once
+ // and skip doing a copy each time here.
+ proximities = Arrays.copyOfRange(
+ SpellCheckerProximityInfo.getProximityForScript(mScript),
proximityIndex,
proximityIndex + SpellCheckerProximityInfo.ROW_SIZE);
}
@@ -475,7 +622,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
+ suggestionsLimit);
Log.i(TAG, "IsInDict = " + isInDict);
Log.i(TAG, "LooksLikeTypo = " + (!isInDict));
- Log.i(TAG, "HasLikelySuggestions = " + result.mHasLikelySuggestions);
+ Log.i(TAG, "HasRecommendedSuggestions = " + result.mHasRecommendedSuggestions);
if (null != result.mSuggestions) {
for (String suggestion : result.mSuggestions) {
Log.i(TAG, suggestion);
@@ -483,10 +630,13 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
}
}
- // TODO: actually use result.mHasLikelySuggestions
final int flags =
(isInDict ? SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY
- : SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO);
+ : SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO)
+ | (result.mHasRecommendedSuggestions
+ ? SuggestionsInfoCompatUtils
+ .getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS()
+ : 0);
return new SuggestionsInfo(flags, result.mSuggestions);
} catch (RuntimeException e) {
// Don't kill the keyboard if there is a bug in the spell checker
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java
index d5b04b27c..2bc2cfdf6 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java
@@ -29,65 +29,150 @@ public class SpellCheckerProximityInfo {
// as the size of the passed array afterwards so they can't be different.
final public static int ROW_SIZE = ProximityInfo.MAX_PROXIMITY_CHARS_SIZE;
- // This is a map from the code point to the index in the PROXIMITY array.
- // At the time the native code to read the binary dictionary needs the proximity info be passed
- // as a flat array spaced by MAX_PROXIMITY_CHARS_SIZE columns, one for each input character.
- // Since we need to build such an array, we want to be able to search in our big proximity data
- // quickly by character, and a map is probably the best way to do this.
- final private static TreeMap<Integer, Integer> INDICES = new TreeMap<Integer, Integer>();
+ // Helper methods
+ final protected static void buildProximityIndices(final int[] proximity,
+ final TreeMap<Integer, Integer> indices) {
+ for (int i = 0; i < proximity.length; i += ROW_SIZE) {
+ if (NUL != proximity[i]) indices.put(proximity[i], i);
+ }
+ }
+ final protected static int computeIndex(final int characterCode,
+ final TreeMap<Integer, Integer> indices) {
+ final Integer result = indices.get(characterCode);
+ if (null == result) return -1;
+ return result;
+ }
- // The proximity here is the union of
- // - the proximity for a QWERTY keyboard.
- // - the proximity for an AZERTY keyboard.
- // - the proximity for a QWERTZ keyboard.
- // ...plus, add all characters in the ('a', 'e', 'i', 'o', 'u') set to each other.
- //
- // The reasoning behind this construction is, almost any alphabetic text we may want
- // to spell check has been entered with one of the keyboards above. Also, specifically
- // to English, many spelling errors consist of the last vowel of the word being wrong
- // because in English vowels tend to merge with each other in pronunciation.
- final public static int[] PROXIMITY = {
- 'q', 'w', 's', 'a', 'z', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'w', 'q', 'a', 's', 'd', 'e', 'x', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'e', 'w', 's', 'd', 'f', 'r', 'a', 'i', 'o', 'u', NUL, NUL, NUL, NUL, NUL, NUL,
- 'r', 'e', 'd', 'f', 'g', 't', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 't', 'r', 'f', 'g', 'h', 'y', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'y', 't', 'g', 'h', 'j', 'u', 'a', 's', 'd', 'x', NUL, NUL, NUL, NUL, NUL, NUL,
- 'u', 'y', 'h', 'j', 'k', 'i', 'a', 'e', 'o', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'i', 'u', 'j', 'k', 'l', 'o', 'a', 'e', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'o', 'i', 'k', 'l', 'p', 'a', 'e', 'u', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'p', 'o', 'l', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ private static class Latin {
+ // This is a map from the code point to the index in the PROXIMITY array.
+ // At the time the native code to read the binary dictionary needs the proximity info be
+ // passed as a flat array spaced by MAX_PROXIMITY_CHARS_SIZE columns, one for each input
+ // character.
+ // Since we need to build such an array, we want to be able to search in our big proximity
+ // data quickly by character, and a map is probably the best way to do this.
+ final private static TreeMap<Integer, Integer> INDICES = new TreeMap<Integer, Integer>();
- 'a', 'z', 'x', 's', 'w', 'q', 'e', 'i', 'o', 'u', NUL, NUL, NUL, NUL, NUL, NUL,
- 's', 'q', 'a', 'z', 'x', 'c', 'd', 'e', 'w', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'd', 'w', 's', 'x', 'c', 'v', 'f', 'r', 'e', 'w', NUL, NUL, NUL, NUL, NUL, NUL,
- 'f', 'e', 'd', 'c', 'v', 'b', 'g', 't', 'r', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'g', 'r', 'f', 'v', 'b', 'n', 'h', 'y', 't', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'h', 't', 'g', 'b', 'n', 'm', 'j', 'u', 'y', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'j', 'y', 'h', 'n', 'm', 'k', 'i', 'u', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'k', 'u', 'j', 'm', 'l', 'o', 'i', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'l', 'i', 'k', 'p', 'o', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ // The proximity here is the union of
+ // - the proximity for a QWERTY keyboard.
+ // - the proximity for an AZERTY keyboard.
+ // - the proximity for a QWERTZ keyboard.
+ // ...plus, add all characters in the ('a', 'e', 'i', 'o', 'u') set to each other.
+ //
+ // The reasoning behind this construction is, almost any alphabetic text we may want
+ // to spell check has been entered with one of the keyboards above. Also, specifically
+ // to English, many spelling errors consist of the last vowel of the word being wrong
+ // because in English vowels tend to merge with each other in pronunciation.
+ final static int[] PROXIMITY = {
+ 'q', 'w', 's', 'a', 'z', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'w', 'q', 'a', 's', 'd', 'e', 'x', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'e', 'w', 's', 'd', 'f', 'r', 'a', 'i', 'o', 'u', NUL, NUL, NUL, NUL, NUL, NUL,
+ 'r', 'e', 'd', 'f', 'g', 't', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 't', 'r', 'f', 'g', 'h', 'y', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'y', 't', 'g', 'h', 'j', 'u', 'a', 's', 'd', 'x', NUL, NUL, NUL, NUL, NUL, NUL,
+ 'u', 'y', 'h', 'j', 'k', 'i', 'a', 'e', 'o', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'i', 'u', 'j', 'k', 'l', 'o', 'a', 'e', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'o', 'i', 'k', 'l', 'p', 'a', 'e', 'u', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'p', 'o', 'l', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'z', 'a', 's', 'd', 'x', 't', 'g', 'h', 'j', 'u', 'q', 'e', NUL, NUL, NUL, NUL,
- 'x', 'z', 'a', 's', 'd', 'c', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'c', 'x', 's', 'd', 'f', 'v', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'v', 'c', 'd', 'f', 'g', 'b', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'b', 'v', 'f', 'g', 'h', 'n', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'n', 'b', 'g', 'h', 'j', 'm', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- 'm', 'n', 'h', 'j', 'k', 'l', 'o', 'p', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
- };
- static {
- for (int i = 0; i < PROXIMITY.length; i += ROW_SIZE) {
- if (NUL != PROXIMITY[i]) INDICES.put(PROXIMITY[i], i);
+ 'a', 'z', 'x', 's', 'w', 'q', 'e', 'i', 'o', 'u', NUL, NUL, NUL, NUL, NUL, NUL,
+ 's', 'q', 'a', 'z', 'x', 'c', 'd', 'e', 'w', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'd', 'w', 's', 'x', 'c', 'v', 'f', 'r', 'e', 'w', NUL, NUL, NUL, NUL, NUL, NUL,
+ 'f', 'e', 'd', 'c', 'v', 'b', 'g', 't', 'r', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'g', 'r', 'f', 'v', 'b', 'n', 'h', 'y', 't', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'h', 't', 'g', 'b', 'n', 'm', 'j', 'u', 'y', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'j', 'y', 'h', 'n', 'm', 'k', 'i', 'u', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'k', 'u', 'j', 'm', 'l', 'o', 'i', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'l', 'i', 'k', 'p', 'o', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+
+ 'z', 'a', 's', 'd', 'x', 't', 'g', 'h', 'j', 'u', 'q', 'e', NUL, NUL, NUL, NUL,
+ 'x', 'z', 'a', 's', 'd', 'c', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'c', 'x', 's', 'd', 'f', 'v', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'v', 'c', 'd', 'f', 'g', 'b', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'b', 'v', 'f', 'g', 'h', 'n', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'n', 'b', 'g', 'h', 'j', 'm', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'm', 'n', 'h', 'j', 'k', 'l', 'o', 'p', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ };
+ static {
+ buildProximityIndices(PROXIMITY, INDICES);
+ }
+ static int getIndexOf(int characterCode) {
+ return computeIndex(characterCode, INDICES);
}
}
- public static int getIndexOf(int characterCode) {
- final Integer result = INDICES.get(characterCode);
- if (null == result) return -1;
- return result;
+
+ private static class Cyrillic {
+ final private static TreeMap<Integer, Integer> INDICES = new TreeMap<Integer, Integer>();
+ final static int[] PROXIMITY = {
+ // TODO: This table is solely based on the keyboard layout. Consult with Russian
+ // speakers on commonly misspelled words/letters.
+ 'й', 'ц', 'ф', 'ы', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'ц', 'й', 'ф', 'ы', 'в', 'у', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'у', 'ц', 'ы', 'в', 'а', 'к', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'к', 'у', 'в', 'а', 'п', 'е', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'е', 'к', 'а', 'п', 'р', 'н', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'н', 'е', 'п', 'р', 'о', 'г', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'г', 'н', 'р', 'о', 'л', 'ш', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'ш', 'г', 'о', 'л', 'д', 'щ', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'щ', 'ш', 'л', 'д', 'ж', 'з', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'з', 'щ', 'д', 'ж', 'э', 'х', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'х', 'з', 'ж', 'э', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+
+ 'ф', 'й', 'ц', 'ы', 'я', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'ы', 'й', 'ц', 'у', 'ф', 'в', 'я', 'ч', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'в', 'ц', 'у', 'к', 'ы', 'а', 'я', 'ч', 'с', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'а', 'у', 'к', 'е', 'в', 'п', 'ч', 'с', 'м', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'п', 'к', 'е', 'н', 'а', 'р', 'с', 'м', 'и', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'р', 'е', 'н', 'г', 'п', 'о', 'м', 'и', 'т', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'о', 'н', 'г', 'ш', 'р', 'л', 'и', 'т', 'ь', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'л', 'г', 'ш', 'щ', 'о', 'д', 'т', 'ь', 'б', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'д', 'ш', 'щ', 'з', 'л', 'ж', 'ь', 'б', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'ж', 'щ', 'з', 'х', 'д', 'э', 'б', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'э', 'з', 'х', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+
+ 'я', 'ф', 'ы', 'в', 'ч', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'ч', 'ы', 'в', 'а', 'я', 'с', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'с', 'в', 'а', 'п', 'ч', 'м', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'м', 'а', 'п', 'р', 'с', 'и', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'и', 'п', 'р', 'о', 'м', 'т', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'т', 'р', 'о', 'л', 'и', 'ь', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'ь', 'о', 'л', 'д', 'т', 'б', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'б', 'л', 'д', 'ж', 'ь', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'ю', 'д', 'ж', 'э', 'б', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ };
+ static {
+ buildProximityIndices(PROXIMITY, INDICES);
+ }
+ static int getIndexOf(int characterCode) {
+ return computeIndex(characterCode, INDICES);
+ }
+ }
+
+ public static int[] getProximityForScript(final int script) {
+ switch (script) {
+ case AndroidSpellCheckerService.SCRIPT_LATIN:
+ return Latin.PROXIMITY;
+ case AndroidSpellCheckerService.SCRIPT_CYRILLIC:
+ return Cyrillic.PROXIMITY;
+ default:
+ throw new RuntimeException("Wrong script supplied: " + script);
+ }
+ }
+ public static int getIndexOfCodeForScript(final int characterCode, final int script) {
+ switch (script) {
+ case AndroidSpellCheckerService.SCRIPT_LATIN:
+ return Latin.getIndexOf(characterCode);
+ case AndroidSpellCheckerService.SCRIPT_CYRILLIC:
+ return Cyrillic.getIndexOf(characterCode);
+ default:
+ throw new RuntimeException("Wrong script supplied: " + script);
+ }
}
}
diff --git a/java/src/com/android/inputmethod/latin/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
index 9a59ef2e0..3d26d972d 100644
--- a/java/src/com/android/inputmethod/latin/MoreSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
@@ -14,7 +14,7 @@
* the License.
*/
-package com.android.inputmethod.latin;
+package com.android.inputmethod.latin.suggestions;
import android.content.res.Resources;
import android.graphics.Paint;
@@ -25,26 +25,27 @@ import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.KeyboardView;
-import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
-import com.android.inputmethod.keyboard.internal.KeyboardParams;
+import com.android.inputmethod.latin.LatinImeLogger;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
public class MoreSuggestions extends Keyboard {
- private static final boolean DBG = LatinImeLogger.sDBG;
-
public static final int SUGGESTION_CODE_BASE = 1024;
private MoreSuggestions(Builder.MoreSuggestionsParam params) {
super(params);
}
- public static class Builder extends KeyboardBuilder<Builder.MoreSuggestionsParam> {
+ public static class Builder extends Keyboard.Builder<Builder.MoreSuggestionsParam> {
+ private static final boolean DBG = LatinImeLogger.sDBG;
+
private final MoreSuggestionsView mPaneView;
private SuggestedWords mSuggestions;
private int mFromPos;
private int mToPos;
- public static class MoreSuggestionsParam extends KeyboardParams {
+ public static class MoreSuggestionsParam extends Keyboard.Params {
private final int[] mWidths = new int[SuggestionsView.MAX_SUGGESTIONS];
private final int[] mRowNumbers = new int[SuggestionsView.MAX_SUGGESTIONS];
private final int[] mColumnOrders = new int[SuggestionsView.MAX_SUGGESTIONS];
@@ -176,9 +177,9 @@ public class MoreSuggestions extends Keyboard {
public Builder layout(SuggestedWords suggestions, int fromPos, int maxWidth,
int minWidth, int maxRow) {
- final Keyboard keyboard = KeyboardSwitcher.getInstance().getLatinKeyboard();
+ final Keyboard keyboard = KeyboardSwitcher.getInstance().getKeyboard();
final int xmlId = R.xml.kbd_suggestions_pane_template;
- load(keyboard.mId.cloneWithNewXml(mResources.getResourceEntryName(xmlId), xmlId));
+ load(xmlId, keyboard.mId);
mParams.mVerticalGap = mParams.mTopPadding = keyboard.mVerticalGap / 2;
final int count = mParams.layout(suggestions, fromPos, maxWidth, minWidth, maxRow,
diff --git a/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
index c61dd6313..b5f67ace0 100644
--- a/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.inputmethod.latin;
+package com.android.inputmethod.latin.suggestions;
import android.content.Context;
import android.content.res.Resources;
@@ -34,6 +34,7 @@ import com.android.inputmethod.keyboard.PointerTracker;
import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy;
import com.android.inputmethod.keyboard.PointerTracker.KeyEventHandler;
import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
+import com.android.inputmethod.latin.R;
/**
* A view that renders a virtual {@link MoreSuggestions}. It handles rendering of keys and detecting
diff --git a/java/src/com/android/inputmethod/latin/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
index c25ecb382..40d782640 100644
--- a/java/src/com/android/inputmethod/latin/SuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
@@ -14,7 +14,7 @@
* the License.
*/
-package com.android.inputmethod.latin;
+package com.android.inputmethod.latin.suggestions;
import android.content.Context;
import android.content.res.Resources;
@@ -30,7 +30,6 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Message;
-import android.os.SystemClock;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
@@ -58,7 +57,12 @@ import com.android.inputmethod.keyboard.KeyboardActionListener;
import com.android.inputmethod.keyboard.KeyboardView;
import com.android.inputmethod.keyboard.MoreKeysPanel;
import com.android.inputmethod.keyboard.PointerTracker;
+import com.android.inputmethod.latin.LatinImeLogger;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
+import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.Utils;
import java.util.ArrayList;
import java.util.List;
@@ -73,7 +77,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
// The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}.
public static final int MAX_SUGGESTIONS = 18;
- private static final boolean DBG = LatinImeLogger.sDBG;
+ static final boolean DBG = LatinImeLogger.sDBG;
private final ViewGroup mSuggestionsStrip;
private KeyboardView mKeyboardView;
@@ -101,8 +105,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
private static class UiHandler extends StaticInnerHandlerWrapper<SuggestionsView> {
private static final int MSG_HIDE_PREVIEW = 0;
- private static final long DELAY_HIDE_PREVIEW = 1300;
-
public UiHandler(SuggestionsView outerInstance) {
super(outerInstance);
}
@@ -117,11 +119,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
}
}
- public void postHidePreview() {
- cancelHidePreview();
- sendMessageDelayed(obtainMessage(MSG_HIDE_PREVIEW), DELAY_HIDE_PREVIEW);
- }
-
public void cancelHidePreview() {
removeMessages(MSG_HIDE_PREVIEW);
}
@@ -149,6 +146,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
private final List<View> mDividers;
private final List<TextView> mInfos;
+ private final int mColorValidTypedWord;
private final int mColorTypedWord;
private final int mColorAutoCorrect;
private final int mColorSuggested;
@@ -172,7 +170,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
public final TextView mWordToSaveView;
private final TextView mHintToSaveView;
- private final CharSequence mHintToSaveText;
public SuggestionsViewParams(Context context, AttributeSet attrs, int defStyle,
List<TextView> words, List<View> dividers, List<TextView> infos) {
@@ -193,6 +190,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.SuggestionsView, defStyle, R.style.SuggestionsViewStyle);
mSuggestionStripOption = a.getInt(R.styleable.SuggestionsView_suggestionStripOption, 0);
+ final float alphaValidTypedWord = getPercent(a,
+ R.styleable.SuggestionsView_alphaValidTypedWord, 100);
final float alphaTypedWord = getPercent(a,
R.styleable.SuggestionsView_alphaTypedWord, 100);
final float alphaAutoCorrect = getPercent(a,
@@ -200,6 +199,9 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
final float alphaSuggested = getPercent(a,
R.styleable.SuggestionsView_alphaSuggested, 100);
mAlphaObsoleted = getPercent(a, R.styleable.SuggestionsView_alphaSuggested, 100);
+ mColorValidTypedWord = applyAlpha(
+ a.getColor(R.styleable.SuggestionsView_colorValidTypedWord, 0),
+ alphaValidTypedWord);
mColorTypedWord = applyAlpha(
a.getColor(R.styleable.SuggestionsView_colorTypedWord, 0), alphaTypedWord);
mColorAutoCorrect = applyAlpha(
@@ -228,7 +230,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
final LayoutInflater inflater = LayoutInflater.from(context);
mWordToSaveView = (TextView)inflater.inflate(R.layout.suggestion_word, null);
mHintToSaveView = (TextView)inflater.inflate(R.layout.suggestion_word, null);
- mHintToSaveText = context.getText(R.string.hint_add_to_dictionary);
}
private static Drawable getMoreSuggestionsHint(Resources res, float textSize, int color) {
@@ -298,6 +299,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
final int color;
if (index == mCenterSuggestionIndex && Utils.willAutoCorrect(suggestions)) {
color = mColorAutoCorrect;
+ } else if (index == mCenterSuggestionIndex && suggestions.mTypedWordValid) {
+ color = mColorValidTypedWord;
} else if (isSuggested) {
color = mColorSuggested;
} else {
@@ -433,7 +436,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
final TextView word = mWords.get(index);
word.setEnabled(true);
- word.setTextColor(mColorTypedWord);
+ word.setTextColor(mColorAutoCorrect);
final CharSequence text = suggestions.getWord(index);
word.setText(text);
word.setTextScaleX(1.0f);
@@ -445,7 +448,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
}
public void layoutAddToDictionaryHint(CharSequence word, ViewGroup stripView,
- int stripWidth) {
+ int stripWidth, CharSequence hintText) {
final int width = stripWidth - mDividerWidth - mPadding * 2;
final TextView wordView = mWordToSaveView;
@@ -464,13 +467,98 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
final TextView hintView = mHintToSaveView;
hintView.setTextColor(mColorAutoCorrect);
final int hintWidth = width - wordWidth;
- final float hintScaleX = getTextScaleX(mHintToSaveText, hintWidth, hintView.getPaint());
- hintView.setText(mHintToSaveText);
+ final float hintScaleX = getTextScaleX(hintText, hintWidth, hintView.getPaint());
+ hintView.setText(hintText);
hintView.setTextScaleX(hintScaleX);
stripView.addView(hintView);
setLayoutWeight(
hintView, 1.0f - mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT);
}
+
+ private static CharSequence getDebugInfo(SuggestedWords suggestions, int pos) {
+ if (DBG && pos < suggestions.size()) {
+ final SuggestedWordInfo wordInfo = suggestions.getInfo(pos);
+ if (wordInfo != null) {
+ final CharSequence debugInfo = wordInfo.getDebugString();
+ if (!TextUtils.isEmpty(debugInfo)) {
+ return debugInfo;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static void setLayoutWeight(View v, float weight, int height) {
+ final ViewGroup.LayoutParams lp = v.getLayoutParams();
+ if (lp instanceof LinearLayout.LayoutParams) {
+ final LinearLayout.LayoutParams llp = (LinearLayout.LayoutParams)lp;
+ llp.weight = weight;
+ llp.width = 0;
+ llp.height = height;
+ }
+ }
+
+ private static float getTextScaleX(CharSequence text, int maxWidth, TextPaint paint) {
+ paint.setTextScaleX(1.0f);
+ final int width = getTextWidth(text, paint);
+ if (width <= maxWidth) {
+ return 1.0f;
+ }
+ return maxWidth / (float)width;
+ }
+
+ private static CharSequence getEllipsizedText(CharSequence text, int maxWidth,
+ TextPaint paint) {
+ if (text == null) return null;
+ paint.setTextScaleX(1.0f);
+ final int width = getTextWidth(text, paint);
+ if (width <= maxWidth) {
+ return text;
+ }
+ final float scaleX = maxWidth / (float)width;
+ if (scaleX >= MIN_TEXT_XSCALE) {
+ paint.setTextScaleX(scaleX);
+ return text;
+ }
+
+ // Note that TextUtils.ellipsize() use text-x-scale as 1.0 if ellipsize is needed. To
+ // get squeezed and ellipsized text, passes enlarged width (maxWidth / MIN_TEXT_XSCALE).
+ final CharSequence ellipsized = TextUtils.ellipsize(
+ text, paint, maxWidth / MIN_TEXT_XSCALE, TextUtils.TruncateAt.MIDDLE);
+ paint.setTextScaleX(MIN_TEXT_XSCALE);
+ return ellipsized;
+ }
+
+ private static int getTextWidth(CharSequence text, TextPaint paint) {
+ if (TextUtils.isEmpty(text)) return 0;
+ final Typeface savedTypeface = paint.getTypeface();
+ paint.setTypeface(getTextTypeface(text));
+ final int len = text.length();
+ final float[] widths = new float[len];
+ final int count = paint.getTextWidths(text, 0, len, widths);
+ int width = 0;
+ for (int i = 0; i < count; i++) {
+ width += Math.round(widths[i] + 0.5f);
+ }
+ paint.setTypeface(savedTypeface);
+ return width;
+ }
+
+ private static Typeface getTextTypeface(CharSequence text) {
+ if (!(text instanceof SpannableString))
+ return Typeface.DEFAULT;
+
+ final SpannableString ss = (SpannableString)text;
+ final StyleSpan[] styles = ss.getSpans(0, text.length(), StyleSpan.class);
+ if (styles.length == 0)
+ return Typeface.DEFAULT;
+
+ switch (styles[0].getStyle()) {
+ case Typeface.BOLD: return Typeface.DEFAULT_BOLD;
+ // TODO: BOLD_ITALIC, ITALIC case?
+ default: return Typeface.DEFAULT;
+ }
+ }
}
/**
@@ -557,99 +645,15 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
mParams.layout(mSuggestions, mSuggestionsStrip, this, getWidth());
}
- private static CharSequence getDebugInfo(SuggestedWords suggestions, int pos) {
- if (DBG && pos < suggestions.size()) {
- final SuggestedWordInfo wordInfo = suggestions.getInfo(pos);
- if (wordInfo != null) {
- final CharSequence debugInfo = wordInfo.getDebugString();
- if (!TextUtils.isEmpty(debugInfo)) {
- return debugInfo;
- }
- }
- }
- return null;
- }
-
- private static void setLayoutWeight(View v, float weight, int height) {
- final ViewGroup.LayoutParams lp = v.getLayoutParams();
- if (lp instanceof LinearLayout.LayoutParams) {
- final LinearLayout.LayoutParams llp = (LinearLayout.LayoutParams)lp;
- llp.weight = weight;
- llp.width = 0;
- llp.height = height;
- }
- }
-
- private static float getTextScaleX(CharSequence text, int maxWidth, TextPaint paint) {
- paint.setTextScaleX(1.0f);
- final int width = getTextWidth(text, paint);
- if (width <= maxWidth) {
- return 1.0f;
- }
- return maxWidth / (float)width;
- }
-
- private static CharSequence getEllipsizedText(CharSequence text, int maxWidth,
- TextPaint paint) {
- if (text == null) return null;
- paint.setTextScaleX(1.0f);
- final int width = getTextWidth(text, paint);
- if (width <= maxWidth) {
- return text;
- }
- final float scaleX = maxWidth / (float)width;
- if (scaleX >= MIN_TEXT_XSCALE) {
- paint.setTextScaleX(scaleX);
- return text;
- }
-
- // Note that TextUtils.ellipsize() use text-x-scale as 1.0 if ellipsize is needed. To get
- // squeezed and ellipsized text, passes enlarged width (maxWidth / MIN_TEXT_XSCALE).
- final CharSequence ellipsized = TextUtils.ellipsize(
- text, paint, maxWidth / MIN_TEXT_XSCALE, TextUtils.TruncateAt.MIDDLE);
- paint.setTextScaleX(MIN_TEXT_XSCALE);
- return ellipsized;
- }
-
- private static int getTextWidth(CharSequence text, TextPaint paint) {
- if (TextUtils.isEmpty(text)) return 0;
- final Typeface savedTypeface = paint.getTypeface();
- paint.setTypeface(getTextTypeface(text));
- final int len = text.length();
- final float[] widths = new float[len];
- final int count = paint.getTextWidths(text, 0, len, widths);
- int width = 0;
- for (int i = 0; i < count; i++) {
- width += Math.round(widths[i] + 0.5f);
- }
- paint.setTypeface(savedTypeface);
- return width;
- }
-
- private static Typeface getTextTypeface(CharSequence text) {
- if (!(text instanceof SpannableString))
- return Typeface.DEFAULT;
-
- final SpannableString ss = (SpannableString)text;
- final StyleSpan[] styles = ss.getSpans(0, text.length(), StyleSpan.class);
- if (styles.length == 0)
- return Typeface.DEFAULT;
-
- switch (styles[0].getStyle()) {
- case Typeface.BOLD: return Typeface.DEFAULT_BOLD;
- // TODO: BOLD_ITALIC, ITALIC case?
- default: return Typeface.DEFAULT;
- }
- }
public boolean isShowingAddToDictionaryHint() {
return mSuggestionsStrip.getChildCount() > 0
&& mSuggestionsStrip.getChildAt(0) == mParams.mWordToSaveView;
}
- public void showAddToDictionaryHint(CharSequence word) {
+ public void showAddToDictionaryHint(CharSequence word, CharSequence hintText) {
clear();
- mParams.layoutAddToDictionaryHint(word, mSuggestionsStrip, getWidth());
+ mParams.layoutAddToDictionaryHint(word, mSuggestionsStrip, getWidth(), hintText);
}
public boolean dismissAddToDictionaryHint() {
@@ -675,34 +679,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
mPreviewPopup.dismiss();
}
- private void showPreview(View view, CharSequence word) {
- if (TextUtils.isEmpty(word))
- return;
-
- final TextView previewText = mPreviewText;
- previewText.setTextColor(mParams.mColorTypedWord);
- previewText.setText(word);
- previewText.measure(
- ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- final int[] offsetInWindow = new int[2];
- view.getLocationInWindow(offsetInWindow);
- final int posX = offsetInWindow[0];
- final int posY = offsetInWindow[1] - previewText.getMeasuredHeight();
- final PopupWindow previewPopup = mPreviewPopup;
- if (previewPopup.isShowing()) {
- previewPopup.update(posX, posY, previewPopup.getWidth(), previewPopup.getHeight());
- } else {
- previewPopup.showAtLocation(this, Gravity.NO_GRAVITY, posX, posY);
- }
- previewText.setVisibility(VISIBLE);
- mHandler.postHidePreview();
- }
-
private void addToDictionary(CharSequence word) {
- if (mListener.addWordToDictionary(word.toString())) {
- final CharSequence message = getContext().getString(R.string.added_word, word);
- showPreview(mParams.mWordToSaveView, message);
- }
+ mListener.addWordToDictionary(word.toString());
}
private final KeyboardActionListener mMoreSuggestionsListener =
@@ -832,8 +810,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
// Decided to be in the sliding input mode only when the touch point has been moved
// upward.
mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_SLIDING_MODE;
- tracker.onShowMoreKeysPanel(
- translatedX, translatedY, SystemClock.uptimeMillis(), moreKeysPanel);
+ tracker.onShowMoreKeysPanel(translatedX, translatedY, moreKeysPanel);
} else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) {
// Decided to be in the modal input mode
mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_MODAL_MODE;