aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/res/layout/seek_bar_dialog.xml (renamed from java/res/layout/sound_effect_volume_dialog.xml)7
-rw-r--r--java/res/layout/vibration_settings_dialog.xml49
-rw-r--r--java/res/raw/main_fr.dictbin1329621 -> 1329620 bytes
-rw-r--r--java/res/values-af/strings.xml2
-rw-r--r--java/res/values-am/strings.xml2
-rw-r--r--java/res/values-ar/strings.xml2
-rw-r--r--java/res/values-be/strings.xml2
-rw-r--r--java/res/values-bg/strings.xml2
-rw-r--r--java/res/values-ca/strings.xml2
-rw-r--r--java/res/values-cs/strings.xml2
-rw-r--r--java/res/values-da/strings.xml2
-rw-r--r--java/res/values-de/strings.xml2
-rw-r--r--java/res/values-el/strings.xml2
-rw-r--r--java/res/values-en-rGB/strings.xml8
-rw-r--r--java/res/values-es-rUS/strings.xml4
-rw-r--r--java/res/values-es/strings.xml2
-rw-r--r--java/res/values-et/strings.xml2
-rw-r--r--java/res/values-fa/strings.xml2
-rw-r--r--java/res/values-fi/strings.xml2
-rw-r--r--java/res/values-fr/strings.xml2
-rw-r--r--java/res/values-hi/strings.xml2
-rw-r--r--java/res/values-hr/strings.xml2
-rw-r--r--java/res/values-hu/strings.xml2
-rw-r--r--java/res/values-in/strings.xml2
-rw-r--r--java/res/values-is/strings.xml2
-rw-r--r--java/res/values-it/strings.xml2
-rw-r--r--java/res/values-iw/strings.xml2
-rw-r--r--java/res/values-ja/strings.xml2
-rw-r--r--java/res/values-ka/strings.xml2
-rw-r--r--java/res/values-ko/strings.xml2
-rw-r--r--java/res/values-lt/strings.xml2
-rw-r--r--java/res/values-lv/strings.xml2
-rw-r--r--java/res/values-mk/strings.xml2
-rw-r--r--java/res/values-mn/strings.xml2
-rw-r--r--java/res/values-ms/strings.xml2
-rw-r--r--java/res/values-nb/strings.xml2
-rw-r--r--java/res/values-nl/strings.xml2
-rw-r--r--java/res/values-pl/strings-appname.xml9
-rw-r--r--java/res/values-pl/strings.xml2
-rw-r--r--java/res/values-pt-rPT/strings.xml2
-rw-r--r--java/res/values-pt/strings.xml2
-rw-r--r--java/res/values-rm/strings.xml2
-rw-r--r--java/res/values-ro/strings.xml2
-rw-r--r--java/res/values-ru/strings.xml2
-rw-r--r--java/res/values-sk/strings.xml2
-rw-r--r--java/res/values-sl/strings.xml2
-rw-r--r--java/res/values-sr/strings.xml2
-rw-r--r--java/res/values-sv/strings.xml2
-rw-r--r--java/res/values-sw/strings.xml2
-rw-r--r--java/res/values-th/strings.xml2
-rw-r--r--java/res/values-tl/strings.xml2
-rw-r--r--java/res/values-tr/strings.xml2
-rw-r--r--java/res/values-uk/strings.xml2
-rw-r--r--java/res/values-vi/strings.xml2
-rw-r--r--java/res/values-zh-rCN/strings.xml2
-rw-r--r--java/res/values-zh-rTW/strings.xml2
-rw-r--r--java/res/values-zu/strings.xml2
-rw-r--r--java/res/values/donottranslate.xml1
-rw-r--r--java/res/values/keyboard-heights.xml2
-rw-r--r--java/res/values/keypress-vibration-durations.xml2
-rw-r--r--java/res/values/keypress-volumes.xml14
-rw-r--r--java/res/values/phantom-sudden-move-event-device-list.xml5
-rw-r--r--java/res/values/strings.xml3
-rw-r--r--java/res/values/sudden-jumping-touch-event-device-list.xml8
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java132
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java21
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java67
-rw-r--r--java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java45
-rw-r--r--java/src/com/android/inputmethod/compat/CompatUtils.java26
-rw-r--r--java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java16
-rw-r--r--java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java6
-rw-r--r--java/src/com/android/inputmethod/compat/InputMethodServiceCompatUtils.java7
-rw-r--r--java/src/com/android/inputmethod/compat/SettingsSecureCompatUtils.java4
-rw-r--r--java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java20
-rw-r--r--java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java11
-rw-r--r--java/src/com/android/inputmethod/event/Event.java56
-rw-r--r--java/src/com/android/inputmethod/event/EventInterpreter.java64
-rw-r--r--java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java37
-rw-r--r--java/src/com/android/inputmethod/event/SoftwareEventDecoder.java7
-rw-r--r--java/src/com/android/inputmethod/event/SoftwareKeyboardEventDecoder.java27
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java35
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java5
-rw-r--r--java/src/com/android/inputmethod/keyboard/MainKeyboardView.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java49
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java179
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java36
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java11
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java108
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/TouchScreenRegulator.java2
-rw-r--r--java/src/com/android/inputmethod/latin/AdditionalSubtype.java2
-rw-r--r--java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java2
-rw-r--r--java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java58
-rw-r--r--java/src/com/android/inputmethod/latin/Constants.java5
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryCollection.java4
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java263
-rw-r--r--java/src/com/android/inputmethod/latin/LatinImeLogger.java2
-rw-r--r--java/src/com/android/inputmethod/latin/PositionalInfoForUserDictPendingAddition.java2
-rw-r--r--java/src/com/android/inputmethod/latin/ResourceUtils.java56
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputConnection.java100
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputMethodManager.java4
-rw-r--r--java/src/com/android/inputmethod/latin/SeekBarDialog.java179
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java417
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsActivity.java2
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsFragment.java375
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsValues.java43
-rw-r--r--java/src/com/android/inputmethod/latin/StringUtils.java17
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeLocale.java8
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeSwitcher.java79
-rw-r--r--java/src/com/android/inputmethod/latin/UserBinaryDictionary.java43
-rw-r--r--java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java3
-rw-r--r--java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java3
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java4
-rw-r--r--java/src/com/android/inputmethod/latin/VibratorUtils.java50
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java1
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java2
-rw-r--r--java/src/com/android/inputmethod/research/ResearchLogger.java67
-rw-r--r--java/src/com/android/inputmethod/research/Statistics.java13
117 files changed, 1790 insertions, 1205 deletions
diff --git a/java/res/layout/sound_effect_volume_dialog.xml b/java/res/layout/seek_bar_dialog.xml
index 294663006..a47e9a038 100644
--- a/java/res/layout/sound_effect_volume_dialog.xml
+++ b/java/res/layout/seek_bar_dialog.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2011, The Android Open Source Project
+** Copyright 2012, 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.
@@ -30,15 +30,14 @@
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_margin="10dp">
- <TextView android:id="@+id/sound_effect_volume_value"
+ <TextView android:id="@+id/seek_bar_dialog_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"/>
</LinearLayout>
<SeekBar
- android:id="@+id/sound_effect_volume_bar"
+ android:id="@+id/seek_bar_dialog_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:max="100"
android:layout_margin="10dp"/>
</LinearLayout>
diff --git a/java/res/layout/vibration_settings_dialog.xml b/java/res/layout/vibration_settings_dialog.xml
deleted file mode 100644
index c9fb6ec4e..000000000
--- a/java/res/layout/vibration_settings_dialog.xml
+++ /dev/null
@@ -1,49 +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.
-*/
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_margin="10dp">
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:layout_margin="10dp">
- <TextView android:id="@+id/vibration_value"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="20dp"/>
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/settings_ms"
- android:textSize="20dp"/>
- </LinearLayout>
- <SeekBar
- android:id="@+id/vibration_settings"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:max="250"
- android:layout_margin="10dp"/>
-</LinearLayout>
diff --git a/java/res/raw/main_fr.dict b/java/res/raw/main_fr.dict
index 5aed479c6..c2941b73a 100644
--- a/java/res/raw/main_fr.dict
+++ b/java/res/raw/main_fr.dict
Binary files differ
diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml
index 18e63f317..80b92320a 100644
--- a/java/res/values-af/strings.xml
+++ b/java/res/values-af/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Sleutelopspringer-wagperiode"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Geen wagperiode nie"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Verstek"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Stel kontakname voor"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Gebruik name van kontakte vir voorstelle en korreksies"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Dubbelspasie-punt"</string>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index 4f66a1676..a59e757ef 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"የቁልፍ ብቅ ባይ መዘግየትን ያስወገዳል"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"የዘገየ የለም"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ነባሪ"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"የዕውቂያ ስም ጠቁም"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"ከዕውቂያዎች ለጥቆማዎች እና ማስተካከያዎች ስሞች ተጠቀም"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"የድርብ-ክፍተት ነጥብ"</string>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index a3877ed49..c3691cd7a 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"تأخير إزالة النافذة المنبثقة الأساسية"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"بلا تأخير"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"افتراضي"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"اقتراح أسماء جهات الاتصال"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"استخدام الأسماء من جهات الاتصال للاقتراحات والتصحيحات"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"نقطة المسافة المزدوجة"</string>
diff --git a/java/res/values-be/strings.xml b/java/res/values-be/strings.xml
index bf396943f..edbd9c3ac 100644
--- a/java/res/values-be/strings.xml
+++ b/java/res/values-be/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Затрым. скр. падк. клав."</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Няма затрымкі"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Па змаўчанні"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Прапан. імёны кантактаў"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Выкарыстоўваць імёны са спісу кантактаў для прапаноў і выпраўл."</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Падвойны iнтэрвал"</string>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index 27d3ac7d5..25030d2b2 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Отхвърляне на подсказката"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Без задържане"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"По подразбиране"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Предложения за контакти"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Използване на имена от „Контакти“ за предложения и поправки"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Точка чрез двоен интервал"</string>
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index 0182dd492..3f73e9085 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retard en ampliar tecla"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sense retard"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminat"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Suggereix noms de contactes"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilitza els noms de contactes per fer suggeriments i correccions"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Punt amb doble espai"</string>
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index 806ac1291..d438ad6e5 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Prodleva vysk. okna klávesnice"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez prodlevy"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Výchozí"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Navrhovat jména kontaktů"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Použít jména ze seznamu kontaktů k návrhům a opravám"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Tečka dvojitým mezerníkem"</string>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index 4fbfe905d..da83d1cac 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Forsink. afvis. af taste-pop op"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Ingen forsink."</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Foreslå navne på kontakter"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Brug navne fra Kontaktpersoner til forslag og rettelser"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"To mellemrum for punktum"</string>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index 1fad9e710..3cdb039af 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tasten-Pop-up"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Keine Verzögerung"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Kontakte vorschlagen"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Namen aus \"Kontakte\" als Vorschläge und Korrekturmöglichkeiten anzeigen"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Punkt plus Leerzeichen"</string>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index 2b99e7e00..8dcc202ce 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Χρόνος εξαφ. αναδ. παραθ."</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Χωρίς καθυστέρ."</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Προεπιλογή"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Πρόταση ονομάτων επαφών"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Χρησιμοποιήστε ονόματα από τις Επαφές για προτάσεις και διορθ."</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Τελεία με διπλό πάτημα πλήκτρ.διαστ."</string>
diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml
index 652d5aa46..7a3b3e612 100644
--- a/java/res/values-en-rGB/strings.xml
+++ b/java/res/values-en-rGB/strings.xml
@@ -42,12 +42,12 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Key pop-up dismiss delay"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"No delay"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Suggest Contact names"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Use names from Contacts for suggestions and corrections"</string>
- <!-- no translation found for use_double_space_period (8781529969425082860) -->
- <skip />
- <!-- no translation found for use_double_space_period_summary (6532892187247952799) -->
- <skip />
+ <string name="use_double_space_period" msgid="8781529969425082860">"Double-space full stop"</string>
+ <string name="use_double_space_period_summary" msgid="6532892187247952799">"Double tap on spacebar inserts a full stop followed by a space"</string>
<string name="auto_cap" msgid="1719746674854628252">"Auto-capitalisation"</string>
<string name="auto_cap_summary" msgid="7934452761022946874">"Capitalise the first word of each sentence"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Add-on dictionaries"</string>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index 9e87970de..ec9614fbe 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso en rechazo de alerta de tecla"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sin demora"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminada"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nombres de contacto"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Usar nombres de los contactos para sugerencias y correcciones"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Punto y doble espacio"</string>
@@ -63,7 +65,7 @@
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muy agresivo"</string>
<string name="bigram_prediction" msgid="1084449187723948550">"Sugerencias para la palabra siguiente"</string>
<string name="bigram_prediction_summary" msgid="3896362682751109677">"Usa la palabra anterior para hacer sugerencias"</string>
- <string name="gesture_input" msgid="826951152254563827">"Habilitar escritura gestual"</string>
+ <string name="gesture_input" msgid="826951152254563827">"Activar escritura gestual"</string>
<string name="gesture_input_summary" msgid="9180350639305731231">"Ingresa una palabra al deslizarte sobre las letras."</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Mostrar recorrido de gesto"</string>
<string name="gesture_floating_preview_text" msgid="4443240334739381053">"Vista previa dinámica flotante"</string>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index 24335e65a..061516a62 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso al ampliar tecla"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sin retraso"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminado"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir contactos"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizar nombres de contactos para sugerencias y correcciones"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Punto y espacio"</string>
diff --git a/java/res/values-et/strings.xml b/java/res/values-et/strings.xml
index 25dcdca73..1158a2126 100644
--- a/java/res/values-et/strings.xml
+++ b/java/res/values-et/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Hüpiku loobumisviivitus"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Viivituseta"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Vaikeseade"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Soovita kontaktkirjeid"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Kasuta soovitusteks ja parandusteks nimesid kontaktiloendist"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Punkt tühikuklahviga"</string>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index d4a0e66b0..1fb577cd9 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"تأخیر در رد کردن کلید نمایشی"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"بدون تأخیر"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"پیش‌فرض"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"پیشنهاد نام‌های مخاطب"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"برای پیشنهاد و تصحیح از نام مخاطبین استفاده شود"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"نقطه با دو فاصله"</string>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index 36890d95a..9064e4a83 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Näppäimen hylkäysviive"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Ei viivettä"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Oletus"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Ehdota yhteystietojen nimiä"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Käytä yhteystietojen nimiä ehdotuksissa ja korjauksissa"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Kaksoisvälilyönti = piste"</string>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index 3f895325e..c251d27dc 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Masquer touche agrandie"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sans délai"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Par défaut"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Proposer noms de contacts"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utiliser des noms de contacts pour les suggestions et corrections"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Point et espace"</string>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index 6537b859e..738368205 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"कुंजी पॉपअप खारिज़ विलंब"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"कोई विलंब नहीं"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"डिफ़ॉल्ट"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"संपर्क नाम सुझाएं"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"सुझाव और सुधार के लिए संपर्क से नामों का उपयोग करें"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"दोहरे स्पेस वाला पीरियड"</string>
diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml
index d788c1f0e..014481ae9 100644
--- a/java/res/values-hr/strings.xml
+++ b/java/res/values-hr/strings.xml
@@ -42,6 +42,8 @@
<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>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Predlaži imena kontakata"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Upotreba imena iz Kontakata za prijedloge i ispravke"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Točka s dva razmaka"</string>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index 1df863927..f146c82ae 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Gombeltüntetés késése"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Nincs késés"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Alapbeállítás"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Javasolt névjegyek"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"A névjegyek használata a javaslatokhoz és javításokhoz"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Dupla szóköz: pont"</string>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index f26ad38a4..d3ae9a18d 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tundaan singkir munculan kunci"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Tanpa penundaan"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Sarankan nama Kontak"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Menggunakan nama dari Kontak untuk saran dan koreksi"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Titik spasi ganda"</string>
diff --git a/java/res/values-is/strings.xml b/java/res/values-is/strings.xml
index 8ea7461c2..016a1d1e5 100644
--- a/java/res/values-is/strings.xml
+++ b/java/res/values-is/strings.xml
@@ -64,6 +64,8 @@
<skip />
<!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) -->
<skip />
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<!-- no translation found for use_contacts_dict (4435317977804180815) -->
<skip />
<!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index a78c5c56a..3efed919d 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ritardo eliminaz. popup tasto"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Nessun ritardo"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predefinito"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Suggerisci nomi di contatti"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizza nomi di Contatti per suggerimenti e correzioni"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Doppio spazio per punto"</string>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index 6542b9fb4..2fec99439 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"עיכוב סגירת חלון קופץ של מקש"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"ללא עיכוב"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ברירת מחדל"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"הצע שמות של אנשי קשר"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"השתמש בשמות מרשימת אנשי הקשר עבור הצעות ותיקונים"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"רווח כפול לנקודה"</string>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index 2b341e116..8d01e75a3 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"キーのポップアップ時間"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"すぐに消去"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"デフォルト"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"候補の連絡先名を表示"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"連絡先の名前を使用して候補表示や自動修正を行います"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"ダブルスペースピリオド"</string>
diff --git a/java/res/values-ka/strings.xml b/java/res/values-ka/strings.xml
index ef3014401..b9ffbf6de 100644
--- a/java/res/values-ka/strings.xml
+++ b/java/res/values-ka/strings.xml
@@ -64,6 +64,8 @@
<skip />
<!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) -->
<skip />
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<!-- no translation found for use_contacts_dict (4435317977804180815) -->
<skip />
<!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index e7b9d5a75..c0c313a74 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"키 팝업 해제 지연"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"지연 없음"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"기본값"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"주소록 이름 활용"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"추천 및 수정에 주소록의 이름 사용"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"더블스페이스 마침표"</string>
diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml
index 5c66e1f22..39fbda6df 100644
--- a/java/res/values-lt/strings.xml
+++ b/java/res/values-lt/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Pagr. išš. l. atsis. d."</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Be delsos"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Numatytasis"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Siūlyti kontaktų vardus"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Siūlant ir taisant naudoti vardus iš „Kontaktų“"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Tšk. ir tarp. pal. dukart"</string>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index a0cf78e89..6bc47714d 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Taust. uzn. loga noraid. aizk."</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez aizkaves"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Noklusējums"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Ieteikt kontaktp. vārdus"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Izmantot kontaktpersonu vārdus kā ieteikumus un labojumus"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Dubultpiesk. = punkts"</string>
diff --git a/java/res/values-mk/strings.xml b/java/res/values-mk/strings.xml
index e199e0316..7758dbbe3 100644
--- a/java/res/values-mk/strings.xml
+++ b/java/res/values-mk/strings.xml
@@ -64,6 +64,8 @@
<skip />
<!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) -->
<skip />
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<!-- no translation found for use_contacts_dict (4435317977804180815) -->
<skip />
<!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
diff --git a/java/res/values-mn/strings.xml b/java/res/values-mn/strings.xml
index 41bf551ba..4d38079aa 100644
--- a/java/res/values-mn/strings.xml
+++ b/java/res/values-mn/strings.xml
@@ -64,6 +64,8 @@
<skip />
<!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) -->
<skip />
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<!-- no translation found for use_contacts_dict (4435317977804180815) -->
<skip />
<!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
diff --git a/java/res/values-ms/strings.xml b/java/res/values-ms/strings.xml
index c1a2f0d09..a0b498369 100644
--- a/java/res/values-ms/strings.xml
+++ b/java/res/values-ms/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Pop tmbl knci ketpkn lengah"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Tiada lengah"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Lalai"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Cadangkan nama Kenalan"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Menggunakan nama daripada Kenalan untuk cadangan dan pembetulan"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Titik ruang berganda"</string>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index f56ce1127..5bcedc11c 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tregt tastevindu"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"U/ forsinkelse"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Foreslå kontaktnavn"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Bruk navn fra Kontakter til forslag og korrigeringer"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Punktum ved doble mellomrom"</string>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index 6bd474a19..034b352a2 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Afwijz.vertr. toetspop-up"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Geen vertraging"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standaard"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Contactnamen suggereren"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Namen uit Contacten gebruiken voor suggesties en correcties"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Dubbeltik is punt, spatie"</string>
diff --git a/java/res/values-pl/strings-appname.xml b/java/res/values-pl/strings-appname.xml
index e460644a3..4d244d705 100644
--- a/java/res/values-pl/strings-appname.xml
+++ b/java/res/values-pl/strings-appname.xml
@@ -21,10 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="english_ime_name" msgid="178705338187710493">"Klawiatura Android"</string>
- <!-- no translation found for spell_checker_service_name (6268342166872202903) -->
- <skip />
- <!-- no translation found for english_ime_settings (7470027018752707691) -->
- <skip />
- <!-- no translation found for android_spell_checker_settings (8397842018475560441) -->
- <skip />
+ <string name="spell_checker_service_name" msgid="6268342166872202903">"Sprawdzanie pisowni w Androidzie"</string>
+ <string name="english_ime_settings" msgid="7470027018752707691">"Ustawienia klawiatury Android"</string>
+ <string name="android_spell_checker_settings" msgid="8397842018475560441">"Ustawienia sprawdzania pisowni"</string>
</resources>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index 27fcf60ba..4ddfa8d28 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Opóźnienie znikania klawiszy"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez opóźnienia"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Wartość domyślna"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Proponuj osoby z kontaktów"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"W propozycjach i poprawkach użyj nazwisk z kontaktów"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Szybka kropka ze spacją"</string>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index 46bd34d72..136470b85 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Atraso p/ ignorar pop-up"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sem atraso"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predefinido"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nomes de Contactos"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizar nomes dos Contactos para sugestões e correções"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Ponto de espaço duplo"</string>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index ce61e0c17..3408dde06 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Dispens. atraso chave princ."</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sem atraso"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Padrão"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nomes de contato"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Usar nomes dos Contatos para sugestões e correções"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Duplo espaço p/ ponto"</string>
diff --git a/java/res/values-rm/strings.xml b/java/res/values-rm/strings.xml
index 5a315f502..90d7357c3 100644
--- a/java/res/values-rm/strings.xml
+++ b/java/res/values-rm/strings.xml
@@ -61,6 +61,8 @@
<skip />
<!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) -->
<skip />
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<!-- no translation found for use_contacts_dict (4435317977804180815) -->
<skip />
<!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml
index 99b82a537..1b0176868 100644
--- a/java/res/values-ro/strings.xml
+++ b/java/res/values-ro/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Înt. înch. pop-up esenţ."</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Fără întârziere"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Prestabilit"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Sugeraţi nume din Agendă"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizaţi numele din Agendă pentru sugestii şi corecţii"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Inserează punct spațiu"</string>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index 1075d2994..2f1f7e6e3 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Задержка закрытия"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Без задержки"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"По умолчанию"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Подсказывать имена"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Подсказывать исправления на основе имен из списка контактов"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Точка с пробелом"</string>
diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml
index 1ee4f3324..55fae954b 100644
--- a/java/res/values-sk/strings.xml
+++ b/java/res/values-sk/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Onesk. zrušenia kľúč. kon. okna"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez oneskorenia"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predvolená"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Navrhnúť mená kontaktov"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Používať mená z Kontaktov na návrhy a opravy"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Bodka s medzerou"</string>
diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml
index 6ac740651..f8fd82121 100644
--- a/java/res/values-sl/strings.xml
+++ b/java/res/values-sl/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Trajanje povečanja tipke"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Brez zakasnitve"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Privzeto"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Predlagaj imena stikov"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Uporaba imen iz stikov za predloge in popravke"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Dva presl. za vnos pike"</string>
diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml
index 1456ae96f..f22fc2fc2 100644
--- a/java/res/values-sr/strings.xml
+++ b/java/res/values-sr/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Одложи одбац. иск. прозора тастера"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Без одлагања"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Подразумевано"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Предложи имена контаката"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Користи имена из Контаката за предлоге и исправке"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Тачка и размак"</string>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index f6426f9a2..ff72c1ab6 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ta bort popup-fördröjning"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Fördröj inte"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Föreslå kontaktnamn"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Använd namn från Kontakter för förslag och korrigeringar"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Dubbelt blanksteg = punkt"</string>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index 81b9003e8..5d84409c0 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Kuchelewesha kutupa kitufe ibukizi"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Hakuna kuchelewa"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Chaguo-msingi"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Pendekeza majini ya Anwani"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Tumia majina kutoka kwa Anwani kwa mapendekezo na marekebisho"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Kitone baada ya nafasi mbili"</string>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index d0890987e..6414e8fef 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"หน่วงเวลาก่อนปิดป๊อปอัพหลัก"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"ไม่มีการหน่วงเวลา"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ค่าเริ่มต้น"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"แนะนำชื่อผู้ติดต่อ"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"ใช้ชื่อจากรายชื่อติดต่อสำหรับคำแนะนำและการแก้ไข"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"แตะ Space สองครั้งแทรกจุด"</string>
diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml
index a16032e80..4c6c5329a 100644
--- a/java/res/values-tl/strings.xml
+++ b/java/res/values-tl/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Balewala antala key popup"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Walang antala"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Mungkahi pangalan Contact"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Gamitin pangalan mula Mga Contact sa mga mungkahi\'t pagwawasto"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Double-space period"</string>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index 7b3748c84..462f7c938 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tuş popup\'ının kapatılmasını geciktirme"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Gecikme yok"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Varsayılan"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Kişi Adları öner"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Öneri ve düzeltmeler için Kişiler\'deki adları kullan"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Çift boşlukla nokta ekleme"</string>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index 532f67147..819b6eaea 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Затримка клавіши закриття"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Без затримки"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"За умовчанням"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Пропон. імена контактів"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Використ. імена зі списку контактів для пропозицій і виправлень"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Крапка подвійним пробілом"</string>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index 2b29120c3..052f60c97 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Loại bỏ hiển thị phím trễ"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Không có tgian trễ"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Mặc định"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Đề xuất tên liên hệ"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Sử dụng tên từ Danh bạ cho các đề xuất và chỉnh sửa"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Dấu cách đôi"</string>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index ed663b753..b119ccdbd 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"弹出字符隐藏延迟"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"无延迟"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"默认"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"联系人姓名建议"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"使用联系人中的姓名提供建议和更正"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"双击空格插入句号"</string>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index 28d32cf38..02737c4a7 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"關閉彈出式鍵盤的延遲時間"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"不延遲"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"預設"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"建議聯絡人名稱"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"根據「聯絡人」名稱提供建議與修正"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"輕按兩下空格鍵即插入句號"</string>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index 575a687b5..65d23515e 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -42,6 +42,8 @@
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ukuvela kokhiye cashisa ukulibazisa"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Cha ukulibazisa"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Okuzenzakalelayo"</string>
+ <!-- no translation found for settings_keypress_vibration_duration (489402970497503329) -->
+ <skip />
<string name="use_contacts_dict" msgid="4435317977804180815">"Sikisela amagama Othintana nabo"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Amagama abasebenzisi kusuka Kothintana nabo bokusikisela nokulungisa"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"Isikhathi se-Double-space"</string>
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index a6ea8a061..193a0191e 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -233,6 +233,5 @@
<!-- dictionary pack package name /settings activity (for shared prefs and settings) -->
<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-heights.xml b/java/res/values/keyboard-heights.xml
index 7d85994be..418d3e5b6 100644
--- a/java/res/values/keyboard-heights.xml
+++ b/java/res/values/keyboard-heights.xml
@@ -33,5 +33,7 @@
<!-- Preferable keyboard height in absolute scale: 48.0mm -->
<!-- Xoom -->
<item>stingray,283.1337</item>
+ <!-- Default value for unknown device: empty string -->
+ <item>DEFAULT,</item>
</string-array>
</resources>
diff --git a/java/res/values/keypress-vibration-durations.xml b/java/res/values/keypress-vibration-durations.xml
index 370959c1a..9b1d5431e 100644
--- a/java/res/values/keypress-vibration-durations.xml
+++ b/java/res/values/keypress-vibration-durations.xml
@@ -24,5 +24,7 @@
<item>tuna,5</item>
<item>mako,5</item>
<item>manta,16</item>
+ <!-- Default value for unknown device -->
+ <item>DEFAULT,10</item>
</string-array>
</resources>
diff --git a/java/res/values/keypress-volumes.xml b/java/res/values/keypress-volumes.xml
index d1120694b..047fe0c5f 100644
--- a/java/res/values/keypress-volumes.xml
+++ b/java/res/values/keypress-volumes.xml
@@ -20,11 +20,13 @@
<resources>
<string-array name="keypress_volumes" translatable="false">
<!-- Build.HARDWARE,volume -->
- <item>herring,0.5</item>
- <item>tuna,0.5</item>
- <item>stingray,0.4</item>
- <item>grouper,0.3</item>
- <item>mako,0.3</item>
- <item>manta,0.2</item>
+ <item>herring,0.5f</item>
+ <item>tuna,0.5f</item>
+ <item>stingray,0.4f</item>
+ <item>grouper,0.3f</item>
+ <item>mako,0.3f</item>
+ <item>manta,0.2f</item>
+ <!-- Default value for unknown device -->
+ <item>DEFAULT,0.2f</item>
</string-array>
</resources>
diff --git a/java/res/values/phantom-sudden-move-event-device-list.xml b/java/res/values/phantom-sudden-move-event-device-list.xml
index 63d12e96e..22f510229 100644
--- a/java/res/values/phantom-sudden-move-event-device-list.xml
+++ b/java/res/values/phantom-sudden-move-event-device-list.xml
@@ -21,6 +21,9 @@
<string-array name="phantom_sudden_move_event_device_list" translatable="false">
<!-- "Build.HARDWARE,true" that needs "phantom sudden move event" hack.
See {@link com.android.inputmethod.keyboard.PointerTracker}. -->
- <item>stingray,true</item> <!-- Xoom -->
+ <!-- Xoom -->
+ <item>stingray,true</item>
+ <!-- Default value for unknown device -->
+ <item>DEFAULT,false</item>
</string-array>
</resources>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 2affdebed..5c5442708 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -76,6 +76,9 @@
<!-- Description for delay for dismissing a popup on screen: default value of the delay [CHAR LIMIT=15] -->
<string name="key_preview_popup_dismiss_default_delay">Default</string>
+ <!-- Units abbreviation for the keypress vibration duration (milliseconds) [CHAR LIMIT=10] -->
+ <string name="settings_keypress_vibration_duration"><xliff:g id="milliseconds">%s</xliff:g>ms</string>
+
<!-- Option name for enabling or disabling the use of names of people in Contacts for suggestion and correction [CHAR LIMIT=25] -->
<string name="use_contacts_dict">Suggest Contact names</string>
<!-- Description for option enabling or disabling the use of names of people in Contacts for suggestion and correction [CHAR LIMIT=65] -->
diff --git a/java/res/values/sudden-jumping-touch-event-device-list.xml b/java/res/values/sudden-jumping-touch-event-device-list.xml
index 543992a81..3fdc0c7e3 100644
--- a/java/res/values/sudden-jumping-touch-event-device-list.xml
+++ b/java/res/values/sudden-jumping-touch-event-device-list.xml
@@ -21,7 +21,11 @@
<string-array name="sudden_jumping_touch_event_device_list" translatable="false">
<!-- "Build.HARDWARE,true" that needs "sudden jump touch event" hack.
See {@link com.android.inputmethod.keyboard.SuddenJumpingTouchEventHandler}. -->
- <item>mahimahi,true</item> <!-- Nexus One -->
- <item>sholes,true</item> <!-- Droid -->
+ <!-- Nexus One -->
+ <item>mahimahi,true</item>
+ <!-- Droid -->
+ <item>sholes,true</item>
+ <!-- Default value for unknown device -->
+ <item>DEFAULT,false</item>
</string-array>
</resources>
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
index 0ab84f7b5..0576f666c 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
@@ -71,12 +71,11 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
/** The current keyboard view. */
private KeyboardView mKeyboardView;
- public AccessibilityEntityProvider(KeyboardView keyboardView, InputMethodService inputMethod) {
+ public AccessibilityEntityProvider(final KeyboardView keyboardView,
+ final InputMethodService inputMethod) {
mInputMethodService = inputMethod;
-
mKeyCodeDescriptionMapper = KeyCodeDescriptionMapper.getInstance();
mAccessibilityUtils = AccessibilityUtils.getInstance();
-
setView(keyboardView);
}
@@ -85,21 +84,19 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
*
* @param keyboardView The keyboard view to represent.
*/
- public void setView(KeyboardView keyboardView) {
+ public void setView(final KeyboardView keyboardView) {
mKeyboardView = keyboardView;
updateParentLocation();
// Since this class is constructed lazily, we might not get a subsequent
// call to setKeyboard() and therefore need to call it now.
- setKeyboard(mKeyboardView.getKeyboard());
+ setKeyboard();
}
/**
* Sets the keyboard represented by this node provider.
- *
- * @param keyboard The keyboard to represent.
*/
- public void setKeyboard(Keyboard keyboard) {
+ public void setKeyboard() {
assignVirtualViewIds();
}
@@ -112,19 +109,16 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
* @return A populated {@link AccessibilityEvent} for the key.
* @see AccessibilityEvent
*/
- public AccessibilityEvent createAccessibilityEvent(Key key, int eventType) {
+ public AccessibilityEvent createAccessibilityEvent(final Key key, final int eventType) {
final int virtualViewId = generateVirtualViewIdForKey(key);
final String keyDescription = getKeyDescription(key);
-
final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
event.setPackageName(mKeyboardView.getContext().getPackageName());
event.setClassName(key.getClass().getName());
event.setContentDescription(keyDescription);
event.setEnabled(true);
-
final AccessibilityRecordCompat record = new AccessibilityRecordCompat(event);
record.setSource(mKeyboardView, virtualViewId);
-
return event;
}
@@ -145,68 +139,65 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
* </p>
*
* @param virtualViewId A client defined virtual view id.
- * @return A populated {@link AccessibilityNodeInfoCompat} for a virtual
- * descendant or the host View.
+ * @return A populated {@link AccessibilityNodeInfoCompat} for a virtual descendant or the host
+ * View.
* @see AccessibilityNodeInfoCompat
*/
@Override
- public AccessibilityNodeInfoCompat createAccessibilityNodeInfo(int virtualViewId) {
- AccessibilityNodeInfoCompat info = null;
-
+ public AccessibilityNodeInfoCompat createAccessibilityNodeInfo(final int virtualViewId) {
if (virtualViewId == UNDEFINED) {
return null;
- } else if (virtualViewId == View.NO_ID) {
+ }
+ if (virtualViewId == View.NO_ID) {
// We are requested to create an AccessibilityNodeInfo describing
// this View, i.e. the root of the virtual sub-tree.
- info = AccessibilityNodeInfoCompat.obtain(mKeyboardView);
- ViewCompat.onInitializeAccessibilityNodeInfo(mKeyboardView, info);
+ final AccessibilityNodeInfoCompat rootInfo =
+ AccessibilityNodeInfoCompat.obtain(mKeyboardView);
+ ViewCompat.onInitializeAccessibilityNodeInfo(mKeyboardView, rootInfo);
// Add the virtual children of the root View.
final Keyboard keyboard = mKeyboardView.getKeyboard();
final Key[] keys = keyboard.mKeys;
for (Key key : keys) {
final int childVirtualViewId = generateVirtualViewIdForKey(key);
- info.addChild(mKeyboardView, childVirtualViewId);
- }
- } else {
- // Find the view that corresponds to the given id.
- final Key key = mVirtualViewIdToKey.get(virtualViewId);
- if (key == null) {
- Log.e(TAG, "Invalid virtual view ID: " + virtualViewId);
- return null;
- }
-
- final String keyDescription = getKeyDescription(key);
- final Rect boundsInParent = key.mHitBox;
-
- // Calculate the key's in-screen bounds.
- mTempBoundsInScreen.set(boundsInParent);
- mTempBoundsInScreen.offset(
- CoordinateUtils.x(mParentLocation), CoordinateUtils.y(mParentLocation));
-
- final Rect boundsInScreen = mTempBoundsInScreen;
-
- // Obtain and initialize an AccessibilityNodeInfo with
- // information about the virtual view.
- info = AccessibilityNodeInfoCompat.obtain();
- info.setPackageName(mKeyboardView.getContext().getPackageName());
- info.setClassName(key.getClass().getName());
- info.setContentDescription(keyDescription);
- info.setBoundsInParent(boundsInParent);
- info.setBoundsInScreen(boundsInScreen);
- info.setParent(mKeyboardView);
- info.setSource(mKeyboardView, virtualViewId);
- info.setBoundsInScreen(boundsInScreen);
- info.setEnabled(true);
- info.setVisibleToUser(true);
-
- if (mAccessibilityFocusedView == virtualViewId) {
- info.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
- } else {
- info.addAction(AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
+ rootInfo.addChild(mKeyboardView, childVirtualViewId);
}
+ return rootInfo;
}
+ // Find the view that corresponds to the given id.
+ final Key key = mVirtualViewIdToKey.get(virtualViewId);
+ if (key == null) {
+ Log.e(TAG, "Invalid virtual view ID: " + virtualViewId);
+ return null;
+ }
+ final String keyDescription = getKeyDescription(key);
+ final Rect boundsInParent = key.mHitBox;
+
+ // Calculate the key's in-screen bounds.
+ mTempBoundsInScreen.set(boundsInParent);
+ mTempBoundsInScreen.offset(
+ CoordinateUtils.x(mParentLocation), CoordinateUtils.y(mParentLocation));
+ final Rect boundsInScreen = mTempBoundsInScreen;
+
+ // Obtain and initialize an AccessibilityNodeInfo with information about the virtual view.
+ final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain();
+ info.setPackageName(mKeyboardView.getContext().getPackageName());
+ info.setClassName(key.getClass().getName());
+ info.setContentDescription(keyDescription);
+ info.setBoundsInParent(boundsInParent);
+ info.setBoundsInScreen(boundsInScreen);
+ info.setParent(mKeyboardView);
+ info.setSource(mKeyboardView, virtualViewId);
+ info.setBoundsInScreen(boundsInScreen);
+ info.setEnabled(true);
+ info.setVisibleToUser(true);
+
+ if (mAccessibilityFocusedView == virtualViewId) {
+ info.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+ } else {
+ info.addAction(AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
+ }
return info;
}
@@ -216,7 +207,7 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
*
* @param key The key to press.
*/
- void simulateKeyPress(Key key) {
+ void simulateKeyPress(final Key key) {
final int x = key.mHitBox.centerX();
final int y = key.mHitBox.centerY();
final long downTime = SystemClock.uptimeMillis();
@@ -227,19 +218,17 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
mKeyboardView.onTouchEvent(downEvent);
mKeyboardView.onTouchEvent(upEvent);
-
downEvent.recycle();
upEvent.recycle();
}
@Override
- public boolean performAction(int virtualViewId, int action, Bundle arguments) {
+ public boolean performAction(final int virtualViewId, final int action,
+ final Bundle arguments) {
final Key key = mVirtualViewIdToKey.get(virtualViewId);
-
if (key == null) {
return false;
}
-
return performActionForKey(key, action, arguments);
}
@@ -249,10 +238,9 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
* @param key The on which to perform the action.
* @param action The action to perform.
* @param arguments The action's arguments.
- * @return The result of performing the action, or false if the action is
- * not supported.
+ * @return The result of performing the action, or false if the action is not supported.
*/
- boolean performActionForKey(Key key, int action, Bundle arguments) {
+ boolean performActionForKey(final Key key, final int action, final Bundle arguments) {
final int virtualViewId = generateVirtualViewIdForKey(key);
switch (action) {
@@ -272,9 +260,9 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
sendAccessibilityEventForKey(
key, AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
return true;
+ default:
+ return false;
}
-
- return false;
}
/**
@@ -283,7 +271,7 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
* @param key The key that's sending the event.
* @param eventType The type of event to send.
*/
- void sendAccessibilityEventForKey(Key key, int eventType) {
+ void sendAccessibilityEventForKey(final Key key, final int eventType) {
final AccessibilityEvent event = createAccessibilityEvent(key, eventType);
mAccessibilityUtils.requestSendAccessibilityEvent(event);
}
@@ -294,12 +282,11 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
* @param key The key to describe.
* @return The context-specific description of the key.
*/
- private String getKeyDescription(Key key) {
+ private String getKeyDescription(final Key key) {
final EditorInfo editorInfo = mInputMethodService.getCurrentInputEditorInfo();
final boolean shouldObscure = mAccessibilityUtils.shouldObscureInput(editorInfo);
final String keyDescription = mKeyCodeDescriptionMapper.getDescriptionForKey(
mKeyboardView.getContext(), mKeyboardView.getKeyboard(), key, shouldObscure);
-
return keyDescription;
}
@@ -311,7 +298,6 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
if (keyboard == null) {
return;
}
-
mVirtualViewIdToKey.clear();
final Key[] keys = keyboard.mKeys;
@@ -335,7 +321,7 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
* @param key The key to identify.
* @return A virtual view identifier.
*/
- private static int generateVirtualViewIdForKey(Key key) {
+ private static int generateVirtualViewIdForKey(final Key key) {
// The key x- and y-coordinates are stable between layout changes.
// Generate an identifier by bit-shifting the x-coordinate to the
// left-half of the integer and OR'ing with the y-coordinate.
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
index 0a700bda4..bf1cea9c3 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
@@ -55,7 +55,7 @@ public final class AccessibilityUtils {
*/
private static final boolean ENABLE_ACCESSIBILITY = true;
- public static void init(InputMethodService inputMethod) {
+ public static void init(final InputMethodService inputMethod) {
if (!ENABLE_ACCESSIBILITY) return;
// These only need to be initialized if the kill switch is off.
@@ -72,7 +72,7 @@ public final class AccessibilityUtils {
// This class is not publicly instantiable.
}
- private void initInternal(Context context) {
+ private void initInternal(final Context context) {
mContext = context;
mAccessibilityManager =
(AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
@@ -100,9 +100,8 @@ public final class AccessibilityUtils {
* @param event The event to check.
* @return {@true} is the event is a touch exploration event
*/
- public boolean isTouchExplorationEvent(MotionEvent event) {
+ public boolean isTouchExplorationEvent(final MotionEvent event) {
final int action = event.getAction();
-
return action == MotionEvent.ACTION_HOVER_ENTER
|| action == MotionEvent.ACTION_HOVER_EXIT
|| action == MotionEvent.ACTION_HOVER_MOVE;
@@ -114,7 +113,7 @@ public final class AccessibilityUtils {
*
* @return {@code true} if the device should obscure password characters.
*/
- public boolean shouldObscureInput(EditorInfo editorInfo) {
+ public boolean shouldObscureInput(final EditorInfo editorInfo) {
if (editorInfo == null) return false;
// The user can optionally force speaking passwords.
@@ -140,7 +139,7 @@ public final class AccessibilityUtils {
* @param view The source view.
* @param text The text to speak.
*/
- public void announceForAccessibility(View view, CharSequence text) {
+ public void announceForAccessibility(final View view, final CharSequence text) {
if (!mAccessibilityManager.isEnabled()) {
Log.e(TAG, "Attempted to speak when accessibility was disabled!");
return;
@@ -157,8 +156,9 @@ public final class AccessibilityUtils {
event.setEnabled(true);
event.getText().add(text);
- // Platforms starting at SDK 16 should use announce events.
- if (Build.VERSION.SDK_INT >= 16) {
+ // Platforms starting at SDK version 16 (Build.VERSION_CODES.JELLY_BEAN) should use
+ // announce events.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
event.setEventType(AccessibilityEventCompat.TYPE_ANNOUNCEMENT);
} else {
event.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED);
@@ -181,7 +181,8 @@ public final class AccessibilityUtils {
* @param editorInfo The input connection's editor info attribute.
* @param restarting Whether the connection is being restarted.
*/
- public void onStartInputViewInternal(View view, EditorInfo editorInfo, boolean restarting) {
+ public void onStartInputViewInternal(final View view, final EditorInfo editorInfo,
+ final boolean restarting) {
if (shouldObscureInput(editorInfo)) {
final CharSequence text = mContext.getText(R.string.spoken_use_headphones);
announceForAccessibility(view, text);
@@ -194,7 +195,7 @@ public final class AccessibilityUtils {
*
* @param event The event to send.
*/
- public void requestSendAccessibilityEvent(AccessibilityEvent event) {
+ public void requestSendAccessibilityEvent(final AccessibilityEvent event) {
if (mAccessibilityManager.isEnabled()) {
mAccessibilityManager.sendAccessibilityEvent(event);
}
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
index fcfa6d4e4..d73924d92 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
@@ -42,12 +42,11 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
private Key mLastHoverKey = null;
/**
- * Inset in pixels to look for keys when the user's finger exits the
- * keyboard area.
+ * Inset in pixels to look for keys when the user's finger exits the keyboard area.
*/
private int mEdgeSlop;
- public static void init(InputMethodService inputMethod) {
+ public static void init(final InputMethodService inputMethod) {
sInstance.initInternal(inputMethod);
}
@@ -59,7 +58,7 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
// Not publicly instantiable.
}
- private void initInternal(InputMethodService inputMethod) {
+ private void initInternal(final InputMethodService inputMethod) {
mInputMethod = inputMethod;
mEdgeSlop = inputMethod.getResources().getDimensionPixelSize(
R.dimen.accessibility_edge_slop);
@@ -70,61 +69,61 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
*
* @param view The view to wrap.
*/
- public void setView(MainKeyboardView view) {
+ public void setView(final MainKeyboardView view) {
if (view == null) {
// Ignore null views.
return;
}
-
mView = view;
// Ensure that the view has an accessibility delegate.
ViewCompat.setAccessibilityDelegate(view, this);
- if (mAccessibilityNodeProvider != null) {
- mAccessibilityNodeProvider.setView(view);
+ if (mAccessibilityNodeProvider == null) {
+ return;
}
+ mAccessibilityNodeProvider.setView(view);
}
- public void setKeyboard(Keyboard keyboard) {
- if (mAccessibilityNodeProvider != null) {
- mAccessibilityNodeProvider.setKeyboard(keyboard);
+ public void setKeyboard() {
+ if (mAccessibilityNodeProvider == null) {
+ return;
}
+ mAccessibilityNodeProvider.setKeyboard();
}
/**
- * Proxy method for View.getAccessibilityNodeProvider(). This method is
- * called in SDK version 15 and higher to obtain the virtual node hierarchy
- * provider.
+ * Proxy method for View.getAccessibilityNodeProvider(). This method is called in SDK
+ * version 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) and higher to obtain the virtual
+ * node hierarchy provider.
*
* @return The accessibility node provider for the current keyboard.
*/
@Override
- public AccessibilityEntityProvider getAccessibilityNodeProvider(View host) {
+ public AccessibilityEntityProvider getAccessibilityNodeProvider(final View host) {
return getAccessibilityNodeProvider();
}
/**
- * Intercepts touch events before dispatch when touch exploration is turned
- * on in ICS and higher.
+ * Intercepts touch events before dispatch when touch exploration is turned on in ICS and
+ * higher.
*
* @param event The motion event being dispatched.
* @return {@code true} if the event is handled
*/
- public boolean dispatchTouchEvent(MotionEvent event) {
+ public boolean dispatchTouchEvent(final MotionEvent event) {
// To avoid accidental key presses during touch exploration, always drop
// touch events generated by the user.
return false;
}
/**
- * Receives hover events when touch exploration is turned on in SDK versions
- * ICS and higher.
+ * Receives hover events when touch exploration is turned on in SDK versions ICS and higher.
*
* @param event The hover event.
* @return {@code true} if the event is handled
*/
- public boolean dispatchHoverEvent(MotionEvent event, PointerTracker tracker) {
+ public boolean dispatchHoverEvent(final MotionEvent event, final PointerTracker tracker) {
final int x = (int) event.getX();
final int y = (int) event.getY();
final Key previousKey = mLastHoverKey;
@@ -135,7 +134,6 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
} else {
key = null;
}
-
mLastHoverKey = key;
switch (event.getAction()) {
@@ -173,30 +171,29 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
}
/**
- * Utility method to determine whether the given point, in local
- * coordinates, is inside the view, where the area of the view is contracted
- * by the edge slop factor.
+ * Utility method to determine whether the given point, in local coordinates, is inside the
+ * view, where the area of the view is contracted by the edge slop factor.
*
* @param localX The local x-coordinate.
* @param localY The local y-coordinate.
*/
- private boolean pointInView(int localX, int localY) {
+ private boolean pointInView(final int localX, final int localY) {
return (localX >= mEdgeSlop) && (localY >= mEdgeSlop)
&& (localX < (mView.getWidth() - mEdgeSlop))
&& (localY < (mView.getHeight() - mEdgeSlop));
}
/**
- * Simulates a transition between two {@link Key}s by sending a HOVER_EXIT
- * on the previous key, a HOVER_ENTER on the current key, and a HOVER_MOVE
- * on the current key.
+ * Simulates a transition between two {@link Key}s by sending a HOVER_EXIT on the previous key,
+ * a HOVER_ENTER on the current key, and a HOVER_MOVE on the current key.
*
* @param currentKey The currently hovered key.
* @param previousKey The previously hovered key.
* @param event The event that triggered the transition.
* @return {@code true} if the event was handled.
*/
- private boolean onTransitionKey(Key currentKey, Key previousKey, MotionEvent event) {
+ private boolean onTransitionKey(final Key currentKey, final Key previousKey,
+ final MotionEvent event) {
final int savedAction = event.getAction();
event.setAction(MotionEvent.ACTION_HOVER_EXIT);
@@ -214,19 +211,18 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
}
/**
- * Handles a hover event on a key. If {@link Key} extended View, this would
- * be analogous to calling View.onHoverEvent(MotionEvent).
+ * Handles a hover event on a key. If {@link Key} extended View, this would be analogous to
+ * calling View.onHoverEvent(MotionEvent).
*
* @param key The currently hovered key.
* @param event The hover event.
* @return {@code true} if the event was handled.
*/
- private boolean onHoverKey(Key key, MotionEvent event) {
+ private boolean onHoverKey(final Key key, final MotionEvent event) {
// Null keys can't receive events.
if (key == null) {
return false;
}
-
final AccessibilityEntityProvider provider = getAccessibilityNodeProvider();
switch (event.getAction()) {
@@ -241,7 +237,6 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
key, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT);
break;
}
-
return true;
}
@@ -268,7 +263,6 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
default:
text = context.getText(R.string.spoken_description_shiftmode_off);
}
-
AccessibilityUtils.getInstance().announceForAccessibility(mView, text);
}
@@ -307,7 +301,6 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
if (resId < 0) {
return;
}
-
final String text = context.getString(resId);
AccessibilityUtils.getInstance().announceForAccessibility(mView, text);
}
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index b87ae3a15..6a01b0190 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -93,17 +93,17 @@ public final class KeyCodeDescriptionMapper {
* @param keyboard The keyboard on which the key resides.
* @param key The key from which to obtain a description.
* @param shouldObscure {@true} if text (e.g. non-control) characters should be obscured.
- * @return a character sequence describing the action performed by pressing
- * the key
+ * @return a character sequence describing the action performed by pressing the key
*/
- public String getDescriptionForKey(Context context, Keyboard keyboard, Key key,
- boolean shouldObscure) {
+ public String getDescriptionForKey(final Context context, final Keyboard keyboard,
+ final Key key, final boolean shouldObscure) {
final int code = key.mCode;
if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) {
final String description = getDescriptionForSwitchAlphaSymbol(context, keyboard);
- if (description != null)
+ if (description != null) {
return description;
+ }
}
if (code == Constants.CODE_SHIFT) {
@@ -127,7 +127,6 @@ public final class KeyCodeDescriptionMapper {
if (key.mCode != Constants.CODE_UNSPECIFIED) {
return getDescriptionForKeyCode(context, keyboard, key, shouldObscure);
}
-
return null;
}
@@ -138,10 +137,10 @@ public final class KeyCodeDescriptionMapper {
*
* @param context The package's context.
* @param keyboard The keyboard on which the key resides.
- * @return a character sequence describing the action performed by pressing
- * the key
+ * @return a character sequence describing the action performed by pressing the key
*/
- private String getDescriptionForSwitchAlphaSymbol(Context context, Keyboard keyboard) {
+ private String getDescriptionForSwitchAlphaSymbol(final Context context,
+ final Keyboard keyboard) {
final KeyboardId keyboardId = keyboard.mId;
final int elementId = keyboardId.mElementId;
final int resId;
@@ -168,7 +167,6 @@ public final class KeyCodeDescriptionMapper {
Log.e(TAG, "Missing description for keyboard element ID:" + elementId);
return null;
}
-
return context.getString(resId);
}
@@ -179,7 +177,7 @@ public final class KeyCodeDescriptionMapper {
* @param keyboard The keyboard on which the key resides.
* @return A context-sensitive description of the "Shift" key.
*/
- private String getDescriptionForShiftKey(Context context, Keyboard keyboard) {
+ private String getDescriptionForShiftKey(final Context context, final Keyboard keyboard) {
final KeyboardId keyboardId = keyboard.mId;
final int elementId = keyboardId.mElementId;
final int resId;
@@ -197,7 +195,6 @@ public final class KeyCodeDescriptionMapper {
default:
resId = R.string.spoken_description_shift;
}
-
return context.getString(resId);
}
@@ -207,10 +204,10 @@ public final class KeyCodeDescriptionMapper {
* @param context The package's context.
* @param keyboard The keyboard on which the key resides.
* @param key The key to describe.
- * @return Returns a context-sensitive description of the "Enter" action
- * key.
+ * @return Returns a context-sensitive description of the "Enter" action key.
*/
- private String getDescriptionForActionKey(Context context, Keyboard keyboard, Key key) {
+ private String getDescriptionForActionKey(final Context context, final Keyboard keyboard,
+ final Key key) {
final KeyboardId keyboardId = keyboard.mId;
final int actionId = keyboardId.imeActionId();
final int resId;
@@ -243,7 +240,6 @@ public final class KeyCodeDescriptionMapper {
default:
resId = R.string.spoken_description_return;
}
-
return context.getString(resId);
}
@@ -265,11 +261,10 @@ public final class KeyCodeDescriptionMapper {
* @param keyboard The keyboard on which the key resides.
* @param key The key from which to obtain a description.
* @param shouldObscure {@true} if text (e.g. non-control) characters should be obscured.
- * @return a character sequence describing the action performed by pressing
- * the key
+ * @return a character sequence describing the action performed by pressing the key
*/
- private String getDescriptionForKeyCode(Context context, Keyboard keyboard, Key key,
- boolean shouldObscure) {
+ private String getDescriptionForKeyCode(final Context context, final Keyboard keyboard,
+ final Key key, final boolean shouldObscure) {
final int code = key.mCode;
// If the key description should be obscured, now is the time to do it.
@@ -277,15 +272,15 @@ public final class KeyCodeDescriptionMapper {
if (shouldObscure && isDefinedNonCtrl) {
return context.getString(OBSCURED_KEY_RES_ID);
}
-
if (mKeyCodeMap.indexOfKey(code) >= 0) {
return context.getString(mKeyCodeMap.get(code));
- } else if (isDefinedNonCtrl) {
+ }
+ if (isDefinedNonCtrl) {
return Character.toString((char) code);
- } else if (!TextUtils.isEmpty(key.mLabel)) {
+ }
+ if (!TextUtils.isEmpty(key.mLabel)) {
return key.mLabel;
- } else {
- return context.getString(R.string.spoken_description_unknown, code);
}
+ return context.getString(R.string.spoken_description_unknown, code);
}
}
diff --git a/java/src/com/android/inputmethod/compat/CompatUtils.java b/java/src/com/android/inputmethod/compat/CompatUtils.java
index ffed6ecb1..a82103ab3 100644
--- a/java/src/com/android/inputmethod/compat/CompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/CompatUtils.java
@@ -31,8 +31,8 @@ public final class CompatUtils {
private static final String INPUT_METHOD_SUBTYPE_SETTINGS =
"android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
- public static Intent getInputLanguageSelectionIntent(String inputMethodId,
- int flagsForSubtypeSettings) {
+ public static Intent getInputLanguageSelectionIntent(final String inputMethodId,
+ final int flagsForSubtypeSettings) {
// Refer to android.provider.Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS
final String action = INPUT_METHOD_SUBTYPE_SETTINGS;
final Intent intent = new Intent(action);
@@ -45,7 +45,7 @@ public final class CompatUtils {
return intent;
}
- public static Class<?> getClass(String className) {
+ public static Class<?> getClass(final String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
@@ -53,8 +53,8 @@ public final class CompatUtils {
}
}
- public static Method getMethod(Class<?> targetClass, String name,
- Class<?>... parameterTypes) {
+ public static Method getMethod(final Class<?> targetClass, final String name,
+ final Class<?>... parameterTypes) {
if (targetClass == null || TextUtils.isEmpty(name)) return null;
try {
return targetClass.getMethod(name, parameterTypes);
@@ -66,7 +66,7 @@ public final class CompatUtils {
return null;
}
- public static Field getField(Class<?> targetClass, String name) {
+ public static Field getField(final Class<?> targetClass, final String name) {
if (targetClass == null || TextUtils.isEmpty(name)) return null;
try {
return targetClass.getField(name);
@@ -78,7 +78,8 @@ public final class CompatUtils {
return null;
}
- public static Constructor<?> getConstructor(Class<?> targetClass, Class<?> ... types) {
+ public static Constructor<?> getConstructor(final Class<?> targetClass,
+ final Class<?> ... types) {
if (targetClass == null || types == null) return null;
try {
return targetClass.getConstructor(types);
@@ -90,7 +91,7 @@ public final class CompatUtils {
return null;
}
- public static Object newInstance(Constructor<?> constructor, Object ... args) {
+ public static Object newInstance(final Constructor<?> constructor, final Object ... args) {
if (constructor == null) return null;
try {
return constructor.newInstance(args);
@@ -100,8 +101,8 @@ public final class CompatUtils {
return null;
}
- public static Object invoke(
- Object receiver, Object defaultValue, Method method, Object... args) {
+ public static Object invoke(final Object receiver, final Object defaultValue,
+ final Method method, final Object... args) {
if (method == null) return defaultValue;
try {
return method.invoke(receiver, args);
@@ -111,7 +112,8 @@ public final class CompatUtils {
return defaultValue;
}
- public static Object getFieldValue(Object receiver, Object defaultValue, Field field) {
+ public static Object getFieldValue(final Object receiver, final Object defaultValue,
+ final Field field) {
if (field == null) return defaultValue;
try {
return field.get(receiver);
@@ -121,7 +123,7 @@ public final class CompatUtils {
return defaultValue;
}
- public static void setFieldValue(Object receiver, Field field, Object value) {
+ public static void setFieldValue(final Object receiver, final Field field, final Object value) {
if (field == null) return;
try {
field.set(receiver, value);
diff --git a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java
index 210058bec..7eefa221a 100644
--- a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java
@@ -21,23 +21,23 @@ import android.view.inputmethod.EditorInfo;
import java.lang.reflect.Field;
public final class EditorInfoCompatUtils {
- // EditorInfo.IME_FLAG_FORCE_ASCII has been introduced since API#16 (JellyBean).
+ // Note that EditorInfo.IME_FLAG_FORCE_ASCII has been introduced
+ // in API level 16 (Build.VERSION_CODES.JELLY_BEAN).
private static final Field FIELD_IME_FLAG_FORCE_ASCII = CompatUtils.getField(
EditorInfo.class, "IME_FLAG_FORCE_ASCII");
- private static final Integer OBJ_IME_FLAG_FORCE_ASCII = (Integer) CompatUtils
- .getFieldValue(null, null, FIELD_IME_FLAG_FORCE_ASCII);
+ private static final Integer OBJ_IME_FLAG_FORCE_ASCII = (Integer) CompatUtils.getFieldValue(
+ null /* receiver */, null /* defaultValue */, FIELD_IME_FLAG_FORCE_ASCII);
private EditorInfoCompatUtils() {
// This utility class is not publicly instantiable.
}
- public static boolean hasFlagForceAscii(int imeOptions) {
- if (OBJ_IME_FLAG_FORCE_ASCII == null)
- return false;
+ public static boolean hasFlagForceAscii(final int imeOptions) {
+ if (OBJ_IME_FLAG_FORCE_ASCII == null) return false;
return (imeOptions & OBJ_IME_FLAG_FORCE_ASCII) != 0;
}
- public static String imeActionName(int imeOptions) {
+ public static String imeActionName(final int imeOptions) {
final int actionId = imeOptions & EditorInfo.IME_MASK_ACTION;
switch (actionId) {
case EditorInfo.IME_ACTION_UNSPECIFIED:
@@ -61,7 +61,7 @@ public final class EditorInfoCompatUtils {
}
}
- public static String imeOptionsName(int imeOptions) {
+ public static String imeOptionsName(final int imeOptions) {
final String action = imeActionName(imeOptions);
final StringBuilder flags = new StringBuilder();
if ((imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
diff --git a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
index 8bd1e5208..a80c3fefe 100644
--- a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
@@ -23,6 +23,8 @@ import android.view.inputmethod.InputMethodManager;
import java.lang.reflect.Method;
public final class InputMethodManagerCompatWrapper {
+ // Note that InputMethodManager.switchToNextInputMethod() has been introduced
+ // in API level 16 (Build.VERSION_CODES.JELLY_BEAN).
private static final Method METHOD_switchToNextInputMethod = CompatUtils.getMethod(
InputMethodManager.class, "switchToNextInputMethod", IBinder.class, Boolean.TYPE);
@@ -33,7 +35,7 @@ public final class InputMethodManagerCompatWrapper {
}
public boolean switchToNextInputMethod(final IBinder token, final boolean onlyCurrentIme) {
- return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToNextInputMethod, token,
- onlyCurrentIme);
+ return (Boolean)CompatUtils.invoke(mImm, false /* defaultValue */,
+ METHOD_switchToNextInputMethod, token, onlyCurrentIme);
}
}
diff --git a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatUtils.java b/java/src/com/android/inputmethod/compat/InputMethodServiceCompatUtils.java
index 8eea31ed2..14ee654f3 100644
--- a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/InputMethodServiceCompatUtils.java
@@ -21,6 +21,8 @@ import android.inputmethodservice.InputMethodService;
import java.lang.reflect.Method;
public final class InputMethodServiceCompatUtils {
+ // Note that InputMethodService.enableHardwareAcceleration() has been introduced
+ // in API level 17 (Build.VERSION_CODES.JELLY_BEAN_MR1).
private static final Method METHOD_enableHardwareAcceleration =
CompatUtils.getMethod(InputMethodService.class, "enableHardwareAcceleration");
@@ -28,7 +30,8 @@ public final class InputMethodServiceCompatUtils {
// This utility class is not publicly instantiable.
}
- public static boolean enableHardwareAcceleration(InputMethodService ims) {
- return (Boolean)CompatUtils.invoke(ims, false, METHOD_enableHardwareAcceleration);
+ public static boolean enableHardwareAcceleration(final InputMethodService ims) {
+ return (Boolean)CompatUtils.invoke(ims, false /* defaultValue */,
+ METHOD_enableHardwareAcceleration);
}
}
diff --git a/java/src/com/android/inputmethod/compat/SettingsSecureCompatUtils.java b/java/src/com/android/inputmethod/compat/SettingsSecureCompatUtils.java
index db5abd0fe..cfaf7ec77 100644
--- a/java/src/com/android/inputmethod/compat/SettingsSecureCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/SettingsSecureCompatUtils.java
@@ -19,6 +19,8 @@ package com.android.inputmethod.compat;
import java.lang.reflect.Field;
public final class SettingsSecureCompatUtils {
+ // Note that Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD has been introduced
+ // in API level 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1).
private static final Field FIELD_ACCESSIBILITY_SPEAK_PASSWORD = CompatUtils.getField(
android.provider.Settings.Secure.class, "ACCESSIBILITY_SPEAK_PASSWORD");
@@ -30,5 +32,5 @@ public final class SettingsSecureCompatUtils {
* Whether to speak passwords while in accessibility mode.
*/
public static final String ACCESSIBILITY_SPEAK_PASSWORD = (String) CompatUtils.getFieldValue(
- null, null, FIELD_ACCESSIBILITY_SPEAK_PASSWORD);
+ null /* receiver */, null /* defaultValue */, FIELD_ACCESSIBILITY_SPEAK_PASSWORD);
}
diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
index 0e3634d52..141e08a8d 100644
--- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
+++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
@@ -34,11 +34,12 @@ import java.util.ArrayList;
public final class SuggestionSpanUtils {
private static final String TAG = SuggestionSpanUtils.class.getSimpleName();
- // Note that SuggestionSpan.FLAG_AUTO_CORRECTION was added in API level 15.
- public static final Field FIELD_FLAG_AUTO_CORRECTION =
- CompatUtils.getField(SuggestionSpan.class, "FLAG_AUTO_CORRECTION");
- public static final Integer OBJ_FLAG_AUTO_CORRECTION =
- (Integer) CompatUtils.getFieldValue(null, null, FIELD_FLAG_AUTO_CORRECTION);
+ // Note that SuggestionSpan.FLAG_AUTO_CORRECTION has been introduced
+ // in API level 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1).
+ public static final Field FIELD_FLAG_AUTO_CORRECTION = CompatUtils.getField(
+ SuggestionSpan.class, "FLAG_AUTO_CORRECTION");
+ public static final Integer OBJ_FLAG_AUTO_CORRECTION = (Integer) CompatUtils.getFieldValue(
+ null /* receiver */, null /* defaultValue */, FIELD_FLAG_AUTO_CORRECTION);
static {
if (LatinImeLogger.sDBG) {
@@ -58,8 +59,9 @@ public final class SuggestionSpanUtils {
return text;
}
final Spannable spannable = new SpannableString(text);
- final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null, new String[] {},
- (int)OBJ_FLAG_AUTO_CORRECTION, SuggestionSpanPickedNotificationReceiver.class);
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null /* locale */,
+ new String[] {} /* suggestions */, (int)OBJ_FLAG_AUTO_CORRECTION,
+ SuggestionSpanPickedNotificationReceiver.class);
spannable.setSpan(suggestionSpan, 0, text.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING);
return spannable;
@@ -87,8 +89,8 @@ public final class SuggestionSpanUtils {
// TODO: We should avoid adding suggestion span candidates that came from the bigram
// prediction.
- final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null,
- suggestionsList.toArray(new String[suggestionsList.size()]), 0,
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null /* locale */,
+ suggestionsList.toArray(new String[suggestionsList.size()]), 0 /* flags */,
SuggestionSpanPickedNotificationReceiver.class);
spannable.setSpan(suggestionSpan, 0, pickedWord.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannable;
diff --git a/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java b/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java
index 8314212c9..d8d2be04c 100644
--- a/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java
@@ -21,10 +21,13 @@ import android.view.textservice.SuggestionsInfo;
import java.lang.reflect.Field;
public final 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);
+ // Note that SuggestionsInfo.RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS has been introduced
+ // in API level 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1).
+ 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 /* receiver */, null /* defaultValue */,
+ 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;
diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java
index c96a3362d..215e4dee5 100644
--- a/java/src/com/android/inputmethod/event/Event.java
+++ b/java/src/com/android/inputmethod/event/Event.java
@@ -29,8 +29,64 @@ package com.android.inputmethod.event;
* The combiner should figure out what to do with this.
*/
public class Event {
+ // Should the types below be represented by separate classes instead? It would be cleaner
+ // but probably a bit too much
+ // An event we don't handle in Latin IME, for example pressing Ctrl on a hardware keyboard.
+ final public static int EVENT_NOT_HANDLED = 0;
+ // A character that is already final, for example pressing an alphabetic character on a
+ // hardware qwerty keyboard.
+ final public static int EVENT_COMMITTABLE = 1;
+ // A dead key, which means a character that should combine with what is coming next. Examples
+ // include the "^" character on an azerty keyboard which combines with "e" to make "ê", or
+ // AltGr+' on a dvorak international keyboard which combines with "e" to make "é". This is
+ // true regardless of the language or combining mode, and should be seen as a property of the
+ // key - a dead key followed by another key with which it can combine should be regarded as if
+ // the keyboard actually had such a key.
+ final public static int EVENT_DEAD = 2;
+ // A toggle event is triggered by a key that affects the previous character. An example would
+ // be a numeric key on a 10-key keyboard, which would toggle between 1 - a - b - c with
+ // repeated presses.
+ final public static int EVENT_TOGGLE = 3;
+ // A mode event instructs the combiner to change modes. The canonical example would be the
+ // hankaku/zenkaku key on a Japanese keyboard, or even the caps lock key on a qwerty keyboard
+ // if handled at the combiner level.
+ final public static int EVENT_MODE_KEY = 4;
+
+ final private static int NOT_A_CODE_POINT = 0;
+
+ private int mType; // The type of event - one of the constants above
+ // The code point associated with the event, if relevant. This is a unicode code point, and
+ // has nothing to do with other representations of the key. It is only relevant if this event
+ // is the right type: COMMITTABLE or DEAD or TOGGLE, but for a mode key like hankaku/zenkaku or
+ // ctrl, there is no code point associated so this should be NOT_A_CODE_POINT to avoid
+ // unintentional use of its value when it's not relevant.
+ private int mCodePoint;
+
static Event obtainEvent() {
// TODO: create an event pool instead
return new Event();
}
+
+ public void setDeadEvent(final int codePoint) {
+ mType = EVENT_DEAD;
+ mCodePoint = codePoint;
+ }
+
+ public void setCommittableEvent(final int codePoint) {
+ mType = EVENT_COMMITTABLE;
+ mCodePoint = codePoint;
+ }
+
+ public void setNotHandledEvent() {
+ mType = EVENT_NOT_HANDLED;
+ mCodePoint = NOT_A_CODE_POINT; // Just in case
+ }
+
+ public boolean isCommittable() {
+ return EVENT_COMMITTABLE == mType;
+ }
+
+ public int getCodePoint() {
+ return mCodePoint;
+ }
}
diff --git a/java/src/com/android/inputmethod/event/EventInterpreter.java b/java/src/com/android/inputmethod/event/EventInterpreter.java
index 443c269a2..1bd0cca00 100644
--- a/java/src/com/android/inputmethod/event/EventInterpreter.java
+++ b/java/src/com/android/inputmethod/event/EventInterpreter.java
@@ -16,8 +16,12 @@
package com.android.inputmethod.event;
+import android.util.SparseArray;
import android.view.KeyEvent;
+import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.LatinIME;
+
/**
* This class implements the logic between receiving events and generating code points.
*
@@ -32,18 +36,45 @@ public class EventInterpreter {
// TODO: Create an object type to represent input material + visual feedback + decoding state
// TODO: Create an interface to call back to Latin IME through the above object
- // TODO: replace this with an associative container to bind device id -> decoder
- HardwareEventDecoder mHardwareEventDecoder;
- SoftwareEventDecoder mSoftwareEventDecoder;
+ final EventDecoderSpec mDecoderSpec;
+ final SparseArray<HardwareEventDecoder> mHardwareEventDecoders;
+ final SoftwareEventDecoder mSoftwareEventDecoder;
+ final LatinIME mLatinIme;
- public EventInterpreter() {
- this(null);
+ /**
+ * Create a default interpreter.
+ *
+ * This creates a default interpreter that does nothing. A default interpreter should normally
+ * only be used for fallback purposes, when we really don't know what we want to do with input.
+ *
+ * @param latinIme a reference to the ime.
+ */
+ public EventInterpreter(final LatinIME latinIme) {
+ this(null, latinIme);
}
- public EventInterpreter(final EventDecoderSpec specification) {
- // TODO: create the decoding chain from a specification. The decoders should be
- // created lazily
- mHardwareEventDecoder = new HardwareKeyboardEventDecoder(0);
+ /**
+ * Create an event interpreter according to a specification.
+ *
+ * The specification contains information about what to do with events. Typically, it will
+ * contain information about the type of keyboards - for example, if hardware keyboard(s) is/are
+ * attached, their type will be included here so that the decoder knows what to do with each
+ * keypress (a 10-key keyboard is not handled like a qwerty-ish keyboard).
+ * It also contains information for combining characters. For example, if the input language
+ * is Japanese, the specification will typically request kana conversion.
+ * Also note that the specification can be null. This means that we need to create a default
+ * interpreter that does no specific combining, and assumes the most common cases.
+ *
+ * @param specification the specification for event interpretation. null for default.
+ * @param latinIme a reference to the ime.
+ */
+ public EventInterpreter(final EventDecoderSpec specification, final LatinIME latinIme) {
+ mDecoderSpec = null != specification ? specification : new EventDecoderSpec();
+ // For both, we expect to have only one decoder in almost all cases, hence the default
+ // capacity of 1.
+ mHardwareEventDecoders = new SparseArray<HardwareEventDecoder>(1);
+ mSoftwareEventDecoder = new SoftwareKeyboardEventDecoder();
+ mLatinIme = latinIme;
}
// Helper method to decode a hardware key event into a generic event, and execute any
@@ -60,15 +91,26 @@ public class EventInterpreter {
}
private HardwareEventDecoder getHardwareKeyEventDecoder(final int deviceId) {
- // TODO: look up the decoder by device id. It should be created lazily
- return mHardwareEventDecoder;
+ final HardwareEventDecoder decoder = mHardwareEventDecoders.get(deviceId);
+ if (null != decoder) return decoder;
+ // TODO: create the decoder according to the specification
+ final HardwareEventDecoder newDecoder = new HardwareKeyboardEventDecoder(deviceId);
+ mHardwareEventDecoders.put(deviceId, newDecoder);
+ return newDecoder;
}
private SoftwareEventDecoder getSoftwareEventDecoder() {
+ // Within the context of Latin IME, since we never present several software interfaces
+ // at the time, we should never need multiple software event decoders at a time.
return mSoftwareEventDecoder;
}
private boolean onEvent(final Event event) {
+ if (event.isCommittable()) {
+ mLatinIme.onCodeInput(event.getCodePoint(),
+ Constants.EXTERNAL_KEYBOARD_COORDINATE, Constants.EXTERNAL_KEYBOARD_COORDINATE);
+ return true;
+ }
// TODO: Classify the event - input or non-input (see design doc)
// TODO: IF action event
// Send decoded action back to LatinIME
diff --git a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
index 9aa6a273e..2dbc9f00b 100644
--- a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
+++ b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
@@ -16,10 +16,17 @@
package com.android.inputmethod.event;
+import android.view.KeyCharacterMap;
import android.view.KeyEvent;
+import com.android.inputmethod.latin.Constants;
+
/**
* A hardware event decoder for a hardware qwerty-ish keyboard.
+ *
+ * The events are always hardware keypresses, but they can be key down or key up events, they
+ * can be dead keys, they can be meta keys like shift or ctrl... This does not deal with
+ * 10-key like keyboards; a different decoder is used for this.
*/
public class HardwareKeyboardEventDecoder implements HardwareEventDecoder {
final int mDeviceId;
@@ -30,7 +37,33 @@ public class HardwareKeyboardEventDecoder implements HardwareEventDecoder {
}
@Override
- public Event decodeHardwareKey(KeyEvent keyEvent) {
- return Event.obtainEvent();
+ public Event decodeHardwareKey(final KeyEvent keyEvent) {
+ final Event event = Event.obtainEvent();
+ // KeyEvent#getUnicodeChar() does not exactly returns a unicode char, but rather a value
+ // that includes both the unicode char in the lower 21 bits and flags in the upper bits,
+ // hence the name "codePointAndFlags". {@see KeyEvent#getUnicodeChar()} for more info.
+ final int codePointAndFlags = keyEvent.getUnicodeChar();
+ // The keyCode is the abstraction used by the KeyEvent to represent different keys that
+ // do not necessarily map to a unicode character. This represents a physical key, like
+ // the key for 'A' or Space, but also Backspace or Ctrl or Caps Lock.
+ final int keyCode = keyEvent.getKeyCode();
+ if (KeyEvent.KEYCODE_DEL == keyCode) {
+ event.setCommittableEvent(Constants.CODE_DELETE);
+ return event;
+ }
+ if (keyEvent.isPrintingKey() || KeyEvent.KEYCODE_SPACE == keyCode
+ || KeyEvent.KEYCODE_ENTER == keyCode) {
+ if (0 != (codePointAndFlags & KeyCharacterMap.COMBINING_ACCENT)) {
+ // A dead key.
+ event.setDeadEvent(codePointAndFlags & KeyCharacterMap.COMBINING_ACCENT_MASK);
+ } else {
+ // A committable character. This should be committed right away, taking into
+ // account the current state.
+ event.setCommittableEvent(codePointAndFlags);
+ }
+ } else {
+ event.setNotHandledEvent();
+ }
+ return event;
}
}
diff --git a/java/src/com/android/inputmethod/event/SoftwareEventDecoder.java b/java/src/com/android/inputmethod/event/SoftwareEventDecoder.java
index 0b80d5c0e..d81ee0b37 100644
--- a/java/src/com/android/inputmethod/event/SoftwareEventDecoder.java
+++ b/java/src/com/android/inputmethod/event/SoftwareEventDecoder.java
@@ -17,7 +17,12 @@
package com.android.inputmethod.event;
/**
- * An event decoder for software events.
+ * An event decoder for events out of a software keyboard.
+ *
+ * This defines the interface for an event decoder that supports events out of a software keyboard.
+ * This differs significantly from hardware keyboard event decoders in several respects. First,
+ * a software keyboard does not have a scancode/layout system; the keypresses that insert
+ * characters output unicode characters directly.
*/
public interface SoftwareEventDecoder extends EventDecoder {
public Event decodeSoftwareEvent();
diff --git a/java/src/com/android/inputmethod/event/SoftwareKeyboardEventDecoder.java b/java/src/com/android/inputmethod/event/SoftwareKeyboardEventDecoder.java
new file mode 100644
index 000000000..de91567c7
--- /dev/null
+++ b/java/src/com/android/inputmethod/event/SoftwareKeyboardEventDecoder.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 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.event;
+
+/**
+ * A decoder for events from software keyboard, like the ones displayed by Latin IME.
+ */
+public class SoftwareKeyboardEventDecoder implements SoftwareEventDecoder {
+ @Override
+ public Event decodeSoftwareEvent() {
+ return null;
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index c1c105e8d..1088fdab4 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -19,6 +19,7 @@ package com.android.inputmethod.keyboard;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
+import android.preference.PreferenceManager;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
@@ -50,7 +51,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
// Note: The themeId should be aligned with "themeId" attribute of Keyboard style
// in values/style.xml.
- public KeyboardTheme(int themeId, int styleId) {
+ public KeyboardTheme(final int themeId, final int styleId) {
mThemeId = themeId;
mStyleId = styleId;
}
@@ -65,7 +66,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
new KeyboardTheme(5, R.style.KeyboardTheme_IceCreamSandwich),
};
- private AudioAndHapticFeedbackManager mFeedbackManager;
+ private final AudioAndHapticFeedbackManager mFeedbackManager =
+ AudioAndHapticFeedbackManager.getInstance();
private SubtypeSwitcher mSubtypeSwitcher;
private SharedPreferences mPrefs;
@@ -95,21 +97,22 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
// Intentional empty constructor for singleton.
}
- public static void init(LatinIME latinIme, SharedPreferences prefs) {
+ public static void init(final LatinIME latinIme) {
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(latinIme);
sInstance.initInternal(latinIme, prefs);
}
- private void initInternal(LatinIME latinIme, SharedPreferences prefs) {
+ private void initInternal(final LatinIME latinIme, final SharedPreferences prefs) {
mLatinIME = latinIme;
mResources = latinIme.getResources();
- mFeedbackManager = new AudioAndHapticFeedbackManager(latinIme);
mPrefs = prefs;
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
mState = new KeyboardState(this);
setContextThemeWrapper(latinIme, getKeyboardTheme(latinIme, prefs));
}
- private static KeyboardTheme getKeyboardTheme(Context context, SharedPreferences prefs) {
+ private static KeyboardTheme getKeyboardTheme(final Context context,
+ final SharedPreferences prefs) {
final String defaultIndex = context.getString(R.string.config_default_keyboard_theme_index);
final String themeIndex = prefs.getString(PREF_KEYBOARD_LAYOUT, defaultIndex);
try {
@@ -124,7 +127,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
return KEYBOARD_THEMES[0];
}
- private void setContextThemeWrapper(Context context, KeyboardTheme keyboardTheme) {
+ private void setContextThemeWrapper(final Context context, final KeyboardTheme keyboardTheme) {
if (mThemeContext == null || mKeyboardTheme.mThemeId != keyboardTheme.mThemeId) {
mKeyboardTheme = keyboardTheme;
mThemeContext = new ContextThemeWrapper(context, keyboardTheme.mStyleId);
@@ -132,7 +135,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
}
}
- public void loadKeyboard(EditorInfo editorInfo, SettingsValues settingsValues) {
+ public void loadKeyboard(final EditorInfo editorInfo, final SettingsValues settingsValues) {
final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder(
mThemeContext, editorInfo);
final Resources res = mThemeContext.getResources();
@@ -210,14 +213,14 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
mState.onResetKeyboardStateToAlphabet();
}
- public void onPressKey(int code) {
+ public void onPressKey(final int code) {
if (isVibrateAndSoundFeedbackRequired()) {
mFeedbackManager.hapticAndAudioFeedback(code, mKeyboardView);
}
mState.onPressKey(code, isSinglePointer(), mLatinIME.getCurrentAutoCapsState());
}
- public void onReleaseKey(int code, boolean withSliding) {
+ public void onReleaseKey(final int code, final boolean withSliding) {
mState.onReleaseKey(code, withSliding);
}
@@ -303,7 +306,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
// Implements {@link KeyboardState.SwitchActions}.
@Override
- public void startLongPressTimer(int code) {
+ public void startLongPressTimer(final int code) {
final MainKeyboardView keyboardView = getMainKeyboardView();
if (keyboardView != null) {
final TimerProxy timer = keyboardView.getTimerProxy();
@@ -323,11 +326,11 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
// Implements {@link KeyboardState.SwitchActions}.
@Override
- public void hapticAndAudioFeedback(int code) {
+ public void hapticAndAudioFeedback(final int code) {
mFeedbackManager.hapticAndAudioFeedback(code, mKeyboardView);
}
- public void onLongPressTimeout(int code) {
+ public void onLongPressTimeout(final int code) {
mState.onLongPressTimeout(code);
}
@@ -346,7 +349,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
/**
* Updates state machine to figure out when to automatically switch back to the previous mode.
*/
- public void onCodeInput(int code) {
+ public void onCodeInput(final int code) {
mState.onCodeInput(code, isSinglePointer(), mLatinIME.getCurrentAutoCapsState());
}
@@ -354,7 +357,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
return mKeyboardView;
}
- public View onCreateInputView(boolean isHardwareAcceleratedDrawingEnabled) {
+ public View onCreateInputView(final boolean isHardwareAcceleratedDrawingEnabled) {
if (mKeyboardView != null) {
mKeyboardView.closing();
}
@@ -383,7 +386,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
}
}
- public void onAutoCorrectionStateChanged(boolean isAutoCorrection) {
+ public void onAutoCorrectionStateChanged(final boolean isAutoCorrection) {
if (mIsAutoCorrectionActive != isAutoCorrection) {
mIsAutoCorrectionActive = isAutoCorrection;
if (mKeyboardView != null) {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 61d38745e..b7bee3430 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -50,6 +50,7 @@ import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
import com.android.inputmethod.latin.StringUtils;
+import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethod.research.ResearchLogger;
@@ -870,9 +871,9 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy,
mPreviewPlacerView.dismissSlidingKeyInputPreview();
}
- public void showGestureFloatingPreviewText(final String gestureFloatingPreviewText) {
+ public void showGestureFloatingPreviewText(final SuggestedWords suggestedWords) {
locatePreviewPlacerView();
- mPreviewPlacerView.setGestureFloatingPreviewText(gestureFloatingPreviewText);
+ mPreviewPlacerView.setGestureFloatingPreviewText(suggestedWords);
}
public void dismissGestureFloatingPreviewText() {
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 584d2fe46..79aab9c76 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -393,8 +393,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
mHasDistinctMultitouch = hasDistinctMultitouch && !forceNonDistinctMultitouch;
final Resources res = getResources();
final boolean needsPhantomSuddenMoveEventHack = Boolean.parseBoolean(
- ResourceUtils.getDeviceOverrideValue(res,
- R.array.phantom_sudden_move_event_device_list, "false"));
+ ResourceUtils.getDeviceOverrideValue(
+ res, R.array.phantom_sudden_move_event_device_list));
PointerTracker.init(needsPhantomSuddenMoveEventHack);
final TypedArray a = context.obtainStyledAttributes(
@@ -530,7 +530,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
// This always needs to be set since the accessibility state can
// potentially change without the keyboard being set again.
- AccessibleKeyboardViewProxy.getInstance().setKeyboard(keyboard);
+ AccessibleKeyboardViewProxy.getInstance().setKeyboard();
}
// Note that this method is called from a non-UI thread.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java b/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java
new file mode 100644
index 000000000..8a3f0645f
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 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.Canvas;
+
+import com.android.inputmethod.keyboard.PointerTracker;
+
+/**
+ * Abstract base class for previews that are drawn on PreviewPlacerView, e.g.,
+ * GestureFloatingPrevewText, GestureTrail, and SlidingKeyInputPreview.
+ */
+public abstract class AbstractDrawingPreview {
+ private boolean mPreviewEnabled;
+
+ public void setPreviewEnabled(final boolean enabled) {
+ mPreviewEnabled = enabled;
+ }
+
+ public boolean isPreviewEnabled() {
+ return mPreviewEnabled;
+ }
+
+ /**
+ * Draws the preview
+ * @param canvas The canvas where the preview is drawn.
+ */
+ public abstract void onDraw(final Canvas canvas);
+
+ /**
+ * Set the position of the preview.
+ * @param pt The new location of the preview is based on the points in PointerTracker pt.
+ */
+ public abstract void setPreviewPosition(final PointerTracker pt);
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java b/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java
new file mode 100644
index 000000000..84cfb389c
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2012 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.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.text.TextUtils;
+
+import com.android.inputmethod.keyboard.PointerTracker;
+import com.android.inputmethod.latin.CoordinateUtils;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.ResizableIntArray;
+import com.android.inputmethod.latin.SuggestedWords;
+
+/**
+ * The class for single gesture preview text. The class for multiple gesture preview text will be
+ * derived from it.
+ */
+public class GestureFloatingPreviewText extends AbstractDrawingPreview {
+ private static final class GesturePreviewTextParams {
+ public final int mGesturePreviewTextSize;
+ public final int mGesturePreviewTextColor;
+ public final int mGesturePreviewTextDimmedColor;
+ public final int mGesturePreviewTextOffset;
+ public final int mGesturePreviewTextHeight;
+ public final int mGesturePreviewColor;
+ public final float mGesturePreviewHorizontalPadding;
+ public final float mGesturePreviewVerticalPadding;
+ public final float mGesturePreviewRoundRadius;
+ public final Paint mTextPaint;
+
+ private static final char[] TEXT_HEIGHT_REFERENCE_CHAR = { 'M' };
+
+ public GesturePreviewTextParams(final TypedArray keyboardViewAttr) {
+ mGesturePreviewTextSize = keyboardViewAttr.getDimensionPixelSize(
+ R.styleable.KeyboardView_gestureFloatingPreviewTextSize, 0);
+ mGesturePreviewTextColor = keyboardViewAttr.getColor(
+ R.styleable.KeyboardView_gestureFloatingPreviewTextColor, 0);
+ mGesturePreviewTextOffset = keyboardViewAttr.getDimensionPixelOffset(
+ R.styleable.KeyboardView_gestureFloatingPreviewTextOffset, 0);
+ mGesturePreviewColor = keyboardViewAttr.getColor(
+ R.styleable.KeyboardView_gestureFloatingPreviewColor, 0);
+ mGesturePreviewHorizontalPadding = keyboardViewAttr.getDimension(
+ R.styleable.KeyboardView_gestureFloatingPreviewHorizontalPadding, 0.0f);
+ mGesturePreviewVerticalPadding = keyboardViewAttr.getDimension(
+ R.styleable.KeyboardView_gestureFloatingPreviewVerticalPadding, 0.0f);
+ mGesturePreviewRoundRadius = keyboardViewAttr.getDimension(
+ R.styleable.KeyboardView_gestureFloatingPreviewRoundRadius, 0.0f);
+ mGesturePreviewTextDimmedColor = Color.GRAY;
+
+ final Paint textPaint = new Paint();
+ textPaint.setAntiAlias(true);
+ textPaint.setTextAlign(Align.CENTER);
+ textPaint.setTextSize(mGesturePreviewTextSize);
+ mTextPaint = textPaint;
+ final Rect textRect = new Rect();
+ textPaint.getTextBounds(TEXT_HEIGHT_REFERENCE_CHAR, 0, 1, textRect);
+ mGesturePreviewTextHeight = textRect.height();
+ }
+ }
+
+ protected final GesturePreviewTextParams mParams;
+ protected int mPreviewWordNum;
+ protected final RectF mGesturePreviewRectangle = new RectF();
+ protected int mHighlightedWordIndex;
+
+ private static final int PREVIEW_TEXT_ARRAY_CAPACITY = 10;
+ // These variables store the positions of preview words. In multi-preview mode, the gesture
+ // floating preview at most shows PREVIEW_TEXT_ARRAY_CAPACITY words.
+ protected final ResizableIntArray mPreviewTextXArray = new ResizableIntArray(
+ PREVIEW_TEXT_ARRAY_CAPACITY);
+ protected final ResizableIntArray mPreviewTextYArray = new ResizableIntArray(
+ PREVIEW_TEXT_ARRAY_CAPACITY);
+
+ protected SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
+ protected final Context mContext;
+ public final int[] mLastPointerCoords = CoordinateUtils.newInstance();
+
+ public GestureFloatingPreviewText(final TypedArray typedArray, final Context context) {
+ mParams = new GesturePreviewTextParams(typedArray);
+ mHighlightedWordIndex = 0;
+ mContext = context;
+ }
+
+ public void setSuggetedWords(final SuggestedWords suggestedWords) {
+ if (suggestedWords == null) {
+ mSuggestedWords = SuggestedWords.EMPTY;
+ } else {
+ mSuggestedWords = suggestedWords;
+ }
+ updatePreviewPosition();
+ }
+
+ protected void drawText(final Canvas canvas, final String text, final float textX,
+ final float textY, final int color) {
+ final Paint paint = mParams.mTextPaint;
+ paint.setColor(color);
+ canvas.drawText(text, textX, textY, paint);
+ }
+
+ @Override
+ public void setPreviewPosition(final PointerTracker pt) {
+ pt.getLastCoordinates(mLastPointerCoords);
+ updatePreviewPosition();
+ }
+
+ /**
+ * Draws gesture preview text
+ * @param canvas The canvas where preview text is drawn.
+ */
+ @Override
+ public void onDraw(final Canvas canvas) {
+ if (!isPreviewEnabled() || mSuggestedWords.isEmpty()
+ || TextUtils.isEmpty(mSuggestedWords.getWord(0))) {
+ return;
+ }
+ final Paint paint = mParams.mTextPaint;
+ paint.setColor(mParams.mGesturePreviewColor);
+ final float round = mParams.mGesturePreviewRoundRadius;
+ canvas.drawRoundRect(mGesturePreviewRectangle, round, round, paint);
+ final String text = mSuggestedWords.getWord(0);
+ final int textX = mPreviewTextXArray.get(0);
+ final int textY = mPreviewTextYArray.get(0);
+ drawText(canvas, text, textX, textY, mParams.mGesturePreviewTextColor);
+ }
+
+ /**
+ * Updates gesture preview text position based on mLastPointerCoords.
+ */
+ protected void updatePreviewPosition() {
+ if (mSuggestedWords.isEmpty() || TextUtils.isEmpty(mSuggestedWords.getWord(0))) {
+ return;
+ }
+ final String text = mSuggestedWords.getWord(0);
+
+ final Paint paint = mParams.mTextPaint;
+ final RectF rectangle = mGesturePreviewRectangle;
+
+ final int textHeight = mParams.mGesturePreviewTextHeight;
+ final float textWidth = paint.measureText(text);
+ final float hPad = mParams.mGesturePreviewHorizontalPadding;
+ final float vPad = mParams.mGesturePreviewVerticalPadding;
+ final float rectWidth = textWidth + hPad * 2.0f;
+ final float rectHeight = textHeight + vPad * 2.0f;
+
+ final int displayWidth = mContext.getResources().getDisplayMetrics().widthPixels;
+ final float rectX = Math.min(
+ Math.max(CoordinateUtils.x(mLastPointerCoords) - rectWidth / 2.0f, 0.0f),
+ displayWidth - rectWidth);
+ final float rectY = CoordinateUtils.y(mLastPointerCoords)
+ - mParams.mGesturePreviewTextOffset - rectHeight;
+ rectangle.set(rectX, rectY, rectX + rectWidth, rectY + rectHeight);
+
+ final int textX = (int)(rectX + hPad + textWidth / 2.0f);
+ final int textY = (int)(rectY + vPad) + textHeight;
+ mPreviewTextXArray.add(0, textX);
+ mPreviewTextYArray.add(0, textY);
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
index 3a57f673a..f8949b2ad 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
@@ -101,6 +101,16 @@ final class GesturePreviewTrail {
}
}
+ /**
+ * Calculate the alpha of a gesture trail.
+ * A gesture trail starts from fully opaque. After mFadeStartDelay has been passed, the alpha
+ * of a trail reduces in proportion to the elapsed time. Then after mFadeDuration has been
+ * passed, a trail becomes fully transparent.
+ *
+ * @param elapsedTime the elapsed time since a trail has been made.
+ * @param params gesture trail display parameters
+ * @return the width of a gesture trail
+ */
private static int getAlpha(final int elapsedTime, final Params params) {
if (elapsedTime < params.mFadeoutStartDelay) {
return Constants.Color.ALPHA_OPAQUE;
@@ -111,10 +121,19 @@ final class GesturePreviewTrail {
return Constants.Color.ALPHA_OPAQUE - decreasingAlpha;
}
+ /**
+ * Calculate the width of a gesture trail.
+ * A gesture trail starts from the width of mTrailStartWidth and reduces its width in proportion
+ * to the elapsed time. After mTrailEndWidth has been passed, the width becomes mTraiLEndWidth.
+ *
+ * @param elapsedTime the elapsed time since a trail has been made.
+ * @param params gesture trail display parameters
+ * @return the width of a gesture trail
+ */
private static float getWidth(final int elapsedTime, final Params params) {
- return Math.max((params.mTrailLingerDuration - elapsedTime)
- * (params.mTrailStartWidth - params.mTrailEndWidth)
- / params.mTrailLingerDuration, 0.0f);
+ final int deltaTime = params.mTrailLingerDuration - elapsedTime;
+ final float deltaWidth = params.mTrailStartWidth - params.mTrailEndWidth;
+ return (deltaTime * deltaWidth) / params.mTrailLingerDuration + params.mTrailEndWidth;
}
private final RoundedLine mRoundedLine = new RoundedLine();
@@ -154,7 +173,7 @@ final class GesturePreviewTrail {
final RoundedLine line = mRoundedLine;
int p1x = getXCoordValue(xCoords[startIndex]);
int p1y = yCoords[startIndex];
- int lastTime = sinceDown - eventTimes[startIndex];
+ final int lastTime = sinceDown - eventTimes[startIndex];
float maxWidth = getWidth(lastTime, params);
float r1 = maxWidth / 2.0f;
// Initialize bounds rectangle.
@@ -167,20 +186,19 @@ final class GesturePreviewTrail {
final float r2 = width / 2.0f;
// Draw trail line only when the current point isn't a down point.
if (!isDownEventXCoord(xCoords[i])) {
- final int alpha = getAlpha(elapsedTime, params);
- paint.setAlpha(alpha);
final Path path = line.makePath(p1x, p1y, r1, p2x, p2y, r2);
if (path != null) {
+ final int alpha = getAlpha(elapsedTime, params);
+ paint.setAlpha(alpha);
canvas.drawPath(path, paint);
+ // Take union for the bounds.
outBoundsRect.union(p2x, p2y);
+ maxWidth = Math.max(maxWidth, width);
}
- // Take union for the bounds.
- maxWidth = Math.max(maxWidth, width);
}
p1x = p2x;
p1y = p2y;
r1 = r2;
- lastTime = elapsedTime;
}
// Take care of trail line width.
final int inset = -((int)maxWidth + 1);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index da418f41a..0f1d5cc80 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -20,6 +20,7 @@ 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.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -240,14 +241,14 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
try {
final int displayHeight = mDisplayMetrics.heightPixels;
final String keyboardHeightString = ResourceUtils.getDeviceOverrideValue(
- mResources, R.array.keyboard_heights, null);
+ mResources, R.array.keyboard_heights);
final float keyboardHeight;
- if (keyboardHeightString != null) {
- keyboardHeight = Float.parseFloat(keyboardHeightString)
- * mDisplayMetrics.density;
- } else {
+ if (TextUtils.isEmpty(keyboardHeightString)) {
keyboardHeight = keyboardAttr.getDimension(
R.styleable.Keyboard_keyboardHeight, displayHeight / 2);
+ } else {
+ keyboardHeight = Float.parseFloat(keyboardHeightString)
+ * mDisplayMetrics.density;
}
final float maxKeyboardHeight = ResourceUtils.getDimensionOrFraction(keyboardAttr,
R.styleable.Keyboard_maxKeyboardHeight, displayHeight, displayHeight / 2);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java
index bc734b08d..a005dc975 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java
@@ -22,13 +22,10 @@ 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.PorterDuffXfermode;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.os.Message;
-import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.widget.RelativeLayout;
@@ -39,15 +36,9 @@ import com.android.inputmethod.latin.CollectionUtils;
import com.android.inputmethod.latin.CoordinateUtils;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
+import com.android.inputmethod.latin.SuggestedWords;
public final class PreviewPlacerView extends RelativeLayout {
- private final int mGestureFloatingPreviewTextColor;
- private final int mGestureFloatingPreviewTextOffset;
- private final int mGestureFloatingPreviewColor;
- private final float mGestureFloatingPreviewHorizontalPadding;
- private final float mGestureFloatingPreviewVerticalPadding;
- private final float mGestureFloatingPreviewRoundRadius;
-
private final int[] mKeyboardViewOrigin = CoordinateUtils.newInstance();
private final SparseArray<GesturePreviewTrail> mGesturePreviewTrails =
@@ -62,16 +53,7 @@ public final class PreviewPlacerView extends RelativeLayout {
private final Canvas mOffscreenCanvas = new Canvas();
private final Rect mOffscreenDirtyRect = new Rect();
private final Rect mGesturePreviewTrailBoundsRect = new Rect(); // per trail
-
- private final Paint mTextPaint;
- private String mGestureFloatingPreviewText;
- private final int mGestureFloatingPreviewTextHeight;
- // {@link RectF} is needed for {@link Canvas#drawRoundRect(RectF, float, float, Paint)}.
- private final RectF mGestureFloatingPreviewRectangle = new RectF();
- private final int[] mLastPointerCoords = CoordinateUtils.newInstance();
- private static final char[] TEXT_HEIGHT_REFERENCE_CHAR = { 'M' };
- private boolean mDrawsGestureFloatingPreviewText;
-
+ private final GestureFloatingPreviewText mGestureFloatingPreviewText;
private boolean mShowSlidingKeyInputPreview;
private final int[] mRubberBandFrom = CoordinateUtils.newInstance();
private final int[] mRubberBandTo = CoordinateUtils.newInstance();
@@ -130,22 +112,11 @@ public final class PreviewPlacerView extends RelativeLayout {
final TypedArray keyboardViewAttr = context.obtainStyledAttributes(
attrs, R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
- final int gestureFloatingPreviewTextSize = keyboardViewAttr.getDimensionPixelSize(
- R.styleable.KeyboardView_gestureFloatingPreviewTextSize, 0);
- mGestureFloatingPreviewTextColor = keyboardViewAttr.getColor(
- R.styleable.KeyboardView_gestureFloatingPreviewTextColor, 0);
- mGestureFloatingPreviewTextOffset = keyboardViewAttr.getDimensionPixelOffset(
- R.styleable.KeyboardView_gestureFloatingPreviewTextOffset, 0);
- mGestureFloatingPreviewColor = keyboardViewAttr.getColor(
- R.styleable.KeyboardView_gestureFloatingPreviewColor, 0);
- mGestureFloatingPreviewHorizontalPadding = keyboardViewAttr.getDimension(
- R.styleable.KeyboardView_gestureFloatingPreviewHorizontalPadding, 0.0f);
- mGestureFloatingPreviewVerticalPadding = keyboardViewAttr.getDimension(
- R.styleable.KeyboardView_gestureFloatingPreviewVerticalPadding, 0.0f);
- mGestureFloatingPreviewRoundRadius = keyboardViewAttr.getDimension(
- R.styleable.KeyboardView_gestureFloatingPreviewRoundRadius, 0.0f);
final int gestureFloatingPreviewTextLingerTimeout = keyboardViewAttr.getInt(
R.styleable.KeyboardView_gestureFloatingPreviewTextLingerTimeout, 0);
+ // TODO: mGestureFloatingPreviewText could be an instance of GestureFloatingPreviewText or
+ // MultiGesturePreviewText, depending on the user's choice in the settings.
+ mGestureFloatingPreviewText = new GestureFloatingPreviewText(keyboardViewAttr, context);
mGesturePreviewTrailParams = new Params(keyboardViewAttr);
keyboardViewAttr.recycle();
@@ -157,15 +128,6 @@ public final class PreviewPlacerView extends RelativeLayout {
gesturePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
mGesturePaint = gesturePaint;
- final Paint textPaint = new Paint();
- textPaint.setAntiAlias(true);
- textPaint.setTextAlign(Align.CENTER);
- textPaint.setTextSize(gestureFloatingPreviewTextSize);
- mTextPaint = textPaint;
- final Rect textRect = new Rect();
- textPaint.getTextBounds(TEXT_HEIGHT_REFERENCE_CHAR, 0, 1, textRect);
- mGestureFloatingPreviewTextHeight = textRect.height();
-
final Paint layerPaint = new Paint();
layerPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
setLayerType(LAYER_TYPE_HARDWARE, layerPaint);
@@ -181,14 +143,14 @@ public final class PreviewPlacerView extends RelativeLayout {
public void setGesturePreviewMode(final boolean drawsGesturePreviewTrail,
final boolean drawsGestureFloatingPreviewText) {
mDrawsGesturePreviewTrail = drawsGesturePreviewTrail;
- mDrawsGestureFloatingPreviewText = drawsGestureFloatingPreviewText;
+ mGestureFloatingPreviewText.setPreviewEnabled(drawsGestureFloatingPreviewText);
}
public void invalidatePointer(final PointerTracker tracker, final boolean isOldestTracker) {
final boolean needsToUpdateLastPointer =
- isOldestTracker && mDrawsGestureFloatingPreviewText;
+ isOldestTracker && mGestureFloatingPreviewText.isPreviewEnabled();
if (needsToUpdateLastPointer) {
- tracker.getLastCoordinates(mLastPointerCoords);
+ mGestureFloatingPreviewText.setPreviewPosition(tracker);
}
if (mDrawsGesturePreviewTrail) {
@@ -252,6 +214,7 @@ public final class PreviewPlacerView extends RelativeLayout {
super.onDraw(canvas);
final int originX = CoordinateUtils.x(mKeyboardViewOrigin);
final int originY = CoordinateUtils.y(mKeyboardViewOrigin);
+ canvas.translate(originX, originY);
if (mDrawsGesturePreviewTrail) {
mayAllocateOffscreenBuffer();
// Draw gesture trails to offscreen buffer.
@@ -259,11 +222,10 @@ public final class PreviewPlacerView extends RelativeLayout {
mOffscreenCanvas, mGesturePaint, mOffscreenDirtyRect);
// Transfer offscreen buffer to screen.
if (!mOffscreenDirtyRect.isEmpty()) {
- final int offsetY = originY - mOffscreenOffsetY;
- canvas.translate(originX, offsetY);
+ canvas.translate(0, - mOffscreenOffsetY);
canvas.drawBitmap(mOffscreenBuffer, mOffscreenDirtyRect, mOffscreenDirtyRect,
mGesturePaint);
- canvas.translate(-originX, -offsetY);
+ canvas.translate(0, mOffscreenOffsetY);
// Note: Defer clearing the dirty rectangle here because we will get cleared
// rectangle on the canvas.
}
@@ -271,16 +233,11 @@ public final class PreviewPlacerView extends RelativeLayout {
mDrawingHandler.postUpdateGestureTrailPreview();
}
}
- if (mDrawsGestureFloatingPreviewText) {
- canvas.translate(originX, originY);
- drawGestureFloatingPreviewText(canvas, mGestureFloatingPreviewText);
- canvas.translate(-originX, -originY);
- }
+ mGestureFloatingPreviewText.onDraw(canvas);
if (mShowSlidingKeyInputPreview) {
- canvas.translate(originX, originY);
drawSlidingKeyInputPreview(canvas);
- canvas.translate(-originX, -originY);
}
+ canvas.translate(-originX, -originY);
}
private boolean drawGestureTrails(final Canvas offscreenCanvas, final Paint paint,
@@ -322,9 +279,9 @@ public final class PreviewPlacerView extends RelativeLayout {
Math.min(out.bottom, bottom));
}
- public void setGestureFloatingPreviewText(final String gestureFloatingPreviewText) {
- if (!mDrawsGestureFloatingPreviewText) return;
- mGestureFloatingPreviewText = gestureFloatingPreviewText;
+ public void setGestureFloatingPreviewText(final SuggestedWords suggestedWords) {
+ if (!mGestureFloatingPreviewText.isPreviewEnabled()) return;
+ mGestureFloatingPreviewText.setSuggetedWords(suggestedWords);
invalidate();
}
@@ -332,39 +289,6 @@ public final class PreviewPlacerView extends RelativeLayout {
mDrawingHandler.dismissGestureFloatingPreviewText();
}
- private void drawGestureFloatingPreviewText(final Canvas canvas,
- final String gestureFloatingPreviewText) {
- if (TextUtils.isEmpty(gestureFloatingPreviewText)) {
- return;
- }
-
- final Paint paint = mTextPaint;
- final RectF rectangle = mGestureFloatingPreviewRectangle;
-
- // Paint the round rectangle background.
- final int textHeight = mGestureFloatingPreviewTextHeight;
- final float textWidth = paint.measureText(gestureFloatingPreviewText);
- final float hPad = mGestureFloatingPreviewHorizontalPadding;
- final float vPad = mGestureFloatingPreviewVerticalPadding;
- final float rectWidth = textWidth + hPad * 2.0f;
- final float rectHeight = textHeight + vPad * 2.0f;
- final int canvasWidth = canvas.getWidth();
- final float rectX = Math.min(
- Math.max(CoordinateUtils.x(mLastPointerCoords) - rectWidth / 2.0f, 0.0f),
- canvasWidth - rectWidth);
- final float rectY = CoordinateUtils.y(mLastPointerCoords)
- - mGestureFloatingPreviewTextOffset - rectHeight;
- rectangle.set(rectX, rectY, rectX + rectWidth, rectY + rectHeight);
- final float round = mGestureFloatingPreviewRoundRadius;
- paint.setColor(mGestureFloatingPreviewColor);
- canvas.drawRoundRect(rectangle, round, round, paint);
- // Paint the text preview
- paint.setColor(mGestureFloatingPreviewTextColor);
- final float textX = rectX + hPad + textWidth / 2.0f;
- final float textY = rectY + vPad + textHeight;
- canvas.drawText(gestureFloatingPreviewText, textX, textY, paint);
- }
-
private void drawSlidingKeyInputPreview(final Canvas canvas) {
// TODO: Implement rubber band preview
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/TouchScreenRegulator.java b/java/src/com/android/inputmethod/keyboard/internal/TouchScreenRegulator.java
index c795d5322..e7a0a70d1 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/TouchScreenRegulator.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/TouchScreenRegulator.java
@@ -55,7 +55,7 @@ public final class TouchScreenRegulator {
public TouchScreenRegulator(final Context context, final ProcessMotionEvent view) {
mView = view;
mNeedsSuddenJumpingHack = Boolean.parseBoolean(ResourceUtils.getDeviceOverrideValue(
- context.getResources(), R.array.sudden_jumping_touch_event_device_list, "false"));
+ context.getResources(), R.array.sudden_jumping_touch_event_device_list));
}
public void setKeyboardGeometry(final int keyboardWidth) {
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
index 509fc1ba3..820733bdc 100644
--- a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
@@ -45,7 +45,7 @@ public final class AdditionalSubtype {
final String keyboardLayoutSetName, final String extraValue) {
final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName;
final String layoutDisplayNameExtraValue;
- if (Build.VERSION.SDK_INT >= /* JELLY_BEAN */ 15
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& SubtypeLocale.isExceptionalLocale(localeString)) {
final String layoutDisplayName = SubtypeLocale.getKeyboardLayoutSetDisplayName(
keyboardLayoutSetName);
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
index 08f08d24e..6ac5a9b94 100644
--- a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
@@ -387,7 +387,7 @@ public final class AdditionalSubtypeSettings extends PreferenceFragment {
super.onCreate(savedInstanceState);
mPrefs = getPreferenceManager().getSharedPreferences();
- RichInputMethodManager.init(getActivity(), mPrefs);
+ RichInputMethodManager.init(getActivity());
mRichImm = RichInputMethodManager.getInstance();
addPreferencesFromResource(R.xml.additional_subtype_settings);
setHasOptionsMenu(true);
diff --git a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java
index 024726391..6367156ef 100644
--- a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java
+++ b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java
@@ -18,11 +18,10 @@ package com.android.inputmethod.latin;
import android.content.Context;
import android.media.AudioManager;
+import android.os.Vibrator;
import android.view.HapticFeedbackConstants;
import android.view.View;
-import com.android.inputmethod.latin.VibratorUtils;
-
/**
* This class gathers audio feedback and haptic feedback functions.
*
@@ -30,34 +29,63 @@ import com.android.inputmethod.latin.VibratorUtils;
* complexity of settings and the like.
*/
public final class AudioAndHapticFeedbackManager {
- private final AudioManager mAudioManager;
- private final VibratorUtils mVibratorUtils;
+ public static final int MAX_KEYPRESS_VIBRATION_DURATION = 250; // millisecond
+
+ private AudioManager mAudioManager;
+ private Vibrator mVibrator;
private SettingsValues mSettingsValues;
private boolean mSoundOn;
- public AudioAndHapticFeedbackManager(final LatinIME latinIme) {
- mVibratorUtils = VibratorUtils.getInstance(latinIme);
- mAudioManager = (AudioManager) latinIme.getSystemService(Context.AUDIO_SERVICE);
+ private static final AudioAndHapticFeedbackManager sInstance =
+ new AudioAndHapticFeedbackManager();
+
+ public static AudioAndHapticFeedbackManager getInstance() {
+ return sInstance;
+ }
+
+ private AudioAndHapticFeedbackManager() {
+ // Intentional empty constructor for singleton.
+ }
+
+ public static void init(final Context context) {
+ sInstance.initInternal(context);
+ }
+
+ private void initInternal(final Context context) {
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+ mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
}
public void hapticAndAudioFeedback(final int primaryCode,
final View viewToPerformHapticFeedbackOn) {
- vibrate(viewToPerformHapticFeedbackOn);
+ vibrateInternal(viewToPerformHapticFeedbackOn);
playKeyClick(primaryCode);
}
+ public boolean hasVibrator() {
+ return mVibrator != null && mVibrator.hasVibrator();
+ }
+
+ public void vibrate(final long milliseconds) {
+ if (mVibrator == null) {
+ return;
+ }
+ mVibrator.vibrate(milliseconds);
+ }
+
private boolean reevaluateIfSoundIsOn() {
if (mSettingsValues == null || !mSettingsValues.mSoundOn || mAudioManager == null) {
return false;
- } else {
- return mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL;
}
+ return mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL;
}
- private void playKeyClick(int primaryCode) {
+ private void playKeyClick(final int primaryCode) {
// if mAudioManager is null, we can't play a sound anyway, so return
- if (mAudioManager == null) return;
+ if (mAudioManager == null) {
+ return;
+ }
if (mSoundOn) {
final int sound;
switch (primaryCode) {
@@ -78,7 +106,7 @@ public final class AudioAndHapticFeedbackManager {
}
}
- private void vibrate(final View viewToPerformHapticFeedbackOn) {
+ private void vibrateInternal(final View viewToPerformHapticFeedbackOn) {
if (!mSettingsValues.mVibrateOn) {
return;
}
@@ -89,9 +117,9 @@ public final class AudioAndHapticFeedbackManager {
HapticFeedbackConstants.KEYBOARD_TAP,
HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
}
- } else if (mVibratorUtils != null) {
- mVibratorUtils.vibrate(mSettingsValues.mKeypressVibrationDuration);
+ return;
}
+ vibrate(mSettingsValues.mKeypressVibrationDuration);
}
public void onSettingsChanged(final SettingsValues settingsValues) {
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
index 16ec5b5db..3a7772452 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -111,7 +111,7 @@ public final class Constants {
}
}
- public static class TextUtils {
+ public static final class TextUtils {
/**
* Capitalization mode for {@link android.text.TextUtils#getCapsMode}: don't capitalize
* characters. This value may be used with
@@ -126,7 +126,7 @@ public final class Constants {
}
}
- public static class Dictionary {
+ public static final class Dictionary {
public static final int MAX_WORD_LENGTH = 48;
private Dictionary() {
@@ -139,6 +139,7 @@ public final class Constants {
public static final int NOT_A_COORDINATE = -1;
public static final int SUGGESTION_STRIP_COORDINATE = -2;
public static final int SPELL_CHECKER_COORDINATE = -3;
+ public static final int EXTERNAL_KEYBOARD_COORDINATE = -4;
public static boolean isValidCoordinate(final int coordinate) {
// Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE},
diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
index 7f78ac8a2..9a771cf1e 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
@@ -38,7 +38,7 @@ public final class DictionaryCollection extends Dictionary {
mDictionaries = CollectionUtils.newCopyOnWriteArrayList();
}
- public DictionaryCollection(final String dictType, Dictionary... dictionaries) {
+ public DictionaryCollection(final String dictType, final Dictionary... dictionaries) {
super(dictType);
if (null == dictionaries) {
mDictionaries = CollectionUtils.newCopyOnWriteArrayList();
@@ -48,7 +48,7 @@ public final class DictionaryCollection extends Dictionary {
}
}
- public DictionaryCollection(final String dictType, Collection<Dictionary> dictionaries) {
+ public DictionaryCollection(final String dictType, final Collection<Dictionary> dictionaries) {
super(dictType);
mDictionaries = CollectionUtils.newCopyOnWriteArrayList(dictionaries);
mDictionaries.removeAll(Collections.singleton(null));
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index dcc131fc5..28994dc8e 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -35,6 +35,7 @@ import android.graphics.Rect;
import android.inputmethodservice.InputMethodService;
import android.media.AudioManager;
import android.net.ConnectivityManager;
+import android.os.Build.VERSION_CODES;
import android.os.Debug;
import android.os.Handler;
import android.os.HandlerThread;
@@ -72,7 +73,6 @@ import com.android.inputmethod.keyboard.KeyboardId;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.KeyboardView;
import com.android.inputmethod.keyboard.MainKeyboardView;
-import com.android.inputmethod.latin.LocaleUtils.RunInLocale;
import com.android.inputmethod.latin.Utils.Stats;
import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethod.latin.suggestions.SuggestionStripView;
@@ -127,7 +127,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// Current space state of the input method. This can be any of the above constants.
private int mSpaceState;
- private SettingsValues mCurrentSettings;
+ private final Settings mSettings;
private View mExtractArea;
private View mKeyPreviewBackingView;
@@ -138,14 +138,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
private ApplicationInfo mTargetApplicationInfo;
private RichInputMethodManager mRichImm;
- private Resources mResources;
- private SharedPreferences mPrefs;
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
private final SubtypeSwitcher mSubtypeSwitcher;
private final SubtypeState mSubtypeState = new SubtypeState();
// At start, create a default event interpreter that does nothing by passing it no decoder spec.
// The event interpreter should never be null.
- private EventInterpreter mEventInterpreter = new EventInterpreter();
+ private EventInterpreter mEventInterpreter = new EventInterpreter(this);
private boolean mIsMainDictionaryAvailable;
private UserBinaryDictionary mUserDictionary;
@@ -400,6 +398,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
public LatinIME() {
super();
+ mSettings = Settings.getInstance();
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
mIsHardwareAcceleratedDrawingEnabled =
@@ -409,17 +408,16 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
@Override
public void onCreate() {
- mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- mResources = getResources();
-
- LatinImeLogger.init(this, mPrefs);
+ Settings.init(this);
+ LatinImeLogger.init(this);
if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.getInstance().init(this, mPrefs);
+ ResearchLogger.getInstance().init(this);
}
- RichInputMethodManager.init(this, mPrefs);
+ RichInputMethodManager.init(this);
mRichImm = RichInputMethodManager.getInstance();
SubtypeSwitcher.init(this);
- KeyboardSwitcher.init(this, mPrefs);
+ KeyboardSwitcher.init(this);
+ AudioAndHapticFeedbackManager.init(this);
AccessibilityUtils.init(this);
super.onCreate();
@@ -430,7 +428,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
loadSettings();
initSuggest();
- mDisplayOrientation = mResources.getConfiguration().orientation;
+ mDisplayOrientation = getResources().getConfiguration().orientation;
// Register to receive ringer mode change and network state change.
// Also receive installation and removal of a dictionary pack.
@@ -457,18 +455,10 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// Has to be package-visible for unit tests
@UsedForTesting
void loadSettings() {
- // Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged()
- // is not guaranteed. It may even be called at the same time on a different thread.
- if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+ final Locale locale = mSubtypeSwitcher.getCurrentSubtypeLocale();
final InputAttributes inputAttributes =
new InputAttributes(getCurrentInputEditorInfo(), isFullscreenMode());
- final RunInLocale<SettingsValues> job = new RunInLocale<SettingsValues>() {
- @Override
- protected SettingsValues job(Resources res) {
- return new SettingsValues(mPrefs, inputAttributes, LatinIME.this);
- }
- };
- mCurrentSettings = job.runInLocale(mResources, mSubtypeSwitcher.getCurrentSubtypeLocale());
+ mSettings.loadSettings(locale, inputAttributes);
resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
}
@@ -495,8 +485,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
}
mSuggest = new Suggest(this /* Context */, subtypeLocale,
this /* SuggestInitializationListener */);
- if (mCurrentSettings.mCorrectionEnabled) {
- mSuggest.setAutoCorrectionThreshold(mCurrentSettings.mAutoCorrectionThreshold);
+ if (mSettings.getCurrent().mCorrectionEnabled) {
+ mSuggest.setAutoCorrectionThreshold(mSettings.getCurrent().mAutoCorrectionThreshold);
}
mIsMainDictionaryAvailable = DictionaryFactory.isDictionaryAvailable(this, subtypeLocale);
@@ -510,10 +500,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
resetContactsDictionary(oldContactsDictionary);
- // Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged()
- // is not guaranteed. It may even be called at the same time on a different thread.
- if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- mUserHistoryDictionary = UserHistoryDictionary.getInstance(this, localeStr, mPrefs);
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ mUserHistoryDictionary = UserHistoryDictionary.getInstance(this, localeStr, prefs);
mSuggest.setUserHistoryDictionary(mUserHistoryDictionary);
}
@@ -526,7 +514,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
* @param oldContactsDictionary an optional dictionary to use, or null
*/
private void resetContactsDictionary(final ContactsBinaryDictionary oldContactsDictionary) {
- final boolean shouldSetDictionary = (null != mSuggest && mCurrentSettings.mUseContactsDict);
+ final boolean shouldSetDictionary =
+ (null != mSuggest && mSettings.getCurrent().mUseContactsDict);
final ContactsBinaryDictionary dictionaryToUse;
if (!shouldSetDictionary) {
@@ -570,6 +559,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
mSuggest.close();
mSuggest = null;
}
+ mSettings.onDestroy();
unregisterReceiver(mReceiver);
// TODO: The experimental version is not supported by the Dictionary Pack Service yet.
if (!ProductionFlag.IS_EXPERIMENTAL) {
@@ -582,10 +572,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
@Override
public void onConfigurationChanged(final Configuration conf) {
- // System locale has been changed. Needs to reload keyboard.
- if (mSubtypeSwitcher.onConfigurationChanged(conf)) {
- loadKeyboard();
- }
// If orientation changed while predicting, commit the change
if (mDisplayOrientation != conf.orientation) {
mDisplayOrientation = conf.orientation;
@@ -651,7 +637,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
public void onCurrentInputMethodSubtypeChanged(final InputMethodSubtype subtype) {
// Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged()
// is not guaranteed. It may even be called at the same time on a different thread.
- mSubtypeSwitcher.updateSubtype(subtype);
+ mSubtypeSwitcher.onSubtypeChanged(subtype);
loadKeyboard();
}
@@ -684,7 +670,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
+ ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_WORDS) != 0));
}
if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_onStartInputViewInternal(editorInfo, mPrefs);
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ ResearchLogger.latinIME_onStartInputViewInternal(editorInfo, prefs);
}
if (InputAttributes.inPrivateImeOptions(null, NO_MICROPHONE_COMPAT, editorInfo)) {
Log.w(TAG, "Deprecated private IME option specified: "
@@ -716,18 +703,10 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
accessUtils.onStartInputViewInternal(mainKeyboardView, editorInfo, restarting);
}
- final boolean inputTypeChanged = !mCurrentSettings.isSameInputType(editorInfo);
+ final boolean inputTypeChanged = !mSettings.getCurrent().isSameInputType(editorInfo);
final boolean isDifferentTextField = !restarting || inputTypeChanged;
if (isDifferentTextField) {
- final boolean currentSubtypeEnabled = mSubtypeSwitcher
- .updateParametersOnStartInputViewAndReturnIfCurrentSubtypeEnabled();
- if (!currentSubtypeEnabled) {
- // Current subtype is disabled. Needs to update subtype and keyboard.
- final InputMethodSubtype newSubtype = mRichImm.getCurrentInputMethodSubtype(
- mSubtypeSwitcher.getNoLanguageSubtype());
- mSubtypeSwitcher.updateSubtype(newSubtype);
- loadKeyboard();
- }
+ mSubtypeSwitcher.updateParametersOnStartInputView();
}
// The EditorInfo might have a flag that affects fullscreen mode.
@@ -754,11 +733,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
mainKeyboardView.closing();
loadSettings();
- if (mSuggest != null && mCurrentSettings.mCorrectionEnabled) {
- mSuggest.setAutoCorrectionThreshold(mCurrentSettings.mAutoCorrectionThreshold);
+ if (mSuggest != null && mSettings.getCurrent().mCorrectionEnabled) {
+ mSuggest.setAutoCorrectionThreshold(
+ mSettings.getCurrent().mAutoCorrectionThreshold);
}
- switcher.loadKeyboard(editorInfo, mCurrentSettings);
+ switcher.loadKeyboard(editorInfo, mSettings.getCurrent());
} else if (restarting) {
// TODO: Come up with a more comprehensive way to reset the keyboard layout when
// a keyboard layout set doesn't get reloaded in this method.
@@ -779,11 +759,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
mHandler.cancelDoubleSpacePeriodTimer();
mainKeyboardView.setMainDictionaryAvailability(mIsMainDictionaryAvailable);
- mainKeyboardView.setKeyPreviewPopupEnabled(mCurrentSettings.mKeyPreviewPopupOn,
- mCurrentSettings.mKeyPreviewPopupDismissDelay);
- mainKeyboardView.setGestureHandlingEnabledByUser(mCurrentSettings.mGestureInputEnabled);
- mainKeyboardView.setGesturePreviewMode(mCurrentSettings.mGesturePreviewTrailEnabled,
- mCurrentSettings.mGestureFloatingPreviewTextEnabled);
+ mainKeyboardView.setKeyPreviewPopupEnabled(mSettings.getCurrent().mKeyPreviewPopupOn,
+ mSettings.getCurrent().mKeyPreviewPopupDismissDelay);
+ mainKeyboardView.setGestureHandlingEnabledByUser(
+ mSettings.getCurrent().mGestureInputEnabled);
+ mainKeyboardView.setGesturePreviewMode(mSettings.getCurrent().mGesturePreviewTrailEnabled,
+ mSettings.getCurrent().mGestureFloatingPreviewTextEnabled);
// If we have a user dictionary addition in progress, we should check now if we should
// replace the previously committed string with the word that has actually been added
@@ -941,7 +922,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
*/
@Override
public void onExtractedTextClicked() {
- if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) return;
+ if (mSettings.getCurrent().isSuggestionsRequested(mDisplayOrientation)) return;
super.onExtractedTextClicked();
}
@@ -957,7 +938,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
*/
@Override
public void onExtractedCursorMovement(final int dx, final int dy) {
- if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) return;
+ if (mSettings.getCurrent().isSuggestionsRequested(mDisplayOrientation)) return;
super.onExtractedCursorMovement(dx, dy);
}
@@ -985,7 +966,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
}
}
}
- if (!mCurrentSettings.isApplicationSpecifiedCompletionsOn()) return;
+ if (!mSettings.getCurrent().isApplicationSpecifiedCompletionsOn()) return;
mApplicationSpecifiedCompletions = applicationSpecifiedCompletions;
if (applicationSpecifiedCompletions == null) {
clearSuggestionStrip();
@@ -1009,9 +990,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
final boolean isAutoCorrection = false;
setSuggestionStrip(suggestedWords, isAutoCorrection);
setAutoCorrectionIndicator(isAutoCorrection);
- // TODO: is this the right thing to do? What should we auto-correct to in
- // this case? This says to keep whatever the user typed.
- mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
setSuggestionStripShown(true);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions);
@@ -1053,7 +1031,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
}
final int keyboardHeight = mainKeyboardView.getHeight();
final int suggestionsHeight = mSuggestionsContainer.getHeight();
- final int displayHeight = mResources.getDisplayMetrics().heightPixels;
+ final int displayHeight = getResources().getDisplayMetrics().heightPixels;
final Rect rect = new Rect();
mKeyPreviewBackingView.getWindowVisibleDisplayFrame(rect);
final int notificationBarHeight = rect.top;
@@ -1132,10 +1110,10 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// the composing word, reset the last composed word, tell the inputconnection about it.
private void resetEntireInputState(final int newCursorPosition) {
resetComposingState(true /* alsoResetLastComposedWord */);
- if (mCurrentSettings.mBigramPredictionEnabled) {
+ if (mSettings.getCurrent().mBigramPredictionEnabled) {
clearSuggestionStrip();
} else {
- setSuggestionStrip(mCurrentSettings.mSuggestPuncList, false);
+ setSuggestionStrip(mSettings.getCurrent().mSuggestPuncList, false);
}
mConnection.resetCachesUponCursorMove(newCursorPosition);
}
@@ -1152,13 +1130,16 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
if (typedWord.length() > 0) {
commitChosenWord(typedWord, LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD,
separatorString);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().onWordComplete(typedWord, Long.MAX_VALUE);
+ }
}
}
// Called from the KeyboardSwitcher which needs to know auto caps state to display
// the right layout.
public int getCurrentAutoCapsState() {
- if (!mCurrentSettings.mAutoCap) return Constants.TextUtils.CAP_MODE_OFF;
+ if (!mSettings.getCurrent().mAutoCap) return Constants.TextUtils.CAP_MODE_OFF;
final EditorInfo ei = getCurrentInputEditorInfo();
if (ei == null) return Constants.TextUtils.CAP_MODE_OFF;
@@ -1187,8 +1168,10 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
if (lastTwo != null && lastTwo.length() == 2
&& lastTwo.charAt(0) == Constants.CODE_SPACE) {
mConnection.deleteSurroundingText(2, 0);
- mConnection.commitText(lastTwo.charAt(1) + " ", 1);
+ final String text = lastTwo.charAt(1) + " ";
+ mConnection.commitText(text, 1);
if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().onWordComplete(text, Long.MAX_VALUE);
ResearchLogger.latinIME_swapSwapperAndSpace();
}
mKeyboardSwitcher.updateShiftState();
@@ -1196,8 +1179,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
}
private boolean maybeDoubleSpacePeriod() {
- if (!mCurrentSettings.mCorrectionEnabled) return false;
- if (!mCurrentSettings.mUseDoubleSpacePeriod) return false;
+ if (!mSettings.getCurrent().mCorrectionEnabled) return false;
+ if (!mSettings.getCurrent().mUseDoubleSpacePeriod) return false;
if (!mHandler.isAcceptingDoubleSpacePeriod()) return false;
final CharSequence lastThree = mConnection.getTextBeforeCursor(3, 0);
if (lastThree != null && lastThree.length() == 3
@@ -1206,7 +1189,11 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
&& lastThree.charAt(2) == Constants.CODE_SPACE) {
mHandler.cancelDoubleSpacePeriodTimer();
mConnection.deleteSurroundingText(2, 0);
- mConnection.commitText(". ", 1);
+ final String textToInsert = ". ";
+ mConnection.commitText(textToInsert, 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().onWordComplete(textToInsert, Long.MAX_VALUE);
+ }
mKeyboardSwitcher.updateShiftState();
return true;
}
@@ -1296,7 +1283,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// TODO: Revise the language switch key behavior to make it much smarter and more reasonable.
private void handleLanguageSwitchKey() {
final IBinder token = getWindow().getWindow().getAttributes().token;
- if (mCurrentSettings.mIncludesOtherImesInLanguageSwitchList) {
+ if (mSettings.getCurrent().mIncludesOtherImesInLanguageSwitchList) {
mRichImm.switchToNextInputMethod(token, false /* onlyCurrentIme */);
return;
}
@@ -1324,10 +1311,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
return;
}
- // 16 is android.os.Build.VERSION_CODES.JELLY_BEAN but we can't write it because
- // we want to be able to compile against the Ice Cream Sandwich SDK.
if (Constants.CODE_ENTER == code && mTargetApplicationInfo != null
- && mTargetApplicationInfo.targetSdkVersion < 16) {
+ && mTargetApplicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN) {
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate
// a hardware keyboard event on pressing enter or delete. This is bad for many
// reasons (there are race conditions with commits) but some applications are
@@ -1400,7 +1385,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
break;
default:
mSpaceState = SPACE_STATE_NONE;
- if (mCurrentSettings.isWordSeparator(primaryCode)) {
+ if (mSettings.getCurrent().isWordSeparator(primaryCode)) {
didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState);
} else {
if (SPACE_STATE_PHANTOM == spaceState) {
@@ -1445,7 +1430,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
public void onTextInput(final String rawText) {
mConnection.beginBatchEdit();
if (mWordComposer.isComposingWord()) {
- commitCurrentAutoCorrection(rawText.toString());
+ commitCurrentAutoCorrection(rawText);
} else {
resetComposingState(true /* alsoResetLastComposedWord */);
}
@@ -1455,6 +1440,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
promotePhantomSpace();
}
mConnection.commitText(text, 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().onWordComplete(text, Long.MAX_VALUE);
+ }
mConnection.endBatchEdit();
// Space state must be updated before calling updateShiftState
mSpaceState = SPACE_STATE_NONE;
@@ -1495,8 +1483,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// should usually be followed by a space, and it should be more readable.
if (Constants.NOT_A_CODE != codePointBeforeCursor
&& !Character.isWhitespace(codePointBeforeCursor)
- && !mCurrentSettings.isPhantomSpacePromotingSymbol(codePointBeforeCursor)
- && !mCurrentSettings.isWeakSpaceStripper(codePointBeforeCursor)) {
+ && !mSettings.getCurrent().isPhantomSpacePromotingSymbol(codePointBeforeCursor)
+ && !mSettings.getCurrent().isWeakSpaceStripper(codePointBeforeCursor)) {
mSpaceState = SPACE_STATE_PHANTOM;
}
}
@@ -1603,9 +1591,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
if (dismissGestureFloatingPreviewText) {
mainKeyboardView.dismissGestureFloatingPreviewText();
} else {
- final String batchInputText = suggestedWords.isEmpty()
- ? null : suggestedWords.getWord(0);
- mainKeyboardView.showGestureFloatingPreviewText(batchInputText);
+ mainKeyboardView.showGestureFloatingPreviewText(suggestedWords);
}
}
@@ -1739,10 +1725,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// This should never happen.
Log.e(TAG, "Backspace when we don't know the selection position");
}
- // 16 is android.os.Build.VERSION_CODES.JELLY_BEAN but we can't write it because
- // we want to be able to compile against the Ice Cream Sandwich SDK.
if (mTargetApplicationInfo != null
- && mTargetApplicationInfo.targetSdkVersion < 16) {
+ && mTargetApplicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN) {
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate
// a hardware keyboard event on pressing enter or delete. This is bad for many
// reasons (there are race conditions with commits) but some applications are
@@ -1755,7 +1739,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
mConnection.deleteSurroundingText(1, 0);
}
}
- if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
+ if (mSettings.getCurrent().isSuggestionsRequested(mDisplayOrientation)) {
restartSuggestionsOnWordBeforeCursorIfAtEndOfWord();
}
}
@@ -1769,10 +1753,10 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
} else if ((SPACE_STATE_WEAK == spaceState
|| SPACE_STATE_SWAP_PUNCTUATION == spaceState)
&& isFromSuggestionStrip) {
- if (mCurrentSettings.isWeakSpaceSwapper(code)) {
+ if (mSettings.getCurrent().isWeakSpaceSwapper(code)) {
return true;
} else {
- if (mCurrentSettings.isWeakSpaceStripper(code)) {
+ if (mSettings.getCurrent().isWeakSpaceStripper(code)) {
mConnection.removeTrailingSpace();
}
return false;
@@ -1787,7 +1771,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
boolean isComposingWord = mWordComposer.isComposingWord();
if (SPACE_STATE_PHANTOM == spaceState &&
- !mCurrentSettings.isSymbolExcludedFromWordSeparators(primaryCode)) {
+ !mSettings.getCurrent().isSymbolExcludedFromWordSeparators(primaryCode)) {
if (isComposingWord) {
// Sanity check
throw new RuntimeException("Should not be composing here");
@@ -1799,9 +1783,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// dozen milliseconds. Avoid calling it as much as possible, since we are on the UI
// thread here.
if (!isComposingWord && (isAlphabet(primaryCode)
- || mCurrentSettings.isSymbolExcludedFromWordSeparators(primaryCode))
- && mCurrentSettings.isSuggestionsRequested(mDisplayOrientation) &&
- !mConnection.isCursorTouchingWord(mCurrentSettings)) {
+ || mSettings.getCurrent().isSymbolExcludedFromWordSeparators(primaryCode))
+ && mSettings.getCurrent().isSuggestionsRequested(mDisplayOrientation) &&
+ !mConnection.isCursorTouchingWord(mSettings.getCurrent())) {
// 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
@@ -1855,7 +1839,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
boolean didAutoCorrect = false;
// Handle separator
if (mWordComposer.isComposingWord()) {
- if (mCurrentSettings.mCorrectionEnabled) {
+ if (mSettings.getCurrent().mCorrectionEnabled) {
// TODO: maybe cache Strings in an <String> sparse array or something
commitCurrentAutoCorrection(new String(new int[]{primaryCode}, 0, 1));
didAutoCorrect = true;
@@ -1868,13 +1852,13 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
Constants.SUGGESTION_STRIP_COORDINATE == x);
if (SPACE_STATE_PHANTOM == spaceState &&
- mCurrentSettings.isPhantomSpacePromotingSymbol(primaryCode)) {
+ mSettings.getCurrent().isPhantomSpacePromotingSymbol(primaryCode)) {
promotePhantomSpace();
}
sendKeyCodePoint(primaryCode);
if (Constants.CODE_SPACE == primaryCode) {
- if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
+ if (mSettings.getCurrent().isSuggestionsRequested(mDisplayOrientation)) {
if (maybeDoubleSpacePeriod()) {
mSpaceState = SPACE_STATE_DOUBLE;
} else if (!isShowingPunctuationList()) {
@@ -1883,7 +1867,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
}
mHandler.startDoubleSpacePeriodTimer();
- if (!mConnection.isCursorTouchingWord(mCurrentSettings)) {
+ if (!mConnection.isCursorTouchingWord(mSettings.getCurrent())) {
mHandler.postUpdateSuggestionStrip();
}
} else {
@@ -1891,8 +1875,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
swapSwapperAndSpace();
mSpaceState = SPACE_STATE_SWAP_PUNCTUATION;
} else if (SPACE_STATE_PHANTOM == spaceState
- && !mCurrentSettings.isWeakSpaceStripper(primaryCode)
- && !mCurrentSettings.isPhantomSpacePromotingSymbol(primaryCode)) {
+ && !mSettings.getCurrent().isWeakSpaceStripper(primaryCode)
+ && !mSettings.getCurrent().isPhantomSpacePromotingSymbol(primaryCode)) {
// If we are in phantom space state, and the user presses a separator, we want to
// stay in phantom space state so that the next keypress has a chance to add the
// space. For example, if I type "Good dat", pick "day" from the suggestion strip
@@ -1925,6 +1909,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
}
private void handleClose() {
+ // TODO: Verify that words are logged properly when IME is closed.
commitTyped(LastComposedWord.NOT_A_SEPARATOR);
requestHideSelf(0);
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
@@ -1938,7 +1923,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
@UsedForTesting
boolean isShowingPunctuationList() {
if (mSuggestionStripView == null) return false;
- return mCurrentSettings.mSuggestPuncList == mSuggestionStripView.getSuggestions();
+ return mSettings.getCurrent().mSuggestPuncList == mSuggestionStripView.getSuggestions();
}
private boolean isSuggestionsStripVisible() {
@@ -1946,11 +1931,11 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
return false;
if (mSuggestionStripView.isShowingAddToDictionaryHint())
return true;
- if (!mCurrentSettings.isSuggestionStripVisibleInOrientation(mDisplayOrientation))
+ if (!mSettings.getCurrent().isSuggestionStripVisibleInOrientation(mDisplayOrientation))
return false;
- if (mCurrentSettings.isApplicationSpecifiedCompletionsOn())
+ if (mSettings.getCurrent().isApplicationSpecifiedCompletionsOn())
return true;
- return mCurrentSettings.isSuggestionsRequested(mDisplayOrientation);
+ return mSettings.getCurrent().isSuggestionsRequested(mDisplayOrientation);
}
private void clearSuggestionStrip() {
@@ -1984,16 +1969,16 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
mHandler.cancelUpdateSuggestionStrip();
// Check if we have a suggestion engine attached.
- if (mSuggest == null || !mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
+ if (mSuggest == null
+ || !mSettings.getCurrent().isSuggestionsRequested(mDisplayOrientation)) {
if (mWordComposer.isComposingWord()) {
Log.w(TAG, "Called updateSuggestionsOrPredictions but suggestions were not "
+ "requested!");
- mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
}
return;
}
- if (!mWordComposer.isComposingWord() && !mCurrentSettings.mBigramPredictionEnabled) {
+ if (!mWordComposer.isComposingWord() && !mSettings.getCurrent().mBigramPredictionEnabled) {
setPunctuationSuggestions();
return;
}
@@ -2014,10 +1999,10 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// should just skip whitespace if any, so 1.
// TODO: this is slow (2-way IPC) - we should probably cache this instead.
final String prevWord =
- mConnection.getNthPreviousWord(mCurrentSettings.mWordSeparators,
+ mConnection.getNthPreviousWord(mSettings.getCurrent().mWordSeparators,
mWordComposer.isComposingWord() ? 2 : 1);
final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
- prevWord, keyboard.getProximityInfo(), mCurrentSettings.mCorrectionEnabled,
+ prevWord, keyboard.getProximityInfo(), mSettings.getCurrent().mCorrectionEnabled,
sessionId);
return maybeRetrieveOlderSuggestions(typedWord, suggestedWords);
}
@@ -2042,7 +2027,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
private SuggestedWords getOlderSuggestions(final String typedWord) {
SuggestedWords previousSuggestions = mSuggestionStripView.getSuggestions();
- if (previousSuggestions == mCurrentSettings.mSuggestPuncList) {
+ if (previousSuggestions == mSettings.getCurrent().mSuggestPuncList) {
previousSuggestions = SuggestedWords.EMPTY;
}
if (typedWord == null) {
@@ -2091,8 +2076,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
+ "is empty? Impossible! I must commit suicide.");
}
if (ProductionFlag.IS_INTERNAL) {
- Stats.onAutoCorrection(
- typedWord, autoCorrection.toString(), separatorString, mWordComposer);
+ Stats.onAutoCorrection(typedWord, autoCorrection, separatorString, mWordComposer);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIme_commitCurrentAutoCorrection(typedWord, autoCorrection,
@@ -2124,7 +2108,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
if (suggestion.length() == 1 && isShowingPunctuationList()) {
// Word separators are suggested before the user inputs something.
// So, LatinImeLogger logs "" as a user's input.
- LatinImeLogger.logOnManualSuggestion("", suggestion.toString(), index, suggestedWords);
+ LatinImeLogger.logOnManualSuggestion("", suggestion, index, suggestedWords);
// Rely on onCodeInput to do the complicated swapping/stripping logic consistently.
final int primaryCode = suggestion.charAt(0);
onCodeInput(primaryCode,
@@ -2141,13 +2125,13 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// the current batch input text and there is no need for a phantom space.
&& !mWordComposer.isBatchMode()) {
int firstChar = Character.codePointAt(suggestion, 0);
- if ((!mCurrentSettings.isWeakSpaceStripper(firstChar))
- && (!mCurrentSettings.isWeakSpaceSwapper(firstChar))) {
+ if ((!mSettings.getCurrent().isWeakSpaceStripper(firstChar))
+ && (!mSettings.getCurrent().isWeakSpaceSwapper(firstChar))) {
promotePhantomSpace();
}
}
- if (mCurrentSettings.isApplicationSpecifiedCompletionsOn()
+ if (mSettings.getCurrent().isApplicationSpecifiedCompletionsOn()
&& mApplicationSpecifiedCompletions != null
&& index >= 0 && index < mApplicationSpecifiedCompletions.length) {
if (mSuggestionStripView != null) {
@@ -2163,9 +2147,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// We need to log before we commit, because the word composer will store away the user
// typed word.
- final String replacedWord = mWordComposer.getTypedWord().toString();
- LatinImeLogger.logOnManualSuggestion(replacedWord,
- suggestion.toString(), index, suggestedWords);
+ final String replacedWord = mWordComposer.getTypedWord();
+ LatinImeLogger.logOnManualSuggestion(replacedWord, suggestion, index, suggestedWords);
mExpectingUpdateSelection = true;
commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK,
LastComposedWord.NOT_A_SEPARATOR);
@@ -2193,7 +2176,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
}
if (showingAddToDictionaryHint && mIsUserDictionaryAvailable) {
mSuggestionStripView.showAddToDictionaryHint(
- suggestion, mCurrentSettings.mHintToSaveText);
+ suggestion, mSettings.getCurrent().mHintToSaveText);
} else {
// If we're not showing the "Touch again to save", then update the suggestion strip.
mHandler.postUpdateSuggestionStrip();
@@ -2214,15 +2197,15 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// what user typed. Note: currently this is done much later in
// LastComposedWord#didCommitTypedWord by string equality of the remembered
// strings.
- mLastComposedWord = mWordComposer.commitWord(commitType, chosenWord.toString(),
- separatorString, prevWord);
+ mLastComposedWord = mWordComposer.commitWord(commitType, chosenWord, separatorString,
+ prevWord);
}
private void setPunctuationSuggestions() {
- if (mCurrentSettings.mBigramPredictionEnabled) {
+ if (mSettings.getCurrent().mBigramPredictionEnabled) {
clearSuggestionStrip();
} else {
- setSuggestionStrip(mCurrentSettings.mSuggestPuncList, false);
+ setSuggestionStrip(mSettings.getCurrent().mSuggestPuncList, false);
}
setAutoCorrectionIndicator(false);
setSuggestionStripShown(isSuggestionsStripVisible());
@@ -2235,12 +2218,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// If correction is not enabled, we don't add words to the user history dictionary.
// That's to avoid unintended additions in some sensitive fields, or fields that
// expect to receive non-words.
- if (!mCurrentSettings.mCorrectionEnabled) return null;
+ if (!mSettings.getCurrent().mCorrectionEnabled) return null;
final UserHistoryDictionary userHistoryDictionary = mUserHistoryDictionary;
if (userHistoryDictionary != null) {
- final CharSequence prevWord
- = mConnection.getNthPreviousWord(mCurrentSettings.mWordSeparators, 2);
+ final String prevWord
+ = mConnection.getNthPreviousWord(mSettings.getCurrent().mWordSeparators, 2);
final String secondWord;
if (mWordComposer.wasAutoCapitalized() && !mWordComposer.isMostlyCaps()) {
secondWord = suggestion.toLowerCase(mSubtypeSwitcher.getCurrentSubtypeLocale());
@@ -2252,9 +2235,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
final int maxFreq = AutoCorrection.getMaxFrequency(
mSuggest.getUnigramDictionaries(), suggestion);
if (maxFreq == 0) return null;
- final String prevWordString = (null == prevWord) ? null : prevWord.toString();
- userHistoryDictionary.addToUserHistory(prevWordString, secondWord, maxFreq > 0);
- return prevWordString;
+ userHistoryDictionary.addToUserHistory(prevWord, secondWord, maxFreq > 0);
+ return prevWord;
}
return null;
}
@@ -2264,7 +2246,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
* word, else do nothing.
*/
private void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() {
- final CharSequence word = mConnection.getWordBeforeCursorIfAtEndOfWord(mCurrentSettings);
+ final CharSequence word =
+ mConnection.getWordBeforeCursorIfAtEndOfWord(mSettings.getCurrent());
if (null != word) {
restartSuggestionsOnWordBeforeCursor(word);
}
@@ -2302,8 +2285,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
}
mConnection.deleteSurroundingText(deleteLength, 0);
if (!TextUtils.isEmpty(previousWord) && !TextUtils.isEmpty(committedWord)) {
- mUserHistoryDictionary.cancelAddingUserHistory(
- previousWord.toString(), committedWord.toString());
+ mUserHistoryDictionary.cancelAddingUserHistory(previousWord, committedWord);
}
mConnection.commitText(originallyTypedWord + mLastComposedWord.mSeparatorString, 1);
if (ProductionFlag.IS_INTERNAL) {
@@ -2311,7 +2293,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_revertCommit(originallyTypedWord);
+ ResearchLogger.latinIME_revertCommit(committedWord, originallyTypedWord);
+ ResearchLogger.getInstance().onWordComplete(originallyTypedWord, Long.MAX_VALUE);
}
// Don't restart suggestion yet. We'll restart if the user deletes the
// separator.
@@ -2322,14 +2305,14 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// This essentially inserts a space, and that's it.
public void promotePhantomSpace() {
- if (mCurrentSettings.shouldInsertSpacesAutomatically()) {
+ if (mSettings.getCurrent().shouldInsertSpacesAutomatically()) {
sendKeyCodePoint(Constants.CODE_SPACE);
}
}
// Used by the RingCharBuffer
public boolean isWordSeparator(final int code) {
- return mCurrentSettings.isWordSeparator(code);
+ return mSettings.getCurrent().isWordSeparator(code);
}
// TODO: Make this private
@@ -2342,7 +2325,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
loadSettings();
if (mKeyboardSwitcher.getMainKeyboardView() != null) {
// Reload keyboard because the current language has been changed.
- mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mCurrentSettings);
+ mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettings.getCurrent());
}
// Since we just changed languages, we should re-evaluate suggestions with whatever word
// we are currently composing. If we are not composing anything, we may want to display
@@ -2399,7 +2382,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
@Override
public boolean onKeyUp(final int keyCode, final KeyEvent event) {
- if (mEventInterpreter.onHardwareKeyEvent(event)) return true;
return super.onKeyUp(keyCode, event);
}
@@ -2504,7 +2486,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
.append("\nPackage : ").append(mTargetApplicationInfo.packageName)
.append("\nTarget app sdk version : ")
.append(mTargetApplicationInfo.targetSdkVersion)
- .append("\nAttributes : ").append(mCurrentSettings.getInputAttributesDebugString())
+ .append("\nAttributes : ").append(mSettings.getCurrent().mInputAttributes)
.append("\nContext : ").append(context);
throw new RuntimeException(s.toString());
}
@@ -2518,13 +2500,14 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
final int keyboardMode = keyboard != null ? keyboard.mId.mMode : -1;
p.println(" Keyboard mode = " + keyboardMode);
+ final SettingsValues settingsValues = mSettings.getCurrent();
p.println(" mIsSuggestionsSuggestionsRequested = "
- + mCurrentSettings.isSuggestionsRequested(mDisplayOrientation));
- p.println(" mCorrectionEnabled=" + mCurrentSettings.mCorrectionEnabled);
+ + settingsValues.isSuggestionsRequested(mDisplayOrientation));
+ p.println(" mCorrectionEnabled=" + settingsValues.mCorrectionEnabled);
p.println(" isComposingWord=" + mWordComposer.isComposingWord());
- p.println(" mSoundOn=" + mCurrentSettings.mSoundOn);
- p.println(" mVibrateOn=" + mCurrentSettings.mVibrateOn);
- p.println(" mKeyPreviewPopupOn=" + mCurrentSettings.mKeyPreviewPopupOn);
- p.println(" inputAttributes=" + mCurrentSettings.getInputAttributesDebugString());
+ p.println(" mSoundOn=" + settingsValues.mSoundOn);
+ p.println(" mVibrateOn=" + settingsValues.mVibrateOn);
+ p.println(" mKeyPreviewPopupOn=" + settingsValues.mKeyPreviewPopupOn);
+ p.println(" inputAttributes=" + settingsValues.mInputAttributes);
}
}
diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
index 394a9c7aa..e4e8b94b2 100644
--- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java
+++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
@@ -31,7 +31,7 @@ public final class LatinImeLogger implements SharedPreferences.OnSharedPreferenc
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
}
- public static void init(LatinIME context, SharedPreferences prefs) {
+ public static void init(LatinIME context) {
}
public static void commit() {
diff --git a/java/src/com/android/inputmethod/latin/PositionalInfoForUserDictPendingAddition.java b/java/src/com/android/inputmethod/latin/PositionalInfoForUserDictPendingAddition.java
index 8a2d22256..1fd25636c 100644
--- a/java/src/com/android/inputmethod/latin/PositionalInfoForUserDictPendingAddition.java
+++ b/java/src/com/android/inputmethod/latin/PositionalInfoForUserDictPendingAddition.java
@@ -29,7 +29,7 @@ import android.view.inputmethod.EditorInfo;
* the IME needs to take a note of what it has to replace and where it is.
* This class encapsulates this data.
*/
-public class PositionalInfoForUserDictPendingAddition {
+public final class PositionalInfoForUserDictPendingAddition {
final private String mOriginalWord;
final private int mCursorPos; // Position of the cursor after the word
final private EditorInfo mEditorInfo; // On what binding this has been added
diff --git a/java/src/com/android/inputmethod/latin/ResourceUtils.java b/java/src/com/android/inputmethod/latin/ResourceUtils.java
index 5021ad384..b74b979b5 100644
--- a/java/src/com/android/inputmethod/latin/ResourceUtils.java
+++ b/java/src/com/android/inputmethod/latin/ResourceUtils.java
@@ -19,11 +19,15 @@ package com.android.inputmethod.latin;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.Build;
+import android.util.Log;
import android.util.TypedValue;
import java.util.HashMap;
public final class ResourceUtils {
+ private static final String TAG = ResourceUtils.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
public static final float UNDEFINED_RATIO = -1.0f;
public static final int UNDEFINED_DIMENSION = -1;
@@ -31,24 +35,44 @@ public final class ResourceUtils {
// This utility class is not publicly instantiable.
}
+ private static final String DEFAULT_PREFIX = "DEFAULT,";
private static final String HARDWARE_PREFIX = Build.HARDWARE + ",";
private static final HashMap<String, String> sDeviceOverrideValueMap =
CollectionUtils.newHashMap();
- public static String getDeviceOverrideValue(Resources res, int overrideResId, String defValue) {
+ public static String getDeviceOverrideValue(final Resources res, final int overrideResId) {
final int orientation = res.getConfiguration().orientation;
final String key = overrideResId + "-" + orientation;
- if (!sDeviceOverrideValueMap.containsKey(key)) {
- String overrideValue = defValue;
- for (final String element : res.getStringArray(overrideResId)) {
- if (element.startsWith(HARDWARE_PREFIX)) {
- overrideValue = element.substring(HARDWARE_PREFIX.length());
- break;
- }
+ if (sDeviceOverrideValueMap.containsKey(key)) {
+ return sDeviceOverrideValueMap.get(key);
+ }
+
+ final String[] overrideArray = res.getStringArray(overrideResId);
+ final String overrideValue = StringUtils.findPrefixedString(HARDWARE_PREFIX, overrideArray);
+ // The overrideValue might be an empty string.
+ if (overrideValue != null) {
+ if (DEBUG) {
+ Log.d(TAG, "Find override value:"
+ + " resource="+ res.getResourceEntryName(overrideResId)
+ + " Build.HARDWARE=" + Build.HARDWARE + " override=" + overrideValue);
}
sDeviceOverrideValueMap.put(key, overrideValue);
+ return overrideValue;
+ }
+
+ final String defaultValue = StringUtils.findPrefixedString(DEFAULT_PREFIX, overrideArray);
+ // The defaultValue might be an empty string.
+ if (defaultValue == null) {
+ Log.w(TAG, "Couldn't find override value nor default value:"
+ + " resource="+ res.getResourceEntryName(overrideResId)
+ + " Build.HARDWARE=" + Build.HARDWARE);
+ } else if (DEBUG) {
+ Log.d(TAG, "Found default value:"
+ + " resource="+ res.getResourceEntryName(overrideResId)
+ + " Build.HARDWARE=" + Build.HARDWARE + " default=" + defaultValue);
}
- return sDeviceOverrideValueMap.get(key);
+ sDeviceOverrideValueMap.put(key, defaultValue);
+ return defaultValue;
}
public static boolean isValidFraction(final float fraction) {
@@ -85,8 +109,8 @@ public final class ResourceUtils {
return a.getDimensionPixelSize(index, ResourceUtils.UNDEFINED_DIMENSION);
}
- public static float getDimensionOrFraction(TypedArray a, int index, int base,
- float defValue) {
+ public static float getDimensionOrFraction(final TypedArray a, final int index, final int base,
+ final float defValue) {
final TypedValue value = a.peekValue(index);
if (value == null) {
return defValue;
@@ -99,7 +123,7 @@ public final class ResourceUtils {
return defValue;
}
- public static int getEnumValue(TypedArray a, int index, int defValue) {
+ public static int getEnumValue(final TypedArray a, final int index, final int defValue) {
final TypedValue value = a.peekValue(index);
if (value == null) {
return defValue;
@@ -110,19 +134,19 @@ public final class ResourceUtils {
return defValue;
}
- public static boolean isFractionValue(TypedValue v) {
+ public static boolean isFractionValue(final TypedValue v) {
return v.type == TypedValue.TYPE_FRACTION;
}
- public static boolean isDimensionValue(TypedValue v) {
+ public static boolean isDimensionValue(final TypedValue v) {
return v.type == TypedValue.TYPE_DIMENSION;
}
- public static boolean isIntegerValue(TypedValue v) {
+ public static boolean isIntegerValue(final TypedValue v) {
return v.type >= TypedValue.TYPE_FIRST_INT && v.type <= TypedValue.TYPE_LAST_INT;
}
- public static boolean isStringValue(TypedValue v) {
+ public static boolean isStringValue(final TypedValue v) {
return v.type == TypedValue.TYPE_STRING;
}
}
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index e9c81dab0..9cb24b54e 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -178,9 +178,6 @@ public final class RichInputConnection {
mComposingText.setLength(0);
if (null != mIC) {
mIC.commitText(text, i);
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.richInputConnection_commitText(text, i);
- }
}
}
@@ -287,40 +284,40 @@ public final class RichInputConnection {
if (DEBUG_BATCH_NESTING) checkBatchEdit();
if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
- // This method is only called for enter or backspace when speaking to old
- // applications (target SDK <= 15), or for digits.
+ // This method is only called for enter or backspace when speaking to old applications
+ // (target SDK <= 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)), or for digits.
// When talking to new applications we never use this method because it's inherently
// racy and has unpredictable results, but for backward compatibility we continue
// sending the key events for only Enter and Backspace because some applications
// mistakenly catch them to do some stuff.
switch (keyEvent.getKeyCode()) {
- case KeyEvent.KEYCODE_ENTER:
- mCommittedTextBeforeComposingText.append("\n");
- mCurrentCursorPosition += 1;
- break;
- case KeyEvent.KEYCODE_DEL:
- if (0 == mComposingText.length()) {
- if (mCommittedTextBeforeComposingText.length() > 0) {
- mCommittedTextBeforeComposingText.delete(
- mCommittedTextBeforeComposingText.length() - 1,
- mCommittedTextBeforeComposingText.length());
- }
- } else {
- mComposingText.delete(mComposingText.length() - 1, mComposingText.length());
- }
- if (mCurrentCursorPosition > 0) mCurrentCursorPosition -= 1;
- break;
- case KeyEvent.KEYCODE_UNKNOWN:
- if (null != keyEvent.getCharacters()) {
- mCommittedTextBeforeComposingText.append(keyEvent.getCharacters());
- mCurrentCursorPosition += keyEvent.getCharacters().length();
+ case KeyEvent.KEYCODE_ENTER:
+ mCommittedTextBeforeComposingText.append("\n");
+ mCurrentCursorPosition += 1;
+ break;
+ case KeyEvent.KEYCODE_DEL:
+ if (0 == mComposingText.length()) {
+ if (mCommittedTextBeforeComposingText.length() > 0) {
+ mCommittedTextBeforeComposingText.delete(
+ mCommittedTextBeforeComposingText.length() - 1,
+ mCommittedTextBeforeComposingText.length());
}
- break;
- default:
- final String text = new String(new int[] { keyEvent.getUnicodeChar() }, 0, 1);
- mCommittedTextBeforeComposingText.append(text);
- mCurrentCursorPosition += text.length();
- break;
+ } else {
+ mComposingText.delete(mComposingText.length() - 1, mComposingText.length());
+ }
+ if (mCurrentCursorPosition > 0) mCurrentCursorPosition -= 1;
+ break;
+ case KeyEvent.KEYCODE_UNKNOWN:
+ if (null != keyEvent.getCharacters()) {
+ mCommittedTextBeforeComposingText.append(keyEvent.getCharacters());
+ mCurrentCursorPosition += keyEvent.getCharacters().length();
+ }
+ break;
+ default:
+ final String text = new String(new int[] { keyEvent.getUnicodeChar() }, 0, 1);
+ mCommittedTextBeforeComposingText.append(text);
+ mCurrentCursorPosition += text.length();
+ break;
}
}
if (null != mIC) {
@@ -537,17 +534,17 @@ public final class RichInputConnection {
// Going backward, alternate skipping non-separators and separators until enough words
// have been read.
int count = additionalPrecedingWordsCount;
- int start = before.length();
+ int startIndexInBefore = before.length();
boolean isStoppingAtWhitespace = true; // toggles to indicate what to stop at
while (true) { // see comments below for why this is guaranteed to halt
- while (start > 0) {
- final int codePoint = Character.codePointBefore(before, start);
+ while (startIndexInBefore > 0) {
+ final int codePoint = Character.codePointBefore(before, startIndexInBefore);
if (isStoppingAtWhitespace == isSeparator(codePoint, sep)) {
break; // inner loop
}
- --start;
+ --startIndexInBefore;
if (Character.isSupplementaryCodePoint(codePoint)) {
- --start;
+ --startIndexInBefore;
}
}
// isStoppingAtWhitespace is true every other time through the loop,
@@ -560,25 +557,20 @@ public final class RichInputConnection {
}
// Find last word separator after the cursor
- int end = -1;
- while (++end < after.length()) {
- final int codePoint = Character.codePointAt(after, end);
+ int endIndexInAfter = -1;
+ while (++endIndexInAfter < after.length()) {
+ final int codePoint = Character.codePointAt(after, endIndexInAfter);
if (isSeparator(codePoint, sep)) {
break;
}
if (Character.isSupplementaryCodePoint(codePoint)) {
- ++end;
+ ++endIndexInAfter;
}
}
- final int cursor = getCursorPosition();
- if (start >= 0 && cursor + end <= after.length() + before.length()) {
- String word = before.toString().substring(start, before.length())
- + after.toString().substring(0, end);
- return new Range(before.length() - start, end, word);
- }
-
- return null;
+ final String word = before.toString().substring(startIndexInBefore, before.length())
+ + after.toString().substring(0, endIndexInAfter);
+ return new Range(before.length() - startIndexInBefore, endIndexInAfter, word);
}
public boolean isCursorTouchingWord(final SettingsValues settingsValues) {
@@ -665,7 +657,11 @@ public final class RichInputConnection {
return false;
}
deleteSurroundingText(2, 0);
- commitText(" ", 1);
+ final String doubleSpace = " ";
+ commitText(doubleSpace, 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().onWordComplete(doubleSpace, Long.MAX_VALUE);
+ }
return true;
}
@@ -686,7 +682,11 @@ public final class RichInputConnection {
return false;
}
deleteSurroundingText(2, 0);
- commitText(" " + textBeforeCursor.subSequence(0, 1), 1);
+ final String text = " " + textBeforeCursor.subSequence(0, 1);
+ commitText(text, 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().onWordComplete(text, Long.MAX_VALUE);
+ }
return true;
}
diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
index af0d61cc7..637916f76 100644
--- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
+++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
@@ -21,6 +21,7 @@ import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.IBinder;
+import android.preference.PreferenceManager;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
@@ -50,7 +51,8 @@ public final class RichInputMethodManager {
return sInstance;
}
- public static void init(final Context context, final SharedPreferences prefs) {
+ public static void init(final Context context) {
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
sInstance.initInternal(context, prefs);
}
diff --git a/java/src/com/android/inputmethod/latin/SeekBarDialog.java b/java/src/com/android/inputmethod/latin/SeekBarDialog.java
new file mode 100644
index 000000000..e576c0984
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/SeekBarDialog.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2012 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.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+
+public final class SeekBarDialog implements DialogInterface.OnClickListener,
+ OnSeekBarChangeListener {
+ public interface Listener {
+ public void onPositiveButtonClick(final SeekBarDialog dialog);
+ public void onNegativeButtonClick(final SeekBarDialog dialog);
+ public void onProgressChanged(final SeekBarDialog dialog);
+ public void onStartTrackingTouch(final SeekBarDialog dialog);
+ public void onStopTrackingTouch(final SeekBarDialog dialog);
+ }
+
+ public static class Adapter implements Listener {
+ @Override
+ public void onPositiveButtonClick(final SeekBarDialog dialog) {}
+ @Override
+ public void onNegativeButtonClick(final SeekBarDialog dialog) { dialog.dismiss(); }
+ @Override
+ public void onProgressChanged(final SeekBarDialog dialog) {}
+ @Override
+ public void onStartTrackingTouch(final SeekBarDialog dialog) {}
+ @Override
+ public void onStopTrackingTouch(final SeekBarDialog dialog) {}
+ }
+
+ private static final Listener EMPTY_ADAPTER = new Adapter();
+
+ private final AlertDialog mDialog;
+ private final Listener mListener;
+ private final TextView mValueView;
+ private final SeekBar mSeekBar;
+ private final String mValueFormat;
+
+ private int mValue;
+
+ private SeekBarDialog(final Builder builder) {
+ final AlertDialog.Builder dialogBuilder = builder.mDialogBuilder;
+ dialogBuilder.setView(builder.mView);
+ dialogBuilder.setPositiveButton(android.R.string.ok, this);
+ dialogBuilder.setNegativeButton(android.R.string.cancel, this);
+ mDialog = dialogBuilder.create();
+ mListener = (builder.mListener == null) ? EMPTY_ADAPTER : builder.mListener;
+ mValueView = (TextView)builder.mView.findViewById(R.id.seek_bar_dialog_value);
+ mSeekBar = (SeekBar)builder.mView.findViewById(R.id.seek_bar_dialog_bar);
+ mSeekBar.setMax(builder.mMaxValue);
+ mSeekBar.setOnSeekBarChangeListener(this);
+ if (builder.mValueFormatResId == 0) {
+ mValueFormat = "%s";
+ } else {
+ mValueFormat = mDialog.getContext().getString(builder.mValueFormatResId);
+ }
+ }
+
+ public void setValue(final int value, final boolean fromUser) {
+ mValue = value;
+ mValueView.setText(String.format(mValueFormat, value));
+ if (!fromUser) {
+ mSeekBar.setProgress(value);
+ }
+ }
+
+ public int getValue() {
+ return mValue;
+ }
+
+ public CharSequence getValueText() {
+ return mValueView.getText();
+ }
+
+ public void show() {
+ mDialog.show();
+ }
+
+ public void dismiss() {
+ mDialog.dismiss();
+ }
+
+ @Override
+ public void onClick(final DialogInterface dialog, int which) {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ mListener.onPositiveButtonClick(this);
+ return;
+ }
+ if (which == DialogInterface.BUTTON_NEGATIVE) {
+ mListener.onNegativeButtonClick(this);
+ return;
+ }
+ }
+
+ @Override
+ public void onProgressChanged(final SeekBar seekBar, final int progress,
+ final boolean fromUser) {
+ setValue(progress, fromUser);
+ if (fromUser) {
+ mListener.onProgressChanged(this);
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(final SeekBar seekBar) {
+ mListener.onStartTrackingTouch(this);
+ }
+
+ @Override
+ public void onStopTrackingTouch(final SeekBar seekBar) {
+ mListener.onStopTrackingTouch(this);
+ }
+
+ public static final class Builder {
+ final AlertDialog.Builder mDialogBuilder;
+ final View mView;
+
+ int mMaxValue;
+ int mValueFormatResId;
+ int mValue;
+ Listener mListener;
+
+ public Builder(final Context context) {
+ mDialogBuilder = new AlertDialog.Builder(context);
+ mView = LayoutInflater.from(context).inflate(R.layout.seek_bar_dialog, null);
+ }
+
+ public Builder setTitle(final int resId) {
+ mDialogBuilder.setTitle(resId);
+ return this;
+ }
+
+ public Builder setMaxValue(final int max) {
+ mMaxValue = max;
+ return this;
+ }
+
+ public Builder setValueFromat(final int resId) {
+ mValueFormatResId = resId;
+ return this;
+ }
+
+ public Builder setValue(final int value) {
+ mValue = value;
+ return this;
+ }
+
+ public Builder setListener(final Listener listener) {
+ mListener = listener;
+ return this;
+ }
+
+ public SeekBarDialog create() {
+ final SeekBarDialog dialog = new SeekBarDialog(this);
+ dialog.setValue(mValue, false /* fromUser */);
+ return dialog;
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 7a73cade3..1d9d85b47 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2013 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
@@ -16,34 +16,16 @@
package com.android.inputmethod.latin;
-import android.app.AlertDialog;
-import android.app.backup.BackupManager;
import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
-import android.media.AudioManager;
-import android.os.Bundle;
-import android.preference.CheckBoxPreference;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceGroup;
-import android.preference.PreferenceScreen;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.inputmethod.InputMethodSubtype;
-import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
-import android.widget.TextView;
+import android.preference.PreferenceManager;
-import com.android.inputmethod.latin.define.ProductionFlag;
-import com.android.inputmethodcommon.InputMethodSettingsFragment;
+import com.android.inputmethod.latin.LocaleUtils.RunInLocale;
-public final class Settings extends InputMethodSettingsFragment
- implements SharedPreferences.OnSharedPreferenceChangeListener {
+import java.util.Locale;
+public final class Settings implements SharedPreferences.OnSharedPreferenceChangeListener {
// In the same order as xml/prefs.xml
public static final String PREF_GENERAL_SETTINGS = "general_settings";
public static final String PREF_AUTO_CAP = "auto_cap";
@@ -84,387 +66,54 @@ public final class Settings extends InputMethodSettingsFragment
public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
public static final String PREF_DEBUG_SETTINGS = "debug_settings";
- private PreferenceScreen mKeypressVibrationDurationSettingsPref;
- private PreferenceScreen mKeypressSoundVolumeSettingsPref;
- private ListPreference mVoicePreference;
- private ListPreference mShowCorrectionSuggestionsPreference;
- private ListPreference mAutoCorrectionThresholdPreference;
- private ListPreference mKeyPreviewPopupDismissDelay;
- // Use bigrams to predict the next word when there is no input for it yet
- private CheckBoxPreference mBigramPrediction;
- private Preference mDebugSettingsPreference;
+ private Resources mRes;
+ private SharedPreferences mPrefs;
+ private Locale mCurrentLocale;
+ private SettingsValues mSettingsValues;
- private TextView mKeypressVibrationDurationSettingsTextView;
- private TextView mKeypressSoundVolumeSettingsTextView;
+ private static final Settings sInstance = new Settings();
- private static void setPreferenceEnabled(final Preference preference, final boolean enabled) {
- if (preference != null) {
- preference.setEnabled(enabled);
- }
+ public static Settings getInstance() {
+ return sInstance;
}
- private void ensureConsistencyOfAutoCorrectionSettings() {
- final String autoCorrectionOff = getResources().getString(
- R.string.auto_correction_threshold_mode_index_off);
- final String currentSetting = mAutoCorrectionThresholdPreference.getValue();
- setPreferenceEnabled(mBigramPrediction, !currentSetting.equals(autoCorrectionOff));
+ public static void init(final Context context) {
+ sInstance.onCreate(context);
}
- @Override
- public void onCreate(final Bundle icicle) {
- super.onCreate(icicle);
- setInputMethodSettingsCategoryTitle(R.string.language_selection_title);
- setSubtypeEnablerTitle(R.string.select_language);
- addPreferencesFromResource(R.xml.prefs);
-
- final Resources res = getResources();
- final Context context = getActivity();
-
- // When we are called from the Settings application but we are not already running, the
- // {@link SubtypeLocale} class may not have been initialized. It is safe to call
- // {@link SubtypeLocale#init(Context)} multiple times.
- SubtypeLocale.init(context);
- mVoicePreference = (ListPreference) findPreference(PREF_VOICE_MODE);
- mShowCorrectionSuggestionsPreference =
- (ListPreference) findPreference(PREF_SHOW_SUGGESTIONS_SETTING);
- SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
- prefs.registerOnSharedPreferenceChangeListener(this);
-
- mAutoCorrectionThresholdPreference =
- (ListPreference) findPreference(PREF_AUTO_CORRECTION_THRESHOLD);
- mBigramPrediction = (CheckBoxPreference) findPreference(PREF_BIGRAM_PREDICTIONS);
- ensureConsistencyOfAutoCorrectionSettings();
-
- final PreferenceGroup generalSettings =
- (PreferenceGroup) findPreference(PREF_GENERAL_SETTINGS);
- final PreferenceGroup textCorrectionGroup =
- (PreferenceGroup) findPreference(PREF_CORRECTION_SETTINGS);
- final PreferenceGroup gestureTypingSettings =
- (PreferenceGroup) findPreference(PREF_GESTURE_SETTINGS);
- final PreferenceGroup miscSettings =
- (PreferenceGroup) findPreference(PREF_MISC_SETTINGS);
-
- mDebugSettingsPreference = findPreference(PREF_DEBUG_SETTINGS);
- if (mDebugSettingsPreference != null) {
- if (ProductionFlag.IS_INTERNAL) {
- final Intent debugSettingsIntent = new Intent(Intent.ACTION_MAIN);
- debugSettingsIntent.setClassName(
- context.getPackageName(), DebugSettingsActivity.class.getName());
- mDebugSettingsPreference.setIntent(debugSettingsIntent);
- } else {
- miscSettings.removePreference(mDebugSettingsPreference);
- }
- }
-
- final boolean showVoiceKeyOption = res.getBoolean(
- R.bool.config_enable_show_voice_key_option);
- if (!showVoiceKeyOption) {
- generalSettings.removePreference(mVoicePreference);
- }
-
- final PreferenceGroup advancedSettings =
- (PreferenceGroup) findPreference(PREF_ADVANCED_SETTINGS);
- if (!VibratorUtils.getInstance(context).hasVibrator()) {
- generalSettings.removePreference(findPreference(PREF_VIBRATE_ON));
- if (null != advancedSettings) { // Theoretically advancedSettings cannot be null
- advancedSettings.removePreference(findPreference(PREF_VIBRATION_DURATION_SETTINGS));
- }
- }
-
- final boolean showKeyPreviewPopupOption = res.getBoolean(
- R.bool.config_enable_show_popup_on_keypress_option);
- mKeyPreviewPopupDismissDelay =
- (ListPreference) findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
- if (!showKeyPreviewPopupOption) {
- generalSettings.removePreference(findPreference(PREF_POPUP_ON));
- if (null != advancedSettings) { // Theoretically advancedSettings cannot be null
- advancedSettings.removePreference(mKeyPreviewPopupDismissDelay);
- }
- } else {
- final String[] entries = new String[] {
- res.getString(R.string.key_preview_popup_dismiss_no_delay),
- res.getString(R.string.key_preview_popup_dismiss_default_delay),
- };
- final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger(
- R.integer.config_key_preview_linger_timeout));
- mKeyPreviewPopupDismissDelay.setEntries(entries);
- mKeyPreviewPopupDismissDelay.setEntryValues(
- new String[] { "0", popupDismissDelayDefaultValue });
- if (null == mKeyPreviewPopupDismissDelay.getValue()) {
- mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
- }
- setPreferenceEnabled(mKeyPreviewPopupDismissDelay,
- SettingsValues.isKeyPreviewPopupEnabled(prefs, res));
- }
-
- setPreferenceEnabled(findPreference(PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST),
- SettingsValues.showsLanguageSwitchKey(prefs));
-
- final PreferenceScreen dictionaryLink =
- (PreferenceScreen) findPreference(PREF_CONFIGURE_DICTIONARIES_KEY);
- final Intent intent = dictionaryLink.getIntent();
-
- final int number = context.getPackageManager().queryIntentActivities(intent, 0).size();
- // TODO: The experimental version is not supported by the Dictionary Pack Service yet
- if (ProductionFlag.IS_EXPERIMENTAL || 0 >= number) {
- textCorrectionGroup.removePreference(dictionaryLink);
- }
-
- final boolean gestureInputEnabledByBuildConfig = res.getBoolean(
- R.bool.config_gesture_input_enabled_by_build_config);
- if (!gestureInputEnabledByBuildConfig) {
- getPreferenceScreen().removePreference(gestureTypingSettings);
- }
-
- mKeypressVibrationDurationSettingsPref =
- (PreferenceScreen) findPreference(PREF_VIBRATION_DURATION_SETTINGS);
- if (mKeypressVibrationDurationSettingsPref != null) {
- mKeypressVibrationDurationSettingsPref.setOnPreferenceClickListener(
- new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference arg0) {
- showKeypressVibrationDurationSettingsDialog();
- return true;
- }
- });
- updateKeypressVibrationDurationSettingsSummary(prefs, res);
- }
-
- mKeypressSoundVolumeSettingsPref =
- (PreferenceScreen) findPreference(PREF_KEYPRESS_SOUND_VOLUME);
- if (mKeypressSoundVolumeSettingsPref != null) {
- mKeypressSoundVolumeSettingsPref.setOnPreferenceClickListener(
- new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference arg0) {
- showKeypressSoundVolumeSettingDialog();
- return true;
- }
- });
- updateKeypressSoundVolumeSummary(prefs, res);
- }
- refreshEnablingsOfKeypressSoundAndVibrationSettings(prefs, res);
+ private Settings() {
+ // Intentional empty constructor for singleton.
}
- @Override
- public void onResume() {
- super.onResume();
- final boolean isShortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled();
- if (isShortcutImeEnabled) {
- updateVoiceModeSummary();
- } else {
- getPreferenceScreen().removePreference(mVoicePreference);
- }
- updateShowCorrectionSuggestionsSummary();
- updateKeyPreviewPopupDelaySummary();
- updateCustomInputStylesSummary();
+ private void onCreate(final Context context) {
+ mRes = context.getResources();
+ mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
+ mPrefs.registerOnSharedPreferenceChangeListener(this);
}
- @Override
public void onDestroy() {
- getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(
- this);
- super.onDestroy();
+ mPrefs.unregisterOnSharedPreferenceChangeListener(this);
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
- (new BackupManager(getActivity())).dataChanged();
- if (key.equals(PREF_POPUP_ON)) {
- setPreferenceEnabled(findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY),
- prefs.getBoolean(PREF_POPUP_ON, true));
- } else if (key.equals(PREF_SHOW_LANGUAGE_SWITCH_KEY)) {
- setPreferenceEnabled(findPreference(PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST),
- SettingsValues.showsLanguageSwitchKey(prefs));
- } else if (key.equals(PREF_GESTURE_INPUT)) {
- final boolean gestureInputEnabledByConfig = getResources().getBoolean(
- R.bool.config_gesture_input_enabled_by_build_config);
- if (gestureInputEnabledByConfig) {
- final boolean gestureInputEnabledByUser = prefs.getBoolean(
- PREF_GESTURE_INPUT, true);
- setPreferenceEnabled(findPreference(PREF_GESTURE_PREVIEW_TRAIL),
- gestureInputEnabledByUser);
- setPreferenceEnabled(findPreference(PREF_GESTURE_FLOATING_PREVIEW_TEXT),
- gestureInputEnabledByUser);
- }
- }
- ensureConsistencyOfAutoCorrectionSettings();
- updateVoiceModeSummary();
- updateShowCorrectionSuggestionsSummary();
- updateKeyPreviewPopupDelaySummary();
- refreshEnablingsOfKeypressSoundAndVibrationSettings(prefs, getResources());
- }
-
- private void updateShowCorrectionSuggestionsSummary() {
- mShowCorrectionSuggestionsPreference.setSummary(
- getResources().getStringArray(R.array.prefs_suggestion_visibilities)
- [mShowCorrectionSuggestionsPreference.findIndexOfValue(
- mShowCorrectionSuggestionsPreference.getValue())]);
- }
-
- private void updateCustomInputStylesSummary() {
- final PreferenceScreen customInputStyles =
- (PreferenceScreen)findPreference(PREF_CUSTOM_INPUT_STYLES);
- final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
- final Resources res = getResources();
- final String prefSubtype = SettingsValues.getPrefAdditionalSubtypes(prefs, res);
- final InputMethodSubtype[] subtypes =
- AdditionalSubtype.createAdditionalSubtypesArray(prefSubtype);
- final StringBuilder styles = new StringBuilder();
- for (final InputMethodSubtype subtype : subtypes) {
- if (styles.length() > 0) styles.append(", ");
- styles.append(SubtypeLocale.getSubtypeDisplayName(subtype, res));
- }
- customInputStyles.setSummary(styles);
- }
-
- private void updateKeyPreviewPopupDelaySummary() {
- final ListPreference lp = mKeyPreviewPopupDismissDelay;
- final CharSequence[] entries = lp.getEntries();
- if (entries == null || entries.length <= 0) return;
- lp.setSummary(entries[lp.findIndexOfValue(lp.getValue())]);
- }
-
- private void updateVoiceModeSummary() {
- mVoicePreference.setSummary(
- getResources().getStringArray(R.array.voice_input_modes_summary)
- [mVoicePreference.findIndexOfValue(mVoicePreference.getValue())]);
+ loadSettings(mCurrentLocale, mSettingsValues.mInputAttributes);
}
- private void refreshEnablingsOfKeypressSoundAndVibrationSettings(
- final SharedPreferences sp, final Resources res) {
- if (mKeypressVibrationDurationSettingsPref != null) {
- final boolean hasVibratorHardware = VibratorUtils.getInstance(getActivity())
- .hasVibrator();
- final boolean vibrateOnByUser = sp.getBoolean(Settings.PREF_VIBRATE_ON,
- res.getBoolean(R.bool.config_default_vibration_enabled));
- setPreferenceEnabled(mKeypressVibrationDurationSettingsPref,
- hasVibratorHardware && vibrateOnByUser);
- }
-
- if (mKeypressSoundVolumeSettingsPref != null) {
- final boolean soundOn = sp.getBoolean(Settings.PREF_SOUND_ON,
- res.getBoolean(R.bool.config_default_sound_enabled));
- setPreferenceEnabled(mKeypressSoundVolumeSettingsPref, soundOn);
- }
- }
-
- private void updateKeypressVibrationDurationSettingsSummary(
- final SharedPreferences sp, final Resources res) {
- if (mKeypressVibrationDurationSettingsPref != null) {
- mKeypressVibrationDurationSettingsPref.setSummary(
- SettingsValues.getCurrentVibrationDuration(sp, res)
- + res.getString(R.string.settings_ms));
- }
- }
-
- private void showKeypressVibrationDurationSettingsDialog() {
- final SharedPreferences sp = getPreferenceManager().getSharedPreferences();
- final Context context = getActivity();
- final Resources res = context.getResources();
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.prefs_keypress_vibration_duration_settings);
- builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int whichButton) {
- final int ms = Integer.valueOf(
- mKeypressVibrationDurationSettingsTextView.getText().toString());
- sp.edit().putInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, ms).apply();
- updateKeypressVibrationDurationSettingsSummary(sp, res);
- }
- });
- builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int whichButton) {
- dialog.dismiss();
- }
- });
- final View v = LayoutInflater.from(context).inflate(
- R.layout.vibration_settings_dialog, null);
- 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);
- sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
- final int tempMs = arg1;
- mKeypressVibrationDurationSettingsTextView.setText(String.valueOf(tempMs));
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar arg0) {
- }
-
+ public void loadSettings(final Locale locale, final InputAttributes inputAttributes) {
+ mCurrentLocale = locale;
+ final SharedPreferences prefs = mPrefs;
+ final RunInLocale<SettingsValues> job = new RunInLocale<SettingsValues>() {
@Override
- public void onStopTrackingTouch(SeekBar arg0) {
- final int tempMs = arg0.getProgress();
- VibratorUtils.getInstance(context).vibrate(tempMs);
+ protected SettingsValues job(final Resources res) {
+ return new SettingsValues(prefs, res, inputAttributes);
}
- });
- sb.setProgress(currentMs);
- mKeypressVibrationDurationSettingsTextView.setText(String.valueOf(currentMs));
- builder.setView(v);
- builder.create().show();
+ };
+ mSettingsValues = job.runInLocale(mRes, locale);
}
- private void updateKeypressSoundVolumeSummary(final SharedPreferences sp, final Resources res) {
- if (mKeypressSoundVolumeSettingsPref != null) {
- mKeypressSoundVolumeSettingsPref.setSummary(String.valueOf(
- (int)(SettingsValues.getCurrentKeypressSoundVolume(sp, res) * 100)));
- }
- }
-
- private void showKeypressSoundVolumeSettingDialog() {
- final Context context = getActivity();
- final AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- final SharedPreferences sp = getPreferenceManager().getSharedPreferences();
- final Resources res = context.getResources();
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.prefs_keypress_sound_volume_settings);
- builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int whichButton) {
- final float volume =
- ((float)Integer.valueOf(
- mKeypressSoundVolumeSettingsTextView.getText().toString())) / 100;
- sp.edit().putFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, volume).apply();
- updateKeypressSoundVolumeSummary(sp, res);
- }
- });
- builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int whichButton) {
- dialog.dismiss();
- }
- });
- final View v = LayoutInflater.from(context).inflate(
- R.layout.sound_effect_volume_dialog, null);
- 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);
- sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
- final int tempVolume = arg1;
- mKeypressSoundVolumeSettingsTextView.setText(String.valueOf(tempVolume));
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar arg0) {
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar arg0) {
- final float tempVolume = ((float)arg0.getProgress()) / 100;
- am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD, tempVolume);
- }
- });
- sb.setProgress(currentVolumeInt);
- mKeypressSoundVolumeSettingsTextView.setText(String.valueOf(currentVolumeInt));
- builder.setView(v);
- builder.create().show();
+ // TODO: Remove this method and add proxy method to SettingsValues.
+ public SettingsValues getCurrent() {
+ return mSettingsValues;
}
}
diff --git a/java/src/com/android/inputmethod/latin/SettingsActivity.java b/java/src/com/android/inputmethod/latin/SettingsActivity.java
index 0d3c8ebb7..3aeb10113 100644
--- a/java/src/com/android/inputmethod/latin/SettingsActivity.java
+++ b/java/src/com/android/inputmethod/latin/SettingsActivity.java
@@ -20,7 +20,7 @@ import android.content.Intent;
import android.preference.PreferenceActivity;
public final class SettingsActivity extends PreferenceActivity {
- private static final String DEFAULT_FRAGMENT = Settings.class.getName();
+ private static final String DEFAULT_FRAGMENT = SettingsFragment.class.getName();
@Override
public Intent getIntent() {
diff --git a/java/src/com/android/inputmethod/latin/SettingsFragment.java b/java/src/com/android/inputmethod/latin/SettingsFragment.java
new file mode 100644
index 000000000..a2980bfa2
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/SettingsFragment.java
@@ -0,0 +1,375 @@
+/*
+ * 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 android.app.backup.BackupManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.media.AudioManager;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.define.ProductionFlag;
+import com.android.inputmethodcommon.InputMethodSettingsFragment;
+
+public final class SettingsFragment extends InputMethodSettingsFragment
+ implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private PreferenceScreen mKeypressVibrationDurationSettingsPref;
+ private PreferenceScreen mKeypressSoundVolumeSettingsPref;
+ private ListPreference mVoicePreference;
+ private ListPreference mShowCorrectionSuggestionsPreference;
+ private ListPreference mAutoCorrectionThresholdPreference;
+ private ListPreference mKeyPreviewPopupDismissDelay;
+ // Use bigrams to predict the next word when there is no input for it yet
+ private CheckBoxPreference mBigramPrediction;
+ private Preference mDebugSettingsPreference;
+
+ private void setPreferenceEnabled(final String preferenceKey, final boolean enabled) {
+ final Preference preference = findPreference(preferenceKey);
+ if (preference != null) {
+ preference.setEnabled(enabled);
+ }
+ }
+
+ private void ensureConsistencyOfAutoCorrectionSettings() {
+ final String autoCorrectionOff = getResources().getString(
+ R.string.auto_correction_threshold_mode_index_off);
+ final String currentSetting = mAutoCorrectionThresholdPreference.getValue();
+ mBigramPrediction.setEnabled(!currentSetting.equals(autoCorrectionOff));
+ }
+
+ @Override
+ public void onCreate(final Bundle icicle) {
+ super.onCreate(icicle);
+ setInputMethodSettingsCategoryTitle(R.string.language_selection_title);
+ setSubtypeEnablerTitle(R.string.select_language);
+ addPreferencesFromResource(R.xml.prefs);
+
+ final Resources res = getResources();
+ final Context context = getActivity();
+
+ // When we are called from the Settings application but we are not already running, the
+ // {@link SubtypeLocale} class may not have been initialized. It is safe to call
+ // {@link SubtypeLocale#init(Context)} multiple times.
+ SubtypeLocale.init(context);
+ mVoicePreference = (ListPreference) findPreference(Settings.PREF_VOICE_MODE);
+ mShowCorrectionSuggestionsPreference =
+ (ListPreference) findPreference(Settings.PREF_SHOW_SUGGESTIONS_SETTING);
+ final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
+ prefs.registerOnSharedPreferenceChangeListener(this);
+
+ mAutoCorrectionThresholdPreference =
+ (ListPreference) findPreference(Settings.PREF_AUTO_CORRECTION_THRESHOLD);
+ mBigramPrediction = (CheckBoxPreference) findPreference(Settings.PREF_BIGRAM_PREDICTIONS);
+ ensureConsistencyOfAutoCorrectionSettings();
+
+ final PreferenceGroup generalSettings =
+ (PreferenceGroup) findPreference(Settings.PREF_GENERAL_SETTINGS);
+ final PreferenceGroup textCorrectionGroup =
+ (PreferenceGroup) findPreference(Settings.PREF_CORRECTION_SETTINGS);
+ final PreferenceGroup gestureTypingSettings =
+ (PreferenceGroup) findPreference(Settings.PREF_GESTURE_SETTINGS);
+ final PreferenceGroup miscSettings =
+ (PreferenceGroup) findPreference(Settings.PREF_MISC_SETTINGS);
+
+ mDebugSettingsPreference = findPreference(Settings.PREF_DEBUG_SETTINGS);
+ if (mDebugSettingsPreference != null) {
+ if (ProductionFlag.IS_INTERNAL) {
+ final Intent debugSettingsIntent = new Intent(Intent.ACTION_MAIN);
+ debugSettingsIntent.setClassName(
+ context.getPackageName(), DebugSettingsActivity.class.getName());
+ mDebugSettingsPreference.setIntent(debugSettingsIntent);
+ } else {
+ miscSettings.removePreference(mDebugSettingsPreference);
+ }
+ }
+
+ final boolean showVoiceKeyOption = res.getBoolean(
+ R.bool.config_enable_show_voice_key_option);
+ if (!showVoiceKeyOption) {
+ generalSettings.removePreference(mVoicePreference);
+ }
+
+ final PreferenceGroup advancedSettings =
+ (PreferenceGroup) findPreference(Settings.PREF_ADVANCED_SETTINGS);
+ if (!AudioAndHapticFeedbackManager.getInstance().hasVibrator()) {
+ generalSettings.removePreference(findPreference(Settings.PREF_VIBRATE_ON));
+ if (null != advancedSettings) { // Theoretically advancedSettings cannot be null
+ advancedSettings.removePreference(
+ findPreference(Settings.PREF_VIBRATION_DURATION_SETTINGS));
+ }
+ }
+
+ final boolean showKeyPreviewPopupOption = res.getBoolean(
+ R.bool.config_enable_show_popup_on_keypress_option);
+ mKeyPreviewPopupDismissDelay =
+ (ListPreference) findPreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
+ if (!showKeyPreviewPopupOption) {
+ generalSettings.removePreference(findPreference(Settings.PREF_POPUP_ON));
+ if (null != advancedSettings) { // Theoretically advancedSettings cannot be null
+ advancedSettings.removePreference(mKeyPreviewPopupDismissDelay);
+ }
+ } else {
+ final String[] entries = new String[] {
+ res.getString(R.string.key_preview_popup_dismiss_no_delay),
+ res.getString(R.string.key_preview_popup_dismiss_default_delay),
+ };
+ final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger(
+ R.integer.config_key_preview_linger_timeout));
+ mKeyPreviewPopupDismissDelay.setEntries(entries);
+ mKeyPreviewPopupDismissDelay.setEntryValues(
+ new String[] { "0", popupDismissDelayDefaultValue });
+ if (null == mKeyPreviewPopupDismissDelay.getValue()) {
+ mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
+ }
+ mKeyPreviewPopupDismissDelay.setEnabled(
+ SettingsValues.isKeyPreviewPopupEnabled(prefs, res));
+ }
+
+ setPreferenceEnabled(Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST,
+ SettingsValues.showsLanguageSwitchKey(prefs));
+
+ final PreferenceScreen dictionaryLink =
+ (PreferenceScreen) findPreference(Settings.PREF_CONFIGURE_DICTIONARIES_KEY);
+ final Intent intent = dictionaryLink.getIntent();
+
+ final int number = context.getPackageManager().queryIntentActivities(intent, 0).size();
+ // TODO: The experimental version is not supported by the Dictionary Pack Service yet
+ if (ProductionFlag.IS_EXPERIMENTAL || 0 >= number) {
+ textCorrectionGroup.removePreference(dictionaryLink);
+ }
+
+ final boolean gestureInputEnabledByBuildConfig = res.getBoolean(
+ R.bool.config_gesture_input_enabled_by_build_config);
+ if (!gestureInputEnabledByBuildConfig) {
+ getPreferenceScreen().removePreference(gestureTypingSettings);
+ }
+
+ mKeypressVibrationDurationSettingsPref =
+ (PreferenceScreen) findPreference(Settings.PREF_VIBRATION_DURATION_SETTINGS);
+ if (mKeypressVibrationDurationSettingsPref != null) {
+ mKeypressVibrationDurationSettingsPref.setOnPreferenceClickListener(
+ new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference arg0) {
+ showKeypressVibrationDurationSettingsDialog();
+ return true;
+ }
+ });
+ mKeypressVibrationDurationSettingsPref.setSummary(
+ res.getString(R.string.settings_keypress_vibration_duration,
+ SettingsValues.getCurrentVibrationDuration(prefs, res)));
+ }
+
+ mKeypressSoundVolumeSettingsPref =
+ (PreferenceScreen) findPreference(Settings.PREF_KEYPRESS_SOUND_VOLUME);
+ if (mKeypressSoundVolumeSettingsPref != null) {
+ mKeypressSoundVolumeSettingsPref.setOnPreferenceClickListener(
+ new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference arg0) {
+ showKeypressSoundVolumeSettingDialog();
+ return true;
+ }
+ });
+ mKeypressSoundVolumeSettingsPref.setSummary(String.valueOf(
+ getCurrentKeyPressSoundVolumePercent(prefs, res)));
+ }
+ refreshEnablingsOfKeypressSoundAndVibrationSettings(prefs, res);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ final boolean isShortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled();
+ if (isShortcutImeEnabled) {
+ updateVoiceModeSummary();
+ } else {
+ getPreferenceScreen().removePreference(mVoicePreference);
+ }
+ updateShowCorrectionSuggestionsSummary();
+ updateKeyPreviewPopupDelaySummary();
+ updateCustomInputStylesSummary();
+ }
+
+ @Override
+ public void onDestroy() {
+ getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(
+ this);
+ super.onDestroy();
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
+ (new BackupManager(getActivity())).dataChanged();
+ if (key.equals(Settings.PREF_POPUP_ON)) {
+ setPreferenceEnabled(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
+ prefs.getBoolean(Settings.PREF_POPUP_ON, true));
+ } else if (key.equals(Settings.PREF_SHOW_LANGUAGE_SWITCH_KEY)) {
+ setPreferenceEnabled(Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST,
+ SettingsValues.showsLanguageSwitchKey(prefs));
+ } else if (key.equals(Settings.PREF_GESTURE_INPUT)) {
+ final boolean gestureInputEnabledByConfig = getResources().getBoolean(
+ R.bool.config_gesture_input_enabled_by_build_config);
+ if (gestureInputEnabledByConfig) {
+ final boolean gestureInputEnabledByUser = prefs.getBoolean(
+ Settings.PREF_GESTURE_INPUT, true);
+ setPreferenceEnabled(Settings.PREF_GESTURE_PREVIEW_TRAIL,
+ gestureInputEnabledByUser);
+ setPreferenceEnabled(Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT,
+ gestureInputEnabledByUser);
+ }
+ }
+ ensureConsistencyOfAutoCorrectionSettings();
+ updateVoiceModeSummary();
+ updateShowCorrectionSuggestionsSummary();
+ updateKeyPreviewPopupDelaySummary();
+ refreshEnablingsOfKeypressSoundAndVibrationSettings(prefs, getResources());
+ }
+
+ private void updateShowCorrectionSuggestionsSummary() {
+ mShowCorrectionSuggestionsPreference.setSummary(
+ getResources().getStringArray(R.array.prefs_suggestion_visibilities)
+ [mShowCorrectionSuggestionsPreference.findIndexOfValue(
+ mShowCorrectionSuggestionsPreference.getValue())]);
+ }
+
+ private void updateCustomInputStylesSummary() {
+ final PreferenceScreen customInputStyles =
+ (PreferenceScreen)findPreference(Settings.PREF_CUSTOM_INPUT_STYLES);
+ final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
+ final Resources res = getResources();
+ final String prefSubtype = SettingsValues.getPrefAdditionalSubtypes(prefs, res);
+ final InputMethodSubtype[] subtypes =
+ AdditionalSubtype.createAdditionalSubtypesArray(prefSubtype);
+ final StringBuilder styles = new StringBuilder();
+ for (final InputMethodSubtype subtype : subtypes) {
+ if (styles.length() > 0) styles.append(", ");
+ styles.append(SubtypeLocale.getSubtypeDisplayName(subtype, res));
+ }
+ customInputStyles.setSummary(styles);
+ }
+
+ private void updateKeyPreviewPopupDelaySummary() {
+ final ListPreference lp = mKeyPreviewPopupDismissDelay;
+ final CharSequence[] entries = lp.getEntries();
+ if (entries == null || entries.length <= 0) return;
+ lp.setSummary(entries[lp.findIndexOfValue(lp.getValue())]);
+ }
+
+ private void updateVoiceModeSummary() {
+ mVoicePreference.setSummary(
+ getResources().getStringArray(R.array.voice_input_modes_summary)
+ [mVoicePreference.findIndexOfValue(mVoicePreference.getValue())]);
+ }
+
+ private void refreshEnablingsOfKeypressSoundAndVibrationSettings(
+ final SharedPreferences sp, final Resources res) {
+ if (mKeypressVibrationDurationSettingsPref != null) {
+ final boolean hasVibratorHardware =
+ AudioAndHapticFeedbackManager.getInstance().hasVibrator();
+ final boolean vibrateOnByUser = sp.getBoolean(Settings.PREF_VIBRATE_ON,
+ res.getBoolean(R.bool.config_default_vibration_enabled));
+ mKeypressVibrationDurationSettingsPref.setEnabled(
+ hasVibratorHardware && vibrateOnByUser);
+ }
+
+ if (mKeypressSoundVolumeSettingsPref != null) {
+ final boolean soundOn = sp.getBoolean(Settings.PREF_SOUND_ON,
+ res.getBoolean(R.bool.config_default_sound_enabled));
+ mKeypressSoundVolumeSettingsPref.setEnabled(soundOn);
+ }
+ }
+
+ private void showKeypressVibrationDurationSettingsDialog() {
+ final SharedPreferences sp = getPreferenceManager().getSharedPreferences();
+ final Context context = getActivity();
+ final PreferenceScreen settingsPref = mKeypressVibrationDurationSettingsPref;
+ final SeekBarDialog.Listener listener = new SeekBarDialog.Adapter() {
+ @Override
+ public void onPositiveButtonClick(final SeekBarDialog dialog) {
+ final int ms = dialog.getValue();
+ sp.edit().putInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, ms).apply();
+ if (settingsPref != null) {
+ settingsPref.setSummary(dialog.getValueText());
+ }
+ }
+
+ @Override
+ public void onStopTrackingTouch(final SeekBarDialog dialog) {
+ final int ms = dialog.getValue();
+ AudioAndHapticFeedbackManager.getInstance().vibrate(ms);
+ }
+ };
+ final int currentMs = SettingsValues.getCurrentVibrationDuration(sp, getResources());
+ final SeekBarDialog.Builder builder = new SeekBarDialog.Builder(context);
+ builder.setTitle(R.string.prefs_keypress_vibration_duration_settings)
+ .setListener(listener)
+ .setMaxValue(AudioAndHapticFeedbackManager.MAX_KEYPRESS_VIBRATION_DURATION)
+ .setValueFromat(R.string.settings_keypress_vibration_duration)
+ .setValue(currentMs)
+ .create()
+ .show();
+ }
+
+ private static final int PERCENT_INT = 100;
+ private static final float PERCENT_FLOAT = 100.0f;
+
+ private static int getCurrentKeyPressSoundVolumePercent(final SharedPreferences sp,
+ final Resources res) {
+ return (int)(SettingsValues.getCurrentKeypressSoundVolume(sp, res) * PERCENT_FLOAT);
+ }
+
+ private void showKeypressSoundVolumeSettingDialog() {
+ final SharedPreferences sp = getPreferenceManager().getSharedPreferences();
+ final Context context = getActivity();
+ final AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+ final PreferenceScreen settingsPref = mKeypressSoundVolumeSettingsPref;
+ final SeekBarDialog.Listener listener = new SeekBarDialog.Adapter() {
+ @Override
+ public void onPositiveButtonClick(final SeekBarDialog dialog) {
+ final float volume = dialog.getValue() / PERCENT_FLOAT;
+ sp.edit().putFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, volume).apply();
+ if (settingsPref != null) {
+ settingsPref.setSummary(dialog.getValueText());
+ }
+ }
+
+ @Override
+ public void onStopTrackingTouch(final SeekBarDialog dialog) {
+ final float volume = dialog.getValue() / PERCENT_FLOAT;
+ am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD, volume);
+ }
+ };
+ final SeekBarDialog.Builder builder = new SeekBarDialog.Builder(context);
+ final int currentVolumeInt = getCurrentKeyPressSoundVolumePercent(sp, getResources());
+ builder.setTitle(R.string.prefs_keypress_sound_volume_settings)
+ .setListener(listener)
+ .setMaxValue(PERCENT_INT)
+ .setValue(currentVolumeInt)
+ .create()
+ .show();
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index a23876722..39406621c 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -16,7 +16,6 @@
package com.android.inputmethod.latin;
-import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -78,16 +77,12 @@ public final class SettingsValues {
public final boolean mUseDoubleSpacePeriod;
// Use bigrams to predict the next word when there is no input for it yet
public final boolean mBigramPredictionEnabled;
- @SuppressWarnings("unused") // TODO: Use this
- private final int mVibrationDurationSettingsRawValue;
- @SuppressWarnings("unused") // TODO: Use this
- private final float mKeypressSoundVolumeRawValue;
public final boolean mGestureInputEnabled;
public final boolean mGesturePreviewTrailEnabled;
public final boolean mGestureFloatingPreviewTextEnabled;
// From the input box
- private final InputAttributes mInputAttributes;
+ public final InputAttributes mInputAttributes;
// Deduced settings
public final int mKeypressVibrationDuration;
@@ -100,10 +95,8 @@ public final class SettingsValues {
private final boolean mVoiceKeyEnabled;
private final boolean mVoiceKeyOnMain;
- public SettingsValues(final SharedPreferences prefs, final InputAttributes inputAttributes,
- final Context context) {
- final Resources res = context.getResources();
-
+ public SettingsValues(final SharedPreferences prefs, final Resources res,
+ final InputAttributes inputAttributes) {
// Get the resources
mDelayUpdateOldSuggestions = res.getInteger(R.integer.config_delay_update_old_suggestions);
mWeakSpaceStrippers = res.getString(R.string.weak_space_stripping_symbols);
@@ -125,7 +118,7 @@ public final class SettingsValues {
res.getString(R.string.symbols_excluded_from_word_separators);
mWordSeparators = createWordSeparators(mWeakSpaceStrippers, mWeakSpaceSwappers,
mSymbolsExcludedFromWordSeparators, res);
- mHintToSaveText = context.getText(R.string.hint_add_to_dictionary);
+ mHintToSaveText = res.getText(R.string.hint_add_to_dictionary);
// Store the input attributes
if (null == inputAttributes) {
@@ -136,7 +129,7 @@ public final class SettingsValues {
// Get the settings preferences
mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true);
- mVibrateOn = isVibrateOn(context, prefs, res);
+ mVibrateOn = isVibrateOn(prefs, res);
mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON,
res.getBoolean(R.bool.config_default_sound_enabled));
mKeyPreviewPopupOn = isKeyPreviewPopupEnabled(prefs, res);
@@ -158,9 +151,6 @@ public final class SettingsValues {
mUseDoubleSpacePeriod = prefs.getBoolean(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true);
mAutoCorrectEnabled = isAutoCorrectEnabled(res, mAutoCorrectionThresholdRawValue);
mBigramPredictionEnabled = isBigramPredictionEnabled(prefs, res);
- 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);
@@ -221,9 +211,8 @@ public final class SettingsValues {
throw new RuntimeException("Bug: visibility string is not configured correctly");
}
- private static boolean isVibrateOn(final Context context, final SharedPreferences prefs,
- final Resources res) {
- final boolean hasVibrator = VibratorUtils.getInstance(context).hasVibrator();
+ private static boolean isVibrateOn(final SharedPreferences prefs, final Resources res) {
+ final boolean hasVibrator = AudioAndHapticFeedbackManager.getInstance().hasVibrator();
return hasVibrator && prefs.getBoolean(Settings.PREF_VIBRATE_ON,
res.getBoolean(R.bool.config_default_vibration_enabled));
}
@@ -280,6 +269,7 @@ public final class SettingsValues {
return !currentAutoCorrectionSetting.equals(autoCorrectionOff);
}
+ // TODO: Clean up and move public helper methods to Settings class.
// Public to access from KeyboardSwitcher. Should it have access to some
// process-global instance instead?
public static boolean isKeyPreviewPopupEnabled(final SharedPreferences prefs,
@@ -383,27 +373,23 @@ public final class SettingsValues {
// Accessed from the settings interface, hence public
public static float getCurrentKeypressSoundVolume(final SharedPreferences prefs,
final Resources res) {
- // TODO: use mVibrationDurationSettingsRawValue instead of reading it again here
final float volume = prefs.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f);
if (volume >= 0) {
return volume;
}
-
- return Float.parseFloat(ResourceUtils.getDeviceOverrideValue(
- res, R.array.keypress_volumes, "-1.0f"));
+ return Float.parseFloat(
+ ResourceUtils.getDeviceOverrideValue(res, R.array.keypress_volumes));
}
// Likewise
public static int getCurrentVibrationDuration(final SharedPreferences prefs,
final Resources res) {
- // TODO: use mKeypressVibrationDuration instead of reading it again here
final int ms = prefs.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1);
if (ms >= 0) {
return ms;
}
-
- return Integer.parseInt(ResourceUtils.getDeviceOverrideValue(
- res, R.array.keypress_vibration_durations, "-1"));
+ return Integer.parseInt(
+ ResourceUtils.getDeviceOverrideValue(res, R.array.keypress_vibration_durations));
}
// Likewise
@@ -434,9 +420,4 @@ public final class SettingsValues {
public boolean isSameInputType(final EditorInfo editorInfo) {
return mInputAttributes.isSameInputType(editorInfo);
}
-
- // For debug.
- public String getInputAttributesDebugString() {
- return mInputAttributes.toString();
- }
}
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
index 043043cef..ddaa5ff5b 100644
--- a/java/src/com/android/inputmethod/latin/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -62,6 +62,23 @@ public final class StringUtils {
}
/**
+ * Find a string that start with specified prefix from an array.
+ *
+ * @param prefix a prefix string to find.
+ * @param array an string array to be searched.
+ * @return the rest part of the string that starts with the prefix.
+ * Returns null if it couldn't be found.
+ */
+ public static String findPrefixedString(final String prefix, final String[] array) {
+ for (final String element : array) {
+ if (element.startsWith(prefix)) {
+ return element.substring(prefix.length());
+ }
+ }
+ return null;
+ }
+
+ /**
* Remove duplicates from an array of strings.
*
* This method will always keep the first occurrence of all strings at their position
diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
index 5d8c0b17d..370a6594b 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
@@ -130,7 +130,8 @@ public final class SubtypeLocale {
}
public static int getSubtypeNameId(String localeString, String keyboardLayoutName) {
- if (Build.VERSION.SDK_INT >= /* JELLY_BEAN */ 15 && isExceptionalLocale(localeString)) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
+ && isExceptionalLocale(localeString)) {
return sExceptionalLocaleToWithLayoutNameIdsMap.get(localeString);
}
final String key = localeString.equals(NO_LANGUAGE)
@@ -166,8 +167,9 @@ public final class SubtypeLocale {
// zz azerty T No language (AZERTY) in system locale
public static String getSubtypeDisplayName(final InputMethodSubtype subtype, Resources res) {
- final String replacementString = (Build.VERSION.SDK_INT >= /* JELLY_BEAN */ 15
- && subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME))
+ final String replacementString =
+ (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
+ && subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME))
? subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)
: getSubtypeLocaleDisplayName(subtype.getLocale());
final int nameResId = subtype.getNameResId();
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 8f2e27549..fe2908428 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -20,7 +20,6 @@ import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.REQ_NET
import android.content.Context;
import android.content.Intent;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.inputmethodservice.InputMethodService;
import android.net.ConnectivityManager;
@@ -53,9 +52,6 @@ public final class SubtypeSwitcher {
private InputMethodInfo mShortcutInputMethodInfo;
private InputMethodSubtype mShortcutSubtype;
private InputMethodSubtype mNoLanguageSubtype;
- // Note: This variable is always non-null after {@link #initialize(LatinIME)}.
- private InputMethodSubtype mCurrentSubtype;
- private Locale mCurrentSystemLocale;
/*-----------------------------------------------------------*/
private boolean mIsNetworkConnected;
@@ -84,7 +80,6 @@ public final class SubtypeSwitcher {
public static void init(final Context context) {
SubtypeLocale.init(context);
sInstance.initialize(context);
- sInstance.updateAllParameters();
}
private SubtypeSwitcher() {
@@ -96,60 +91,28 @@ public final class SubtypeSwitcher {
mRichImm = RichInputMethodManager.getInstance();
mConnectivityManager = (ConnectivityManager) service.getSystemService(
Context.CONNECTIVITY_SERVICE);
- mCurrentSystemLocale = mResources.getConfiguration().locale;
mNoLanguageSubtype = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
SubtypeLocale.NO_LANGUAGE, SubtypeLocale.QWERTY);
- mCurrentSubtype = mRichImm.getCurrentInputMethodSubtype(mNoLanguageSubtype);
if (mNoLanguageSubtype == null) {
throw new RuntimeException("Can't find no lanugage with QWERTY subtype");
}
final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
mIsNetworkConnected = (info != null && info.isConnected());
- }
-
- // Update all parameters stored in SubtypeSwitcher.
- // Only configuration changed event is allowed to call this because this is heavy.
- private void updateAllParameters() {
- mCurrentSystemLocale = mResources.getConfiguration().locale;
- updateSubtype(mRichImm.getCurrentInputMethodSubtype(mNoLanguageSubtype));
- updateParametersOnStartInputViewAndReturnIfCurrentSubtypeEnabled();
- }
- /**
- * Update parameters which are changed outside LatinIME. This parameters affect UI so they
- * should be updated every time onStartInputView.
- *
- * @return true if the current subtype is enabled.
- */
- public boolean updateParametersOnStartInputViewAndReturnIfCurrentSubtypeEnabled() {
- final boolean currentSubtypeEnabled =
- updateEnabledSubtypesAndReturnIfEnabled(mCurrentSubtype);
- updateShortcutIME();
- return currentSubtypeEnabled;
+ onSubtypeChanged(getCurrentSubtype());
+ updateParametersOnStartInputView();
}
/**
- * Update enabled subtypes from the framework.
- *
- * @param subtype the subtype to be checked
- * @return true if the {@code subtype} is enabled.
+ * Update parameters which are changed outside LatinIME. This parameters affect UI so that they
+ * should be updated every time onStartInputView is called.
*/
- private boolean updateEnabledSubtypesAndReturnIfEnabled(final InputMethodSubtype subtype) {
+ public void updateParametersOnStartInputView() {
final List<InputMethodSubtype> enabledSubtypesOfThisIme =
mRichImm.getInputMethodManager().getEnabledInputMethodSubtypeList(null, true);
mNeedsToDisplayLanguage.updateEnabledSubtypeCount(enabledSubtypesOfThisIme.size());
-
- for (final InputMethodSubtype ims : enabledSubtypesOfThisIme) {
- if (ims.equals(subtype)) {
- return true;
- }
- }
- if (DBG) {
- Log.w(TAG, "Subtype: " + subtype.getLocale() + "/" + subtype.getExtraValue()
- + " was disabled");
- }
- return false;
+ updateShortcutIME();
}
private void updateShortcutIME() {
@@ -185,25 +148,21 @@ public final class SubtypeSwitcher {
}
// Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function.
- public void updateSubtype(InputMethodSubtype newSubtype) {
+ public void onSubtypeChanged(final InputMethodSubtype newSubtype) {
if (DBG) {
- Log.w(TAG, "onCurrentInputMethodSubtypeChanged: to: "
- + newSubtype.getLocale() + "/" + newSubtype.getExtraValue() + ", from: "
- + mCurrentSubtype.getLocale() + "/" + mCurrentSubtype.getExtraValue());
+ Log.w(TAG, "onSubtypeChanged: " + SubtypeLocale.getSubtypeDisplayName(
+ newSubtype, mResources));
}
final Locale newLocale = SubtypeLocale.getSubtypeLocale(newSubtype);
- final boolean sameLocale = mCurrentSystemLocale.equals(newLocale);
- final boolean sameLanguage = mCurrentSystemLocale.getLanguage().equals(
- newLocale.getLanguage());
+ final Locale systemLocale = mResources.getConfiguration().locale;
+ final boolean sameLocale = systemLocale.equals(newLocale);
+ final boolean sameLanguage = systemLocale.getLanguage().equals(newLocale.getLanguage());
final boolean implicitlyEnabled =
mRichImm.checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled(newSubtype);
mNeedsToDisplayLanguage.updateIsSystemLanguageSameAsInputLanguage(
sameLocale || (sameLanguage && implicitlyEnabled));
- if (newSubtype.equals(mCurrentSubtype)) return;
-
- mCurrentSubtype = newSubtype;
updateShortcutIME();
}
@@ -281,21 +240,11 @@ public final class SubtypeSwitcher {
}
public Locale getCurrentSubtypeLocale() {
- return SubtypeLocale.getSubtypeLocale(mCurrentSubtype);
- }
-
- public boolean onConfigurationChanged(final Configuration conf) {
- final Locale systemLocale = conf.locale;
- final boolean systemLocaleChanged = !systemLocale.equals(mCurrentSystemLocale);
- // If system configuration was changed, update all parameters.
- if (systemLocaleChanged) {
- updateAllParameters();
- }
- return systemLocaleChanged;
+ return SubtypeLocale.getSubtypeLocale(getCurrentSubtype());
}
public InputMethodSubtype getCurrentSubtype() {
- return mCurrentSubtype;
+ return mRichImm.getCurrentInputMethodSubtype(mNoLanguageSubtype);
}
public InputMethodSubtype getNoLanguageSubtype() {
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
index ddae5ac48..a16784985 100644
--- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -24,27 +24,28 @@ import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
+import android.os.Build;
import android.provider.UserDictionary.Words;
import android.text.TextUtils;
import java.util.Arrays;
/**
- * An expandable dictionary that stores the words in the user unigram dictionary.
- *
- * Largely a copy of UserDictionary, will replace that class in the future.
+ * An expandable dictionary that stores the words in the user dictionary provider into a binary
+ * dictionary file to use it from native code.
*/
public class UserBinaryDictionary extends ExpandableBinaryDictionary {
// The user dictionary provider uses an empty string to mean "all languages".
private static final String USER_DICTIONARY_ALL_LANGUAGES = "";
+ private static final int HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY = 250;
+ private static final int LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY = 160;
// TODO: use Words.SHORTCUT when we target JellyBean or above
final static String SHORTCUT = "shortcut";
private static final String[] PROJECTION_QUERY;
static {
- // 16 is JellyBean, but we want this to compile against ICS.
- if (android.os.Build.VERSION.SDK_INT >= 16) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
PROJECTION_QUERY = new String[] {
Words.WORD,
SHORTCUT,
@@ -90,13 +91,14 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
mObserver = new ContentObserver(null) {
@Override
public void onChange(final boolean self) {
- // This hook is deprecated as of API level 16, but should still be supported for
- // cases where the IME is running on an older version of the platform.
+ // This hook is deprecated as of API level 16 (Build.VERSION_CODES.JELLY_BEAN),
+ // but should still be supported for cases where the IME is running on an older
+ // version of the platform.
onChange(self, null);
}
- // The following hook is only available as of API level 16, and as such it will only
- // work on JellyBean+ devices. On older versions of the platform, the hook
- // above will be called instead.
+ // The following hook is only available as of API level 16
+ // (Build.VERSION_CODES.JELLY_BEAN), and as such it will only work on JellyBean+
+ // devices. On older versions of the platform, the hook above will be called instead.
@Override
public void onChange(final boolean self, final Uri uri) {
setRequiresReload(true);
@@ -232,9 +234,21 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
mContext.startActivity(intent);
}
+ private int scaleFrequencyFromDefaultToLatinIme(final int defaultFrequency) {
+ // The default frequency for the user dictionary is 250 for historical reasons.
+ // Latin IME considers a good value for the default user dictionary frequency
+ // is about 160 considering the scale we use. So we are scaling down the values.
+ if (defaultFrequency > Integer.MAX_VALUE / LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY) {
+ return (defaultFrequency / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY)
+ * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY;
+ } else {
+ return (defaultFrequency * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY)
+ / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY;
+ }
+ }
+
private void addWords(final Cursor cursor) {
- // 16 is JellyBean, but we want this to compile against ICS.
- final boolean hasShortcutColumn = android.os.Build.VERSION.SDK_INT >= 16;
+ final boolean hasShortcutColumn = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
clearFusionDictionary();
if (cursor == null) return;
if (cursor.moveToFirst()) {
@@ -245,12 +259,13 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
final String word = cursor.getString(indexWord);
final String shortcut = hasShortcutColumn ? cursor.getString(indexShortcut) : null;
final int frequency = cursor.getInt(indexFrequency);
+ final int adjustedFrequency = scaleFrequencyFromDefaultToLatinIme(frequency);
// Safeguard against adding really long words.
if (word.length() < MAX_WORD_LENGTH) {
- super.addWord(word, null, frequency);
+ super.addWord(word, null, adjustedFrequency);
}
if (null != shortcut && shortcut.length() < MAX_WORD_LENGTH) {
- super.addWord(shortcut, word, frequency);
+ super.addWord(shortcut, word, adjustedFrequency);
}
cursor.moveToNext();
}
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java
index 100e377f6..4fa3d7df8 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java
@@ -48,6 +48,7 @@ public final class UserHistoryDictIOUtils {
public void setBigram(final String word1, final String word2, final int frequency);
}
+ @UsedForTesting
public interface BigramDictionaryInterface {
public int getFrequency(final String word1, final String word2);
}
@@ -214,4 +215,4 @@ public final class UserHistoryDictIOUtils {
}
}
-} \ No newline at end of file
+}
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java
index df44948f9..316f09603 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java
@@ -18,6 +18,8 @@ package com.android.inputmethod.latin;
import android.util.Log;
+import com.android.inputmethod.annotations.UsedForTesting;
+
import java.util.HashMap;
import java.util.Set;
@@ -26,6 +28,7 @@ import java.util.Set;
* All bigrams including stale ones in SQL DB should be stored in this class to avoid adding stale
* bigrams when we write to the SQL DB.
*/
+@UsedForTesting
public final class UserHistoryDictionaryBigramList {
public static final byte FORGETTING_CURVE_INITIAL_VALUE = 0;
private static final String TAG = UserHistoryDictionaryBigramList.class.getSimpleName();
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 3eac6a237..acfcd5354 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -61,7 +61,7 @@ public final class Utils {
}
}
- /* package */ static class RingCharBuffer {
+ /* package */ static final class RingCharBuffer {
private static RingCharBuffer sRingCharBuffer = new RingCharBuffer();
private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC';
private static final int INVALID_COORDINATE = -2;
@@ -203,7 +203,7 @@ public final class Utils {
}
// Initialization-on-demand holder
- private static class OnDemandInitializationHolder {
+ private static final class OnDemandInitializationHolder {
public static final UsabilityStudyLogUtils sInstance = new UsabilityStudyLogUtils();
}
diff --git a/java/src/com/android/inputmethod/latin/VibratorUtils.java b/java/src/com/android/inputmethod/latin/VibratorUtils.java
deleted file mode 100644
index b6696cec0..000000000
--- a/java/src/com/android/inputmethod/latin/VibratorUtils.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2012 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.os.Vibrator;
-
-public final class VibratorUtils {
- private static final VibratorUtils sInstance = new VibratorUtils();
- private Vibrator mVibrator;
-
- private VibratorUtils() {
- // This utility class is not publicly instantiable.
- }
-
- public static VibratorUtils getInstance(Context context) {
- if (sInstance.mVibrator == null) {
- sInstance.mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
- }
- return sInstance;
- }
-
- public boolean hasVibrator() {
- if (mVibrator == null) {
- return false;
- }
- return mVibrator.hasVibrator();
- }
-
- public void vibrate(long milliseconds) {
- if (mVibrator == null) {
- return;
- }
- mVibrator.vibrate(milliseconds);
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
index f1a7e97e8..937d7ab34 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
@@ -56,6 +56,7 @@ public final class BinaryDictInputOutput {
private static final int MAX_PASSES = 24;
private static final int MAX_JUMPS = 12;
+ @UsedForTesting
public interface FusionDictionaryBufferInterface {
public int readUnsignedByte();
public int readUnsignedShort();
diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
index f7cc69359..bfc275df5 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.latin.makedict;
+import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.Constants;
import java.util.ArrayList;
@@ -29,6 +30,7 @@ import java.util.LinkedList;
/**
* A dictionary that can fusion heads and tails of words for more compression.
*/
+@UsedForTesting
public final class FusionDictionary implements Iterable<Word> {
private static final boolean DBG = MakedictLog.DBG;
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index f5465d7b0..2fc18eab1 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -38,6 +38,7 @@ import android.net.Uri;
import android.os.Build;
import android.os.IBinder;
import android.os.SystemClock;
+import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
@@ -161,7 +162,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
return sInstance;
}
- public void init(final LatinIME latinIME, final SharedPreferences prefs) {
+ public void init(final LatinIME latinIME) {
assert latinIME != null;
if (latinIME == null) {
Log.w(TAG, "IMS is null; logging is off");
@@ -171,6 +172,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
Log.w(TAG, "IME storage directory does not exist.");
}
}
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(latinIME);
if (prefs != null) {
mUUIDString = getUUID(prefs);
if (!prefs.contains(PREF_USABILITY_STUDY_MODE)) {
@@ -741,7 +743,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private static final LogStatement LOGSTATEMENT_COMMIT_RECORD_SPLIT_WORDS =
new LogStatement("recordSplitWords", true, false);
- private void onWordComplete(final String word, final long maxTime, final boolean isSplitWords) {
+ public void onWordComplete(final String word, final long maxTime) {
final Dictionary dictionary = getDictionary();
if (word != null && word.length() > 0 && hasLetters(word)) {
mCurrentLogUnit.setWord(word);
@@ -751,11 +753,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
final LogUnit newLogUnit = mCurrentLogUnit.splitByTime(maxTime);
enqueueCommitText(word);
- if (isSplitWords) {
- enqueueEvent(LOGSTATEMENT_COMMIT_RECORD_SPLIT_WORDS);
- enqueueCommitText(" ");
- mStatistics.recordSplitWords();
- }
commitCurrentLogUnit();
mCurrentLogUnit = newLogUnit;
}
@@ -1049,12 +1046,15 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
new LogStatement("LatinIMEPickSuggestionManually", true, false, "replacedWord", "index",
"suggestion", "x", "y");
public static void latinIME_pickSuggestionManually(final String replacedWord,
- final int index, CharSequence suggestion) {
+ final int index, final String suggestion) {
+ final String scrubbedWord = scrubDigitsFromString(suggestion);
final ResearchLogger researchLogger = getInstance();
researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_PICKSUGGESTIONMANUALLY,
scrubDigitsFromString(replacedWord), index,
- suggestion == null ? null : scrubDigitsFromString(suggestion.toString()),
- Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE);
+ suggestion == null ? null : scrubbedWord, Constants.SUGGESTION_STRIP_COORDINATE,
+ Constants.SUGGESTION_STRIP_COORDINATE);
+ researchLogger.onWordComplete(scrubbedWord, Long.MAX_VALUE);
+ researchLogger.mStatistics.recordManualSuggestion();
}
/**
@@ -1065,10 +1065,11 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private static final LogStatement LOGSTATEMENT_LATINIME_PUNCTUATIONSUGGESTION =
new LogStatement("LatinIMEPunctuationSuggestion", false, false, "index", "suggestion",
"x", "y");
- public static void latinIME_punctuationSuggestion(final int index,
- final CharSequence suggestion) {
- getInstance().enqueueEvent(LOGSTATEMENT_LATINIME_PUNCTUATIONSUGGESTION, index, suggestion,
+ public static void latinIME_punctuationSuggestion(final int index, final String suggestion) {
+ final ResearchLogger researchLogger = getInstance();
+ researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_PUNCTUATIONSUGGESTION, index, suggestion,
Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE);
+ researchLogger.onWordComplete(suggestion, Long.MAX_VALUE);
}
/**
@@ -1147,9 +1148,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
* backspace.
*/
private static final LogStatement LOGSTATEMENT_LATINIME_REVERTCOMMIT =
- new LogStatement("LatinIMERevertCommit", true, false, "originallyTypedWord");
- public static void latinIME_revertCommit(final String originallyTypedWord) {
- getInstance().enqueueEvent(LOGSTATEMENT_LATINIME_REVERTCOMMIT, originallyTypedWord);
+ new LogStatement("LatinIMERevertCommit", true, false, "committedWord",
+ "originallyTypedWord");
+ public static void latinIME_revertCommit(final String committedWord,
+ final String originallyTypedWord) {
+ final ResearchLogger researchLogger = getInstance();
+ researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_REVERTCOMMIT, committedWord,
+ originallyTypedWord);
+ researchLogger.mStatistics.recordRevertCommit();
}
/**
@@ -1259,17 +1265,27 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
final ResearchLogger researchLogger = getInstance();
researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_COMMITCURRENTAUTOCORRECTION,
scrubbedTypedWord, scrubbedAutoCorrection, separatorString);
- researchLogger.onWordComplete(scrubbedAutoCorrection, Long.MAX_VALUE,
- false /* isPartial */);
+ researchLogger.onWordComplete(scrubbedAutoCorrection, Long.MAX_VALUE);
}
private boolean isExpectingCommitText = false;
+ /**
+ * Log a call to RichInputConnection.commitPartialText
+ *
+ * SystemResponse: The IME is committing part of a word. This happens if a space is
+ * automatically inserted to split a single typed string into two or more words.
+ */
+ // TODO: This method is currently unused. Find where it should be called from in the IME and
+ // add invocations.
+ private static final LogStatement LOGSTATEMENT_LATINIME_COMMIT_PARTIAL_TEXT =
+ new LogStatement("LatinIMECommitPartialText", true, false, "newCursorPosition");
public static void latinIME_commitPartialText(final CharSequence committedWord,
final long lastTimestampOfWordData) {
final ResearchLogger researchLogger = getInstance();
final String scrubbedWord = scrubDigitsFromString(committedWord.toString());
- researchLogger.onWordComplete(scrubbedWord, lastTimestampOfWordData, true /* isPartial */);
- researchLogger.isExpectingCommitText = true;
+ researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_COMMIT_PARTIAL_TEXT);
+ researchLogger.onWordComplete(scrubbedWord, lastTimestampOfWordData);
+ researchLogger.mStatistics.recordSplitWords();
}
/**
@@ -1287,7 +1303,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
if (!researchLogger.isExpectingCommitText) {
researchLogger.enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTIONCOMMITTEXT,
newCursorPosition);
- researchLogger.onWordComplete(scrubbedWord, Long.MAX_VALUE, false /* isPartial */);
+ researchLogger.onWordComplete(scrubbedWord, Long.MAX_VALUE);
}
researchLogger.isExpectingCommitText = false;
}
@@ -1465,7 +1481,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
"isEmptinessStateKnown", "averageTimeBetweenKeys", "averageTimeBeforeDelete",
"averageTimeDuringRepeatedDelete", "averageTimeAfterDelete",
"dictionaryWordCount", "splitWordsCount", "gestureInputCount",
- "gestureCharsCount", "gesturesDeletedCount");
+ "gestureCharsCount", "gesturesDeletedCount", "manualSuggestionsCount",
+ "revertCommitsCount");
private static void logStatistics() {
final ResearchLogger researchLogger = getInstance();
final Statistics statistics = researchLogger.mStatistics;
@@ -1477,8 +1494,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
statistics.mDuringRepeatedDeleteKeysCounter.getAverageTime(),
statistics.mAfterDeleteKeyCounter.getAverageTime(),
statistics.mDictionaryWordCount, statistics.mSplitWordsCount,
- statistics.mGesturesInputCount,
- statistics.mGesturesCharsCount,
- statistics.mGesturesDeletedCount);
+ statistics.mGesturesInputCount, statistics.mGesturesCharsCount,
+ statistics.mGesturesDeletedCount, statistics.mManualSuggestionsCount,
+ statistics.mRevertCommitsCount);
}
}
diff --git a/java/src/com/android/inputmethod/research/Statistics.java b/java/src/com/android/inputmethod/research/Statistics.java
index a02aabf3c..e9c02c919 100644
--- a/java/src/com/android/inputmethod/research/Statistics.java
+++ b/java/src/com/android/inputmethod/research/Statistics.java
@@ -47,6 +47,10 @@ public class Statistics {
int mGesturesDeletedCount;
// Total number of characters in words entered by gesture.
int mGesturesCharsCount;
+ // Number of manual suggestions chosen.
+ int mManualSuggestionsCount;
+ // Number of times a commit was reverted in this session.
+ int mRevertCommitsCount;
// Whether the text field was empty upon editing
boolean mIsEmptyUponStarting;
boolean mIsEmptinessStateKnown;
@@ -111,6 +115,8 @@ public class Statistics {
mSplitWordsCount = 0;
mGesturesInputCount = 0;
mGesturesDeletedCount = 0;
+ mManualSuggestionsCount = 0;
+ mRevertCommitsCount = 0;
mIsEmptyUponStarting = true;
mIsEmptinessStateKnown = false;
mKeyCounter.reset();
@@ -184,4 +190,11 @@ public class Statistics {
public void recordGestureDelete() {
mGesturesDeletedCount++;
}
+ public void recordManualSuggestion() {
+ mManualSuggestionsCount++;
+ }
+
+ public void recordRevertCommit() {
+ mRevertCommitsCount++;
+ }
}