diff options
Diffstat (limited to 'java')
319 files changed, 6458 insertions, 6466 deletions
diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml index 0d80c037b..031d62e0c 100644 --- a/java/AndroidManifest.xml +++ b/java/AndroidManifest.xml @@ -18,7 +18,7 @@ coreApp="true" package="com.android.inputmethod.latin"> - <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" /> + <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /> @@ -32,7 +32,7 @@ <uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" /> <application android:label="@string/english_ime_name" - android:icon="@drawable/ic_launcher_keyboard" + android:icon="@mipmap/ic_launcher_keyboard" android:killAfterRestore="false" android:supportsRtl="true"> @@ -57,7 +57,7 @@ <activity android:name=".setup.SetupActivity" android:label="@string/english_ime_name" - android:icon="@drawable/ic_launcher_keyboard" + android:icon="@mipmap/ic_launcher_keyboard" android:launchMode="singleTask" android:noHistory="true"> <intent-filter> diff --git a/java/res/drawable-hdpi/btn_keyboard_key_normal.9.png b/java/res/drawable-hdpi/btn_keyboard_key_normal.9.png Binary files differnew file mode 100644 index 000000000..3e25180f0 --- /dev/null +++ b/java/res/drawable-hdpi/btn_keyboard_key_normal.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png b/java/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png Binary files differnew file mode 100644 index 000000000..bad360f77 --- /dev/null +++ b/java/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png b/java/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png Binary files differnew file mode 100644 index 000000000..49f519860 --- /dev/null +++ b/java/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_pressed.9.png b/java/res/drawable-hdpi/btn_keyboard_key_pressed.9.png Binary files differnew file mode 100644 index 000000000..e784eddf8 --- /dev/null +++ b/java/res/drawable-hdpi/btn_keyboard_key_pressed.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png b/java/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png Binary files differnew file mode 100644 index 000000000..a4731cf1a --- /dev/null +++ b/java/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png b/java/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png Binary files differnew file mode 100644 index 000000000..03e163c9c --- /dev/null +++ b/java/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png diff --git a/java/res/drawable-hdpi/ic_launcher_keyboard.png b/java/res/drawable-hdpi/ic_launcher_keyboard.png Binary files differdeleted file mode 100644 index 7ae00ed3f..000000000 --- a/java/res/drawable-hdpi/ic_launcher_keyboard.png +++ /dev/null diff --git a/java/res/drawable-hdpi/ic_subtype_mic_dark.png b/java/res/drawable-hdpi/ic_subtype_mic_dark.png Binary files differnew file mode 100644 index 000000000..eacbcd255 --- /dev/null +++ b/java/res/drawable-hdpi/ic_subtype_mic_dark.png diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_background_klp.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_background_klp.9.png Binary files differindex be394151a..50ed568ff 100644 --- a/java/res/drawable-hdpi/keyboard_key_feedback_background_klp.9.png +++ b/java/res/drawable-hdpi/keyboard_key_feedback_background_klp.9.png diff --git a/java/res/drawable-hdpi/sym_keyboard_settings_holo_dark.png b/java/res/drawable-hdpi/sym_keyboard_settings_holo_dark.png Binary files differindex 2ea4a74a5..5af09ad8c 100644 --- a/java/res/drawable-hdpi/sym_keyboard_settings_holo_dark.png +++ b/java/res/drawable-hdpi/sym_keyboard_settings_holo_dark.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_normal.9.png b/java/res/drawable-mdpi/btn_keyboard_key_normal.9.png Binary files differnew file mode 100644 index 000000000..12bc97928 --- /dev/null +++ b/java/res/drawable-mdpi/btn_keyboard_key_normal.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png b/java/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png Binary files differnew file mode 100644 index 000000000..44bd414a1 --- /dev/null +++ b/java/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png b/java/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png Binary files differnew file mode 100644 index 000000000..43fdf5b88 --- /dev/null +++ b/java/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_pressed.9.png b/java/res/drawable-mdpi/btn_keyboard_key_pressed.9.png Binary files differnew file mode 100644 index 000000000..1c1f3d711 --- /dev/null +++ b/java/res/drawable-mdpi/btn_keyboard_key_pressed.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png b/java/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png Binary files differnew file mode 100644 index 000000000..dacb675a9 --- /dev/null +++ b/java/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png b/java/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png Binary files differnew file mode 100644 index 000000000..3daa69f31 --- /dev/null +++ b/java/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png diff --git a/java/res/drawable-mdpi/ic_launcher_keyboard.png b/java/res/drawable-mdpi/ic_launcher_keyboard.png Binary files differdeleted file mode 100644 index cc73f3be1..000000000 --- a/java/res/drawable-mdpi/ic_launcher_keyboard.png +++ /dev/null diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_background_klp.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_background_klp.9.png Binary files differindex 625490b1f..564f5460c 100644 --- a/java/res/drawable-mdpi/keyboard_key_feedback_background_klp.9.png +++ b/java/res/drawable-mdpi/keyboard_key_feedback_background_klp.9.png diff --git a/java/res/drawable-mdpi/sym_keyboard_label_mic_holo_dark.png b/java/res/drawable-mdpi/sym_keyboard_label_mic_holo_dark.png Binary files differnew file mode 100644 index 000000000..537f39b02 --- /dev/null +++ b/java/res/drawable-mdpi/sym_keyboard_label_mic_holo_dark.png diff --git a/java/res/drawable-mdpi/sym_keyboard_mic_holo_light.png b/java/res/drawable-mdpi/sym_keyboard_mic_holo_light.png Binary files differnew file mode 100644 index 000000000..84a63dc7f --- /dev/null +++ b/java/res/drawable-mdpi/sym_keyboard_mic_holo_light.png diff --git a/java/res/drawable-mdpi/sym_keyboard_settings_holo_dark.png b/java/res/drawable-mdpi/sym_keyboard_settings_holo_dark.png Binary files differindex 613f4dc88..36c8c9623 100644 --- a/java/res/drawable-mdpi/sym_keyboard_settings_holo_dark.png +++ b/java/res/drawable-mdpi/sym_keyboard_settings_holo_dark.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_normal.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_normal.9.png Binary files differnew file mode 100644 index 000000000..026005d6f --- /dev/null +++ b/java/res/drawable-xhdpi/btn_keyboard_key_normal.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png Binary files differnew file mode 100644 index 000000000..38c5f244b --- /dev/null +++ b/java/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png Binary files differnew file mode 100644 index 000000000..f1223e50e --- /dev/null +++ b/java/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png Binary files differnew file mode 100644 index 000000000..ec35db54d --- /dev/null +++ b/java/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png Binary files differnew file mode 100644 index 000000000..bd30464d6 --- /dev/null +++ b/java/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png Binary files differnew file mode 100644 index 000000000..a3ff5d1bb --- /dev/null +++ b/java/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png diff --git a/java/res/drawable-xhdpi/ic_launcher_keyboard.png b/java/res/drawable-xhdpi/ic_launcher_keyboard.png Binary files differdeleted file mode 100644 index f2ac50dfe..000000000 --- a/java/res/drawable-xhdpi/ic_launcher_keyboard.png +++ /dev/null diff --git a/java/res/drawable-xhdpi/ic_subtype_mic_dark.png b/java/res/drawable-xhdpi/ic_subtype_mic_dark.png Binary files differnew file mode 100644 index 000000000..17581ba89 --- /dev/null +++ b/java/res/drawable-xhdpi/ic_subtype_mic_dark.png diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_background_klp.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_background_klp.9.png Binary files differindex c211d89c8..e8c65f677 100644 --- a/java/res/drawable-xhdpi/keyboard_key_feedback_background_klp.9.png +++ b/java/res/drawable-xhdpi/keyboard_key_feedback_background_klp.9.png diff --git a/java/res/drawable-xhdpi/sym_keyboard_settings_holo_dark.png b/java/res/drawable-xhdpi/sym_keyboard_settings_holo_dark.png Binary files differindex 15a97394e..99ee97dbf 100644 --- a/java/res/drawable-xhdpi/sym_keyboard_settings_holo_dark.png +++ b/java/res/drawable-xhdpi/sym_keyboard_settings_holo_dark.png diff --git a/java/res/drawable-xxhdpi/ic_launcher_keyboard.png b/java/res/drawable-xxhdpi/ic_launcher_keyboard.png Binary files differdeleted file mode 100644 index df386e827..000000000 --- a/java/res/drawable-xxhdpi/ic_launcher_keyboard.png +++ /dev/null diff --git a/java/res/drawable-xxhdpi/ic_subtype_mic_dark.png b/java/res/drawable-xxhdpi/ic_subtype_mic_dark.png Binary files differnew file mode 100644 index 000000000..811103a56 --- /dev/null +++ b/java/res/drawable-xxhdpi/ic_subtype_mic_dark.png diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_background_klp.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_background_klp.9.png Binary files differindex fd2f9e514..11eee94f3 100644 --- a/java/res/drawable-xxhdpi/keyboard_key_feedback_background_klp.9.png +++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_background_klp.9.png diff --git a/java/res/drawable-xxhdpi/sym_keyboard_settings_holo_dark.png b/java/res/drawable-xxhdpi/sym_keyboard_settings_holo_dark.png Binary files differindex bf643e1d8..7041bb6ce 100644 --- a/java/res/drawable-xxhdpi/sym_keyboard_settings_holo_dark.png +++ b/java/res/drawable-xxhdpi/sym_keyboard_settings_holo_dark.png diff --git a/java/res/drawable/btn_keyboard_spacebar_gb.xml b/java/res/drawable/btn_keyboard_spacebar_gb.xml deleted file mode 100644 index 4d51f3c9c..000000000 --- a/java/res/drawable/btn_keyboard_spacebar_gb.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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 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. ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_pressed="true" - android:drawable="@drawable/btn_keyboard_key_light_pressed" /> - <item android:drawable="@drawable/btn_keyboard_key_light_normal" /> -</selector> diff --git a/java/res/drawable/btn_keyboard_spacebar_ics.xml b/java/res/drawable/btn_keyboard_spacebar_ics.xml deleted file mode 100644 index 4530ea079..000000000 --- a/java/res/drawable/btn_keyboard_spacebar_ics.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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 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. ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_pressed="true" - android:drawable="@drawable/btn_keyboard_key_light_pressed_ics" /> - <item android:drawable="@drawable/btn_keyboard_key_light_normal_holo" /> -</selector> diff --git a/java/res/drawable/btn_keyboard_spacebar_klp.xml b/java/res/drawable/btn_keyboard_spacebar_klp.xml deleted file mode 100644 index 6b07a392f..000000000 --- a/java/res/drawable/btn_keyboard_spacebar_klp.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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 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. ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_pressed="true" - android:drawable="@drawable/btn_keyboard_key_light_pressed_klp" /> - <item android:drawable="@drawable/btn_keyboard_key_light_normal_holo" /> -</selector> diff --git a/java/res/layout/emoji_keyboard_page.xml b/java/res/layout/emoji_keyboard_page.xml index 9afad366a..e0b752b32 100644 --- a/java/res/layout/emoji_keyboard_page.xml +++ b/java/res/layout/emoji_keyboard_page.xml @@ -18,9 +18,16 @@ */ --> -<com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView +<com.android.inputmethod.keyboard.internal.ScrollViewWithNotifier xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/emoji_keyboard_page" - android:layoutDirection="ltr" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> + android:id="@+id/emoji_keyboard_scroller" + android:clipToPadding="false" + android:layout_width="match_parent" + android:layout_height="match_parent" +> + <com.android.inputmethod.keyboard.internal.ScrollKeyboardView + android:id="@+id/emoji_keyboard_page" + android:layoutDirection="ltr" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> +</com.android.inputmethod.keyboard.internal.ScrollViewWithNotifier> diff --git a/java/res/layout/emoji_palettes_view.xml b/java/res/layout/emoji_palettes_view.xml index b25285967..1c6da90ba 100644 --- a/java/res/layout/emoji_palettes_view.xml +++ b/java/res/layout/emoji_palettes_view.xml @@ -29,7 +29,7 @@ <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" - android:layout_height="@dimen/config_suggestions_strip_height" + android:layout_height="@dimen/suggestions_strip_height" > <TabHost android:id="@+id/emoji_category_tabhost" @@ -73,7 +73,7 @@ android:background="@color/emoji_key_background_color" android:src="@drawable/sym_keyboard_delete_holo_dark" /> </LinearLayout> - <com.android.inputmethod.keyboard.internal.CustomViewPager + <android.support.v4.view.ViewPager android:id="@+id/emoji_keyboard_pager" android:layout_width="match_parent" android:layout_height="wrap_content" /> diff --git a/java/res/layout/hint_add_to_dictionary.xml b/java/res/layout/hint_add_to_dictionary.xml index d42908260..68a9faf19 100644 --- a/java/res/layout/hint_add_to_dictionary.xml +++ b/java/res/layout/hint_add_to_dictionary.xml @@ -23,7 +23,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" - android:textSize="@dimen/config_suggestion_text_size" + android:textSize="@dimen/suggestion_text_size" android:gravity="center" android:paddingLeft="0dp" android:paddingTop="0dp" diff --git a/java/res/layout/input_view.xml b/java/res/layout/input_view.xml index ed387e5b2..1e7a3844e 100644 --- a/java/res/layout/input_view.xml +++ b/java/res/layout/input_view.xml @@ -41,10 +41,10 @@ android:id="@+id/suggestion_strip_view" android:layoutDirection="ltr" android:layout_width="match_parent" - android:layout_height="@dimen/config_suggestions_strip_height" + android:layout_height="@dimen/suggestions_strip_height" android:gravity="center_vertical" - android:paddingRight="@dimen/config_suggestions_strip_horizontal_padding" - android:paddingLeft="@dimen/config_suggestions_strip_horizontal_padding" + android:paddingRight="@dimen/suggestions_strip_padding" + android:paddingLeft="@dimen/suggestions_strip_padding" style="?attr/suggestionStripViewStyle" /> <!-- To ensure that key preview popup is correctly placed when the current system locale is diff --git a/java/res/values-sw768dp/config-screen-metrics.xml b/java/res/layout/key_preview_gb.xml index c555cbb9f..2f2a321a3 100644 --- a/java/res/values-sw768dp/config-screen-metrics.xml +++ b/java/res/layout/key_preview_gb.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2013, The Android Open Source Project +** Copyright 2010, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -18,12 +18,10 @@ */ --> -<resources> - <!-- Screen metrics for logging. - 0 = "small phone screen" - 1 = "large phone screen" - 2 = "large tablet screen" - 3 = "small tablet screen" - --> - <integer name="log_screen_metrics">2</integer> -</resources> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@drawable/keyboard_key_feedback_gb" + android:minWidth="32dp" + android:gravity="center" +/> diff --git a/java/res/layout/key_preview.xml b/java/res/layout/key_preview_ics.xml index 16d4c72c3..33b6947ef 100644 --- a/java/res/layout/key_preview.xml +++ b/java/res/layout/key_preview_ics.xml @@ -21,7 +21,7 @@ <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:background="@drawable/keyboard_key_feedback_ics" android:minWidth="32dp" android:gravity="center" - style="?attr/keyPreviewTextViewStyle" /> diff --git a/java/res/values/config-spellchecker-thresholds.xml b/java/res/layout/key_preview_klp.xml index e99ba6621..160aeb9a9 100644 --- a/java/res/values/config-spellchecker-thresholds.xml +++ b/java/res/layout/key_preview_klp.xml @@ -18,8 +18,10 @@ */ --> -<resources> - <!-- Threshold of the normalized score of the best suggestion for the spell checker to declare - a word to be "recommended" --> - <string name="spellchecker_recommended_threshold_value" translatable="false">0.11</string> -</resources> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@drawable/keyboard_key_feedback_klp" + android:minWidth="32dp" + android:gravity="center" +/> diff --git a/java/res/layout/more_keys_keyboard.xml b/java/res/layout/more_keys_keyboard.xml index f3795afdc..6637117e0 100644 --- a/java/res/layout/more_keys_keyboard.xml +++ b/java/res/layout/more_keys_keyboard.xml @@ -22,9 +22,11 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:orientation="vertical" + android:orientation="horizontal" + style="?attr/moreKeysKeyboardContainerStyle" > <com.android.inputmethod.keyboard.MoreKeysKeyboardView + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" android:id="@+id/more_keys_keyboard_view" android:layout_width="wrap_content" android:layout_height="wrap_content" /> diff --git a/java/res/layout/more_suggestions.xml b/java/res/layout/more_suggestions.xml index 0869992c9..8659f0761 100644 --- a/java/res/layout/more_suggestions.xml +++ b/java/res/layout/more_suggestions.xml @@ -22,15 +22,16 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:orientation="vertical" + android:orientation="horizontal" + style="?attr/moreKeysKeyboardContainerStyle" > <com.android.inputmethod.latin.suggestions.MoreSuggestionsView xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" android:id="@+id/more_suggestions_view" android:layout_width="wrap_content" android:layout_height="wrap_content" - latin:keyLetterSize="@dimen/config_suggestion_text_size" - latin:keyLabelSize="@dimen/config_suggestion_text_size" - latin:keyHintLetterRatio="@fraction/config_more_suggestions_info_ratio" + latin:keyLetterSize="@dimen/suggestion_text_size" + latin:keyLabelSize="@dimen/suggestion_text_size" + latin:keyHintLetterRatio="@fraction/more_suggestions_info_ratio" latin:keyHintLetterColor="@android:color/white" /> </LinearLayout> diff --git a/java/res/layout/suggestion_word.xml b/java/res/layout/suggestion_word.xml index 47d2bd864..c82a13c99 100644 --- a/java/res/layout/suggestion_word.xml +++ b/java/res/layout/suggestion_word.xml @@ -24,12 +24,12 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" - android:minWidth="@dimen/config_suggestion_min_width" - android:textSize="@dimen/config_suggestion_text_size" + android:minWidth="@dimen/suggestion_min_width" + android:textSize="@dimen/suggestion_text_size" android:gravity="center" - android:paddingLeft="@dimen/config_suggestion_text_horizontal_padding" + android:paddingLeft="@dimen/suggestion_padding" android:paddingTop="0dp" - android:paddingRight="@dimen/config_suggestion_text_horizontal_padding" + android:paddingRight="@dimen/suggestion_padding" android:paddingBottom="0dp" android:hapticFeedbackEnabled="false" android:focusable="false" diff --git a/java/res/layout/user_dictionary_add_word.xml b/java/res/layout/user_dictionary_add_word.xml index 607f5c4a8..bbf9b1b5b 100644 --- a/java/res/layout/user_dictionary_add_word.xml +++ b/java/res/layout/user_dictionary_add_word.xml @@ -52,7 +52,7 @@ android:hint="@string/user_dict_settings_add_word_hint" android:imeOptions="flagNoFullscreen" android:inputType="textNoSuggestions" - android:maxLength="@integer/config_user_dictionary_max_word_length" > + android:maxLength="@integer/user_dictionary_max_word_length" > <requestFocus /> </EditText> diff --git a/java/res/layout/user_dictionary_add_word_fullscreen.xml b/java/res/layout/user_dictionary_add_word_fullscreen.xml index 9bcb189b4..219485b66 100644 --- a/java/res/layout/user_dictionary_add_word_fullscreen.xml +++ b/java/res/layout/user_dictionary_add_word_fullscreen.xml @@ -30,7 +30,7 @@ android:hint="@string/user_dict_settings_add_word_hint" android:imeOptions="flagNoFullscreen" android:inputType="textNoSuggestions" - android:maxLength="@integer/config_user_dictionary_max_word_length" > + android:maxLength="@integer/user_dictionary_max_word_length" > <requestFocus /> </EditText> @@ -61,7 +61,7 @@ android:hint="@string/user_dict_settings_add_shortcut_hint" android:imeOptions="flagNoFullscreen" android:inputType="textNoSuggestions" - android:maxLength="@integer/config_user_dictionary_max_word_length" /> + android:maxLength="@integer/user_dictionary_max_word_length" /> <TextView android:id="@+id/user_dictionary_add_locale_label" diff --git a/java/res/mipmap-hdpi/ic_launcher_keyboard.png b/java/res/mipmap-hdpi/ic_launcher_keyboard.png Binary files differnew file mode 100644 index 000000000..36b1ccae2 --- /dev/null +++ b/java/res/mipmap-hdpi/ic_launcher_keyboard.png diff --git a/java/res/mipmap-mdpi/ic_launcher_keyboard.png b/java/res/mipmap-mdpi/ic_launcher_keyboard.png Binary files differnew file mode 100644 index 000000000..67ef189ff --- /dev/null +++ b/java/res/mipmap-mdpi/ic_launcher_keyboard.png diff --git a/java/res/mipmap-xhdpi/ic_launcher_keyboard.png b/java/res/mipmap-xhdpi/ic_launcher_keyboard.png Binary files differnew file mode 100644 index 000000000..b33208332 --- /dev/null +++ b/java/res/mipmap-xhdpi/ic_launcher_keyboard.png diff --git a/java/res/mipmap-xxhdpi/ic_launcher_keyboard.png b/java/res/mipmap-xxhdpi/ic_launcher_keyboard.png Binary files differnew file mode 100644 index 000000000..acc424fe2 --- /dev/null +++ b/java/res/mipmap-xxhdpi/ic_launcher_keyboard.png diff --git a/java/res/raw/main_de.dict b/java/res/raw/main_de.dict Binary files differindex c65698d7b..69796bbaa 100644 --- a/java/res/raw/main_de.dict +++ b/java/res/raw/main_de.dict diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml index 9607ceb4c..045e97d94 100644 --- a/java/res/values-af/strings.xml +++ b/java/res/values-af/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"tyd"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Steminvoerinstellings"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Op hoofsleutelbord"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Op simbolesleutelbord"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Af"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofoon op hoofsleutelbord"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofoon op simbolesleutelbord"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Steminvoer is gedeaktiveer"</string> <string name="configure_input_method" msgid="373356270290742459">"Stel invoermetodes op"</string> <string name="language_selection_title" msgid="1651299598555326750">"Invoertale"</string> <string name="send_feedback" msgid="1780431884109392046">"Stuur terugvoer"</string> diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml index d131e340c..0b81034f4 100644 --- a/java/res/values-am/strings.xml +++ b/java/res/values-am/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"ጊዜ"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"ዩ አር ኤል"</string> <string name="voice_input" msgid="3583258583521397548">"የድምፅ ግቤት ቁልፍ"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"በዋናቁልፍ ሰሌዳ ላይ"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"በምልክቶች ቁልፍ ሰሌዳ ላይ"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"ውጪ"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"ድምፅ ማጉያ በዋናው ቁልፍሰሌዳው ላይ"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"የድምፅ ማጉያ ምልክትበቁልፍ ሰሌዳላይ"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"የድምፅ ግቤት ቦዝኗል"</string> <string name="configure_input_method" msgid="373356270290742459">"ግቤት ሜተዶችን አዋቀር"</string> <string name="language_selection_title" msgid="1651299598555326750">"ቋንቋዎች አግቤት"</string> <string name="send_feedback" msgid="1780431884109392046">"ግብረ-መልስ ላክ"</string> diff --git a/java/res/values-ar/config-spacing-and-punctuations.xml b/java/res/values-ar/donottranslate.xml index 9e637e458..57de2538b 100644 --- a/java/res/values-ar/config-spacing-and-punctuations.xml +++ b/java/res/values-ar/donottranslate.xml @@ -21,5 +21,5 @@ <!-- The all letters need to be mirrored are found at http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt --> <!-- Symbols that are suggested between words --> - <string name="suggested_punctuations" translatable="false">!,?,\\,,:,;,\",(|),)|(,\',-,/,@,_</string> + <string name="suggested_punctuations">!,?,\\,,:,;,\",(|),)|(,\',-,/,@,_</string> </resources> diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml index 226936b14..da331196c 100644 --- a/java/res/values-ar/strings.xml +++ b/java/res/values-ar/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"الوقت"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"عنوان URL"</string> <string name="voice_input" msgid="3583258583521397548">"مفتاح الإدخال الصوتي"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"لوحة مفاتيح رئيسية"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"لوحة مفاتيح الرموز"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"إيقاف"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"ميكروفون على لوحة مفاتيح رئيسية"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"ميكروفون على لوحة مفاتيح الرموز"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"الإدخال الصوتي مُعطل"</string> <string name="configure_input_method" msgid="373356270290742459">"تهيئة طرق الإدخال"</string> <string name="language_selection_title" msgid="1651299598555326750">"لغات الإدخال"</string> <string name="send_feedback" msgid="1780431884109392046">"إرسال تعليقات"</string> diff --git a/java/res/values-be-rBY/bools.xml b/java/res/values-be/bools.xml index 840d20c21..840d20c21 100644 --- a/java/res/values-be-rBY/bools.xml +++ b/java/res/values-be/bools.xml diff --git a/java/res/values-be-rBY/strings-action-keys.xml b/java/res/values-be/strings-action-keys.xml index 91416c8b7..91416c8b7 100644 --- a/java/res/values-be-rBY/strings-action-keys.xml +++ b/java/res/values-be/strings-action-keys.xml diff --git a/java/res/values-be/strings-appname.xml b/java/res/values-be/strings-appname.xml new file mode 100644 index 000000000..2f9593bdc --- /dev/null +++ b/java/res/values-be/strings-appname.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** +** Copyright 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 the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="english_ime_name" msgid="5940510615957428904">"Клавіятура Android (AOSP)"</string> + <string name="spell_checker_service_name" msgid="1254221805440242662">"Iнструмент праверкi правапiсу для Android (AOSP)"</string> + <string name="english_ime_settings" msgid="5760361067176802794">"Налады клавіятуры Android (AOSP)"</string> + <string name="android_spell_checker_settings" msgid="6123949487832861885">"Налады інструмента праверкі правапісу для Android (AOSP)"</string> +</resources> diff --git a/java/res/values-be/strings.xml b/java/res/values-be/strings.xml new file mode 100644 index 000000000..02972f07e --- /dev/null +++ b/java/res/values-be/strings.xml @@ -0,0 +1,253 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** +** Copyright 2008, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="english_ime_input_options" msgid="3909945612939668554">"Параметры ўводу"</string> + <string name="english_ime_research_log" msgid="8492602295696577851">"Каманды гiсторыя даследаванняў"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Шукаць імёны кантактаў"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Модуль праверкі правапісу выкарыстоўвае запісы са спісу кантактаў"</string> + <string name="vibrate_on_keypress" msgid="5258079494276955460">"Вібрацыя пры націску клавіш"</string> + <string name="sound_on_keypress" msgid="6093592297198243644">"Гук пры націску"</string> + <string name="popup_on_keypress" msgid="123894815723512944">"Па націску на клавішы ўсплывае акно"</string> + <string name="general_category" msgid="1859088467017573195">"Агульныя"</string> + <string name="correction_category" msgid="2236750915056607613">"Выпраўленне тэксту"</string> + <string name="gesture_typing_category" msgid="497263612130532630">"Набор жэстамі"</string> + <string name="misc_category" msgid="6894192814868233453">"Іншыя параметры"</string> + <string name="advanced_settings" msgid="362895144495591463">"Адмысловыя налады"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Функцыi для спецыялістаў"</string> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Перакл. да інш. спос. ув."</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Кнопка пераключэння мовы звязана i з iншымi спосабамi ўводу"</string> + <string name="show_language_switch_key" msgid="5915478828318774384">"Кнопка пераключэння мовы"</string> + <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Паказваць, калі ўключана некалькі моў ўводу"</string> + <string name="sliding_key_input_preview" msgid="6604262359510068370">"Iндыкатар слайд-шоу"</string> + <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Паказаць візуальны сігнал падчас слiзгання клавiш Shift або Symbol"</string> + <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> + <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g> мс"</string> + <!-- no translation found for settings_system_default (6268225104743331821) --> + <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> + <string name="use_double_space_period_summary" msgid="6532892187247952799">"Падвойнае нацiсканне на прабел ўстаўляе iнтэрвал з наступным прабелам"</string> + <string name="auto_cap" msgid="1719746674854628252">"Аўтаматычна рабіць вялікія літары"</string> + <string name="auto_cap_summary" msgid="7934452761022946874">"Пісаць з загалоўнай літары першае слова ў кожным сказе"</string> + <string name="edit_personal_dictionary" msgid="3996910038952940420">"Персанальны слоўнік"</string> + <string name="configure_dictionaries_title" msgid="4238652338556902049">"Дадатковыя слоўнікі"</string> + <string name="main_dictionary" msgid="4798763781818361168">"Асноўны слоўнік"</string> + <string name="prefs_show_suggestions" msgid="8026799663445531637">"Паказаць прапановы на выпраўленне"</string> + <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Паказваць прапанаваныя словы падчас набору тэксту"</string> + <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Заўсёды паказваць"</string> + <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Паказаць у партрэтным рэжыме"</string> + <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Заўседы хаваць"</string> + <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Блакіраваць абразлівыя словы"</string> + <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Не прапануйце патэнцыяльна абразлівых слоў"</string> + <string name="auto_correction" msgid="7630720885194996950">"Аўтавыпраўленне"</string> + <string name="auto_correction_summary" msgid="5625751551134658006">"Прабелы і пунктуацыйныя знакі дазваляюць аўтаматычна выпраўляць памылкова ўведзеныя словы"</string> + <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Адключаны"</string> + <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Сціплы"</string> + <!-- no translation found for auto_correction_threshold_mode_aggressive (7319007299148899623) --> + <skip /> + <!-- no translation found for auto_correction_threshold_mode_very_aggressive (1853309024129480416) --> + <skip /> + <string name="bigram_prediction" msgid="1084449187723948550">"Падказкi для наступнага слова"</string> + <string name="bigram_prediction_summary" msgid="3896362682751109677">"Выкарыстоўваць папярэдняе слова, каб атрымлiваць падказкi"</string> + <string name="gesture_input" msgid="826951152254563827">"Уключыць набор жэстамі"</string> + <string name="gesture_input_summary" msgid="9180350639305731231">"Уводзьце слова, перасоўваючы палец па літарах"</string> + <string name="gesture_preview_trail" msgid="3802333369335722221">"Паказаць след жэста"</string> + <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Дынамічны плаваючы прагляд"</string> + <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Праглядаць прапанаванае слова падчас жэсту"</string> + <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Захаваныя"</string> + <string name="spoken_use_headphones" msgid="896961781287283493">"Каб праслухаць паролi, падключыце гарнiтуру."</string> + <string name="spoken_current_text_is" msgid="2485723011272583845">"Бягучы тэкст %s"</string> + <string name="spoken_no_text_entered" msgid="7479685225597344496">"Тэкст не ўведзены"</string> + <!-- no translation found for spoken_auto_correct (8005997889020109763) --> + <skip /> + <!-- no translation found for spoken_auto_correct_obscured (6276420476908833791) --> + <skip /> + <string name="spoken_description_unknown" msgid="3197434010402179157">"Клавішны код %d"</string> + <string name="spoken_description_shift" msgid="244197883292549308">"Зрух"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift уключаны (націснiце, каб адключыць)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock уключаны (націснiце, каб адключыць)"</string> + <string name="spoken_description_delete" msgid="8740376944276199801">"Выдаліць"</string> + <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Сімвалы"</string> + <string name="spoken_description_to_alpha" msgid="23129338819771807">"Літары"</string> + <string name="spoken_description_to_numeric" msgid="591752092685161732">"Лічбы"</string> + <string name="spoken_description_settings" msgid="4627462689603838099">"Налады"</string> + <string name="spoken_description_tab" msgid="2667716002663482248">"Укладка"</string> + <string name="spoken_description_space" msgid="2582521050049860859">"Прабел"</string> + <string name="spoken_description_mic" msgid="615536748882611950">"Галасавы ўвод"</string> + <string name="spoken_description_smiley" msgid="2256309826200113918">"Смайлік"</string> + <string name="spoken_description_return" msgid="8178083177238315647">"Увод"</string> + <string name="spoken_description_search" msgid="1247236163755920808">"Пошук"</string> + <string name="spoken_description_dot" msgid="40711082435231673">"Кропка"</string> + <string name="spoken_description_language_switch" msgid="5507091328222331316">"Пераключыць мову"</string> + <string name="spoken_description_action_next" msgid="8636078276664150324">"Далей"</string> + <string name="spoken_description_action_previous" msgid="800872415009336208">"Назад"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift уключаны"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock уключаны"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift адключаны"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Рэжым знакаў"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Рэжым лiтар"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Рэжым тэлефона"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Рэжым тэлефонных знакаў"</string> + <string name="announce_keyboard_hidden" msgid="8718927835531429807">"Клавіятура схавана"</string> + <string name="announce_keyboard_mode" msgid="4729081055438508321">"Паказана клавiятура ў рэжыме \" <xliff:g id="MODE">%s</xliff:g>\""</string> + <string name="keyboard_mode_date" msgid="3137520166817128102">"дата"</string> + <string name="keyboard_mode_date_time" msgid="339593358488851072">"дата i час"</string> + <string name="keyboard_mode_email" msgid="6216248078128294262">"электронная пошта"</string> + <string name="keyboard_mode_im" msgid="1137405089766557048">"абмен паведамленнямі"</string> + <string name="keyboard_mode_number" msgid="7991623440699957069">"нумар"</string> + <string name="keyboard_mode_phone" msgid="6851627527401433229">"тэлефон"</string> + <string name="keyboard_mode_text" msgid="6479436687899701619">"тэкст"</string> + <string name="keyboard_mode_time" msgid="4381856885582143277">"час"</string> + <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> + <string name="voice_input" msgid="3583258583521397548">"Ключ галасавога ўводу"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"На асн. клавіятуры"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"На сімв. клавіятуры"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Адключана"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Мік. на асн. клав."</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Мік. на сімв. клав."</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Галасавы набор адкл."</string> + <string name="configure_input_method" msgid="373356270290742459">"Налада метадаў уводу"</string> + <string name="language_selection_title" msgid="1651299598555326750">"Мовы ўводу"</string> + <string name="send_feedback" msgid="1780431884109392046">"Адправіць водгук"</string> + <string name="select_language" msgid="3693815588777926848">"Мовы ўводу"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Дакраніцеся зноў, каб захаваць"</string> + <string name="has_dictionary" msgid="6071847973466625007">"Слоўнік даступны"</string> + <string name="prefs_enable_log" msgid="6620424505072963557">"Уключыць зваротную сувязь з карыстальнікамі"</string> + <string name="prefs_description_log" msgid="7525225584555429211">"Дапамажыце палепшыць гэты рэдактар метаду ўводу, аўтаматычна адпраўляючы статыстыку выкарыстання і справаздачы аб збоях Google."</string> + <string name="keyboard_layout" msgid="8451164783510487501">"Тэма клавіятуры"</string> + <string name="subtype_en_GB" msgid="88170601942311355">"Англійская (ЗК)"</string> + <string name="subtype_en_US" msgid="6160452336634534239">"Англійская (ЗША)"</string> + <string name="subtype_es_US" msgid="5583145191430180200">"iспанская (ЗША)"</string> + <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Англійская (Вялікабрытанія) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string> + <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Англійская (ЗША) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string> + <string name="subtype_with_layout_es_US" msgid="6261791057007890189">"iспанская (ЗША) ( <xliff:g id="LAYOUT">%s</xliff:g> )"</string> + <!-- no translation found for subtype_nepali_traditional (9032247506728040447) --> + <skip /> + <!-- no translation found for subtype_no_language (7137390094240139495) --> + <skip /> + <!-- no translation found for subtype_no_language_qwerty (244337630616742604) --> + <skip /> + <!-- no translation found for subtype_no_language_qwertz (443066912507547976) --> + <skip /> + <!-- no translation found for subtype_no_language_azerty (8144348527575640087) --> + <skip /> + <!-- no translation found for subtype_no_language_dvorak (1564494667584718094) --> + <skip /> + <!-- no translation found for subtype_no_language_colemak (5837418400010302623) --> + <skip /> + <!-- no translation found for subtype_no_language_pcqwerty (5354918232046200018) --> + <skip /> + <!-- no translation found for subtype_emoji (7483586578074549196) --> + <skip /> + <string name="custom_input_styles_title" msgid="8429952441821251512">"Карыстальніцкія стылі ўводу"</string> + <string name="add_style" msgid="6163126614514489951">"Дадаць стыль"</string> + <string name="add" msgid="8299699805688017798">"Дадаць"</string> + <string name="remove" msgid="4486081658752944606">"Выдаліць"</string> + <string name="save" msgid="7646738597196767214">"Захаваць"</string> + <string name="subtype_locale" msgid="8576443440738143764">"Мова"</string> + <string name="keyboard_layout_set" msgid="4309233698194565609">"Раскладка"</string> + <string name="custom_input_style_note_message" msgid="8826731320846363423">"Карыстальніцкі метад уводу павінен быць уключаны, перш чым пачаць выкарыстоўваць яго. Жадаеце ўключыць яго зараз?"</string> + <string name="enable" msgid="5031294444630523247">"Уключыць"</string> + <string name="not_now" msgid="6172462888202790482">"Не цяпер"</string> + <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Такі метад уводу ўжо існуе: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string> + <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Рэжым даследвання выкарыстальнасці"</string> + <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Затрымка доўгага націску клавішы"</string> + <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Працягласць вібрацыі пры націску клавіш"</string> + <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Гучнасць гуку пры націску клавіш"</string> + <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Чытанне знешняга файла слоўніка"</string> + <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"У папцы загрузак няма файлаў слоўніка"</string> + <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Вылучыце файл слоўніка для ўсталёўкі"</string> + <string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Сапраўды ўсталяваць гэты файл на мове: <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string> + <string name="error" msgid="8940763624668513648">"Была памылка"</string> + <string name="button_default" msgid="3988017840431881491">"Па змаўчанні"</string> + <string name="setup_welcome_title" msgid="6112821709832031715">"Вітаем у прыкладанні <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> + <string name="setup_welcome_additional_description" msgid="8150252008545768953">"з уводам жэстамі"</string> + <string name="setup_start_action" msgid="8936036460897347708">"Пачаць"</string> + <string name="setup_next_action" msgid="371821437915144603">"Далей"</string> + <string name="setup_steps_title" msgid="6400373034871816182">"Наладка прыкладання <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> + <string name="setup_step1_title" msgid="3147967630253462315">"Уключыць прыкладанне <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> + <string name="setup_step1_instruction" msgid="2578631936624637241">"Праверце прыкладанне \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" на сваёй мове і параметры ўводу. Гэта дасць магчымасць дазволіць яму працаваць на вашай прыладзе."</string> + <string name="setup_step1_finished_instruction" msgid="10761482004957994">"Прыкладанне <xliff:g id="APPLICATION_NAME">%s</xliff:g> ужо ўключана для вашай мовы і параметраў уводу, так што гэты крок зроблены. Пераходзім да наступнага!"</string> + <string name="setup_step1_action" msgid="4366513534999901728">"Уключыць у наладах"</string> + <string name="setup_step2_title" msgid="6860725447906690594">"Пераключыцца на прыкладанне <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string> + <string name="setup_step2_instruction" msgid="9141481964870023336">"Выберыце \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" як актыўны метад уводу тэксту."</string> + <string name="setup_step2_action" msgid="1660330307159824337">"Пераключэнне метадаў уводу"</string> + <string name="setup_step3_title" msgid="3154757183631490281">"Усё гатова!"</string> + <string name="setup_step3_instruction" msgid="8025981829605426000">"Цяпер вы можаце ўводзіць ўсе свае любімыя прыкладанні з iмем <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string> + <string name="setup_step3_action" msgid="600879797256942259">"Наладка дадатковых моў"</string> + <string name="setup_finish_action" msgid="276559243409465389">"Гатова"</string> + <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Паказаць значок прыкладання"</string> + <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Паказаць значок прыкладання ў панэлi запуску"</string> + <string name="app_name" msgid="6320102637491234792">"Пастаўшчык слоўніка"</string> + <string name="dictionary_provider_name" msgid="3027315045397363079">"Пастаўшчык слоўніка"</string> + <string name="dictionary_service_name" msgid="6237472350693511448">"Слоўнік"</string> + <string name="download_description" msgid="6014835283119198591">"Інфармацыя абнаўлення слоўніка"</string> + <string name="dictionary_settings_title" msgid="8091417676045693313">"Дадатковыя слоўнікі"</string> + <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Даступны слоўнік"</string> + <string name="dictionary_settings_summary" msgid="5305694987799824349">"Налады для слоўнікаў"</string> + <string name="user_dictionaries" msgid="3582332055892252845">"Карыстальніцкія слоўнікі"</string> + <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Карыстацкі слоўнік"</string> + <string name="dictionary_available" msgid="4728975345815214218">"Даступны слоўнік"</string> + <string name="dictionary_downloading" msgid="2982650524622620983">"Спампоўваецца зараз"</string> + <string name="dictionary_installed" msgid="8081558343559342962">"Усталявана"</string> + <string name="dictionary_disabled" msgid="8950383219564621762">"Усталявана, адключана"</string> + <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Праблема падключэння да слоўніка"</string> + <string name="no_dictionaries_available" msgid="8039920716566132611">"Слоўнікаў няма"</string> + <string name="check_for_updates_now" msgid="8087688440916388581">"Абнавіць"</string> + <string name="last_update" msgid="730467549913588780">"Апошняе абнаўленне"</string> + <string name="message_updating" msgid="4457761393932375219">"Праверка наяўнасці абнаўленняў"</string> + <string name="message_loading" msgid="8689096636874758814">"Загрузка..."</string> + <string name="main_dict_description" msgid="3072821352793492143">"Асноўны слоўнік"</string> + <string name="cancel" msgid="6830980399865683324">"Адмяніць"</string> + <string name="install_dict" msgid="180852772562189365">"Усталяваць"</string> + <string name="cancel_download_dict" msgid="7843340278507019303">"Адмена"</string> + <string name="delete_dict" msgid="756853268088330054">"Выдаліць"</string> + <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Для выбранай мовы на мабільнай прыладзе ёсць слоўнік.<br/> Мы рэкамендуем <b>спампаваць</b> слоўнік для мовы \"<xliff:g id="LANGUAGE">%1$s</xliff:g>\" для паляпшэння зручнасці набору.<br/> <br/> Спампоўка можа заняць хвіліну або дзве ў 3G-сетках. Калі ў вас няма <b>безлімітнага тарыфнага плану перадачы дадзеных</b>, могуць прымяняцца дадатковыя плацяжы<br/>. Калі вы не ведаеце дакладна, які ў вас тарыфны план, мы рэкамендуем знайсці падлучэнне да сеткі Wi-Fi, каб пачаць аўтаматычную спампоўку.<br/> <br/> Парада: можна спампоўваць і выдаляць слоўнікі, перайшоўшы ў раздзел <b>Мова і ўвод</b> у меню <b>Налады</b> вашай мабільнай прылады."</string> + <string name="download_over_metered" msgid="1643065851159409546">"Спампаваць зараз (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>МБ)"</string> + <string name="do_not_download_over_metered" msgid="2176209579313941583">"Спампаваць праз Wi-Fi"</string> + <string name="dict_available_notification_title" msgid="6514288591959117288">"Слоўнік для мовы \"<xliff:g id="LANGUAGE">%1$s</xliff:g>\""</string> + <string name="dict_available_notification_description" msgid="1075194169443163487">"Нацiснiце, каб прагледзець i спампаваць"</string> + <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Загрузка: прапановы для мовы \"<xliff:g id="LANGUAGE">%1$s</xliff:g>\" хутка з\'явяцца."</string> + <string name="version_text" msgid="2715354215568469385">"Версія <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string> + <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"Дадаць"</string> + <string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"Дадаць у слоўнік"</string> + <string name="user_dict_settings_add_screen_title" msgid="5818914331629278758">"Выраз"</string> + <string name="user_dict_settings_add_dialog_more_options" msgid="5671682004887093112">"Дадатковыя параметры"</string> + <string name="user_dict_settings_add_dialog_less_options" msgid="2716586567241724126">"Асн. параметры"</string> + <string name="user_dict_settings_add_dialog_confirm" msgid="4703129507388332950">"OК"</string> + <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"Слова:"</string> + <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"Шлях хуткага доступу:"</string> + <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"Мова:"</string> + <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"Увядзіце слова"</string> + <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"Дадатковы цэтлiк"</string> + <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"Рэдагаваць слова"</string> + <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"Рэдагаваць"</string> + <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"Выдаліць"</string> + <string name="user_dict_settings_empty_text" msgid="558499587532668203">"У вашым карыстальніцкім слоўніку няма ніводнага слова. Вы можаце дадаваць словы, дакранаючыся да кнопкі \"+\" у пункце меню \"Дадаць\"."</string> + <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"Для ўсіх моў"</string> + <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"Іншыя мовы..."</string> + <string name="user_dict_settings_delete" msgid="110413335187193859">"Выдаліць"</string> + <string name="user_dict_fast_scroll_alphabet" msgid="5431919401558285473">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> +</resources> diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml index 604c8d97c..c3fbd7982 100644 --- a/java/res/values-bg/strings.xml +++ b/java/res/values-bg/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"часа"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL адреси"</string> <string name="voice_input" msgid="3583258583521397548">"Клавиш за гласово въвеждане"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"На осн. клавиатура"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"На клав. на симв."</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Изкл."</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Микр. на осн. клав."</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Микр. на клав. на симв."</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Глас. въвежд. е деакт."</string> <string name="configure_input_method" msgid="373356270290742459">"Конфигуриране на въвеждането"</string> <string name="language_selection_title" msgid="1651299598555326750">"Входни езици"</string> <string name="send_feedback" msgid="1780431884109392046">"Изпращане на отзиви"</string> diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml index e4623da51..0b9ee037e 100644 --- a/java/res/values-ca/strings.xml +++ b/java/res/values-ca/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"hora"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Tecla d\'entrada de veu"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Al teclat principal"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Al teclat de símbols"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Desactivada"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micròfon al teclat principal"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micro en tecl. símb."</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entrada de veu desactivada"</string> <string name="configure_input_method" msgid="373356270290742459">"Configura mètodes d\'entrada"</string> <string name="language_selection_title" msgid="1651299598555326750">"Idiomes"</string> <string name="send_feedback" msgid="1780431884109392046">"Envia comentaris"</string> diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml index 4b883e35a..c73e8ab1c 100644 --- a/java/res/values-cs/strings.xml +++ b/java/res/values-cs/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"čas"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"adresy URL"</string> <string name="voice_input" msgid="3583258583521397548">"Klávesa hlasového vstupu"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na hlavní klávesnici"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na klávesnici se symboly"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Vypnuto"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon na hlavní klávesnici"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofon na klávesnici se symboly"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hlasový vstup vypnut"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigurace metod zadávání"</string> <string name="language_selection_title" msgid="1651299598555326750">"Vstupní jazyky"</string> <string name="send_feedback" msgid="1780431884109392046">"Odeslat zpětnou vazbu"</string> diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml index 33ac25b45..86bdad469 100644 --- a/java/res/values-da/strings.xml +++ b/java/res/values-da/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"klokkeslæt"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"Webadresse"</string> <string name="voice_input" msgid="3583258583521397548">"Nøgle til stemmeinput"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"På hovedtastatur"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"På symboltastatur"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Fra"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mik. på hovedtastatur"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik. på symboltastatur"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Stemmeinput deaktiveret"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigurer inputmetoder"</string> <string name="language_selection_title" msgid="1651299598555326750">"Inputsprog"</string> <string name="send_feedback" msgid="1780431884109392046">"Send feedback"</string> diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml index 563f4c277..b65053465 100644 --- a/java/res/values-de/strings.xml +++ b/java/res/values-de/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"Zeit"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Taste für Spracheingabe"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Auf Haupttastatur"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Auf Symboltastatur"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Aus"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikro auf Haupttastatur"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikro auf Symboltastatur"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Spracheingabe deaktiviert"</string> <string name="configure_input_method" msgid="373356270290742459">"Eingabemethoden konfigurieren"</string> <string name="language_selection_title" msgid="1651299598555326750">"Eingabesprachen"</string> <string name="send_feedback" msgid="1780431884109392046">"Feedback geben"</string> diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml index 138d64da5..79e83423c 100644 --- a/java/res/values-el/strings.xml +++ b/java/res/values-el/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"ώρα"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"διεύθυνση URL"</string> <string name="voice_input" msgid="3583258583521397548">"Κλειδί φωνητικής εξόδου"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Στο κύριο πληκτρολ."</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Πληκτρ. συμβ. ενερ."</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Απενεργοποίηση"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Μικ. στο κύριο πληκ."</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Μικ. στο πληκ. συμβ."</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Απεν. φωνητ. είσοδος"</string> <string name="configure_input_method" msgid="373356270290742459">"Διαμόρφωση μεθόδων εισαγωγής"</string> <string name="language_selection_title" msgid="1651299598555326750">"Γλώσσες εισόδου"</string> <string name="send_feedback" msgid="1780431884109392046">"Αποστολή σχολίων"</string> diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml index 56a8b90de..4bc1b15cf 100644 --- a/java/res/values-en-rGB/strings.xml +++ b/java/res/values-en-rGB/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"time"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Voice input key"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"On main keyboard"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"On symbols keyboard"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Off"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic on main keyboard"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic on symbols keyboard"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Voice input is disabled"</string> <string name="configure_input_method" msgid="373356270290742459">"Configure input methods"</string> <string name="language_selection_title" msgid="1651299598555326750">"Input languages"</string> <string name="send_feedback" msgid="1780431884109392046">"Send feedback"</string> diff --git a/java/res/values-en-rIN/strings.xml b/java/res/values-en-rIN/strings.xml index 56a8b90de..4bc1b15cf 100644 --- a/java/res/values-en-rIN/strings.xml +++ b/java/res/values-en-rIN/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"time"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Voice input key"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"On main keyboard"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"On symbols keyboard"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Off"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic on main keyboard"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic on symbols keyboard"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Voice input is disabled"</string> <string name="configure_input_method" msgid="373356270290742459">"Configure input methods"</string> <string name="language_selection_title" msgid="1651299598555326750">"Input languages"</string> <string name="send_feedback" msgid="1780431884109392046">"Send feedback"</string> diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml index e33bbd5a7..1fd9cf8f0 100644 --- a/java/res/values-es-rUS/strings.xml +++ b/java/res/values-es-rUS/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"hora"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Tecla de entrada por voz"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"En el teclado principal"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"En el teclado de símbolos"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Desactivado"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micrófono en el teclado principal"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micrófono en el teclado de símbolos"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"La entrada por voz está inhabilitada"</string> <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string> <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string> <string name="send_feedback" msgid="1780431884109392046">"Enviar comentarios"</string> diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml index 8240c89a5..39b45e0c4 100644 --- a/java/res/values-es/strings.xml +++ b/java/res/values-es/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"hora"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Tecla de entrada de voz"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"En teclado principal"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"En teclado de símbolos"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"No"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micrófono en teclado principal"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micrófono en teclado de símbolos"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entrada de voz inhabilitada"</string> <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string> <string name="language_selection_title" msgid="1651299598555326750">"Idiomas"</string> <string name="send_feedback" msgid="1780431884109392046">"Danos tu opinión"</string> diff --git a/java/res/values-et-rEE/strings.xml b/java/res/values-et-rEE/strings.xml index a01d5636c..e0f992c0d 100644 --- a/java/res/values-et-rEE/strings.xml +++ b/java/res/values-et-rEE/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"aeg"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Häälesisendi klahv"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Peamisel klaviatuuril"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Sümbolite klaviatuuril"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Väljas"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon peamisel klaviatuuril"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr. sümb. klaviat."</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Kõnesisend on keelatud"</string> <string name="configure_input_method" msgid="373356270290742459">"Sisestusmeetodite seadistamine"</string> <string name="language_selection_title" msgid="1651299598555326750">"Sisestuskeeled"</string> <string name="send_feedback" msgid="1780431884109392046">"Saatke tagasisidet"</string> diff --git a/java/res/values-fa/config-spacing-and-punctuations.xml b/java/res/values-fa/donottranslate.xml index 9e637e458..57de2538b 100644 --- a/java/res/values-fa/config-spacing-and-punctuations.xml +++ b/java/res/values-fa/donottranslate.xml @@ -21,5 +21,5 @@ <!-- The all letters need to be mirrored are found at http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt --> <!-- Symbols that are suggested between words --> - <string name="suggested_punctuations" translatable="false">!,?,\\,,:,;,\",(|),)|(,\',-,/,@,_</string> + <string name="suggested_punctuations">!,?,\\,,:,;,\",(|),)|(,\',-,/,@,_</string> </resources> diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml index 714dbc8fc..af886ef8c 100644 --- a/java/res/values-fa/strings.xml +++ b/java/res/values-fa/strings.xml @@ -121,6 +121,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"زمان"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"نشانی اینترنتی"</string> <string name="voice_input" msgid="3583258583521397548">"کلید ورودی صدا"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"در صفحهکلید اصلی"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"در صفحهکلید نمادها"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"خاموش"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"میکروفن در صفحهکلید اصلی"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"میکروفن در صفحهکلید نمادها"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"ورودی صدا غیرفعال است"</string> <string name="configure_input_method" msgid="373356270290742459">"پیکربندی روشهای ورودی"</string> <string name="language_selection_title" msgid="1651299598555326750">"زبانهای ورودی"</string> <string name="send_feedback" msgid="1780431884109392046">"ارسال بازخورد"</string> diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml index f623d1a1e..a58bfac3e 100644 --- a/java/res/values-fi/strings.xml +++ b/java/res/values-fi/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"aika"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL-osoite"</string> <string name="voice_input" msgid="3583258583521397548">"Äänisyöteavain"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Päänäppäimistössä"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Symbolinäppäim."</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Ei käytössä"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikr. päänäppäim."</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr. symbolinäpp."</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Äänisyöte ei käyt."</string> <string name="configure_input_method" msgid="373356270290742459">"Määritä syöttötavat"</string> <string name="language_selection_title" msgid="1651299598555326750">"Syöttökielet"</string> <string name="send_feedback" msgid="1780431884109392046">"Lähetä palautetta"</string> diff --git a/java/res/values-fr-rCA/config-spacing-and-punctuations.xml b/java/res/values-fr-rCA/donottranslate.xml index 06254800b..21f18d852 100644 --- a/java/res/values-fr-rCA/config-spacing-and-punctuations.xml +++ b/java/res/values-fr-rCA/donottranslate.xml @@ -20,12 +20,12 @@ <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- Symbols that are normally preceded by a space (used to add an auto-space before these) --> <!-- This is similar to French with the exception of "!" "?" and ";" which do not take a space before in Canadian French. Note that ":" does take a space before according to Canadian rules. --> - <string name="symbols_preceded_by_space" translatable="false">([{&:</string> + <string name="symbols_preceded_by_space">([{&:</string> <!-- Symbols that are normally followed by a space (used to add an auto-space after these) --> - <string name="symbols_followed_by_space" translatable="false">.,;:!?)]}&</string> + <string name="symbols_followed_by_space">.,;:!?)]}&</string> <!-- Symbols that separate words --> <!-- Don't remove the enclosing double quotes, they protect whitespace (not just U+0020) --> - <string name="symbols_word_separators" translatable="false">"	 \n"()[]{}*&<>+=|.,;:!?/_\"</string> + <string name="symbols_word_separators">"	 \n"()[]{}*&<>+=|.,;:!?/_\"</string> <!-- Word connectors --> - <string name="symbols_word_connectors" translatable="false">\'-</string> + <string name="symbols_word_connectors">\'-</string> </resources> diff --git a/java/res/values-fr-rCA/strings.xml b/java/res/values-fr-rCA/strings.xml index 8ff60f621..2551ce9f8 100644 --- a/java/res/values-fr-rCA/strings.xml +++ b/java/res/values-fr-rCA/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"Heure"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Touche de saisie vocale"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Sur le clavier principal"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Sur clavier symboles"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Désactiver"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micro sur le clavier principal"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micro sur le clavier des symboles"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Saisie vocale désactivée"</string> <string name="configure_input_method" msgid="373356270290742459">"Configurer les modes de saisie"</string> <string name="language_selection_title" msgid="1651299598555326750">"Langues de saisie"</string> <string name="send_feedback" msgid="1780431884109392046">"Envoyer des commentaires"</string> diff --git a/java/res/values-fr/config-spacing-and-punctuations.xml b/java/res/values-fr/donottranslate.xml index 33e0236b0..f0644118a 100644 --- a/java/res/values-fr/config-spacing-and-punctuations.xml +++ b/java/res/values-fr/donottranslate.xml @@ -19,12 +19,12 @@ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- Symbols that are normally preceded by a space (used to add an auto-space before these) --> - <string name="symbols_preceded_by_space" translatable="false">([{&;:!?</string> + <string name="symbols_preceded_by_space">([{&;:!?</string> <!-- Symbols that are normally followed by a space (used to add an auto-space after these) --> - <string name="symbols_followed_by_space" translatable="false">.,;:!?)]}&</string> + <string name="symbols_followed_by_space">.,;:!?)]}&</string> <!-- Symbols that separate words --> <!-- Don't remove the enclosing double quotes, they protect whitespace (not just U+0020) --> - <string name="symbols_word_separators" translatable="false">"	 \n"()[]{}*&<>+=|.,;:!?/_\"</string> + <string name="symbols_word_separators">"	 \n"()[]{}*&<>+=|.,;:!?/_\"</string> <!-- Word connectors --> - <string name="symbols_word_connectors" translatable="false">\'-</string> + <string name="symbols_word_connectors">\'-</string> </resources> diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml index 9ab95583d..b877db014 100644 --- a/java/res/values-fr/strings.xml +++ b/java/res/values-fr/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"Heure"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Touche de saisie vocale"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Sur clavier principal"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Sur clavier symboles"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Désactiver"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micro sur le clavier principal"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micro sur clavier symboles"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Saisie vocale désactivée"</string> <string name="configure_input_method" msgid="373356270290742459">"Configurer les modes de saisie"</string> <string name="language_selection_title" msgid="1651299598555326750">"Langues de saisie"</string> <string name="send_feedback" msgid="1780431884109392046">"Envoyer des commentaires"</string> diff --git a/java/res/values-h1200dp-port/setup-dimens-large-tablet-port.xml b/java/res/values-h1200dp-port/setup-dimens-large-tablet-port.xml index adc3e35a9..bc7928d6a 100644 --- a/java/res/values-h1200dp-port/setup-dimens-large-tablet-port.xml +++ b/java/res/values-h1200dp-port/setup-dimens-large-tablet-port.xml @@ -20,6 +20,7 @@ <dimen name="setup_welcome_description_text_size">38sp</dimen> <dimen name="setup_step_bullet_text_size">24sp</dimen> <dimen name="setup_step_triangle_indicator_height">24dp</dimen> + <dimen name="setup_step_indicator_height">24dp</dimen> <dimen name="setup_step_title_text_size">24sp</dimen> <dimen name="setup_step_instruction_text_size">18sp</dimen> <dimen name="setup_step_action_text_size">20sp</dimen> diff --git a/java/res/values-h330dp-land/setup-dimens-large-phone-land.xml b/java/res/values-h330dp-land/setup-dimens-large-phone-land.xml index 1ff43ff9f..aebf6d2f3 100644 --- a/java/res/values-h330dp-land/setup-dimens-large-phone-land.xml +++ b/java/res/values-h330dp-land/setup-dimens-large-phone-land.xml @@ -20,6 +20,7 @@ <dimen name="setup_welcome_description_text_size">22sp</dimen> <dimen name="setup_step_bullet_text_size">22sp</dimen> <dimen name="setup_step_triangle_indicator_height">24dp</dimen> + <dimen name="setup_step_indicator_height">24dp</dimen> <dimen name="setup_step_title_text_size">20sp</dimen> <dimen name="setup_step_instruction_text_size">16sp</dimen> <dimen name="setup_step_action_text_size">18sp</dimen> diff --git a/java/res/values-h520dp-land/setup-dimens-small-tablet-land.xml b/java/res/values-h520dp-land/setup-dimens-small-tablet-land.xml index a0e30cd37..aedf79fb2 100644 --- a/java/res/values-h520dp-land/setup-dimens-small-tablet-land.xml +++ b/java/res/values-h520dp-land/setup-dimens-small-tablet-land.xml @@ -20,6 +20,7 @@ <dimen name="setup_welcome_description_text_size">32sp</dimen> <dimen name="setup_step_bullet_text_size">24sp</dimen> <dimen name="setup_step_triangle_indicator_height">24dp</dimen> + <dimen name="setup_step_indicator_height">24dp</dimen> <dimen name="setup_step_title_text_size">24sp</dimen> <dimen name="setup_step_instruction_text_size">18sp</dimen> <dimen name="setup_step_action_text_size">20sp</dimen> diff --git a/java/res/values-h540dp-port/setup-dimens-large-phone-port.xml b/java/res/values-h540dp-port/setup-dimens-large-phone-port.xml index cf2a10a9e..6d66f46eb 100644 --- a/java/res/values-h540dp-port/setup-dimens-large-phone-port.xml +++ b/java/res/values-h540dp-port/setup-dimens-large-phone-port.xml @@ -20,6 +20,7 @@ <dimen name="setup_welcome_description_text_size">26sp</dimen> <dimen name="setup_step_bullet_text_size">22sp</dimen> <dimen name="setup_step_triangle_indicator_height">24dp</dimen> + <dimen name="setup_step_indicator_height">24dp</dimen> <dimen name="setup_step_title_text_size">20sp</dimen> <dimen name="setup_step_instruction_text_size">16sp</dimen> <dimen name="setup_step_action_text_size">18sp</dimen> diff --git a/java/res/values-h720dp-land/setup-dimens-large-tablet-land.xml b/java/res/values-h720dp-land/setup-dimens-large-tablet-land.xml index a782ef8f4..e22b741fb 100644 --- a/java/res/values-h720dp-land/setup-dimens-large-tablet-land.xml +++ b/java/res/values-h720dp-land/setup-dimens-large-tablet-land.xml @@ -20,6 +20,7 @@ <dimen name="setup_welcome_description_text_size">38sp</dimen> <dimen name="setup_step_bullet_text_size">24sp</dimen> <dimen name="setup_step_triangle_indicator_height">24dp</dimen> + <dimen name="setup_step_indicator_height">24dp</dimen> <dimen name="setup_step_title_text_size">24sp</dimen> <dimen name="setup_step_instruction_text_size">18sp</dimen> <dimen name="setup_step_action_text_size">20sp</dimen> diff --git a/java/res/values-h800dp-port/setup-dimens-small-tablet-port.xml b/java/res/values-h800dp-port/setup-dimens-small-tablet-port.xml index 9ac0f115f..86cf3a04a 100644 --- a/java/res/values-h800dp-port/setup-dimens-small-tablet-port.xml +++ b/java/res/values-h800dp-port/setup-dimens-small-tablet-port.xml @@ -20,6 +20,7 @@ <dimen name="setup_welcome_description_text_size">36sp</dimen> <dimen name="setup_step_bullet_text_size">24sp</dimen> <dimen name="setup_step_triangle_indicator_height">24dp</dimen> + <dimen name="setup_step_indicator_height">24dp</dimen> <dimen name="setup_step_title_text_size">24sp</dimen> <dimen name="setup_step_instruction_text_size">18sp</dimen> <dimen name="setup_step_action_text_size">20sp</dimen> diff --git a/java/res/values-sw540dp/config-screen-metrics.xml b/java/res/values-hdpi/config.xml index 1205aaa1e..4cf3562fe 100644 --- a/java/res/values-sw540dp/config-screen-metrics.xml +++ b/java/res/values-hdpi/config.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2013, The Android Open Source Project +** Copyright 2011, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -20,10 +20,11 @@ <resources> <!-- Screen metrics for logging. - 0 = "small phone screen" - 1 = "large phone screen" - 2 = "large tablet screen" - 3 = "small tablet screen" + 0 = "mdpi phone screen" + 1 = "hdpi phone screen" + 2 = "mdpi 11 inch tablet screen" + 3 = "xhdpi phone screen?" + 4 = ? --> <integer name="log_screen_metrics">1</integer> </resources> diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml index d2ace1ac7..d7735433d 100644 --- a/java/res/values-hi/strings.xml +++ b/java/res/values-hi/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"समय"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"ध्वनि इनपुट कुंजी"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"मुख्य कीबोर्ड पर"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"प्रतीक कीबोर्ड पर"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"बंद"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"मुख्य कीबोर्ड पर माइक"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"प्रतीक कीबोर्ड पर माइक"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"ध्वनि इनपुट अक्षम है"</string> <string name="configure_input_method" msgid="373356270290742459">"इनपुट पद्धति कॉन्फ़िगर करें"</string> <string name="language_selection_title" msgid="1651299598555326750">"इनपुट भाषा"</string> <string name="send_feedback" msgid="1780431884109392046">"सुझाव भेजें"</string> diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml index e7a72f9c4..b9cfef384 100644 --- a/java/res/values-hr/strings.xml +++ b/java/res/values-hr/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"vrijeme"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Tipka za glasovni unos"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na glavnoj tipkovnici"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na tipkovnici simb."</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Isključeno"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon na gl. tipkovnici"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik. na tipk. simb."</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Glas. unos onemog."</string> <string name="configure_input_method" msgid="373356270290742459">"Konfiguriraj načine ulaza"</string> <string name="language_selection_title" msgid="1651299598555326750">"Jezici unosa"</string> <string name="send_feedback" msgid="1780431884109392046">"Slanje povratnih informacija"</string> diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml index 27efd0c92..a61378fca 100644 --- a/java/res/values-hu/strings.xml +++ b/java/res/values-hu/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"idő"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Hangbeviteli gomb"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"A fő billentyűzeten"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Szimbólumoknál"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Ki"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon a billentyűzeten"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr. a szimbólumoknál"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hangbevivel KI"</string> <string name="configure_input_method" msgid="373356270290742459">"Beviteli módok beállítása"</string> <string name="language_selection_title" msgid="1651299598555326750">"Beviteli nyelvek"</string> <string name="send_feedback" msgid="1780431884109392046">"Visszajelzés küldése"</string> diff --git a/java/res/values-hy-rAM/config-spacing-and-punctuations.xml b/java/res/values-hy-rAM/donottranslate.xml index f26a30def..7b0c56655 100644 --- a/java/res/values-hy-rAM/config-spacing-and-punctuations.xml +++ b/java/res/values-hy-rAM/donottranslate.xml @@ -22,11 +22,11 @@ <!-- U+055D: "՝" ARMENIAN COMMA --> <!-- U+0589: "։" ARMENIAN FULL STOP --> <!-- Symbols that are normally followed by a space (used to add an auto-space after these) --> - <string name="symbols_followed_by_space" translatable="false">.,;:!?)]}&։՝</string> + <string name="symbols_followed_by_space">.,;:!?)]}&։՝</string> <!-- Symbols that separate words. Adding armenian period and comma. --> <!-- Don't remove the enclosing double quotes, they protect whitespace (not just U+0020) --> - <string name="symbols_word_separators" translatable="false">"	 \n"()[]{}*&<>+=|.,;:!?/_\"։՝</string> + <string name="symbols_word_separators">"	 \n"()[]{}*&<>+=|.,;:!?/_\"։՝</string> <!-- The sentence separator code point, for capitalization --> <!-- U+0589: "։" ARMENIAN FULL STOP ; 589h = 1417d --> - <integer name="sentence_separator" translatable="false">1417</integer> + <integer name="sentence_separator">1417</integer> </resources> diff --git a/java/res/values-hy-rAM/strings.xml b/java/res/values-hy-rAM/strings.xml index 62dc45b1f..0b8e19a76 100644 --- a/java/res/values-hy-rAM/strings.xml +++ b/java/res/values-hy-rAM/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"ժամանակ"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Ձայնային մուտքագրման ստեղն"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Հիմնական ստեղնաշարի վրա"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Նշանների ստեղնաշարի վրա"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Անջատված"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Բարձրախոս հիմնական ստեղնաշարի վրա"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Բարձրախոս նշանների ստեղնաշարի վրա"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Ձայնային մուտքագրումն անջատված է"</string> <string name="configure_input_method" msgid="373356270290742459">"Կարգավորել մուտքագրման մեթոդները"</string> <string name="language_selection_title" msgid="1651299598555326750">"Մուտքագրման լեզուներ"</string> <string name="send_feedback" msgid="1780431884109392046">"Արձագանքել"</string> diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml index 83530f2b9..d83a22c6c 100644 --- a/java/res/values-in/strings.xml +++ b/java/res/values-in/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"waktu"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Tombol masukan suara"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Pada keyboard utama"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Pada keyboard simbol"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Mati"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mik pada keyboard utama"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik pada keyboard simbol"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Masukan suara dinonaktifkan"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigurasikan metode masukan"</string> <string name="language_selection_title" msgid="1651299598555326750">"Bahasa masukan"</string> <string name="send_feedback" msgid="1780431884109392046">"Kirim masukan"</string> diff --git a/java/res/values-is/strings.xml b/java/res/values-is/strings.xml index 1137fd09d..6f685d395 100644 --- a/java/res/values-is/strings.xml +++ b/java/res/values-is/strings.xml @@ -214,6 +214,18 @@ <skip /> <!-- no translation found for voice_input (3583258583521397548) --> <skip /> + <!-- no translation found for voice_input_modes_main_keyboard (3360660341121083174) --> + <skip /> + <!-- no translation found for voice_input_modes_symbols_keyboard (7203213240786084067) --> + <skip /> + <!-- no translation found for voice_input_modes_off (3745699748218082014) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_main_keyboard (6586544292900314339) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_symbols_keyboard (5233725927281932391) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_off (63875609591897607) --> + <skip /> <!-- no translation found for configure_input_method (373356270290742459) --> <skip /> <!-- no translation found for language_selection_title (1651299598555326750) --> diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml index 12b597ac3..1111c4901 100644 --- a/java/res/values-it/strings.xml +++ b/java/res/values-it/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"ora"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Tasto input vocale"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Su tastiera principale"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Su tastiera simboli"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"OFF"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Microfono su tastiera principale"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Microfono su tastiera simboli"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Input vocale disatt."</string> <string name="configure_input_method" msgid="373356270290742459">"Configura metodi di immissione"</string> <string name="language_selection_title" msgid="1651299598555326750">"Lingue comandi"</string> <string name="send_feedback" msgid="1780431884109392046">"Invia feedback"</string> diff --git a/java/res/values-iw/config-spacing-and-punctuations.xml b/java/res/values-iw/donottranslate.xml index 9e637e458..57de2538b 100644 --- a/java/res/values-iw/config-spacing-and-punctuations.xml +++ b/java/res/values-iw/donottranslate.xml @@ -21,5 +21,5 @@ <!-- The all letters need to be mirrored are found at http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt --> <!-- Symbols that are suggested between words --> - <string name="suggested_punctuations" translatable="false">!,?,\\,,:,;,\",(|),)|(,\',-,/,@,_</string> + <string name="suggested_punctuations">!,?,\\,,:,;,\",(|),)|(,\',-,/,@,_</string> </resources> diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml index ab15649d0..8d02e685b 100644 --- a/java/res/values-iw/strings.xml +++ b/java/res/values-iw/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"זמן"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"כתובות אתרים"</string> <string name="voice_input" msgid="3583258583521397548">"מקש קלט קולי"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"במקלדת הראשית"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"במקלדת סמלים"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"כבוי"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"מיקרופון במקלדת הראשית"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"מיקרופון במקלדת סמלים"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"הקלט הקולי מושבת"</string> <string name="configure_input_method" msgid="373356270290742459">"הגדרת שיטות קלט"</string> <string name="language_selection_title" msgid="1651299598555326750">"שפות קלט"</string> <string name="send_feedback" msgid="1780431884109392046">"שלח משוב"</string> diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml index 39f14ff35..fbfd3b7f7 100644 --- a/java/res/values-ja/strings.xml +++ b/java/res/values-ja/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"時刻"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"音声入力キー"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"メインキーボード上"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"記号キーボード上"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"OFF"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"メインキーボードのマイク"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"記号キーボードのマイク"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"音声入力は無効です"</string> <string name="configure_input_method" msgid="373356270290742459">"入力方法を設定"</string> <string name="language_selection_title" msgid="1651299598555326750">"入力言語"</string> <string name="send_feedback" msgid="1780431884109392046">"フィードバックを送信"</string> diff --git a/java/res/values-ka-rGE/strings.xml b/java/res/values-ka-rGE/strings.xml index 2adf9c440..dec6b3a6b 100644 --- a/java/res/values-ka-rGE/strings.xml +++ b/java/res/values-ka-rGE/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"დრო"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"ხმოვანი შეყვანის კლავიში"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"მთავარ კლავიატურაზე"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"სიმბოლოთა კლავიატურაზე"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"გამორთვა"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"მიკროფონი მთავარ კლავიატურაზე"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"მიკროფონი სიმბოლოთა კლავიატურაზე"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"ხმოვანი შეყვანა გამორთულია"</string> <string name="configure_input_method" msgid="373356270290742459">"შეყვანის მეთოდების კონფიგურაცია"</string> <string name="language_selection_title" msgid="1651299598555326750">"შეყვანის ენები"</string> <string name="send_feedback" msgid="1780431884109392046">"უკუკავშირის გაგზავნა"</string> diff --git a/java/res/values-kk/strings.xml b/java/res/values-kk/strings.xml index 80b289f4d..947ff2fe9 100644 --- a/java/res/values-kk/strings.xml +++ b/java/res/values-kk/strings.xml @@ -119,6 +119,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"уақыт"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Дауыстық енгізу пернесі"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Негізгі пернетақтада"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Таңбалар пернетақтасында"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Өшірулі"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Негізгі пернетақтадағы Mic"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Таңбалар пернетақтасындағы Mic"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Дауыстық енгізу өшірілген"</string> <string name="configure_input_method" msgid="373356270290742459">"Енгізу әдістерін теңшеу"</string> <string name="language_selection_title" msgid="1651299598555326750">"Енгізу тілдері"</string> <string name="send_feedback" msgid="1780431884109392046">"Кері байланыс жіберу"</string> diff --git a/java/res/values-km-rKH/config-spacing-and-punctuations.xml b/java/res/values-km-rKH/donottranslate.xml index a9893feec..a9893feec 100644 --- a/java/res/values-km-rKH/config-spacing-and-punctuations.xml +++ b/java/res/values-km-rKH/donottranslate.xml diff --git a/java/res/values-km-rKH/strings.xml b/java/res/values-km-rKH/strings.xml index 0609bd26d..86ecc5e10 100644 --- a/java/res/values-km-rKH/strings.xml +++ b/java/res/values-km-rKH/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"ពេលវេលា"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"គ្រាប់ចុចបញ្ចូលសំឡេង"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"នៅលើក្ដារចុចចម្បង"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"នៅលើក្ដារចុចនិមិត្តសញ្ញា"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"បិទ"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"មីក្រូហ្វូននៅលើក្ដារចុចចម្បង"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"មីក្រូហ្វូននៅលើក្ដារចុចនិមិត្តសញ្ញា"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"បានបិទការបញ្ចូលសំឡេង"</string> <string name="configure_input_method" msgid="373356270290742459">"កំណត់រចនាសម្ព័ន្ធវិធីសាស្ត្របញ្ចូល"</string> <string name="language_selection_title" msgid="1651299598555326750">"បញ្ចូលភាសា"</string> <string name="send_feedback" msgid="1780431884109392046">"ផ្ញើមតិអ្នកប្រើ"</string> diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml index 678cc3ee4..ca10bdf52 100644 --- a/java/res/values-ko/strings.xml +++ b/java/res/values-ko/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"시간"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"음성 입력 키"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"기본 키보드"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"기호 키보드"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"사용 안함"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"기본 키보드의 마이크"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"기호 키보드의 마이크"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"음성 입력이 사용 중지됨"</string> <string name="configure_input_method" msgid="373356270290742459">"입력 방법 설정"</string> <string name="language_selection_title" msgid="1651299598555326750">"입력 언어"</string> <string name="send_feedback" msgid="1780431884109392046">"의견 보내기"</string> diff --git a/java/res/values-ky/strings.xml b/java/res/values-ky/strings.xml index c3aab7858..e30c4b965 100644 --- a/java/res/values-ky/strings.xml +++ b/java/res/values-ky/strings.xml @@ -168,6 +168,18 @@ <skip /> <!-- no translation found for voice_input (3583258583521397548) --> <skip /> + <!-- no translation found for voice_input_modes_main_keyboard (3360660341121083174) --> + <skip /> + <!-- no translation found for voice_input_modes_symbols_keyboard (7203213240786084067) --> + <skip /> + <!-- no translation found for voice_input_modes_off (3745699748218082014) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_main_keyboard (6586544292900314339) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_symbols_keyboard (5233725927281932391) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_off (63875609591897607) --> + <skip /> <!-- no translation found for configure_input_method (373356270290742459) --> <skip /> <!-- no translation found for language_selection_title (1651299598555326750) --> diff --git a/java/res/values-land/config.xml b/java/res/values-land/config.xml index ade7d002c..7d93cc2ff 100644 --- a/java/res/values-land/config.xml +++ b/java/res/values-land/config.xml @@ -18,67 +18,6 @@ */ --> -<!-- Configuration values for Small Phone Landscape. --> <resources> <bool name="config_use_fullscreen_mode">true</bool> - - <!-- Preferable keyboard height in absolute scale: 1.100in --> - <!-- This config_default_keyboard_height value should match with keyboard-heights.xml --> - <dimen name="config_default_keyboard_height">176.0dp</dimen> - <fraction name="config_min_keyboard_height">45%p</fraction> - - <!-- key_height + key_bottom_gap = config_more_keys_keyboard_key_height --> - <dimen name="config_more_keys_keyboard_key_height">44.8dp</dimen> - <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. --> - <!-- config_more_keys_keyboard_key_height x 1.2 --> - <dimen name="config_more_keys_keyboard_slide_allowance">53.76dp</dimen> - - <fraction name="config_keyboard_top_padding_gb">1.818%p</fraction> - <fraction name="config_keyboard_bottom_padding_gb">0.0%p</fraction> - <fraction name="config_key_vertical_gap_gb">5.941%p</fraction> - <fraction name="config_key_horizontal_gap_gb">0.997%p</fraction> - <!-- config_more_keys_keyboard_key_height x -1.0 --> - <dimen name="config_more_keys_keyboard_vertical_correction_gb">-44.8dp</dimen> - <dimen name="config_key_preview_offset_gb">0.0dp</dimen> - - <fraction name="config_keyboard_top_padding_holo">2.727%p</fraction> - <fraction name="config_keyboard_bottom_padding_holo">0.0%p</fraction> - <fraction name="config_key_vertical_gap_holo">5.368%p</fraction> - <fraction name="config_key_horizontal_gap_holo">1.020%p</fraction> - <!-- config_more_keys_keyboard_key_height x -0.5 --> - <dimen name="config_more_keys_keyboard_vertical_correction_holo">-22.4dp</dimen> - <dimen name="config_key_preview_offset_holo">1.6dp</dimen> - - <fraction name="config_key_preview_text_ratio">90%</fraction> - <fraction name="config_key_letter_ratio">65%</fraction> - <fraction name="config_key_large_letter_ratio">74%</fraction> - <fraction name="config_key_label_ratio">40%</fraction> - <fraction name="config_key_hint_letter_ratio">30%</fraction> - <fraction name="config_key_hint_label_ratio">52%</fraction> - <fraction name="config_key_shifted_letter_hint_ratio">40%</fraction> - <fraction name="config_language_on_spacebar_text_ratio">40.000%</fraction> - <!-- left or right padding of label alignment --> - <dimen name="config_key_label_horizontal_padding">8dp</dimen> - - <!-- For 5-row keyboard --> - <fraction name="config_key_vertical_gap_5row">3.20%p</fraction> - <fraction name="config_key_letter_ratio_5row">78%</fraction> - <fraction name="config_key_shifted_letter_hint_ratio_5row">48%</fraction> - - <dimen name="config_suggestions_strip_height">36dp</dimen> - <dimen name="config_more_suggestions_row_height">36dp</dimen> - <integer name="config_max_more_suggestions_row">2</integer> - <fraction name="config_min_more_suggestions_width">60%</fraction> - - <!-- Gesture floating preview text parameters --> - <dimen name="config_gesture_floating_preview_text_size">23dp</dimen> - <dimen name="config_gesture_floating_preview_text_offset">54dp</dimen> - <dimen name="config_gesture_floating_preview_horizontal_padding">23dp</dimen> - <dimen name="config_gesture_floating_preview_vertical_padding">15dp</dimen> - - <!-- Emoji keyboard --> - <fraction name="config_emoji_keyboard_key_width">10%p</fraction> - <fraction name="config_emoji_keyboard_row_height">50%p</fraction> - <fraction name="config_emoji_keyboard_key_letter_size">54%p</fraction> - <integer name="config_emoji_keyboard_max_page_key_count">20</integer> </resources> diff --git a/java/res/values-land/dimens.xml b/java/res/values-land/dimens.xml new file mode 100644 index 000000000..c97e68f11 --- /dev/null +++ b/java/res/values-land/dimens.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2008, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<resources> + <!-- Preferable keyboard height in absolute scale: 1.100in --> + <!-- This keyboardHeight value should match with keyboard-heights.xml --> + <dimen name="keyboardHeight">176.0dp</dimen> + <fraction name="minKeyboardHeight">45%p</fraction> + <!-- key_height + key_bottom_gap = popup_key_height --> + <dimen name="popup_key_height">44.8dp</dimen> + + <fraction name="keyboard_top_padding_gb">1.818%p</fraction> + <fraction name="keyboard_bottom_padding_gb">0.0%p</fraction> + <fraction name="key_bottom_gap_gb">5.941%p</fraction> + <fraction name="key_horizontal_gap_gb">0.997%p</fraction> + + <fraction name="keyboard_top_padding_holo">2.727%p</fraction> + <fraction name="keyboard_bottom_padding_holo">0.0%p</fraction> + <fraction name="key_bottom_gap_holo">5.368%p</fraction> + <fraction name="key_horizontal_gap_holo">1.020%p</fraction> + + <!-- left or right padding of label alignment --> + <dimen name="key_label_horizontal_padding">8dp</dimen> + + <fraction name="key_letter_ratio">65%</fraction> + <fraction name="key_large_letter_ratio">74%</fraction> + <fraction name="key_label_ratio">40%</fraction> + <fraction name="key_hint_letter_ratio">30%</fraction> + <fraction name="key_hint_label_ratio">52%</fraction> + <fraction name="key_uppercase_letter_ratio">40%</fraction> + <fraction name="key_preview_text_ratio">90%</fraction> + <fraction name="spacebar_text_ratio">40.000%</fraction> + <dimen name="key_preview_offset_gb">0.0dp</dimen> + + <!-- For 5-row keyboard --> + <fraction name="key_bottom_gap_5row">3.20%p</fraction> + <fraction name="key_letter_ratio_5row">78%</fraction> + <fraction name="key_uppercase_letter_ratio_5row">48%</fraction> + + <dimen name="key_preview_offset_holo">1.6dp</dimen> + <!-- popup_key_height x -0.5 --> + <dimen name="more_keys_keyboard_vertical_correction_holo">-22.4dp</dimen> + + <dimen name="suggestions_strip_height">36dp</dimen> + <dimen name="more_suggestions_row_height">36dp</dimen> + <integer name="max_more_suggestions_row">2</integer> + <fraction name="min_more_suggestions_width">60%</fraction> + <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. --> + <!-- popup_key_height x 1.2 --> + <dimen name="more_keys_keyboard_slide_allowance">53.76dp</dimen> + <!-- popup_key_height x -1.0 --> + <dimen name="more_keys_keyboard_vertical_correction_gb">-44.8dp</dimen> + + <!-- Gesture floating preview text parameters --> + <dimen name="gesture_floating_preview_text_size">23dp</dimen> + <dimen name="gesture_floating_preview_text_offset">54dp</dimen> + <dimen name="gesture_floating_preview_horizontal_padding">23dp</dimen> + <dimen name="gesture_floating_preview_vertical_padding">15dp</dimen> + + <!-- Emoji keyboard --> + <fraction name="emoji_keyboard_key_width">10%p</fraction> + <fraction name="emoji_keyboard_row_height">50%p</fraction> + <fraction name="emoji_keyboard_key_letter_size">54%p</fraction> + <integer name="emoji_keyboard_max_key_count">20</integer> + +</resources> diff --git a/java/res/values-land/setup-dimens-small-phone-land.xml b/java/res/values-land/setup-dimens-small-phone-land.xml index de93eee08..088e6562a 100644 --- a/java/res/values-land/setup-dimens-small-phone-land.xml +++ b/java/res/values-land/setup-dimens-small-phone-land.xml @@ -20,6 +20,7 @@ <dimen name="setup_welcome_description_text_size">18sp</dimen> <dimen name="setup_step_bullet_text_size">18sp</dimen> <dimen name="setup_step_triangle_indicator_height">18dp</dimen> + <dimen name="setup_step_indicator_height">18dp</dimen> <dimen name="setup_step_title_text_size">18sp</dimen> <dimen name="setup_step_instruction_text_size">14sp</dimen> <dimen name="setup_step_action_text_size">16sp</dimen> diff --git a/java/res/values-lo-rLA/config-spacing-and-punctuations.xml b/java/res/values-lo-rLA/donottranslate.xml index a9893feec..a9893feec 100644 --- a/java/res/values-lo-rLA/config-spacing-and-punctuations.xml +++ b/java/res/values-lo-rLA/donottranslate.xml diff --git a/java/res/values-lo-rLA/strings.xml b/java/res/values-lo-rLA/strings.xml index bbf1715b8..a4dbc2de2 100644 --- a/java/res/values-lo-rLA/strings.xml +++ b/java/res/values-lo-rLA/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"ເວລາ"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"ປຸ່ມປ້ອນຂໍ້ມູນດ້ວຍສຽງ"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"ແປ້ນພິມຫຼັກ"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"ໃນແປ້ນພິມສັນຍາລັກ"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"ປິດ"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"ໄມໃນແປ້ນພິມຫຼັກ"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"ໄມໃນແປ້ນພິມສັນຍາລັກ"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"ການປ້ອນຂໍ້ມູນດ້ວຍສຽງປິດນຳໃຊ້ຢູ່"</string> <string name="configure_input_method" msgid="373356270290742459">"ຕັ້ງຄ່າຮູບແບບການປ້ອນຂໍ້ມູນ"</string> <string name="language_selection_title" msgid="1651299598555326750">"ພາສາການປ້ອນຂໍ້ມູນ"</string> <string name="send_feedback" msgid="1780431884109392046">"ສົ່ງຄຳຕິຊົມ"</string> diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml index bf37143db..1f943944c 100644 --- a/java/res/values-lt/strings.xml +++ b/java/res/values-lt/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"laiko"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Įvesties balsu klavišas"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Pagr. klaviatūroje"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Simbolių klaviatūr."</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Išjungta"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrof. pagr. klav."</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrof. simb. klav."</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Balso įv. neleidž."</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigūruoti įvesties metodus"</string> <string name="language_selection_title" msgid="1651299598555326750">"Įvesties kalbos"</string> <string name="send_feedback" msgid="1780431884109392046">"Siųsti atsiliepimą"</string> diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml index 9afea26b8..8ea24edb7 100644 --- a/java/res/values-lv/strings.xml +++ b/java/res/values-lv/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"laiks"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Balss ievades atslēga"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Uz galv. tastatūras"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Uz simbolu tastat."</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Izslēgts"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikr.uz galv.tastat."</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr.uz simb.tastat."</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Balss iev. atspējota"</string> <string name="configure_input_method" msgid="373356270290742459">"Ievades metožu konfigurēšana"</string> <string name="language_selection_title" msgid="1651299598555326750">"Ievades valodas"</string> <string name="send_feedback" msgid="1780431884109392046">"Sūtīt atsauksmes"</string> diff --git a/java/res/values-mk/strings.xml b/java/res/values-mk/strings.xml index 1137fd09d..6f685d395 100644 --- a/java/res/values-mk/strings.xml +++ b/java/res/values-mk/strings.xml @@ -214,6 +214,18 @@ <skip /> <!-- no translation found for voice_input (3583258583521397548) --> <skip /> + <!-- no translation found for voice_input_modes_main_keyboard (3360660341121083174) --> + <skip /> + <!-- no translation found for voice_input_modes_symbols_keyboard (7203213240786084067) --> + <skip /> + <!-- no translation found for voice_input_modes_off (3745699748218082014) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_main_keyboard (6586544292900314339) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_symbols_keyboard (5233725927281932391) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_off (63875609591897607) --> + <skip /> <!-- no translation found for configure_input_method (373356270290742459) --> <skip /> <!-- no translation found for language_selection_title (1651299598555326750) --> diff --git a/java/res/values-mn-rMN/strings.xml b/java/res/values-mn-rMN/strings.xml index 4b36f03d6..d4175899f 100644 --- a/java/res/values-mn-rMN/strings.xml +++ b/java/res/values-mn-rMN/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"цаг"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Дуун оруулгын товч"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Үндсэн гар дээр"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Симбол гар дээр"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Идэвхгүй"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Мик үндсэн гар дээр"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Мик симбол гар дээр"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Дуун оруулах идэвхгүйжсэн"</string> <string name="configure_input_method" msgid="373356270290742459">"Оруулах аргуудын тохиргоо"</string> <string name="language_selection_title" msgid="1651299598555326750">"Оруулах хэл"</string> <string name="send_feedback" msgid="1780431884109392046">"Санал хүсэлт илгээх"</string> diff --git a/java/res/values-ms-rMY/strings.xml b/java/res/values-ms-rMY/strings.xml index d3ab3f97c..c9b4a0359 100644 --- a/java/res/values-ms-rMY/strings.xml +++ b/java/res/values-ms-rMY/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"masa"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Kunci input suara"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Pada papan kekunci utama"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Pada papan kekunci simbol"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Dimati"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon pada papan kekunci utama"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofon pada papan kekunci simbol"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Input suara dilmphkn"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigurasikan kaedah input"</string> <string name="language_selection_title" msgid="1651299598555326750">"Bahasa input"</string> <string name="send_feedback" msgid="1780431884109392046">"Hantar maklum balas"</string> diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml index 6d9f64fb3..00aa10da7 100644 --- a/java/res/values-nb/strings.xml +++ b/java/res/values-nb/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"tid"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"Nettadresse"</string> <string name="voice_input" msgid="3583258583521397548">"Tast for taleinndata"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"På hovedtastatur"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"På talltastatur"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Av"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon på hovedtast."</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofon på talltastatur"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Taleinndata er deaktiv."</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigurer inndatametoder"</string> <string name="language_selection_title" msgid="1651299598555326750">"Inndataspråk"</string> <string name="send_feedback" msgid="1780431884109392046">"Send tilbakemelding"</string> @@ -180,7 +186,7 @@ <string name="setup_step3_title" msgid="3154757183631490281">"Gratulerer, du er klar!"</string> <string name="setup_step3_instruction" msgid="8025981829605426000">"Nå kan du skrive inn alle favorittappene dine med <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string> <string name="setup_step3_action" msgid="600879797256942259">"Konfigurer flere språk"</string> - <string name="setup_finish_action" msgid="276559243409465389">"Fullført"</string> + <string name="setup_finish_action" msgid="276559243409465389">"Ferdig"</string> <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Vis app-ikonet"</string> <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Vis app-ikonet i appvelgeren"</string> <string name="app_name" msgid="6320102637491234792">"Ordlisteleverandør"</string> diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml index f99c34520..dcbf2c09c 100644 --- a/java/res/values-nl/strings.xml +++ b/java/res/values-nl/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"tijd"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Toets voor spraakinvoer"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Op hoofdtoetsenbord"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Op symbooltoetsenb."</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Uitgeschakeld"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Microfoon op hoofdtoetsenbord"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic op symb.toetsb."</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Spraakinvoer is uit"</string> <string name="configure_input_method" msgid="373356270290742459">"Invoermethoden configureren"</string> <string name="language_selection_title" msgid="1651299598555326750">"Invoertalen"</string> <string name="send_feedback" msgid="1780431884109392046">"Feedback verzenden"</string> diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml index 558415d89..c78674a9b 100644 --- a/java/res/values-pl/strings.xml +++ b/java/res/values-pl/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"godzina"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Klawisz rozpoznawania mowy"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na klawiaturze głównej"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na klawiaturze z symbolami"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Wyłącz"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon na klawiaturze głównej"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofon na klawiaturze z symbolami"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Rozpoznawanie mowy jest wyłączone"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfiguruj metody wprowadzania"</string> <string name="language_selection_title" msgid="1651299598555326750">"Języki wprowadzania"</string> <string name="send_feedback" msgid="1780431884109392046">"Prześlij opinię"</string> diff --git a/java/res/values-port/setup-dimens-small-phone-port.xml b/java/res/values-port/setup-dimens-small-phone-port.xml index cf2751f1b..8ac72ea7c 100644 --- a/java/res/values-port/setup-dimens-small-phone-port.xml +++ b/java/res/values-port/setup-dimens-small-phone-port.xml @@ -20,6 +20,7 @@ <dimen name="setup_welcome_description_text_size">20sp</dimen> <dimen name="setup_step_bullet_text_size">18sp</dimen> <dimen name="setup_step_triangle_indicator_height">18dp</dimen> + <dimen name="setup_step_indicator_height">18dp</dimen> <dimen name="setup_step_title_text_size">18sp</dimen> <dimen name="setup_step_instruction_text_size">14sp</dimen> <dimen name="setup_step_action_text_size">16sp</dimen> diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml index 36425e174..c27758116 100644 --- a/java/res/values-pt-rPT/strings.xml +++ b/java/res/values-pt-rPT/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"hora"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URLs"</string> <string name="voice_input" msgid="3583258583521397548">"Chave de entrada de voz"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"No teclado principal"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"No teclado símbolos"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Desligar"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic. tecl. principal"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic. tecl. símbolos"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entr. voz desact."</string> <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de introdução"</string> <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string> <string name="send_feedback" msgid="1780431884109392046">"Enviar comentários"</string> diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml index 925adf0b0..f98ef8cd6 100644 --- a/java/res/values-pt/strings.xml +++ b/java/res/values-pt/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"hora"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Chave de entrada de texto por voz"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"No teclado principal"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"No teclado de símb."</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Desativado"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic. no teclado"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic. no teclado"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Texto por voz desat."</string> <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string> <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string> <string name="send_feedback" msgid="1780431884109392046">"Enviar comentários"</string> diff --git a/java/res/values-rm/strings.xml b/java/res/values-rm/strings.xml index 378c25426..3f0bab963 100644 --- a/java/res/values-rm/strings.xml +++ b/java/res/values-rm/strings.xml @@ -209,6 +209,18 @@ <skip /> <!-- no translation found for voice_input (3583258583521397548) --> <skip /> + <!-- no translation found for voice_input_modes_main_keyboard (3360660341121083174) --> + <skip /> + <!-- no translation found for voice_input_modes_symbols_keyboard (7203213240786084067) --> + <skip /> + <!-- no translation found for voice_input_modes_off (3745699748218082014) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_main_keyboard (6586544292900314339) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_symbols_keyboard (5233725927281932391) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_off (63875609591897607) --> + <skip /> <!-- no translation found for configure_input_method (373356270290742459) --> <skip /> <string name="language_selection_title" msgid="1651299598555326750">"Linguas da cumonds vocals"</string> diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml index 9758a0b62..147f83e61 100644 --- a/java/res/values-ro/strings.xml +++ b/java/res/values-ro/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"ore"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"adrese URL"</string> <string name="voice_input" msgid="3583258583521397548">"Tastă pentru intrarea vocală"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Pe tastat. princip."</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Pe tastat. simbol."</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Dezactivată"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic. pe tast. princ."</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micr. pe tast. simb."</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Intr. vocală dezact."</string> <string name="configure_input_method" msgid="373356270290742459">"Configuraţi metodele de intrare"</string> <string name="language_selection_title" msgid="1651299598555326750">"Selectaţi limba"</string> <string name="send_feedback" msgid="1780431884109392046">"Trimiteți feedback"</string> diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml index 36990fe41..8bbaead0a 100644 --- a/java/res/values-ru/strings.xml +++ b/java/res/values-ru/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"ввода времени"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"ввода URL"</string> <string name="voice_input" msgid="3583258583521397548">"Кнопка голосового ввода"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Значок на основной клавиатуре"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Значок на клавиатуре символов"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Выкл."</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Значок на основной клавиатуре"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Значок на клавиатуре символов"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Голосовой ввод откл."</string> <string name="configure_input_method" msgid="373356270290742459">"Настройка способов ввода"</string> <string name="language_selection_title" msgid="1651299598555326750">"Языки ввода"</string> <string name="send_feedback" msgid="1780431884109392046">"Отправить отзыв"</string> diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml index 42e55fa1f..d1f966cea 100644 --- a/java/res/values-sk/strings.xml +++ b/java/res/values-sk/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"čas"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"Adresa URL"</string> <string name="voice_input" msgid="3583258583521397548">"Kľúč hlasového vstupu"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na hlavnej klávesnici"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na klávesnici so symbolmi"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Vypnuté"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofón na hlavnej klávesnici"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofón na klávesnici so symbolmi"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hlasový vstup je zakázaný"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigurovať metódy vstupu"</string> <string name="language_selection_title" msgid="1651299598555326750">"Jazyky vstupu"</string> <string name="send_feedback" msgid="1780431884109392046">"Odoslať spätnú väzbu"</string> diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml index 59113e30b..a0f83c12f 100644 --- a/java/res/values-sl/strings.xml +++ b/java/res/values-sl/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"ura"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Tipka za glasovni vnos"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na glavni tipkovnici"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na tipk. s simboli"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Izklopljeno"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mik. na glavni tipk."</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik. na tipk. s sim."</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Glas. vnos je onem."</string> <string name="configure_input_method" msgid="373356270290742459">"Nastavitev načinov vnosa"</string> <string name="language_selection_title" msgid="1651299598555326750">"Jeziki vnosa"</string> <string name="send_feedback" msgid="1780431884109392046">"Pošljite povratne informacije"</string> diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml index 663cb327d..ce4978ff5 100644 --- a/java/res/values-sr/strings.xml +++ b/java/res/values-sr/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"време"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Тастер за гласовни унос"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"На главној тастатури"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"На тастатури са симболима"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Искључи"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Микрофон на главној тастатури"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Микрофон на тастатури са симболима"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Гласовни унос је онемогућен"</string> <string name="configure_input_method" msgid="373356270290742459">"Конфигурисање метода уноса"</string> <string name="language_selection_title" msgid="1651299598555326750">"Језици за унос"</string> <string name="send_feedback" msgid="1780431884109392046">"Пошаљи повратне информације"</string> diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml index f5e129af9..afe349afd 100644 --- a/java/res/values-sv/strings.xml +++ b/java/res/values-sv/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"klockslag"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"webbadresser"</string> <string name="voice_input" msgid="3583258583521397548">"Röstinmatningsknapp"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"På huvudtangentbord"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"På symboltangentbord"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Av"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mick huvudtangentbord"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mick bland symboler"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Röstinmatning inaktiv"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigurera inmatningsmetoder"</string> <string name="language_selection_title" msgid="1651299598555326750">"Inmatningsspråk"</string> <string name="send_feedback" msgid="1780431884109392046">"Skicka feedback"</string> diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml index 8e23496d1..191ad977c 100644 --- a/java/res/values-sw/strings.xml +++ b/java/res/values-sw/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"wakati"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Kibao cha kuweka data kwa kutamka"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Kwenye kibodi kuu"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Kwenye kibodi ya ishara"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Zima"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Maikrofoni kwenye kibodi kuu"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Maikrofoni kwenye kibodi ya ishara"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Kipengele cha kuweka data kwa kutamka kimezimwa"</string> <string name="configure_input_method" msgid="373356270290742459">"Sanidi mbinu za uingizaji"</string> <string name="language_selection_title" msgid="1651299598555326750">"Lugha za uingizaji"</string> <string name="send_feedback" msgid="1780431884109392046">"Tuma maoni"</string> diff --git a/java/res/values-sw540dp-land/config.xml b/java/res/values-sw540dp-land/config.xml index f4785e721..b3cd7278d 100644 --- a/java/res/values-sw540dp-land/config.xml +++ b/java/res/values-sw540dp-land/config.xml @@ -18,56 +18,6 @@ */ --> -<!-- Configuration values for Large Phone and Small Tablet Landscape. --> <resources> <bool name="config_use_fullscreen_mode">false</bool> - - <!-- Preferable keyboard height in absolute scale: 45.0mm --> - <!-- This config_default_keyboard_height value should match with keyboard-heights.xml --> - <dimen name="config_default_keyboard_height">283.5dp</dimen> - <fraction name="config_min_keyboard_height">45%p</fraction> - - <dimen name="config_more_keys_keyboard_key_height">81.9dp</dimen> - - <fraction name="config_keyboard_top_padding_gb">2.444%p</fraction> - <fraction name="config_keyboard_bottom_padding_gb">0.0%p</fraction> - <fraction name="config_key_vertical_gap_gb">5.200%p</fraction> - <fraction name="config_key_horizontal_gap_gb">1.447%p</fraction> - - <fraction name="config_keyboard_top_padding_holo">2.727%p</fraction> - <fraction name="config_keyboard_bottom_padding_holo">0.0%p</fraction> - <fraction name="config_key_vertical_gap_holo">4.5%p</fraction> - <fraction name="config_key_horizontal_gap_holo">0.9%p</fraction> - - <fraction name="config_key_letter_ratio">50%</fraction> - <fraction name="config_key_large_letter_ratio">48%</fraction> - <fraction name="config_key_label_ratio">32%</fraction> - <fraction name="config_key_hint_letter_ratio">23%</fraction> - <fraction name="config_key_hint_label_ratio">34%</fraction> - <fraction name="config_key_shifted_letter_hint_ratio">29%</fraction> - <fraction name="config_language_on_spacebar_text_ratio">30.0%</fraction> - <!-- left or right padding of label alignment --> - <dimen name="config_key_label_horizontal_padding">18dp</dimen> - <dimen name="config_key_shifted_letter_hint_padding">4dp</dimen> - - <!-- For 5-row keyboard --> - <fraction name="config_key_vertical_gap_5row">3.20%p</fraction> - <fraction name="config_key_letter_ratio_5row">62%</fraction> - <fraction name="config_key_shifted_letter_hint_ratio_5row">36%</fraction> - - <dimen name="config_suggestions_strip_horizontal_padding">252.0dp</dimen> - <integer name="config_max_more_suggestions_row">5</integer> - <fraction name="config_min_more_suggestions_width">50%</fraction> - - <!-- Gesture floating preview text parameters --> - <dimen name="config_gesture_floating_preview_text_size">26dp</dimen> - <dimen name="config_gesture_floating_preview_text_offset">76dp</dimen> - <dimen name="config_gesture_floating_preview_horizontal_padding">26dp</dimen> - <dimen name="config_gesture_floating_preview_vertical_padding">17dp</dimen> - - <!-- Emoji keyboard --> - <fraction name="config_emoji_keyboard_key_width">10%p</fraction> - <fraction name="config_emoji_keyboard_row_height">33%p</fraction> - <fraction name="config_emoji_keyboard_key_letter_size">70%p</fraction> - <integer name="config_emoji_keyboard_max_page_key_count">30</integer> </resources> diff --git a/java/res/values-sw540dp-land/dimens.xml b/java/res/values-sw540dp-land/dimens.xml new file mode 100644 index 000000000..002493798 --- /dev/null +++ b/java/res/values-sw540dp-land/dimens.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<resources> + <!-- Preferable keyboard height in absolute scale: 45.0mm --> + <!-- This keyboardHeight value should match with keyboard-heights.xml --> + <dimen name="keyboardHeight">283.5dp</dimen> + <fraction name="minKeyboardHeight">45%p</fraction> + + <fraction name="keyboard_top_padding_gb">2.444%p</fraction> + <fraction name="keyboard_bottom_padding_gb">0.0%p</fraction> + <fraction name="key_bottom_gap_gb">5.200%p</fraction> + <fraction name="key_horizontal_gap_gb">1.447%p</fraction> + + <fraction name="keyboard_top_padding_holo">2.727%p</fraction> + <fraction name="keyboard_bottom_padding_holo">0.0%p</fraction> + <fraction name="key_bottom_gap_holo">4.5%p</fraction> + <fraction name="key_horizontal_gap_holo">0.9%p</fraction> + + <dimen name="popup_key_height">81.9dp</dimen> + + <!-- left or right padding of label alignment --> + <dimen name="key_label_horizontal_padding">18dp</dimen> + + <fraction name="key_letter_ratio">50%</fraction> + <fraction name="key_large_letter_ratio">48%</fraction> + <fraction name="key_label_ratio">32%</fraction> + <fraction name="key_hint_letter_ratio">23%</fraction> + <fraction name="key_hint_label_ratio">34%</fraction> + <fraction name="key_uppercase_letter_ratio">29%</fraction> + <fraction name="spacebar_text_ratio">30.0%</fraction> + <dimen name="key_uppercase_letter_padding">4dp</dimen> + + <!-- For 5-row keyboard --> + <fraction name="key_bottom_gap_5row">3.20%p</fraction> + <fraction name="key_letter_ratio_5row">62%</fraction> + <fraction name="key_uppercase_letter_ratio_5row">36%</fraction> + + <dimen name="suggestions_strip_padding">252.0dp</dimen> + <integer name="max_more_suggestions_row">5</integer> + <fraction name="min_more_suggestions_width">50%</fraction> + + <!-- Gesture floating preview text parameters --> + <dimen name="gesture_floating_preview_text_size">26dp</dimen> + <dimen name="gesture_floating_preview_text_offset">76dp</dimen> + <dimen name="gesture_floating_preview_horizontal_padding">26dp</dimen> + <dimen name="gesture_floating_preview_vertical_padding">17dp</dimen> + + <!-- Emoji keyboard --> + <fraction name="emoji_keyboard_key_width">10%p</fraction> + <fraction name="emoji_keyboard_row_height">33%p</fraction> + <fraction name="emoji_keyboard_key_letter_size">70%p</fraction> + <integer name="emoji_keyboard_max_key_count">30</integer> + +</resources> diff --git a/java/res/values-sw540dp/config-per-form-factor.xml b/java/res/values-sw540dp/config-per-form-factor.xml deleted file mode 100644 index 7f898e017..000000000 --- a/java/res/values-sw540dp/config-per-form-factor.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 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. -*/ ---> - -<!-- Configuration values for Large Phone. --> -<resources> - <bool name="config_enable_show_key_preview_popup_option">false</bool> - <!-- Whether or not Popup on key press is enabled by default --> - <bool name="config_default_key_preview_popup">false</bool> - <bool name="config_default_sound_enabled">true</bool> - <bool name="config_enable_show_voice_key_option">true</bool> - <bool name="config_key_selection_by_dragging_finger">false</bool> - <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if - false --> - <bool name="config_show_more_keys_keyboard_at_touched_point">false</bool> -</resources> diff --git a/java/res/values-sw540dp/config.xml b/java/res/values-sw540dp/config.xml index 8637d6bab..027780ce3 100644 --- a/java/res/values-sw540dp/config.xml +++ b/java/res/values-sw540dp/config.xml @@ -18,78 +18,22 @@ */ --> -<!-- Configuration values for Large Phone and Small Tablet Portrait. --> <resources> + <bool name="config_enable_show_option_of_key_preview_popup">false</bool> + <bool name="config_enable_bigram_suggestions_option">false</bool> + <!-- Whether or not Popup on key press is enabled by default --> + <bool name="config_default_key_preview_popup">false</bool> + <bool name="config_default_sound_enabled">true</bool> + <bool name="config_auto_correction_spacebar_led_enabled">false</bool> + <!-- The language is never displayed if == 0, always displayed if < 0 --> + <integer name="config_delay_before_fadeout_language_on_spacebar">1200</integer> + <integer name="config_max_more_keys_column">5</integer> + <!-- + Configuration for MainKeyboardView + --> <dimen name="config_key_hysteresis_distance">40.0dp</dimen> - - <!-- Preferable keyboard height in absolute scale: 48.0mm --> - <!-- This config_default_keyboard_height value should match with keyboard-heights.xml --> - <dimen name="config_default_keyboard_height">302.4dp</dimen> - <fraction name="config_max_keyboard_height">46%p</fraction> - <fraction name="config_min_keyboard_height">-35.0%p</fraction> - - <dimen name="config_more_keys_keyboard_key_height">63.0dp</dimen> - <dimen name="config_more_keys_keyboard_key_horizontal_padding">6dp</dimen> - <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. --> - <!-- config_more_keys_keyboard_key_height x 1.2 --> - <dimen name="config_more_keys_keyboard_slide_allowance">98.3dp</dimen> - - <fraction name="config_keyboard_top_padding_gb">2.291%p</fraction> - <fraction name="config_keyboard_bottom_padding_gb">0.0%p</fraction> - <fraction name="config_key_vertical_gap_gb">4.625%p</fraction> - <fraction name="config_key_horizontal_gap_gb">2.113%p</fraction> - <!-- config_more_keys_keyboard_key_height x -1.0 --> - <dimen name="config_more_keys_keyboard_vertical_correction_gb">-81.9dp</dimen> - <dimen name="config_key_preview_offset_gb">16.0dp</dimen> - - <fraction name="config_keyboard_top_padding_holo">2.335%p</fraction> - <fraction name="config_keyboard_bottom_padding_holo">4.0%p</fraction> - <fraction name="config_key_vertical_gap_holo">4.5%p</fraction> - <fraction name="config_key_horizontal_gap_holo">1.565%p</fraction> - <!-- config_more_keys_keyboard_key_height x -0.5 --> - <dimen name="config_more_keys_keyboard_vertical_correction_holo">-31.5dp</dimen> - <dimen name="config_key_preview_offset_holo">8.0dp</dimen> - - <dimen name="config_key_preview_height">94.5dp</dimen> - <fraction name="config_key_preview_text_ratio">50%</fraction> - <fraction name="config_key_letter_ratio">42%</fraction> - <fraction name="config_key_large_letter_ratio">45%</fraction> - <fraction name="config_key_label_ratio">25%</fraction> - <fraction name="config_key_large_label_ratio">32%</fraction> - <fraction name="config_key_hint_letter_ratio">23%</fraction> - <fraction name="config_key_hint_label_ratio">28%</fraction> - <fraction name="config_key_shifted_letter_hint_ratio">22%</fraction> - <fraction name="config_language_on_spacebar_text_ratio">28.0%</fraction> - <!-- left or right padding of label alignment --> - <dimen name="config_key_label_horizontal_padding">6dp</dimen> - <dimen name="config_key_hint_letter_padding">3dp</dimen> - <dimen name="config_key_shifted_letter_hint_padding">3dp</dimen> - - <!-- For 5-row keyboard --> - <fraction name="config_key_vertical_gap_5row">3.20%p</fraction> - <fraction name="config_key_letter_ratio_5row">52%</fraction> - <fraction name="config_key_shifted_letter_hint_ratio_5row">27%</fraction> - - <dimen name="config_suggestions_strip_height">44dp</dimen> - <dimen name="config_more_suggestions_row_height">44dp</dimen> - <integer name="config_max_more_suggestions_row">6</integer> - <fraction name="config_min_more_suggestions_width">90%</fraction> - <dimen name="config_suggestions_strip_horizontal_padding">94.5dp</dimen> - <dimen name="config_suggestion_min_width">48.0dp</dimen> - <dimen name="config_suggestion_text_horizontal_padding">12dp</dimen> - <dimen name="config_suggestion_text_size">22dp</dimen> - <dimen name="config_more_suggestions_hint_text_size">33dp</dimen> - - <!-- Gesture floating preview text parameters --> - <dimen name="config_gesture_floating_preview_text_size">28dp</dimen> - <dimen name="config_gesture_floating_preview_text_offset">87dp</dimen> - <dimen name="config_gesture_floating_preview_horizontal_padding">28dp</dimen> - <dimen name="config_gesture_floating_preview_vertical_padding">19dp</dimen> - <dimen name="config_gesture_floating_preview_round_radius">3dp</dimen> - - <!-- Emoji keyboard --> - <fraction name="config_emoji_keyboard_key_width">12.5%p</fraction> - <fraction name="config_emoji_keyboard_row_height">33%p</fraction> - <fraction name="config_emoji_keyboard_key_letter_size">60%p</fraction> - <integer name="config_emoji_keyboard_max_page_key_count">24</integer> + <bool name="config_sliding_key_input_enabled">false</bool> + <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if + false --> + <bool name="config_show_more_keys_keyboard_at_touched_point">true</bool> </resources> diff --git a/java/res/values-sw540dp/dimens.xml b/java/res/values-sw540dp/dimens.xml new file mode 100644 index 000000000..801b7acb5 --- /dev/null +++ b/java/res/values-sw540dp/dimens.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<resources> + <!-- Preferable keyboard height in absolute scale: 48.0mm --> + <!-- This keyboardHeight value should match with keyboard-heights.xml --> + <dimen name="keyboardHeight">302.4dp</dimen> + <fraction name="maxKeyboardHeight">46%p</fraction> + <fraction name="minKeyboardHeight">-35.0%p</fraction> + + <dimen name="popup_key_height">63.0dp</dimen> + + <fraction name="keyboard_top_padding_gb">2.291%p</fraction> + <fraction name="keyboard_bottom_padding_gb">0.0%p</fraction> + <fraction name="key_bottom_gap_gb">4.625%p</fraction> + <fraction name="key_horizontal_gap_gb">2.113%p</fraction> + + <fraction name="keyboard_top_padding_holo">2.335%p</fraction> + <fraction name="keyboard_bottom_padding_holo">4.0%p</fraction> + <fraction name="key_bottom_gap_holo">4.5%p</fraction> + <fraction name="key_horizontal_gap_holo">1.565%p</fraction> + + <dimen name="more_keys_keyboard_key_horizontal_padding">6dp</dimen> + <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. --> + <!-- popup_key_height x 1.2 --> + <dimen name="more_keys_keyboard_slide_allowance">98.3dp</dimen> + <!-- popup_key_height x -1.0 --> + <dimen name="more_keys_keyboard_vertical_correction_gb">-81.9dp</dimen> + + <!-- left or right padding of label alignment --> + <dimen name="key_label_horizontal_padding">6dp</dimen> + <dimen name="key_hint_letter_padding">3dp</dimen> + <dimen name="key_uppercase_letter_padding">3dp</dimen> + + <fraction name="key_letter_ratio">42%</fraction> + <fraction name="key_large_letter_ratio">45%</fraction> + <fraction name="key_label_ratio">25%</fraction> + <fraction name="key_large_label_ratio">32%</fraction> + <fraction name="key_hint_letter_ratio">23%</fraction> + <fraction name="key_hint_label_ratio">28%</fraction> + <fraction name="key_uppercase_letter_ratio">22%</fraction> + <fraction name="key_preview_text_ratio">50%</fraction> + <fraction name="spacebar_text_ratio">28.0%</fraction> + <dimen name="key_preview_height">94.5dp</dimen> + <dimen name="key_preview_offset_gb">16.0dp</dimen> + + <!-- For 5-row keyboard --> + <fraction name="key_bottom_gap_5row">3.20%p</fraction> + <fraction name="key_letter_ratio_5row">52%</fraction> + <fraction name="key_uppercase_letter_ratio_5row">27%</fraction> + + <dimen name="key_preview_offset_holo">8.0dp</dimen> + <!-- popup_key_height x -0.5 --> + <dimen name="more_keys_keyboard_vertical_correction_holo">-31.5dp</dimen> + + <dimen name="suggestions_strip_height">44dp</dimen> + <dimen name="more_suggestions_row_height">44dp</dimen> + <integer name="max_more_suggestions_row">6</integer> + <fraction name="min_more_suggestions_width">90%</fraction> + <dimen name="suggestions_strip_padding">94.5dp</dimen> + <dimen name="suggestion_min_width">48.0dp</dimen> + <dimen name="suggestion_padding">12dp</dimen> + <dimen name="suggestion_text_size">22dp</dimen> + <dimen name="more_suggestions_hint_text_size">33dp</dimen> + + <!-- Gesture trail parameters --> + <dimen name="gesture_trail_width">2.5dp</dimen> + <!-- Gesture floating preview text parameters --> + <dimen name="gesture_floating_preview_text_size">28dp</dimen> + <dimen name="gesture_floating_preview_text_offset">87dp</dimen> + <dimen name="gesture_floating_preview_horizontal_padding">28dp</dimen> + <dimen name="gesture_floating_preview_vertical_padding">19dp</dimen> + <dimen name="gesture_floating_preview_round_radius">3dp</dimen> + + <!-- Emoji keyboard --> + <fraction name="emoji_keyboard_key_width">12.5%p</fraction> + <fraction name="emoji_keyboard_row_height">33%p</fraction> + <fraction name="emoji_keyboard_key_letter_size">60%p</fraction> + <integer name="emoji_keyboard_max_key_count">24</integer> + +</resources> diff --git a/java/res/values-sw600dp/config-per-form-factor.xml b/java/res/values-sw600dp/config-per-form-factor.xml deleted file mode 100644 index 1c7e677a9..000000000 --- a/java/res/values-sw600dp/config-per-form-factor.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 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. -*/ ---> - -<!-- Configuration values for Small Tablet. --> -<resources> - <bool name="config_enable_show_key_preview_popup_option">false</bool> - <!-- Whether or not Popup on key press is enabled by default --> - <bool name="config_default_key_preview_popup">false</bool> - <bool name="config_default_sound_enabled">true</bool> - <bool name="config_enable_show_voice_key_option">false</bool> - <bool name="config_key_selection_by_dragging_finger">false</bool> - <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if - false --> - <bool name="config_show_more_keys_keyboard_at_touched_point">false</bool> -</resources> diff --git a/java/res/values-sw600dp/config-screen-metrics.xml b/java/res/values-sw600dp/config-screen-metrics.xml deleted file mode 100644 index e939c068f..000000000 --- a/java/res/values-sw600dp/config-screen-metrics.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<resources> - <!-- Screen metrics for logging. - 0 = "small phone screen" - 1 = "large phone screen" - 2 = "large tablet screen" - 3 = "small tablet screen" - --> - <integer name="log_screen_metrics">3</integer> -</resources> diff --git a/java/res/xml/kbd_swiss.xml b/java/res/values-sw600dp/config.xml index c64ad1103..e72e4941e 100644 --- a/java/res/xml/kbd_swiss.xml +++ b/java/res/values-sw600dp/config.xml @@ -18,9 +18,6 @@ */ --> -<Keyboard - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/rows_swiss" /> -</Keyboard> +<resources> + <bool name="config_enable_show_voice_key_option">false</bool> +</resources> diff --git a/java/res/values-sw768dp-land/config.xml b/java/res/values-sw768dp-land/config.xml index b97872f54..b3cd7278d 100644 --- a/java/res/values-sw768dp-land/config.xml +++ b/java/res/values-sw768dp-land/config.xml @@ -18,56 +18,6 @@ */ --> -<!-- Configuration values for Large Tablet Landscape. --> <resources> <bool name="config_use_fullscreen_mode">false</bool> - - <!-- Preferable keyboard height in absolute scale: 58.0mm --> - <!-- This config_default_keyboard_height value should match with keyboard-heights.xml --> - <dimen name="config_default_keyboard_height">365.4dp</dimen> - <fraction name="config_min_keyboard_height">45%p</fraction> - - <fraction name="config_keyboard_top_padding_gb">1.896%p</fraction> - <fraction name="config_keyboard_bottom_padding_gb">0.0%p</fraction> - <fraction name="config_key_vertical_gap_gb">3.896%p</fraction> - <fraction name="config_key_horizontal_gap_gb">1.195%p</fraction> - - <fraction name="config_keyboard_top_padding_holo">1.896%p</fraction> - <fraction name="config_keyboard_bottom_padding_holo">0.0%p</fraction> - <fraction name="config_key_vertical_gap_holo">3.690%p</fraction> - <fraction name="config_key_horizontal_gap_holo">1.030%p</fraction> - <dimen name="config_key_preview_offset_holo">8.0dp</dimen> - - <dimen name="config_more_keys_keyboard_key_height">81.9dp</dimen> - - <dimen name="config_key_preview_height">107.1dp</dimen> - <fraction name="config_key_letter_ratio">43%</fraction> - <fraction name="config_key_large_letter_ratio">42%</fraction> - <fraction name="config_key_label_ratio">28%</fraction> - <fraction name="config_key_hint_letter_ratio">23%</fraction> - <fraction name="config_key_hint_label_ratio">28%</fraction> - <fraction name="config_key_shifted_letter_hint_ratio">24%</fraction> - <fraction name="config_language_on_spacebar_text_ratio">24.00%</fraction> - <!-- left or right padding of label alignment --> - <dimen name="config_key_label_horizontal_padding">18dp</dimen> - - <!-- For 5-row keyboard --> - <fraction name="config_key_vertical_gap_5row">2.65%p</fraction> - <fraction name="config_key_letter_ratio_5row">53%</fraction> - <fraction name="config_key_shifted_letter_hint_ratio_5row">30%</fraction> - - <dimen name="config_suggestions_strip_horizontal_padding">252.0dp</dimen> - <fraction name="config_min_more_suggestions_width">50%</fraction> - - <!-- Gesture floating preview text parameters --> - <dimen name="config_gesture_floating_preview_text_size">32dp</dimen> - <dimen name="config_gesture_floating_preview_text_offset">100dp</dimen> - <dimen name="config_gesture_floating_preview_horizontal_padding">32dp</dimen> - <dimen name="config_gesture_floating_preview_vertical_padding">21dp</dimen> - - <!-- Emoji keyboard --> - <fraction name="config_emoji_keyboard_key_width">7.69%p</fraction> - <fraction name="config_emoji_keyboard_row_height">33%p</fraction> - <fraction name="config_emoji_keyboard_key_letter_size">60%p</fraction> - <integer name="config_emoji_keyboard_max_page_key_count">39</integer> </resources> diff --git a/java/res/values-sw768dp-land/dimens.xml b/java/res/values-sw768dp-land/dimens.xml new file mode 100644 index 000000000..653f5e7d5 --- /dev/null +++ b/java/res/values-sw768dp-land/dimens.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2010, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<resources> + <!-- Preferable keyboard height in absolute scale: 58.0mm --> + <!-- This keyboardHeight value should match with keyboard-heights.xml --> + <dimen name="keyboardHeight">365.4dp</dimen> + <fraction name="minKeyboardHeight">45%p</fraction> + + <fraction name="keyboard_top_padding_gb">1.896%p</fraction> + <fraction name="keyboard_bottom_padding_gb">0.0%p</fraction> + <fraction name="key_bottom_gap_gb">3.896%p</fraction> + <fraction name="key_horizontal_gap_gb">1.195%p</fraction> + + <fraction name="keyboard_top_padding_holo">1.896%p</fraction> + <fraction name="keyboard_bottom_padding_holo">0.0%p</fraction> + <fraction name="key_bottom_gap_holo">3.690%p</fraction> + <fraction name="key_horizontal_gap_holo">1.030%p</fraction> + + <dimen name="popup_key_height">81.9dp</dimen> + + <!-- left or right padding of label alignment --> + <dimen name="key_label_horizontal_padding">18dp</dimen> + + <fraction name="key_letter_ratio">43%</fraction> + <fraction name="key_large_letter_ratio">42%</fraction> + <fraction name="key_label_ratio">28%</fraction> + <fraction name="key_hint_letter_ratio">23%</fraction> + <fraction name="key_hint_label_ratio">28%</fraction> + <fraction name="key_uppercase_letter_ratio">24%</fraction> + <fraction name="spacebar_text_ratio">24.00%</fraction> + <dimen name="key_preview_height">107.1dp</dimen> + + <!-- For 5-row keyboard --> + <fraction name="key_bottom_gap_5row">2.65%p</fraction> + <fraction name="key_letter_ratio_5row">53%</fraction> + <fraction name="key_uppercase_letter_ratio_5row">30%</fraction> + + <dimen name="key_preview_offset_holo">8.0dp</dimen> + + <dimen name="suggestions_strip_padding">252.0dp</dimen> + <fraction name="min_more_suggestions_width">50%</fraction> + + <!-- Gesture floating preview text parameters --> + <dimen name="gesture_floating_preview_text_size">32dp</dimen> + <dimen name="gesture_floating_preview_text_offset">100dp</dimen> + <dimen name="gesture_floating_preview_horizontal_padding">32dp</dimen> + <dimen name="gesture_floating_preview_vertical_padding">21dp</dimen> + + <!-- Emoji keyboard --> + <fraction name="emoji_keyboard_key_width">7.69%p</fraction> + <fraction name="emoji_keyboard_row_height">33%p</fraction> + <fraction name="emoji_keyboard_key_letter_size">60%p</fraction> + <integer name="emoji_keyboard_max_key_count">39</integer> + +</resources> diff --git a/java/res/values-sw768dp/config-per-form-factor.xml b/java/res/values-sw768dp/config-per-form-factor.xml deleted file mode 100644 index 136f41567..000000000 --- a/java/res/values-sw768dp/config-per-form-factor.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 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. -*/ ---> - -<!-- Configuration values for Large Tablet. --> -<resources> - <bool name="config_enable_show_key_preview_popup_option">false</bool> - <!-- Whether or not Popup on key press is enabled by default --> - <bool name="config_default_key_preview_popup">false</bool> - <bool name="config_default_sound_enabled">true</bool> - <bool name="config_enable_show_voice_key_option">false</bool> - <bool name="config_key_selection_by_dragging_finger">false</bool> - <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if - false --> - <bool name="config_show_more_keys_keyboard_at_touched_point">true</bool> -</resources> diff --git a/java/res/values-sw768dp/config.xml b/java/res/values-sw768dp/config.xml index 33286c686..e1c07d6f8 100644 --- a/java/res/values-sw768dp/config.xml +++ b/java/res/values-sw768dp/config.xml @@ -18,76 +18,28 @@ */ --> -<!-- Configuration values for Large Tablet Portrait. --> <resources> - <!-- Preferable keyboard height in absolute scale: 48.0mm --> - <!-- This config_default_keyboard_height value should match with keyboard-heights.xml --> - <dimen name="config_default_keyboard_height">302.4dp</dimen> - <fraction name="config_max_keyboard_height">46%p</fraction> - <fraction name="config_min_keyboard_height">-35.0%p</fraction> - - <fraction name="config_keyboard_top_padding_gb">2.291%p</fraction> - <fraction name="config_keyboard_bottom_padding_gb">0.0%p</fraction> - <fraction name="config_key_vertical_gap_gb">4.687%p</fraction> - <fraction name="config_key_horizontal_gap_gb">1.272%p</fraction> - <!-- config_more_keys_keyboard_key_height x -1.0 --> - <dimen name="config_more_keys_keyboard_vertical_correction_gb">-81.9dp</dimen> - <dimen name="config_key_preview_offset_gb">16.0dp</dimen> - - <fraction name="config_keyboard_top_padding_holo">2.335%p</fraction> - <fraction name="config_keyboard_bottom_padding_holo">0.0%p</fraction> - <fraction name="config_key_vertical_gap_holo">3.312%p</fraction> - <fraction name="config_key_horizontal_gap_holo">1.066%p</fraction> - <!-- config_more_keys_keyboard_key_height x -0.5 --> - <dimen name="config_more_keys_keyboard_vertical_correction_holo">-31.5dp</dimen> - <dimen name="config_key_preview_offset_holo">8.0dp</dimen> - - <dimen name="config_more_keys_keyboard_key_height">63.0dp</dimen> - <dimen name="config_more_keys_keyboard_key_horizontal_padding">12dp</dimen> - <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. --> - <!-- config_more_keys_keyboard_key_height x 1.2 --> - <dimen name="config_more_keys_keyboard_slide_allowance">98.3dp</dimen> - - <dimen name="config_key_preview_height">94.5dp</dimen> - <fraction name="config_key_preview_text_ratio">50%</fraction> - <fraction name="config_key_letter_ratio">40%</fraction> - <fraction name="config_key_large_letter_ratio">42%</fraction> - <fraction name="config_key_label_ratio">28%</fraction> - <fraction name="config_key_large_label_ratio">28%</fraction> - <fraction name="config_key_hint_letter_ratio">23%</fraction> - <fraction name="config_key_hint_label_ratio">28%</fraction> - <fraction name="config_key_shifted_letter_hint_ratio">26%</fraction> - <fraction name="config_language_on_spacebar_text_ratio">29.03%</fraction> - <!-- left or right padding of label alignment --> - <dimen name="config_key_label_horizontal_padding">6dp</dimen> - <dimen name="config_key_hint_letter_padding">3dp</dimen> - <dimen name="config_key_shifted_letter_hint_padding">3dp</dimen> - - <!-- For 5-row keyboard --> - <fraction name="config_key_vertical_gap_5row">2.95%p</fraction> - <fraction name="config_key_letter_ratio_5row">51%</fraction> - <fraction name="config_key_shifted_letter_hint_ratio_5row">33%</fraction> - - <dimen name="config_suggestions_strip_height">44dp</dimen> - <dimen name="config_more_suggestions_row_height">44dp</dimen> - <integer name="config_max_more_suggestions_row">6</integer> - <fraction name="config_min_more_suggestions_width">90%</fraction> - <dimen name="config_suggestions_strip_horizontal_padding">94.5dp</dimen> - <dimen name="config_suggestion_min_width">46dp</dimen> - <dimen name="config_suggestion_text_horizontal_padding">8dp</dimen> - <dimen name="config_suggestion_text_size">22dp</dimen> - <dimen name="config_more_suggestions_hint_text_size">33dp</dimen> - - <!-- Gesture floating preview text parameters --> - <dimen name="config_gesture_floating_preview_text_size">26dp</dimen> - <dimen name="config_gesture_floating_preview_text_offset">86dp</dimen> - <dimen name="config_gesture_floating_preview_horizontal_padding">26dp</dimen> - <dimen name="config_gesture_floating_preview_vertical_padding">17dp</dimen> - <dimen name="config_gesture_floating_preview_round_radius">3dp</dimen> - - <!-- Emoji keyboard --> - <fraction name="config_emoji_keyboard_key_width">10%p</fraction> - <fraction name="config_emoji_keyboard_row_height">33%p</fraction> - <fraction name="config_emoji_keyboard_key_letter_size">68%p</fraction> - <integer name="config_emoji_keyboard_max_page_key_count">30</integer> + <bool name="config_enable_show_voice_key_option">false</bool> + <bool name="config_enable_show_option_of_key_preview_popup">false</bool> + <bool name="config_enable_bigram_suggestions_option">false</bool> + <!-- Whether or not Popup on key press is enabled by default --> + <bool name="config_default_key_preview_popup">false</bool> + <bool name="config_default_sound_enabled">true</bool> + <bool name="config_auto_correction_spacebar_led_enabled">false</bool> + <integer name="config_max_more_keys_column">5</integer> + <!-- + Configuration for MainKeyboardView + --> + <bool name="config_sliding_key_input_enabled">false</bool> + <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if + false --> + <bool name="config_show_more_keys_keyboard_at_touched_point">true</bool> + <!-- Screen metrics for logging. + 0 = "mdpi phone screen" + 1 = "hdpi phone screen" + 2 = "mdpi 11 inch tablet screen" + 3 = "xhdpi phone screen?" + 4 = ? + --> + <integer name="log_screen_metrics">2</integer> </resources> diff --git a/java/res/values-sw768dp/dimens.xml b/java/res/values-sw768dp/dimens.xml new file mode 100644 index 000000000..4671aa28b --- /dev/null +++ b/java/res/values-sw768dp/dimens.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2010, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<resources> + <!-- Preferable keyboard height in absolute scale: 48.0mm --> + <!-- This keyboardHeight value should match with keyboard-heights.xml --> + <dimen name="keyboardHeight">302.4dp</dimen> + <fraction name="maxKeyboardHeight">46%p</fraction> + <fraction name="minKeyboardHeight">-35.0%p</fraction> + + <fraction name="keyboard_top_padding_gb">2.291%p</fraction> + <fraction name="keyboard_bottom_padding_gb">0.0%p</fraction> + <fraction name="key_bottom_gap_gb">4.687%p</fraction> + <fraction name="key_horizontal_gap_gb">1.272%p</fraction> + + <fraction name="keyboard_top_padding_holo">2.335%p</fraction> + <fraction name="keyboard_bottom_padding_holo">0.0%p</fraction> + <fraction name="key_bottom_gap_holo">3.312%p</fraction> + <fraction name="key_horizontal_gap_holo">1.066%p</fraction> + + <dimen name="popup_key_height">63.0dp</dimen> + + <dimen name="more_keys_keyboard_key_horizontal_padding">12dp</dimen> + <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. --> + <!-- popup_key_height x 1.2 --> + <dimen name="more_keys_keyboard_slide_allowance">98.3dp</dimen> + <!-- popup_key_height x -1.0 --> + <dimen name="more_keys_keyboard_vertical_correction_gb">-81.9dp</dimen> + + <!-- left or right padding of label alignment --> + <dimen name="key_label_horizontal_padding">6dp</dimen> + <dimen name="key_hint_letter_padding">3dp</dimen> + <dimen name="key_uppercase_letter_padding">3dp</dimen> + + <fraction name="key_letter_ratio">40%</fraction> + <fraction name="key_large_letter_ratio">42%</fraction> + <fraction name="key_label_ratio">28%</fraction> + <fraction name="key_large_label_ratio">28%</fraction> + <fraction name="key_hint_letter_ratio">23%</fraction> + <fraction name="key_hint_label_ratio">28%</fraction> + <fraction name="key_uppercase_letter_ratio">26%</fraction> + <fraction name="key_preview_text_ratio">50%</fraction> + <fraction name="spacebar_text_ratio">29.03%</fraction> + <dimen name="key_preview_height">94.5dp</dimen> + <dimen name="key_preview_offset_gb">16.0dp</dimen> + + <!-- For 5-row keyboard --> + <fraction name="key_bottom_gap_5row">2.95%p</fraction> + <fraction name="key_letter_ratio_5row">51%</fraction> + <fraction name="key_uppercase_letter_ratio_5row">33%</fraction> + + <dimen name="key_preview_offset_holo">8.0dp</dimen> + <!-- popup_key_height x -0.5 --> + <dimen name="more_keys_keyboard_vertical_correction_holo">-31.5dp</dimen> + + <dimen name="suggestions_strip_height">44dp</dimen> + <dimen name="more_suggestions_row_height">44dp</dimen> + <integer name="max_more_suggestions_row">6</integer> + <fraction name="min_more_suggestions_width">90%</fraction> + <dimen name="suggestions_strip_padding">94.5dp</dimen> + <dimen name="suggestion_min_width">46dp</dimen> + <dimen name="suggestion_padding">8dp</dimen> + <dimen name="suggestion_text_size">22dp</dimen> + <dimen name="more_suggestions_hint_text_size">33dp</dimen> + + <!-- Gesture trail parameters --> + <dimen name="gesture_trail_width">2.5dp</dimen> + <!-- Gesture floating preview text parameters --> + <dimen name="gesture_floating_preview_text_size">26dp</dimen> + <dimen name="gesture_floating_preview_text_offset">86dp</dimen> + <dimen name="gesture_floating_preview_horizontal_padding">26dp</dimen> + <dimen name="gesture_floating_preview_vertical_padding">17dp</dimen> + <dimen name="gesture_floating_preview_round_radius">3dp</dimen> + + <!-- Emoji keyboard --> + <fraction name="emoji_keyboard_key_width">10%p</fraction> + <fraction name="emoji_keyboard_row_height">33%p</fraction> + <fraction name="emoji_keyboard_key_letter_size">68%p</fraction> + <integer name="emoji_keyboard_max_key_count">30</integer> + +</resources> diff --git a/java/res/values-th/config-spacing-and-punctuations.xml b/java/res/values-th/donottranslate.xml index a9893feec..a9893feec 100644 --- a/java/res/values-th/config-spacing-and-punctuations.xml +++ b/java/res/values-th/donottranslate.xml diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml index 8b1567679..9249c05d5 100644 --- a/java/res/values-th/strings.xml +++ b/java/res/values-th/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"เวลา"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"แป้นการป้อนข้อมูลด้วยเสียง"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"บนแป้นพิมพ์หลัก"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"บนแป้นพิมพ์สัญลักษณ์"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"ปิด"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"ไมค์บนแป้นพิมพ์หลัก"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"ไมค์บนแป้นพิมพ์สัญลักษณ์"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"ปิดใช้งานป้อนข้อมูลด้วยเสียง"</string> <string name="configure_input_method" msgid="373356270290742459">"กำหนดค่าวิธีการป้อนข้อมูล"</string> <string name="language_selection_title" msgid="1651299598555326750">"ภาษาในการป้อนข้อมูล"</string> <string name="send_feedback" msgid="1780431884109392046">"ส่งข้อเสนอแนะ"</string> diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml index 5da0861a9..df6bda09b 100644 --- a/java/res/values-tl/strings.xml +++ b/java/res/values-tl/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"oras"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Voice input key"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Sa pangunahing keyboard"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Sa keyboard ng mga simbolo"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Naka-off"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic sa pangunahing keyboard"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic sa keyboard ng mga simbolo"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hindi pinagana ang voice input"</string> <string name="configure_input_method" msgid="373356270290742459">"I-configure ang mga pamamaraan ng pag-input"</string> <string name="language_selection_title" msgid="1651299598555326750">"Mag-input ng mga wika"</string> <string name="send_feedback" msgid="1780431884109392046">"Magpadala ng feedback"</string> diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml index 7304f464b..a14295153 100644 --- a/java/res/values-tr/strings.xml +++ b/java/res/values-tr/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"saat"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Ses girişi tuşu"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Ana klavyede"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Simge klavyesinde"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Kapalı"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Ana klavyedeki mikrofon"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Simge klavysnd mikrf"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Sesle grş devre dışı"</string> <string name="configure_input_method" msgid="373356270290742459">"Giriş yöntemlerini yapılandır"</string> <string name="language_selection_title" msgid="1651299598555326750">"Giriş dilleri"</string> <string name="send_feedback" msgid="1780431884109392046">"Geri bildirim gönder"</string> diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml index ab952912d..da26d5005 100644 --- a/java/res/values-uk/strings.xml +++ b/java/res/values-uk/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"час"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL-адреси"</string> <string name="voice_input" msgid="3583258583521397548">"Ключ голосового вводу"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"На основ. клавіатурі"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Символьна клавіатура"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Вимк."</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Мікрофон на основній клавіатурі"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Miкр. на симв. клавіат."</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Голос. ввід вимкнено"</string> <string name="configure_input_method" msgid="373356270290742459">"Налаштування методів введення"</string> <string name="language_selection_title" msgid="1651299598555326750">"Мови вводу"</string> <string name="send_feedback" msgid="1780431884109392046">"Надіслати відгук"</string> diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml index d75016a0a..81cd373e4 100644 --- a/java/res/values-vi/strings.xml +++ b/java/res/values-vi/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"giờ"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string> <string name="voice_input" msgid="3583258583521397548">"Khóa nhập giọng nói"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Trên bàn phím chính"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Trên bàn phím biểu tượng"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"Tắt"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micrô trên bàn phím chính"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micrô trên bàn phím biểu tượng"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Nhập liệu bằng giọng nói đã bị tắt"</string> <string name="configure_input_method" msgid="373356270290742459">"Định cấu hình phương thức nhập"</string> <string name="language_selection_title" msgid="1651299598555326750">"Ngôn ngữ nhập"</string> <string name="send_feedback" msgid="1780431884109392046">"Gửi phản hồi"</string> diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml index 1b59935a2..d347c9ce8 100644 --- a/java/res/values-zh-rCN/strings.xml +++ b/java/res/values-zh-rCN/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"时间"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"网址"</string> <string name="voice_input" msgid="3583258583521397548">"语音输入键"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"主键盘上"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"符号键盘上"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"关闭"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"主键盘上的麦克风"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"符号键盘上的麦克风"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"语音输入功能已停用"</string> <string name="configure_input_method" msgid="373356270290742459">"配置输入法"</string> <string name="language_selection_title" msgid="1651299598555326750">"输入语言"</string> <string name="send_feedback" msgid="1780431884109392046">"发送反馈"</string> diff --git a/java/res/values-zh-rHK/strings.xml b/java/res/values-zh-rHK/strings.xml index 665728db7..306045591 100644 --- a/java/res/values-zh-rHK/strings.xml +++ b/java/res/values-zh-rHK/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"時間"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"網址"</string> <string name="voice_input" msgid="3583258583521397548">"語音輸入鍵"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"於主鍵盤"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"符號鍵盤上"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"關閉"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"主鍵盤上的麥克風"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"符號鍵盤上的麥克風"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"語音輸入已停用"</string> <string name="configure_input_method" msgid="373356270290742459">"設定輸入法"</string> <string name="language_selection_title" msgid="1651299598555326750">"輸入語言"</string> <string name="send_feedback" msgid="1780431884109392046">"傳送意見"</string> diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml index d082fc744..2c474b79e 100644 --- a/java/res/values-zh-rTW/strings.xml +++ b/java/res/values-zh-rTW/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"時間"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"網址"</string> <string name="voice_input" msgid="3583258583521397548">"語音輸入按鍵"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"主鍵盤上"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"符號鍵盤上"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"關閉"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"主鍵盤上的麥克風"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"符號鍵盤上的麥克風"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"語音輸入已停用"</string> <string name="configure_input_method" msgid="373356270290742459">"設定輸入法"</string> <string name="language_selection_title" msgid="1651299598555326750">"輸入語言"</string> <string name="send_feedback" msgid="1780431884109392046">"提供意見"</string> diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml index fb2cd6e34..27d11316c 100644 --- a/java/res/values-zu/strings.xml +++ b/java/res/values-zu/strings.xml @@ -117,6 +117,12 @@ <string name="keyboard_mode_time" msgid="4381856885582143277">"isikhathi"</string> <string name="keyboard_mode_url" msgid="1519819835514911218">"I-URL"</string> <string name="voice_input" msgid="3583258583521397548">"Inkinobho yokufaka izwi"</string> + <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Kwikhibhodi eyisisekelo"</string> + <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Ikhibhodi yezimpawu"</string> + <string name="voice_input_modes_off" msgid="3745699748218082014">"VALIWE"</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"I-mic kwikhibhodi eyisisekelo"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Ikhibhodi yezimpawu ze-mic"</string> + <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Okufakwayo ngezwi kuvinjelwe"</string> <string name="configure_input_method" msgid="373356270290742459">"Misa izindlela zokufakwayo"</string> <string name="language_selection_title" msgid="1651299598555326750">"Izilimi zokufakwayo"</string> <string name="send_feedback" msgid="1780431884109392046">"Thumela impendulo"</string> diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml index a9474a03a..31945d020 100644 --- a/java/res/values/attrs.xml +++ b/java/res/values/attrs.xml @@ -26,14 +26,14 @@ <attr name="keyboardViewStyle" format="reference" /> <!-- MainKeyboardView style --> <attr name="mainKeyboardViewStyle" format="reference" /> - <!-- Key preview text view style --> - <attr name="keyPreviewTextViewStyle" format="reference"/> <!-- EmojiPalettesView style --> <attr name="emojiPalettesViewStyle" format="reference" /> <!-- MoreKeysKeyboard style --> <attr name="moreKeysKeyboardStyle" format="reference" /> <!-- MoreKeysKeyboardView style --> <attr name="moreKeysKeyboardViewStyle" format="reference" /> + <!-- MoreKeysKeyboardView container style --> + <attr name="moreKeysKeyboardContainerStyle" format="reference" /> <!-- Suggestions strip style --> <attr name="suggestionStripViewStyle" format="reference" /> <!-- Suggestion word style --> @@ -41,9 +41,9 @@ </declare-styleable> <declare-styleable name="KeyboardView"> - <!-- Image for the key. This image needs to be a {@link StateListDrawable}, with the - following possible states: normal, pressed, checkable, checkable+pressed, - checkable+checked, checkable+checked+pressed. --> + <!-- Image for the key. This image needs to be a StateListDrawable, with the following + possible states: normal, pressed, checkable, checkable+pressed, checkable+checked, + checkable+checked+pressed. --> <attr name="keyBackground" format="reference" /> <!-- Image for the functional key used in Emoji layout. --> <attr name="keyBackgroundEmojiFunctional" format="reference" /> @@ -72,11 +72,9 @@ <attr name="autoCorrectionSpacebarLedEnabled" format="boolean" /> <attr name="autoCorrectionSpacebarLedIcon" format="reference" /> <!-- Size of the text for spacebar language label, in the proportion of key height. --> - <attr name="languageOnSpacebarTextRatio" format="fraction" /> - <attr name="languageOnSpacebarTextColor" format="color" /> - <attr name="languageOnSpacebarTextShadowColor" format="color" /> - <!-- Background image for the spacebar. --> - <attr name="spacebarBackground" format="reference" /> + <attr name="spacebarTextRatio" format="fraction" /> + <attr name="spacebarTextColor" format="color" /> + <attr name="spacebarTextShadowColor" format="color" /> <!-- Fadeout animator for spacebar language label. --> <attr name="languageOnSpacebarFinalAlpha" format="integer" /> <attr name="languageOnSpacebarFadeoutAnimator" format="reference" /> @@ -91,8 +89,8 @@ <attr name="touchNoiseThresholdTime" format="integer" /> <!-- Touch noise threshold distance in millimeter --> <attr name="touchNoiseThresholdDistance" format="dimension" /> - <!-- Enable key selection by dragging finger --> - <attr name="keySelectionByDraggingFinger" format="boolean" /> + <!-- Sliding key input enable --> + <attr name="slidingKeyInputEnable" format="boolean" /> <attr name="slidingKeyInputPreviewColor" format="color" /> <attr name="slidingKeyInputPreviewWidth" format="dimension" /> <attr name="slidingKeyInputPreviewBodyRatio" format="integer" /> @@ -111,10 +109,6 @@ <attr name="keyPreviewOffset" format="dimension" /> <!-- Height of the key press feedback popup. --> <attr name="keyPreviewHeight" format="dimension" /> - <!-- Duration of key preview popup zoom in animation in millisecond --> - <attr name="keyPreviewZoomInDuration" format="integer" /> - <!-- Duration of key preview popup zoom out animation in millisecond --> - <attr name="keyPreviewZoomOutDuration" format="integer" /> <!-- Delay after key releasing and key press feedback dismissing in millisecond --> <attr name="keyPreviewLingerTimeout" format="integer" /> <!-- Layout resource for more keys keyboard --> @@ -223,6 +217,7 @@ <attr name="iconSearchKey" format="reference" /> <attr name="iconTabKey" format="reference" /> <attr name="iconShortcutKey" format="reference" /> + <attr name="iconShortcutForLabel" format="reference" /> <attr name="iconSpaceKeyForNumberLayout" format="reference" /> <attr name="iconShiftKeyShifted" format="reference" /> <attr name="iconShortcutKeyDisabled" format="reference" /> @@ -281,8 +276,6 @@ <attr name="keyLabel" format="string" /> <!-- The hint label to display on the key in conjunction with the label. --> <attr name="keyHintLabel" format="string" /> - <!-- The vertical adjustment of key hint label in proportion to its height. --> - <attr name="keyHintLabelVerticalAdjustment" format="fraction" /> <!-- The key label flags. --> <attr name="keyLabelFlags" format="integer"> <!-- This should be aligned with Key.LABEL_FLAGS__* --> @@ -299,20 +292,17 @@ <flag name="hasPopupHint" value="0x200" /> <flag name="hasShiftedLetterHint" value="0x400" /> <flag name="hasHintLabel" value="0x800" /> - <!-- These two flags are currently unused. Leave these for possible future use. --> <flag name="withIconLeft" value="0x1000" /> <flag name="withIconRight" value="0x2000" /> <flag name="autoXScale" value="0x4000" /> - <!-- The autoScale value implies autoXScale bit on to optimize scaling code path. --> - <flag name="autoScale" value="0xc000" /> <!-- If true, character case of code, altCode, moreKeys, keyOutputText, keyLabel, or keyHintLabel will never be subject to change. --> - <flag name="preserveCase" value="0x10000" /> + <flag name="preserveCase" value="0x8000" /> <!-- If true, use keyShiftedLetterHintActivatedColor for the shifted letter hint and keyTextInactivatedColor for the primary key top label. --> - <flag name="shiftedLetterActivated" value="0x20000" /> + <flag name="shiftedLetterActivated" value="0x10000" /> <!-- If true, use EditorInfo.actionLabel for the key label. --> - <flag name="fromCustomActionLabel" value="0x40000" /> + <flag name="fromCustomActionLabel" value="0x20000" /> <!-- If true, disable keyHintLabel. --> <flag name="disableKeyHintLabel" value="0x40000000" /> <!-- If true, disable additionalMoreKeys. --> @@ -425,7 +415,8 @@ <attr name="navigatePrevious" format="boolean" /> <attr name="passwordInput" format="boolean" /> <attr name="clobberSettingsKey" format="boolean" /> - <attr name="supportsSwitchingToShortcutIme" format="boolean" /> + <attr name="shortcutKeyEnabled" format="boolean" /> + <attr name="shortcutKeyOnSymbols" format="boolean" /> <attr name="hasShortcutKey" format="boolean" /> <attr name="languageSwitchKeyEnabled" format="boolean" /> <attr name="isMultiLine" format="boolean" /> diff --git a/java/res/values/config-auto-correction-thresholds.xml b/java/res/values/config-auto-correction-thresholds.xml deleted file mode 100644 index 7d94a42a4..000000000 --- a/java/res/values/config-auto-correction-thresholds.xml +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<resources> - <!-- The array of auto correction threshold values. --> - <string-array name="auto_correction_threshold_values" translatable="false"> - <!-- Off, When auto correction setting is Off, this value is not used. --> - <item>floatMaxValue</item> - <!-- Modest : Suggestion whose normalized score is greater than this value - will be subject to auto-correction. --> - <item>0.185</item> - <!-- Aggressive --> - <item>0.067</item> - <!-- Very Aggressive : Suggestion whose normalized score is greater than this value - will be subject to auto-correction. "floatNegativeInfinity" is a special marker - string for Float.NEGATIVE_INFINITY --> - <item>floatNegativeInfinity</item> - </string-array> - - <!-- The index of the auto correction threshold values array. --> - <string name="auto_correction_threshold_mode_index_off" translatable="false">0</string> - <string name="auto_correction_threshold_mode_index_modest" translatable="false">1</string> - <string name="auto_correction_threshold_mode_index_aggressive" translatable="false">2</string> - <string name="auto_correction_threshold_mode_index_very_aggressive" translatable="false">3</string> - - <!-- The array of the auto correction threshold settings values. --> - <string-array name="auto_correction_threshold_mode_indexes" translatable="false"> - <item>@string/auto_correction_threshold_mode_index_off</item> - <item>@string/auto_correction_threshold_mode_index_modest</item> - <item>@string/auto_correction_threshold_mode_index_aggressive</item> - <item>@string/auto_correction_threshold_mode_index_very_aggressive</item> - </string-array> - <!-- The array of the human readable auto correction threshold settings entries. --> - <string-array name="auto_correction_threshold_modes" translatable="false"> - <item>@string/auto_correction_threshold_mode_off</item> - <item>@string/auto_correction_threshold_mode_modest</item> - <item>@string/auto_correction_threshold_mode_aggressive</item> - <item>@string/auto_correction_threshold_mode_very_aggressive</item> - </string-array> -</resources> diff --git a/java/res/values/config-common.xml b/java/res/values/config-common.xml deleted file mode 100644 index ab16a9045..000000000 --- a/java/res/values/config-common.xml +++ /dev/null @@ -1,142 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<resources> - <bool name="config_block_potentially_offensive">true</bool> - <!-- Default value for next word prediction: after entering a word and a space only, should we look - at input history to suggest a hopefully helpful suggestions for the next word? --> - <bool name="config_default_next_word_prediction">true</bool> - - <!-- This configuration is an index of {@link KeyboardSwitcher#KEYBOARD_THEMES[]}. --> - <string name="config_default_keyboard_theme_index" translatable="false">2</string> - - <integer name="config_delay_update_shift_state">100</integer> - <integer name="config_double_space_period_timeout">1100</integer> - - <integer name="config_key_repeat_start_timeout">400</integer> - <integer name="config_key_repeat_interval">50</integer> - - <integer name="config_ignore_alt_code_key_timeout">350</integer> - - <integer name="config_key_preview_zoom_in_duration">35</integer> - <integer name="config_key_preview_zoom_out_duration">40</integer> - <integer name="config_key_preview_linger_timeout">70</integer> - <!-- Suppress showing key preview duration after batch input in millisecond --> - <integer name="config_suppress_key_preview_after_batch_input_duration">1000</integer> - - <bool name="config_default_vibration_enabled">true</bool> - <integer name="config_max_vibration_duration">100</integer> - - <integer name="config_default_longpress_key_timeout">300</integer> - <integer name="config_max_longpress_timeout">700</integer> - <integer name="config_min_longpress_timeout">100</integer> - <integer name="config_longpress_timeout_step">10</integer> - <integer name="config_max_more_keys_column">5</integer> - <integer name="config_more_keys_keyboard_fadein_anim_time">0</integer> - <integer name="config_more_keys_keyboard_fadeout_anim_time">100</integer> - - <!-- Long pressing shift will invoke caps-lock if > 0, never invoke caps-lock if == 0 --> - <integer name="config_longpress_shift_lock_timeout">1200</integer> - - <!-- Sliding key input preview parameters --> - <dimen name="config_sliding_key_input_preview_width">8.0dp</dimen> - <!-- Percentages of sliding key input preview body and shadow, in proportion to the width. - A negative value of the shadow ratio disables drawing shadow. --> - <!-- TODO: May use the shadow to alleviate rugged trail drawing. --> - <integer name="config_sliding_key_input_preview_body_ratio">100</integer> - <integer name="config_sliding_key_input_preview_shadow_ratio">-1</integer> - <dimen name="config_key_hysteresis_distance_for_sliding_modifier">8.0dp</dimen> - - <integer name="config_language_on_spacebar_final_alpha">128</integer> - <dimen name="config_language_on_spacebar_horizontal_margin">1dp</dimen> - - <integer name="config_gesture_floating_preview_text_linger_timeout">200</integer> - <integer name="config_gesture_trail_fadeout_start_delay">100</integer> - <integer name="config_gesture_trail_fadeout_duration">800</integer> - <integer name="config_gesture_trail_update_interval">20</integer> - <!-- Static threshold for gesture after fast typing (msec) --> - <integer name="config_gesture_static_time_threshold_after_fast_typing">500</integer> - <!-- Static threshold for starting gesture detection (keyWidth%/sec) --> - <fraction name="config_gesture_detect_fast_move_speed_threshold">150%</fraction> - <!-- Dynamic threshold for gesture after fast typing (msec) --> - <integer name="config_gesture_dynamic_threshold_decay_duration">450</integer> - <!-- Time based threshold values for gesture detection (msec) --> - <integer name="config_gesture_dynamic_time_threshold_from">300</integer> - <integer name="config_gesture_dynamic_time_threshold_to">20</integer> - <!-- Distance based threshold values for gesture detection (keyWidth%/sec) --> - <fraction name="config_gesture_dynamic_distance_threshold_from">600%</fraction> - <fraction name="config_gesture_dynamic_distance_threshold_to">50%</fraction> - <!-- Parameter for gesture sampling (keyWidth%/sec) --> - <fraction name="config_gesture_sampling_minimum_distance">16.6666%</fraction> - <!-- Parameters for gesture recognition (msec) and (keyWidth%/sec) --> - <integer name="config_gesture_recognition_minimum_time">100</integer> - <integer name="config_gesture_recognition_update_time">100</integer> - <fraction name="config_gesture_recognition_speed_threshold">550%</fraction> - - <integer name="config_keyboard_grid_width">32</integer> - <integer name="config_keyboard_grid_height">16</integer> - <dimen name="config_touch_noise_threshold_distance">12.6dp</dimen> - <integer name="config_touch_noise_threshold_time">40</integer> - - <!-- Common keyboard configuration. --> - <fraction name="config_keyboard_left_padding">0%p</fraction> - <fraction name="config_keyboard_right_padding">0%p</fraction> - <dimen name="config_keyboard_vertical_correction">0.0dp</dimen> - - <!-- Common key top visual configuration. --> - <dimen name="config_key_popup_hint_letter_padding">2dp</dimen> - - <!-- Common suggestion strip configuration. --> - <integer name="config_suggestions_count_in_strip">3</integer> - <fraction name="config_center_suggestion_percentile">36%</fraction> - <integer name="config_delay_update_suggestions">100</integer> - <integer name="config_delay_update_old_suggestions">300</integer> - - <!-- Common more suggestions configuraion. --> - <dimen name="config_more_suggestions_key_horizontal_padding">12dp</dimen> - <dimen name="config_more_suggestions_bottom_gap">6dp</dimen> - <dimen name="config_more_suggestions_modal_tolerance">32.0dp</dimen> - <fraction name="config_more_suggestions_info_ratio">18%</fraction> - - <!-- Common gesture trail parameters --> - <!-- Minimum distance between gesture trail sampling points. --> - <dimen name="config_gesture_trail_min_sampling_distance">9.6dp</dimen> - <!-- Maximum angular threshold between gesture trails interpolation segments in degree. --> - <integer name="config_gesture_trail_max_interpolation_angular_threshold">15</integer> - <!-- Maximum distance threshold between gesture trails interpolation segments. --> - <dimen name="config_gesture_trail_max_interpolation_distance_threshold">16.0dp</dimen> - <!-- Maximum number of gesture trail interpolation segments. --> - <integer name="config_gesture_trail_max_interpolation_segments">6</integer> - <dimen name="config_gesture_trail_start_width">10.0dp</dimen> - <dimen name="config_gesture_trail_end_width">2.5dp</dimen> - <!-- Percentages of gesture preview taril body and shadow, in proportion to the trail width. - A negative value of the shadow ratio disables drawing shadow. --> - <!-- TODO: May use the shadow to alleviate rugged trail drawing. --> - <integer name="config_gesture_trail_body_ratio">100</integer> - <integer name="config_gesture_trail_shadow_ratio">-1</integer> - - <!-- Common configuration of Emoji keyboard --> - <dimen name="config_emoji_category_page_id_height">3dp</dimen> - - <!-- Inset used in Accessibility mode to avoid accidental key presses when a finger slides off the screen. --> - <dimen name="config_accessibility_edge_slop">8dp</dimen> - - <integer name="config_user_dictionary_max_word_length">48</integer> -</resources> diff --git a/java/res/values/config-dictionary-pack.xml b/java/res/values/config-dictionary-pack.xml deleted file mode 100644 index d076af452..000000000 --- a/java/res/values/config-dictionary-pack.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 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. -*/ ---> - -<!-- Configuration values for Dictionary pack. --> -<resources> - <!-- Settings for the dictionary pack --> - <bool name="allow_over_metered">false</bool> - <bool name="allow_over_roaming">false</bool> - <bool name="dict_downloads_visible_in_download_UI">false</bool> - <bool name="metadata_downloads_visible_in_download_UI">false</bool> - <bool name="display_notification_for_auto_update">false</bool> - <bool name="display_notification_for_user_requested_update">false</bool> -</resources> diff --git a/java/res/values/config-per-form-factor.xml b/java/res/values/config-per-form-factor.xml deleted file mode 100644 index 67fc75134..000000000 --- a/java/res/values/config-per-form-factor.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 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. -*/ ---> - -<!-- Configuration values for Small Phone. --> -<resources> - <bool name="config_enable_show_key_preview_popup_option">true</bool> - <!-- Whether or not Popup on key press is enabled by default --> - <bool name="config_default_key_preview_popup">true</bool> - <bool name="config_default_sound_enabled">false</bool> - <bool name="config_enable_show_voice_key_option">true</bool> - <bool name="config_key_selection_by_dragging_finger">true</bool> - <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if - false --> - <bool name="config_show_more_keys_keyboard_at_touched_point">false</bool> -</resources> diff --git a/java/res/values/config-screen-metrics.xml b/java/res/values/config-screen-metrics.xml deleted file mode 100644 index 7b9870602..000000000 --- a/java/res/values/config-screen-metrics.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<resources> - <!-- Screen metrics for logging. - 0 = "small phone screen" - 1 = "large phone screen" - 2 = "large tablet screen" - 3 = "small tablet screen" - --> - <integer name="log_screen_metrics">0</integer> -</resources> diff --git a/java/res/values/config-spacing-and-punctuations.xml b/java/res/values/config-spacing-and-punctuations.xml deleted file mode 100644 index f10f810dc..000000000 --- a/java/res/values/config-spacing-and-punctuations.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- TODO: these settings depend on the language. They should be put either in the dictionary - header, or in the subtype maybe? --> - <!-- Symbols that are suggested between words --> - <string name="suggested_punctuations" translatable="false">!,?,\\,,:,;,\",(,),\',-,/,@,_</string> - <!-- Symbols that are normally preceded by a space (used to add an auto-space before these) --> - <string name="symbols_preceded_by_space" translatable="false">([{&</string> - <!-- Symbols that are normally followed by a space (used to add an auto-space after these) --> - <string name="symbols_followed_by_space" translatable="false">.,;:!?)]}&</string> - <!-- Symbols that separate words --> - <!-- Don't remove the enclosing double quotes, they protect whitespace (not just U+0020) --> - <string name="symbols_word_separators" translatable="false">"	 \n"()[]{}*&<>+=|.,;:!?/_\"</string> - <!-- Word connectors --> - <string name="symbols_word_connectors" translatable="false">\'-</string> - <!-- The sentence separator code point, for capitalization --> - <!-- U+002E: "." FULL STOP ; 2Eh = 46d --> - <integer name="sentence_separator" translatable="false">46</integer> - <!-- Whether this language uses spaces between words --> - <bool name="current_language_has_spaces">true</bool> -</resources> diff --git a/java/res/values/config.xml b/java/res/values/config.xml index e64b4b192..61779d4b5 100644 --- a/java/res/values/config.xml +++ b/java/res/values/config.xml @@ -18,79 +18,120 @@ */ --> -<!-- Configuration values for Small Phone Portrait. --> <resources> <bool name="config_use_fullscreen_mode">false</bool> + <bool name="config_enable_show_voice_key_option">true</bool> + <bool name="config_enable_show_option_of_key_preview_popup">true</bool> + <!-- TODO: Disable the following configuration for production. --> + <bool name="config_enable_usability_study_mode_option">true</bool> + <!-- Whether or not Popup on key press is enabled by default --> + <bool name="config_default_key_preview_popup">true</bool> + <!-- Default value for next word prediction: after entering a word and a space only, should we look + at input history to suggest a hopefully helpful suggestions for the next word? --> + <bool name="config_default_next_word_prediction">true</bool> + <bool name="config_default_sound_enabled">false</bool> + <bool name="config_default_vibration_enabled">true</bool> + <integer name="config_max_vibration_duration">100</integer> <!-- milliseconds --> + <integer name="config_delay_update_suggestions">100</integer> + <integer name="config_delay_update_old_suggestions">300</integer> + <integer name="config_delay_update_shift_state">100</integer> + <integer name="config_language_on_spacebar_final_alpha">128</integer> + <integer name="config_more_keys_keyboard_fadein_anim_time">0</integer> + <integer name="config_more_keys_keyboard_fadeout_anim_time">100</integer> + <integer name="config_keyboard_grid_width">32</integer> + <integer name="config_keyboard_grid_height">16</integer> + <integer name="config_double_space_period_timeout">1100</integer> + <!-- This configuration is an index of {@link KeyboardSwitcher#KEYBOARD_THEMES[]}. --> + <string name="config_default_keyboard_theme_index" translatable="false">2</string> + <integer name="config_max_more_keys_column">5</integer> + <!-- + Configuration for MainKeyboardView + --> <dimen name="config_key_hysteresis_distance">8.0dp</dimen> + <dimen name="config_key_hysteresis_distance_for_sliding_modifier">8.0dp</dimen> + <integer name="config_touch_noise_threshold_time">40</integer> + <dimen name="config_touch_noise_threshold_distance">12.6dp</dimen> + <integer name="config_key_preview_linger_timeout">70</integer> + <bool name="config_sliding_key_input_enabled">true</bool> + <!-- Sliding key input preview parameters --> + <dimen name="config_sliding_key_input_preview_width">8.0dp</dimen> + <!-- Percentages of sliding key input preview body and shadow, in proportion to the width. + A negative value of the shadow ratio disables drawing shadow. --> + <!-- TODO: May use the shadow to alleviate rugged trail drawing. --> + <integer name="config_sliding_key_input_preview_body_ratio">100</integer> + <integer name="config_sliding_key_input_preview_shadow_ratio">-1</integer> + <integer name="config_key_repeat_start_timeout">400</integer> + <integer name="config_key_repeat_interval">50</integer> + <integer name="config_default_longpress_key_timeout">300</integer> <!-- milliseconds --> + <integer name="config_longpress_timeout_step">10</integer> <!-- milliseconds --> + <integer name="config_min_longpress_timeout">100</integer> <!-- milliseconds --> + <integer name="config_max_longpress_timeout">700</integer> <!-- milliseconds --> + <!-- Long pressing shift will invoke caps-lock if > 0, never invoke caps-lock if == 0 --> + <integer name="config_longpress_shift_lock_timeout">1200</integer> <!-- milliseconds --> + <integer name="config_ignore_alt_code_key_timeout">350</integer> <!-- milliseconds --> + <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if + false --> + <bool name="config_show_more_keys_keyboard_at_touched_point">false</bool> + <bool name="config_block_potentially_offensive">true</bool> + <integer name="config_gesture_floating_preview_text_linger_timeout">200</integer> + <integer name="config_gesture_trail_fadeout_start_delay">100</integer> + <integer name="config_gesture_trail_fadeout_duration">800</integer> + <integer name="config_gesture_trail_update_interval">20</integer> + <!-- Static threshold for gesture after fast typing (msec) --> + <integer name="config_gesture_static_time_threshold_after_fast_typing">500</integer> + <!-- Static threshold for starting gesture detection (keyWidth%/sec) --> + <fraction name="config_gesture_detect_fast_move_speed_threshold">150%</fraction> + <!-- Dynamic threshold for gesture after fast typing (msec) --> + <integer name="config_gesture_dynamic_threshold_decay_duration">450</integer> + <!-- Time based threshold values for gesture detection (msec) --> + <integer name="config_gesture_dynamic_time_threshold_from">300</integer> + <integer name="config_gesture_dynamic_time_threshold_to">20</integer> + <!-- Distance based threshold values for gesture detection (keyWidth%/sec) --> + <fraction name="config_gesture_dynamic_distance_threshold_from">600%</fraction> + <fraction name="config_gesture_dynamic_distance_threshold_to">50%</fraction> + <!-- Parameter for gesture sampling (keyWidth%/sec) --> + <fraction name="config_gesture_sampling_minimum_distance">16.6666%</fraction> + <!-- Parameters for gesture recognition (msec) and (keyWidth%/sec) --> + <integer name="config_gesture_recognition_minimum_time">100</integer> + <integer name="config_gesture_recognition_update_time">100</integer> + <fraction name="config_gesture_recognition_speed_threshold">550%</fraction> + <!-- Suppress showing key preview duration after batch input in millisecond --> + <integer name="config_suppress_key_preview_after_batch_input_duration">1000</integer> + <!-- + Configuration for auto correction + --> + <string-array name="auto_correction_threshold_values" translatable="false"> + <!-- Off, When auto correction setting is Off, this value is not used. --> + <item>floatMaxValue</item> + <!-- Modest : Suggestion whose normalized score is greater than this value + will be subject to auto-correction. --> + <item>0.185</item> + <!-- Aggressive --> + <item>0.067</item> + <!-- Very Aggressive : Suggestion whose normalized score is greater than this value + will be subject to auto-correction. "floatNegativeInfinity" is a special marker + string for Float.NEGATIVE_INFINITY --> + <item>floatNegativeInfinity</item> + </string-array> + <!-- Threshold of the normalized score of the best suggestion for the spell checker to declare + a word to be "recommended" --> + <string name="spellchecker_recommended_threshold_value" translatable="false">0.11</string> + <!-- Screen metrics for logging. + 0 = "mdpi phone screen" + 1 = "hdpi phone screen" + 2 = "mdpi 11 inch tablet screen" + 3 = "xhdpi phone screen?" + 4 = ? + --> + <integer name="log_screen_metrics">0</integer> - <!-- Preferable keyboard height in absolute scale: 1.285in --> - <!-- This config_default_keyboard_height value should match with keyboard-heights.xml --> - <dimen name="config_default_keyboard_height">205.6dp</dimen> - <fraction name="config_max_keyboard_height">46%p</fraction> - <fraction name="config_min_keyboard_height">-61.8%p</fraction> + <!-- Settings for the dictionary pack --> + <bool name="allow_over_metered">false</bool> + <bool name="allow_over_roaming">false</bool> + <bool name="dict_downloads_visible_in_download_UI">false</bool> + <bool name="metadata_downloads_visible_in_download_UI">false</bool> + <bool name="display_notification_for_auto_update">false</bool> + <bool name="display_notification_for_user_requested_update">false</bool> - <dimen name="config_more_keys_keyboard_key_height">52.8dp</dimen> - <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. --> - <!-- config_more_keys_keyboard_key_height x 1.2 --> - <dimen name="config_more_keys_keyboard_slide_allowance">63.36dp</dimen> - <dimen name="config_more_keys_keyboard_key_horizontal_padding">8dp</dimen> - - <fraction name="config_keyboard_top_padding_gb">1.556%p</fraction> - <fraction name="config_keyboard_bottom_padding_gb">4.669%p</fraction> - <fraction name="config_key_vertical_gap_gb">6.495%p</fraction> - <fraction name="config_key_horizontal_gap_gb">1.971%p</fraction> - <!-- config_more_keys_keyboard_key_height x -1.0 --> - <dimen name="config_more_keys_keyboard_vertical_correction_gb">-52.8dp</dimen> - <dimen name="config_key_preview_offset_gb">-8.0dp</dimen> - - <fraction name="config_keyboard_top_padding_holo">2.335%p</fraction> - <fraction name="config_keyboard_bottom_padding_holo">4.669%p</fraction> - <fraction name="config_key_vertical_gap_holo">6.127%p</fraction> - <fraction name="config_key_horizontal_gap_holo">1.739%p</fraction> - <!-- config_more_keys_keyboard_key_height x -0.5 --> - <dimen name="config_more_keys_keyboard_vertical_correction_holo">-26.4dp</dimen> - <dimen name="config_key_preview_offset_holo">8.0dp</dimen> - - <dimen name="config_key_preview_height">80dp</dimen> - <fraction name="config_key_preview_text_ratio">82%</fraction> - <fraction name="config_key_letter_ratio">55%</fraction> - <fraction name="config_key_large_letter_ratio">65%</fraction> - <fraction name="config_key_label_ratio">34%</fraction> - <fraction name="config_key_large_label_ratio">40%</fraction> - <fraction name="config_key_hint_letter_ratio">25%</fraction> - <fraction name="config_key_hint_label_ratio">44%</fraction> - <fraction name="config_key_shifted_letter_hint_ratio">35%</fraction> - <fraction name="config_language_on_spacebar_text_ratio">33.735%</fraction> - <dimen name="config_key_label_horizontal_padding">4dp</dimen> - <dimen name="config_key_hint_letter_padding">1dp</dimen> - <dimen name="config_key_shifted_letter_hint_padding">2dp</dimen> - - <!-- For 5-row keyboard --> - <fraction name="config_key_vertical_gap_5row">3.20%p</fraction> - <fraction name="config_key_letter_ratio_5row">64%</fraction> - <fraction name="config_key_shifted_letter_hint_ratio_5row">41%</fraction> - - <dimen name="config_suggestions_strip_height">40dp</dimen> - <dimen name="config_more_suggestions_row_height">40dp</dimen> - <integer name="config_max_more_suggestions_row">6</integer> - <fraction name="config_min_more_suggestions_width">90%</fraction> - <dimen name="config_suggestions_strip_horizontal_padding">0dp</dimen> - <dimen name="config_suggestion_min_width">44dp</dimen> - <dimen name="config_suggestion_text_horizontal_padding">6dp</dimen> - <dimen name="config_suggestion_text_size">18dp</dimen> - <dimen name="config_more_suggestions_hint_text_size">27dp</dimen> - - <!-- Gesture floating preview text parameters --> - <dimen name="config_gesture_floating_preview_text_size">24dp</dimen> - <dimen name="config_gesture_floating_preview_text_offset">73dp</dimen> - <dimen name="config_gesture_floating_preview_horizontal_padding">24dp</dimen> - <dimen name="config_gesture_floating_preview_vertical_padding">16dp</dimen> - <dimen name="config_gesture_floating_preview_round_radius">2dp</dimen> - - <!-- Emoji keyboard --> - <fraction name="config_emoji_keyboard_key_width">14.2857%p</fraction> - <fraction name="config_emoji_keyboard_row_height">33%p</fraction> - <fraction name="config_emoji_keyboard_key_letter_size">68%p</fraction> - <integer name="config_emoji_keyboard_max_page_key_count">21</integer> </resources> diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml new file mode 100644 index 000000000..4588b10eb --- /dev/null +++ b/java/res/values/dimens.xml @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2008, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<resources> + <!-- Preferable keyboard height in absolute scale: 1.285in --> + <!-- This keyboardHeight value should match with keyboard-heights.xml --> + <dimen name="keyboardHeight">205.6dp</dimen> + <fraction name="maxKeyboardHeight">46%p</fraction> + <fraction name="minKeyboardHeight">-61.8%p</fraction> + + <dimen name="popup_key_height">52.8dp</dimen> + + <dimen name="more_keys_keyboard_key_horizontal_padding">8dp</dimen> + + <fraction name="keyboard_left_padding">0%p</fraction> + <fraction name="keyboard_right_padding">0%p</fraction> + + <fraction name="keyboard_top_padding_gb">1.556%p</fraction> + <fraction name="keyboard_bottom_padding_gb">4.669%p</fraction> + <fraction name="key_bottom_gap_gb">6.495%p</fraction> + <fraction name="key_horizontal_gap_gb">1.971%p</fraction> + + <fraction name="keyboard_top_padding_holo">2.335%p</fraction> + <fraction name="keyboard_bottom_padding_holo">4.669%p</fraction> + <fraction name="key_bottom_gap_holo">6.127%p</fraction> + <fraction name="key_horizontal_gap_holo">1.739%p</fraction> + + <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. --> + <!-- popup_key_height x 1.2 --> + <dimen name="more_keys_keyboard_slide_allowance">63.36dp</dimen> + <!-- popup_key_height x -1.0 --> + <dimen name="more_keys_keyboard_vertical_correction_gb">-52.8dp</dimen> + <dimen name="keyboard_vertical_correction">0.0dp</dimen> + + <fraction name="key_letter_ratio">55%</fraction> + <fraction name="key_large_letter_ratio">65%</fraction> + <fraction name="key_label_ratio">34%</fraction> + <fraction name="key_large_label_ratio">40%</fraction> + <fraction name="key_hint_letter_ratio">25%</fraction> + <fraction name="key_hint_label_ratio">44%</fraction> + <fraction name="key_uppercase_letter_ratio">35%</fraction> + <fraction name="key_preview_text_ratio">82%</fraction> + <fraction name="spacebar_text_ratio">33.735%</fraction> + <dimen name="key_preview_height">80dp</dimen> + <dimen name="key_preview_offset_gb">-8.0dp</dimen> + + <dimen name="key_label_horizontal_padding">4dp</dimen> + <dimen name="key_hint_letter_padding">1dp</dimen> + <dimen name="key_popup_hint_letter_padding">2dp</dimen> + <dimen name="key_uppercase_letter_padding">2dp</dimen> + + <!-- For 5-row keyboard --> + <fraction name="key_bottom_gap_5row">3.20%p</fraction> + <fraction name="key_letter_ratio_5row">64%</fraction> + <fraction name="key_uppercase_letter_ratio_5row">41%</fraction> + + <dimen name="key_preview_offset_holo">8.0dp</dimen> + <!-- popup_key_height x -0.5 --> + <dimen name="more_keys_keyboard_vertical_correction_holo">-26.4dp</dimen> + + <dimen name="suggestions_strip_height">40dp</dimen> + <dimen name="more_suggestions_key_horizontal_padding">12dp</dimen> + <dimen name="more_suggestions_row_height">40dp</dimen> + <dimen name="more_suggestions_bottom_gap">6dp</dimen> + <dimen name="more_suggestions_modal_tolerance">32.0dp</dimen> + <dimen name="more_suggestions_slide_allowance">16.0dp</dimen> + <integer name="max_more_suggestions_row">6</integer> + <fraction name="min_more_suggestions_width">90%</fraction> + <fraction name="more_suggestions_info_ratio">18%</fraction> + <dimen name="suggestions_strip_padding">0dp</dimen> + <dimen name="suggestion_min_width">44dp</dimen> + <dimen name="suggestion_padding">6dp</dimen> + <dimen name="suggestion_text_size">18dp</dimen> + <dimen name="more_suggestions_hint_text_size">27dp</dimen> + <integer name="suggestions_count_in_strip">3</integer> + <fraction name="center_suggestion_percentile">36%</fraction> + + <!-- Gesture trail parameters --> + <!-- Minimum distance between gesture trail sampling points. --> + <dimen name="gesture_trail_min_sampling_distance">9.6dp</dimen> + <!-- Maximum angular threshold between gesture trails interpolation segments in degree. --> + <integer name="gesture_trail_max_interpolation_angular_threshold">15</integer> + <!-- Maximum distance threshold between gesture trails interpolation segments. --> + <dimen name="gesture_trail_max_interpolation_distance_threshold">16.0dp</dimen> + <!-- Maximum number of gesture trail interpolation segments. --> + <integer name="gesture_trail_max_interpolation_segments">6</integer> + <dimen name="gesture_trail_start_width">10.0dp</dimen> + <dimen name="gesture_trail_end_width">2.5dp</dimen> + <!-- Percentages of gesture preview taril body and shadow, in proportion to the trail width. + A negative value of the shadow ratio disables drawing shadow. --> + <!-- TODO: May use the shadow to alleviate rugged trail drawing. --> + <integer name="gesture_trail_body_ratio">100</integer> + <integer name="gesture_trail_shadow_ratio">-1</integer> + <!-- Gesture floating preview text parameters --> + <dimen name="gesture_floating_preview_text_size">24dp</dimen> + <dimen name="gesture_floating_preview_text_offset">73dp</dimen> + <dimen name="gesture_floating_preview_horizontal_padding">24dp</dimen> + <dimen name="gesture_floating_preview_vertical_padding">16dp</dimen> + <dimen name="gesture_floating_preview_round_radius">2dp</dimen> + + <!-- Emoji keyboard --> + <fraction name="emoji_keyboard_key_width">14.2857%p</fraction> + <fraction name="emoji_keyboard_row_height">33%p</fraction> + <fraction name="emoji_keyboard_key_letter_size">68%p</fraction> + <integer name="emoji_keyboard_max_key_count">21</integer> + <dimen name="emoji_category_page_id_height">3dp</dimen> + + <!-- Inset used in Accessibility mode to avoid accidental key presses when a finger slides off the screen. --> + <dimen name="accessibility_edge_slop">8dp</dimen> + + <integer name="user_dictionary_max_word_length" translatable="false">48</integer> + + <dimen name="language_on_spacebar_horizontal_margin">1dp</dimen> + +</resources> diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml index 4be5863f2..af5ec061b 100644 --- a/java/res/values/donottranslate.xml +++ b/java/res/values/donottranslate.xml @@ -18,6 +18,25 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- TODO: these settings depend on the language. They should be put either in the dictionary + header, or in the subtype maybe? --> + <!-- Symbols that are suggested between words --> + <string name="suggested_punctuations">!,?,\\,,:,;,\",(,),\',-,/,@,_</string> + <!-- Symbols that are normally preceded by a space (used to add an auto-space before these) --> + <string name="symbols_preceded_by_space">([{&</string> + <!-- Symbols that are normally followed by a space (used to add an auto-space after these) --> + <string name="symbols_followed_by_space">.,;:!?)]}&</string> + <!-- Symbols that separate words --> + <!-- Don't remove the enclosing double quotes, they protect whitespace (not just U+0020) --> + <string name="symbols_word_separators">"	 \n"()[]{}*&<>+=|.,;:!?/_\"</string> + <!-- Word connectors --> + <string name="symbols_word_connectors">\'-</string> + <!-- The sentence separator code point, for capitalization --> + <!-- U+002E: "." FULL STOP ; 2Eh = 46d --> + <integer name="sentence_separator">46</integer> + <!-- Whether this language uses spaces between words --> + <bool name="current_language_has_spaces">true</bool> + <!-- Always show the suggestion strip --> <string name="prefs_suggestion_visibility_show_value">0</string> <!-- Show the suggestion strip only on portrait mode --> @@ -38,9 +57,43 @@ <item>@string/prefs_suggestion_visibility_hide_name</item> </string-array> - <!-- For backward compatibility. - See {@link SettingsValues#needsToShowVoiceInputKey(SharedPreferences,Resources)} --> + <string name="auto_correction_threshold_mode_index_off">0</string> + <string name="auto_correction_threshold_mode_index_modest">1</string> + <string name="auto_correction_threshold_mode_index_aggressive">2</string> + <string name="auto_correction_threshold_mode_index_very_aggressive">3</string> + <string-array name="auto_correction_threshold_mode_indexes"> + <item>@string/auto_correction_threshold_mode_index_off</item> + <item>@string/auto_correction_threshold_mode_index_modest</item> + <item>@string/auto_correction_threshold_mode_index_aggressive</item> + <item>@string/auto_correction_threshold_mode_index_very_aggressive</item> + </string-array> + <string-array name="auto_correction_threshold_modes"> + <item>@string/auto_correction_threshold_mode_off</item> + <item>@string/auto_correction_threshold_mode_modest</item> + <item>@string/auto_correction_threshold_mode_aggressive</item> + <item>@string/auto_correction_threshold_mode_very_aggressive</item> + </string-array> + <string name="voice_mode_main">0</string> + <string name="voice_mode_symbols">1</string> + <string name="voice_mode_off">2</string> + <string-array name="voice_input_modes_values"> + <item>@string/voice_mode_main</item> + <item>@string/voice_mode_symbols</item> + <item>@string/voice_mode_off</item> + </string-array> + <!-- Array of Voice Input modes --> + <string-array name="voice_input_modes"> + <item>@string/voice_input_modes_main_keyboard</item> + <item>@string/voice_input_modes_symbols_keyboard</item> + <item>@string/voice_input_modes_off</item> + </string-array> + <!-- Array of Voice Input modes summary --> + <string-array name="voice_input_modes_summary"> + <item>@string/voice_input_modes_summary_main_keyboard</item> + <item>@string/voice_input_modes_summary_symbols_keyboard</item> + <item>@string/voice_input_modes_summary_off</item> + </string-array> <!-- Title for Latin keyboard debug settings activity / dialog --> <string name="english_ime_debug_settings">Android keyboard Debug settings</string> diff --git a/java/res/values/keyboard-icons-holo.xml b/java/res/values/keyboard-icons-holo.xml index 4c888d570..b49e1d10b 100644 --- a/java/res/values/keyboard-icons-holo.xml +++ b/java/res/values/keyboard-icons-holo.xml @@ -32,6 +32,7 @@ <item name="iconSearchKey">@drawable/sym_keyboard_search_holo_dark</item> <item name="iconTabKey">@drawable/sym_keyboard_tab_holo_dark</item> <item name="iconShortcutKey">@drawable/sym_keyboard_voice_holo_dark</item> + <item name="iconShortcutForLabel">@drawable/sym_keyboard_label_mic_holo_dark</item> <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space_holo_dark</item> <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked_holo_dark</item> <item name="iconShortcutKeyDisabled">@drawable/sym_keyboard_voice_off_holo_dark</item> diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index a269d4979..11b3ea3af 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -245,6 +245,21 @@ <!-- Preferences item for enabling speech input --> <string name="voice_input">Voice input key</string> + <!-- Voice Input modes --> + <!-- On settings screen, voice input pop-up menu option to show voice key on main keyboard [CHAR LIMIT=20] --> + <string name="voice_input_modes_main_keyboard">On main keyboard</string> + <!-- On settings screen, voice input pop-up menu option to show voice key on symbols keyboard [CHAR LIMIT=20] --> + <string name="voice_input_modes_symbols_keyboard">On symbols keyboard</string> + <!-- On settings screen, voice input pop-up menu option to never show voice key [CHAR LIMIT=20] --> + <string name="voice_input_modes_off">Off</string> + <!-- Voice Input modes summary --> + <!-- On settings screen, voice input pop-up menu summary text to show voice key on main keyboard [CHAR LIMIT=20] --> + <string name="voice_input_modes_summary_main_keyboard">Mic on main keyboard</string> + <!-- On settings screen, voice input pop-up menu summary text to show voice key on symbols keyboard [CHAR LIMIT=20] --> + <string name="voice_input_modes_summary_symbols_keyboard">Mic on symbols keyboard</string> + <!-- On settings screen, voice input pop-up menu summary text to never show voice key [CHAR LIMIT=20] --> + <string name="voice_input_modes_summary_off">Voice input is disabled</string> + <!-- Title for configuring input method settings [CHAR LIMIT=35] --> <string name="configure_input_method">Configure input methods</string> diff --git a/java/res/values/themes-common.xml b/java/res/values/themes-common.xml index 7c9b51c0a..298936d9c 100644 --- a/java/res/values/themes-common.xml +++ b/java/res/values/themes-common.xml @@ -25,49 +25,49 @@ <item name="touchPositionCorrectionData">@array/touch_position_correction_data_default</item> <item name="rowHeight">25%p</item> <item name="moreKeysTemplate">@xml/kbd_more_keys_keyboard_template</item> - <item name="keyboardLeftPadding">@fraction/config_keyboard_left_padding</item> - <item name="keyboardRightPadding">@fraction/config_keyboard_right_padding</item> + <item name="keyboardLeftPadding">@fraction/keyboard_left_padding</item> + <item name="keyboardRightPadding">@fraction/keyboard_right_padding</item> <item name="maxMoreKeysColumn">@integer/config_max_more_keys_column</item> </style> <style name="KeyboardView"> <item name="keyBackground">@drawable/btn_keyboard_key_klp</item> - <item name="keyLetterSize">@fraction/config_key_letter_ratio</item> - <item name="keyLargeLetterRatio">@fraction/config_key_large_letter_ratio</item> - <item name="keyLabelSize">@fraction/config_key_label_ratio</item> - <item name="keyLargeLabelRatio">@fraction/config_key_large_label_ratio</item> - <item name="keyHintLetterRatio">@fraction/config_key_hint_letter_ratio</item> - <item name="keyHintLabelRatio">@fraction/config_key_hint_label_ratio</item> - <item name="keyShiftedLetterHintRatio">@fraction/config_key_shifted_letter_hint_ratio</item> + <item name="keyLetterSize">@fraction/key_letter_ratio</item> + <item name="keyLargeLetterRatio">@fraction/key_large_letter_ratio</item> + <item name="keyLabelSize">@fraction/key_label_ratio</item> + <item name="keyLargeLabelRatio">@fraction/key_large_label_ratio</item> + <item name="keyHintLetterRatio">@fraction/key_hint_letter_ratio</item> + <item name="keyHintLabelRatio">@fraction/key_hint_label_ratio</item> + <item name="keyShiftedLetterHintRatio">@fraction/key_uppercase_letter_ratio</item> <item name="keyTypeface">normal</item> - <item name="keyLabelHorizontalPadding">@dimen/config_key_label_horizontal_padding</item> - <item name="keyHintLetterPadding">@dimen/config_key_hint_letter_padding</item> - <item name="keyPopupHintLetterPadding">@dimen/config_key_popup_hint_letter_padding</item> - <item name="keyShiftedLetterHintPadding">@dimen/config_key_shifted_letter_hint_padding</item> - <item name="keyPreviewTextRatio">@fraction/config_key_preview_text_ratio</item> - <item name="verticalCorrection">@dimen/config_keyboard_vertical_correction</item> + <item name="keyLabelHorizontalPadding">@dimen/key_label_horizontal_padding</item> + <item name="keyHintLetterPadding">@dimen/key_hint_letter_padding</item> + <item name="keyPopupHintLetterPadding">@dimen/key_popup_hint_letter_padding</item> + <item name="keyShiftedLetterHintPadding">@dimen/key_uppercase_letter_padding</item> + <item name="keyPreviewTextRatio">@fraction/key_preview_text_ratio</item> + <item name="verticalCorrection">@dimen/keyboard_vertical_correction</item> <item name="backgroundDimAlpha">128</item> - <item name="gestureFloatingPreviewTextSize">@dimen/config_gesture_floating_preview_text_size</item> - <item name="gestureFloatingPreviewTextOffset">@dimen/config_gesture_floating_preview_text_offset</item> - <item name="gestureFloatingPreviewHorizontalPadding">@dimen/config_gesture_floating_preview_horizontal_padding</item> - <item name="gestureFloatingPreviewVerticalPadding">@dimen/config_gesture_floating_preview_vertical_padding</item> - <item name="gestureFloatingPreviewRoundRadius">@dimen/config_gesture_floating_preview_round_radius</item> - <item name="gestureTrailMinSamplingDistance">@dimen/config_gesture_trail_min_sampling_distance</item> - <item name="gestureTrailMaxInterpolationAngularThreshold">@integer/config_gesture_trail_max_interpolation_angular_threshold</item> - <item name="gestureTrailMaxInterpolationDistanceThreshold">@dimen/config_gesture_trail_max_interpolation_distance_threshold</item> - <item name="gestureTrailMaxInterpolationSegments">@integer/config_gesture_trail_max_interpolation_segments</item> + <item name="gestureFloatingPreviewTextSize">@dimen/gesture_floating_preview_text_size</item> + <item name="gestureFloatingPreviewTextOffset">@dimen/gesture_floating_preview_text_offset</item> + <item name="gestureFloatingPreviewHorizontalPadding">@dimen/gesture_floating_preview_horizontal_padding</item> + <item name="gestureFloatingPreviewVerticalPadding">@dimen/gesture_floating_preview_vertical_padding</item> + <item name="gestureFloatingPreviewRoundRadius">@dimen/gesture_floating_preview_round_radius</item> + <item name="gestureTrailMinSamplingDistance">@dimen/gesture_trail_min_sampling_distance</item> + <item name="gestureTrailMaxInterpolationAngularThreshold">@integer/gesture_trail_max_interpolation_angular_threshold</item> + <item name="gestureTrailMaxInterpolationDistanceThreshold">@dimen/gesture_trail_max_interpolation_distance_threshold</item> + <item name="gestureTrailMaxInterpolationSegments">@integer/gesture_trail_max_interpolation_segments</item> <item name="gestureTrailFadeoutStartDelay">@integer/config_gesture_trail_fadeout_start_delay</item> <item name="gestureTrailFadeoutDuration">@integer/config_gesture_trail_fadeout_duration</item> <item name="gestureTrailUpdateInterval">@integer/config_gesture_trail_update_interval</item> - <item name="gestureTrailStartWidth">@dimen/config_gesture_trail_start_width</item> - <item name="gestureTrailEndWidth">@dimen/config_gesture_trail_end_width</item> - <item name="gestureTrailBodyRatio">@integer/config_gesture_trail_body_ratio</item> - <item name="gestureTrailShadowRatio">@integer/config_gesture_trail_shadow_ratio</item> + <item name="gestureTrailStartWidth">@dimen/gesture_trail_start_width</item> + <item name="gestureTrailEndWidth">@dimen/gesture_trail_end_width</item> + <item name="gestureTrailBodyRatio">@integer/gesture_trail_body_ratio</item> + <item name="gestureTrailShadowRatio">@integer/gesture_trail_shadow_ratio</item> <!-- Common attributes of MainKeyboardView --> <item name="keyHysteresisDistance">@dimen/config_key_hysteresis_distance</item> <item name="keyHysteresisDistanceForSlidingModifier">@dimen/config_key_hysteresis_distance_for_sliding_modifier</item> <item name="touchNoiseThresholdTime">@integer/config_touch_noise_threshold_time</item> <item name="touchNoiseThresholdDistance">@dimen/config_touch_noise_threshold_distance</item> - <item name="keySelectionByDraggingFinger">@bool/config_key_selection_by_dragging_finger</item> + <item name="slidingKeyInputEnable">@bool/config_sliding_key_input_enabled</item> <item name="slidingKeyInputPreviewWidth">@dimen/config_sliding_key_input_preview_width</item> <item name="slidingKeyInputPreviewBodyRatio">@integer/config_sliding_key_input_preview_body_ratio</item> <item name="slidingKeyInputPreviewShadowRatio">@integer/config_sliding_key_input_preview_shadow_ratio</item> @@ -75,14 +75,11 @@ <item name="keyRepeatInterval">@integer/config_key_repeat_interval</item> <item name="longPressShiftLockTimeout">@integer/config_longpress_shift_lock_timeout</item> <item name="ignoreAltCodeKeyTimeout">@integer/config_ignore_alt_code_key_timeout</item> - <item name="keyPreviewLayout">@layout/key_preview</item> - <item name="keyPreviewHeight">@dimen/config_key_preview_height</item> - <item name="keyPreviewZoomInDuration">@integer/config_key_preview_zoom_in_duration</item> - <item name="keyPreviewZoomOutDuration">@integer/config_key_preview_zoom_out_duration</item> + <item name="keyPreviewHeight">@dimen/key_preview_height</item> <item name="keyPreviewLingerTimeout">@integer/config_key_preview_linger_timeout</item> <item name="moreKeysKeyboardLayout">@layout/more_keys_keyboard</item> <item name="showMoreKeysKeyboardAtTouchedPoint">@bool/config_show_more_keys_keyboard_at_touched_point</item> - <item name="languageOnSpacebarTextRatio">@fraction/config_language_on_spacebar_text_ratio</item> + <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item> <item name="languageOnSpacebarFinalAlpha">@integer/config_language_on_spacebar_final_alpha</item> <item name="languageOnSpacebarFadeoutAnimator">@anim/language_on_spacebar_fadeout</item> <!-- Remove animations for now because it could drain a non-negligible amount of battery while typing. @@ -107,7 +104,6 @@ <style name="MainKeyboardView" parent="KeyboardView" /> - <style name="KeyPreviewTextView" /> <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it, for instance delete button, need themed {@link KeyboardView} attributes. --> <style @@ -122,14 +118,14 @@ parent="MainKeyboardView" /> <style name="MoreKeysKeyboardContainer" /> <style name="SuggestionStripView"> - <item name="suggestionsCountInStrip">@integer/config_suggestions_count_in_strip</item> - <item name="centerSuggestionPercentile">@fraction/config_center_suggestion_percentile</item> - <item name="maxMoreSuggestionsRow">@integer/config_max_more_suggestions_row</item> - <item name="minMoreSuggestionsWidth">@fraction/config_min_more_suggestions_width</item> + <item name="suggestionsCountInStrip">@integer/suggestions_count_in_strip</item> + <item name="centerSuggestionPercentile">@fraction/center_suggestion_percentile</item> + <item name="maxMoreSuggestionsRow">@integer/max_more_suggestions_row</item> + <item name="minMoreSuggestionsWidth">@fraction/min_more_suggestions_width</item> </style> <style name="SuggestionWord" /> <style name="MoreKeysKeyboardAnimation"> <item name="android:windowEnterAnimation">@anim/more_keys_keyboard_fadein</item> <item name="android:windowExitAnimation">@anim/more_keys_keyboard_fadeout</item> </style> -</resources> +</resources>
\ No newline at end of file diff --git a/java/res/values/themes-gb.xml b/java/res/values/themes-gb.xml index 52ecafd62..f52695f55 100644 --- a/java/res/values/themes-gb.xml +++ b/java/res/values/themes-gb.xml @@ -23,10 +23,10 @@ <item name="keyboardStyle">@style/Keyboard.GB</item> <item name="keyboardViewStyle">@style/KeyboardView.GB</item> <item name="mainKeyboardViewStyle">@style/MainKeyboardView.GB</item> - <item name="keyPreviewTextViewStyle">@style/KeyPreviewTextView.GB</item> <item name="emojiPalettesViewStyle">@style/EmojiPalettesView.GB</item> <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.GB</item> <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.GB</item> + <item name="moreKeysKeyboardContainerStyle">@style/MoreKeysKeyboardContainer.GB</item> <item name="suggestionStripViewStyle">@style/SuggestionStripView.GB</item> <item name="suggestionWordStyle">@style/SuggestionWord.GB</item> </style> @@ -40,6 +40,7 @@ <item name="iconSearchKey">@drawable/sym_keyboard_search_holo_dark</item> <item name="iconTabKey">@drawable/sym_keyboard_tab_holo_dark</item> <item name="iconShortcutKey">@drawable/sym_keyboard_mic_holo_dark</item> + <item name="iconShortcutForLabel">@drawable/sym_keyboard_label_mic_holo_dark</item> <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space</item> <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked_holo_dark</item> <!-- TODO: Needs non-holo disabled shortcut icon drawable --> @@ -58,10 +59,10 @@ <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] --> <item name="themeId">1</item> <item name="touchPositionCorrectionData">@array/touch_position_correction_data_gb</item> - <item name="keyboardTopPadding">@fraction/config_keyboard_top_padding_gb</item> - <item name="keyboardBottomPadding">@fraction/config_keyboard_bottom_padding_gb</item> - <item name="horizontalGap">@fraction/config_key_horizontal_gap_gb</item> - <item name="verticalGap">@fraction/config_key_vertical_gap_gb</item> + <item name="keyboardTopPadding">@fraction/keyboard_top_padding_gb</item> + <item name="keyboardBottomPadding">@fraction/keyboard_bottom_padding_gb</item> + <item name="horizontalGap">@fraction/key_horizontal_gap_gb</item> + <item name="verticalGap">@fraction/key_bottom_gap_gb</item> </style> <style name="KeyboardView.GB" @@ -84,22 +85,16 @@ name="MainKeyboardView.GB" parent="KeyboardView.GB" > - <item name="keyPreviewOffset">@dimen/config_key_preview_offset_gb</item> + <item name="keyPreviewLayout">@layout/key_preview_gb</item> + <item name="keyPreviewOffset">@dimen/key_preview_offset_gb</item> <item name="gestureFloatingPreviewTextColor">@color/highlight_color_gb</item> <item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_gb</item> <item name="gestureTrailColor">@color/highlight_color_gb</item> <item name="slidingKeyInputPreviewColor">@color/highlight_translucent_color_gb</item> <item name="autoCorrectionSpacebarLedEnabled">true</item> <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led_gb</item> - <item name="languageOnSpacebarTextColor">@color/spacebar_text_color_gb</item> - <item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_gb</item> - <item name="spacebarBackground">@drawable/btn_keyboard_spacebar_gb</item> - </style> - <style - name="KeyPreviewTextView.GB" - parent="KeyPreviewTextView" - > - <item name="android:background">@drawable/keyboard_key_feedback_gb</item> + <item name="spacebarTextColor">@color/spacebar_text_color_gb</item> + <item name="spacebarTextShadowColor">@color/spacebar_text_shadow_color_gb</item> </style> <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it, for instance delete button, need themed {@link KeyboardView} attributes. --> @@ -123,10 +118,15 @@ name="MoreKeysKeyboardView.GB" parent="KeyboardView.GB" > - <item name="android:background">@drawable/keyboard_popup_panel_background_gb</item> + <item name="android:background">@null</item> <item name="keyBackground">@drawable/btn_keyboard_key_popup_gb</item> <item name="keyTypeface">normal</item> - <item name="verticalCorrection">@dimen/config_more_keys_keyboard_vertical_correction_gb</item> + <item name="verticalCorrection">@dimen/more_keys_keyboard_vertical_correction_gb</item> + </style> + <style + name="MoreKeysKeyboardContainer.GB" + > + <item name="android:background">@drawable/keyboard_popup_panel_background_gb</item> </style> <style name="SuggestionStripView.GB" diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml index 125b640b6..432ad5122 100644 --- a/java/res/values/themes-ics.xml +++ b/java/res/values/themes-ics.xml @@ -23,10 +23,10 @@ <item name="keyboardStyle">@style/Keyboard.ICS</item> <item name="keyboardViewStyle">@style/KeyboardView.ICS</item> <item name="mainKeyboardViewStyle">@style/MainKeyboardView.ICS</item> - <item name="keyPreviewTextViewStyle">@style/KeyPreviewTextView.ICS</item> <item name="emojiPalettesViewStyle">@style/EmojiPalettesView.ICS</item> <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.ICS</item> <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.ICS</item> + <item name="moreKeysKeyboardContainerStyle">@style/MoreKeysKeyboardContainer.ICS</item> <item name="suggestionStripViewStyle">@style/SuggestionStripView.ICS</item> <item name="suggestionWordStyle">@style/SuggestionWord.ICS</item> </style> @@ -36,10 +36,10 @@ > <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] --> <item name="themeId">2</item> - <item name="keyboardTopPadding">@fraction/config_keyboard_top_padding_holo</item> - <item name="keyboardBottomPadding">@fraction/config_keyboard_bottom_padding_holo</item> - <item name="horizontalGap">@fraction/config_key_horizontal_gap_holo</item> - <item name="verticalGap">@fraction/config_key_vertical_gap_holo</item> + <item name="keyboardTopPadding">@fraction/keyboard_top_padding_holo</item> + <item name="keyboardBottomPadding">@fraction/keyboard_bottom_padding_holo</item> + <item name="horizontalGap">@fraction/key_horizontal_gap_holo</item> + <item name="verticalGap">@fraction/key_bottom_gap_holo</item> <item name="touchPositionCorrectionData">@array/touch_position_correction_data_holo</item> </style> <style @@ -63,22 +63,16 @@ name="MainKeyboardView.ICS" parent="KeyboardView.ICS" > - <item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item> + <item name="keyPreviewLayout">@layout/key_preview_ics</item> + <item name="keyPreviewOffset">@dimen/key_preview_offset_holo</item> <item name="gestureFloatingPreviewTextColor">@color/highlight_color_ics</item> <item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_holo</item> <item name="gestureTrailColor">@color/highlight_color_ics</item> <item name="slidingKeyInputPreviewColor">@color/highlight_translucent_color_ics</item> <item name="autoCorrectionSpacebarLedEnabled">false</item> <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led_holo</item> - <item name="languageOnSpacebarTextColor">@color/spacebar_text_color_holo</item> - <item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item> - <item name="spacebarBackground">@drawable/btn_keyboard_spacebar_ics</item> - </style> - <style - name="KeyPreviewTextView.ICS" - parent="KeyPreviewTextView" - > - <item name="android:background">@drawable/keyboard_key_feedback_ics</item> + <item name="spacebarTextColor">@color/spacebar_text_color_holo</item> + <item name="spacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item> </style> <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it, for instance delete button, need themed {@link KeyboardView} attributes. --> @@ -102,10 +96,15 @@ name="MoreKeysKeyboardView.ICS" parent="KeyboardView.ICS" > - <item name="android:background">@drawable/keyboard_popup_panel_background_ics</item> + <item name="android:background">@null</item> <item name="keyBackground">@drawable/btn_keyboard_key_popup_ics</item> <item name="keyTypeface">normal</item> - <item name="verticalCorrection">@dimen/config_more_keys_keyboard_vertical_correction_holo</item> + <item name="verticalCorrection">@dimen/more_keys_keyboard_vertical_correction_holo</item> + </style> + <style + name="MoreKeysKeyboardContainer.ICS" + > + <item name="android:background">@drawable/keyboard_popup_panel_background_ics</item> </style> <style name="SuggestionStripView.ICS" diff --git a/java/res/values/themes-klp.xml b/java/res/values/themes-klp.xml index f6c076767..a3730019d 100644 --- a/java/res/values/themes-klp.xml +++ b/java/res/values/themes-klp.xml @@ -23,10 +23,10 @@ <item name="keyboardStyle">@style/Keyboard.KLP</item> <item name="keyboardViewStyle">@style/KeyboardView.KLP</item> <item name="mainKeyboardViewStyle">@style/MainKeyboardView.KLP</item> - <item name="keyPreviewTextViewStyle">@style/KeyPreviewTextView.KLP</item> <item name="emojiPalettesViewStyle">@style/EmojiPalettesView.KLP</item> <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.KLP</item> <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.KLP</item> + <item name="moreKeysKeyboardContainerStyle">@style/MoreKeysKeyboardContainer.KLP</item> <item name="suggestionStripViewStyle">@style/SuggestionStripView.KLP</item> <item name="suggestionWordStyle">@style/SuggestionWord.KLP</item> </style> @@ -36,10 +36,10 @@ > <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] --> <item name="themeId">0</item> - <item name="keyboardTopPadding">@fraction/config_keyboard_top_padding_holo</item> - <item name="keyboardBottomPadding">@fraction/config_keyboard_bottom_padding_holo</item> - <item name="horizontalGap">@fraction/config_key_horizontal_gap_holo</item> - <item name="verticalGap">@fraction/config_key_vertical_gap_holo</item> + <item name="keyboardTopPadding">@fraction/keyboard_top_padding_holo</item> + <item name="keyboardBottomPadding">@fraction/keyboard_bottom_padding_holo</item> + <item name="horizontalGap">@fraction/key_horizontal_gap_holo</item> + <item name="verticalGap">@fraction/key_bottom_gap_holo</item> <item name="touchPositionCorrectionData">@array/touch_position_correction_data_holo</item> </style> <style @@ -63,22 +63,16 @@ name="MainKeyboardView.KLP" parent="KeyboardView.KLP" > - <item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item> + <item name="keyPreviewLayout">@layout/key_preview_klp</item> + <item name="keyPreviewOffset">@dimen/key_preview_offset_holo</item> <item name="gestureFloatingPreviewTextColor">@color/highlight_color_klp</item> <item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_holo</item> <item name="gestureTrailColor">@color/highlight_color_klp</item> <item name="slidingKeyInputPreviewColor">@color/highlight_translucent_color_klp</item> <item name="autoCorrectionSpacebarLedEnabled">false</item> <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led_holo</item> - <item name="languageOnSpacebarTextColor">@color/spacebar_text_color_holo</item> - <item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item> - <item name="spacebarBackground">@drawable/btn_keyboard_spacebar_klp</item> - </style> - <style - name="KeyPreviewTextView.KLP" - parent="KeyPreviewTextView" - > - <item name="android:background">@drawable/keyboard_key_feedback_klp</item> + <item name="spacebarTextColor">@color/spacebar_text_color_holo</item> + <item name="spacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item> </style> <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it, for instance delete button, need themed {@link KeyboardView} attributes. --> @@ -102,10 +96,15 @@ name="MoreKeysKeyboardView.KLP" parent="KeyboardView.KLP" > - <item name="android:background">@drawable/keyboard_popup_panel_background_klp</item> + <item name="android:background">@null</item> <item name="keyBackground">@drawable/btn_keyboard_key_popup_klp</item> <item name="keyTypeface">normal</item> - <item name="verticalCorrection">@dimen/config_more_keys_keyboard_vertical_correction_holo</item> + <item name="verticalCorrection">@dimen/more_keys_keyboard_vertical_correction_holo</item> + </style> + <style + name="MoreKeysKeyboardContainer.KLP" + > + <item name="android:background">@drawable/keyboard_popup_panel_background_klp</item> </style> <style name="SuggestionStripView.KLP" diff --git a/java/res/xml-sw600dp-land/kbd_more_keys_keyboard_template.xml b/java/res/xml-sw600dp-land/kbd_more_keys_keyboard_template.xml index c7d446014..4d8b446a2 100644 --- a/java/res/xml-sw600dp-land/kbd_more_keys_keyboard_template.xml +++ b/java/res/xml-sw600dp-land/kbd_more_keys_keyboard_template.xml @@ -20,7 +20,7 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" latin:keyWidth="5%p" - latin:rowHeight="@dimen/config_more_keys_keyboard_key_height" + latin:rowHeight="@dimen/popup_key_height" style="?attr/moreKeysKeyboardStyle" > </Keyboard> diff --git a/java/res/xml-sw600dp/kbd_more_keys_keyboard_template.xml b/java/res/xml-sw600dp/kbd_more_keys_keyboard_template.xml index fbe8cfcc0..d90a5884e 100644 --- a/java/res/xml-sw600dp/kbd_more_keys_keyboard_template.xml +++ b/java/res/xml-sw600dp/kbd_more_keys_keyboard_template.xml @@ -20,7 +20,7 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" latin:keyWidth="8%p" - latin:rowHeight="@dimen/config_more_keys_keyboard_key_height" + latin:rowHeight="@dimen/popup_key_height" style="?attr/moreKeysKeyboardStyle" > </Keyboard> diff --git a/java/res/xml-sw600dp/key_f1.xml b/java/res/xml-sw600dp/key_f1.xml index 530f7d63b..ac0053236 100644 --- a/java/res/xml-sw600dp/key_f1.xml +++ b/java/res/xml-sw600dp/key_f1.xml @@ -23,11 +23,34 @@ > <switch> <case + latin:keyboardLayoutSetElement="symbols" + latin:mode="url" + > + <Key + latin:keyLabel=":" /> + </case> + <case + latin:keyboardLayoutSetElement="symbols" + > + <Key + latin:keyLabel="\@" /> + </case> + <!-- keyboardLayoutSetElement != "symbols" --> + <case latin:mode="email" > <Key latin:keyLabel="\@" /> </case> + <case + latin:mode="url" + > + <Key + latin:keyLabel="/" + latin:keyHintLabel=":" + latin:moreKeys=":" + latin:keyStyle="hasShiftedLetterHintStyle" /> + </case> <default> <Key latin:keyLabel="/" /> diff --git a/java/res/xml-sw600dp/key_shortcut.xml b/java/res/xml-sw600dp/key_shortcut.xml index c869e745b..87fc75cd5 100644 --- a/java/res/xml-sw600dp/key_shortcut.xml +++ b/java/res/xml-sw600dp/key_shortcut.xml @@ -23,7 +23,7 @@ > <switch> <case - latin:supportsSwitchingToShortcutIme="true" + latin:shortcutKeyEnabled="true" latin:clobberSettingsKey="false" > <Key @@ -32,20 +32,20 @@ latin:moreKeys="!text/settings_as_more_key" /> </case> <case - latin:supportsSwitchingToShortcutIme="true" + latin:shortcutKeyEnabled="true" latin:clobberSettingsKey="true" > <Key latin:keyStyle="shortcutKeyStyle" /> </case> <case - latin:supportsSwitchingToShortcutIme="false" + latin:shortcutKeyEnabled="false" latin:clobberSettingsKey="false" > <Key latin:keyStyle="settingsKeyStyle" /> </case> - <!-- supportsSwitchingToShortcutIme="false" clobberSettingsKey="true" --> + <!-- shortcutKeyEnabled="false" clobberSettingsKey="true" --> <default> <Spacer /> </default> diff --git a/java/res/xml-sw600dp/key_space_symbols.xml b/java/res/xml-sw600dp/key_space_symbols.xml index d6f7cab09..07aa7d179 100644 --- a/java/res/xml-sw600dp/key_space_symbols.xml +++ b/java/res/xml-sw600dp/key_space_symbols.xml @@ -22,6 +22,5 @@ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > <include - latin:backgroundType="normal" latin:keyboardLayout="@xml/key_space_5kw" /> </merge> diff --git a/java/res/xml-sw600dp/keys_comma_period.xml b/java/res/xml-sw600dp/keys_comma_period.xml index 55302aeab..7604e033d 100644 --- a/java/res/xml-sw600dp/keys_comma_period.xml +++ b/java/res/xml-sw600dp/keys_comma_period.xml @@ -21,18 +21,83 @@ <merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > - <Key - latin:keyLabel="!text/keylabel_for_tablet_comma" - latin:keyHintLabel="!text/keyhintlabel_for_tablet_comma" - latin:keyLabelFlags="hasPopupHint" - latin:moreKeys="!text/more_keys_for_tablet_comma" - latin:backgroundType="functional" - latin:keyStyle="hasShiftedLetterHintStyle" /> - <Key - latin:keyLabel="!text/keylabel_for_tablet_period" - latin:keyHintLabel="!text/keyhintlabel_for_tablet_period" - latin:keyLabelFlags="hasPopupHint" - latin:moreKeys="!text/more_keys_for_tablet_period" - latin:backgroundType="functional" - latin:keyStyle="hasShiftedLetterHintStyle" /> + <switch> + <case + latin:mode="email|url" + > + <Key + latin:keyLabel="," + latin:keyHintLabel="-" + latin:moreKeys="-" + latin:backgroundType="functional" + latin:keyStyle="hasShiftedLetterHintStyle" /> + <Key + latin:keyLabel="." + latin:keyHintLabel="_" + latin:moreKeys="_" + latin:backgroundType="functional" + latin:keyStyle="hasShiftedLetterHintStyle" /> + </case> + <case + latin:languageCode="ar" + > + <Key + latin:keyLabel="!text/keylabel_for_apostrophe" + latin:keyHintLabel="!text/keyhintlabel_for_apostrophe" + latin:moreKeys="!text/more_keys_for_apostrophe" + latin:backgroundType="functional" + latin:keyStyle="hasShiftedLetterHintStyle" /> + <Key + latin:keyLabel="." + latin:keyHintLabel="!text/keyhintlabel_for_arabic_diacritics" + latin:keyLabelFlags="hasPopupHint" + latin:moreKeys="!text/more_keys_for_arabic_diacritics" + latin:backgroundType="functional" + latin:keyStyle="hasShiftedLetterHintStyle" /> + </case> + <case + latin:languageCode="fa" + > + <Key + latin:keyLabel="!text/keylabel_for_apostrophe" + latin:keyHintLabel="!text/keyhintlabel_for_apostrophe" + latin:keyLabelFlags="hasPopupHint" + latin:moreKeys="!text/more_keys_for_apostrophe" + latin:backgroundType="functional" + latin:keyStyle="hasShiftedLetterHintStyle" /> + <Key + latin:keyLabel="." + latin:keyHintLabel="!text/keyhintlabel_for_arabic_diacritics" + latin:keyLabelFlags="hasPopupHint" + latin:moreKeys="!text/more_keys_for_arabic_diacritics" + latin:backgroundType="functional" + latin:keyStyle="hasShiftedLetterHintStyle" /> + </case> + <case + latin:languageCode="hy" + > + <!-- U+055D: "՝" ARMENIAN COMMA --> + <Key + latin:keyLabel="՝" + latin:backgroundType="functional" /> + <!-- U+0589: "։" ARMENIAN FULL STOP --> + <Key + latin:keyLabel="։" + latin:keyLabelFlags="hasPopupHint" + latin:backgroundType="functional" + latin:moreKeys="!text/more_keys_for_punctuation" /> + </case> + <default> + <Key + latin:keyLabel="!text/keylabel_for_tablet_comma" + latin:keyHintLabel="!text/keyhintlabel_for_tablet_comma" + latin:backgroundType="functional" + latin:moreKeys="!text/more_keys_for_tablet_comma" /> + <Key + latin:keyLabel="." + latin:keyHintLabel="!text/keyhintlabel_for_period" + latin:backgroundType="functional" + latin:moreKeys="!text/more_keys_for_period" /> + </default> + </switch> </merge> diff --git a/java/res/xml-sw600dp/keys_exclamation_question.xml b/java/res/xml-sw600dp/keys_exclamation_question.xml index fd849222d..cd38282ee 100644 --- a/java/res/xml-sw600dp/keys_exclamation_question.xml +++ b/java/res/xml-sw600dp/keys_exclamation_question.xml @@ -22,9 +22,7 @@ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > <Key - latin:keyLabel="!" - latin:moreKeys="!text/more_keys_for_exclamation" /> + latin:keyLabel="!" /> <Key - latin:keyLabel="\?" - latin:moreKeys="!text/more_keys_for_question" /> + latin:keyLabel="\?" /> </merge> diff --git a/java/res/xml-sw600dp/keys_pcqwerty4_right3.xml b/java/res/xml-sw600dp/keys_pcqwerty4_right3.xml index 46a1c85dc..774ff8d05 100644 --- a/java/res/xml-sw600dp/keys_pcqwerty4_right3.xml +++ b/java/res/xml-sw600dp/keys_pcqwerty4_right3.xml @@ -40,7 +40,7 @@ latin:keyHintLabel="\?" latin:additionalMoreKeys="\?" latin:keyStyle="hasShiftedLetterHintStyle" - latin:moreKeys="!text/more_keys_for_question" /> + latin:moreKeys="!text/more_keys_for_symbols_question" /> </case> <!-- keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted" --> <default> @@ -58,7 +58,7 @@ latin:moreKeys="!fixedColumnOrder!3,›,≥,»" /> <Key latin:keyLabel="\?" - latin:moreKeys="!text/more_keys_for_question" /> + latin:moreKeys="!text/more_keys_for_symbols_question" /> </default> </switch> </merge> diff --git a/java/res/xml-sw600dp/rowkeys_pcqwerty1.xml b/java/res/xml-sw600dp/rowkeys_pcqwerty1.xml index ae6bab79c..254d3fdba 100644 --- a/java/res/xml-sw600dp/rowkeys_pcqwerty1.xml +++ b/java/res/xml-sw600dp/rowkeys_pcqwerty1.xml @@ -31,7 +31,7 @@ latin:keyHintLabel="!" latin:additionalMoreKeys="!" latin:keyStyle="hasShiftedLetterHintStyle" - latin:moreKeys="!text/more_keys_for_exclamation,!text/more_keys_for_symbols_1" /> + latin:moreKeys="!text/more_keys_for_symbols_exclamation,!text/more_keys_for_symbols_1" /> <Key latin:keyLabel="2" latin:keyHintLabel="\@" diff --git a/java/res/xml-sw600dp/rows_hebrew.xml b/java/res/xml-sw600dp/rows_hebrew.xml index 86b34202f..852e17683 100644 --- a/java/res/xml-sw600dp/rows_hebrew.xml +++ b/java/res/xml-sw600dp/rows_hebrew.xml @@ -45,10 +45,8 @@ latin:keyWidth="9.0%p" > <include - latin:keyboardLayout="@xml/rowkeys_hebrew3" /> - <include - latin:keyboardLayout="@xml/keys_exclamation_question" - latin:keyWidth="9.5%p" /> + latin:keyboardLayout="@xml/rowkeys_hebrew3" + latin:keyXPos="10.0%p" /> </Row> <include latin:keyboardLayout="@xml/row_qwerty4" /> diff --git a/java/res/xml-sw600dp/rows_swiss.xml b/java/res/xml-sw600dp/rows_swiss.xml deleted file mode 100644 index 4f4ca85b4..000000000 --- a/java/res/xml-sw600dp/rows_swiss.xml +++ /dev/null @@ -1,63 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/key_styles_common" /> - <Row - latin:keyWidth="8.182%p" - > - <include - latin:keyboardLayout="@xml/rowkeys_swiss1" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="8.182%p" - > - <include - latin:keyboardLayout="@xml/rowkeys_swiss2" /> - <Key - latin:keyStyle="enterKeyStyle" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="8.182%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="10.0%p" /> - <Spacer - latin:keyWidth="3.181%p" /> - <include - latin:keyboardLayout="@xml/rowkeys_qwertz3" /> - <include - latin:keyboardLayout="@xml/keys_exclamation_question" /> - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyXPos="-10.0%p" - latin:keyWidth="fillRight" /> - </Row> - <include - latin:keyboardLayout="@xml/row_qwerty4" /> -</merge> diff --git a/java/res/xml-sw600dp/rows_symbols.xml b/java/res/xml-sw600dp/rows_symbols.xml index 7a33f4923..cf94b06ed 100644 --- a/java/res/xml-sw600dp/rows_symbols.xml +++ b/java/res/xml-sw600dp/rows_symbols.xml @@ -62,7 +62,6 @@ </Row> <Row latin:keyWidth="9.0%p" - latin:backgroundType="functional" > <Key latin:keyStyle="toAlphaKeyStyle" diff --git a/java/res/xml-sw600dp/rows_symbols_shift.xml b/java/res/xml-sw600dp/rows_symbols_shift.xml index 79d1aa142..92299f65d 100644 --- a/java/res/xml-sw600dp/rows_symbols_shift.xml +++ b/java/res/xml-sw600dp/rows_symbols_shift.xml @@ -64,7 +64,6 @@ </Row> <Row latin:keyWidth="9.0%p" - latin:backgroundType="functional" > <Key latin:keyStyle="toAlphaKeyStyle" diff --git a/java/res/xml/kbd_armenian_phonetic.xml b/java/res/xml/kbd_armenian_phonetic.xml index da12870ed..1eb3c7e7d 100644 --- a/java/res/xml/kbd_armenian_phonetic.xml +++ b/java/res/xml/kbd_armenian_phonetic.xml @@ -21,9 +21,9 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" latin:rowHeight="20%p" - latin:verticalGap="@fraction/config_key_vertical_gap_5row" - latin:keyLetterSize="@fraction/config_key_letter_ratio_5row" - latin:keyShiftedLetterHintRatio="@fraction/config_key_shifted_letter_hint_ratio_5row" + latin:verticalGap="@fraction/key_bottom_gap_5row" + latin:keyLetterSize="@fraction/key_letter_ratio_5row" + latin:keyShiftedLetterHintRatio="@fraction/key_uppercase_letter_ratio_5row" latin:touchPositionCorrectionData="@array/touch_position_correction_data_default" > <include diff --git a/java/res/xml/kbd_emoji_category1.xml b/java/res/xml/kbd_emoji_category1.xml index 5145ea9d3..c11a83017 100644 --- a/java/res/xml/kbd_emoji_category1.xml +++ b/java/res/xml/kbd_emoji_category1.xml @@ -20,9 +20,9 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyWidth="@fraction/config_emoji_keyboard_key_width" + latin:keyWidth="@fraction/emoji_keyboard_key_width" latin:keyLetterSize="90%p" - latin:rowHeight="@fraction/config_emoji_keyboard_row_height" + latin:rowHeight="@fraction/emoji_keyboard_row_height" > <GridRows latin:codesArray="@array/emoji_faces" diff --git a/java/res/xml/kbd_emoji_category2.xml b/java/res/xml/kbd_emoji_category2.xml index ac8784f4b..d3e5890ea 100644 --- a/java/res/xml/kbd_emoji_category2.xml +++ b/java/res/xml/kbd_emoji_category2.xml @@ -20,9 +20,9 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyWidth="@fraction/config_emoji_keyboard_key_width" + latin:keyWidth="@fraction/emoji_keyboard_key_width" latin:keyLetterSize="90%p" - latin:rowHeight="@fraction/config_emoji_keyboard_row_height" + latin:rowHeight="@fraction/emoji_keyboard_row_height" > <GridRows latin:codesArray="@array/emoji_objects" diff --git a/java/res/xml/kbd_emoji_category3.xml b/java/res/xml/kbd_emoji_category3.xml index 88c4db92b..0efafa814 100644 --- a/java/res/xml/kbd_emoji_category3.xml +++ b/java/res/xml/kbd_emoji_category3.xml @@ -20,9 +20,9 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyWidth="@fraction/config_emoji_keyboard_key_width" + latin:keyWidth="@fraction/emoji_keyboard_key_width" latin:keyLetterSize="90%p" - latin:rowHeight="@fraction/config_emoji_keyboard_row_height" + latin:rowHeight="@fraction/emoji_keyboard_row_height" > <GridRows latin:codesArray="@array/emoji_nature" diff --git a/java/res/xml/kbd_emoji_category4.xml b/java/res/xml/kbd_emoji_category4.xml index 262384d80..e5291207f 100644 --- a/java/res/xml/kbd_emoji_category4.xml +++ b/java/res/xml/kbd_emoji_category4.xml @@ -20,9 +20,9 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyWidth="@fraction/config_emoji_keyboard_key_width" + latin:keyWidth="@fraction/emoji_keyboard_key_width" latin:keyLetterSize="90%p" - latin:rowHeight="@fraction/config_emoji_keyboard_row_height" + latin:rowHeight="@fraction/emoji_keyboard_row_height" > <GridRows latin:codesArray="@array/emoji_places" diff --git a/java/res/xml/kbd_emoji_category5.xml b/java/res/xml/kbd_emoji_category5.xml index bf823f978..1836879d6 100644 --- a/java/res/xml/kbd_emoji_category5.xml +++ b/java/res/xml/kbd_emoji_category5.xml @@ -20,9 +20,9 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyWidth="@fraction/config_emoji_keyboard_key_width" + latin:keyWidth="@fraction/emoji_keyboard_key_width" latin:keyLetterSize="90%p" - latin:rowHeight="@fraction/config_emoji_keyboard_row_height" + latin:rowHeight="@fraction/emoji_keyboard_row_height" > <GridRows latin:codesArray="@array/emoji_symbols" diff --git a/java/res/xml/kbd_emoji_category6.xml b/java/res/xml/kbd_emoji_category6.xml index edb82fc64..b47ebfec0 100644 --- a/java/res/xml/kbd_emoji_category6.xml +++ b/java/res/xml/kbd_emoji_category6.xml @@ -20,10 +20,10 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyWidth="@fraction/config_emoji_keyboard_key_width" + latin:keyWidth="@fraction/emoji_keyboard_key_width" latin:keyLetterSize="90%p" latin:keyLabelSize="60%p" - latin:rowHeight="@fraction/config_emoji_keyboard_row_height" + latin:rowHeight="@fraction/emoji_keyboard_row_height" > <GridRows latin:textsArray="@array/emoji_emoticons" diff --git a/java/res/xml/kbd_emoji_recents.xml b/java/res/xml/kbd_emoji_recents.xml index edf3872c1..73926ecc0 100644 --- a/java/res/xml/kbd_emoji_recents.xml +++ b/java/res/xml/kbd_emoji_recents.xml @@ -20,10 +20,10 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyWidth="@fraction/config_emoji_keyboard_key_width" - latin:keyLetterSize="@fraction/config_emoji_keyboard_key_letter_size" + latin:keyWidth="@fraction/emoji_keyboard_key_width" + latin:keyLetterSize="@fraction/emoji_keyboard_key_letter_size" latin:keyLabelSize="60%p" - latin:rowHeight="@fraction/config_emoji_keyboard_row_height" + latin:rowHeight="@fraction/emoji_keyboard_row_height" > <GridRows latin:codesArray="@array/emoji_recents" diff --git a/java/res/xml/kbd_khmer.xml b/java/res/xml/kbd_khmer.xml index d703e78f7..7a2337a48 100644 --- a/java/res/xml/kbd_khmer.xml +++ b/java/res/xml/kbd_khmer.xml @@ -21,9 +21,9 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" latin:rowHeight="20%p" - latin:verticalGap="@fraction/config_key_vertical_gap_5row" - latin:keyLetterSize="@fraction/config_key_letter_ratio_5row" - latin:keyShiftedLetterHintRatio="@fraction/config_key_shifted_letter_hint_ratio_5row" + latin:verticalGap="@fraction/key_bottom_gap_5row" + latin:keyLetterSize="@fraction/key_letter_ratio_5row" + latin:keyShiftedLetterHintRatio="@fraction/key_uppercase_letter_ratio_5row" latin:touchPositionCorrectionData="@array/touch_position_correction_data_default" > <include diff --git a/java/res/xml/kbd_lao.xml b/java/res/xml/kbd_lao.xml index 6f7709562..2bba330de 100644 --- a/java/res/xml/kbd_lao.xml +++ b/java/res/xml/kbd_lao.xml @@ -21,9 +21,9 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" latin:rowHeight="20%p" - latin:verticalGap="@fraction/config_key_vertical_gap_5row" - latin:keyLetterSize="@fraction/config_key_letter_ratio_5row" - latin:keyShiftedLetterHintRatio="@fraction/config_key_shifted_letter_hint_ratio_5row" + latin:verticalGap="@fraction/key_bottom_gap_5row" + latin:keyLetterSize="@fraction/key_letter_ratio_5row" + latin:keyShiftedLetterHintRatio="@fraction/key_uppercase_letter_ratio_5row" latin:touchPositionCorrectionData="@array/touch_position_correction_data_default" > <include diff --git a/java/res/xml/kbd_more_keys_keyboard_template.xml b/java/res/xml/kbd_more_keys_keyboard_template.xml index 7104ec7e0..537973d03 100644 --- a/java/res/xml/kbd_more_keys_keyboard_template.xml +++ b/java/res/xml/kbd_more_keys_keyboard_template.xml @@ -20,7 +20,7 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" latin:keyWidth="10%p" - latin:rowHeight="@dimen/config_more_keys_keyboard_key_height" + latin:rowHeight="@dimen/popup_key_height" style="?attr/moreKeysKeyboardStyle" > </Keyboard> diff --git a/java/res/xml/kbd_pcqwerty.xml b/java/res/xml/kbd_pcqwerty.xml index 045696451..5155bc510 100644 --- a/java/res/xml/kbd_pcqwerty.xml +++ b/java/res/xml/kbd_pcqwerty.xml @@ -21,9 +21,9 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" latin:rowHeight="20%p" - latin:verticalGap="@fraction/config_key_vertical_gap_5row" - latin:keyLetterSize="@fraction/config_key_letter_ratio_5row" - latin:keyShiftedLetterHintRatio="@fraction/config_key_shifted_letter_hint_ratio_5row" + latin:verticalGap="@fraction/key_bottom_gap_5row" + latin:keyLetterSize="@fraction/key_letter_ratio_5row" + latin:keyShiftedLetterHintRatio="@fraction/key_uppercase_letter_ratio_5row" latin:touchPositionCorrectionData="@array/touch_position_correction_data_default" > <include diff --git a/java/res/xml/kbd_suggestions_pane_template.xml b/java/res/xml/kbd_suggestions_pane_template.xml index 5b4f60673..21316e6bb 100644 --- a/java/res/xml/kbd_suggestions_pane_template.xml +++ b/java/res/xml/kbd_suggestions_pane_template.xml @@ -20,6 +20,6 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" latin:keyWidth="10%p" - latin:rowHeight="@dimen/config_more_suggestions_row_height" + latin:rowHeight="@dimen/more_suggestions_row_height" > </Keyboard> diff --git a/java/res/xml/kbd_thai.xml b/java/res/xml/kbd_thai.xml index 7e65217f9..294bffb5b 100644 --- a/java/res/xml/kbd_thai.xml +++ b/java/res/xml/kbd_thai.xml @@ -21,9 +21,9 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" latin:rowHeight="20%p" - latin:verticalGap="@fraction/config_key_vertical_gap_5row" - latin:keyLetterSize="@fraction/config_key_letter_ratio_5row" - latin:keyShiftedLetterHintRatio="@fraction/config_key_shifted_letter_hint_ratio_5row" + latin:verticalGap="@fraction/key_bottom_gap_5row" + latin:keyLetterSize="@fraction/key_letter_ratio_5row" + latin:keyShiftedLetterHintRatio="@fraction/key_uppercase_letter_ratio_5row" latin:touchPositionCorrectionData="@array/touch_position_correction_data_default" > <include diff --git a/java/res/xml/key_f1.xml b/java/res/xml/key_f1.xml index 0e9d497b6..72e38cb1a 100644 --- a/java/res/xml/key_f1.xml +++ b/java/res/xml/key_f1.xml @@ -37,16 +37,6 @@ latin:keyStyle="f1MoreKeysStyle" /> </case> <case - latin:supportsSwitchingToShortcutIme="false" - > - <Key - latin:keyLabel="!text/keylabel_for_comma" - latin:keyLabelFlags="hasPopupHint" - latin:additionalMoreKeys="!text/more_keys_for_comma" - latin:keyStyle="f1MoreKeysStyle" /> - </case> - <!-- latin:supportsSwitchingToShortcutIme="true" --> - <case latin:hasShortcutKey="true" > <Key diff --git a/java/res/xml/key_period.xml b/java/res/xml/key_nepali_traditional_period.xml index 838db25c3..1c389b009 100644 --- a/java/res/xml/key_period.xml +++ b/java/res/xml/key_nepali_traditional_period.xml @@ -18,31 +18,32 @@ */ --> +<!-- The code point U+25CC for key label is needed because the font rendering system prior to + API version 16 can't automatically render dotted circle for incomplete combining letter + of Hindi. The files named res/xml/{key,keys}_nepali*.xml have this U+25CC hack, although the + counterpart files named res/xml-v16/{key,keys}_nepali*.xml don't have this hack. --> <merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > <switch> <case - latin:languageCode="ne" - latin:keyboardLayoutSet="nepali_traditional" + latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted" > + <Key + latin:keyLabel="," + latin:backgroundType="functional" /> + </case> + <default> <!-- Because the font rendering system prior to API version 16 can't automatically render dotted circle for incomplete combining letter of some scripts, different set of Key definitions are needed based on the API version. --> <include latin:keyboardLayout="@xml/keystyle_devanagari_sign_virama" /> + <!-- U+002E: "." FULL STOP --> <Key latin:keyStyle="baseKeyDevanagariSignVirama" latin:keyLabelFlags="hasPopupHint" - latin:moreKeys="!text/more_keys_for_punctuation" - latin:backgroundType="functional" /> - </case> - <default> - <Key - latin:keyLabel="!text/keylabel_for_period" - latin:keyHintLabel="!text/keyhintlabel_for_period" - latin:keyLabelFlags="hasPopupHint|hasShiftedLetterHint" - latin:moreKeys="!text/more_keys_for_period" + latin:moreKeys="!fixedColumnOrder!9,.,!text/more_keys_for_punctuation" latin:backgroundType="functional" /> </default> </switch> diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml index d538eb8c3..c9d87bfd4 100644 --- a/java/res/xml/key_styles_common.xml +++ b/java/res/xml/key_styles_common.xml @@ -160,10 +160,27 @@ latin:keyLabelFlags="preserveCase" latin:keyActionFlags="noKeyPreview" latin:backgroundType="functional" /> - <key-style - latin:styleName="baseForToSymbolKeyStyle" - latin:keyLabel="!text/label_to_symbol_key" - latin:parentStyle="baseForLayoutSwitchKeyStyle" /> + <switch> + <!-- When this qwerty keyboard has no shortcut keys but shortcut key is enabled, then symbol + keyboard will have a shortcut key. That means we should use label_to_symbol_key label + and shortcut_for_label icon. --> + <case + latin:shortcutKeyOnSymbols="true" + > + <key-style + latin:styleName="baseForToSymbolKeyStyle" + latin:keyIcon="!icon/shortcut_for_label" + latin:keyLabel="!text/label_to_symbol_with_microphone_key" + latin:keyLabelFlags="withIconRight|preserveCase" + latin:parentStyle="baseForLayoutSwitchKeyStyle" /> + </case> + <default> + <key-style + latin:styleName="baseForToSymbolKeyStyle" + latin:keyLabel="!text/label_to_symbol_key" + latin:parentStyle="baseForLayoutSwitchKeyStyle" /> + </default> + </switch> <key-style latin:styleName="toSymbolKeyStyle" latin:code="!code/key_switch_alpha_symbol" @@ -183,6 +200,12 @@ latin:code="!code/key_shift" latin:parentStyle="baseForToSymbolKeyStyle" /> <key-style + latin:styleName="punctuationKeyStyle" + latin:keyLabel="." + latin:keyLabelFlags="hasPopupHint" + latin:moreKeys="!text/more_keys_for_punctuation" + latin:backgroundType="functional" /> + <key-style latin:styleName="comKeyStyle" latin:keyLabel="!text/keylabel_for_popular_domain" latin:keyLabelFlags="autoXScale|fontNormal|hasPopupHint|preserveCase" diff --git a/java/res/xml/key_symbols_period.xml b/java/res/xml/key_symbols_period.xml new file mode 100644 index 000000000..6efc9dee3 --- /dev/null +++ b/java/res/xml/key_symbols_period.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 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 the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+2105: "℅" CARE OF + U+2122: "™" TRADE MARK SIGN + U+00AE: "®" REGISTERED SIGN + U+00A9: "©" COPYRIGHT SIGN + U+00A7: "§" SECTION SIGN + U+00B6: "¶" PILCROW SIGN + U+002C: "," COMMA + U+2022: "•" BULLET --> + <!-- U+00B0: "°" DEGREE SIGN + U+2032: "′" PRIME + U+2033: "″" DOUBLE PRIME + U+2191: "↑" UPWARDS ARROW + U+2193: "↓" DOWNWARDS ARROW + U+2190: "←" LEFTWARDS ARROW + U+2192: "→" RIGHTWARDS ARROW + U+2026: "…" HORIZONTAL ELLIPSIS --> + <!-- U+0394: "Δ" GREEK CAPITAL LETTER DELTA + U+03A0: "Π" GREEK CAPITAL LETTER PI + U+03C0: "π" GREEK SMALL LETTER PI --> + <Key + latin:keyLabel="." + latin:keyLabelFlags="hasPopupHint" + latin:moreKeys="!fixedColumnOrder!8,℅,™,®,©,§,¶,\\,,•,°,′,″,↑,↓,←,→,…,!text/more_keys_for_bullet,Δ,Π,π" /> +</merge> diff --git a/java/res/xml/keyboard_layout_set_swiss.xml b/java/res/xml/keyboard_layout_set_swiss.xml deleted file mode 100644 index e17a5ab8b..000000000 --- a/java/res/xml/keyboard_layout_set_swiss.xml +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 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. -*/ ---> - -<KeyboardLayoutSet - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"> - <Element - latin:elementName="alphabet" - latin:elementKeyboard="@xml/kbd_swiss" - latin:enableProximityCharsCorrection="true" /> - <Element - latin:elementName="symbols" - latin:elementKeyboard="@xml/kbd_symbols" /> - <Element - latin:elementName="symbolsShifted" - latin:elementKeyboard="@xml/kbd_symbols_shift" /> - <Element - latin:elementName="phone" - latin:elementKeyboard="@xml/kbd_phone" /> - <Element - latin:elementName="phoneSymbols" - latin:elementKeyboard="@xml/kbd_phone_symbols" /> - <Element - latin:elementName="number" - latin:elementKeyboard="@xml/kbd_number" /> -</KeyboardLayoutSet> diff --git a/java/res/xml/keys_comma_period.xml b/java/res/xml/keys_comma_period.xml new file mode 100644 index 000000000..1b51e45ed --- /dev/null +++ b/java/res/xml/keys_comma_period.xml @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** 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. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <switch> + <case + latin:languageCode="ar" + > + <Key + latin:keyLabel="!text/keylabel_for_apostrophe" + latin:keyHintLabel="!text/keyhintlabel_for_apostrophe" + latin:moreKeys="!text/more_keys_for_apostrophe" + latin:backgroundType="functional" + latin:keyStyle="hasShiftedLetterHintStyle" /> + <Key + latin:keyLabel="." + latin:keyHintLabel="!text/keyhintlabel_for_arabic_diacritics" + latin:keyLabelFlags="hasPopupHint" + latin:moreKeys="!text/more_keys_for_arabic_diacritics" + latin:backgroundType="functional" + latin:keyStyle="hasShiftedLetterHintStyle" /> + </case> + <case + latin:languageCode="fa" + > + <Key + latin:keyLabel="!text/keylabel_for_apostrophe" + latin:keyHintLabel="!text/keyhintlabel_for_apostrophe" + latin:keyLabelFlags="hasPopupHint" + latin:moreKeys="!text/more_keys_for_apostrophe" + latin:backgroundType="functional" + latin:keyStyle="hasShiftedLetterHintStyle" /> + <Key + latin:keyLabel="." + latin:keyHintLabel="!text/keyhintlabel_for_arabic_diacritics" + latin:keyLabelFlags="hasPopupHint" + latin:moreKeys="!text/more_keys_for_arabic_diacritics" + latin:backgroundType="functional" + latin:keyStyle="hasShiftedLetterHintStyle" /> + </case> + <case + latin:languageCode="hy" + > + <!-- U+055D: "՝" ARMENIAN COMMA --> + <Key + latin:keyLabel="՝" + latin:backgroundType="functional" /> + <!-- U+0589: "։" ARMENIAN FULL STOP --> + <Key + latin:keyLabel="։" + latin:keyLabelFlags="hasPopupHint" + latin:backgroundType="functional" + latin:moreKeys="!text/more_keys_for_punctuation" /> + </case> + <default> + <Key + latin:keyLabel="!text/keylabel_for_tablet_comma" + latin:keyHintLabel="!text/keyhintlabel_for_tablet_comma" + latin:backgroundType="functional" + latin:moreKeys="!text/more_keys_for_tablet_comma" /> + <Key + latin:keyLabel="." + latin:keyHintLabel="!text/keyhintlabel_for_period" + latin:backgroundType="functional" + latin:moreKeys="!text/more_keys_for_period" /> + </default> + </switch> +</merge> diff --git a/java/res/xml/keys_comma_period_symbols.xml b/java/res/xml/keys_comma_period_symbols.xml deleted file mode 100644 index 6465fedd1..000000000 --- a/java/res/xml/keys_comma_period_symbols.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <Key - latin:keyLabel="," - latin:backgroundType="functional" /> - <!-- U+2026: "…" HORIZONTAL ELLIPSIS --> - <Key - latin:keyLabel="." - latin:moreKeys="…" - latin:backgroundType="functional" /> -</merge> diff --git a/java/res/xml/keys_pcqwerty4_right3.xml b/java/res/xml/keys_pcqwerty4_right3.xml index a5d5a429c..e6084cb45 100644 --- a/java/res/xml/keys_pcqwerty4_right3.xml +++ b/java/res/xml/keys_pcqwerty4_right3.xml @@ -34,7 +34,7 @@ <Key latin:keyLabel="/" latin:additionalMoreKeys="\?" - latin:moreKeys="!text/more_keys_for_question" /> + latin:moreKeys="!text/more_keys_for_symbols_question" /> </case> <!-- keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted" --> <default> @@ -52,7 +52,7 @@ latin:moreKeys="!fixedColumnOrder!3,›,≥,»" /> <Key latin:keyLabel="\?" - latin:moreKeys="!text/more_keys_for_question" /> + latin:moreKeys="!text/more_keys_for_symbols_question" /> </default> </switch> </merge> diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml index 78e771fda..0a27da93f 100644 --- a/java/res/xml/method.xml +++ b/java/res/xml/method.xml @@ -25,14 +25,13 @@ af: Afrikaans/qwerty ar: Arabic/arabic (az: Azerbaijani/qwerty) # disabled temporarily. waiting for string resources. - be_BY: Belarusian/east_slavic + be: Belarusian/east_slavic bg: Bulgarian/bulgarian bg: Bulgarian/bulgarian_bds ca: Catalan/spanish cs: Czech/qwertz da: Danish/nordic de: German/qwertz - de_CH: German Switzerland/swiss el: Greek/greek en_US: English United States/qwerty en_GB: English Great Britain/qwerty @@ -45,7 +44,6 @@ fi: Finnish/nordic fr: French/azerty fr_CA: French Canada/qwerty - fr_CH: French Switzerland/swiss hi: Hindi/hindi hr: Croatian/qwertz hu: Hungarian/qwertz @@ -90,22 +88,19 @@ (zz: Emoji/emoji) --> <!-- TODO: use <lang>_keyboard icon instead of a common keyboard icon. --> -<!-- TODO: Remove "AsciiCapable" from the extra values when we can stop supporting JB-MR1 --> <!-- Note: SupportTouchPositionCorrection extra value is obsolete and maintained for backward compatibility. --> <!-- If IME doesn't have an applicable subtype, the first subtype will be used as a default subtype.--> <input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="com.android.inputmethod.latin.settings.SettingsActivity" - android:isDefault="@bool/im_is_default" - android:supportsSwitchingToNextInputMethod="true"> + android:isDefault="@bool/im_is_default"> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_en_US" android:subtypeId="0xc9194f98" android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_en_GB" @@ -113,7 +108,6 @@ android:imeSubtypeLocale="en_GB" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -121,7 +115,6 @@ android:imeSubtypeLocale="af" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -129,7 +122,6 @@ android:imeSubtypeLocale="ar" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="false" /> <!-- <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -138,16 +130,14 @@ android:imeSubtypeLocale="az" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> --> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" android:subtypeId="0x1dc3a859" - android:imeSubtypeLocale="be_BY" + android:imeSubtypeLocale="be" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -155,7 +145,6 @@ android:imeSubtypeLocale="bg" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=bulgarian,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_bulgarian_bds" @@ -163,7 +152,6 @@ android:imeSubtypeLocale="bg" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=bulgarian_bds,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -171,7 +159,6 @@ android:imeSubtypeLocale="ca" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -179,7 +166,6 @@ android:imeSubtypeLocale="cs" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -187,7 +173,6 @@ android:imeSubtypeLocale="da" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -195,15 +180,6 @@ android:imeSubtypeLocale="de" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" - /> - <subtype android:icon="@drawable/ic_ime_switcher_dark" - android:label="@string/subtype_generic" - android:subtypeId="0x7acfd0aa" - android:imeSubtypeLocale="de_CH" - android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="KeyboardLayoutSet=swiss,AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -211,7 +187,6 @@ android:imeSubtypeLocale="el" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=greek,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -219,7 +194,6 @@ android:imeSubtypeLocale="eo" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -227,7 +201,6 @@ android:imeSubtypeLocale="es" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_es_US" @@ -235,7 +208,6 @@ android:imeSubtypeLocale="es_US" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <!-- <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -244,7 +216,6 @@ android:imeSubtypeLocale="es_419" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> --> <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -253,7 +224,6 @@ android:imeSubtypeLocale="et_EE" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=nordic,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -261,7 +231,6 @@ android:imeSubtypeLocale="fa" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=farsi,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -269,7 +238,6 @@ android:imeSubtypeLocale="fi" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -277,7 +245,6 @@ android:imeSubtypeLocale="fr" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -285,15 +252,6 @@ android:imeSubtypeLocale="fr_CA" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" - /> - <subtype android:icon="@drawable/ic_ime_switcher_dark" - android:label="@string/subtype_generic" - android:subtypeId="0xeadc55f5" - android:imeSubtypeLocale="fr_CH" - android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="KeyboardLayoutSet=swiss,AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -301,7 +259,6 @@ android:imeSubtypeLocale="hi" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=hindi,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -309,7 +266,6 @@ android:imeSubtypeLocale="hr" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -317,7 +273,6 @@ android:imeSubtypeLocale="hu" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -325,7 +280,6 @@ android:imeSubtypeLocale="hy_AM" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=armenian_phonetic,EmojiCapable" - android:isAsciiCapable="false" /> <!-- Java uses the deprecated "in" code instead of the standard "id" code for Indonesian. --> <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -334,7 +288,6 @@ android:imeSubtypeLocale="in" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -342,7 +295,6 @@ android:imeSubtypeLocale="is" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -350,7 +302,6 @@ android:imeSubtypeLocale="it" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <!-- Java uses the deprecated "iw" code instead of the standard "he" code for Hebrew. --> <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -359,7 +310,6 @@ android:imeSubtypeLocale="iw" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -367,7 +317,6 @@ android:imeSubtypeLocale="ka_GE" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=georgian,EmojiCapable" - android:isAsciiCapable="false" /> <!-- <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -376,7 +325,6 @@ android:imeSubtypeLocale="kk" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic,EmojiCapable" - android:isAsciiCapable="false" /> --> <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -385,7 +333,6 @@ android:imeSubtypeLocale="km_KH" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=khmer,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -393,7 +340,6 @@ android:imeSubtypeLocale="ky" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -401,7 +347,6 @@ android:imeSubtypeLocale="lo_LA" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=lao,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -409,7 +354,6 @@ android:imeSubtypeLocale="lt" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -417,7 +361,6 @@ android:imeSubtypeLocale="lv" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -425,7 +368,6 @@ android:imeSubtypeLocale="mk" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=south_slavic,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -433,7 +375,6 @@ android:imeSubtypeLocale="mn_MN" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=mongolian,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -441,7 +382,6 @@ android:imeSubtypeLocale="ms_MY" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -449,7 +389,6 @@ android:imeSubtypeLocale="nb" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <!-- <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -458,7 +397,6 @@ android:imeSubtypeLocale="ne" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=nepali_romanized,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_nepali_traditional" @@ -466,7 +404,6 @@ android:imeSubtypeLocale="ne" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=nepali_traditional,EmojiCapable" - android:isAsciiCapable="false" /> --> <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -475,7 +412,6 @@ android:imeSubtypeLocale="nl" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -483,7 +419,6 @@ android:imeSubtypeLocale="nl_BE" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=azerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -491,7 +426,6 @@ android:imeSubtypeLocale="pl" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -499,7 +433,6 @@ android:imeSubtypeLocale="pt_BR" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -507,7 +440,6 @@ android:imeSubtypeLocale="pt_PT" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -515,7 +447,6 @@ android:imeSubtypeLocale="ro" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -523,7 +454,6 @@ android:imeSubtypeLocale="ru" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -531,7 +461,6 @@ android:imeSubtypeLocale="sk" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -539,7 +468,6 @@ android:imeSubtypeLocale="sl" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -547,7 +475,6 @@ android:imeSubtypeLocale="sr" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="false" /> <!-- TODO: Uncomment once we can handle IETF language tag with script name specified. <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -556,7 +483,6 @@ android:imeSubtypeLocale="sr" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_serbian_latin" @@ -564,7 +490,6 @@ android:imeSubtypeLocale="sr-Latn" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> --> <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -573,7 +498,6 @@ android:imeSubtypeLocale="sv" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -581,7 +505,6 @@ android:imeSubtypeLocale="sw" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -589,7 +512,6 @@ android:imeSubtypeLocale="th" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=thai,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -597,7 +519,6 @@ android:imeSubtypeLocale="tl" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -605,7 +526,6 @@ android:imeSubtypeLocale="tr" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -613,7 +533,6 @@ android:imeSubtypeLocale="uk" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic,EmojiCapable" - android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -621,7 +540,6 @@ android:imeSubtypeLocale="vi" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -629,7 +547,6 @@ android:imeSubtypeLocale="zu" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_no_language_qwerty" @@ -637,7 +554,6 @@ android:imeSubtypeLocale="zz" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EnabledWhenDefaultIsNotAsciiCapable,EmojiCapable" - android:isAsciiCapable="true" /> <!-- Emoji subtype has to be an addtional subtype added at boot time because ICS doesn't support Emoji. --> @@ -648,7 +564,6 @@ android:imeSubtypeLocale="zz" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=emoji,EmojiCapable" - android:isAsciiCapable="false" /> --> </input-method> diff --git a/java/res/xml/prefs_for_debug.xml b/java/res/xml/prefs_for_debug.xml index 124c44388..8d9508e38 100644 --- a/java/res/xml/prefs_for_debug.xml +++ b/java/res/xml/prefs_for_debug.xml @@ -58,12 +58,6 @@ android:persistent="true" android:title="@string/prefs_use_only_personalization_dictionary" /> - <CheckBoxPreference - android:defaultValue="false" - android:key="boost_personalization_dictionary_for_debug" - android:persistent="true" - android:title="@string/prefs_boost_personalization_dictionary" /> - <PreferenceScreen android:key="read_external_dictionary" android:title="@string/prefs_read_external_dictionary" /> diff --git a/java/res/xml/row_pcqwerty5.xml b/java/res/xml/row_pcqwerty5.xml index 0a3f4d289..4ec908ba1 100644 --- a/java/res/xml/row_pcqwerty5.xml +++ b/java/res/xml/row_pcqwerty5.xml @@ -28,7 +28,7 @@ latin:keyWidth="11.538%p" /> <switch> <case - latin:supportsSwitchingToShortcutIme="true" + latin:shortcutKeyEnabled="true" > <Key latin:keyStyle="shortcutKeyStyle" diff --git a/java/res/xml/row_qwerty4.xml b/java/res/xml/row_qwerty4.xml index 509092d96..578bc1234 100644 --- a/java/res/xml/row_qwerty4.xml +++ b/java/res/xml/row_qwerty4.xml @@ -32,8 +32,36 @@ <include latin:keyXPos="25%p" latin:keyboardLayout="@xml/key_space_5kw" /> - <include - latin:keyboardLayout="@xml/key_period" /> + <switch> + <case + latin:languageCode="ar|fa" + > + <Key + latin:keyHintLabel="!text/keyhintlabel_for_arabic_diacritics" + latin:keyLabelFlags="hasPopupHint|hasShiftedLetterHint" + latin:moreKeys="!text/more_keys_for_arabic_diacritics" + latin:keyStyle="punctuationKeyStyle" /> + </case> + <case + latin:languageCode="ne" + latin:keyboardLayoutSet="nepali_traditional" + > + <include + latin:keyboardLayout="@xml/key_nepali_traditional_period" /> + </case> + <case + latin:languageCode="hy" + > + <!-- U+0589: "։" ARMENIAN FULL STOP --> + <Key + latin:keyLabel="։" + latin:keyStyle="punctuationKeyStyle" /> + </case> + <default> + <Key + latin:keyStyle="punctuationKeyStyle" /> + </default> + </switch> <Key latin:keyStyle="enterKeyStyle" latin:keyWidth="fillRight" /> diff --git a/java/res/xml/row_symbols4.xml b/java/res/xml/row_symbols4.xml index 09d2a1971..fbfdc5f72 100644 --- a/java/res/xml/row_symbols4.xml +++ b/java/res/xml/row_symbols4.xml @@ -19,12 +19,24 @@ --> <merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > + <Key + latin:backgroundType="functional" latin:keyLabel="_" /> <Key + latin:backgroundType="functional" latin:keyLabel="/" /> - <include - latin:keyboardLayout="@xml/key_space_symbols" /> - <include - latin:keyboardLayout="@xml/keys_comma_period_symbols" /> + + <switch> + <case latin:hasShortcutKey="true" > + <Key latin:keyStyle="shortcutKeyStyle" /> + </case> + <!-- latin:hasShortcutKey="false" --> + <default> + </default> + </switch> + + <include latin:keyboardLayout="@xml/key_space_symbols" /> + <include latin:keyboardLayout="@xml/keys_comma_period" /> + </merge> diff --git a/java/res/xml/row_symbols_shift4.xml b/java/res/xml/row_symbols_shift4.xml index f75575bc6..0909374f4 100644 --- a/java/res/xml/row_symbols_shift4.xml +++ b/java/res/xml/row_symbols_shift4.xml @@ -22,5 +22,5 @@ <include latin:keyboardLayout="@xml/keys_less_greater" /> <include latin:keyboardLayout="@xml/key_space_symbols" /> - <include latin:keyboardLayout="@xml/keys_comma_period_symbols" /> + <include latin:keyboardLayout="@xml/keys_comma_period" /> </merge> diff --git a/java/res/xml/rowkeys_khmer1.xml b/java/res/xml/rowkeys_khmer1.xml index 05d1a864a..25da66400 100644 --- a/java/res/xml/rowkeys_khmer1.xml +++ b/java/res/xml/rowkeys_khmer1.xml @@ -64,7 +64,6 @@ <Key latin:keyLabel="័" latin:keyHintLabel="៚" - latin:keyHintLabelVerticalAdjustment="-30%" latin:moreKeys="៚" latin:keyLabelFlags="fontNormal" /> <!-- U+17CF: "៏" KHMER SIGN AHSDA --> diff --git a/java/res/xml/rowkeys_khmer2.xml b/java/res/xml/rowkeys_khmer2.xml index 801f23ff6..cba2d3b90 100644 --- a/java/res/xml/rowkeys_khmer2.xml +++ b/java/res/xml/rowkeys_khmer2.xml @@ -31,13 +31,12 @@ latin:keyLabel="ឈ" latin:keyHintLabel="ៜ" latin:moreKeys="ៜ" - latin:keyLabelFlags="fontNormal|autoScale" /> + latin:keyLabelFlags="fontNormal" /> <!-- U+17BA: "ឺ" KHMER VOWEL SIGN YY U+17DD: "៝" KHMER SIGN ATTHACAN --> <Key latin:keyLabel="ឺ" latin:keyHintLabel="៝" - latin:keyHintLabelVerticalAdjustment="40%" latin:moreKeys="៝" latin:keyLabelFlags="fontNormal" /> <!-- U+17C2: "ែ" KHMER VOWEL SIGN AE --> @@ -70,7 +69,7 @@ <!-- U+17C5: "ៅ" KHMER VOWEL SIGN AU --> <Key latin:keyLabel="ៅ" - latin:keyLabelFlags="fontNormal|autoScale" /> + latin:keyLabelFlags="fontNormal" /> <!-- U+1797: "ភ" KHMER LETTER PHO --> <Key latin:keyLabel="ភ" @@ -78,7 +77,7 @@ <!-- U+17BF: "ឿ" KHMER VOWEL SIGN YA --> <Key latin:keyLabel="ឿ" - latin:keyLabelFlags="fontNormal|autoScale" /> + latin:keyLabelFlags="fontNormal" /> <!-- U+17B0: "ឰ" KHMER INDEPENDENT VOWEL QAI --> <Key latin:keyLabel="ឰ" @@ -120,7 +119,7 @@ <!-- U+17C4: "ោ" KHMER VOWEL SIGN OO --> <Key latin:keyLabel="ោ" - latin:keyLabelFlags="fontNormal|autoScale" /> + latin:keyLabelFlags="fontNormal" /> <!-- U+1795: "ផ" KHMER LETTER PHA --> <Key latin:keyLabel="ផ" @@ -128,7 +127,7 @@ <!-- U+17C0: "ៀ" KHMER VOWEL SIGN IE --> <Key latin:keyLabel="ៀ" - latin:keyLabelFlags="fontNormal|autoScale" /> + latin:keyLabelFlags="fontNormal" /> <!-- U+17AA: "ឪ" KHMER INDEPENDENT VOWEL QUUV U+17A7: "ឧ" KHMER INDEPENDENT VOWEL QU U+17B1: "ឱ" KHMER INDEPENDENT VOWEL QOO TYPE ONE diff --git a/java/res/xml/rowkeys_khmer3.xml b/java/res/xml/rowkeys_khmer3.xml index f35ba5c56..ff6c9ca51 100644 --- a/java/res/xml/rowkeys_khmer3.xml +++ b/java/res/xml/rowkeys_khmer3.xml @@ -70,7 +70,7 @@ <!-- U+17C4/U+17C7: "ោះ" KHMER VOWEL SIGN OO/KHMER SIGN REAHMUK --> <Key latin:keyLabel="ោះ" - latin:keyLabelFlags="fontNormal|followKeyLetterRatio|autoScale" /> + latin:keyLabelFlags="fontNormal" /> <!-- U+17C9: "៉" KHMER SIGN MUUSIKATOAN --> <Key latin:keyLabel="៉" diff --git a/java/res/xml/rowkeys_khmer4.xml b/java/res/xml/rowkeys_khmer4.xml index 598aed8d5..fe6c59125 100644 --- a/java/res/xml/rowkeys_khmer4.xml +++ b/java/res/xml/rowkeys_khmer4.xml @@ -40,7 +40,7 @@ <!-- U+17C1/U+17C7: "េះ" KHMER VOWEL SIGN E/KHMER SIGN REAHMUK --> <Key latin:keyLabel="េះ" - latin:keyLabelFlags="fontNormal|followKeyLetterRatio|autoScale" /> + latin:keyLabelFlags="fontNormal" /> <!-- U+1796: "ព" KHMER LETTER PO U+179E: "ឞ" KHMER LETTER SSO --> <Key @@ -51,7 +51,7 @@ <!-- U+178E: "ណ" KHMER LETTER NNO --> <Key latin:keyLabel="ណ" - latin:keyLabelFlags="fontNormal|autoScale" /> + latin:keyLabelFlags="fontNormal" /> <!-- U+17C6: "ំ" KHMER SIGN NIKAHIT --> <Key latin:keyLabel="ំ" diff --git a/java/res/xml/rowkeys_pcqwerty1.xml b/java/res/xml/rowkeys_pcqwerty1.xml index 1ac264afa..de548d0ba 100644 --- a/java/res/xml/rowkeys_pcqwerty1.xml +++ b/java/res/xml/rowkeys_pcqwerty1.xml @@ -26,7 +26,7 @@ latin:additionalMoreKeys="~" /> <Key latin:keyLabel="1" - latin:additionalMoreKeys="!,!text/more_keys_for_exclamation" + latin:additionalMoreKeys="!,!text/more_keys_for_symbols_exclamation" latin:moreKeys="!text/more_keys_for_symbols_1" /> <Key latin:keyLabel="2" diff --git a/java/res/xml/rowkeys_pcqwerty1_shift.xml b/java/res/xml/rowkeys_pcqwerty1_shift.xml index 718acfd24..bc39f944e 100644 --- a/java/res/xml/rowkeys_pcqwerty1_shift.xml +++ b/java/res/xml/rowkeys_pcqwerty1_shift.xml @@ -25,7 +25,7 @@ latin:keyLabel="~" /> <Key latin:keyLabel="!" - latin:additionalMoreKeys="!text/more_keys_for_exclamation" /> + latin:additionalMoreKeys="!text/more_keys_for_symbols_exclamation" /> <Key latin:keyLabel="\@" /> <Key diff --git a/java/res/xml/rowkeys_swiss1.xml b/java/res/xml/rowkeys_swiss1.xml deleted file mode 100644 index e3b842619..000000000 --- a/java/res/xml/rowkeys_swiss1.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/rowkeys_qwertz1" /> - <Key - latin:keyLabel="!text/keylabel_for_swiss_row1_11" - latin:moreKeys="!text/more_keys_for_swiss_row1_11" /> -</merge> diff --git a/java/res/xml/rowkeys_swiss2.xml b/java/res/xml/rowkeys_swiss2.xml deleted file mode 100644 index 5364a448c..000000000 --- a/java/res/xml/rowkeys_swiss2.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/rowkeys_qwerty2" /> - <Key - latin:keyLabel="!text/keylabel_for_swiss_row2_10" - latin:moreKeys="!text/more_keys_for_swiss_row2_10" /> - <Key - latin:keyLabel="!text/keylabel_for_swiss_row2_11" - latin:moreKeys="!text/more_keys_for_swiss_row2_11" /> -</merge> diff --git a/java/res/xml/rowkeys_symbols3.xml b/java/res/xml/rowkeys_symbols3.xml index e525dc480..074078cb6 100644 --- a/java/res/xml/rowkeys_symbols3.xml +++ b/java/res/xml/rowkeys_symbols3.xml @@ -55,8 +55,8 @@ latin:moreKeys="!text/more_keys_for_symbols_semicolon" /> <Key latin:keyLabel="!" - latin:moreKeys="!text/more_keys_for_exclamation" /> + latin:moreKeys="!text/more_keys_for_symbols_exclamation" /> <Key latin:keyLabel="!text/keylabel_for_symbols_question" - latin:moreKeys="!text/more_keys_for_question" /> + latin:moreKeys="!text/more_keys_for_symbols_question" /> </merge> diff --git a/java/res/xml/rows_swiss.xml b/java/res/xml/rows_swiss.xml deleted file mode 100644 index 03e412940..000000000 --- a/java/res/xml/rows_swiss.xml +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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 the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/key_styles_common" /> - <Row - latin:keyWidth="9.091%p" - > - <include - latin:keyboardLayout="@xml/rowkeys_swiss1" /> - </Row> - <Row - latin:keyWidth="9.091%p" - > - <include - latin:keyboardLayout="@xml/rowkeys_swiss2" /> - </Row> - <Row - latin:keyWidth="9.2%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="15%p" - latin:visualInsetsRight="1%p" /> - <Spacer - latin:keyWidth="2.8%p" /> - <include - latin:keyboardLayout="@xml/rowkeys_qwertz3" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-15%p" - latin:keyWidth="fillRight" - latin:visualInsetsLeft="1%p" /> - </Row> - <include - latin:keyboardLayout="@xml/row_qwerty4" /> -</merge> diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java index c601cf17e..73896dfd3 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java @@ -82,7 +82,7 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp private void initInternal(final InputMethodService inputMethod) { mInputMethod = inputMethod; mEdgeSlop = inputMethod.getResources().getDimensionPixelSize( - R.dimen.config_accessibility_edge_slop); + R.dimen.accessibility_edge_slop); } /** diff --git a/java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java b/java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java index d56a3cf25..e23131a30 100644 --- a/java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java +++ b/java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java @@ -31,17 +31,17 @@ public class EmojiCategoryPageIndicatorView extends LinearLayout { private int mCurrentCategoryPageId = 0; private float mOffset = 0.0f; - public EmojiCategoryPageIndicatorView(final Context context) { + public EmojiCategoryPageIndicatorView(Context context) { this(context, null /* attrs */); } - public EmojiCategoryPageIndicatorView(final Context context, final AttributeSet attrs) { + public EmojiCategoryPageIndicatorView(Context context, AttributeSet attrs) { super(context, attrs); mPaint.setColor(context.getResources().getColor( R.color.emoji_category_page_id_view_foreground)); } - public void setCategoryPageId(final int size, final int id, final float offset) { + public void setCategoryPageId(int size, int id, float offset) { mCategoryPageSize = size; mCurrentCategoryPageId = id; mOffset = offset; @@ -49,7 +49,7 @@ public class EmojiCategoryPageIndicatorView extends LinearLayout { } @Override - protected void onDraw(final Canvas canvas) { + protected void onDraw(Canvas canvas) { if (mCategoryPageSize <= 1) { // If the category is not set yet or contains only one category, // just clear and return. diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java b/java/src/com/android/inputmethod/keyboard/EmojiLayoutParams.java index 12e063261..967448c28 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java +++ b/java/src/com/android/inputmethod/keyboard/EmojiLayoutParams.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.inputmethod.keyboard.internal; +package com.android.inputmethod.keyboard; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.utils.ResourceUtils; @@ -37,22 +37,22 @@ public class EmojiLayoutParams { private final int mBottomPadding; private final int mTopPadding; - public EmojiLayoutParams(final Resources res) { + public EmojiLayoutParams(Resources res) { final int defaultKeyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res); final int defaultKeyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res); - mKeyVerticalGap = (int) res.getFraction(R.fraction.config_key_vertical_gap_holo, - defaultKeyboardHeight, defaultKeyboardHeight); - mBottomPadding = (int) res.getFraction(R.fraction.config_keyboard_bottom_padding_holo, - defaultKeyboardHeight, defaultKeyboardHeight); - mTopPadding = (int) res.getFraction(R.fraction.config_keyboard_top_padding_holo, - defaultKeyboardHeight, defaultKeyboardHeight); - mKeyHorizontalGap = (int) (res.getFraction(R.fraction.config_key_horizontal_gap_holo, + mKeyVerticalGap = (int) res.getFraction(R.fraction.key_bottom_gap_holo, + (int) defaultKeyboardHeight, (int) defaultKeyboardHeight); + mBottomPadding = (int) res.getFraction(R.fraction.keyboard_bottom_padding_holo, + (int) defaultKeyboardHeight, (int) defaultKeyboardHeight); + mTopPadding = (int) res.getFraction(R.fraction.keyboard_top_padding_holo, + (int) defaultKeyboardHeight, (int) defaultKeyboardHeight); + mKeyHorizontalGap = (int) (res.getFraction(R.fraction.key_horizontal_gap_holo, defaultKeyboardWidth, defaultKeyboardWidth)); mEmojiCategoryPageIdViewHeight = - (int) (res.getDimension(R.dimen.config_emoji_category_page_id_height)); + (int) (res.getDimension(R.dimen.emoji_category_page_id_height)); final int baseheight = defaultKeyboardHeight - mBottomPadding - mTopPadding + mKeyVerticalGap; - mEmojiActionBarHeight = baseheight / DEFAULT_KEYBOARD_ROWS + mEmojiActionBarHeight = ((int) baseheight) / DEFAULT_KEYBOARD_ROWS - (mKeyVerticalGap - mBottomPadding) / 2; mEmojiPagerHeight = defaultKeyboardHeight - mEmojiActionBarHeight - mEmojiCategoryPageIdViewHeight; @@ -60,26 +60,26 @@ public class EmojiLayoutParams { mEmojiKeyboardHeight = mEmojiPagerHeight - mEmojiPagerBottomMargin - 1; } - public void setPagerProperties(final ViewPager vp) { + public void setPagerProperties(ViewPager vp) { final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) vp.getLayoutParams(); lp.height = mEmojiKeyboardHeight; lp.bottomMargin = mEmojiPagerBottomMargin; vp.setLayoutParams(lp); } - public void setCategoryPageIdViewProperties(final LinearLayout ll) { + public void setCategoryPageIdViewProperties(LinearLayout ll) { final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) ll.getLayoutParams(); lp.height = mEmojiCategoryPageIdViewHeight; ll.setLayoutParams(lp); } - public void setActionBarProperties(final LinearLayout ll) { + public void setActionBarProperties(LinearLayout ll) { final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) ll.getLayoutParams(); lp.height = mEmojiActionBarHeight - mBottomPadding; ll.setLayoutParams(lp); } - public void setKeyProperties(final ImageView ib) { + public void setKeyProperties(ImageView ib) { final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) ib.getLayoutParams(); lp.leftMargin = mKeyHorizontalGap / 2; lp.rightMargin = mKeyHorizontalGap / 2; diff --git a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java index ff0d53865..f12373503 100644 --- a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java +++ b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java @@ -44,8 +44,8 @@ import android.widget.TabHost.OnTabChangeListener; import android.widget.TextView; import com.android.inputmethod.keyboard.internal.DynamicGridKeyboard; -import com.android.inputmethod.keyboard.internal.EmojiLayoutParams; -import com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView; +import com.android.inputmethod.keyboard.internal.ScrollKeyboardView; +import com.android.inputmethod.keyboard.internal.ScrollViewWithNotifier; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SubtypeSwitcher; @@ -72,15 +72,15 @@ import java.util.concurrent.ConcurrentHashMap; */ public final class EmojiPalettesView extends LinearLayout implements OnTabChangeListener, ViewPager.OnPageChangeListener, View.OnClickListener, - EmojiPageKeyboardView.OnKeyClickListener { - static final String TAG = EmojiPalettesView.class.getSimpleName(); + ScrollKeyboardView.OnKeyClickListener { + private static final String TAG = EmojiPalettesView.class.getSimpleName(); private static final boolean DEBUG_PAGER = false; private final int mKeyBackgroundId; private final int mEmojiFunctionalKeyBackgroundId; + private final KeyboardLayoutSet mLayoutSet; private final ColorStateList mTabLabelColor; private final DeleteKeyOnTouchListener mDeleteKeyOnTouchListener; private EmojiPalettesAdapter mEmojiPalettesAdapter; - private final EmojiLayoutParams mEmojiLayoutParams; private TabHost mTabHost; private ViewPager mEmojiPager; @@ -149,7 +149,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange public EmojiCategory(final SharedPreferences prefs, final Resources res, final KeyboardLayoutSet layoutSet) { mPrefs = prefs; - mMaxPageKeyCount = res.getInteger(R.integer.config_emoji_keyboard_max_page_key_count); + mMaxPageKeyCount = res.getInteger(R.integer.emoji_keyboard_max_key_count); mLayoutSet = layoutSet; for (int i = 0; i < sCategoryName.length; ++i) { mCategoryNameToIdMap.put(sCategoryName[i], i); @@ -174,7 +174,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange .loadRecentKeys(mCategoryKeyboardMap.values()); } - private void addShownCategoryId(final int categoryId) { + private void addShownCategoryId(int categoryId) { // Load a keyboard of categoryId getKeyboard(categoryId, 0 /* cagetoryPageId */); final CategoryProperties properties = @@ -182,20 +182,20 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange mShownCategories.add(properties); } - public String getCategoryName(final int categoryId, final int categoryPageId) { + public String getCategoryName(int categoryId, int categoryPageId) { return sCategoryName[categoryId] + "-" + categoryPageId; } - public int getCategoryId(final String name) { + public int getCategoryId(String name) { final String[] strings = name.split("-"); return mCategoryNameToIdMap.get(strings[0]); } - public int getCategoryIcon(final int categoryId) { + public int getCategoryIcon(int categoryId) { return sCategoryIcon[categoryId]; } - public String getCategoryLabel(final int categoryId) { + public String getCategoryLabel(int categoryId) { return sCategoryLabel[categoryId]; } @@ -211,7 +211,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange return getCategoryPageSize(mCurrentCategoryId); } - public int getCategoryPageSize(final int categoryId) { + public int getCategoryPageSize(int categoryId) { for (final CategoryProperties prop : mShownCategories) { if (prop.mCategoryId == categoryId) { return prop.mPageCount; @@ -222,12 +222,12 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange return 0; } - public void setCurrentCategoryId(final int categoryId) { + public void setCurrentCategoryId(int categoryId) { mCurrentCategoryId = categoryId; Settings.writeLastShownEmojiCategoryId(mPrefs, categoryId); } - public void setCurrentCategoryPageId(final int id) { + public void setCurrentCategoryPageId(int id) { mCurrentCategoryPageId = id; } @@ -244,7 +244,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange return mCurrentCategoryId == CATEGORY_ID_RECENTS; } - public int getTabIdFromCategoryId(final int categoryId) { + public int getTabIdFromCategoryId(int categoryId) { for (int i = 0; i < mShownCategories.size(); ++i) { if (mShownCategories.get(i).mCategoryId == categoryId) { return i; @@ -255,7 +255,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange } // Returns the view pager's page position for the categoryId - public int getPageIdFromCategoryId(final int categoryId) { + public int getPageIdFromCategoryId(int categoryId) { final int lastSavedCategoryPageId = Settings.readLastTypedEmojiCategoryPageId(mPrefs, categoryId); int sum = 0; @@ -274,7 +274,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange return getTabIdFromCategoryId(CATEGORY_ID_RECENTS); } - private int getCategoryPageCount(final int categoryId) { + private int getCategoryPageCount(int categoryId) { final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[categoryId]); return (keyboard.getKeys().length - 1) / mMaxPageKeyCount + 1; } @@ -283,9 +283,9 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange // position. The category page id is numbered in each category. And the view page position // is the position of the current shown page in the view pager which contains all pages of // all categories. - public Pair<Integer, Integer> getCategoryIdAndPageIdFromPagePosition(final int position) { + public Pair<Integer, Integer> getCategoryIdAndPageIdFromPagePosition(int position) { int sum = 0; - for (final CategoryProperties properties : mShownCategories) { + for (CategoryProperties properties : mShownCategories) { final int temp = sum; sum += properties.mPageCount; if (sum > position) { @@ -296,7 +296,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange } // Returns a keyboard from the view pager's page position. - public DynamicGridKeyboard getKeyboardFromPagePosition(final int position) { + public DynamicGridKeyboard getKeyboardFromPagePosition(int position) { final Pair<Integer, Integer> categoryAndId = getCategoryIdAndPageIdFromPagePosition(position); if (categoryAndId != null) { @@ -305,41 +305,39 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange return null; } - private static final Long getCategoryKeyboardMapKey(final int categoryId, final int id) { - return (((long) categoryId) << Constants.MAX_INT_BIT_COUNT) | id; - } - - public DynamicGridKeyboard getKeyboard(final int categoryId, final int id) { - synchronized (mCategoryKeyboardMap) { - final Long categotyKeyboardMapKey = getCategoryKeyboardMapKey(categoryId, id); - if (mCategoryKeyboardMap.containsKey(categotyKeyboardMapKey)) { - return mCategoryKeyboardMap.get(categotyKeyboardMapKey); - } - - if (categoryId == CATEGORY_ID_RECENTS) { - final DynamicGridKeyboard kbd = new DynamicGridKeyboard(mPrefs, - mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS), - mMaxPageKeyCount, categoryId); - mCategoryKeyboardMap.put(categotyKeyboardMapKey, kbd); - return kbd; - } - - final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[categoryId]); - final Key[][] sortedKeys = sortKeysIntoPages(keyboard.getKeys(), mMaxPageKeyCount); - for (int pageId = 0; pageId < sortedKeys.length; ++pageId) { - final DynamicGridKeyboard tempKeyboard = new DynamicGridKeyboard(mPrefs, - mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS), - mMaxPageKeyCount, categoryId); - for (final Key emojiKey : sortedKeys[pageId]) { - if (emojiKey == null) { - break; + public DynamicGridKeyboard getKeyboard(int categoryId, int id) { + synchronized(mCategoryKeyboardMap) { + final long key = (((long) categoryId) << Constants.MAX_INT_BIT_COUNT) | id; + final DynamicGridKeyboard kbd; + if (!mCategoryKeyboardMap.containsKey(key)) { + if (categoryId != CATEGORY_ID_RECENTS) { + final Keyboard keyboard = + mLayoutSet.getKeyboard(sCategoryElementId[categoryId]); + final Key[][] sortedKeys = sortKeys(keyboard.getKeys(), mMaxPageKeyCount); + for (int i = 0; i < sortedKeys.length; ++i) { + final DynamicGridKeyboard tempKbd = new DynamicGridKeyboard(mPrefs, + mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS), + mMaxPageKeyCount, categoryId, i /* categoryPageId */); + for (Key emojiKey : sortedKeys[i]) { + if (emojiKey == null) { + break; + } + tempKbd.addKeyLast(emojiKey); + } + mCategoryKeyboardMap.put((((long) categoryId) + << Constants.MAX_INT_BIT_COUNT) | i, tempKbd); } - tempKeyboard.addKeyLast(emojiKey); + kbd = mCategoryKeyboardMap.get(key); + } else { + kbd = new DynamicGridKeyboard(mPrefs, + mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS), + mMaxPageKeyCount, categoryId, 0 /* categoryPageId */); + mCategoryKeyboardMap.put(key, kbd); } - mCategoryKeyboardMap.put( - getCategoryKeyboardMapKey(categoryId, pageId), tempKeyboard); + } else { + kbd = mCategoryKeyboardMap.get(key); } - return mCategoryKeyboardMap.get(categotyKeyboardMapKey); + return kbd; } } @@ -351,31 +349,29 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange return sum; } - private static Comparator<Key> EMOJI_KEY_COMPARATOR = new Comparator<Key>() { - @Override - public int compare(final Key lhs, final Key rhs) { - final Rect lHitBox = lhs.getHitBox(); - final Rect rHitBox = rhs.getHitBox(); - if (lHitBox.top < rHitBox.top) { - return -1; - } else if (lHitBox.top > rHitBox.top) { - return 1; - } - if (lHitBox.left < rHitBox.left) { - return -1; - } else if (lHitBox.left > rHitBox.left) { - return 1; - } - if (lhs.getCode() == rhs.getCode()) { - return 0; + private Key[][] sortKeys(Key[] inKeys, int maxPageCount) { + Key[] keys = Arrays.copyOf(inKeys, inKeys.length); + Arrays.sort(keys, 0, keys.length, new Comparator<Key>() { + @Override + public int compare(Key lhs, Key rhs) { + final Rect lHitBox = lhs.getHitBox(); + final Rect rHitBox = rhs.getHitBox(); + if (lHitBox.top < rHitBox.top) { + return -1; + } else if (lHitBox.top > rHitBox.top) { + return 1; + } + if (lHitBox.left < rHitBox.left) { + return -1; + } else if (lHitBox.left > rHitBox.left) { + return 1; + } + if (lhs.getCode() == rhs.getCode()) { + return 0; + } + return lhs.getCode() < rhs.getCode() ? -1 : 1; } - return lhs.getCode() < rhs.getCode() ? -1 : 1; - } - }; - - private static Key[][] sortKeysIntoPages(final Key[] inKeys, final int maxPageCount) { - final Key[] keys = Arrays.copyOf(inKeys, inKeys.length); - Arrays.sort(keys, 0, keys.length, EMOJI_KEY_COMPARATOR); + }); final int pageCount = (keys.length - 1) / maxPageCount + 1; final Key[][] retval = new Key[pageCount][maxPageCount]; for (int i = 0; i < keys.length; ++i) { @@ -408,12 +404,12 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder( context, null /* editorInfo */); final Resources res = context.getResources(); - mEmojiLayoutParams = new EmojiLayoutParams(res); + final EmojiLayoutParams emojiLp = new EmojiLayoutParams(res); builder.setSubtype(SubtypeSwitcher.getInstance().getEmojiSubtype()); builder.setKeyboardGeometry(ResourceUtils.getDefaultKeyboardWidth(res), - mEmojiLayoutParams.mEmojiKeyboardHeight); - builder.setOptions(false /* shortcutImeEnabled */, false /* showsVoiceInputKey */, - false /* languageSwitchKeyEnabled */); + emojiLp.mEmojiKeyboardHeight); + builder.setOptions(false, false, false /* lanuageSwitchKeyEnabled */); + mLayoutSet = builder.build(); mEmojiCategory = new EmojiCategory(PreferenceManager.getDefaultSharedPreferences(context), context.getResources(), builder.build()); mDeleteKeyOnTouchListener = new DeleteKeyOnTouchListener(context); @@ -427,7 +423,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange final int width = ResourceUtils.getDefaultKeyboardWidth(res) + getPaddingLeft() + getPaddingRight(); final int height = ResourceUtils.getDefaultKeyboardHeight(res) - + res.getDimensionPixelSize(R.dimen.config_suggestions_strip_height) + + res.getDimensionPixelSize(R.dimen.suggestions_strip_height) + getPaddingTop() + getPaddingBottom(); setMeasuredDimension(width, height); } @@ -462,23 +458,25 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange mTabHost.setOnTabChangedListener(this); mTabHost.getTabWidget().setStripEnabled(true); - mEmojiPalettesAdapter = new EmojiPalettesAdapter(mEmojiCategory, this); + mEmojiPalettesAdapter = new EmojiPalettesAdapter(mEmojiCategory, mLayoutSet, this); mEmojiPager = (ViewPager)findViewById(R.id.emoji_keyboard_pager); mEmojiPager.setAdapter(mEmojiPalettesAdapter); mEmojiPager.setOnPageChangeListener(this); mEmojiPager.setOffscreenPageLimit(0); - mEmojiPager.setPersistentDrawingCache(PERSISTENT_NO_CACHE); - mEmojiLayoutParams.setPagerProperties(mEmojiPager); + mEmojiPager.setPersistentDrawingCache(ViewPager.PERSISTENT_NO_CACHE); + final Resources res = getResources(); + final EmojiLayoutParams emojiLp = new EmojiLayoutParams(res); + emojiLp.setPagerProperties(mEmojiPager); mEmojiCategoryPageIndicatorView = (EmojiCategoryPageIndicatorView)findViewById(R.id.emoji_category_page_id_view); - mEmojiLayoutParams.setCategoryPageIdViewProperties(mEmojiCategoryPageIndicatorView); + emojiLp.setCategoryPageIdViewProperties(mEmojiCategoryPageIndicatorView); setCurrentCategoryId(mEmojiCategory.getCurrentCategoryId(), true /* force */); final LinearLayout actionBar = (LinearLayout)findViewById(R.id.emoji_action_bar); - mEmojiLayoutParams.setActionBarProperties(actionBar); + emojiLp.setActionBarProperties(actionBar); final ImageView deleteKey = (ImageView)findViewById(R.id.emoji_keyboard_delete); deleteKey.setTag(Constants.CODE_DELETE); @@ -491,7 +489,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange spaceKey.setBackgroundResource(mKeyBackgroundId); spaceKey.setTag(Constants.CODE_SPACE); spaceKey.setOnClickListener(this); - mEmojiLayoutParams.setKeyProperties(spaceKey); + emojiLp.setKeyProperties(spaceKey); final ImageView alphabetKey2 = (ImageView)findViewById(R.id.emoji_keyboard_alphabet2); alphabetKey2.setBackgroundResource(mEmojiFunctionalKeyBackgroundId); alphabetKey2.setTag(Constants.CODE_SWITCH_ALPHA_SYMBOL); @@ -630,15 +628,16 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange } private static class EmojiPalettesAdapter extends PagerAdapter { - private final EmojiPageKeyboardView.OnKeyClickListener mListener; + private final ScrollKeyboardView.OnKeyClickListener mListener; private final DynamicGridKeyboard mRecentsKeyboard; - private final SparseArray<EmojiPageKeyboardView> mActiveKeyboardViews = + private final SparseArray<ScrollKeyboardView> mActiveKeyboardViews = CollectionUtils.newSparseArray(); private final EmojiCategory mEmojiCategory; private int mActivePosition = 0; public EmojiPalettesAdapter(final EmojiCategory emojiCategory, - final EmojiPageKeyboardView.OnKeyClickListener listener) { + final KeyboardLayoutSet layoutSet, + final ScrollKeyboardView.OnKeyClickListener listener) { mEmojiCategory = emojiCategory; mListener = listener; mRecentsKeyboard = mEmojiCategory.getKeyboard(CATEGORY_ID_RECENTS, 0); @@ -672,12 +671,11 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange } @Override - public void setPrimaryItem(final ViewGroup container, final int position, - final Object object) { + public void setPrimaryItem(final View container, final int position, final Object object) { if (mActivePosition == position) { return; } - final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition); + final ScrollKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition); if (oldKeyboardView != null) { oldKeyboardView.releaseCurrentKey(); oldKeyboardView.deallocateMemory(); @@ -690,7 +688,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange if (DEBUG_PAGER) { Log.d(TAG, "instantiate item: " + position); } - final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position); + final ScrollKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position); if (oldKeyboardView != null) { oldKeyboardView.deallocateMemory(); // This may be redundant but wanted to be safer.. @@ -699,13 +697,18 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange final Keyboard keyboard = mEmojiCategory.getKeyboardFromPagePosition(position); final LayoutInflater inflater = LayoutInflater.from(container.getContext()); - final EmojiPageKeyboardView keyboardView = (EmojiPageKeyboardView)inflater.inflate( + final View view = inflater.inflate( R.layout.emoji_keyboard_page, container, false /* attachToRoot */); + final ScrollKeyboardView keyboardView = (ScrollKeyboardView)view.findViewById( + R.id.emoji_keyboard_page); keyboardView.setKeyboard(keyboard); keyboardView.setOnKeyClickListener(mListener); - container.addView(keyboardView); + final ScrollViewWithNotifier scrollView = (ScrollViewWithNotifier)view.findViewById( + R.id.emoji_keyboard_scroller); + keyboardView.setScrollView(scrollView); + container.addView(view); mActiveKeyboardViews.put(position, keyboardView); - return keyboardView; + return view; } @Override @@ -719,7 +722,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange if (DEBUG_PAGER) { Log.d(TAG, "destroy item: " + position + ", " + object.getClass().getSimpleName()); } - final EmojiPageKeyboardView keyboardView = mActiveKeyboardViews.get(position); + final ScrollKeyboardView keyboardView = mActiveKeyboardViews.get(position); if (keyboardView != null) { keyboardView.deallocateMemory(); mActiveKeyboardViews.remove(position); @@ -792,7 +795,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange } } - public void pressDelete(final int repeatCount) { + public void pressDelete(int repeatCount) { mKeyboardActionListener.onPressKey( Constants.CODE_DELETE, repeatCount, true /* isSinglePointer */); mKeyboardActionListener.onCodeInput( @@ -801,22 +804,22 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange Constants.CODE_DELETE, false /* withSliding */); } - public void setKeyboardActionListener(final KeyboardActionListener listener) { + public void setKeyboardActionListener(KeyboardActionListener listener) { mKeyboardActionListener = listener; } @Override - public boolean onTouch(final View v, final MotionEvent event) { + public boolean onTouch(View v, MotionEvent event) { switch(event.getAction()) { - case MotionEvent.ACTION_DOWN: - v.setBackgroundColor(mDeleteKeyPressedBackgroundColor); - pressDelete(0 /* repeatCount */); - startRepeat(); - return true; - case MotionEvent.ACTION_UP: - v.setBackgroundColor(0); - abortRepeat(); - return true; + case MotionEvent.ACTION_DOWN: + v.setBackgroundColor(mDeleteKeyPressedBackgroundColor); + pressDelete(0 /* repeatCount */); + startRepeat(); + return true; + case MotionEvent.ACTION_UP: + v.setBackgroundColor(0); + abortRepeat(); + return true; } return false; } diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index b975b9c70..f7ec9509d 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -28,6 +28,7 @@ import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.text.TextUtils; +import android.util.Log; import android.util.Xml; import com.android.inputmethod.keyboard.internal.KeyDrawParams; @@ -52,6 +53,8 @@ import java.util.Locale; * Class for describing the position and characteristics of a single key in the keyboard. */ public class Key implements Comparable<Key> { + private static final String TAG = Key.class.getSimpleName(); + /** * The key code (unicode or custom code) that this key generates. */ @@ -81,16 +84,10 @@ public class Key implements Comparable<Key> { private static final int LABEL_FLAGS_HAS_HINT_LABEL = 0x800; private static final int LABEL_FLAGS_WITH_ICON_LEFT = 0x1000; private static final int LABEL_FLAGS_WITH_ICON_RIGHT = 0x2000; - // The bit to calculate the ratio of key label width against key width. If autoXScale bit is on - // and autoYScale bit is off, the key label may be shrunk only for X-direction. - // If both autoXScale and autoYScale bits are on, the key label text size may be auto scaled. private static final int LABEL_FLAGS_AUTO_X_SCALE = 0x4000; - private static final int LABEL_FLAGS_AUTO_Y_SCALE = 0x8000; - private static final int LABEL_FLAGS_AUTO_SCALE = LABEL_FLAGS_AUTO_X_SCALE - | LABEL_FLAGS_AUTO_Y_SCALE; - private static final int LABEL_FLAGS_PRESERVE_CASE = 0x10000; - private static final int LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED = 0x20000; - private static final int LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL = 0x40000; + private static final int LABEL_FLAGS_PRESERVE_CASE = 0x8000; + private static final int LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED = 0x10000; + private static final int LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL = 0x20000; private static final int LABEL_FLAGS_DISABLE_HINT_LABEL = 0x40000000; private static final int LABEL_FLAGS_DISABLE_ADDITIONAL_MORE_KEYS = 0x80000000; @@ -379,6 +376,9 @@ public class Key implements Comparable<Key> { mKeyVisualAttributes = KeyVisualAttributes.newInstance(keyAttr); keyAttr.recycle(); mHashCode = computeHashCode(this); + if (hasShiftedLetterHint() && TextUtils.isEmpty(mHintLabel)) { + Log.w(TAG, "hasShiftedLetterHint specified without keyHintLabel: " + this); + } } /** @@ -702,14 +702,10 @@ public class Key implements Comparable<Key> { return (mLabelFlags & LABEL_FLAGS_WITH_ICON_RIGHT) != 0; } - public final boolean needsAutoXScale() { + public final boolean needsXScale() { return (mLabelFlags & LABEL_FLAGS_AUTO_X_SCALE) != 0; } - public final boolean needsAutoScale() { - return (mLabelFlags & LABEL_FLAGS_AUTO_SCALE) == LABEL_FLAGS_AUTO_SCALE; - } - public final boolean isShiftedLetterActivated() { return (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0; } diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java index 149f10fd7..befb6fa92 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java +++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java @@ -81,7 +81,7 @@ public class KeyDetector { return mKeyboard; } - public boolean alwaysAllowsKeySelectionByDraggingFinger() { + public boolean alwaysAllowsSlidingInput() { return false; } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java index 02beb3f11..736f13ed6 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java @@ -70,7 +70,8 @@ public final class KeyboardId { public final int mElementId; private final EditorInfo mEditorInfo; public final boolean mClobberSettingsKey; - public final boolean mSupportsSwitchingToShortcutIme; + public final boolean mShortcutKeyEnabled; + public final boolean mShortcutKeyOnSymbols; public final boolean mLanguageSwitchKeyEnabled; public final String mCustomActionLabel; public final boolean mHasShortcutKey; @@ -86,11 +87,17 @@ public final class KeyboardId { mElementId = elementId; mEditorInfo = params.mEditorInfo; mClobberSettingsKey = params.mNoSettingsKey; - mSupportsSwitchingToShortcutIme = params.mSupportsSwitchingToShortcutIme; + mShortcutKeyEnabled = params.mVoiceKeyEnabled; + mShortcutKeyOnSymbols = mShortcutKeyEnabled && !params.mVoiceKeyOnMain; mLanguageSwitchKeyEnabled = params.mLanguageSwitchKeyEnabled; mCustomActionLabel = (mEditorInfo.actionLabel != null) ? mEditorInfo.actionLabel.toString() : null; - mHasShortcutKey = mSupportsSwitchingToShortcutIme && params.mShowsVoiceInputKey; + final boolean alphabetMayHaveShortcutKey = isAlphabetKeyboard(elementId) + && !mShortcutKeyOnSymbols; + final boolean symbolsMayHaveShortcutKey = (elementId == KeyboardId.ELEMENT_SYMBOLS) + && mShortcutKeyOnSymbols; + mHasShortcutKey = mShortcutKeyEnabled + && (alphabetMayHaveShortcutKey || symbolsMayHaveShortcutKey); mHashCode = computeHashCode(this); } @@ -103,8 +110,8 @@ public final class KeyboardId { id.mHeight, id.passwordInput(), id.mClobberSettingsKey, - id.mSupportsSwitchingToShortcutIme, - id.mHasShortcutKey, + id.mShortcutKeyEnabled, + id.mShortcutKeyOnSymbols, id.mLanguageSwitchKeyEnabled, id.isMultiLine(), id.imeAction(), @@ -124,8 +131,8 @@ public final class KeyboardId { && other.mHeight == mHeight && other.passwordInput() == passwordInput() && other.mClobberSettingsKey == mClobberSettingsKey - && other.mSupportsSwitchingToShortcutIme == mSupportsSwitchingToShortcutIme - && other.mHasShortcutKey == mHasShortcutKey + && other.mShortcutKeyEnabled == mShortcutKeyEnabled + && other.mShortcutKeyOnSymbols == mShortcutKeyOnSymbols && other.mLanguageSwitchKeyEnabled == mLanguageSwitchKeyEnabled && other.isMultiLine() == isMultiLine() && other.imeAction() == imeAction() @@ -179,20 +186,21 @@ public final class KeyboardId { @Override public String toString() { - return String.format(Locale.ROOT, "[%s %s:%s %dx%d %s %s%s%s%s%s%s%s%s%s]", + return String.format(Locale.ROOT, "[%s %s:%s %dx%d %s %s %s%s%s%s%s%s%s%s%s]", elementIdToName(mElementId), mLocale, mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET), mWidth, mHeight, modeName(mMode), - actionName(imeAction()), - (navigateNext() ? " navigateNext" : ""), - (navigatePrevious() ? " navigatePrevious" : ""), + imeAction(), + (navigateNext() ? "navigateNext" : ""), + (navigatePrevious() ? "navigatePrevious" : ""), (mClobberSettingsKey ? " clobberSettingsKey" : ""), (passwordInput() ? " passwordInput" : ""), - (mSupportsSwitchingToShortcutIme ? " supportsSwitchingToShortcutIme" : ""), + (mShortcutKeyEnabled ? " shortcutKeyEnabled" : ""), + (mShortcutKeyOnSymbols ? " shortcutKeyOnSymbols" : ""), (mHasShortcutKey ? " hasShortcutKey" : ""), (mLanguageSwitchKeyEnabled ? " languageSwitchKeyEnabled" : ""), - (isMultiLine() ? " isMultiLine" : "") + (isMultiLine() ? "isMultiLine" : "") ); } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java index e5b814faf..1eccdf341 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java @@ -105,10 +105,10 @@ public final class KeyboardLayoutSet { int mMode; EditorInfo mEditorInfo; boolean mDisableTouchPositionCorrectionDataForTest; - boolean mIsPasswordField; - boolean mSupportsSwitchingToShortcutIme; - boolean mShowsVoiceInputKey; - boolean mNoMicrophoneKey; + boolean mVoiceKeyEnabled; + // TODO: Remove mVoiceKeyOnMain when it's certainly confirmed that we no longer show + // the voice input key on the symbol layout + boolean mVoiceKeyOnMain; boolean mNoSettingsKey; boolean mLanguageSwitchKeyEnabled; InputMethodSubtype mSubtype; @@ -221,24 +221,16 @@ public final class KeyboardLayoutSet { private static final EditorInfo EMPTY_EDITOR_INFO = new EditorInfo(); - public Builder(final Context context, final EditorInfo ei) { + public Builder(final Context context, final EditorInfo editorInfo) { mContext = context; mPackageName = context.getPackageName(); mResources = context.getResources(); final Params params = mParams; - final EditorInfo editorInfo = (ei != null) ? ei : EMPTY_EDITOR_INFO; params.mMode = getKeyboardMode(editorInfo); - params.mEditorInfo = editorInfo; - params.mIsPasswordField = InputTypeUtils.isPasswordInputType(editorInfo.inputType); - @SuppressWarnings("deprecation") - final boolean deprecatedNoMicrophone = InputAttributes.inPrivateImeOptions( - null, NO_MICROPHONE_COMPAT, editorInfo); - params.mNoMicrophoneKey = InputAttributes.inPrivateImeOptions( - mPackageName, NO_MICROPHONE, editorInfo) - || deprecatedNoMicrophone; + params.mEditorInfo = (editorInfo != null) ? editorInfo : EMPTY_EDITOR_INFO; params.mNoSettingsKey = InputAttributes.inPrivateImeOptions( - mPackageName, NO_SETTINGS_KEY, editorInfo); + mPackageName, NO_SETTINGS_KEY, params.mEditorInfo); } public Builder setKeyboardGeometry(final int keyboardWidth, final int keyboardHeight) { @@ -269,11 +261,18 @@ public final class KeyboardLayoutSet { return this; } - public Builder setOptions(final boolean isShortcutImeEnabled, - final boolean showsVoiceInputKey, final boolean languageSwitchKeyEnabled) { - mParams.mSupportsSwitchingToShortcutIme = - isShortcutImeEnabled && !mParams.mNoMicrophoneKey && !mParams.mIsPasswordField; - mParams.mShowsVoiceInputKey = showsVoiceInputKey; + // TODO: Remove mVoiceKeyOnMain when it's certainly confirmed that we no longer show + // the voice input key on the symbol layout + public Builder setOptions(final boolean voiceKeyEnabled, final boolean voiceKeyOnMain, + final boolean languageSwitchKeyEnabled) { + @SuppressWarnings("deprecation") + final boolean deprecatedNoMicrophone = InputAttributes.inPrivateImeOptions( + null, NO_MICROPHONE_COMPAT, mParams.mEditorInfo); + final boolean noMicrophone = InputAttributes.inPrivateImeOptions( + mPackageName, NO_MICROPHONE, mParams.mEditorInfo) + || deprecatedNoMicrophone; + mParams.mVoiceKeyEnabled = voiceKeyEnabled && !noMicrophone; + mParams.mVoiceKeyOnMain = voiceKeyOnMain; mParams.mLanguageSwitchKeyEnabled = languageSwitchKeyEnabled; return this; } @@ -369,6 +368,9 @@ public final class KeyboardLayoutSet { } private static int getKeyboardMode(final EditorInfo editorInfo) { + if (editorInfo == null) + return KeyboardId.MODE_TEXT; + final int inputType = editorInfo.inputType; final int variation = inputType & InputType.TYPE_MASK_VARIATION; diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index fb84f1d73..5abc9ab38 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -154,8 +154,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { builder.setKeyboardGeometry(keyboardWidth, keyboardHeight); builder.setSubtype(mSubtypeSwitcher.getCurrentSubtype()); builder.setOptions( - mSubtypeSwitcher.isShortcutImeEnabled(), - settingsValues.mShowsVoiceInputKey, + settingsValues.isVoiceKeyEnabled(editorInfo), + true /* always show a voice key on the main keyboard */, settingsValues.isLanguageSwitchKeyEnabled()); mKeyboardLayoutSet = builder.build(); try { diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 422bd12a3..5578713a0 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -113,6 +113,9 @@ public class KeyboardView extends View { private final Canvas mOffscreenCanvas = new Canvas(); private final Paint mPaint = new Paint(); private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics(); + private static final char[] KEY_LABEL_REFERENCE_CHAR = { 'M' }; + private static final char[] KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR = { '8' }; + public KeyboardView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.keyboardViewStyle); } @@ -319,7 +322,7 @@ public class KeyboardView extends View { params.mAnimAlpha = Constants.Color.ALPHA_OPAQUE; if (!key.isSpacer()) { - onDrawKeyBackground(key, canvas, mKeyBackground); + onDrawKeyBackground(key, canvas); } onDrawKeyTopVisuals(key, canvas, paint, params); @@ -327,14 +330,14 @@ public class KeyboardView extends View { } // Draw key background. - protected void onDrawKeyBackground(final Key key, final Canvas canvas, - final Drawable background) { + protected void onDrawKeyBackground(final Key key, final Canvas canvas) { final Rect padding = mKeyBackgroundPadding; final int bgWidth = key.getDrawWidth() + padding.left + padding.right; final int bgHeight = key.getHeight() + padding.top + padding.bottom; final int bgX = -padding.left; final int bgY = -padding.top; final int[] drawableState = key.getCurrentDrawableState(); + final Drawable background = mKeyBackground; background.setState(drawableState); final Rect bounds = background.getBounds(); if (bgWidth != bounds.right || bgHeight != bounds.bottom) { @@ -367,8 +370,10 @@ public class KeyboardView extends View { if (label != null) { paint.setTypeface(key.selectTypeface(params)); paint.setTextSize(key.selectTextSize(params)); - final float labelCharHeight = TypefaceUtils.getReferenceCharHeight(paint); - final float labelCharWidth = TypefaceUtils.getReferenceCharWidth(paint); + final float labelCharHeight = TypefaceUtils.getCharHeight( + KEY_LABEL_REFERENCE_CHAR, paint); + final float labelCharWidth = TypefaceUtils.getCharWidth( + KEY_LABEL_REFERENCE_CHAR, paint); // Vertical label text alignment. final float baseline = centerY + labelCharHeight / 2.0f; @@ -386,12 +391,12 @@ public class KeyboardView extends View { positionX = centerX - labelCharWidth * 7.0f / 4.0f; paint.setTextAlign(Align.LEFT); } else if (key.hasLabelWithIconLeft() && icon != null) { - labelWidth = TypefaceUtils.getStringWidth(label, paint) + icon.getIntrinsicWidth() + labelWidth = TypefaceUtils.getLabelWidth(label, paint) + icon.getIntrinsicWidth() + LABEL_ICON_MARGIN * keyWidth; positionX = centerX + labelWidth / 2.0f; paint.setTextAlign(Align.RIGHT); } else if (key.hasLabelWithIconRight() && icon != null) { - labelWidth = TypefaceUtils.getStringWidth(label, paint) + icon.getIntrinsicWidth() + labelWidth = TypefaceUtils.getLabelWidth(label, paint) + icon.getIntrinsicWidth() + LABEL_ICON_MARGIN * keyWidth; positionX = centerX - labelWidth / 2.0f; paint.setTextAlign(Align.LEFT); @@ -399,15 +404,9 @@ public class KeyboardView extends View { positionX = centerX; paint.setTextAlign(Align.CENTER); } - if (key.needsAutoXScale()) { - final float ratio = Math.min(1.0f, (keyWidth * MAX_LABEL_RATIO) / - TypefaceUtils.getStringWidth(label, paint)); - if (key.needsAutoScale()) { - final float autoSize = paint.getTextSize() * ratio; - paint.setTextSize(autoSize); - } else { - paint.setTextScaleX(ratio); - } + if (key.needsXScale()) { + paint.setTextScaleX(Math.min(1.0f, + (keyWidth * MAX_LABEL_RATIO) / TypefaceUtils.getLabelWidth(label, paint))); } paint.setColor(key.selectTextColor(params)); @@ -452,35 +451,36 @@ public class KeyboardView extends View { // TODO: Should add a way to specify type face for hint letters paint.setTypeface(Typeface.DEFAULT_BOLD); blendAlpha(paint, params.mAnimAlpha); - final float labelCharHeight = TypefaceUtils.getReferenceCharHeight(paint); - final float labelCharWidth = TypefaceUtils.getReferenceCharWidth(paint); - final KeyVisualAttributes visualAttr = key.getVisualAttributes(); - final float adjustmentY = (visualAttr == null) ? 0.0f - : visualAttr.mHintLabelVerticalAdjustment * labelCharHeight; final float hintX, hintY; if (key.hasHintLabel()) { // The hint label is placed just right of the key label. Used mainly on // "phone number" layout. // TODO: Generalize the following calculations. - hintX = positionX + labelCharWidth * 2.0f; - hintY = centerY + labelCharHeight / 2.0f; + hintX = positionX + + TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) * 2.0f; + hintY = centerY + + TypefaceUtils.getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f; paint.setTextAlign(Align.LEFT); } else if (key.hasShiftedLetterHint()) { // The hint label is placed at top-right corner of the key. Used mainly on tablet. - hintX = keyWidth - mKeyShiftedLetterHintPadding - labelCharWidth / 2.0f; + hintX = keyWidth - mKeyShiftedLetterHintPadding + - TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f; paint.getFontMetrics(mFontMetrics); hintY = -mFontMetrics.top; paint.setTextAlign(Align.CENTER); } else { // key.hasHintLetter() // The hint letter is placed at top-right corner of the key. Used mainly on phone. - final float hintDigitWidth = TypefaceUtils.getReferenceDigitWidth(paint); - final float hintLabelWidth = TypefaceUtils.getStringWidth(hintLabel, paint); + final float keyNumericHintLabelReferenceCharWidth = + TypefaceUtils.getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint); + final float keyHintLabelStringWidth = + TypefaceUtils.getStringWidth(hintLabel, paint); hintX = keyWidth - mKeyHintLetterPadding - - Math.max(hintDigitWidth, hintLabelWidth) / 2.0f; + - Math.max(keyNumericHintLabelReferenceCharWidth, keyHintLabelStringWidth) + / 2.0f; hintY = -paint.ascent(); paint.setTextAlign(Align.CENTER); } - canvas.drawText(hintLabel, 0, hintLabel.length(), hintX, hintY + adjustmentY, paint); + canvas.drawText(hintLabel, 0, hintLabel.length(), hintX, hintY, paint); if (LatinImeLogger.sVISUALDEBUG) { final Paint line = new Paint(); @@ -530,7 +530,7 @@ public class KeyboardView extends View { paint.setColor(params.mHintLabelColor); paint.setTextAlign(Align.CENTER); final float hintX = keyWidth - mKeyHintLetterPadding - - TypefaceUtils.getReferenceCharWidth(paint) / 2.0f; + - TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f; final float hintY = keyHeight - mKeyPopupHintLetterPadding; canvas.drawText(POPUP_HINT_CHAR, hintX, hintY, paint); diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index 1400e05c8..13db47004 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -16,10 +16,7 @@ package com.android.inputmethod.keyboard; -import android.animation.Animator; import android.animation.AnimatorInflater; -import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; import android.content.SharedPreferences; @@ -31,24 +28,27 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.os.Message; +import android.os.SystemClock; import android.preference.PreferenceManager; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; +import android.util.SparseArray; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; -import android.view.animation.AccelerateInterpolator; -import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.InputMethodSubtype; import android.widget.TextView; import com.android.inputmethod.accessibility.AccessibilityUtils; import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; import com.android.inputmethod.annotations.ExternallyReferenced; -import com.android.inputmethod.keyboard.internal.DrawingHandler; +import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; +import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; import com.android.inputmethod.keyboard.internal.GestureFloatingPreviewText; import com.android.inputmethod.keyboard.internal.GestureTrailsPreview; import com.android.inputmethod.keyboard.internal.KeyDrawParams; @@ -56,7 +56,6 @@ import com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams; import com.android.inputmethod.keyboard.internal.NonDistinctMultitouchHelper; import com.android.inputmethod.keyboard.internal.PreviewPlacerView; import com.android.inputmethod.keyboard.internal.SlidingKeyInputPreview; -import com.android.inputmethod.keyboard.internal.TimerHandler; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; @@ -65,15 +64,13 @@ import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.latin.settings.DebugSettings; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.CoordinateUtils; +import com.android.inputmethod.latin.utils.StaticInnerHandlerWrapper; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; import com.android.inputmethod.latin.utils.TypefaceUtils; import com.android.inputmethod.latin.utils.UsabilityStudyLogUtils; import com.android.inputmethod.latin.utils.ViewLayoutUtils; import com.android.inputmethod.research.ResearchLogger; -import java.util.ArrayDeque; -import java.util.HashMap; -import java.util.HashSet; import java.util.WeakHashMap; /** @@ -81,10 +78,9 @@ import java.util.WeakHashMap; * * @attr ref R.styleable#MainKeyboardView_autoCorrectionSpacebarLedEnabled * @attr ref R.styleable#MainKeyboardView_autoCorrectionSpacebarLedIcon - * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextRatio - * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextColor - * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextShadowColor - * @attr ref R.styleable#MainKeyboardView_spacebarBackground + * @attr ref R.styleable#MainKeyboardView_spacebarTextRatio + * @attr ref R.styleable#MainKeyboardView_spacebarTextColor + * @attr ref R.styleable#MainKeyboardView_spacebarTextShadowColor * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarFinalAlpha * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarFadeoutAnimator * @attr ref R.styleable#MainKeyboardView_altCodeKeyWhileTypingFadeoutAnimator @@ -92,7 +88,7 @@ import java.util.WeakHashMap; * @attr ref R.styleable#MainKeyboardView_keyHysteresisDistance * @attr ref R.styleable#MainKeyboardView_touchNoiseThresholdTime * @attr ref R.styleable#MainKeyboardView_touchNoiseThresholdDistance - * @attr ref R.styleable#MainKeyboardView_keySelectionByDraggingFinger + * @attr ref R.styleable#MainKeyboardView_slidingKeyInputEnable * @attr ref R.styleable#MainKeyboardView_keyRepeatStartTimeout * @attr ref R.styleable#MainKeyboardView_keyRepeatInterval * @attr ref R.styleable#MainKeyboardView_longPressKeyTimeout @@ -118,27 +114,26 @@ import java.util.WeakHashMap; * @attr ref R.styleable#MainKeyboardView_gestureRecognitionSpeedThreshold * @attr ref R.styleable#MainKeyboardView_suppressKeyPreviewAfterBatchInputDuration */ -public final class MainKeyboardView extends KeyboardView implements PointerTracker.DrawingProxy, - MoreKeysPanel.Controller, DrawingHandler.Callbacks, TimerHandler.Callbacks { +public final class MainKeyboardView extends KeyboardView implements PointerTracker.KeyEventHandler, + PointerTracker.DrawingProxy, MoreKeysPanel.Controller { private static final String TAG = MainKeyboardView.class.getSimpleName(); /** Listener for {@link KeyboardActionListener}. */ private KeyboardActionListener mKeyboardActionListener; - /* Space key and its icon and background. */ + /* Space key and its icons */ private Key mSpaceKey; - private Drawable mSpacebarIcon; - private final Drawable mSpacebarBackground; + private Drawable mSpaceIcon; // Stuff to draw language name on spacebar. private final int mLanguageOnSpacebarFinalAlpha; private ObjectAnimator mLanguageOnSpacebarFadeoutAnimator; private boolean mNeedsToDisplayLanguage; private boolean mHasMultipleEnabledIMEsOrSubtypes; private int mLanguageOnSpacebarAnimAlpha = Constants.Color.ALPHA_OPAQUE; - private final float mLanguageOnSpacebarTextRatio; - private float mLanguageOnSpacebarTextSize; - private final int mLanguageOnSpacebarTextColor; - private final int mLanguageOnSpacebarTextShadowColor; + private final float mSpacebarTextRatio; + private float mSpacebarTextSize; + private final int mSpacebarTextColor; + private final int mSpacebarTextShadowColor; // The minimum x-scale to fit the language name on spacebar. private static final float MINIMUM_XSCALE_OF_LANGUAGE_NAME = 0.8f; // Stuff to draw auto correction LED on spacebar. @@ -148,8 +143,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack private static final int SPACE_LED_LENGTH_PERCENT = 80; // Stuff to draw altCodeWhileTyping keys. - private final ObjectAnimator mAltCodeKeyWhileTypingFadeoutAnimator; - private final ObjectAnimator mAltCodeKeyWhileTypingFadeinAnimator; + private ObjectAnimator mAltCodeKeyWhileTypingFadeoutAnimator; + private ObjectAnimator mAltCodeKeyWhileTypingFadeinAnimator; private int mAltCodeKeyWhileTypingAnimAlpha = Constants.Color.ALPHA_OPAQUE; // Preview placer view @@ -160,26 +155,13 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack private final SlidingKeyInputPreview mSlidingKeyInputPreview; // Key preview - private static final boolean FADE_OUT_KEY_TOP_LETTER_WHEN_KEY_IS_PRESSED = false; private final int mKeyPreviewLayoutId; private final int mKeyPreviewOffset; private final int mKeyPreviewHeight; - // Free {@link TextView} pool that can be used for key preview. - private final ArrayDeque<TextView> mFreeKeyPreviewTextViews = CollectionUtils.newArrayDeque(); - // Map from {@link Key} to {@link TextView} that is currently being displayed as key preview. - private final HashMap<Key,TextView> mShowingKeyPreviewTextViews = CollectionUtils.newHashMap(); + private final SparseArray<TextView> mKeyPreviewTexts = CollectionUtils.newSparseArray(); private final KeyPreviewDrawParams mKeyPreviewDrawParams = new KeyPreviewDrawParams(); private boolean mShowKeyPreviewPopup = true; private int mKeyPreviewLingerTimeout; - private int mKeyPreviewZoomInDuration; - private int mKeyPreviewZoomOutDuration; - private static final float KEY_PREVIEW_START_ZOOM_IN_SCALE = 0.7f; - private static final float KEY_PREVIEW_END_ZOOM_IN_SCALE = 1.0f; - private static final float KEY_PREVIEW_END_ZOOM_OUT_SCALE = 0.7f; - private static final AccelerateInterpolator ACCELERATE_INTERPOLATOR = - new AccelerateInterpolator(); - private static final DecelerateInterpolator DECELERATE_INTERPOLATOR = - new DecelerateInterpolator(); // More keys keyboard private final Paint mBackgroundDimAlphaPaint = new Paint(); @@ -196,43 +178,253 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack // TODO: Make this parameter customizable by user via settings. private int mGestureFloatingPreviewTextLingerTimeout; - private final KeyDetector mKeyDetector; + private KeyDetector mKeyDetector; private final NonDistinctMultitouchHelper mNonDistinctMultitouchHelper; - private final TimerHandler mKeyTimerHandler; + private final KeyTimerHandler mKeyTimerHandler; private final int mLanguageOnSpacebarHorizontalMargin; - private final DrawingHandler mDrawingHandler = - new DrawingHandler(this); + private static final class KeyTimerHandler extends StaticInnerHandlerWrapper<MainKeyboardView> + implements TimerProxy { + private static final int MSG_TYPING_STATE_EXPIRED = 0; + private static final int MSG_REPEAT_KEY = 1; + private static final int MSG_LONGPRESS_KEY = 2; + private static final int MSG_DOUBLE_TAP_SHIFT_KEY = 3; + private static final int MSG_UPDATE_BATCH_INPUT = 4; - public MainKeyboardView(final Context context, final AttributeSet attrs) { - this(context, attrs, R.attr.mainKeyboardViewStyle); + private final int mIgnoreAltCodeKeyTimeout; + private final int mGestureRecognitionUpdateTime; + + public KeyTimerHandler(final MainKeyboardView outerInstance, + final TypedArray mainKeyboardViewAttr) { + super(outerInstance); + + mIgnoreAltCodeKeyTimeout = mainKeyboardViewAttr.getInt( + R.styleable.MainKeyboardView_ignoreAltCodeKeyTimeout, 0); + mGestureRecognitionUpdateTime = mainKeyboardViewAttr.getInt( + R.styleable.MainKeyboardView_gestureRecognitionUpdateTime, 0); + } + + @Override + public void handleMessage(final Message msg) { + final MainKeyboardView keyboardView = getOuterInstance(); + if (keyboardView == null) { + return; + } + final PointerTracker tracker = (PointerTracker) msg.obj; + switch (msg.what) { + case MSG_TYPING_STATE_EXPIRED: + startWhileTypingFadeinAnimation(keyboardView); + break; + case MSG_REPEAT_KEY: + tracker.onKeyRepeat(msg.arg1 /* code */, msg.arg2 /* repeatCount */); + break; + case MSG_LONGPRESS_KEY: + keyboardView.onLongPress(tracker); + break; + case MSG_UPDATE_BATCH_INPUT: + tracker.updateBatchInputByTimer(SystemClock.uptimeMillis()); + startUpdateBatchInputTimer(tracker); + break; + } + } + + @Override + public void startKeyRepeatTimer(final PointerTracker tracker, final int repeatCount, + final int delay) { + final Key key = tracker.getKey(); + if (key == null || delay == 0) { + return; + } + sendMessageDelayed( + obtainMessage(MSG_REPEAT_KEY, key.getCode(), repeatCount, tracker), delay); + } + + public void cancelKeyRepeatTimer() { + removeMessages(MSG_REPEAT_KEY); + } + + // TODO: Suppress layout changes in key repeat mode + public boolean isInKeyRepeat() { + return hasMessages(MSG_REPEAT_KEY); + } + + @Override + public void startLongPressTimer(final PointerTracker tracker, final int delay) { + cancelLongPressTimer(); + if (delay <= 0) return; + sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, tracker), delay); + } + + @Override + public void cancelLongPressTimer() { + removeMessages(MSG_LONGPRESS_KEY); + } + + private static void cancelAndStartAnimators(final ObjectAnimator animatorToCancel, + final ObjectAnimator animatorToStart) { + if (animatorToCancel == null || animatorToStart == null) { + // TODO: Stop using null as a no-operation animator. + return; + } + float startFraction = 0.0f; + if (animatorToCancel.isStarted()) { + animatorToCancel.cancel(); + startFraction = 1.0f - animatorToCancel.getAnimatedFraction(); + } + final long startTime = (long)(animatorToStart.getDuration() * startFraction); + animatorToStart.start(); + animatorToStart.setCurrentPlayTime(startTime); + } + + private static void startWhileTypingFadeinAnimation(final MainKeyboardView keyboardView) { + cancelAndStartAnimators(keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator, + keyboardView.mAltCodeKeyWhileTypingFadeinAnimator); + } + + private static void startWhileTypingFadeoutAnimation(final MainKeyboardView keyboardView) { + cancelAndStartAnimators(keyboardView.mAltCodeKeyWhileTypingFadeinAnimator, + keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator); + } + + @Override + public void startTypingStateTimer(final Key typedKey) { + if (typedKey.isModifier() || typedKey.altCodeWhileTyping()) { + return; + } + + final boolean isTyping = isTypingState(); + removeMessages(MSG_TYPING_STATE_EXPIRED); + final MainKeyboardView keyboardView = getOuterInstance(); + + // When user hits the space or the enter key, just cancel the while-typing timer. + final int typedCode = typedKey.getCode(); + if (typedCode == Constants.CODE_SPACE || typedCode == Constants.CODE_ENTER) { + if (isTyping) { + startWhileTypingFadeinAnimation(keyboardView); + } + return; + } + + sendMessageDelayed( + obtainMessage(MSG_TYPING_STATE_EXPIRED), mIgnoreAltCodeKeyTimeout); + if (isTyping) { + return; + } + startWhileTypingFadeoutAnimation(keyboardView); + } + + @Override + public boolean isTypingState() { + return hasMessages(MSG_TYPING_STATE_EXPIRED); + } + + @Override + public void startDoubleTapShiftKeyTimer() { + sendMessageDelayed(obtainMessage(MSG_DOUBLE_TAP_SHIFT_KEY), + ViewConfiguration.getDoubleTapTimeout()); + } + + @Override + public void cancelDoubleTapShiftKeyTimer() { + removeMessages(MSG_DOUBLE_TAP_SHIFT_KEY); + } + + @Override + public boolean isInDoubleTapShiftKeyTimeout() { + return hasMessages(MSG_DOUBLE_TAP_SHIFT_KEY); + } + + @Override + public void cancelKeyTimers() { + cancelKeyRepeatTimer(); + cancelLongPressTimer(); + } + + @Override + public void startUpdateBatchInputTimer(final PointerTracker tracker) { + if (mGestureRecognitionUpdateTime <= 0) { + return; + } + removeMessages(MSG_UPDATE_BATCH_INPUT, tracker); + sendMessageDelayed(obtainMessage(MSG_UPDATE_BATCH_INPUT, tracker), + mGestureRecognitionUpdateTime); + } + + @Override + public void cancelUpdateBatchInputTimer(final PointerTracker tracker) { + removeMessages(MSG_UPDATE_BATCH_INPUT, tracker); + } + + @Override + public void cancelAllUpdateBatchInputTimers() { + removeMessages(MSG_UPDATE_BATCH_INPUT); + } + + public void cancelAllMessages() { + cancelKeyTimers(); + cancelAllUpdateBatchInputTimers(); + } } - public MainKeyboardView(final Context context, final AttributeSet attrs, final int defStyle) { - super(context, attrs, defStyle); + private final DrawingHandler mDrawingHandler = new DrawingHandler(this); - mPreviewPlacerView = new PreviewPlacerView(context, attrs); + public static class DrawingHandler extends StaticInnerHandlerWrapper<MainKeyboardView> { + private static final int MSG_DISMISS_KEY_PREVIEW = 0; + private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1; - final TypedArray mainKeyboardViewAttr = context.obtainStyledAttributes( - attrs, R.styleable.MainKeyboardView, defStyle, R.style.MainKeyboardView); - final int ignoreAltCodeKeyTimeout = mainKeyboardViewAttr.getInt( - R.styleable.MainKeyboardView_ignoreAltCodeKeyTimeout, 0); - final int gestureRecognitionUpdateTime = mainKeyboardViewAttr.getInt( - R.styleable.MainKeyboardView_gestureRecognitionUpdateTime, 0); - mKeyTimerHandler = new TimerHandler( - this, ignoreAltCodeKeyTimeout, gestureRecognitionUpdateTime); + public DrawingHandler(final MainKeyboardView outerInstance) { + super(outerInstance); + } - final float keyHysteresisDistance = mainKeyboardViewAttr.getDimension( - R.styleable.MainKeyboardView_keyHysteresisDistance, 0.0f); - final float keyHysteresisDistanceForSlidingModifier = mainKeyboardViewAttr.getDimension( - R.styleable.MainKeyboardView_keyHysteresisDistanceForSlidingModifier, 0.0f); - mKeyDetector = new KeyDetector( - keyHysteresisDistance, keyHysteresisDistanceForSlidingModifier); + @Override + public void handleMessage(final Message msg) { + final MainKeyboardView mainKeyboardView = getOuterInstance(); + if (mainKeyboardView == null) return; + final PointerTracker tracker = (PointerTracker) msg.obj; + switch (msg.what) { + case MSG_DISMISS_KEY_PREVIEW: + final TextView previewText = mainKeyboardView.mKeyPreviewTexts.get( + tracker.mPointerId); + if (previewText != null) { + previewText.setVisibility(INVISIBLE); + } + break; + case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT: + mainKeyboardView.showGestureFloatingPreviewText(SuggestedWords.EMPTY); + break; + } + } + + public void dismissKeyPreview(final long delay, final PointerTracker tracker) { + sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, tracker), delay); + } - PointerTracker.init(mainKeyboardViewAttr, mKeyTimerHandler, this /* DrawingProxy */, - mKeyDetector); + public void cancelDismissKeyPreview(final PointerTracker tracker) { + removeMessages(MSG_DISMISS_KEY_PREVIEW, tracker); + } + + private void cancelAllDismissKeyPreviews() { + removeMessages(MSG_DISMISS_KEY_PREVIEW); + } + public void dismissGestureFloatingPreviewText(final long delay) { + sendMessageDelayed(obtainMessage(MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT), delay); + } + + public void cancelAllMessages() { + cancelAllDismissKeyPreviews(); + } + } + + public MainKeyboardView(final Context context, final AttributeSet attrs) { + this(context, attrs, R.attr.mainKeyboardViewStyle); + } + + public MainKeyboardView(final Context context, final AttributeSet attrs, final int defStyle) { + super(context, attrs, defStyle); + + PointerTracker.init(getResources()); final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); final boolean forceNonDistinctMultitouch = prefs.getBoolean( DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH, false); @@ -240,24 +432,26 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT) && !forceNonDistinctMultitouch; mNonDistinctMultitouchHelper = hasDistinctMultitouch ? null - : new NonDistinctMultitouchHelper(PointerTracker.getPointerTracker(0)); + : new NonDistinctMultitouchHelper(); + + mPreviewPlacerView = new PreviewPlacerView(context, attrs); + final TypedArray mainKeyboardViewAttr = context.obtainStyledAttributes( + attrs, R.styleable.MainKeyboardView, defStyle, R.style.MainKeyboardView); final int backgroundDimAlpha = mainKeyboardViewAttr.getInt( R.styleable.MainKeyboardView_backgroundDimAlpha, 0); mBackgroundDimAlphaPaint.setColor(Color.BLACK); mBackgroundDimAlphaPaint.setAlpha(backgroundDimAlpha); - mSpacebarBackground = mainKeyboardViewAttr.getDrawable( - R.styleable.MainKeyboardView_spacebarBackground); mAutoCorrectionSpacebarLedEnabled = mainKeyboardViewAttr.getBoolean( R.styleable.MainKeyboardView_autoCorrectionSpacebarLedEnabled, false); mAutoCorrectionSpacebarLedIcon = mainKeyboardViewAttr.getDrawable( R.styleable.MainKeyboardView_autoCorrectionSpacebarLedIcon); - mLanguageOnSpacebarTextRatio = mainKeyboardViewAttr.getFraction( - R.styleable.MainKeyboardView_languageOnSpacebarTextRatio, 1, 1, 1.0f); - mLanguageOnSpacebarTextColor = mainKeyboardViewAttr.getColor( - R.styleable.MainKeyboardView_languageOnSpacebarTextColor, 0); - mLanguageOnSpacebarTextShadowColor = mainKeyboardViewAttr.getColor( - R.styleable.MainKeyboardView_languageOnSpacebarTextShadowColor, 0); + mSpacebarTextRatio = mainKeyboardViewAttr.getFraction( + R.styleable.MainKeyboardView_spacebarTextRatio, 1, 1, 1.0f); + mSpacebarTextColor = mainKeyboardViewAttr.getColor( + R.styleable.MainKeyboardView_spacebarTextColor, 0); + mSpacebarTextShadowColor = mainKeyboardViewAttr.getColor( + R.styleable.MainKeyboardView_spacebarTextShadowColor, 0); mLanguageOnSpacebarFinalAlpha = mainKeyboardViewAttr.getInt( R.styleable.MainKeyboardView_languageOnSpacebarFinalAlpha, Constants.Color.ALPHA_OPAQUE); @@ -268,6 +462,13 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack final int altCodeKeyWhileTypingFadeinAnimatorResId = mainKeyboardViewAttr.getResourceId( R.styleable.MainKeyboardView_altCodeKeyWhileTypingFadeinAnimator, 0); + final float keyHysteresisDistance = mainKeyboardViewAttr.getDimension( + R.styleable.MainKeyboardView_keyHysteresisDistance, 0.0f); + final float keyHysteresisDistanceForSlidingModifier = mainKeyboardViewAttr.getDimension( + R.styleable.MainKeyboardView_keyHysteresisDistanceForSlidingModifier, 0.0f); + mKeyDetector = new KeyDetector( + keyHysteresisDistance, keyHysteresisDistanceForSlidingModifier); + mKeyTimerHandler = new KeyTimerHandler(this, mainKeyboardViewAttr); mKeyPreviewOffset = mainKeyboardViewAttr.getDimensionPixelOffset( R.styleable.MainKeyboardView_keyPreviewOffset, 0); mKeyPreviewHeight = mainKeyboardViewAttr.getDimensionPixelSize( @@ -279,10 +480,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack if (mKeyPreviewLayoutId == 0) { mShowKeyPreviewPopup = false; } - mKeyPreviewZoomInDuration = mainKeyboardViewAttr.getInt( - R.styleable.MainKeyboardView_keyPreviewZoomInDuration, 0); - mKeyPreviewZoomOutDuration = mainKeyboardViewAttr.getInt( - R.styleable.MainKeyboardView_keyPreviewZoomOutDuration, 0); final int moreKeysKeyboardLayoutId = mainKeyboardViewAttr.getResourceId( R.styleable.MainKeyboardView_moreKeysKeyboardLayout, 0); mConfigShowMoreKeysKeyboardAtTouchedPoint = mainKeyboardViewAttr.getBoolean( @@ -290,6 +487,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mGestureFloatingPreviewTextLingerTimeout = mainKeyboardViewAttr.getInt( R.styleable.MainKeyboardView_gestureFloatingPreviewTextLingerTimeout, 0); + PointerTracker.setParameters(mainKeyboardViewAttr); mGestureFloatingPreviewText = new GestureFloatingPreviewText( mPreviewPlacerView, mainKeyboardViewAttr); @@ -315,8 +513,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER; - mLanguageOnSpacebarHorizontalMargin = (int)getResources().getDimension( - R.dimen.config_language_on_spacebar_horizontal_margin); + mLanguageOnSpacebarHorizontalMargin = + (int) getResources().getDimension(R.dimen.language_on_spacebar_horizontal_margin); } @Override @@ -338,35 +536,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack return animator; } - private static void cancelAndStartAnimators(final ObjectAnimator animatorToCancel, - final ObjectAnimator animatorToStart) { - if (animatorToCancel == null || animatorToStart == null) { - // TODO: Stop using null as a no-operation animator. - return; - } - float startFraction = 0.0f; - if (animatorToCancel.isStarted()) { - animatorToCancel.cancel(); - startFraction = 1.0f - animatorToCancel.getAnimatedFraction(); - } - final long startTime = (long)(animatorToStart.getDuration() * startFraction); - animatorToStart.start(); - animatorToStart.setCurrentPlayTime(startTime); - } - - // Implements {@link TimerHander.Callbacks} method. - @Override - public void startWhileTypingFadeinAnimation() { - cancelAndStartAnimators( - mAltCodeKeyWhileTypingFadeoutAnimator, mAltCodeKeyWhileTypingFadeinAnimator); - } - - @Override - public void startWhileTypingFadeoutAnimation() { - cancelAndStartAnimators( - mAltCodeKeyWhileTypingFadeinAnimator, mAltCodeKeyWhileTypingFadeoutAnimator); - } - @ExternallyReferenced public int getLanguageOnSpacebarAnimAlpha() { return mLanguageOnSpacebarAnimAlpha; @@ -404,16 +573,28 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack PointerTracker.setKeyboardActionListener(listener); } - // TODO: We should reconsider which coordinate system should be used to represent keyboard - // event. - public int getKeyX(final int x) { - return Constants.isValidCoordinate(x) ? mKeyDetector.getTouchX(x) : x; + /** + * Returns the {@link KeyboardActionListener} object. + * @return the listener attached to this keyboard + */ + @Override + public KeyboardActionListener getKeyboardActionListener() { + return mKeyboardActionListener; } - // TODO: We should reconsider which coordinate system should be used to represent keyboard - // event. - public int getKeyY(final int y) { - return Constants.isValidCoordinate(y) ? mKeyDetector.getTouchY(y) : y; + @Override + public KeyDetector getKeyDetector() { + return mKeyDetector; + } + + @Override + public DrawingProxy getDrawingProxy() { + return this; + } + + @Override + public TimerProxy getTimerProxy() { + return mKeyTimerHandler; } /** @@ -425,20 +606,19 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack */ @Override public void setKeyboard(final Keyboard keyboard) { - // Remove any pending messages. - mKeyTimerHandler.cancelAllKeyTimers(); + // Remove any pending messages, except dismissing preview and key repeat. + mKeyTimerHandler.cancelLongPressTimer(); super.setKeyboard(keyboard); mKeyDetector.setKeyboard( keyboard, -getPaddingLeft(), -getPaddingTop() + getVerticalCorrection()); PointerTracker.setKeyDetector(mKeyDetector); - PointerTracker.setKeyboardActionListener(mKeyboardActionListener); mMoreKeysKeyboardCache.clear(); mSpaceKey = keyboard.getKey(Constants.CODE_SPACE); - mSpacebarIcon = (mSpaceKey != null) + mSpaceIcon = (mSpaceKey != null) ? mSpaceKey.getIcon(keyboard.mIconsSet, Constants.Color.ALPHA_OPAQUE) : null; final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap; - mLanguageOnSpacebarTextSize = keyHeight * mLanguageOnSpacebarTextRatio; + mSpacebarTextSize = keyHeight * mSpacebarTextRatio; if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { final int orientation = getContext().getResources().getConfiguration().orientation; ResearchLogger.mainKeyboardView_setKeyboard(keyboard, orientation); @@ -501,33 +681,34 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack return mShowKeyPreviewPopup; } - private TextView getKeyPreviewTextView(final Key key) { - TextView previewTextView = mShowingKeyPreviewTextViews.remove(key); - if (previewTextView != null) { - return previewTextView; - } - previewTextView = mFreeKeyPreviewTextViews.poll(); - if (previewTextView != null) { - return previewTextView; + private void addKeyPreview(final TextView keyPreview) { + locatePreviewPlacerView(); + mPreviewPlacerView.addView( + keyPreview, ViewLayoutUtils.newLayoutParam(mPreviewPlacerView, 0, 0)); + } + + private TextView getKeyPreviewText(final int pointerId) { + TextView previewText = mKeyPreviewTexts.get(pointerId); + if (previewText != null) { + return previewText; } final Context context = getContext(); if (mKeyPreviewLayoutId != 0) { - previewTextView = (TextView)LayoutInflater.from(context) - .inflate(mKeyPreviewLayoutId, null); + previewText = (TextView)LayoutInflater.from(context).inflate(mKeyPreviewLayoutId, null); } else { - previewTextView = new TextView(context); + previewText = new TextView(context); } - locatePreviewPlacerView(); - mPreviewPlacerView.addView( - previewTextView, ViewLayoutUtils.newLayoutParam(mPreviewPlacerView, 0, 0)); - return previewTextView; + mKeyPreviewTexts.put(pointerId, previewText); + return previewText; } - // Implements {@link DrawingHandler.Callbacks} method. - @Override - public void dismissAllKeyPreviews() { - for (final Key key : new HashSet<Key>(mShowingKeyPreviewTextViews.keySet())) { - dismissKeyPreviewWithoutDelay(key); + private void dismissAllKeyPreviews() { + final int pointerCount = mKeyPreviewTexts.size(); + for (int id = 0; id < pointerCount; id++) { + final TextView previewText = mKeyPreviewTexts.get(id); + if (previewText != null) { + previewText.setVisibility(INVISIBLE); + } } PointerTracker.setReleasedKeyGraphicsToAllKeys(); } @@ -553,16 +734,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack private static final int STATE_NORMAL = 0; private static final int STATE_HAS_MOREKEYS = 1; - // TODO: Take this method out of this class. @Override - public void showKeyPreview(final Key key) { - // If key is invalid or IME is already closed, we must not show key preview. - // Trying to show key preview while root window is closed causes - // WindowManager.BadTokenException. - if (key == null) { - return; - } - + public void showKeyPreview(final PointerTracker tracker) { final KeyPreviewDrawParams previewParams = mKeyPreviewDrawParams; final Keyboard keyboard = getKeyboard(); if (!mShowKeyPreviewPopup) { @@ -570,40 +743,54 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack return; } - final TextView previewTextView = getKeyPreviewTextView(key); + final TextView previewText = getKeyPreviewText(tracker.mPointerId); + // If the key preview has no parent view yet, add it to the ViewGroup which can place + // key preview absolutely in SoftInputWindow. + if (previewText.getParent() == null) { + addKeyPreview(previewText); + } + + mDrawingHandler.cancelDismissKeyPreview(tracker); + final Key key = tracker.getKey(); + // If key is invalid or IME is already closed, we must not show key preview. + // Trying to show key preview while root window is closed causes + // WindowManager.BadTokenException. + if (key == null) { + return; + } + final KeyDrawParams drawParams = mKeyDrawParams; - previewTextView.setTextColor(drawParams.mPreviewTextColor); - final Drawable background = previewTextView.getBackground(); + previewText.setTextColor(drawParams.mPreviewTextColor); + final Drawable background = previewText.getBackground(); final String label = key.getPreviewLabel(); // What we show as preview should match what we show on a key top in onDraw(). if (label != null) { // TODO Should take care of temporaryShiftLabel here. - previewTextView.setCompoundDrawables(null, null, null, null); - previewTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, + previewText.setCompoundDrawables(null, null, null, null); + previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, key.selectPreviewTextSize(drawParams)); - previewTextView.setTypeface(key.selectPreviewTypeface(drawParams)); - previewTextView.setText(label); + previewText.setTypeface(key.selectPreviewTypeface(drawParams)); + previewText.setText(label); } else { - previewTextView.setCompoundDrawables(null, null, null, + previewText.setCompoundDrawables(null, null, null, key.getPreviewIcon(keyboard.mIconsSet)); - previewTextView.setText(null); + previewText.setText(null); } - previewTextView.measure( + previewText.measure( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); final int keyDrawWidth = key.getDrawWidth(); - final int previewWidth = previewTextView.getMeasuredWidth(); + final int previewWidth = previewText.getMeasuredWidth(); final int previewHeight = mKeyPreviewHeight; // The width and height of visible part of the key preview background. The content marker // of the background 9-patch have to cover the visible part of the background. - previewParams.mPreviewVisibleWidth = previewWidth - previewTextView.getPaddingLeft() - - previewTextView.getPaddingRight(); - previewParams.mPreviewVisibleHeight = previewHeight - previewTextView.getPaddingTop() - - previewTextView.getPaddingBottom(); + previewParams.mPreviewVisibleWidth = previewWidth - previewText.getPaddingLeft() + - previewText.getPaddingRight(); + previewParams.mPreviewVisibleHeight = previewHeight - previewText.getPaddingTop() + - previewText.getPaddingBottom(); // The distance between the top edge of the parent key and the bottom of the visible part // of the key preview background. - previewParams.mPreviewVisibleOffset = - mKeyPreviewOffset - previewTextView.getPaddingBottom(); + previewParams.mPreviewVisibleOffset = mKeyPreviewOffset - previewText.getPaddingBottom(); getLocationInWindow(mOriginCoords); // The key preview is horizontally aligned with the center of the visible part of the // parent key. If it doesn't fit in this {@link KeyboardView}, it is moved inward to fit and @@ -630,132 +817,13 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack background.setState(KEY_PREVIEW_BACKGROUND_STATE_TABLE[statePosition][hasMoreKeys]); } ViewLayoutUtils.placeViewAt( - previewTextView, previewX, previewY, previewWidth, previewHeight); - - if (!isHardwareAccelerated()) { - previewTextView.setVisibility(VISIBLE); - mShowingKeyPreviewTextViews.put(key, previewTextView); - return; - } - previewTextView.setPivotX(previewWidth / 2.0f); - previewTextView.setPivotY(previewHeight); - - final Animator zoomIn = createZoomInAniation(key, previewTextView); - final Animator zoomOut = createZoomOutAnimation(key, previewTextView); - final KeyPreviewAnimations animation = new KeyPreviewAnimations(zoomIn, zoomOut); - previewTextView.setTag(animation); - animation.startZoomIn(); + previewText, previewX, previewY, previewWidth, previewHeight); + previewText.setVisibility(VISIBLE); } - // TODO: Move this internal class out to a separate external class. - private static class KeyPreviewAnimations extends AnimatorListenerAdapter { - private final Animator mZoomIn; - private final Animator mZoomOut; - - public KeyPreviewAnimations(final Animator zoomIn, final Animator zoomOut) { - mZoomIn = zoomIn; - mZoomOut = zoomOut; - } - - public void startZoomIn() { - mZoomIn.start(); - } - - public void startZoomOut() { - if (mZoomIn.isRunning()) { - mZoomIn.addListener(this); - return; - } - mZoomOut.start(); - } - - @Override - public void onAnimationEnd(final Animator animation) { - mZoomOut.start(); - } - } - - // TODO: Take this method out of this class. - private Animator createZoomInAniation(final Key key, final TextView previewTextView) { - final ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat( - previewTextView, SCALE_X, KEY_PREVIEW_START_ZOOM_IN_SCALE, - KEY_PREVIEW_END_ZOOM_IN_SCALE); - final ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat( - previewTextView, SCALE_Y, KEY_PREVIEW_START_ZOOM_IN_SCALE, - KEY_PREVIEW_END_ZOOM_IN_SCALE); - final AnimatorSet zoomInAnimation = new AnimatorSet(); - zoomInAnimation.play(scaleXAnimation).with(scaleYAnimation); - // TODO: Implement preference option to control key preview animation duration. - zoomInAnimation.setDuration(mKeyPreviewZoomInDuration); - zoomInAnimation.setInterpolator(DECELERATE_INTERPOLATOR); - zoomInAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(final Animator animation) { - previewTextView.setVisibility(VISIBLE); - mShowingKeyPreviewTextViews.put(key, previewTextView); - } - }); - return zoomInAnimation; - } - - // TODO: Take this method out of this class. - private Animator createZoomOutAnimation(final Key key, final TextView previewTextView) { - final ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat( - previewTextView, SCALE_X, KEY_PREVIEW_END_ZOOM_OUT_SCALE); - final ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat( - previewTextView, SCALE_Y, KEY_PREVIEW_END_ZOOM_OUT_SCALE); - final AnimatorSet zoomOutAnimation = new AnimatorSet(); - zoomOutAnimation.play(scaleXAnimation).with(scaleYAnimation); - // TODO: Implement preference option to control key preview animation duration. - zoomOutAnimation.setDuration(mKeyPreviewZoomOutDuration); - zoomOutAnimation.setInterpolator(ACCELERATE_INTERPOLATOR); - zoomOutAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(final Animator animation) { - dismissKeyPreviewWithoutDelay(key); - } - }); - return zoomOutAnimation; - } - - // Implements {@link TimerHandler.Callbacks} method. - // TODO: Take this method out of this class. @Override - public void dismissKeyPreviewWithoutDelay(final Key key) { - if (key == null) { - return; - } - final TextView previewTextView = mShowingKeyPreviewTextViews.remove(key); - if (previewTextView != null) { - final Object tag = previewTextView.getTag(); - if (tag instanceof Animator) { - ((Animator)tag).cancel(); - } - previewTextView.setTag(null); - previewTextView.setVisibility(INVISIBLE); - mFreeKeyPreviewTextViews.add(previewTextView); - } - // To redraw key top letter. - invalidateKey(key); - } - - // TODO: Take this method out of this class. - @Override - public void dismissKeyPreview(final Key key) { - final TextView previewTextView = mShowingKeyPreviewTextViews.get(key); - if (previewTextView == null) { - return; - } - if (!isHardwareAccelerated()) { - // TODO: Implement preference option to control key preview method and duration. - mDrawingHandler.dismissKeyPreview(mKeyPreviewLingerTimeout, key); - return; - } - final Object tag = previewTextView.getTag(); - if (tag instanceof KeyPreviewAnimations) { - final KeyPreviewAnimations animation = (KeyPreviewAnimations)tag; - animation.startZoomOut(); - } + public void dismissKeyPreview(final PointerTracker tracker) { + mDrawingHandler.dismissKeyPreview(mKeyPreviewLingerTimeout, tracker); } public void setSlidingKeyInputPreviewEnabled(final boolean enabled) { @@ -779,8 +847,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mGestureTrailsPreview.setPreviewEnabled(isGestureTrailEnabled); } - // Implements {@link DrawingHandler.Callbacks} method. - @Override public void showGestureFloatingPreviewText(final SuggestedWords suggestedWords) { locatePreviewPlacerView(); mGestureFloatingPreviewText.setSuggetedWords(suggestedWords); @@ -856,13 +922,11 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack return moreKeysKeyboardView; } - // Implements {@link TimerHandler.Callbacks} method. /** * Called when a key is long pressed. * @param tracker the pointer tracker which pressed the parent key */ - @Override - public void onLongPress(final PointerTracker tracker) { + private void onLongPress(final PointerTracker tracker) { if (isShowingMoreKeysPanel()) { return; } @@ -918,15 +982,13 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack final int pointY = key.getY() + mKeyPreviewDrawParams.mPreviewVisibleOffset; moreKeysPanel.showMoreKeysPanel(this, this, pointX, pointY, mKeyboardActionListener); tracker.onShowMoreKeysPanel(moreKeysPanel); - // TODO: Implement zoom in animation of more keys panel. - dismissKeyPreviewWithoutDelay(key); } - public boolean isInDraggingFinger() { + public boolean isInSlidingKeyInput() { if (isShowingMoreKeysPanel()) { return true; } - return PointerTracker.isAnyInDraggingFinger(); + return PointerTracker.isAnyInSlidingKeyInput(); } @Override @@ -987,10 +1049,10 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack if (mNonDistinctMultitouchHelper != null) { if (me.getPointerCount() > 1 && mKeyTimerHandler.isInKeyRepeat()) { // Key repeating timer will be canceled if 2 or more keys are in action. - mKeyTimerHandler.cancelKeyRepeatTimers(); + mKeyTimerHandler.cancelKeyRepeatTimer(); } // Non distinct multitouch screen support - mNonDistinctMultitouchHelper.processMotionEvent(me, mKeyDetector); + mNonDistinctMultitouchHelper.processMotionEvent(me, this); return true; } return processMotionEvent(me); @@ -1007,14 +1069,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack final int index = me.getActionIndex(); final int id = me.getPointerId(index); - final PointerTracker tracker = PointerTracker.getPointerTracker(id); - // When a more keys panel is showing, we should ignore other fingers' single touch events - // other than the finger that is showing the more keys panel. - if (isShowingMoreKeysPanel() && !tracker.isShowingMoreKeysPanel() - && PointerTracker.getActivePointerTrackerCount() == 1) { - return true; - } - tracker.processMotionEvent(me, mKeyDetector); + final PointerTracker tracker = PointerTracker.getPointerTracker(id, this); + tracker.processMotionEvent(me, this); return true; } @@ -1043,7 +1099,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack @Override public boolean dispatchHoverEvent(final MotionEvent event) { if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { - final PointerTracker tracker = PointerTracker.getPointerTracker(0); + final PointerTracker tracker = PointerTracker.getPointerTracker(0, this); return AccessibleKeyboardViewProxy.getInstance().dispatchHoverEvent(event, tracker); } @@ -1113,30 +1169,12 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } } - // Draw key background. - @Override - protected void onDrawKeyBackground(final Key key, final Canvas canvas, - final Drawable background) { - if (key.getCode() == Constants.CODE_SPACE) { - super.onDrawKeyBackground(key, canvas, mSpacebarBackground); - return; - } - super.onDrawKeyBackground(key, canvas, background); - } - @Override protected void onDrawKeyTopVisuals(final Key key, final Canvas canvas, final Paint paint, final KeyDrawParams params) { if (key.altCodeWhileTyping() && key.isEnabled()) { params.mAnimAlpha = mAltCodeKeyWhileTypingAnimAlpha; } - // Don't draw key top letter when key preview is showing. - if (FADE_OUT_KEY_TOP_LETTER_WHEN_KEY_IS_PRESSED - && mShowingKeyPreviewTextViews.containsKey(key)) { - // TODO: Fade out animation for the key top letter, and fade in animation for the key - // background color when the user presses the key. - return; - } final int code = key.getCode(); if (code == Constants.CODE_SPACE) { drawSpacebar(key, canvas, paint); @@ -1155,7 +1193,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack private boolean fitsTextIntoWidth(final int width, final String text, final Paint paint) { final int maxTextWidth = width - mLanguageOnSpacebarHorizontalMargin * 2; paint.setTextScaleX(1.0f); - final float textWidth = TypefaceUtils.getStringWidth(text, paint); + final float textWidth = TypefaceUtils.getLabelWidth(text, paint); if (textWidth < width) { return true; } @@ -1166,7 +1204,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } paint.setTextScaleX(scaleX); - return TypefaceUtils.getStringWidth(text, paint) < maxTextWidth; + return TypefaceUtils.getLabelWidth(text, paint) < maxTextWidth; } // Layout language name on spacebar. @@ -1200,17 +1238,17 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack if (mNeedsToDisplayLanguage) { paint.setTextAlign(Align.CENTER); paint.setTypeface(Typeface.DEFAULT); - paint.setTextSize(mLanguageOnSpacebarTextSize); + paint.setTextSize(mSpacebarTextSize); final InputMethodSubtype subtype = getKeyboard().mId.mSubtype; final String language = layoutLanguageOnSpacebar(paint, subtype, width); // Draw language text with shadow final float descent = paint.descent(); final float textHeight = -paint.ascent() + descent; final float baseline = height / 2 + textHeight / 2; - paint.setColor(mLanguageOnSpacebarTextShadowColor); + paint.setColor(mSpacebarTextShadowColor); paint.setAlpha(mLanguageOnSpacebarAnimAlpha); canvas.drawText(language, width / 2, baseline - descent - 1, paint); - paint.setColor(mLanguageOnSpacebarTextColor); + paint.setColor(mSpacebarTextColor); paint.setAlpha(mLanguageOnSpacebarAnimAlpha); canvas.drawText(language, width / 2, baseline - descent, paint); } @@ -1222,12 +1260,12 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack int x = (width - iconWidth) / 2; int y = height - iconHeight; drawIcon(canvas, mAutoCorrectionSpacebarLedIcon, x, y, iconWidth, iconHeight); - } else if (mSpacebarIcon != null) { - final int iconWidth = mSpacebarIcon.getIntrinsicWidth(); - final int iconHeight = mSpacebarIcon.getIntrinsicHeight(); + } else if (mSpaceIcon != null) { + final int iconWidth = mSpaceIcon.getIntrinsicWidth(); + final int iconHeight = mSpaceIcon.getIntrinsicHeight(); int x = (width - iconWidth) / 2; int y = height - iconHeight; - drawIcon(canvas, mSpacebarIcon, x, y, iconWidth, iconHeight); + drawIcon(canvas, mSpaceIcon, x, y, iconWidth, iconHeight); } } diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java index 81b8f0428..6b76e2461 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java @@ -28,7 +28,7 @@ public final class MoreKeysDetector extends KeyDetector { } @Override - public boolean alwaysAllowsKeySelectionByDraggingFinger() { + public boolean alwaysAllowsSlidingInput() { return true; } diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java index 670524380..8256d4623 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java @@ -223,7 +223,7 @@ public final class MoreKeysKeyboard extends Keyboard { } public int getDefaultKeyCoordX() { - return mLeftKeys * mColumnWidth + mLeftPadding; + return mLeftKeys * mColumnWidth; } public int getX(final int n, final int row) { @@ -298,7 +298,7 @@ public final class MoreKeysKeyboard extends Keyboard { height = keyPreviewDrawParams.mPreviewVisibleHeight + mParams.mVerticalGap; } else { final float padding = context.getResources().getDimension( - R.dimen.config_more_keys_keyboard_key_horizontal_padding) + R.dimen.more_keys_keyboard_key_horizontal_padding) + (parentKey.hasLabelsInMoreKeys() ? mParams.mDefaultKeyWidth * LABEL_PADDING_RATIO : 0.0f); width = getMaxKeyWidth(parentKey, mParams.mDefaultKeyWidth, padding, @@ -327,7 +327,7 @@ public final class MoreKeysKeyboard extends Keyboard { // If the label is single letter, minKeyWidth is enough to hold the label. if (label != null && StringUtils.codePointCount(label) > 1) { maxWidth = Math.max(maxWidth, - (int)(TypefaceUtils.getStringWidth(label, paint) + padding)); + (int)(TypefaceUtils.getLabelWidth(label, paint) + padding)); } } return maxWidth; diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java index a7c468538..973128d36 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java @@ -52,7 +52,7 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel final Resources res = context.getResources(); mKeyDetector = new MoreKeysDetector( - res.getDimension(R.dimen.config_more_keys_keyboard_slide_allowance)); + res.getDimension(R.dimen.more_keys_keyboard_slide_allowance)); } @Override @@ -81,13 +81,11 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel mListener = listener; final View container = getContainerView(); // The coordinates of panel's left-top corner in parentView's coordinate system. - // We need to consider background drawable paddings. - final int x = pointX - getDefaultCoordX() - container.getPaddingLeft() - getPaddingLeft(); - final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom() - + getPaddingBottom(); + final int x = pointX - getDefaultCoordX() - container.getPaddingLeft(); + final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom(); parentView.getLocationInWindow(mCoordinates); - // Ensure the horizontal position of the panel does not extend past the parentView edges. + // Ensure the horizontal position of the panel does not extend past the screen edges. final int maxX = parentView.getMeasuredWidth() - container.getMeasuredWidth(); final int panelX = Math.max(0, Math.min(maxX, x)) + CoordinateUtils.x(mCoordinates); final int panelY = y + CoordinateUtils.y(mCoordinates); diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index f9e78bfd9..52f190e77 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -55,10 +55,37 @@ public final class PointerTracker implements PointerTrackerQueue.Element { private static boolean sGestureHandlingEnabledByInputField = false; private static boolean sGestureHandlingEnabledByUser = false; + public interface KeyEventHandler { + /** + * Get KeyDetector object that is used for this PointerTracker. + * @return the KeyDetector object that is used for this PointerTracker + */ + public KeyDetector getKeyDetector(); + + /** + * Get KeyboardActionListener object that is used to register key code and so on. + * @return the KeyboardActionListner for this PointerTracke + */ + public KeyboardActionListener getKeyboardActionListener(); + + /** + * Get DrawingProxy object that is used for this PointerTracker. + * @return the DrawingProxy object that is used for this PointerTracker + */ + public DrawingProxy getDrawingProxy(); + + /** + * Get TimerProxy object that handles key repeat and long press timer event for this + * PointerTracker. + * @return the TimerProxy object that handles key repeat and long press timer event. + */ + public TimerProxy getTimerProxy(); + } + public interface DrawingProxy { public void invalidateKey(Key key); - public void showKeyPreview(Key key); - public void dismissKeyPreview(Key key); + public void showKeyPreview(PointerTracker tracker); + public void dismissKeyPreview(PointerTracker tracker); public void showSlidingKeyInputPreview(PointerTracker tracker); public void dismissSlidingKeyInputPreview(); public void showGestureTrail(PointerTracker tracker, boolean showsFloatingPreviewText); @@ -67,13 +94,13 @@ public final class PointerTracker implements PointerTrackerQueue.Element { public interface TimerProxy { public void startTypingStateTimer(Key typedKey); public boolean isTypingState(); - public void startKeyRepeatTimerOf(PointerTracker tracker, int repeatCount, int delay); - public void startLongPressTimerOf(PointerTracker tracker, int delay); - public void cancelLongPressTimerOf(PointerTracker tracker); - public void cancelKeyTimersOf(PointerTracker tracker); + public void startKeyRepeatTimer(PointerTracker tracker, int repeatCount, int delay); + public void startLongPressTimer(PointerTracker tracker, int delay); + public void cancelLongPressTimer(); public void startDoubleTapShiftKeyTimer(); public void cancelDoubleTapShiftKeyTimer(); public boolean isInDoubleTapShiftKeyTimeout(); + public void cancelKeyTimers(); public void startUpdateBatchInputTimer(PointerTracker tracker); public void cancelUpdateBatchInputTimer(PointerTracker tracker); public void cancelAllUpdateBatchInputTimers(); @@ -84,13 +111,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element { @Override public boolean isTypingState() { return false; } @Override - public void startKeyRepeatTimerOf(PointerTracker tracker, int repeatCount, int delay) {} - @Override - public void startLongPressTimerOf(PointerTracker tracker, int delay) {} + public void startKeyRepeatTimer(PointerTracker tracker, int repeatCount, int delay) {} @Override - public void cancelLongPressTimerOf(PointerTracker tracker) {} + public void startLongPressTimer(PointerTracker tracker, int delay) {} @Override - public void cancelKeyTimersOf(PointerTracker tracker) {} + public void cancelLongPressTimer() {} @Override public void startDoubleTapShiftKeyTimer() {} @Override @@ -98,6 +123,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { @Override public boolean isInDoubleTapShiftKeyTimeout() { return false; } @Override + public void cancelKeyTimers() {} + @Override public void startUpdateBatchInputTimer(PointerTracker tracker) {} @Override public void cancelUpdateBatchInputTimer(PointerTracker tracker) {} @@ -107,7 +134,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } static final class PointerTrackerParams { - public final boolean mKeySelectionByDraggingFinger; + public final boolean mSlidingKeyInputEnabled; public final int mTouchNoiseThresholdTime; public final int mTouchNoiseThresholdDistance; public final int mSuppressKeyPreviewAfterBatchInputDuration; @@ -115,9 +142,21 @@ public final class PointerTracker implements PointerTrackerQueue.Element { public final int mKeyRepeatInterval; public final int mLongPressShiftLockTimeout; + public static final PointerTrackerParams DEFAULT = new PointerTrackerParams(); + + private PointerTrackerParams() { + mSlidingKeyInputEnabled = false; + mTouchNoiseThresholdTime = 0; + mTouchNoiseThresholdDistance = 0; + mSuppressKeyPreviewAfterBatchInputDuration = 0; + mKeyRepeatStartTimeout = 0; + mKeyRepeatInterval = 0; + mLongPressShiftLockTimeout = 0; + } + public PointerTrackerParams(final TypedArray mainKeyboardViewAttr) { - mKeySelectionByDraggingFinger = mainKeyboardViewAttr.getBoolean( - R.styleable.MainKeyboardView_keySelectionByDraggingFinger, false); + mSlidingKeyInputEnabled = mainKeyboardViewAttr.getBoolean( + R.styleable.MainKeyboardView_slidingKeyInputEnable, false); mTouchNoiseThresholdTime = mainKeyboardViewAttr.getInt( R.styleable.MainKeyboardView_touchNoiseThresholdTime, 0); mTouchNoiseThresholdDistance = mainKeyboardViewAttr.getDimensionPixelSize( @@ -150,14 +189,13 @@ public final class PointerTracker implements PointerTrackerQueue.Element { public final int mPointerId; - private static DrawingProxy sDrawingProxy; - private static TimerProxy sTimerProxy; - private static KeyDetector sDefaultKeyDetector; + private DrawingProxy mDrawingProxy; + private TimerProxy mTimerProxy; private KeyDetector mKeyDetector; - private static KeyboardActionListener sListener = KeyboardActionListener.EMPTY_LISTENER; + private KeyboardActionListener mListener = KeyboardActionListener.EMPTY_LISTENER; private Keyboard mKeyboard; - private int mPhantomSuddenMoveThreshold; + private int mPhantonSuddenMoveThreshold; private final BogusMoveEventDetector mBogusMoveEventDetector = new BogusMoveEventDetector(); private boolean mIsDetectingGesture = false; // per PointerTracker. @@ -303,16 +341,16 @@ public final class PointerTracker implements PointerTrackerQueue.Element { private MoreKeysPanel mMoreKeysPanel; private static final int MULTIPLIER_FOR_LONG_PRESS_TIMEOUT_IN_SLIDING_INPUT = 3; - // true if this pointer is in the dragging finger mode. - boolean mIsInDraggingFinger; - // true if this pointer is sliding from a modifier key and in the sliding key input mode, - // so that further modifier keys should be ignored. + // true if this pointer is in a sliding key input. boolean mIsInSlidingKeyInput; + // true if this pointer is in a sliding key input from a modifier key, + // so that further modifier keys should be ignored. + boolean mIsInSlidingKeyInputFromModifier; // if not a NOT_A_CODE, the key of this code is repeating private int mCurrentRepeatingKeyCode = Constants.NOT_A_CODE; - // true if dragging finger is allowed. - private boolean mIsAllowedDraggingFinger; + // true if a sliding key input is allowed. + private boolean mIsAllowedSlidingKeyInput; private final GestureStrokeWithPreviewPoints mGestureStrokeWithPreviewPoints; @@ -339,26 +377,22 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return needsTheHack; } - // TODO: Add PointerTrackerFactory singleton and move some class static methods into it. - public static void init(final TypedArray mainKeyboardViewAttr, final TimerProxy timerProxy, - final DrawingProxy drawingProxy, final KeyDetector defaultKeyDetector) { - sParams = new PointerTrackerParams(mainKeyboardViewAttr); - sGestureStrokeParams = new GestureStrokeParams(mainKeyboardViewAttr); - sGesturePreviewParams = new GestureStrokePreviewParams(mainKeyboardViewAttr); - sTimeRecorder = new TimeRecorder(sParams, sGestureStrokeParams); - - final Resources res = mainKeyboardViewAttr.getResources(); + public static void init(final Resources res) { sNeedsPhantomSuddenMoveEventHack = Boolean.parseBoolean( ResourceUtils.getDeviceOverrideValue( res, R.array.phantom_sudden_move_event_device_list)); sNeedsProximateBogusDownMoveUpEventHack = needsProximateBogusDownMoveUpEventHack(res); + sParams = PointerTrackerParams.DEFAULT; sGestureStrokeParams = GestureStrokeParams.DEFAULT; sGesturePreviewParams = GestureStrokePreviewParams.DEFAULT; sTimeRecorder = new TimeRecorder(sParams, sGestureStrokeParams); + } - sTimerProxy = timerProxy; - sDrawingProxy = drawingProxy; - sDefaultKeyDetector = defaultKeyDetector; + public static void setParameters(final TypedArray mainKeyboardViewAttr) { + sParams = new PointerTrackerParams(mainKeyboardViewAttr); + sGestureStrokeParams = new GestureStrokeParams(mainKeyboardViewAttr); + sGesturePreviewParams = new GestureStrokePreviewParams(mainKeyboardViewAttr); + sTimeRecorder = new TimeRecorder(sParams, sGestureStrokeParams); } private static void updateGestureHandlingMode() { @@ -379,20 +413,20 @@ public final class PointerTracker implements PointerTrackerQueue.Element { updateGestureHandlingMode(); } - public static PointerTracker getPointerTracker(final int id) { + public static PointerTracker getPointerTracker(final int id, final KeyEventHandler handler) { final ArrayList<PointerTracker> trackers = sTrackers; // Create pointer trackers until we can get 'id+1'-th tracker, if needed. for (int i = trackers.size(); i <= id; i++) { - final PointerTracker tracker = new PointerTracker(i); + final PointerTracker tracker = new PointerTracker(i, handler); trackers.add(tracker); } return trackers.get(id); } - public static boolean isAnyInDraggingFinger() { - return sPointerTrackerQueue.isAnyInDraggingFinger(); + public static boolean isAnyInSlidingKeyInput() { + return sPointerTrackerQueue.isAnyInSlidingKeyInput(); } public static void cancelAllPointerTrackers() { @@ -400,7 +434,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } public static void setKeyboardActionListener(final KeyboardActionListener listener) { - sListener = listener; + final int trackersSize = sTrackers.size(); + for (int i = 0; i < trackersSize; ++i) { + final PointerTracker tracker = sTrackers.get(i); + tracker.mListener = listener; + } } public static void setKeyDetector(final KeyDetector keyDetector) { @@ -408,6 +446,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { for (int i = 0; i < trackersSize; ++i) { final PointerTracker tracker = sTrackers.get(i); tracker.setKeyDetectorInner(keyDetector); + // Mark that keyboard layout has been changed. + tracker.mKeyboardLayoutHasBeenChanged = true; } final Keyboard keyboard = keyDetector.getKeyboard(); sGestureHandlingEnabledByInputField = !keyboard.mId.passwordInput(); @@ -418,7 +458,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final int trackersSize = sTrackers.size(); for (int i = 0; i < trackersSize; ++i) { final PointerTracker tracker = sTrackers.get(i); - tracker.setReleasedKeyGraphics(tracker.getKey()); + tracker.setReleasedKeyGraphics(tracker.mCurrentKey); } } @@ -426,15 +466,28 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final int trackersSize = sTrackers.size(); for (int i = 0; i < trackersSize; ++i) { final PointerTracker tracker = sTrackers.get(i); - tracker.dismissMoreKeysPanel(); + if (tracker.isShowingMoreKeysPanel()) { + tracker.mMoreKeysPanel.dismissMoreKeysPanel(); + tracker.mMoreKeysPanel = null; + } } } - private PointerTracker(final int id) { + private PointerTracker(final int id, final KeyEventHandler handler) { + if (handler == null) { + throw new NullPointerException(); + } mPointerId = id; mGestureStrokeWithPreviewPoints = new GestureStrokeWithPreviewPoints( id, sGestureStrokeParams, sGesturePreviewParams); - setKeyDetectorInner(sDefaultKeyDetector); + setKeyEventHandler(handler); + } + + private void setKeyEventHandler(final KeyEventHandler handler) { + setKeyDetectorInner(handler.getKeyDetector()); + mListener = handler.getKeyboardActionListener(); + mDrawingProxy = handler.getDrawingProxy(); + mTimerProxy = handler.getTimerProxy(); } // Returns true if keyboard has been changed by this callback. @@ -447,7 +500,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (sInGesture || mIsDetectingGesture || mIsTrackingForActionDisabled) { return false; } - final boolean ignoreModifierKey = mIsInDraggingFinger && key.isModifier(); + final boolean ignoreModifierKey = mIsInSlidingKeyInput && key.isModifier(); if (DEBUG_LISTENER) { Log.d(TAG, String.format("[%d] onPress : %s%s%s%s", mPointerId, KeyDetector.printableCode(key), @@ -459,10 +512,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return false; } if (key.isEnabled()) { - sListener.onPressKey(key.getCode(), repeatCount, getActivePointerTrackerCount() == 1); + mListener.onPressKey(key.getCode(), repeatCount, getActivePointerTrackerCount() == 1); final boolean keyboardLayoutHasBeenChanged = mKeyboardLayoutHasBeenChanged; mKeyboardLayoutHasBeenChanged = false; - sTimerProxy.startTypingStateTimer(key); + mTimerProxy.startTypingStateTimer(key); return keyboardLayoutHasBeenChanged; } return false; @@ -472,8 +525,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { // primaryCode is different from {@link Key#mCode}. private void callListenerOnCodeInput(final Key key, final int primaryCode, final int x, final int y, final long eventTime) { - final boolean ignoreModifierKey = mIsInDraggingFinger && key.isModifier(); - final boolean altersCode = key.altCodeWhileTyping() && sTimerProxy.isTypingState(); + final boolean ignoreModifierKey = mIsInSlidingKeyInput && key.isModifier(); + final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState(); final int code = altersCode ? key.getAltCode() : primaryCode; if (DEBUG_LISTENER) { final String output = code == Constants.CODE_OUTPUT_TEXT @@ -493,9 +546,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (key.isEnabled() || altersCode) { sTimeRecorder.onCodeInput(code, eventTime); if (code == Constants.CODE_OUTPUT_TEXT) { - sListener.onTextInput(key.getOutputText()); + mListener.onTextInput(key.getOutputText()); } else if (code != Constants.CODE_UNSPECIFIED) { - sListener.onCodeInput(code, x, y); + mListener.onCodeInput(code, x, y); } } } @@ -508,7 +561,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (sInGesture || mIsDetectingGesture || mIsTrackingForActionDisabled) { return; } - final boolean ignoreModifierKey = mIsInDraggingFinger && key.isModifier(); + final boolean ignoreModifierKey = mIsInSlidingKeyInput && key.isModifier(); if (DEBUG_LISTENER) { Log.d(TAG, String.format("[%d] onRelease : %s%s%s%s", mPointerId, Constants.printableCode(primaryCode), @@ -523,7 +576,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return; } if (key.isEnabled()) { - sListener.onReleaseKey(primaryCode, withSliding); + mListener.onReleaseKey(primaryCode, withSliding); } } @@ -531,7 +584,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (DEBUG_LISTENER) { Log.d(TAG, String.format("[%d] onFinishSlidingInput", mPointerId)); } - sListener.onFinishSlidingInput(); + mListener.onFinishSlidingInput(); } private void callListenerOnCancelInput() { @@ -541,7 +594,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.pointerTracker_callListenerOnCancelInput(); } - sListener.onCancelInput(); + mListener.onCancelInput(); } private void setKeyDetectorInner(final KeyDetector keyDetector) { @@ -551,25 +604,23 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } mKeyDetector = keyDetector; mKeyboard = keyDetector.getKeyboard(); - // Mark that keyboard layout has been changed. - mKeyboardLayoutHasBeenChanged = true; final int keyWidth = mKeyboard.mMostCommonKeyWidth; final int keyHeight = mKeyboard.mMostCommonKeyHeight; mGestureStrokeWithPreviewPoints.setKeyboardGeometry(keyWidth, mKeyboard.mOccupiedHeight); final Key newKey = mKeyDetector.detectHitKey(mKeyX, mKeyY); if (newKey != mCurrentKey) { - if (sDrawingProxy != null) { + if (mDrawingProxy != null) { setReleasedKeyGraphics(mCurrentKey); } // Keep {@link #mCurrentKey} that comes from previous keyboard. } - mPhantomSuddenMoveThreshold = (int)(keyWidth * PHANTOM_SUDDEN_MOVE_THRESHOLD); + mPhantonSuddenMoveThreshold = (int)(keyWidth * PHANTOM_SUDDEN_MOVE_THRESHOLD); mBogusMoveEventDetector.setKeyboardGeometry(keyWidth, keyHeight); } @Override - public boolean isInDraggingFinger() { - return mIsInDraggingFinger; + public boolean isInSlidingKeyInput() { + return mIsInSlidingKeyInput; } public Key getKey() { @@ -586,7 +637,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } private void setReleasedKeyGraphics(final Key key) { - sDrawingProxy.dismissKeyPreview(key); + mDrawingProxy.dismissKeyPreview(this); if (key == null) { return; } @@ -627,14 +678,14 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } // Even if the key is disabled, it should respond if it is in the altCodeWhileTyping state. - final boolean altersCode = key.altCodeWhileTyping() && sTimerProxy.isTypingState(); + final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState(); final boolean needsToUpdateGraphics = key.isEnabled() || altersCode; if (!needsToUpdateGraphics) { return; } if (!key.noKeyPreview() && !sInGesture && !needsToSuppressKeyPreviewPopup(eventTime)) { - sDrawingProxy.showKeyPreview(key); + mDrawingProxy.showKeyPreview(this); } updatePressKeyGraphics(key); @@ -646,7 +697,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } } - if (key.altCodeWhileTyping() && sTimerProxy.isTypingState()) { + if (key.altCodeWhileTyping() && mTimerProxy.isTypingState()) { final int altCode = key.getAltCode(); final Key altKey = mKeyboard.getKey(altCode); if (altKey != null) { @@ -660,14 +711,14 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } } - private static void updateReleaseKeyGraphics(final Key key) { + private void updateReleaseKeyGraphics(final Key key) { key.onReleased(); - sDrawingProxy.invalidateKey(key); + mDrawingProxy.invalidateKey(key); } - private static void updatePressKeyGraphics(final Key key) { + private void updatePressKeyGraphics(final Key key) { key.onPressed(); - sDrawingProxy.invalidateKey(key); + mDrawingProxy.invalidateKey(key); } public GestureStrokeWithPreviewPoints getGestureStrokeWithPreviewPoints() { @@ -715,7 +766,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return newKey; } - /* package */ static int getActivePointerTrackerCount() { + private static int getActivePointerTrackerCount() { return sPointerTrackerQueue.size(); } @@ -738,12 +789,12 @@ public final class PointerTracker implements PointerTrackerQueue.Element { sAggregratedPointers.reset(); sLastRecognitionPointSize = 0; sLastRecognitionTime = 0; - sListener.onStartBatchInput(); + mListener.onStartBatchInput(); dismissAllMoreKeysPanels(); } - sTimerProxy.cancelLongPressTimerOf(this); + mTimerProxy.cancelLongPressTimer(); // A gesture floating preview text will be shown at the oldest pointer/finger on the screen. - sDrawingProxy.showGestureTrail( + mDrawingProxy.showGestureTrail( this, isOldestTrackerInQueue() /* showsFloatingPreviewText */); } @@ -761,7 +812,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return; } // A gesture floating preview text will be shown at the oldest pointer/finger on the screen. - sDrawingProxy.showGestureTrail( + mDrawingProxy.showGestureTrail( this, isOldestTrackerInQueue() /* showsFloatingPreviewText */); } @@ -776,8 +827,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { Log.d(TAG, String.format("[%d] onUpdateBatchInput: batchPoints=%d", mPointerId, size)); } - sTimerProxy.startUpdateBatchInputTimer(this); - sListener.onUpdateBatchInput(sAggregratedPointers); + mTimerProxy.startUpdateBatchInputTimer(this); + mListener.onUpdateBatchInput(sAggregratedPointers); // The listener may change the size of the pointers (when auto-committing // for example), so we need to get the size from the pointers again. sLastRecognitionPointSize = sAggregratedPointers.getPointerSize(); @@ -792,13 +843,13 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (getActivePointerTrackerCount() == 1) { sInGesture = false; sTimeRecorder.onEndBatchInput(eventTime); - sTimerProxy.cancelAllUpdateBatchInputTimers(); + mTimerProxy.cancelAllUpdateBatchInputTimers(); if (!mIsTrackingForActionDisabled) { if (DEBUG_LISTENER) { Log.d(TAG, String.format("[%d] onEndBatchInput : batchPoints=%d", mPointerId, sAggregratedPointers.getPointerSize())); } - sListener.onEndBatchInput(sAggregratedPointers); + mListener.onEndBatchInput(sAggregratedPointers); } } } @@ -806,7 +857,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return; } // A gesture floating preview text will be shown at the oldest pointer/finger on the screen. - sDrawingProxy.showGestureTrail( + mDrawingProxy.showGestureTrail( this, isOldestTrackerInQueue() /* showsFloatingPreviewText */); } @@ -820,26 +871,19 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (DEBUG_LISTENER) { Log.d(TAG, String.format("[%d] onCancelBatchInput", mPointerId)); } - sListener.onCancelBatchInput(); + mListener.onCancelBatchInput(); } - public void processMotionEvent(final MotionEvent me, final KeyDetector keyDetector) { + public void processMotionEvent(final MotionEvent me, final KeyEventHandler handler) { final int action = me.getActionMasked(); final long eventTime = me.getEventTime(); if (action == MotionEvent.ACTION_MOVE) { - // When this pointer is the only active pointer and is showing a more keys panel, - // we should ignore other pointers' motion event. - final boolean shouldIgnoreOtherPointers = - isShowingMoreKeysPanel() && getActivePointerTrackerCount() == 1; final int pointerCount = me.getPointerCount(); for (int index = 0; index < pointerCount; index++) { final int id = me.getPointerId(index); - if (shouldIgnoreOtherPointers && id != mPointerId) { - continue; - } + final PointerTracker tracker = getPointerTracker(id, handler); final int x = (int)me.getX(index); final int y = (int)me.getY(index); - final PointerTracker tracker = getPointerTracker(id); tracker.onMoveEvent(x, y, eventTime, me); } return; @@ -850,7 +894,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { switch (action) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: - onDownEvent(x, y, eventTime, keyDetector); + onDownEvent(x, y, eventTime, handler); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: @@ -863,11 +907,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } private void onDownEvent(final int x, final int y, final long eventTime, - final KeyDetector keyDetector) { + final KeyEventHandler handler) { if (DEBUG_EVENT) { printTouchEvent("onDownEvent:", x, y, eventTime); } - setKeyDetectorInner(keyDetector); + setKeyEventHandler(handler); // Naive up-to-down noise filter. final long deltaT = eventTime - mUpTime; if (deltaT < sParams.mTouchNoiseThresholdTime) { @@ -910,29 +954,20 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } } - /* package */ boolean isShowingMoreKeysPanel() { + private boolean isShowingMoreKeysPanel() { return (mMoreKeysPanel != null); } - private void dismissMoreKeysPanel() { - if (isShowingMoreKeysPanel()) { - mMoreKeysPanel.dismissMoreKeysPanel(); - mMoreKeysPanel = null; - } - } - private void onDownEventInternal(final int x, final int y, final long eventTime) { Key key = onDownKey(x, y, eventTime); - // Key selection by dragging finger is allowed when 1) key selection by dragging finger is - // enabled by configuration, 2) this pointer starts dragging from modifier key, or 3) this - // pointer's KeyDetector always allows key selection by dragging finger, such as - // {@link MoreKeysKeyboard}. - mIsAllowedDraggingFinger = sParams.mKeySelectionByDraggingFinger + // Sliding key is allowed when 1) enabled by configuration, 2) this pointer starts sliding + // from modifier key, or 3) this pointer's KeyDetector always allows sliding input. + mIsAllowedSlidingKeyInput = sParams.mSlidingKeyInputEnabled || (key != null && key.isModifier()) - || mKeyDetector.alwaysAllowsKeySelectionByDraggingFinger(); + || mKeyDetector.alwaysAllowsSlidingInput(); mKeyboardLayoutHasBeenChanged = false; mIsTrackingForActionDisabled = false; - resetKeySelectionByDraggingFinger(); + resetSlidingKeyInput(); if (key != null) { // This onPress call may have changed keyboard layout. Those cases are detected at // {@link #setKeyboard}. In those cases, we should update key according to the new @@ -947,17 +982,17 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } } - private void startKeySelectionByDraggingFinger(final Key key) { - if (!mIsInDraggingFinger) { - mIsInSlidingKeyInput = key.isModifier(); + private void startSlidingKeyInput(final Key key) { + if (!mIsInSlidingKeyInput) { + mIsInSlidingKeyInputFromModifier = key.isModifier(); } - mIsInDraggingFinger = true; + mIsInSlidingKeyInput = true; } - private void resetKeySelectionByDraggingFinger() { - mIsInDraggingFinger = false; + private void resetSlidingKeyInput() { mIsInSlidingKeyInput = false; - sDrawingProxy.dismissSlidingKeyInputPreview(); + mIsInSlidingKeyInputFromModifier = false; + mDrawingProxy.dismissSlidingKeyInputPreview(); } private void onGestureMoveEvent(final int x, final int y, final long eventTime, @@ -968,7 +1003,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final boolean onValidArea = mGestureStrokeWithPreviewPoints.addPointOnKeyboard( x, y, gestureTime, isMajorEvent); if (mGestureStrokeWithPreviewPoints.getLength() > beforeLength) { - sTimerProxy.startUpdateBatchInputTimer(this); + mTimerProxy.startUpdateBatchInputTimer(this); } // If the move event goes out from valid batch input area, cancel batch input. if (!onValidArea) { @@ -1013,15 +1048,15 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final int translatedY = mMoreKeysPanel.translateY(y); mMoreKeysPanel.onMoveEvent(translatedX, translatedY, mPointerId, eventTime); onMoveKey(x, y); - if (mIsInSlidingKeyInput) { - sDrawingProxy.showSlidingKeyInputPreview(this); + if (mIsInSlidingKeyInputFromModifier) { + mDrawingProxy.showSlidingKeyInputPreview(this); } return; } onMoveEventInternal(x, y, eventTime); } - private void processDraggingFingerInToNewKey(final Key newKey, final int x, final int y, + private void processSlidingKeyInput(final Key newKey, final int x, final int y, final long eventTime) { // This onPress call may have changed keyboard layout. Those cases are detected // at {@link #setKeyboard}. In those cases, we should update key according @@ -1075,29 +1110,29 @@ public final class PointerTracker implements PointerTrackerQueue.Element { onDownEventInternal(x, y, eventTime); } - private void processDraggingFingerOutFromOldKey(final Key oldKey) { + private void processSildeOutFromOldKey(final Key oldKey) { setReleasedKeyGraphics(oldKey); callListenerOnRelease(oldKey, oldKey.getCode(), true /* withSliding */); - startKeySelectionByDraggingFinger(oldKey); - sTimerProxy.cancelKeyTimersOf(this); + startSlidingKeyInput(oldKey); + mTimerProxy.cancelKeyTimers(); } - private void dragFingerFromOldKeyToNewKey(final Key key, final int x, final int y, + private void slideFromOldKeyToNewKey(final Key key, final int x, final int y, final long eventTime, final Key oldKey, final int lastX, final int lastY) { // The pointer has been slid in to the new key from the previous key, we must call // onRelease() first to notify that the previous key has been released, then call // onPress() to notify that the new key is being pressed. - processDraggingFingerOutFromOldKey(oldKey); + processSildeOutFromOldKey(oldKey); startRepeatKey(key); - if (mIsAllowedDraggingFinger) { - processDraggingFingerInToNewKey(key, x, y, eventTime); + if (mIsAllowedSlidingKeyInput) { + processSlidingKeyInput(key, x, y, eventTime); } // HACK: On some devices, quick successive touches may be reported as a sudden move by // touch panel firmware. This hack detects such cases and translates the move event to // successive up and down events. // TODO: Should find a way to balance gesture detection and this hack. else if (sNeedsPhantomSuddenMoveEventHack - && getDistance(x, y, lastX, lastY) >= mPhantomSuddenMoveThreshold) { + && getDistance(x, y, lastX, lastY) >= mPhantonSuddenMoveThreshold) { processPhantomSuddenMoveHack(key, x, y, eventTime, oldKey, lastX, lastY); } // HACK: On some devices, quick successive proximate touches may be reported as a bogus @@ -1128,11 +1163,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } } - private void dragFingerOutFromOldKey(final Key oldKey, final int x, final int y) { + private void slideOutFromOldKey(final Key oldKey, final int x, final int y) { // The pointer has been slid out from the previous key, we must call onRelease() to // notify that the previous key has been released. - processDraggingFingerOutFromOldKey(oldKey); - if (mIsAllowedDraggingFinger) { + processSildeOutFromOldKey(oldKey); + if (mIsAllowedSlidingKeyInput) { onMoveToNewKey(null, x, y); } else { if (!mIsDetectingGesture) { @@ -1159,19 +1194,19 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (newKey != null) { if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, eventTime, newKey)) { - dragFingerFromOldKeyToNewKey(newKey, x, y, eventTime, oldKey, lastX, lastY); + slideFromOldKeyToNewKey(newKey, x, y, eventTime, oldKey, lastX, lastY); } else if (oldKey == null) { // The pointer has been slid in to the new key, but the finger was not on any keys. // In this case, we must call onPress() to notify that the new key is being pressed. - processDraggingFingerInToNewKey(newKey, x, y, eventTime); + processSlidingKeyInput(newKey, x, y, eventTime); } } else { // newKey == null if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, eventTime, newKey)) { - dragFingerOutFromOldKey(oldKey, x, y); + slideOutFromOldKey(oldKey, x, y); } } - if (mIsInSlidingKeyInput) { - sDrawingProxy.showSlidingKeyInputPreview(this); + if (mIsInSlidingKeyInputFromModifier) { + mDrawingProxy.showSlidingKeyInputPreview(this); } } @@ -1180,7 +1215,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { printTouchEvent("onUpEvent :", x, y, eventTime); } - sTimerProxy.cancelUpdateBatchInputTimer(this); + mTimerProxy.cancelUpdateBatchInputTimer(this); if (!sInGesture) { if (mCurrentKey != null && mCurrentKey.isModifier()) { // Before processing an up event of modifier key, all pointers already being @@ -1202,15 +1237,18 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (DEBUG_EVENT) { printTouchEvent("onPhntEvent:", mLastX, mLastY, eventTime); } + if (isShowingMoreKeysPanel()) { + return; + } onUpEventInternal(mLastX, mLastY, eventTime); cancelTrackingForAction(); } private void onUpEventInternal(final int x, final int y, final long eventTime) { - sTimerProxy.cancelKeyTimersOf(this); - final boolean isInDraggingFinger = mIsInDraggingFinger; + mTimerProxy.cancelKeyTimers(); final boolean isInSlidingKeyInput = mIsInSlidingKeyInput; - resetKeySelectionByDraggingFinger(); + final boolean isInSlidingKeyInputFromModifier = mIsInSlidingKeyInputFromModifier; + resetSlidingKeyInput(); mIsDetectingGesture = false; final Key currentKey = mCurrentKey; mCurrentKey = null; @@ -1242,11 +1280,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return; } if (currentKey != null && currentKey.isRepeatable() - && (currentKey.getCode() == currentRepeatingKeyCode) && !isInDraggingFinger) { + && (currentKey.getCode() == currentRepeatingKeyCode) && !isInSlidingKeyInput) { return; } detectAndSendKey(currentKey, mKeyX, mKeyY, eventTime); - if (isInSlidingKeyInput) { + if (isInSlidingKeyInputFromModifier) { callListenerOnFinishSlidingInput(); } } @@ -1268,7 +1306,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } public void onLongPressed() { - resetKeySelectionByDraggingFinger(); + resetSlidingKeyInput(); cancelTrackingForAction(); setReleasedKeyGraphics(mCurrentKey); sPointerTrackerQueue.remove(this); @@ -1286,9 +1324,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } private void onCancelEventInternal() { - sTimerProxy.cancelKeyTimersOf(this); + mTimerProxy.cancelKeyTimers(); setReleasedKeyGraphics(mCurrentKey); - resetKeySelectionByDraggingFinger(); + resetSlidingKeyInput(); if (isShowingMoreKeysPanel()) { mMoreKeysPanel.dismissMoreKeysPanel(); mMoreKeysPanel = null; @@ -1309,7 +1347,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } // Here curKey points to the different key from newKey. final int keyHysteresisDistanceSquared = mKeyDetector.getKeyHysteresisDistanceSquared( - mIsInSlidingKeyInput); + mIsInSlidingKeyInputFromModifier); final int distanceFromKeyEdgeSquared = curKey.squaredDistanceToEdge(x, y); if (distanceFromKeyEdgeSquared >= keyHysteresisDistanceSquared) { if (DEBUG_MODE) { @@ -1320,7 +1358,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } return true; } - if (sNeedsProximateBogusDownMoveUpEventHack && !mIsAllowedDraggingFinger + if (sNeedsProximateBogusDownMoveUpEventHack && !mIsAllowedSlidingKeyInput && sTimeRecorder.isInFastTyping(eventTime) && mBogusMoveEventDetector.hasTraveledLongDistance(x, y)) { if (DEBUG_MODE) { @@ -1342,26 +1380,26 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (key == null) return; if (!key.isLongPressEnabled()) return; // Caveat: Please note that isLongPressEnabled() can be true even if the current key - // doesn't have its more keys. (e.g. spacebar, globe key) If we are in the dragging finger - // mode, we will disable long press timer of such key. + // doesn't have its more keys. (e.g. spacebar, globe key) // We always need to start the long press timer if the key has its more keys regardless of - // whether or not we are in the dragging finger mode. - if (mIsInDraggingFinger && key.getMoreKeys() == null) return; - - final int delay = getLongPressTimeout(key.getCode()); - sTimerProxy.startLongPressTimerOf(this, delay); - } - - private int getLongPressTimeout(final int code) { - if (code == Constants.CODE_SHIFT) { - return sParams.mLongPressShiftLockTimeout; - } - final int longpressTimeout = Settings.getInstance().getCurrent().mKeyLongpressTimeout; - if (mIsInSlidingKeyInput) { - // We use longer timeout for sliding finger input started from the modifier key. - return longpressTimeout * MULTIPLIER_FOR_LONG_PRESS_TIMEOUT_IN_SLIDING_INPUT; + // whether or not we are in the sliding input mode. + if (mIsInSlidingKeyInput && key.getMoreKeys() == null) return; + final int delay; + switch (key.getCode()) { + case Constants.CODE_SHIFT: + delay = sParams.mLongPressShiftLockTimeout; + break; + default: + final int longpressTimeout = Settings.getInstance().getCurrent().mKeyLongpressTimeout; + if (mIsInSlidingKeyInputFromModifier) { + // We use longer timeout for sliding finger input started from the modifier key. + delay = longpressTimeout * MULTIPLIER_FOR_LONG_PRESS_TIMEOUT_IN_SLIDING_INPUT; + } else { + delay = longpressTimeout; + } + break; } - return longpressTimeout; + mTimerProxy.startLongPressTimer(this, delay); } private void detectAndSendKey(final Key key, final int x, final int y, final long eventTime) { @@ -1379,10 +1417,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (sInGesture) return; if (key == null) return; if (!key.isRepeatable()) return; - // Don't start key repeat when we are in the dragging finger mode. - if (mIsInDraggingFinger) return; + // Don't start key repeat when we are in sliding input mode. + if (mIsInSlidingKeyInput) return; final int startRepeatCount = 1; - startKeyRepeatTimer(startRepeatCount); + mTimerProxy.startKeyRepeatTimer(this, startRepeatCount, sParams.mKeyRepeatStartTimeout); } public void onKeyRepeat(final int code, final int repeatCount) { @@ -1394,17 +1432,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element { mCurrentRepeatingKeyCode = code; mIsDetectingGesture = false; final int nextRepeatCount = repeatCount + 1; - startKeyRepeatTimer(nextRepeatCount); + mTimerProxy.startKeyRepeatTimer(this, nextRepeatCount, sParams.mKeyRepeatInterval); callListenerOnPressAndCheckKeyboardLayoutChange(key, repeatCount); callListenerOnCodeInput(key, code, mKeyX, mKeyY, SystemClock.uptimeMillis()); } - private void startKeyRepeatTimer(final int repeatCount) { - final int delay = - (repeatCount == 1) ? sParams.mKeyRepeatStartTimeout : sParams.mKeyRepeatInterval; - sTimerProxy.startKeyRepeatTimerOf(this, repeatCount, delay); - } - private void printTouchEvent(final String title, final int x, final int y, final long eventTime) { final Key key = mKeyDetector.detectHitKey(x, y); diff --git a/java/src/com/android/inputmethod/keyboard/internal/CustomViewPager.java b/java/src/com/android/inputmethod/keyboard/internal/CustomViewPager.java deleted file mode 100644 index f5cc45ca7..000000000 --- a/java/src/com/android/inputmethod/keyboard/internal/CustomViewPager.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 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.support.v4.view.ViewPager; -import android.util.AttributeSet; -import android.util.Log; -import android.view.MotionEvent; - -/** - * Custom view pager to prevent {@link ViewPager} from crashing while handling multi-touch - * event. - */ -public class CustomViewPager extends ViewPager { - private static final String TAG = CustomViewPager.class.getSimpleName(); - - public CustomViewPager(final Context context, final AttributeSet attrs) { - super(context, attrs); - } - - @Override - public boolean onInterceptTouchEvent(final MotionEvent event) { - // This only happens when you multi-touch, take the first finger off and move. - // Unfortunately this causes {@link ViewPager} to crash, so we will ignore such events. - if (event.getAction() == MotionEvent.ACTION_MOVE && event.getPointerId(0) != 0) { - Log.w(TAG, "Ignored multi-touch move event to prevent ViewPager from crashing"); - return false; - } - - return super.onInterceptTouchEvent(event); - } -} diff --git a/java/src/com/android/inputmethod/keyboard/internal/DrawingHandler.java b/java/src/com/android/inputmethod/keyboard/internal/DrawingHandler.java deleted file mode 100644 index df82becae..000000000 --- a/java/src/com/android/inputmethod/keyboard/internal/DrawingHandler.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 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.os.Message; - -import com.android.inputmethod.keyboard.Key; -import com.android.inputmethod.keyboard.internal.DrawingHandler.Callbacks; -import com.android.inputmethod.latin.SuggestedWords; -import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper; - -// TODO: Separate this class into KeyPreviewHandler and BatchInputPreviewHandler or so. -public class DrawingHandler extends LeakGuardHandlerWrapper<Callbacks> { - public interface Callbacks { - public void dismissKeyPreviewWithoutDelay(Key key); - public void dismissAllKeyPreviews(); - public void showGestureFloatingPreviewText(SuggestedWords suggestedWords); - } - - private static final int MSG_DISMISS_KEY_PREVIEW = 0; - private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1; - - public DrawingHandler(final Callbacks ownerInstance) { - super(ownerInstance); - } - - @Override - public void handleMessage(final Message msg) { - final Callbacks callbacks = getOwnerInstance(); - if (callbacks == null) { - return; - } - switch (msg.what) { - case MSG_DISMISS_KEY_PREVIEW: - callbacks.dismissKeyPreviewWithoutDelay((Key)msg.obj); - break; - case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT: - callbacks.showGestureFloatingPreviewText(SuggestedWords.EMPTY); - break; - } - } - - public void dismissKeyPreview(final long delay, final Key key) { - sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, key), delay); - } - - private void cancelAllDismissKeyPreviews() { - removeMessages(MSG_DISMISS_KEY_PREVIEW); - final Callbacks callbacks = getOwnerInstance(); - if (callbacks == null) { - return; - } - callbacks.dismissAllKeyPreviews(); - } - - public void dismissGestureFloatingPreviewText(final long delay) { - sendMessageDelayed(obtainMessage(MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT), delay); - } - - public void cancelAllMessages() { - cancelAllDismissKeyPreviews(); - } -} diff --git a/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java b/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java index e2fd39017..3133e54be 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java @@ -25,7 +25,7 @@ import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.settings.Settings; import com.android.inputmethod.latin.utils.CollectionUtils; -import com.android.inputmethod.latin.utils.JsonUtils; +import com.android.inputmethod.latin.utils.StringUtils; import java.util.ArrayDeque; import java.util.ArrayList; @@ -53,7 +53,7 @@ public class DynamicGridKeyboard extends Keyboard { private Key[] mCachedGridKeys; public DynamicGridKeyboard(final SharedPreferences prefs, final Keyboard templateKeyboard, - final int maxKeyCount, final int categoryId) { + final int maxKeyCount, final int categoryId, final int categoryPageId) { super(templateKeyboard); final Key key0 = getTemplateKey(TEMPLATE_KEY_CODE_0); final Key key1 = getTemplateKey(TEMPLATE_KEY_CODE_1); @@ -124,7 +124,7 @@ public class DynamicGridKeyboard extends Keyboard { final int keyY0 = getKeyY0(index); final int keyX1 = getKeyX1(index); final int keyY1 = getKeyY1(index); - gridKey.updateCoordinates(keyX0, keyY0, keyX1, keyY1); + gridKey.updateCorrdinates(keyX0, keyY0, keyX1, keyY1); index++; } } @@ -139,48 +139,36 @@ public class DynamicGridKeyboard extends Keyboard { keys.add(key.getCode()); } } - final String jsonStr = JsonUtils.listToJsonStr(keys); + final String jsonStr = StringUtils.listToJsonStr(keys); Settings.writeEmojiRecentKeys(mPrefs, jsonStr); } - private static Key getKeyByCode(final Collection<DynamicGridKeyboard> keyboards, - final int code) { - for (final DynamicGridKeyboard keyboard : keyboards) { - final Key key = keyboard.getKey(code); - if (key != null) { - return key; - } - } - return null; - } - - private static Key getKeyByOutputText(final Collection<DynamicGridKeyboard> keyboards, - final String outputText) { + private static Key getKey(final Collection<DynamicGridKeyboard> keyboards, final Object o) { for (final DynamicGridKeyboard kbd : keyboards) { - final Key key = kbd.getKeyFromOutputText(outputText); - if (key != null) { - return key; + if (o instanceof Integer) { + final int code = (Integer) o; + final Key key = kbd.getKey(code); + if (key != null) { + return key; + } + } else if (o instanceof String) { + final String outputText = (String) o; + final Key key = kbd.getKeyFromOutputText(outputText); + if (key != null) { + return key; + } + } else { + Log.w(TAG, "Invalid object: " + o); } } return null; } - public void loadRecentKeys(final Collection<DynamicGridKeyboard> keyboards) { + public void loadRecentKeys(Collection<DynamicGridKeyboard> keyboards) { final String str = Settings.readEmojiRecentKeys(mPrefs); - final List<Object> keys = JsonUtils.jsonStrToList(str); + final List<Object> keys = StringUtils.jsonStrToList(str); for (final Object o : keys) { - final Key key; - if (o instanceof Integer) { - final int code = (Integer)o; - key = getKeyByCode(keyboards, code); - } else if (o instanceof String) { - final String outputText = (String)o; - key = getKeyByOutputText(keyboards, outputText); - } else { - Log.w(TAG, "Invalid object: " + o); - continue; - } - addKeyLast(key); + addKeyLast(getKey(keyboards, o)); } } @@ -229,7 +217,7 @@ public class DynamicGridKeyboard extends Keyboard { super(originalKey); } - public void updateCoordinates(final int x0, final int y0, final int x1, final int y1) { + public void updateCorrdinates(final int x0, final int y0, final int x1, final int y1) { mCurrentX = x0; mCurrentY = y0; getHitBox().set(x0, y0, x1, y1); diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureTrailsPreview.java b/java/src/com/android/inputmethod/keyboard/internal/GestureTrailsPreview.java index 8b413e5e2..19e995548 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureTrailsPreview.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureTrailsPreview.java @@ -31,7 +31,7 @@ import android.view.View; import com.android.inputmethod.keyboard.PointerTracker; import com.android.inputmethod.keyboard.internal.GestureTrail.Params; import com.android.inputmethod.latin.utils.CollectionUtils; -import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper; +import com.android.inputmethod.latin.utils.StaticInnerHandlerWrapper; /** * Draw gesture trail preview graphics during gesture. @@ -52,23 +52,21 @@ public final class GestureTrailsPreview extends AbstractDrawingPreview { private final DrawingHandler mDrawingHandler; private static final class DrawingHandler - extends LeakGuardHandlerWrapper<GestureTrailsPreview> { + extends StaticInnerHandlerWrapper<GestureTrailsPreview> { private static final int MSG_UPDATE_GESTURE_TRAIL = 0; private final Params mGestureTrailParams; - public DrawingHandler(final GestureTrailsPreview ownerInstance, + public DrawingHandler(final GestureTrailsPreview outerInstance, final Params gestureTrailParams) { - super(ownerInstance); + super(outerInstance); mGestureTrailParams = gestureTrailParams; } @Override public void handleMessage(final Message msg) { - final GestureTrailsPreview preview = getOwnerInstance(); - if (preview == null) { - return; - } + final GestureTrailsPreview preview = getOuterInstance(); + if (preview == null) return; switch (msg.what) { case MSG_UPDATE_GESTURE_TRAIL: preview.getDrawingView().invalidate(); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java index accfaedcb..22f5b3dd1 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java @@ -78,10 +78,10 @@ public final class KeySpecParser { * or has no key specifications. */ public static String[] splitKeySpecs(final String text) { - if (TextUtils.isEmpty(text)) { + final int size = text.length(); + if (size == 0) { return null; } - final int size = text.length(); // Optimization for one-letter key specification. if (size == 1) { return text.charAt(0) == COMMA ? null : new String[] { text }; @@ -380,9 +380,6 @@ public final class KeySpecParser { public static String resolveTextReference(final String rawText, final KeyboardTextsSet textsSet) { - if (TextUtils.isEmpty(rawText)) { - return null; - } int level = 0; String text = rawText; StringBuilder sb; @@ -395,7 +392,7 @@ public final class KeySpecParser { final int prefixLen = PREFIX_TEXT.length(); final int size = text.length(); if (size < prefixLen) { - return TextUtils.isEmpty(text) ? null : text; + return text; } sb = null; @@ -424,7 +421,7 @@ public final class KeySpecParser { text = sb.toString(); } } while (sb != null); - return TextUtils.isEmpty(text) ? null : text; + return text; } private static int searchTextNameEnd(final String text, final int start) { @@ -486,7 +483,7 @@ public final class KeySpecParser { public static int toUpperCaseOfCodeForLocale(final int code, final boolean needsToUpperCase, final Locale locale) { if (!Constants.isLetterCode(code) || !needsToUpperCase) return code; - final String text = StringUtils.newSingleCodePointString(code); + final String text = new String(new int[] { code } , 0, 1); final String casedText = KeySpecParser.toUpperCaseOfStringForLocale( text, needsToUpperCase, locale); return StringUtils.codePointCount(casedText) == 1 diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java index f7e43a6c2..05d855e31 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java @@ -27,7 +27,6 @@ import com.android.inputmethod.latin.utils.XmlParseUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import java.util.Arrays; import java.util.HashMap; public final class KeyStylesSet { @@ -91,8 +90,7 @@ public final class KeyStylesSet { } final Object value = mStyleAttributes.get(index); if (value != null) { - final String[] array = (String[])value; - return Arrays.copyOf(array, array.length); + return (String[])value; } final KeyStyle parentStyle = mStyles.get(mParentStyleName); return parentStyle.getStringArray(a, index); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java b/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java index c3e0aa685..8bdad364c 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java @@ -47,8 +47,6 @@ public final class KeyVisualAttributes { public final int mShiftedLetterHintActivatedColor; public final int mPreviewTextColor; - public final float mHintLabelVerticalAdjustment; - private static final int[] VISUAL_ATTRIBUTE_IDS = { R.styleable.Keyboard_Key_keyTypeface, R.styleable.Keyboard_Key_keyLetterSize, @@ -67,7 +65,6 @@ public final class KeyVisualAttributes { R.styleable.Keyboard_Key_keyShiftedLetterHintInactivatedColor, R.styleable.Keyboard_Key_keyShiftedLetterHintActivatedColor, R.styleable.Keyboard_Key_keyPreviewTextColor, - R.styleable.Keyboard_Key_keyHintLabelVerticalAdjustment, }; private static final SparseIntArray sVisualAttributeIds = new SparseIntArray(); private static final int ATTR_DEFINED = 1; @@ -130,8 +127,5 @@ public final class KeyVisualAttributes { mShiftedLetterHintActivatedColor = keyAttr.getColor( R.styleable.Keyboard_Key_keyShiftedLetterHintActivatedColor, 0); mPreviewTextColor = keyAttr.getColor(R.styleable.Keyboard_Key_keyPreviewTextColor, 0); - - mHintLabelVerticalAdjustment = ResourceUtils.getFraction(keyAttr, - R.styleable.Keyboard_Key_keyHintLabelVerticalAdjustment, 0.0f); } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java index b31358f3c..c1ae65695 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java @@ -459,7 +459,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> { final int x = (int)row.getKeyX(null); final int y = row.getKeyY(); final Key key = new Key(mParams, label, null /* hintLabel */, 0 /* iconId */, - code, outputText, x, y, (int)keyWidth, row.getRowHeight(), + code, outputText, x, y, (int)keyWidth, (int)row.getRowHeight(), row.getDefaultKeyLabelFlags(), row.getDefaultBackgroundType()); endKey(key); row.advanceXPos(keyWidth); @@ -649,9 +649,10 @@ public class KeyboardBuilder<KP extends KeyboardParams> { R.styleable.Keyboard_Case_passwordInput, id.passwordInput()); final boolean clobberSettingsKeyMatched = matchBoolean(caseAttr, R.styleable.Keyboard_Case_clobberSettingsKey, id.mClobberSettingsKey); - final boolean supportsSwitchingToShortcutImeMatched = matchBoolean(caseAttr, - R.styleable.Keyboard_Case_supportsSwitchingToShortcutIme, - id.mSupportsSwitchingToShortcutIme); + final boolean shortcutKeyEnabledMatched = matchBoolean(caseAttr, + R.styleable.Keyboard_Case_shortcutKeyEnabled, id.mShortcutKeyEnabled); + final boolean shortcutKeyOnSymbolsMatched = matchBoolean(caseAttr, + R.styleable.Keyboard_Case_shortcutKeyOnSymbols, id.mShortcutKeyOnSymbols); final boolean hasShortcutKeyMatched = matchBoolean(caseAttr, R.styleable.Keyboard_Case_hasShortcutKey, id.mHasShortcutKey); final boolean languageSwitchKeyEnabledMatched = matchBoolean(caseAttr, @@ -670,12 +671,13 @@ public class KeyboardBuilder<KP extends KeyboardParams> { final boolean selected = keyboardLayoutSetMatched && keyboardLayoutSetElementMatched && modeMatched && navigateNextMatched && navigatePreviousMatched && passwordInputMatched && clobberSettingsKeyMatched - && supportsSwitchingToShortcutImeMatched && hasShortcutKeyMatched - && languageSwitchKeyEnabledMatched && isMultiLineMatched && imeActionMatched - && localeCodeMatched && languageCodeMatched && countryCodeMatched; + && shortcutKeyEnabledMatched && shortcutKeyOnSymbolsMatched + && hasShortcutKeyMatched && languageSwitchKeyEnabledMatched + && isMultiLineMatched && imeActionMatched && localeCodeMatched + && languageCodeMatched && countryCodeMatched; if (DEBUG) { - startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE, + startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE, textAttr(caseAttr.getString( R.styleable.Keyboard_Case_keyboardLayoutSet), "keyboardLayoutSet"), textAttr(caseAttr.getString( @@ -692,9 +694,10 @@ public class KeyboardBuilder<KP extends KeyboardParams> { "clobberSettingsKey"), booleanAttr(caseAttr, R.styleable.Keyboard_Case_passwordInput, "passwordInput"), - booleanAttr( - caseAttr, R.styleable.Keyboard_Case_supportsSwitchingToShortcutIme, - "supportsSwitchingToShortcutIme"), + booleanAttr(caseAttr, R.styleable.Keyboard_Case_shortcutKeyEnabled, + "shortcutKeyEnabled"), + booleanAttr(caseAttr, R.styleable.Keyboard_Case_shortcutKeyOnSymbols, + "shortcutKeyOnSymbols"), booleanAttr(caseAttr, R.styleable.Keyboard_Case_hasShortcutKey, "hasShortcutKey"), booleanAttr(caseAttr, R.styleable.Keyboard_Case_languageSwitchKeyEnabled, diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java index 0ee935f60..336db186e 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java @@ -48,6 +48,7 @@ public final class KeyboardIconsSet { "search_key", R.styleable.Keyboard_iconSearchKey, "tab_key", R.styleable.Keyboard_iconTabKey, "shortcut_key", R.styleable.Keyboard_iconShortcutKey, + "shortcut_for_label", R.styleable.Keyboard_iconShortcutForLabel, "space_key_for_number_layout", R.styleable.Keyboard_iconSpaceKeyForNumberLayout, "shift_key_shifted", R.styleable.Keyboard_iconShiftKeyShifted, "shortcut_key_disabled", R.styleable.Keyboard_iconShortcutKeyDisabled, diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java index 1b722c5ce..c2a01b5e8 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java @@ -87,11 +87,11 @@ public final class KeyboardTextsSet { return (text == null) ? LANGUAGE_DEFAULT[id] : text; } - // These texts' name should be aligned with the @string/<name> in - // values*/strings-action-keys.xml. private static final String[] RESOURCE_NAMES = { + // These texts' name should be aligned with the @string/<name> in values/strings.xml. // Labels for action. "label_go_key", + // "label_search_key", "label_send_key", "label_next_key", "label_done_key", @@ -147,118 +147,111 @@ public final class KeyboardTextsSet { /* 42 */ "keylabel_for_south_slavic_row3_8", /* 43 */ "more_keys_for_cyrillic_ie", /* 44 */ "more_keys_for_cyrillic_i", - /* 45 */ "keylabel_for_swiss_row1_11", - /* 46 */ "keylabel_for_swiss_row2_10", - /* 47 */ "keylabel_for_swiss_row2_11", - /* 48 */ "more_keys_for_swiss_row1_11", - /* 49 */ "more_keys_for_swiss_row2_10", - /* 50 */ "more_keys_for_swiss_row2_11", - /* 51 */ "label_to_alpha_key", - /* 52 */ "single_quotes", - /* 53 */ "double_quotes", - /* 54 */ "single_angle_quotes", - /* 55 */ "double_angle_quotes", - /* 56 */ "more_keys_for_currency_dollar", - /* 57 */ "keylabel_for_currency", - /* 58 */ "more_keys_for_currency", - /* 59 */ "more_keys_for_punctuation", - /* 60 */ "more_keys_for_tablet_punctuation", - /* 61 */ "more_keys_for_star", - /* 62 */ "more_keys_for_bullet", - /* 63 */ "more_keys_for_plus", - /* 64 */ "more_keys_for_left_parenthesis", - /* 65 */ "more_keys_for_right_parenthesis", - /* 66 */ "more_keys_for_less_than", - /* 67 */ "more_keys_for_greater_than", - /* 68 */ "more_keys_for_arabic_diacritics", - /* 69 */ "keylabel_for_symbols_1", - /* 70 */ "keylabel_for_symbols_2", - /* 71 */ "keylabel_for_symbols_3", - /* 72 */ "keylabel_for_symbols_4", - /* 73 */ "keylabel_for_symbols_5", - /* 74 */ "keylabel_for_symbols_6", - /* 75 */ "keylabel_for_symbols_7", - /* 76 */ "keylabel_for_symbols_8", - /* 77 */ "keylabel_for_symbols_9", - /* 78 */ "keylabel_for_symbols_0", - /* 79 */ "label_to_symbol_key", - /* 80 */ "label_to_symbol_with_microphone_key", - /* 81 */ "additional_more_keys_for_symbols_1", - /* 82 */ "additional_more_keys_for_symbols_2", - /* 83 */ "additional_more_keys_for_symbols_3", - /* 84 */ "additional_more_keys_for_symbols_4", - /* 85 */ "additional_more_keys_for_symbols_5", - /* 86 */ "additional_more_keys_for_symbols_6", - /* 87 */ "additional_more_keys_for_symbols_7", - /* 88 */ "additional_more_keys_for_symbols_8", - /* 89 */ "additional_more_keys_for_symbols_9", - /* 90 */ "additional_more_keys_for_symbols_0", - /* 91 */ "more_keys_for_symbols_1", - /* 92 */ "more_keys_for_symbols_2", - /* 93 */ "more_keys_for_symbols_3", - /* 94 */ "more_keys_for_symbols_4", - /* 95 */ "more_keys_for_symbols_5", - /* 96 */ "more_keys_for_symbols_6", - /* 97 */ "more_keys_for_symbols_7", - /* 98 */ "more_keys_for_symbols_8", - /* 99 */ "more_keys_for_symbols_9", - /* 100 */ "more_keys_for_symbols_0", - /* 101 */ "keylabel_for_comma", - /* 102 */ "more_keys_for_comma", - /* 103 */ "keylabel_for_tablet_comma", - /* 104 */ "keyhintlabel_for_tablet_comma", - /* 105 */ "more_keys_for_tablet_comma", - /* 106 */ "keylabel_for_period", + /* 45 */ "label_to_alpha_key", + /* 46 */ "single_quotes", + /* 47 */ "double_quotes", + /* 48 */ "single_angle_quotes", + /* 49 */ "double_angle_quotes", + /* 50 */ "more_keys_for_currency_dollar", + /* 51 */ "keylabel_for_currency", + /* 52 */ "more_keys_for_currency", + /* 53 */ "more_keys_for_punctuation", + /* 54 */ "more_keys_for_star", + /* 55 */ "more_keys_for_bullet", + /* 56 */ "more_keys_for_plus", + /* 57 */ "more_keys_for_left_parenthesis", + /* 58 */ "more_keys_for_right_parenthesis", + /* 59 */ "more_keys_for_less_than", + /* 60 */ "more_keys_for_greater_than", + /* 61 */ "more_keys_for_arabic_diacritics", + /* 62 */ "keyhintlabel_for_arabic_diacritics", + /* 63 */ "keylabel_for_symbols_1", + /* 64 */ "keylabel_for_symbols_2", + /* 65 */ "keylabel_for_symbols_3", + /* 66 */ "keylabel_for_symbols_4", + /* 67 */ "keylabel_for_symbols_5", + /* 68 */ "keylabel_for_symbols_6", + /* 69 */ "keylabel_for_symbols_7", + /* 70 */ "keylabel_for_symbols_8", + /* 71 */ "keylabel_for_symbols_9", + /* 72 */ "keylabel_for_symbols_0", + /* 73 */ "label_to_symbol_key", + /* 74 */ "label_to_symbol_with_microphone_key", + /* 75 */ "additional_more_keys_for_symbols_1", + /* 76 */ "additional_more_keys_for_symbols_2", + /* 77 */ "additional_more_keys_for_symbols_3", + /* 78 */ "additional_more_keys_for_symbols_4", + /* 79 */ "additional_more_keys_for_symbols_5", + /* 80 */ "additional_more_keys_for_symbols_6", + /* 81 */ "additional_more_keys_for_symbols_7", + /* 82 */ "additional_more_keys_for_symbols_8", + /* 83 */ "additional_more_keys_for_symbols_9", + /* 84 */ "additional_more_keys_for_symbols_0", + /* 85 */ "more_keys_for_symbols_1", + /* 86 */ "more_keys_for_symbols_2", + /* 87 */ "more_keys_for_symbols_3", + /* 88 */ "more_keys_for_symbols_4", + /* 89 */ "more_keys_for_symbols_5", + /* 90 */ "more_keys_for_symbols_6", + /* 91 */ "more_keys_for_symbols_7", + /* 92 */ "more_keys_for_symbols_8", + /* 93 */ "more_keys_for_symbols_9", + /* 94 */ "more_keys_for_symbols_0", + /* 95 */ "keylabel_for_comma", + /* 96 */ "more_keys_for_comma", + /* 97 */ "keylabel_for_symbols_question", + /* 98 */ "keylabel_for_symbols_semicolon", + /* 99 */ "keylabel_for_symbols_percent", + /* 100 */ "more_keys_for_symbols_exclamation", + /* 101 */ "more_keys_for_symbols_question", + /* 102 */ "more_keys_for_symbols_semicolon", + /* 103 */ "more_keys_for_symbols_percent", + /* 104 */ "keylabel_for_tablet_comma", + /* 105 */ "keyhintlabel_for_tablet_comma", + /* 106 */ "more_keys_for_tablet_comma", /* 107 */ "keyhintlabel_for_period", /* 108 */ "more_keys_for_period", - /* 109 */ "keylabel_for_tablet_period", - /* 110 */ "keyhintlabel_for_tablet_period", - /* 111 */ "more_keys_for_tablet_period", - /* 112 */ "keylabel_for_symbols_question", - /* 113 */ "keylabel_for_symbols_semicolon", - /* 114 */ "keylabel_for_symbols_percent", - /* 115 */ "more_keys_for_exclamation", - /* 116 */ "more_keys_for_question", - /* 117 */ "more_keys_for_symbols_semicolon", - /* 118 */ "more_keys_for_symbols_percent", - /* 119 */ "more_keys_for_q", - /* 120 */ "more_keys_for_x", - /* 121 */ "keylabel_for_q", - /* 122 */ "keylabel_for_w", - /* 123 */ "keylabel_for_y", - /* 124 */ "keylabel_for_x", - /* 125 */ "keylabel_for_spanish_row2_10", - /* 126 */ "more_keys_for_am_pm", - /* 127 */ "settings_as_more_key", - /* 128 */ "shortcut_as_more_key", - /* 129 */ "action_next_as_more_key", - /* 130 */ "action_previous_as_more_key", - /* 131 */ "label_to_more_symbol_key", - /* 132 */ "label_to_more_symbol_for_tablet_key", - /* 133 */ "label_tab_key", - /* 134 */ "label_to_phone_numeric_key", - /* 135 */ "label_to_phone_symbols_key", - /* 136 */ "label_time_am", - /* 137 */ "label_time_pm", - /* 138 */ "keylabel_for_popular_domain", - /* 139 */ "more_keys_for_popular_domain", - /* 140 */ "more_keys_for_smiley", - /* 141 */ "single_laqm_raqm", - /* 142 */ "single_laqm_raqm_rtl", - /* 143 */ "single_raqm_laqm", - /* 144 */ "double_laqm_raqm", - /* 145 */ "double_laqm_raqm_rtl", - /* 146 */ "double_raqm_laqm", - /* 147 */ "single_lqm_rqm", - /* 148 */ "single_9qm_lqm", - /* 149 */ "single_9qm_rqm", - /* 150 */ "double_lqm_rqm", - /* 151 */ "double_9qm_lqm", - /* 152 */ "double_9qm_rqm", - /* 153 */ "more_keys_for_single_quote", - /* 154 */ "more_keys_for_double_quote", - /* 155 */ "more_keys_for_tablet_double_quote", - /* 156 */ "emoji_key_as_more_key", + /* 109 */ "keylabel_for_apostrophe", + /* 110 */ "keyhintlabel_for_apostrophe", + /* 111 */ "more_keys_for_apostrophe", + /* 112 */ "more_keys_for_q", + /* 113 */ "more_keys_for_x", + /* 114 */ "keylabel_for_q", + /* 115 */ "keylabel_for_w", + /* 116 */ "keylabel_for_y", + /* 117 */ "keylabel_for_x", + /* 118 */ "keylabel_for_spanish_row2_10", + /* 119 */ "more_keys_for_am_pm", + /* 120 */ "settings_as_more_key", + /* 121 */ "shortcut_as_more_key", + /* 122 */ "action_next_as_more_key", + /* 123 */ "action_previous_as_more_key", + /* 124 */ "label_to_more_symbol_key", + /* 125 */ "label_to_more_symbol_for_tablet_key", + /* 126 */ "label_tab_key", + /* 127 */ "label_to_phone_numeric_key", + /* 128 */ "label_to_phone_symbols_key", + /* 129 */ "label_time_am", + /* 130 */ "label_time_pm", + /* 131 */ "keylabel_for_popular_domain", + /* 132 */ "more_keys_for_popular_domain", + /* 133 */ "more_keys_for_smiley", + /* 134 */ "single_laqm_raqm", + /* 135 */ "single_laqm_raqm_rtl", + /* 136 */ "single_raqm_laqm", + /* 137 */ "double_laqm_raqm", + /* 138 */ "double_laqm_raqm_rtl", + /* 139 */ "double_raqm_laqm", + /* 140 */ "single_lqm_rqm", + /* 141 */ "single_9qm_lqm", + /* 142 */ "single_9qm_rqm", + /* 143 */ "double_lqm_rqm", + /* 144 */ "double_9qm_lqm", + /* 145 */ "double_9qm_rqm", + /* 146 */ "more_keys_for_single_quote", + /* 147 */ "more_keys_for_double_quote", + /* 148 */ "more_keys_for_tablet_double_quote", + /* 149 */ "emoji_key_as_more_key", }; private static final String EMPTY = ""; @@ -269,148 +262,145 @@ public final class KeyboardTextsSet { EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, - EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, - /* ~50 */ + EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, + /* ~44 */ // Label for "switch to alphabetic" key. - /* 51 */ "ABC", - /* 52 */ "!text/single_lqm_rqm", - /* 53 */ "!text/double_lqm_rqm", - /* 54 */ "!text/single_laqm_raqm", - /* 55 */ "!text/double_laqm_raqm", + /* 45 */ "ABC", + /* 46 */ "!text/single_lqm_rqm", + /* 47 */ "!text/double_lqm_rqm", + /* 48 */ "!text/single_laqm_raqm", + /* 49 */ "!text/double_laqm_raqm", // U+00A2: "¢" CENT SIGN // U+00A3: "£" POUND SIGN // U+20AC: "€" EURO SIGN // U+00A5: "¥" YEN SIGN // U+20B1: "₱" PESO SIGN - /* 56 */ "\u00A2,\u00A3,\u20AC,\u00A5,\u20B1", - /* 57 */ "$", - /* 58 */ "$,\u00A2,\u20AC,\u00A3,\u00A5,\u20B1", - /* 59 */ "!fixedColumnOrder!8,;,/,(,),#,!,\\,,?,&,\\%,+,\",-,:,',@", - /* 60 */ "!fixedColumnOrder!7,;,/,(,),#,',\\,,&,\\%,+,\",-,:,@", + /* 50 */ "\u00A2,\u00A3,\u20AC,\u00A5,\u20B1", + /* 51 */ "$", + /* 52 */ "$,\u00A2,\u20AC,\u00A3,\u00A5,\u20B1", + /* 53 */ "!fixedColumnOrder!8,;,/,(,),#,!,\\,,?,&,\\%,+,\",-,:,',@", // U+2020: "†" DAGGER // U+2021: "‡" DOUBLE DAGGER // U+2605: "★" BLACK STAR - /* 61 */ "\u2020,\u2021,\u2605", + /* 54 */ "\u2020,\u2021,\u2605", // U+266A: "♪" EIGHTH NOTE // U+2665: "♥" BLACK HEART SUIT // U+2660: "♠" BLACK SPADE SUIT // U+2666: "♦" BLACK DIAMOND SUIT // U+2663: "♣" BLACK CLUB SUIT - /* 62 */ "\u266A,\u2665,\u2660,\u2666,\u2663", + /* 55 */ "\u266A,\u2665,\u2660,\u2666,\u2663", // U+00B1: "±" PLUS-MINUS SIGN - /* 63 */ "\u00B1", + /* 56 */ "\u00B1", // The all letters need to be mirrored are found at // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt - /* 64 */ "!fixedColumnOrder!3,<,{,[", - /* 65 */ "!fixedColumnOrder!3,>,},]", + /* 57 */ "!fixedColumnOrder!3,<,{,[", + /* 58 */ "!fixedColumnOrder!3,>,},]", // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK // U+2264: "≤" LESS-THAN OR EQUAL TO // U+2265: "≥" GREATER-THAN EQUAL TO // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK - /* 66 */ "!fixedColumnOrder!3,\u2039,\u2264,\u00AB", - /* 67 */ "!fixedColumnOrder!3,\u203A,\u2265,\u00BB", - /* 68 */ EMPTY, - /* 69 */ "1", - /* 70 */ "2", - /* 71 */ "3", - /* 72 */ "4", - /* 73 */ "5", - /* 74 */ "6", - /* 75 */ "7", - /* 76 */ "8", - /* 77 */ "9", - /* 78 */ "0", + /* 59 */ "!fixedColumnOrder!3,\u2039,\u2264,\u00AB", + /* 60 */ "!fixedColumnOrder!3,\u203A,\u2265,\u00BB", + /* 61 */ EMPTY, + /* 62 */ EMPTY, + /* 63 */ "1", + /* 64 */ "2", + /* 65 */ "3", + /* 66 */ "4", + /* 67 */ "5", + /* 68 */ "6", + /* 69 */ "7", + /* 70 */ "8", + /* 71 */ "9", + /* 72 */ "0", // Label for "switch to symbols" key. - /* 79 */ "?123", + /* 73 */ "?123", // Label for "switch to symbols with microphone" key. This string shouldn't include the "mic" // part because it'll be appended by the code. - /* 80 */ "123", - /* 81~ */ + /* 74 */ "123", + /* 75~ */ EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, - /* ~90 */ + /* ~84 */ // U+00B9: "¹" SUPERSCRIPT ONE // U+00BD: "½" VULGAR FRACTION ONE HALF // U+2153: "⅓" VULGAR FRACTION ONE THIRD // U+00BC: "¼" VULGAR FRACTION ONE QUARTER // U+215B: "⅛" VULGAR FRACTION ONE EIGHTH - /* 91 */ "\u00B9,\u00BD,\u2153,\u00BC,\u215B", + /* 85 */ "\u00B9,\u00BD,\u2153,\u00BC,\u215B", // U+00B2: "²" SUPERSCRIPT TWO // U+2154: "⅔" VULGAR FRACTION TWO THIRDS - /* 92 */ "\u00B2,\u2154", + /* 86 */ "\u00B2,\u2154", // U+00B3: "³" SUPERSCRIPT THREE // U+00BE: "¾" VULGAR FRACTION THREE QUARTERS // U+215C: "⅜" VULGAR FRACTION THREE EIGHTHS - /* 93 */ "\u00B3,\u00BE,\u215C", + /* 87 */ "\u00B3,\u00BE,\u215C", // U+2074: "⁴" SUPERSCRIPT FOUR - /* 94 */ "\u2074", + /* 88 */ "\u2074", // U+215D: "⅝" VULGAR FRACTION FIVE EIGHTHS - /* 95 */ "\u215D", - /* 96 */ EMPTY, + /* 89 */ "\u215D", + /* 90 */ EMPTY, // U+215E: "⅞" VULGAR FRACTION SEVEN EIGHTHS - /* 97 */ "\u215E", - /* 98 */ EMPTY, - /* 99 */ EMPTY, + /* 91 */ "\u215E", + /* 92 */ EMPTY, + /* 93 */ EMPTY, // U+207F: "ⁿ" SUPERSCRIPT LATIN SMALL LETTER N // U+2205: "∅" EMPTY SET - /* 100 */ "\u207F,\u2205", - // Comma key - /* 101 */ ",", - /* 102 */ EMPTY, - /* 103 */ ",", - /* 104 */ EMPTY, - /* 105 */ EMPTY, - // Period key - /* 106 */ ".", - /* 107 */ EMPTY, - /* 108 */ "!text/more_keys_for_punctuation", - /* 109 */ ".", - /* 110 */ EMPTY, - /* 111 */ "!text/more_keys_for_tablet_punctuation", - /* 112 */ "?", - /* 113 */ ";", - /* 114 */ "%", + /* 94 */ "\u207F,\u2205", + /* 95 */ ",", + /* 96 */ EMPTY, + /* 97 */ "?", + /* 98 */ ";", + /* 99 */ "%", // U+00A1: "¡" INVERTED EXCLAMATION MARK - /* 115 */ "\u00A1", + /* 100 */ "\u00A1", // U+00BF: "¿" INVERTED QUESTION MARK - /* 116 */ "\u00BF", - /* 117 */ EMPTY, + /* 101 */ "\u00BF", + /* 102 */ EMPTY, // U+2030: "‰" PER MILLE SIGN - /* 118 */ "\u2030", - /* 119 */ EMPTY, - /* 120 */ EMPTY, - /* 121 */ "q", - /* 122 */ "w", - /* 123 */ "y", - /* 124 */ "x", - // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE - /* 125 */ "\u00F1", - /* 126 */ "!fixedColumnOrder!2,!hasLabels!,!text/label_time_am,!text/label_time_pm", - /* 127 */ "!icon/settings_key|!code/key_settings", - /* 128 */ "!icon/shortcut_key|!code/key_shortcut", - /* 129 */ "!hasLabels!,!text/label_next_key|!code/key_action_next", - /* 130 */ "!hasLabels!,!text/label_previous_key|!code/key_action_previous", + /* 103 */ "\u2030", + /* 104 */ ",", + /* 105~ */ + EMPTY, EMPTY, EMPTY, + /* ~107 */ + // U+2026: "…" HORIZONTAL ELLIPSIS + /* 108 */ "\u2026", + /* 109 */ "\'", + /* 110 */ "\"", + /* 111 */ "\"", + /* 112 */ EMPTY, + /* 113 */ EMPTY, + /* 114 */ "q", + /* 115 */ "w", + /* 116 */ "y", + /* 117 */ "x", + /* 118 */ EMPTY, + /* 119 */ "!fixedColumnOrder!2,!hasLabels!,!text/label_time_am,!text/label_time_pm", + /* 120 */ "!icon/settings_key|!code/key_settings", + /* 121 */ "!icon/shortcut_key|!code/key_shortcut", + /* 122 */ "!hasLabels!,!text/label_next_key|!code/key_action_next", + /* 123 */ "!hasLabels!,!text/label_previous_key|!code/key_action_previous", // Label for "switch to more symbol" modifier key. Must be short to fit on key! - /* 131 */ "= \\ <", + /* 124 */ "= \\ <", // Label for "switch to more symbol" modifier key on tablets. Must be short to fit on key! - /* 132 */ "~ [ <", + /* 125 */ "~ [ <", // Label for "Tab" key. Must be short to fit on key! - /* 133 */ "Tab", + /* 126 */ "Tab", // Label for "switch to phone numeric" key. Must be short to fit on key! - /* 134 */ "123", + /* 127 */ "123", // Label for "switch to phone symbols" key. Must be short to fit on key! // U+FF0A: "*" FULLWIDTH ASTERISK // U+FF03: "#" FULLWIDTH NUMBER SIGN - /* 135 */ "\uFF0A\uFF03", + /* 128 */ "\uFF0A\uFF03", // Key label for "ante meridiem" - /* 136 */ "AM", + /* 129 */ "AM", // Key label for "post meridiem" - /* 137 */ "PM", - /* 138 */ ".com", + /* 130 */ "PM", + /* 131 */ ".com", // popular web domains for the locale - most popular, displayed on the keyboard - /* 139 */ "!hasLabels!,.net,.org,.gov,.edu", - /* 140 */ "!fixedColumnOrder!5,!hasLabels!,=-O|=-O ,:-P|:-P ,;-)|;-) ,:-(|:-( ,:-)|:-) ,:-!|:-! ,:-$|:-$ ,B-)|B-) ,:O|:O ,:-*|:-* ,:-D|:-D ,:\'(|:\'( ,:-\\\\|:-\\\\ ,O:-)|O:-) ,:-[|:-[ ", + /* 132 */ "!hasLabels!,.net,.org,.gov,.edu", + /* 133 */ "!fixedColumnOrder!5,!hasLabels!,=-O|=-O ,:-P|:-P ,;-)|;-) ,:-(|:-( ,:-)|:-) ,:-!|:-! ,:-$|:-$ ,B-)|B-) ,:O|:O ,:-*|:-* ,:-D|:-D ,:\'(|:\'( ,:-\\\\|:-\\\\ ,O:-)|O:-) ,:-[|:-[ ", // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK @@ -432,25 +422,25 @@ public final class KeyboardTextsSet { // The following each quotation mark pair consist of // <opening quotation mark>, <closing quotation mark> // and is named after (single|double)_<opening quotation mark>_<closing quotation mark>. - /* 141 */ "\u2039,\u203A", - /* 142 */ "\u2039|\u203A,\u203A|\u2039", - /* 143 */ "\u203A,\u2039", - /* 144 */ "\u00AB,\u00BB", - /* 145 */ "\u00AB|\u00BB,\u00BB|\u00AB", - /* 146 */ "\u00BB,\u00AB", + /* 134 */ "\u2039,\u203A", + /* 135 */ "\u2039|\u203A,\u203A|\u2039", + /* 136 */ "\u203A,\u2039", + /* 137 */ "\u00AB,\u00BB", + /* 138 */ "\u00AB|\u00BB,\u00BB|\u00AB", + /* 139 */ "\u00BB,\u00AB", // The following each quotation mark triplet consists of // <another quotation mark>, <opening quotation mark>, <closing quotation mark> // and is named after (single|double)_<opening quotation mark>_<closing quotation mark>. - /* 147 */ "\u201A,\u2018,\u2019", - /* 148 */ "\u2019,\u201A,\u2018", - /* 149 */ "\u2018,\u201A,\u2019", - /* 150 */ "\u201E,\u201C,\u201D", - /* 151 */ "\u201D,\u201E,\u201C", - /* 152 */ "\u201C,\u201E,\u201D", - /* 153 */ "!fixedColumnOrder!5,!text/single_quotes,!text/single_angle_quotes", - /* 154 */ "!fixedColumnOrder!5,!text/double_quotes,!text/double_angle_quotes", - /* 155 */ "!fixedColumnOrder!6,!text/double_quotes,!text/single_quotes,!text/double_angle_quotes,!text/single_angle_quotes", - /* 156 */ "!icon/emoji_key|!code/key_emoji", + /* 140 */ "\u201A,\u2018,\u2019", + /* 141 */ "\u2019,\u201A,\u2018", + /* 142 */ "\u2018,\u201A,\u2019", + /* 143 */ "\u201E,\u201C,\u201D", + /* 144 */ "\u201D,\u201E,\u201C", + /* 145 */ "\u201C,\u201E,\u201D", + /* 146 */ "!fixedColumnOrder!5,!text/single_quotes,!text/single_angle_quotes", + /* 147 */ "!fixedColumnOrder!5,!text/double_quotes,!text/double_angle_quotes", + /* 148 */ "!fixedColumnOrder!6,!text/double_quotes,!text/single_quotes,!text/double_angle_quotes,!text/single_angle_quotes", + /* 149 */ "!icon/emoji_key|!code/key_emoji", }; /* Language af: Afrikaans */ @@ -512,43 +502,44 @@ public final class KeyboardTextsSet { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~50 */ + /* ~44 */ // Label for "switch to alphabetic" key. // U+0623: "ا" ARABIC LETTER ALEF // U+200C: ZERO WIDTH NON-JOINER // U+0628: "ب" ARABIC LETTER BEH // U+062C: "پ" ARABIC LETTER PEH - /* 51 */ "\u0623\u200C\u0628\u200C\u062C", - /* 52 */ null, - /* 53 */ null, - /* 54 */ "!text/single_laqm_raqm_rtl", - /* 55 */ "!text/double_laqm_raqm_rtl", - /* 56~ */ + /* 45 */ "\u0623\u200C\u0628\u200C\u062C", + /* 46 */ null, + /* 47 */ null, + /* 48 */ "!text/single_laqm_raqm_rtl", + /* 49 */ "!text/double_laqm_raqm_rtl", + /* 50~ */ null, null, null, - /* ~58 */ - /* 59 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(|),)|(", - /* 60 */ null, + /* ~52 */ + // U+061F: "؟" ARABIC QUESTION MARK + // U+060C: "،" ARABIC COMMA + // U+061B: "؛" ARABIC SEMICOLON + /* 53 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(|),)|(", // U+2605: "★" BLACK STAR // U+066D: "٭" ARABIC FIVE POINTED STAR - /* 61 */ "\u2605,\u066D", + /* 54 */ "\u2605,\u066D", // U+266A: "♪" EIGHTH NOTE - /* 62 */ "\u266A", - /* 63 */ null, + /* 55 */ "\u266A", + /* 56 */ null, // The all letters need to be mirrored are found at // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt // U+FD3E: "﴾" ORNATE LEFT PARENTHESIS // U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS - /* 64 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]", - /* 65 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[", + /* 57 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]", + /* 58 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[", // U+2264: "≤" LESS-THAN OR EQUAL TO // U+2265: "≥" GREATER-THAN EQUAL TO // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - /* 66 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB", - /* 67 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB", + /* 59 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB", + /* 60 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB", // U+0655: "ٕ" ARABIC HAMZA BELOW // U+0654: "ٔ" ARABIC HAMZA ABOVE // U+0652: "ْ" ARABIC SUKUN @@ -565,74 +556,70 @@ public final class KeyboardTextsSet { // U+0640: "ـ" ARABIC TATWEEL // In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label. // Note: The space character is needed as a preceding letter to draw Arabic diacritics characters correctly. - /* 68 */ "!fixedColumnOrder!7, \u0655|\u0655, \u0654|\u0654, \u0652|\u0652, \u064D|\u064D, \u064C|\u064C, \u064B|\u064B, \u0651|\u0651, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u0650|\u0650, \u064F|\u064F, \u064E|\u064E,\u0640\u0640\u0640|\u0640", + /* 61 */ "!fixedColumnOrder!7, \u0655|\u0655, \u0654|\u0654, \u0652|\u0652, \u064D|\u064D, \u064C|\u064C, \u064B|\u064B, \u0651|\u0651, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u0650|\u0650, \u064F|\u064F, \u064E|\u064E,\u0640\u0640\u0640|\u0640", + /* 62 */ "\u0651", // U+0661: "١" ARABIC-INDIC DIGIT ONE - /* 69 */ "\u0661", + /* 63 */ "\u0661", // U+0662: "٢" ARABIC-INDIC DIGIT TWO - /* 70 */ "\u0662", + /* 64 */ "\u0662", // U+0663: "٣" ARABIC-INDIC DIGIT THREE - /* 71 */ "\u0663", + /* 65 */ "\u0663", // U+0664: "٤" ARABIC-INDIC DIGIT FOUR - /* 72 */ "\u0664", + /* 66 */ "\u0664", // U+0665: "٥" ARABIC-INDIC DIGIT FIVE - /* 73 */ "\u0665", + /* 67 */ "\u0665", // U+0666: "٦" ARABIC-INDIC DIGIT SIX - /* 74 */ "\u0666", + /* 68 */ "\u0666", // U+0667: "٧" ARABIC-INDIC DIGIT SEVEN - /* 75 */ "\u0667", + /* 69 */ "\u0667", // U+0668: "٨" ARABIC-INDIC DIGIT EIGHT - /* 76 */ "\u0668", + /* 70 */ "\u0668", // U+0669: "٩" ARABIC-INDIC DIGIT NINE - /* 77 */ "\u0669", + /* 71 */ "\u0669", // U+0660: "٠" ARABIC-INDIC DIGIT ZERO - /* 78 */ "\u0660", + /* 72 */ "\u0660", // Label for "switch to symbols" key. // U+061F: "؟" ARABIC QUESTION MARK - /* 79 */ "\u0663\u0662\u0661\u061F", + /* 73 */ "\u0663\u0662\u0661\u061F", // Label for "switch to symbols with microphone" key. This string shouldn't include the "mic" // part because it'll be appended by the code. - /* 80 */ "\u0663\u0662\u0661", - /* 81 */ "1", - /* 82 */ "2", - /* 83 */ "3", - /* 84 */ "4", - /* 85 */ "5", - /* 86 */ "6", - /* 87 */ "7", - /* 88 */ "8", - /* 89 */ "9", + /* 74 */ "\u0663\u0662\u0661", + /* 75 */ "1", + /* 76 */ "2", + /* 77 */ "3", + /* 78 */ "4", + /* 79 */ "5", + /* 80 */ "6", + /* 81 */ "7", + /* 82 */ "8", + /* 83 */ "9", // U+066B: "٫" ARABIC DECIMAL SEPARATOR // U+066C: "٬" ARABIC THOUSANDS SEPARATOR - /* 90 */ "0,\u066B,\u066C", - /* 91~ */ + /* 84 */ "0,\u066B,\u066C", + /* 85~ */ null, null, null, null, null, null, null, null, null, null, - /* ~100 */ + /* ~94 */ // U+060C: "،" ARABIC COMMA - /* 101 */ "\u060C", - /* 102 */ "\\,", - // U+061F: "؟" ARABIC QUESTION MARK - // U+060C: "،" ARABIC COMMA - // U+061B: "؛" ARABIC SEMICOLON - /* 103 */ "\u060C", - /* 104 */ "\u061F", - /* 105 */ "!fixedColumnOrder!4,:,!,\u061F,\u061B,-,/,\",\'", - /* 106 */ null, - // U+0651: "ّ" ARABIC SHADDA - /* 107 */ "\u0651", - /* 108 */ "!text/more_keys_for_arabic_diacritics", - /* 109 */ null, - /* 110 */ "\u0651", - /* 111 */ "!text/more_keys_for_arabic_diacritics", - /* 112 */ "\u061F", - /* 113 */ "\u061B", + /* 95 */ "\u060C", + /* 96 */ "\\,", + /* 97 */ "\u061F", + /* 98 */ "\u061B", // U+066A: "٪" ARABIC PERCENT SIGN - /* 114 */ "\u066A", - /* 115 */ null, - // U+00BF: "¿" INVERTED QUESTION MARK - /* 116 */ "?,\u00BF", - /* 117 */ ";", + /* 99 */ "\u066A", + /* 100 */ null, + /* 101 */ "?", + /* 102 */ ";", // U+2030: "‰" PER MILLE SIGN - /* 118 */ "\\%,\u2030", + /* 103 */ "\\%,\u2030", + /* 104~ */ + null, null, null, null, null, + /* ~108 */ + // U+060C: "،" ARABIC COMMA + // U+061B: "؛" ARABIC SEMICOLON + // U+061F: "؟" ARABIC QUESTION MARK + /* 109 */ "\u060C", + /* 110 */ "\u061F", + /* 111 */ "\u061F,\u061B,!,:,-,/,\',\"", }; /* Language az: Azerbaijani */ @@ -681,8 +668,8 @@ public final class KeyboardTextsSet { /* 15 */ "\u011F", }; - /* Language be_BY: Belarusian (Belarus) */ - private static final String[] LANGUAGE_be_BY = { + /* Language be: Belarusian */ + private static final String[] LANGUAGE_be = { /* 0~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, @@ -707,16 +694,14 @@ public final class KeyboardTextsSet { /* ~42 */ // U+0451: "ё" CYRILLIC SMALL LETTER IO /* 43 */ "\u0451", - /* 44~ */ - null, null, null, null, null, null, null, - /* ~50 */ + /* 44 */ null, // Label for "switch to alphabetic" key. // U+0410: "А" CYRILLIC CAPITAL LETTER A // U+0411: "Б" CYRILLIC CAPITAL LETTER BE // U+0412: "В" CYRILLIC CAPITAL LETTER VE - /* 51 */ "\u0410\u0411\u0412", - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", + /* 45 */ "\u0410\u0411\u0412", + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", }; /* Language bg: Bulgarian */ @@ -725,16 +710,15 @@ public final class KeyboardTextsSet { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~50 */ + /* ~44 */ // Label for "switch to alphabetic" key. // U+0410: "А" CYRILLIC CAPITAL LETTER A // U+0411: "Б" CYRILLIC CAPITAL LETTER BE // U+0412: "В" CYRILLIC CAPITAL LETTER VE - /* 51 */ "\u0410\u0411\u0412", - /* 52 */ null, + /* 45 */ "\u0410\u0411\u0412", + /* 46 */ null, // single_quotes of Bulgarian is default single_quotes_right_left. - /* 53 */ "!text/double_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", }; /* Language ca: Catalan */ @@ -798,20 +782,22 @@ public final class KeyboardTextsSet { /* 15~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, null, null, - /* ~58 */ + null, null, null, null, null, null, null, null, + /* ~52 */ // U+00B7: "·" MIDDLE DOT - /* 59 */ "!fixedColumnOrder!9,;,/,(,),#,\u00B7,!,\\,,?,&,\\%,+,\",-,:,',@", - /* 60 */ "!fixedColumnOrder!8,;,/,(,),#,\u00B7,',\\,,&,\\%,+,\",-,:,@", - /* 61~ */ - null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + /* 53 */ "!fixedColumnOrder!9,;,/,(,),#,\u00B7,!,\\,,?,&,\\%,+,\",-,:,',@", + /* 54~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, - /* ~124 */ + null, null, null, null, null, null, null, null, null, + /* ~107 */ + /* 108 */ "?,\u00B7", + /* 109~ */ + null, null, null, null, null, null, null, null, null, + /* ~117 */ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA - /* 125 */ "\u00E7", + /* 118 */ "\u00E7", }; /* Language cs: Czech */ @@ -885,12 +871,12 @@ public final class KeyboardTextsSet { /* 13~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, - /* ~51 */ - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", - /* 54 */ "!text/single_raqm_laqm", - /* 55 */ "!text/double_raqm_laqm", + null, null, null, + /* ~45 */ + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", + /* 48 */ "!text/single_raqm_laqm", + /* 49 */ "!text/double_raqm_laqm", }; /* Language da: Danish */ @@ -954,12 +940,12 @@ public final class KeyboardTextsSet { /* 24 */ "\u00F6", /* 25~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - /* ~51 */ - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", - /* 54 */ "!text/single_raqm_laqm", - /* 55 */ "!text/double_raqm_laqm", + null, null, null, null, null, null, + /* ~45 */ + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", + /* 48 */ "!text/single_raqm_laqm", + /* 49 */ "!text/double_raqm_laqm", }; /* Language de: German */ @@ -1005,25 +991,12 @@ public final class KeyboardTextsSet { /* 7~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, - /* ~44 */ - // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS - /* 45 */ "\u00FC", - // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS - /* 46 */ "\u00F6", - // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS - /* 47 */ "\u00E4", - // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE - /* 48 */ "\u00E8", - // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE - /* 49 */ "\u00E9", - // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE - /* 50 */ "\u00E0", - /* 51 */ null, - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", - /* 54 */ "!text/single_raqm_laqm", - /* 55 */ "!text/double_raqm_laqm", + null, null, null, null, null, null, null, null, null, + /* ~45 */ + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", + /* 48 */ "!text/single_raqm_laqm", + /* 49 */ "!text/double_raqm_laqm", }; /* Language el: Greek */ @@ -1032,13 +1005,12 @@ public final class KeyboardTextsSet { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~50 */ + /* ~44 */ // Label for "switch to alphabetic" key. // U+0391: "Α" GREEK CAPITAL LETTER ALPHA // U+0392: "Β" GREEK CAPITAL LETTER BETA // U+0393: "Γ" GREEK CAPITAL LETTER GAMMA - /* 51 */ "\u0391\u0392\u0393", + /* 45 */ "\u0391\u0392\u0393", }; /* Language en: English */ @@ -1210,20 +1182,20 @@ public final class KeyboardTextsSet { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, - /* ~118 */ - /* 119 */ "q", - /* 120 */ "x", + null, null, + /* ~111 */ + /* 112 */ "q", + /* 113 */ "x", // U+015D: "ŝ" LATIN SMALL LETTER S WITH CIRCUMFLEX - /* 121 */ "\u015D", + /* 114 */ "\u015D", // U+011D: "ĝ" LATIN SMALL LETTER G WITH CIRCUMFLEX - /* 122 */ "\u011D", + /* 115 */ "\u011D", // U+016D: "ŭ" LATIN SMALL LETTER U WITH BREVE - /* 123 */ "\u016D", + /* 116 */ "\u016D", // U+0109: "ĉ" LATIN SMALL LETTER C WITH CIRCUMFLEX - /* 124 */ "\u0109", + /* 117 */ "\u0109", // U+0135: "ĵ" LATIN SMALL LETTER J WITH CIRCUMFLEX - /* 125 */ "\u0135", + /* 118 */ "\u0135", }; /* Language es: Spanish */ @@ -1282,15 +1254,33 @@ public final class KeyboardTextsSet { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~58 */ + /* ~52 */ // U+00A1: "¡" INVERTED EXCLAMATION MARK // U+00BF: "¿" INVERTED QUESTION MARK - /* 59 */ "!fixedColumnOrder!9,\u00A1,;,/,(,),#,!,\\,,?,\u00BF,&,\\%,+,\",-,:,',@", + /* 53 */ "!fixedColumnOrder!4,;,!,\\,,?,:,\u00A1,@,\u00BF", + /* 54~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, + /* ~105 */ + // U+00A1: "¡" INVERTED EXCLAMATION MARK + /* 106 */ "!,\u00A1", + /* 107 */ null, + // U+00BF: "¿" INVERTED QUESTION MARK + /* 108 */ "?,\u00BF", + /* 109 */ "\"", + /* 110 */ "\'", + /* 111 */ "\'", + /* 112~ */ + null, null, null, null, null, null, + /* ~117 */ + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + /* 118 */ "\u00F1", }; - /* Language et_EE: Estonian (Estonia) */ - private static final String[] LANGUAGE_et_EE = { + /* Language et: Estonian */ + private static final String[] LANGUAGE_et = { // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE @@ -1389,10 +1379,10 @@ public final class KeyboardTextsSet { /* 23 */ "\u00F5", /* 24~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, null, - /* ~51 */ - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", + null, null, null, null, null, null, null, + /* ~45 */ + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", }; /* Language fa: Persian */ @@ -1401,47 +1391,45 @@ public final class KeyboardTextsSet { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~50 */ + /* ~44 */ // Label for "switch to alphabetic" key. // U+0627: "ا" ARABIC LETTER ALEF // U+200C: ZERO WIDTH NON-JOINER // U+0628: "ب" ARABIC LETTER BEH // U+067E: "پ" ARABIC LETTER PEH - /* 51 */ "\u0627\u200C\u0628\u200C\u067E", - /* 52 */ null, - /* 53 */ null, - /* 54 */ "!text/single_laqm_raqm_rtl", - /* 55 */ "!text/double_laqm_raqm_rtl", - /* 56 */ null, + /* 45 */ "\u0627\u200C\u0628\u200C\u067E", + /* 46 */ null, + /* 47 */ null, + /* 48 */ "!text/single_laqm_raqm_rtl", + /* 49 */ "!text/double_laqm_raqm_rtl", + /* 50 */ null, // U+FDFC: "﷼" RIAL SIGN - /* 57 */ "\uFDFC", - /* 58 */ null, + /* 51 */ "\uFDFC", + /* 52 */ null, // U+061F: "؟" ARABIC QUESTION MARK // U+060C: "،" ARABIC COMMA // U+061B: "؛" ARABIC SEMICOLON - /* 59 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(|),)|(", - /* 60 */ null, + /* 53 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(|),)|(", // U+2605: "★" BLACK STAR // U+066D: "٭" ARABIC FIVE POINTED STAR - /* 61 */ "\u2605,\u066D", + /* 54 */ "\u2605,\u066D", // U+266A: "♪" EIGHTH NOTE - /* 62 */ "\u266A", - /* 63 */ null, + /* 55 */ "\u266A", + /* 56 */ null, // The all letters need to be mirrored are found at // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt // U+FD3E: "﴾" ORNATE LEFT PARENTHESIS // U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS - /* 64 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]", - /* 65 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[", + /* 57 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]", + /* 58 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[", // U+2264: "≤" LESS-THAN OR EQUAL TO // U+2265: "≥" GREATER-THAN EQUAL TO // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - /* 66 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,<|>", - /* 67 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,>|<", + /* 59 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,<|>", + /* 60 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,>|<", // U+0655: "ٕ" ARABIC HAMZA BELOW // U+0652: "ْ" ARABIC SUKUN // U+0651: "ّ" ARABIC SHADDA @@ -1458,75 +1446,74 @@ public final class KeyboardTextsSet { // U+0640: "ـ" ARABIC TATWEEL // In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label. // Note: The space character is needed as a preceding letter to draw Arabic diacritics characters correctly. - /* 68 */ "!fixedColumnOrder!7, \u0655|\u0655, \u0652|\u0652, \u0651|\u0651, \u064C|\u064C, \u064D|\u064D, \u064B|\u064B, \u0654|\u0654, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u064F|\u064F, \u0650|\u0650, \u064E|\u064E,\u0640\u0640\u0640|\u0640", + /* 61 */ "!fixedColumnOrder!7, \u0655|\u0655, \u0652|\u0652, \u0651|\u0651, \u064C|\u064C, \u064D|\u064D, \u064B|\u064B, \u0654|\u0654, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u064F|\u064F, \u0650|\u0650, \u064E|\u064E,\u0640\u0640\u0640|\u0640", + /* 62 */ "\u064B", // U+06F1: "۱" EXTENDED ARABIC-INDIC DIGIT ONE - /* 69 */ "\u06F1", + /* 63 */ "\u06F1", // U+06F2: "۲" EXTENDED ARABIC-INDIC DIGIT TWO - /* 70 */ "\u06F2", + /* 64 */ "\u06F2", // U+06F3: "۳" EXTENDED ARABIC-INDIC DIGIT THREE - /* 71 */ "\u06F3", + /* 65 */ "\u06F3", // U+06F4: "۴" EXTENDED ARABIC-INDIC DIGIT FOUR - /* 72 */ "\u06F4", + /* 66 */ "\u06F4", // U+06F5: "۵" EXTENDED ARABIC-INDIC DIGIT FIVE - /* 73 */ "\u06F5", + /* 67 */ "\u06F5", // U+06F6: "۶" EXTENDED ARABIC-INDIC DIGIT SIX - /* 74 */ "\u06F6", + /* 68 */ "\u06F6", // U+06F7: "۷" EXTENDED ARABIC-INDIC DIGIT SEVEN - /* 75 */ "\u06F7", + /* 69 */ "\u06F7", // U+06F8: "۸" EXTENDED ARABIC-INDIC DIGIT EIGHT - /* 76 */ "\u06F8", + /* 70 */ "\u06F8", // U+06F9: "۹" EXTENDED ARABIC-INDIC DIGIT NINE - /* 77 */ "\u06F9", + /* 71 */ "\u06F9", // U+06F0: "۰" EXTENDED ARABIC-INDIC DIGIT ZERO - /* 78 */ "\u06F0", + /* 72 */ "\u06F0", // Label for "switch to symbols" key. // U+061F: "؟" ARABIC QUESTION MARK - /* 79 */ "\u06F3\u06F2\u06F1\u061F", + /* 73 */ "\u06F3\u06F2\u06F1\u061F", // Label for "switch to symbols with microphone" key. This string shouldn't include the "mic" // part because it'll be appended by the code. - /* 80 */ "\u06F3\u06F2\u06F1", - /* 81 */ "1", - /* 82 */ "2", - /* 83 */ "3", - /* 84 */ "4", - /* 85 */ "5", - /* 86 */ "6", - /* 87 */ "7", - /* 88 */ "8", - /* 89 */ "9", + /* 74 */ "\u06F3\u06F2\u06F1", + /* 75 */ "1", + /* 76 */ "2", + /* 77 */ "3", + /* 78 */ "4", + /* 79 */ "5", + /* 80 */ "6", + /* 81 */ "7", + /* 82 */ "8", + /* 83 */ "9", // U+066B: "٫" ARABIC DECIMAL SEPARATOR // U+066C: "٬" ARABIC THOUSANDS SEPARATOR - /* 90 */ "0,\u066B,\u066C", - /* 91~ */ + /* 84 */ "0,\u066B,\u066C", + /* 85~ */ null, null, null, null, null, null, null, null, null, null, - /* ~100 */ + /* ~94 */ // U+060C: "،" ARABIC COMMA - /* 101 */ "\u060C", - /* 102 */ "\\,", + /* 95 */ "\u060C", + /* 96 */ "\\,", + /* 97 */ "\u061F", + /* 98 */ "\u061B", + // U+066A: "٪" ARABIC PERCENT SIGN + /* 99 */ "\u066A", + /* 100 */ null, + /* 101 */ "?", + /* 102 */ ";", + // U+2030: "‰" PER MILLE SIGN + /* 103 */ "\\%,\u2030", // U+060C: "،" ARABIC COMMA // U+061B: "؛" ARABIC SEMICOLON // U+061F: "؟" ARABIC QUESTION MARK // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK - /* 103 */ "\u060C", - /* 104 */ "\u061F", - /* 105 */ "!fixedColumnOrder!4,:,!,\u061F,\u061B,-,/,\u00AB|\u00BB,\u00BB|\u00AB", - /* 106 */ null, + /* 104 */ "\u060C", + /* 105 */ "!", + /* 106 */ "!,\\,", /* 107 */ "\u061F", - /* 108 */ "!text/more_keys_for_arabic_diacritics", - /* 109 */ null, - /* 110 */ "\u064B", - /* 111 */ "!text/more_keys_for_arabic_diacritics", - /* 112 */ "\u061F", - /* 113 */ "\u061B", - // U+066A: "٪" ARABIC PERCENT SIGN - /* 114 */ "\u066A", - /* 115 */ null, - // U+00BF: "¿" INVERTED QUESTION MARK - /* 116 */ "?,\u00BF", - /* 117 */ ";", - // U+2030: "‰" PER MILLE SIGN - /* 118 */ "\\%,\u2030", + /* 108 */ "\u061F,?", + /* 109 */ "\u060C", + /* 110 */ "\u061F", + /* 111 */ "!fixedColumnOrder!4,:,!,\u061F,\u061B,-,/,\u00AB|\u00BB,\u00BB|\u00AB", }; /* Language fi: Finnish */ @@ -1627,23 +1614,6 @@ public final class KeyboardTextsSet { /* 7 */ "\u00E7,\u0107,\u010D", // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS /* 8 */ "%,\u00FF", - /* 9~ */ - null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~44 */ - // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE - /* 45 */ "\u00E8", - // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE - /* 46 */ "\u00E9", - // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE - /* 47 */ "\u00E0", - // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS - /* 48 */ "\u00FC", - // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS - /* 49 */ "\u00F6", - // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS - /* 50 */ "\u00E4", }; /* Language hi: Hindi */ @@ -1652,56 +1622,55 @@ public final class KeyboardTextsSet { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~50 */ + /* ~44 */ // Label for "switch to alphabetic" key. // U+0915: "क" DEVANAGARI LETTER KA // U+0916: "ख" DEVANAGARI LETTER KHA // U+0917: "ग" DEVANAGARI LETTER GA - /* 51 */ "\u0915\u0916\u0917", - /* 52~ */ + /* 45 */ "\u0915\u0916\u0917", + /* 46~ */ null, null, null, null, null, - /* ~56 */ + /* ~50 */ // U+20B9: "₹" INDIAN RUPEE SIGN - /* 57 */ "\u20B9", - /* 58~ */ + /* 51 */ "\u20B9", + /* 52~ */ null, null, null, null, null, null, null, null, null, null, null, - /* ~68 */ + /* ~62 */ // U+0967: "१" DEVANAGARI DIGIT ONE - /* 69 */ "\u0967", + /* 63 */ "\u0967", // U+0968: "२" DEVANAGARI DIGIT TWO - /* 70 */ "\u0968", + /* 64 */ "\u0968", // U+0969: "३" DEVANAGARI DIGIT THREE - /* 71 */ "\u0969", + /* 65 */ "\u0969", // U+096A: "४" DEVANAGARI DIGIT FOUR - /* 72 */ "\u096A", + /* 66 */ "\u096A", // U+096B: "५" DEVANAGARI DIGIT FIVE - /* 73 */ "\u096B", + /* 67 */ "\u096B", // U+096C: "६" DEVANAGARI DIGIT SIX - /* 74 */ "\u096C", + /* 68 */ "\u096C", // U+096D: "७" DEVANAGARI DIGIT SEVEN - /* 75 */ "\u096D", + /* 69 */ "\u096D", // U+096E: "८" DEVANAGARI DIGIT EIGHT - /* 76 */ "\u096E", + /* 70 */ "\u096E", // U+096F: "९" DEVANAGARI DIGIT NINE - /* 77 */ "\u096F", + /* 71 */ "\u096F", // U+0966: "०" DEVANAGARI DIGIT ZERO - /* 78 */ "\u0966", + /* 72 */ "\u0966", // Label for "switch to symbols" key. - /* 79 */ "?\u0967\u0968\u0969", + /* 73 */ "?\u0967\u0968\u0969", // Label for "switch to symbols with microphone" key. This string shouldn't include the "mic" // part because it'll be appended by the code. - /* 80 */ "\u0967\u0968\u0969", - /* 81 */ "1", - /* 82 */ "2", - /* 83 */ "3", - /* 84 */ "4", - /* 85 */ "5", - /* 86 */ "6", - /* 87 */ "7", - /* 88 */ "8", - /* 89 */ "9", - /* 90 */ "0", + /* 74 */ "\u0967\u0968\u0969", + /* 75 */ "1", + /* 76 */ "2", + /* 77 */ "3", + /* 78 */ "4", + /* 79 */ "5", + /* 80 */ "6", + /* 81 */ "7", + /* 82 */ "8", + /* 83 */ "9", + /* 84 */ "0", }; /* Language hr: Croatian */ @@ -1732,12 +1701,12 @@ public final class KeyboardTextsSet { /* 13~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, - /* ~51 */ - /* 52 */ "!text/single_9qm_rqm", - /* 53 */ "!text/double_9qm_rqm", - /* 54 */ "!text/single_raqm_laqm", - /* 55 */ "!text/double_raqm_laqm", + null, null, null, + /* ~45 */ + /* 46 */ "!text/single_9qm_rqm", + /* 47 */ "!text/double_9qm_rqm", + /* 48 */ "!text/single_raqm_laqm", + /* 49 */ "!text/double_raqm_laqm", }; /* Language hu: Hungarian */ @@ -1786,23 +1755,22 @@ public final class KeyboardTextsSet { /* 5~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, - /* ~51 */ - /* 52 */ "!text/single_9qm_rqm", - /* 53 */ "!text/double_9qm_rqm", - /* 54 */ "!text/single_raqm_laqm", - /* 55 */ "!text/double_raqm_laqm", + null, null, null, null, null, null, null, null, null, null, null, + /* ~45 */ + /* 46 */ "!text/single_9qm_rqm", + /* 47 */ "!text/double_9qm_rqm", + /* 48 */ "!text/single_raqm_laqm", + /* 49 */ "!text/double_raqm_laqm", }; - /* Language hy_AM: Armenian (Armenia) */ - private static final String[] LANGUAGE_hy_AM = { + /* Language hy: Armenian */ + private static final String[] LANGUAGE_hy = { /* 0~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, null, null, - /* ~58 */ + null, null, null, null, null, null, null, null, + /* ~52 */ // U+058A: "֊" ARMENIAN HYPHEN // U+055C: "՜" ARMENIAN EXCLAMATION MARK // U+055D: "՝" ARMENIAN COMMA @@ -1811,36 +1779,19 @@ public final class KeyboardTextsSet { // U+055A: "՚" ARMENIAN APOSTROPHE // U+055B: "՛" ARMENIAN EMPHASIS MARK // U+055F: "՟" ARMENIAN ABBREVIATION MARK - /* 59 */ "!fixedColumnOrder!8,!,?,\\,,.,\u058A,\u055C,\u055D,\u055E,:,;,@,\u0559,\u055A,\u055B,\u055F", - /* 60~ */ + /* 53 */ "!fixedColumnOrder!8,!,?,\\,,.,\u058A,\u055C,\u055D,\u055E,:,;,@,\u0559,\u055A,\u055B,\u055F", + /* 54~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, null, - /* ~102 */ - // U+058F: "֏" ARMENIAN DRAM SIGN - // TODO: Enable this when we have glyph for the following letter - // <string name="keylabel_for_currency">֏</string> - // - // U+055D: "՝" ARMENIAN COMMA - /* 103 */ "\u055D", - /* 104 */ null, - /* 105 */ null, - // U+0589: "։" ARMENIAN FULL STOP - /* 106 */ "\u0589", - /* 107 */ null, - /* 108 */ null, - /* 109 */ "\u0589", - /* 110 */ null, - /* 111 */ "!text/more_keys_for_punctuation", - /* 112~ */ - null, null, null, - /* ~114 */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, + /* ~99 */ // U+055C: "՜" ARMENIAN EXCLAMATION MARK // U+00A1: "¡" INVERTED EXCLAMATION MARK - /* 115 */ "\u055C,\u00A1", + /* 100 */ "\u055C,\u00A1", // U+055E: "՞" ARMENIAN QUESTION MARK // U+00BF: "¿" INVERTED QUESTION MARK - /* 116 */ "\u055E,\u00BF", + /* 101 */ "\u055E,\u00BF", }; /* Language is: Icelandic */ @@ -1906,10 +1857,10 @@ public final class KeyboardTextsSet { /* 22 */ "\u00FE", /* 23~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, null, null, - /* ~51 */ - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", + null, null, null, null, null, null, null, null, + /* ~45 */ + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", }; /* Language it: Italian */ @@ -1963,13 +1914,12 @@ public final class KeyboardTextsSet { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~50 */ + /* ~44 */ // Label for "switch to alphabetic" key. // U+05D0: "א" HEBREW LETTER ALEF // U+05D1: "ב" HEBREW LETTER BET // U+05D2: "ג" HEBREW LETTER GIMEL - /* 51 */ "\u05D0\u05D1\u05D2", + /* 45 */ "\u05D0\u05D1\u05D2", // The following characters don't need BIDI mirroring. // U+2018: "‘" LEFT SINGLE QUOTATION MARK // U+2019: "’" RIGHT SINGLE QUOTATION MARK @@ -1977,51 +1927,58 @@ public final class KeyboardTextsSet { // U+201C: "“" LEFT DOUBLE QUOTATION MARK // U+201D: "”" RIGHT DOUBLE QUOTATION MARK // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK - /* 52 */ "\u2018,\u2019,\u201A", - /* 53 */ "\u201C,\u201D,\u201E", - /* 54 */ "!text/single_laqm_raqm_rtl", - /* 55 */ "!text/double_laqm_raqm_rtl", - /* 56 */ null, + /* 46 */ "\u2018,\u2019,\u201A", + /* 47 */ "\u201C,\u201D,\u201E", + /* 48 */ "!text/single_laqm_raqm_rtl", + /* 49 */ "!text/double_laqm_raqm_rtl", + /* 50 */ null, // U+20AA: "₪" NEW SHEQEL SIGN - /* 57 */ "\u20AA", - /* 58 */ null, - /* 59 */ "!fixedColumnOrder!8,;,/,(|),)|(,#,!,\\,,?,&,\\%,+,\",-,:,',@", - /* 60 */ "!fixedColumnOrder!7,;,/,(|),)|(,#,',\\,,&,\\%,+,\",-,:,@", + /* 51 */ "\u20AA", + /* 52 */ null, + /* 53 */ "!fixedColumnOrder!8,;,/,(|),)|(,#,!,\\,,?,&,\\%,+,\",-,:,',@", // U+2605: "★" BLACK STAR - /* 61 */ "\u2605", - /* 62 */ null, + /* 54 */ "\u2605", + /* 55 */ null, // U+00B1: "±" PLUS-MINUS SIGN // U+FB29: "﬩" HEBREW LETTER ALTERNATIVE PLUS SIGN - /* 63 */ "\u00B1,\uFB29", + /* 56 */ "\u00B1,\uFB29", // The all letters need to be mirrored are found at // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt - /* 64 */ "!fixedColumnOrder!3,<|>,{|},[|]", - /* 65 */ "!fixedColumnOrder!3,>|<,}|{,]|[", + /* 57 */ "!fixedColumnOrder!3,<|>,{|},[|]", + /* 58 */ "!fixedColumnOrder!3,>|<,}|{,]|[", // U+2264: "≤" LESS-THAN OR EQUAL TO // U+2265: "≥" GREATER-THAN EQUAL TO // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - /* 66 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB", - /* 67 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB", + /* 59 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB", + /* 60 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB", + /* 61~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, + /* ~104 */ + /* 105 */ "!", + /* 106 */ "!", + /* 107 */ "?", + /* 108 */ "?", }; - /* Language ka_GE: Georgian (Georgia) */ - private static final String[] LANGUAGE_ka_GE = { + /* Language ka: Georgian */ + private static final String[] LANGUAGE_ka = { /* 0~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~50 */ + /* ~44 */ // Label for "switch to alphabetic" key. // U+10D0: "ა" GEORGIAN LETTER AN // U+10D1: "ბ" GEORGIAN LETTER BAN // U+10D2: "გ" GEORGIAN LETTER GAN - /* 51 */ "\u10D0\u10D1\u10D2", - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", + /* 45 */ "\u10D0\u10D1\u10D2", + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", }; /* Language kk: Kazakh */ @@ -2064,34 +2021,31 @@ public final class KeyboardTextsSet { /* ~42 */ // U+0451: "ё" CYRILLIC SMALL LETTER IO /* 43 */ "\u0451", - /* 44~ */ - null, null, null, null, null, null, null, - /* ~50 */ + /* 44 */ null, // Label for "switch to alphabetic" key. // U+0410: "А" CYRILLIC CAPITAL LETTER A // U+0411: "Б" CYRILLIC CAPITAL LETTER BE // U+0412: "В" CYRILLIC CAPITAL LETTER VE - /* 51 */ "\u0410\u0411\u0412", + /* 45 */ "\u0410\u0411\u0412", }; - /* Language km_KH: Khmer (Cambodia) */ - private static final String[] LANGUAGE_km_KH = { + /* Language km: Khmer */ + private static final String[] LANGUAGE_km = { /* 0~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~50 */ + /* ~44 */ // Label for "switch to alphabetic" key. // U+1780: "ក" KHMER LETTER KA // U+1781: "ខ" KHMER LETTER KHA // U+1782: "គ" KHMER LETTER KO - /* 51 */ "\u1780\u1781\u1782", - /* 52~ */ + /* 45 */ "\u1780\u1781\u1782", + /* 46~ */ null, null, null, null, - /* ~55 */ + /* ~49 */ // U+17DB: "៛" KHMER CURRENCY SYMBOL RIEL - /* 56 */ "\u17DB,\u00A2,\u00A3,\u20AC,\u00A5,\u20B1", + /* 50 */ "\u17DB,\u00A2,\u00A3,\u20AC,\u00A5,\u20B1", }; /* Language ky: Kirghiz */ @@ -2127,34 +2081,31 @@ public final class KeyboardTextsSet { /* ~42 */ // U+0451: "ё" CYRILLIC SMALL LETTER IO /* 43 */ "\u0451", - /* 44~ */ - null, null, null, null, null, null, null, - /* ~50 */ + /* 44 */ null, // Label for "switch to alphabetic" key. // U+0410: "А" CYRILLIC CAPITAL LETTER A // U+0411: "Б" CYRILLIC CAPITAL LETTER BE // U+0412: "В" CYRILLIC CAPITAL LETTER VE - /* 51 */ "\u0410\u0411\u0412", + /* 45 */ "\u0410\u0411\u0412", }; - /* Language lo_LA: Lao (Laos) */ - private static final String[] LANGUAGE_lo_LA = { + /* Language lo: Lao */ + private static final String[] LANGUAGE_lo = { /* 0~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~50 */ + /* ~44 */ // Label for "switch to alphabetic" key. // U+0E81: "ກ" LAO LETTER KO // U+0E82: "ຂ" LAO LETTER KHO SUNG // U+0E84: "ຄ" LAO LETTER KHO TAM - /* 51 */ "\u0E81\u0E82\u0E84", - /* 52~ */ + /* 45 */ "\u0E81\u0E82\u0E84", + /* 46~ */ null, null, null, null, null, - /* ~56 */ + /* ~50 */ // U+20AD: "₭" KIP SIGN - /* 57 */ "\u20AD", + /* 51 */ "\u20AD", }; /* Language lt: Lithuanian */ @@ -2248,10 +2199,9 @@ public final class KeyboardTextsSet { /* 16~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~51 */ - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", + /* ~45 */ + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", }; /* Language lv: Latvian */ @@ -2344,10 +2294,9 @@ public final class KeyboardTextsSet { /* 16~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~51 */ - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", + /* ~45 */ + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", }; /* Language mk: Macedonian */ @@ -2369,36 +2318,32 @@ public final class KeyboardTextsSet { /* 43 */ "\u0450", // U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE /* 44 */ "\u045D", - /* 45~ */ - null, null, null, null, null, null, - /* ~50 */ // Label for "switch to alphabetic" key. // U+0410: "А" CYRILLIC CAPITAL LETTER A // U+0411: "Б" CYRILLIC CAPITAL LETTER BE // U+0412: "В" CYRILLIC CAPITAL LETTER VE - /* 51 */ "\u0410\u0411\u0412", - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", + /* 45 */ "\u0410\u0411\u0412", + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", }; - /* Language mn_MN: Mongolian (Mongolia) */ - private static final String[] LANGUAGE_mn_MN = { + /* Language mn: Mongolian */ + private static final String[] LANGUAGE_mn = { /* 0~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~50 */ + /* ~44 */ // Label for "switch to alphabetic" key. // U+0410: "А" CYRILLIC CAPITAL LETTER A // U+0411: "Б" CYRILLIC CAPITAL LETTER BE // U+0412: "В" CYRILLIC CAPITAL LETTER VE - /* 51 */ "\u0410\u0411\u0412", - /* 52~ */ + /* 45 */ "\u0410\u0411\u0412", + /* 46~ */ null, null, null, null, null, - /* ~56 */ + /* ~50 */ // U+20AE: "₮" TUGRIK SIGN - /* 57 */ "\u20AE", + /* 51 */ "\u20AE", }; /* Language nb: Norwegian Bokmål */ @@ -2448,10 +2393,10 @@ public final class KeyboardTextsSet { /* 24 */ "\u00E4", /* 25~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - /* ~51 */ - /* 52 */ "!text/single_9qm_rqm", - /* 53 */ "!text/double_9qm_rqm", + null, null, null, null, null, null, + /* ~45 */ + /* 46 */ "!text/single_9qm_rqm", + /* 47 */ "!text/double_9qm_rqm", }; /* Language ne: Nepali */ @@ -2460,56 +2405,55 @@ public final class KeyboardTextsSet { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~50 */ + /* ~44 */ // Label for "switch to alphabetic" key. // U+0915: "क" DEVANAGARI LETTER KA // U+0916: "ख" DEVANAGARI LETTER KHA // U+0917: "ग" DEVANAGARI LETTER GA - /* 51 */ "\u0915\u0916\u0917", - /* 52~ */ + /* 45 */ "\u0915\u0916\u0917", + /* 46~ */ null, null, null, null, null, - /* ~56 */ + /* ~50 */ // U+0930/U+0941/U+002E "रु." NEPALESE RUPEE SIGN - /* 57 */ "\u0930\u0941.", - /* 58~ */ + /* 51 */ "\u0930\u0941.", + /* 52~ */ null, null, null, null, null, null, null, null, null, null, null, - /* ~68 */ + /* ~62 */ // U+0967: "१" DEVANAGARI DIGIT ONE - /* 69 */ "\u0967", + /* 63 */ "\u0967", // U+0968: "२" DEVANAGARI DIGIT TWO - /* 70 */ "\u0968", + /* 64 */ "\u0968", // U+0969: "३" DEVANAGARI DIGIT THREE - /* 71 */ "\u0969", + /* 65 */ "\u0969", // U+096A: "४" DEVANAGARI DIGIT FOUR - /* 72 */ "\u096A", + /* 66 */ "\u096A", // U+096B: "५" DEVANAGARI DIGIT FIVE - /* 73 */ "\u096B", + /* 67 */ "\u096B", // U+096C: "६" DEVANAGARI DIGIT SIX - /* 74 */ "\u096C", + /* 68 */ "\u096C", // U+096D: "७" DEVANAGARI DIGIT SEVEN - /* 75 */ "\u096D", + /* 69 */ "\u096D", // U+096E: "८" DEVANAGARI DIGIT EIGHT - /* 76 */ "\u096E", + /* 70 */ "\u096E", // U+096F: "९" DEVANAGARI DIGIT NINE - /* 77 */ "\u096F", + /* 71 */ "\u096F", // U+0966: "०" DEVANAGARI DIGIT ZERO - /* 78 */ "\u0966", + /* 72 */ "\u0966", // Label for "switch to symbols" key. - /* 79 */ "?\u0967\u0968\u0969", + /* 73 */ "?\u0967\u0968\u0969", // Label for "switch to symbols with microphone" key. This string shouldn't include the "mic" // part because it'll be appended by the code. - /* 80 */ "\u0967\u0968\u0969", - /* 81 */ "1", - /* 82 */ "2", - /* 83 */ "3", - /* 84 */ "4", - /* 85 */ "5", - /* 86 */ "6", - /* 87 */ "7", - /* 88 */ "8", - /* 89 */ "9", - /* 90 */ "0", + /* 74 */ "\u0967\u0968\u0969", + /* 75 */ "1", + /* 76 */ "2", + /* 77 */ "3", + /* 78 */ "4", + /* 79 */ "5", + /* 80 */ "6", + /* 81 */ "7", + /* 82 */ "8", + /* 83 */ "9", + /* 84 */ "0", }; /* Language nl: Dutch */ @@ -2564,10 +2508,10 @@ public final class KeyboardTextsSet { /* 9~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, null, - /* ~51 */ - /* 52 */ "!text/single_9qm_rqm", - /* 53 */ "!text/double_9qm_rqm", + null, null, null, null, null, null, null, + /* ~45 */ + /* 46 */ "!text/single_9qm_rqm", + /* 47 */ "!text/double_9qm_rqm", }; /* Language pl: Polish */ @@ -2625,10 +2569,10 @@ public final class KeyboardTextsSet { /* 15~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, - /* ~51 */ - /* 52 */ "!text/single_9qm_rqm", - /* 53 */ "!text/double_9qm_rqm", + null, + /* ~45 */ + /* 46 */ "!text/single_9qm_rqm", + /* 47 */ "!text/double_9qm_rqm", }; /* Language pt: Portuguese */ @@ -2731,10 +2675,10 @@ public final class KeyboardTextsSet { /* 12~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, - /* ~51 */ - /* 52 */ "!text/single_9qm_rqm", - /* 53 */ "!text/double_9qm_rqm", + null, null, null, null, + /* ~45 */ + /* 46 */ "!text/single_9qm_rqm", + /* 47 */ "!text/double_9qm_rqm", }; /* Language ru: Russian */ @@ -2763,16 +2707,14 @@ public final class KeyboardTextsSet { /* ~42 */ // U+0451: "ё" CYRILLIC SMALL LETTER IO /* 43 */ "\u0451", - /* 44~ */ - null, null, null, null, null, null, null, - /* ~50 */ + /* 44 */ null, // Label for "switch to alphabetic" key. // U+0410: "А" CYRILLIC CAPITAL LETTER A // U+0411: "Б" CYRILLIC CAPITAL LETTER BE // U+0412: "В" CYRILLIC CAPITAL LETTER VE - /* 51 */ "\u0410\u0411\u0412", - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", + /* 45 */ "\u0410\u0411\u0412", + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", }; /* Language sk: Slovak */ @@ -2866,12 +2808,11 @@ public final class KeyboardTextsSet { /* 16~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~51 */ - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", - /* 54 */ "!text/single_raqm_laqm", - /* 55 */ "!text/double_raqm_laqm", + /* ~45 */ + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", + /* 48 */ "!text/single_raqm_laqm", + /* 49 */ "!text/double_raqm_laqm", }; /* Language sl: Slovenian */ @@ -2895,12 +2836,12 @@ public final class KeyboardTextsSet { /* 13~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, - /* ~51 */ - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", - /* 54 */ "!text/single_raqm_laqm", - /* 55 */ "!text/double_raqm_laqm", + null, null, null, + /* ~45 */ + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", + /* 48 */ "!text/single_raqm_laqm", + /* 49 */ "!text/double_raqm_laqm", }; /* Language sr: Serbian */ @@ -2940,19 +2881,16 @@ public final class KeyboardTextsSet { /* 43 */ "\u0450", // U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE /* 44 */ "\u045D", - /* 45~ */ - null, null, null, null, null, null, - /* ~50 */ // END: More keys definitions for Serbian (Cyrillic) // Label for "switch to alphabetic" key. // U+0410: "А" CYRILLIC CAPITAL LETTER A // U+0411: "Б" CYRILLIC CAPITAL LETTER BE // U+0412: "В" CYRILLIC CAPITAL LETTER VE - /* 51 */ "\u0410\u0411\u0412", - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", - /* 54 */ "!text/single_raqm_laqm", - /* 55 */ "!text/double_raqm_laqm", + /* 45 */ "\u0410\u0411\u0412", + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", + /* 48 */ "!text/single_raqm_laqm", + /* 49 */ "!text/double_raqm_laqm", }; /* Language sv: Swedish */ @@ -3034,10 +2972,10 @@ public final class KeyboardTextsSet { /* 24 */ "\u00E6", /* 25~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, null, null, - /* ~53 */ - /* 54 */ "!text/single_raqm_laqm", - /* 55 */ "!text/double_raqm_laqm", + null, null, null, null, null, null, null, null, + /* ~47 */ + /* 48 */ "!text/single_raqm_laqm", + /* 49 */ "!text/double_raqm_laqm", }; /* Language sw: Swahili */ @@ -3097,18 +3035,17 @@ public final class KeyboardTextsSet { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, - /* ~50 */ + /* ~44 */ // Label for "switch to alphabetic" key. // U+0E01: "ก" THAI CHARACTER KO KAI // U+0E02: "ข" THAI CHARACTER KHO KHAI // U+0E04: "ค" THAI CHARACTER KHO KHWAI - /* 51 */ "\u0E01\u0E02\u0E04", - /* 52~ */ + /* 45 */ "\u0E01\u0E02\u0E04", + /* 46~ */ null, null, null, null, null, - /* ~56 */ + /* ~50 */ // U+0E3F: "฿" THAI CURRENCY SYMBOL BAHT - /* 57 */ "\u0E3F", + /* 51 */ "\u0E3F", }; /* Language tl: Tagalog */ @@ -3238,20 +3175,20 @@ public final class KeyboardTextsSet { // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN /* 37 */ "\u044A", /* 38~ */ - null, null, null, null, null, null, null, null, null, null, null, null, null, - /* ~50 */ + null, null, null, null, null, null, null, + /* ~44 */ // Label for "switch to alphabetic" key. // U+0410: "А" CYRILLIC CAPITAL LETTER A // U+0411: "Б" CYRILLIC CAPITAL LETTER BE // U+0412: "В" CYRILLIC CAPITAL LETTER VE - /* 51 */ "\u0410\u0411\u0412", - /* 52 */ "!text/single_9qm_lqm", - /* 53 */ "!text/double_9qm_lqm", - /* 54~ */ + /* 45 */ "\u0410\u0411\u0412", + /* 46 */ "!text/single_9qm_lqm", + /* 47 */ "!text/double_9qm_lqm", + /* 48~ */ null, null, null, - /* ~56 */ + /* ~50 */ // U+20B4: "₴" HRYVNIA SIGN - /* 57 */ "\u20B4", + /* 51 */ "\u20B4", }; /* Language vi: Vietnamese */ @@ -3336,11 +3273,10 @@ public final class KeyboardTextsSet { /* 10~ */ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, - /* ~56 */ + null, null, null, null, null, null, null, null, null, null, null, + /* ~50 */ // U+20AB: "₫" DONG SIGN - /* 57 */ "\u20AB", + /* 51 */ "\u20AB", }; /* Language zu: Zulu */ @@ -3513,14 +3449,12 @@ public final class KeyboardTextsSet { /* 19 */ "\u0175", }; - // TODO: Use the language + "_" + region representation for the locale string key. - // Currently we are dropping the region from the key. private static final Object[] LANGUAGES_AND_TEXTS = { "DEFAULT", LANGUAGE_DEFAULT, /* default */ "af", LANGUAGE_af, /* Afrikaans */ "ar", LANGUAGE_ar, /* Arabic */ "az", LANGUAGE_az, /* Azerbaijani */ - "be" /* "be_BY" */, LANGUAGE_be_BY, /* Belarusian (Belarus) */ + "be", LANGUAGE_be, /* Belarusian */ "bg", LANGUAGE_bg, /* Bulgarian */ "ca", LANGUAGE_ca, /* Catalan */ "cs", LANGUAGE_cs, /* Czech */ @@ -3530,26 +3464,26 @@ public final class KeyboardTextsSet { "en", LANGUAGE_en, /* English */ "eo", LANGUAGE_eo, /* Esperanto */ "es", LANGUAGE_es, /* Spanish */ - "et" /* "et_EE" */, LANGUAGE_et_EE, /* Estonian (Estonia) */ + "et", LANGUAGE_et, /* Estonian */ "fa", LANGUAGE_fa, /* Persian */ "fi", LANGUAGE_fi, /* Finnish */ "fr", LANGUAGE_fr, /* French */ "hi", LANGUAGE_hi, /* Hindi */ "hr", LANGUAGE_hr, /* Croatian */ "hu", LANGUAGE_hu, /* Hungarian */ - "hy" /* "hy_AM" */, LANGUAGE_hy_AM, /* Armenian (Armenia) */ + "hy", LANGUAGE_hy, /* Armenian */ "is", LANGUAGE_is, /* Icelandic */ "it", LANGUAGE_it, /* Italian */ "iw", LANGUAGE_iw, /* Hebrew */ - "ka" /* "ka_GE" */, LANGUAGE_ka_GE, /* Georgian (Georgia) */ + "ka", LANGUAGE_ka, /* Georgian */ "kk", LANGUAGE_kk, /* Kazakh */ - "km" /* "km_KH" */, LANGUAGE_km_KH, /* Khmer (Cambodia) */ + "km", LANGUAGE_km, /* Khmer */ "ky", LANGUAGE_ky, /* Kirghiz */ - "lo" /* "lo_LA" */, LANGUAGE_lo_LA, /* Lao (Laos) */ + "lo", LANGUAGE_lo, /* Lao */ "lt", LANGUAGE_lt, /* Lithuanian */ "lv", LANGUAGE_lv, /* Latvian */ "mk", LANGUAGE_mk, /* Macedonian */ - "mn" /* "mn_MN" */, LANGUAGE_mn_MN, /* Mongolian (Mongolia) */ + "mn", LANGUAGE_mn, /* Mongolian */ "nb", LANGUAGE_nb, /* Norwegian Bokmål */ "ne", LANGUAGE_ne, /* Nepali */ "nl", LANGUAGE_nl, /* Dutch */ diff --git a/java/src/com/android/inputmethod/keyboard/internal/NonDistinctMultitouchHelper.java b/java/src/com/android/inputmethod/keyboard/internal/NonDistinctMultitouchHelper.java index 111eb6db6..a0935b985 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/NonDistinctMultitouchHelper.java +++ b/java/src/com/android/inputmethod/keyboard/internal/NonDistinctMultitouchHelper.java @@ -20,24 +20,18 @@ import android.util.Log; import android.view.MotionEvent; import com.android.inputmethod.keyboard.Key; -import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.PointerTracker; +import com.android.inputmethod.keyboard.PointerTracker.KeyEventHandler; import com.android.inputmethod.latin.utils.CoordinateUtils; public final class NonDistinctMultitouchHelper { private static final String TAG = NonDistinctMultitouchHelper.class.getSimpleName(); - // Use only main (id=0) pointer tracker. - private final PointerTracker mMainTracker; private int mOldPointerCount = 1; private Key mOldKey; private int[] mLastCoords = CoordinateUtils.newInstance(); - public NonDistinctMultitouchHelper(final PointerTracker mainTracker) { - mMainTracker = mainTracker; - } - - public void processMotionEvent(final MotionEvent me, final KeyDetector keyDetector) { + public void processMotionEvent(final MotionEvent me, final KeyEventHandler keyEventHandler) { final int pointerCount = me.getPointerCount(); final int oldPointerCount = mOldPointerCount; mOldPointerCount = pointerCount; @@ -47,7 +41,8 @@ public final class NonDistinctMultitouchHelper { return; } - final PointerTracker mainTracker = mMainTracker; + // Use only main (id=0) pointer tracker. + final PointerTracker mainTracker = PointerTracker.getPointerTracker(0, keyEventHandler); final int action = me.getActionMasked(); final int index = me.getActionIndex(); final long eventTime = me.getEventTime(); @@ -56,12 +51,12 @@ public final class NonDistinctMultitouchHelper { // In single-touch. if (oldPointerCount == 1 && pointerCount == 1) { if (me.getPointerId(index) == mainTracker.mPointerId) { - mainTracker.processMotionEvent(me, keyDetector); + mainTracker.processMotionEvent(me, keyEventHandler); return; } // Inject a copied event. injectMotionEvent(action, me.getX(index), me.getY(index), downTime, eventTime, - mainTracker, keyDetector); + mainTracker, keyEventHandler); return; } @@ -75,7 +70,7 @@ public final class NonDistinctMultitouchHelper { mOldKey = mainTracker.getKeyOn(x, y); // Inject an artifact up event for the old key. injectMotionEvent(MotionEvent.ACTION_UP, x, y, downTime, eventTime, - mainTracker, keyDetector); + mainTracker, keyEventHandler); return; } @@ -90,11 +85,11 @@ public final class NonDistinctMultitouchHelper { // Inject an artifact down event for the new key. // An artifact up event for the new key will usually be injected as a single-touch. injectMotionEvent(MotionEvent.ACTION_DOWN, x, y, downTime, eventTime, - mainTracker, keyDetector); + mainTracker, keyEventHandler); if (action == MotionEvent.ACTION_UP) { // Inject an artifact up event for the new key also. injectMotionEvent(MotionEvent.ACTION_UP, x, y, downTime, eventTime, - mainTracker, keyDetector); + mainTracker, keyEventHandler); } } return; @@ -106,11 +101,11 @@ public final class NonDistinctMultitouchHelper { private static void injectMotionEvent(final int action, final float x, final float y, final long downTime, final long eventTime, final PointerTracker tracker, - final KeyDetector keyDetector) { + final KeyEventHandler handler) { final MotionEvent me = MotionEvent.obtain( downTime, eventTime, action, x, y, 0 /* metaState */); try { - tracker.processMotionEvent(me, keyDetector); + tracker.processMotionEvent(me, handler); } finally { me.recycle(); } diff --git a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java index 5ac34188c..7ee45e8f6 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java +++ b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java @@ -28,7 +28,7 @@ public final class PointerTrackerQueue { public interface Element { public boolean isModifier(); - public boolean isInDraggingFinger(); + public boolean isInSlidingKeyInput(); public void onPhantomUpEvent(long eventTime); public void cancelTrackingForAction(); } @@ -193,13 +193,13 @@ public final class PointerTrackerQueue { } } - public boolean isAnyInDraggingFinger() { + public boolean isAnyInSlidingKeyInput() { synchronized (mExpandableArrayOfActivePointers) { final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers; final int arraySize = mArraySize; for (int index = 0; index < arraySize; index++) { final Element element = expandableArray.get(index); - if (element.isInDraggingFinger()) { + if (element.isInSlidingKeyInput()) { return true; } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java b/java/src/com/android/inputmethod/keyboard/internal/ScrollKeyboardView.java index 5a996ff53..9cf68d43d 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/internal/ScrollKeyboardView.java @@ -20,21 +20,25 @@ import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; +import android.widget.ScrollView; +import android.widget.Scroller; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardView; -import com.android.inputmethod.keyboard.PointerTracker; import com.android.inputmethod.latin.R; /** - * This is an extended {@link KeyboardView} class that hosts an emoji page keyboard. + * This is an extended {@link KeyboardView} class that hosts a vertical scroll keyboard. * Multi-touch unsupported. No {@link PointerTracker}s. No gesture support. + * TODO: Vertical scroll capability should be removed from this class because it's no longer used. */ // TODO: Implement key popup preview. -public final class EmojiPageKeyboardView extends KeyboardView implements - GestureDetector.OnGestureListener { +public final class ScrollKeyboardView extends KeyboardView implements + ScrollViewWithNotifier.ScrollListener, GestureDetector.OnGestureListener { + private static final boolean PAGINATION = false; + public interface OnKeyClickListener { public void onKeyClick(Key key); } @@ -48,15 +52,63 @@ public final class EmojiPageKeyboardView extends KeyboardView implements private final KeyDetector mKeyDetector = new KeyDetector(0.0f /*keyHysteresisDistance */); private final GestureDetector mGestureDetector; - public EmojiPageKeyboardView(final Context context, final AttributeSet attrs) { + private final Scroller mScroller; + private ScrollViewWithNotifier mScrollView; + + public ScrollKeyboardView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.keyboardViewStyle); } - public EmojiPageKeyboardView(final Context context, final AttributeSet attrs, - final int defStyle) { + public ScrollKeyboardView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); mGestureDetector = new GestureDetector(context, this); mGestureDetector.setIsLongpressEnabled(false /* isLongpressEnabled */); + mScroller = new Scroller(context); + } + + public void setScrollView(final ScrollViewWithNotifier scrollView) { + mScrollView = scrollView; + scrollView.setScrollListener(this); + } + + private final Runnable mScrollTask = new Runnable() { + @Override + public void run() { + final Scroller scroller = mScroller; + final ScrollView scrollView = mScrollView; + scroller.computeScrollOffset(); + scrollView.scrollTo(0, scroller.getCurrY()); + if (!scroller.isFinished()) { + scrollView.post(this); + } + } + }; + + // {@link ScrollViewWithNotified#ScrollListener} methods. + @Override + public void notifyScrollChanged(final int scrollX, final int scrollY, final int oldX, + final int oldY) { + if (PAGINATION) { + mScroller.forceFinished(true /* finished */); + mScrollView.removeCallbacks(mScrollTask); + final int currentTop = mScrollView.getScrollY(); + final int pageHeight = getKeyboard().mBaseHeight; + final int lastPageNo = currentTop / pageHeight; + final int lastPageTop = lastPageNo * pageHeight; + final int nextPageNo = lastPageNo + 1; + final int nextPageTop = Math.min(nextPageNo * pageHeight, getHeight() - pageHeight); + final int scrollTo = (currentTop - lastPageTop) < (nextPageTop - currentTop) + ? lastPageTop : nextPageTop; + final int deltaY = scrollTo - currentTop; + mScroller.startScroll(0, currentTop, 0, deltaY, 300); + mScrollView.post(mScrollTask); + } + } + + @Override + public void notifyOverScrolled(final int scrollX, final int scrollY, final boolean clampedX, + final boolean clampedY) { + releaseCurrentKey(); } public void setOnKeyClickListener(final OnKeyClickListener listener) { diff --git a/java/src/com/android/inputmethod/keyboard/internal/ScrollViewWithNotifier.java b/java/src/com/android/inputmethod/keyboard/internal/ScrollViewWithNotifier.java new file mode 100644 index 000000000..d1ccdc7b5 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/internal/ScrollViewWithNotifier.java @@ -0,0 +1,66 @@ +/* + * 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 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.util.AttributeSet; +import android.widget.ScrollView; + +/** + * This is an extended {@link ScrollView} that can notify + * {@link ScrollView#onScrollChanged(int,int,int,int} and + * {@link ScrollView#onOverScrolled(int,int,int,int)} to a content view. + */ +public class ScrollViewWithNotifier extends ScrollView { + private ScrollListener mScrollListener = EMPTY_LISTER; + + public interface ScrollListener { + public void notifyScrollChanged(int scrollX, int scrollY, int oldX, int oldY); + public void notifyOverScrolled(int scrollX, int scrollY, boolean clampedX, + boolean clampedY); + } + + private static final ScrollListener EMPTY_LISTER = new ScrollListener() { + @Override + public void notifyScrollChanged(int scrollX, int scrollY, int oldX, int oldY) {} + @Override + public void notifyOverScrolled(int scrollX, int scrollY, boolean clampedX, + boolean clampedY) {} + }; + + public ScrollViewWithNotifier(final Context context, final AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onScrollChanged(final int scrollX, final int scrollY, final int oldX, + final int oldY) { + super.onScrollChanged(scrollX, scrollY, oldX, oldY); + mScrollListener.notifyScrollChanged(scrollX, scrollY, oldX, oldY); + } + + @Override + protected void onOverScrolled(final int scrollX, final int scrollY, final boolean clampedX, + final boolean clampedY) { + super.onOverScrolled(scrollX, scrollY, clampedX, clampedY); + mScrollListener.notifyOverScrolled(scrollX, scrollY, clampedX, clampedY); + } + + public void setScrollListener(final ScrollListener listener) { + mScrollListener = listener; + } +} diff --git a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java deleted file mode 100644 index 88d0878d1..000000000 --- a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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 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.os.Message; -import android.os.SystemClock; -import android.view.ViewConfiguration; - -import com.android.inputmethod.keyboard.Key; -import com.android.inputmethod.keyboard.PointerTracker; -import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; -import com.android.inputmethod.keyboard.internal.TimerHandler.Callbacks; -import com.android.inputmethod.latin.Constants; -import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper; - -// TODO: Separate this class into KeyTimerHandler and BatchInputTimerHandler or so. -public final class TimerHandler extends LeakGuardHandlerWrapper<Callbacks> implements TimerProxy { - public interface Callbacks { - public void startWhileTypingFadeinAnimation(); - public void startWhileTypingFadeoutAnimation(); - public void onLongPress(PointerTracker tracker); - } - - private static final int MSG_TYPING_STATE_EXPIRED = 0; - private static final int MSG_REPEAT_KEY = 1; - private static final int MSG_LONGPRESS_KEY = 2; - private static final int MSG_DOUBLE_TAP_SHIFT_KEY = 3; - private static final int MSG_UPDATE_BATCH_INPUT = 4; - - private final int mIgnoreAltCodeKeyTimeout; - private final int mGestureRecognitionUpdateTime; - - public TimerHandler(final Callbacks ownerInstance, final int ignoreAltCodeKeyTimeout, - final int gestureRecognitionUpdateTime) { - super(ownerInstance); - mIgnoreAltCodeKeyTimeout = ignoreAltCodeKeyTimeout; - mGestureRecognitionUpdateTime = gestureRecognitionUpdateTime; - } - - @Override - public void handleMessage(final Message msg) { - final Callbacks callbacks = getOwnerInstance(); - if (callbacks == null) { - return; - } - final PointerTracker tracker = (PointerTracker) msg.obj; - switch (msg.what) { - case MSG_TYPING_STATE_EXPIRED: - callbacks.startWhileTypingFadeinAnimation(); - break; - case MSG_REPEAT_KEY: - tracker.onKeyRepeat(msg.arg1 /* code */, msg.arg2 /* repeatCount */); - break; - case MSG_LONGPRESS_KEY: - cancelLongPressTimers(); - callbacks.onLongPress(tracker); - break; - case MSG_UPDATE_BATCH_INPUT: - tracker.updateBatchInputByTimer(SystemClock.uptimeMillis()); - startUpdateBatchInputTimer(tracker); - break; - } - } - - @Override - public void startKeyRepeatTimerOf(final PointerTracker tracker, final int repeatCount, - final int delay) { - final Key key = tracker.getKey(); - if (key == null || delay == 0) { - return; - } - sendMessageDelayed( - obtainMessage(MSG_REPEAT_KEY, key.getCode(), repeatCount, tracker), delay); - } - - private void cancelKeyRepeatTimerOf(final PointerTracker tracker) { - removeMessages(MSG_REPEAT_KEY, tracker); - } - - public void cancelKeyRepeatTimers() { - removeMessages(MSG_REPEAT_KEY); - } - - // TODO: Suppress layout changes in key repeat mode - public boolean isInKeyRepeat() { - return hasMessages(MSG_REPEAT_KEY); - } - - @Override - public void startLongPressTimerOf(final PointerTracker tracker, final int delay) { - if (delay <= 0) { - return; - } - sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, tracker), delay); - } - - @Override - public void cancelLongPressTimerOf(final PointerTracker tracker) { - removeMessages(MSG_LONGPRESS_KEY, tracker); - } - - private void cancelLongPressTimers() { - removeMessages(MSG_LONGPRESS_KEY); - } - - @Override - public void startTypingStateTimer(final Key typedKey) { - if (typedKey.isModifier() || typedKey.altCodeWhileTyping()) { - return; - } - - final boolean isTyping = isTypingState(); - removeMessages(MSG_TYPING_STATE_EXPIRED); - final Callbacks callbacks = getOwnerInstance(); - if (callbacks == null) { - return; - } - - // When user hits the space or the enter key, just cancel the while-typing timer. - final int typedCode = typedKey.getCode(); - if (typedCode == Constants.CODE_SPACE || typedCode == Constants.CODE_ENTER) { - if (isTyping) { - callbacks.startWhileTypingFadeinAnimation(); - } - return; - } - - sendMessageDelayed( - obtainMessage(MSG_TYPING_STATE_EXPIRED), mIgnoreAltCodeKeyTimeout); - if (isTyping) { - return; - } - callbacks.startWhileTypingFadeoutAnimation(); - } - - @Override - public boolean isTypingState() { - return hasMessages(MSG_TYPING_STATE_EXPIRED); - } - - @Override - public void startDoubleTapShiftKeyTimer() { - sendMessageDelayed(obtainMessage(MSG_DOUBLE_TAP_SHIFT_KEY), - ViewConfiguration.getDoubleTapTimeout()); - } - - @Override - public void cancelDoubleTapShiftKeyTimer() { - removeMessages(MSG_DOUBLE_TAP_SHIFT_KEY); - } - - @Override - public boolean isInDoubleTapShiftKeyTimeout() { - return hasMessages(MSG_DOUBLE_TAP_SHIFT_KEY); - } - - @Override - public void cancelKeyTimersOf(final PointerTracker tracker) { - cancelKeyRepeatTimerOf(tracker); - cancelLongPressTimerOf(tracker); - } - - public void cancelAllKeyTimers() { - cancelKeyRepeatTimers(); - cancelLongPressTimers(); - } - - @Override - public void startUpdateBatchInputTimer(final PointerTracker tracker) { - if (mGestureRecognitionUpdateTime <= 0) { - return; - } - removeMessages(MSG_UPDATE_BATCH_INPUT, tracker); - sendMessageDelayed(obtainMessage(MSG_UPDATE_BATCH_INPUT, tracker), - mGestureRecognitionUpdateTime); - } - - @Override - public void cancelUpdateBatchInputTimer(final PointerTracker tracker) { - removeMessages(MSG_UPDATE_BATCH_INPUT, tracker); - } - - @Override - public void cancelAllUpdateBatchInputTimers() { - removeMessages(MSG_UPDATE_BATCH_INPUT); - } - - public void cancelAllMessages() { - cancelAllKeyTimers(); - cancelAllUpdateBatchInputTimers(); - } -} diff --git a/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java b/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java index e6fb9807e..463d09344 100644 --- a/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java +++ b/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java @@ -27,13 +27,15 @@ import java.io.File; import java.io.IOException; import java.util.Map; -abstract public class AbstractDictionaryWriter { +// TODO: Quit extending Dictionary after implementing dynamic binary dictionary. +abstract public class AbstractDictionaryWriter extends Dictionary { /** Used for Log actions from this class */ private static final String TAG = AbstractDictionaryWriter.class.getSimpleName(); private final Context mContext; - public AbstractDictionaryWriter(final Context context) { + public AbstractDictionaryWriter(final Context context, final String dictType) { + super(dictType); mContext = context; } @@ -53,16 +55,18 @@ abstract public class AbstractDictionaryWriter { // TODO: Remove lastModifiedTime after making binary dictionary support forgetting curve. abstract public void addBigramWords(final String word0, final String word1, - final int frequency, final boolean isValid, final long lastModifiedTime); + final int frequency, final boolean isValid, + final long lastModifiedTime); abstract public void removeBigramWords(final String word0, final String word1); abstract protected void writeDictionary(final DictEncoder dictEncoder, final Map<String, String> attributeMap) throws IOException, UnsupportedFormatException; - public void write(final File file, final Map<String, String> attributeMap) { - final String tempFilePath = file.getAbsolutePath() + ".temp"; - final File tempFile = new File(tempFilePath); + public void write(final String fileName, final Map<String, String> attributeMap) { + final String tempFileName = fileName + ".temp"; + final File file = new File(mContext.getFilesDir(), fileName); + final File tempFile = new File(mContext.getFilesDir(), tempFileName); try { final DictEncoder dictEncoder = new Ver3DictEncoder(tempFile); writeDictionary(dictEncoder, attributeMap); diff --git a/java/src/com/android/inputmethod/latin/AssetFileAddress.java b/java/src/com/android/inputmethod/latin/AssetFileAddress.java index fd6c24dfe..875192554 100644 --- a/java/src/com/android/inputmethod/latin/AssetFileAddress.java +++ b/java/src/com/android/inputmethod/latin/AssetFileAddress.java @@ -16,8 +16,6 @@ package com.android.inputmethod.latin; -import com.android.inputmethod.latin.utils.FileUtils; - import java.io.File; /** @@ -54,12 +52,4 @@ public final class AssetFileAddress { if (!f.isFile()) return null; return new AssetFileAddress(filename, offset, length); } - - public boolean pointsToPhysicalFile() { - return 0 == mOffset; - } - - public void deleteUnderlyingFile() { - FileUtils.deleteRecursively(new File(mFilename)); - } } diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index db4234c63..fd296988e 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -26,7 +26,6 @@ import com.android.inputmethod.latin.settings.NativeSuggestOptions; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.JniUtils; import com.android.inputmethod.latin.utils.StringUtils; -import com.android.inputmethod.latin.utils.UnigramProperty; import java.io.File; import java.util.ArrayList; @@ -58,21 +57,6 @@ public final class BinaryDictionary extends Dictionary { @UsedForTesting public static final String MAX_BIGRAM_COUNT_QUERY = "MAX_BIGRAM_COUNT"; - public static final int NOT_A_VALID_TIMESTAMP = -1; - - // Format to get unigram flags from native side via getUnigramPropertyNative(). - private static final int FORMAT_UNIGRAM_PROPERTY_OUTPUT_FLAG_COUNT = 4; - private static final int FORMAT_UNIGRAM_PROPERTY_IS_NOT_A_WORD_INDEX = 0; - private static final int FORMAT_UNIGRAM_PROPERTY_IS_BLACKLISTED_INDEX = 1; - private static final int FORMAT_UNIGRAM_PROPERTY_HAS_BIGRAMS_INDEX = 2; - private static final int FORMAT_UNIGRAM_PROPERTY_HAS_SHORTCUTS_INDEX = 3; - - // Format to get unigram historical info from native side via getUnigramPropertyNative(). - private static final int FORMAT_UNIGRAM_PROPERTY_OUTPUT_HISTORICAL_INFO_COUNT = 3; - private static final int FORMAT_UNIGRAM_PROPERTY_TIMESTAMP_INDEX = 0; - private static final int FORMAT_UNIGRAM_PROPERTY_LEVEL_INDEX = 1; - private static final int FORMAT_UNIGRAM_PROPERTY_COUNT_INDEX = 2; - private long mNativeDict; private final Locale mLocale; private final long mDictSize; @@ -139,13 +123,8 @@ public final class BinaryDictionary extends Dictionary { private static native boolean needsToRunGCNative(long dict, boolean mindsBlockByGC); private static native void flushWithGCNative(long dict, String filePath); private static native void closeNative(long dict); - private static native int getFormatVersionNative(long dict); private static native int getProbabilityNative(long dict, int[] word); private static native int getBigramProbabilityNative(long dict, int[] word0, int[] word1); - private static native void getUnigramPropertyNative(long dict, int[] word, - int[] outCodePoints, boolean[] outFlags, int[] outProbability, - int[] outHistoricalInfo, ArrayList<int[]> outShortcutTargets, - ArrayList<Integer> outShortcutProbabilities); private static native int getSuggestionsNative(long dict, long proximityInfo, long traverseSession, int[] xCoordinates, int[] yCoordinates, int[] times, int[] pointerIds, int[] inputCodePoints, int inputSize, int commitPoint, @@ -154,14 +133,10 @@ public final class BinaryDictionary extends Dictionary { int[] outputAutoCommitFirstWordConfidence); private static native float calcNormalizedScoreNative(int[] before, int[] after, int score); private static native int editDistanceNative(int[] before, int[] after); - private static native void addUnigramWordNative(long dict, int[] word, int probability, - int[] shortcutTarget, int shortcutProbability, boolean isNotAWord, - boolean isBlacklisted, int timestamp); + private static native void addUnigramWordNative(long dict, int[] word, int probability); private static native void addBigramWordsNative(long dict, int[] word0, int[] word1, - int probability, int timestamp); + int probability); private static native void removeBigramWordsNative(long dict, int[] word0, int[] word1); - private static native int addMultipleDictionaryEntriesNative(long dict, - LanguageModelParam[] languageModelParams, int startIndex); private static native int calculateProbabilityNative(long dict, int unigramProbability, int bigramProbability); private static native String getPropertyNative(long dict, String query); @@ -260,10 +235,6 @@ public final class BinaryDictionary extends Dictionary { return mNativeDict != 0; } - public int getFormatVersion() { - return getFormatVersionNative(mNativeDict); - } - public static float calcNormalizedScore(final String before, final String after, final int score) { return calcNormalizedScoreNative(StringUtils.toCodePointArray(before), @@ -303,55 +274,23 @@ public final class BinaryDictionary extends Dictionary { return getBigramProbabilityNative(mNativeDict, codePoints0, codePoints1); } - @UsedForTesting - public UnigramProperty getUnigramProperty(final String word) { - if (TextUtils.isEmpty(word)) { - return null; - } - final int[] codePoints = StringUtils.toCodePointArray(word); - final int[] outCodePoints = new int[MAX_WORD_LENGTH]; - final boolean[] outFlags = new boolean[FORMAT_UNIGRAM_PROPERTY_OUTPUT_FLAG_COUNT]; - final int[] outProbability = new int[1]; - final int[] outHistoricalInfo = - new int[FORMAT_UNIGRAM_PROPERTY_OUTPUT_HISTORICAL_INFO_COUNT]; - final ArrayList<int[]> outShortcutTargets = CollectionUtils.newArrayList(); - final ArrayList<Integer> outShortcutProbabilities = CollectionUtils.newArrayList(); - getUnigramPropertyNative(mNativeDict, codePoints, outCodePoints, outFlags, outProbability, - outHistoricalInfo, outShortcutTargets, outShortcutProbabilities); - return new UnigramProperty(codePoints, - outFlags[FORMAT_UNIGRAM_PROPERTY_IS_NOT_A_WORD_INDEX], - outFlags[FORMAT_UNIGRAM_PROPERTY_IS_BLACKLISTED_INDEX], - outFlags[FORMAT_UNIGRAM_PROPERTY_HAS_BIGRAMS_INDEX], - outFlags[FORMAT_UNIGRAM_PROPERTY_HAS_SHORTCUTS_INDEX], outProbability[0], - outHistoricalInfo[FORMAT_UNIGRAM_PROPERTY_TIMESTAMP_INDEX], - outHistoricalInfo[FORMAT_UNIGRAM_PROPERTY_LEVEL_INDEX], - outHistoricalInfo[FORMAT_UNIGRAM_PROPERTY_COUNT_INDEX], - outShortcutTargets, outShortcutProbabilities); - } - - // Add a unigram entry to binary dictionary with unigram attributes in native code. - public void addUnigramWord(final String word, final int probability, - final String shortcutTarget, final int shortcutProbability, final boolean isNotAWord, - final boolean isBlacklisted, final int timestamp) { + // Add a unigram entry to binary dictionary in native code. + public void addUnigramWord(final String word, final int probability) { if (TextUtils.isEmpty(word)) { return; } final int[] codePoints = StringUtils.toCodePointArray(word); - final int[] shortcutTargetCodePoints = (shortcutTarget != null) ? - StringUtils.toCodePointArray(shortcutTarget) : null; - addUnigramWordNative(mNativeDict, codePoints, probability, shortcutTargetCodePoints, - shortcutProbability, isNotAWord, isBlacklisted, timestamp); + addUnigramWordNative(mNativeDict, codePoints, probability); } - // Add a bigram entry to binary dictionary with timestamp in native code. - public void addBigramWords(final String word0, final String word1, final int probability, - final int timestamp) { + // Add a bigram entry to binary dictionary in native code. + public void addBigramWords(final String word0, final String word1, final int probability) { if (TextUtils.isEmpty(word0) || TextUtils.isEmpty(word1)) { return; } final int[] codePoints0 = StringUtils.toCodePointArray(word0); final int[] codePoints1 = StringUtils.toCodePointArray(word1); - addBigramWordsNative(mNativeDict, codePoints0, codePoints1, probability, timestamp); + addBigramWordsNative(mNativeDict, codePoints0, codePoints1, probability); } // Remove a bigram entry form binary dictionary in native code. @@ -364,70 +303,10 @@ public final class BinaryDictionary extends Dictionary { removeBigramWordsNative(mNativeDict, codePoints0, codePoints1); } - public static class LanguageModelParam { - public final int[] mWord0; - public final int[] mWord1; - public final int[] mShortcutTarget; - public final int mUnigramProbability; - public final int mBigramProbability; - public final int mShortcutProbability; - public final boolean mIsNotAWord; - public final boolean mIsBlacklisted; - public final int mTimestamp; - - // Constructor for unigram. - public LanguageModelParam(final String word, final int unigramProbability, - final int timestamp) { - mWord0 = null; - mWord1 = StringUtils.toCodePointArray(word); - mShortcutTarget = null; - mUnigramProbability = unigramProbability; - mBigramProbability = NOT_A_PROBABILITY; - mShortcutProbability = NOT_A_PROBABILITY; - mIsNotAWord = false; - mIsBlacklisted = false; - mTimestamp = timestamp; - } - - // Constructor for unigram and bigram. - public LanguageModelParam(final String word0, final String word1, - final int unigramProbability, final int bigramProbability, - final int timestamp) { - mWord0 = StringUtils.toCodePointArray(word0); - mWord1 = StringUtils.toCodePointArray(word1); - mShortcutTarget = null; - mUnigramProbability = unigramProbability; - mBigramProbability = bigramProbability; - mShortcutProbability = NOT_A_PROBABILITY; - mIsNotAWord = false; - mIsBlacklisted = false; - mTimestamp = timestamp; - } - } - - public void addMultipleDictionaryEntries(final LanguageModelParam[] languageModelParams) { - if (!isValidDictionary()) return; - int processedParamCount = 0; - while (processedParamCount < languageModelParams.length) { - if (needsToRunGC(true /* mindsBlockByGC */)) { - flushWithGC(); - } - processedParamCount = addMultipleDictionaryEntriesNative(mNativeDict, - languageModelParams, processedParamCount); - if (processedParamCount <= 0) { - return; - } - } - - } - private void reopen() { close(); final File dictFile = new File(mDictFilePath); - // WARNING: Because we pass 0 as the offset and file.length() as the length, this can - // only be called for actual files. Right now it's only called by the flush() family of - // functions, which require an updatable dictionary, so it's okay. But beware. - loadDictionary(dictFile.getAbsolutePath(), 0 /* startOffset */, + mNativeDict = openNative(dictFile.getAbsolutePath(), 0 /* startOffset */, dictFile.length(), true /* isUpdatable */); } diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index b4382bc2c..722a82961 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -98,7 +98,7 @@ public final class BinaryDictionaryFileDumper { * This creates a URI builder able to build a URI pointing to the dictionary * pack content provider for a specific dictionary id. */ - public static Uri.Builder getProviderUriBuilder(final String path) { + private static Uri.Builder getProviderUriBuilder(final String path) { return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(DictionaryPackConstants.AUTHORITY).appendPath(path); } @@ -339,25 +339,15 @@ public final class BinaryDictionaryFileDumper { Log.e(TAG, "Could not copy a word list. Will not be able to use it."); // If we can't copy it we should warn the dictionary provider so that it can mark it // as invalid. - reportBrokenFileToDictionaryProvider(providerClient, clientId, wordlistId); - } - - public static boolean reportBrokenFileToDictionaryProvider( - final ContentProviderClient providerClient, final String clientId, - final String wordlistId) { + wordListUriBuilder.appendQueryParameter(QUERY_PARAMETER_DELETE_RESULT, + QUERY_PARAMETER_FAILURE); try { - final Uri.Builder wordListUriBuilder = getContentUriBuilderForType(clientId, - providerClient, QUERY_PATH_DATAFILE, wordlistId /* extraPath */); - wordListUriBuilder.appendQueryParameter(QUERY_PARAMETER_DELETE_RESULT, - QUERY_PARAMETER_FAILURE); if (0 >= providerClient.delete(wordListUriBuilder.build(), null, null)) { - Log.e(TAG, "Unable to delete a word list."); + Log.e(TAG, "In addition, we were unable to delete it."); } } catch (RemoteException e) { - Log.e(TAG, "Communication with the dictionary provider was cut", e); - return false; + Log.e(TAG, "In addition, communication with the dictionary provider was cut", e); } - return true; } // Ideally the two following methods should be merged, but AssetFileDescriptor does not @@ -442,9 +432,8 @@ public final class BinaryDictionaryFileDumper { // Actually copy the file final byte[] buffer = new byte[FILE_READ_BUFFER_SIZE]; - for (int readBytes = input.read(buffer); readBytes >= 0; readBytes = input.read(buffer)) { + for (int readBytes = input.read(buffer); readBytes >= 0; readBytes = input.read(buffer)) output.write(buffer, 0, readBytes); - } input.close(); } @@ -489,7 +478,8 @@ public final class BinaryDictionaryFileDumper { * @param context the context for resources and providers. * @param clientId the client ID to use. */ - public static void initializeClientRecordHelper(final Context context, final String clientId) { + public static void initializeClientRecordHelper(final Context context, + final String clientId) { try { final ContentProviderClient client = context.getContentResolver(). acquireContentProviderClient(getProviderUriBuilder("").build()); diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java index c260434d5..9a9653094 100644 --- a/java/src/com/android/inputmethod/latin/Constants.java +++ b/java/src/com/android/inputmethod/latin/Constants.java @@ -70,47 +70,38 @@ public final class Constants { public static final class ExtraValue { /** - * The subtype extra value used to indicate that this subtype is capable of - * entering ASCII characters. + * The subtype extra value used to indicate that the subtype keyboard layout is capable + * for typing ASCII characters. */ public static final String ASCII_CAPABLE = "AsciiCapable"; /** - * The subtype extra value used to indicate that this subtype is enabled - * when the default subtype is not marked as ascii capable. - */ - public static final String ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE = - "EnabledWhenDefaultIsNotAsciiCapable"; - - /** - * The subtype extra value used to indicate that this subtype is capable of - * entering emoji characters. + * The subtype extra value used to indicate that the subtype keyboard layout is capable + * for typing EMOJI characters. */ public static final String EMOJI_CAPABLE = "EmojiCapable"; - /** - * The subtype extra value used to indicate that this subtype requires a network - * connection to work. + * The subtype extra value used to indicate that the subtype require network connection + * to work. */ public static final String REQ_NETWORK_CONNECTIVITY = "requireNetworkConnectivity"; /** - * The subtype extra value used to indicate that the display name of this subtype - * contains a "%s" for printf-like replacement and it should be replaced by - * this extra value. + * The subtype extra value used to indicate that the subtype display name contains "%s" + * for replacement mark and it should be replaced by this extra value. * This extra value is supported on JellyBean and later. */ public static final String UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME = "UntranslatableReplacementStringInSubtypeName"; /** - * The subtype extra value used to indicate this subtype keyboard layout set name. + * The subtype extra value used to indicate that the subtype keyboard layout set name. * This extra value is private to LatinIME. */ public static final String KEYBOARD_LAYOUT_SET = "KeyboardLayoutSet"; /** - * The subtype extra value used to indicate that this subtype is an additional subtype + * The subtype extra value used to indicate that the subtype is additional subtype * that the user defined. This extra value is private to LatinIME. */ public static final String IS_ADDITIONAL_SUBTYPE = "isAdditionalSubtype"; diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java index b6cfcd064..47891c6b7 100644 --- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java @@ -44,8 +44,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { private static final String TAG = ContactsBinaryDictionary.class.getSimpleName(); private static final String NAME = "contacts"; - private static final boolean DEBUG = false; - private static final boolean DEBUG_DUMP = false; + private static boolean DEBUG = false; /** * Frequency for contacts information into the dictionary @@ -72,8 +71,8 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { private final boolean mUseFirstLastBigrams; public ContactsBinaryDictionary(final Context context, final Locale locale) { - super(context, getDictNameWithLocale(NAME, locale), locale, - Dictionary.TYPE_CONTACTS, false /* isUpdatable */); + super(context, getFilenameWithLocale(NAME, locale.toString()), Dictionary.TYPE_CONTACTS, + false /* isUpdatable */); mLocale = locale; mUseFirstLastBigrams = useFirstLastBigramsForLocale(locale); registerObserver(context); @@ -169,10 +168,6 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { if (isValidName(name)) { addName(name); ++count; - } else { - if (DEBUG_DUMP) { - Log.d(TAG, "Invalid name: " + name); - } } cursor.moveToNext(); } @@ -209,9 +204,6 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { if (Character.isLetter(name.codePointAt(i))) { int end = getWordEndPosition(name, len, i); String word = name.substring(i, end); - if (DEBUG_DUMP) { - Log.d(TAG, "addName word = " + word); - } i = end - 1; // Don't add single letter words, possibly confuses // capitalization of i. diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java index e04524843..fa79f5af7 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -52,10 +52,13 @@ public abstract class Dictionary { public static final String TYPE_CONTACTS = "contacts"; // User dictionary, the system-managed one. public static final String TYPE_USER = "user"; - // User history dictionary internal to LatinIME. + // User history dictionary internal to LatinIME. This assumes bigram prediction for now. public static final String TYPE_USER_HISTORY = "history"; - // Personalization dictionary. + // Personalization binary dictionary internal to LatinIME. public static final String TYPE_PERSONALIZATION = "personalization"; + // Personalization prediction dictionary internal to LatinIME's Java code. + public static final String TYPE_PERSONALIZATION_PREDICTION_IN_JAVA = + "personalization_prediction_in_java"; public final String mDictType; public Dictionary(final String dictType) { diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index e09c309ea..828e54f14 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -16,7 +16,6 @@ package com.android.inputmethod.latin; -import android.content.ContentProviderClient; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.content.res.Resources; @@ -65,10 +64,6 @@ public final class DictionaryFactory { useFullEditDistance, locale, Dictionary.TYPE_MAIN); if (readOnlyBinaryDictionary.isValidDictionary()) { dictList.add(readOnlyBinaryDictionary); - } else { - readOnlyBinaryDictionary.close(); - // Prevent this dictionary to do any further harm. - killDictionary(context, f); } } } @@ -80,51 +75,6 @@ public final class DictionaryFactory { } /** - * Kills a dictionary so that it is never used again, if possible. - * @param context The context to contact the dictionary provider, if possible. - * @param f A file address to the dictionary to kill. - */ - private static void killDictionary(final Context context, final AssetFileAddress f) { - if (f.pointsToPhysicalFile()) { - f.deleteUnderlyingFile(); - // Warn the dictionary provider if the dictionary came from there. - final ContentProviderClient providerClient; - try { - providerClient = context.getContentResolver().acquireContentProviderClient( - BinaryDictionaryFileDumper.getProviderUriBuilder("").build()); - } catch (final SecurityException e) { - Log.e(TAG, "No permission to communicate with the dictionary provider", e); - return; - } - if (null == providerClient) { - Log.e(TAG, "Can't establish communication with the dictionary provider"); - return; - } - final String wordlistId = - DictionaryInfoUtils.getWordListIdFromFileName(new File(f.mFilename).getName()); - if (null != wordlistId) { - // TODO: this is a reasonable last resort, but it is suboptimal. - // The following will remove the entry for this dictionary with the dictionary - // provider. When the metadata is downloaded again, we will try downloading it - // again. - // However, in the practice that will mean the user will find themselves without - // the new dictionary. That's fine for languages where it's included in the APK, - // but for other languages it will leave the user without a dictionary at all until - // the next update, which may be a few days away. - // Ideally, we would trigger a new download right away, and use increasing retry - // delays for this particular id/version combination. - // Then again, this is expected to only ever happen in case of human mistake. If - // the wrong file is on the server, the following is still doing the right thing. - // If it's a file left over from the last version however, it's not great. - BinaryDictionaryFileDumper.reportBrokenFileToDictionaryProvider( - providerClient, - context.getString(R.string.dictionary_pack_client_id), - wordlistId); - } - } - } - - /** * Initializes a main dictionary collection from a dictionary pack, with default flags. * * This searches for a content provider providing a dictionary pack for the specified diff --git a/java/src/com/android/inputmethod/latin/DictionaryWriter.java b/java/src/com/android/inputmethod/latin/DictionaryWriter.java index 89ef96d7f..3df2a2b63 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryWriter.java +++ b/java/src/com/android/inputmethod/latin/DictionaryWriter.java @@ -18,6 +18,8 @@ package com.android.inputmethod.latin; import android.content.Context; +import com.android.inputmethod.keyboard.ProximityInfo; +import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.makedict.DictEncoder; import com.android.inputmethod.latin.makedict.FormatSpec; import com.android.inputmethod.latin.makedict.FusionDictionary; @@ -35,14 +37,14 @@ import java.util.Map; * An in memory dictionary for memorizing entries and writing a binary dictionary. */ public class DictionaryWriter extends AbstractDictionaryWriter { - private static final int BINARY_DICT_VERSION = 2; + private static final int BINARY_DICT_VERSION = 3; private static final FormatSpec.FormatOptions FORMAT_OPTIONS = - new FormatSpec.FormatOptions(BINARY_DICT_VERSION, false /* supportsDynamicUpdate */); + new FormatSpec.FormatOptions(BINARY_DICT_VERSION, true /* supportsDynamicUpdate */); private FusionDictionary mFusionDictionary; - public DictionaryWriter(final Context context) { - super(context); + public DictionaryWriter(final Context context, final String dictType) { + super(context, dictType); clear(); } @@ -50,7 +52,7 @@ public class DictionaryWriter extends AbstractDictionaryWriter { public void clear() { final HashMap<String, String> attributes = CollectionUtils.newHashMap(); mFusionDictionary = new FusionDictionary(new PtNodeArray(), - new FusionDictionary.DictionaryOptions(attributes)); + new FusionDictionary.DictionaryOptions(attributes, false, false)); } /** @@ -90,4 +92,18 @@ public class DictionaryWriter extends AbstractDictionaryWriter { } dictEncoder.writeDictionary(mFusionDictionary, FORMAT_OPTIONS); } + + @Override + public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, + final String prevWord, final ProximityInfo proximityInfo, + boolean blockOffensiveWords, final int[] additionalFeaturesOptions) { + // This class doesn't support suggestion. + return null; + } + + @Override + public boolean isValidWord(String word) { + // This class doesn't support dictionary retrieval. + return false; + } } diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index 9f5cd162f..eb8650e6f 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -22,22 +22,18 @@ import android.util.Log; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.ProximityInfo; -import com.android.inputmethod.latin.BinaryDictionary.LanguageModelParam; import com.android.inputmethod.latin.makedict.FormatSpec; +import com.android.inputmethod.latin.personalization.DynamicPersonalizationDictionaryWriter; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.utils.AsyncResultHolder; import com.android.inputmethod.latin.utils.CollectionUtils; -import com.android.inputmethod.latin.utils.FileUtils; import com.android.inputmethod.latin.utils.PrioritizedSerialExecutor; import java.io.File; import java.util.ArrayList; import java.util.HashMap; -import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @@ -56,7 +52,10 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { /** Whether to print debug output to log */ private static boolean DEBUG = false; - private static final boolean DBG_STRESS_TEST = false; + + // TODO: Remove. + /** Whether to call binary dictionary dynamically updating methods. */ + public static boolean ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE = true; private static final int TIMEOUT_FOR_READ_OPS_IN_MILLISECONDS = 100; @@ -65,19 +64,22 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { */ protected static final int MAX_WORD_LENGTH = Constants.DICTIONARY_MAX_WORD_LENGTH; - private static final int DICTIONARY_FORMAT_VERSION = FormatSpec.VERSION4; + private static final int DICTIONARY_FORMAT_VERSION = 3; + + private static final String SUPPORTS_DYNAMIC_UPDATE = + FormatSpec.FileHeader.ATTRIBUTE_VALUE_TRUE; /** * A static map of update controllers, each of which records the time of accesses to a single * binary dictionary file and tracks whether the file is regenerating. The key for this map is - * the dictionary name and the value is the shared dictionary time recorder associated with - * that dictionary name. + * the filename and the value is the shared dictionary time recorder associated with that + * filename. */ private static final ConcurrentHashMap<String, DictionaryUpdateController> - sDictNameDictionaryUpdateControllerMap = CollectionUtils.newConcurrentHashMap(); + sFilenameDictionaryUpdateControllerMap = CollectionUtils.newConcurrentHashMap(); private static final ConcurrentHashMap<String, PrioritizedSerialExecutor> - sDictNameExecutorMap = CollectionUtils.newConcurrentHashMap(); + sFilenameExecutorMap = CollectionUtils.newConcurrentHashMap(); /** The application context. */ protected final Context mContext; @@ -93,24 +95,18 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { protected AbstractDictionaryWriter mDictionaryWriter; /** - * The name of this dictionary, used as a part of the filename for storing the binary - * dictionary. Multiple dictionary instances with the same name is supported, with access - * controlled by DictionaryUpdateController. + * The name of this dictionary, used as the filename for storing the binary dictionary. Multiple + * dictionary instances with the same filename is supported, with access controlled by + * DictionaryTimeRecorder. */ - private final String mDictName; - - /** Dictionary locale */ - private final Locale mLocale; + private final String mFilename; /** Whether to support dynamically updating the dictionary */ private final boolean mIsUpdatable; - /** Dictionary file */ - private final File mDictFile; - // TODO: remove, once dynamic operations is serialized /** Controls updating the shared binary dictionary file across multiple instances. */ - private final DictionaryUpdateController mDictNameDictionaryUpdateController; + private final DictionaryUpdateController mFilenameDictionaryUpdateController; // TODO: remove, once dynamic operations is serialized /** Controls updating the local binary dictionary for this instance. */ @@ -136,57 +132,45 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { */ protected abstract boolean hasContentChanged(); - protected boolean matchesExpectedBinaryDictFormatVersionForThisType(final int formatVersion) { - // This class is using format 2 because it's used by the User and Contacts dictionary - // only, which right now use format 2 (dicts using format 4 use Decaying*, which overrides - // this method). - // TODO: Migrate these dicts to ver4 format, and remove this function. - return formatVersion == 2; - } - - public boolean isValidDictionary() { - return mBinaryDictionary.isValidDictionary(); - } - - private File getDictFile() { - return mDictFile; - } - /** - * Gets the dictionary update controller for the given dictionary name. + * Gets the dictionary update controller for the given filename. */ private static DictionaryUpdateController getDictionaryUpdateController( - final String dictName) { - DictionaryUpdateController recorder = sDictNameDictionaryUpdateControllerMap.get(dictName); + String filename) { + DictionaryUpdateController recorder = sFilenameDictionaryUpdateControllerMap.get(filename); if (recorder == null) { - synchronized(sDictNameDictionaryUpdateControllerMap) { + synchronized(sFilenameDictionaryUpdateControllerMap) { recorder = new DictionaryUpdateController(); - sDictNameDictionaryUpdateControllerMap.put(dictName, recorder); + sFilenameDictionaryUpdateControllerMap.put(filename, recorder); } } return recorder; } /** - * Gets the executor for the given dictionary name. + * Gets the executor for the given filename. */ - private static PrioritizedSerialExecutor getExecutor(final String dictName) { - PrioritizedSerialExecutor executor = sDictNameExecutorMap.get(dictName); + private static PrioritizedSerialExecutor getExecutor(final String filename) { + PrioritizedSerialExecutor executor = sFilenameExecutorMap.get(filename); if (executor == null) { - synchronized(sDictNameExecutorMap) { + synchronized(sFilenameExecutorMap) { executor = new PrioritizedSerialExecutor(); - sDictNameExecutorMap.put(dictName, executor); + sFilenameExecutorMap.put(filename, executor); } } return executor; } private static AbstractDictionaryWriter getDictionaryWriter(final Context context, - final boolean isDynamicPersonalizationDictionary) { + final String dictType, final boolean isDynamicPersonalizationDictionary) { if (isDynamicPersonalizationDictionary) { - return null; + if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { + return null; + } else { + return new DynamicPersonalizationDictionaryWriter(context, dictType); + } } else { - return new DictionaryWriter(context); + return new DictionaryWriter(context, dictType); } } @@ -194,37 +178,26 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { * Creates a new expandable binary dictionary. * * @param context The application context of the parent. - * @param dictName The name of the dictionary. Multiple instances with the same - * name is supported. - * @param locale the dictionary locale. + * @param filename The filename for this binary dictionary. Multiple dictionaries with the same + * filename is supported. * @param dictType the dictionary type, as a human-readable string * @param isUpdatable whether to support dynamically updating the dictionary. Please note that * dynamic dictionary has negative effects on memory space and computation time. */ - public ExpandableBinaryDictionary(final Context context, final String dictName, - final Locale locale, final String dictType, final boolean isUpdatable) { - this(context, dictName, locale, dictType, isUpdatable, - new File(context.getFilesDir(), dictName + DICT_FILE_EXTENSION)); - } - - // Creates an instance that uses a given dictionary file. - public ExpandableBinaryDictionary(final Context context, final String dictName, - final Locale locale, final String dictType, final boolean isUpdatable, - final File dictFile) { + public ExpandableBinaryDictionary(final Context context, final String filename, + final String dictType, final boolean isUpdatable) { super(dictType); - mDictName = dictName; + mFilename = filename; mContext = context; - mLocale = locale; mIsUpdatable = isUpdatable; - mDictFile = dictFile; mBinaryDictionary = null; - mDictNameDictionaryUpdateController = getDictionaryUpdateController(dictName); + mFilenameDictionaryUpdateController = getDictionaryUpdateController(filename); // Currently, only dynamic personalization dictionary is updatable. - mDictionaryWriter = getDictionaryWriter(context, isUpdatable); + mDictionaryWriter = getDictionaryWriter(context, dictType, isUpdatable); } - protected static String getDictNameWithLocale(final String name, final Locale locale) { - return name + "." + locale.toString(); + protected static String getFilenameWithLocale(final String name, final String localeStr) { + return name + "." + localeStr + DICT_FILE_EXTENSION; } /** @@ -232,20 +205,23 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { */ @Override public void close() { - getExecutor(mDictName).execute(new Runnable() { + getExecutor(mFilename).execute(new Runnable() { @Override public void run() { if (mBinaryDictionary!= null) { mBinaryDictionary.close(); mBinaryDictionary = null; } + if (mDictionaryWriter != null) { + mDictionaryWriter.close(); + } } }); } protected void closeBinaryDictionary() { // Ensure that no other threads are accessing the local binary dictionary. - getExecutor(mDictName).execute(new Runnable() { + getExecutor(mFilename).execute(new Runnable() { @Override public void run() { if (mBinaryDictionary != null) { @@ -258,23 +234,19 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { protected Map<String, String> getHeaderAttributeMap() { HashMap<String, String> attributeMap = new HashMap<String, String>(); - attributeMap.put(FormatSpec.FileHeader.DICTIONARY_ID_ATTRIBUTE, mDictName); - attributeMap.put(FormatSpec.FileHeader.DICTIONARY_LOCALE_ATTRIBUTE, mLocale.toString()); - attributeMap.put(FormatSpec.FileHeader.DICTIONARY_VERSION_ATTRIBUTE, - String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()))); + attributeMap.put(FormatSpec.FileHeader.SUPPORTS_DYNAMIC_UPDATE_ATTRIBUTE, + SUPPORTS_DYNAMIC_UPDATE); + attributeMap.put(FormatSpec.FileHeader.DICTIONARY_ID_ATTRIBUTE, mFilename); return attributeMap; } protected void clear() { - getExecutor(mDictName).execute(new Runnable() { + getExecutor(mFilename).execute(new Runnable() { @Override public void run() { - if (mDictionaryWriter == null) { + if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE && mDictionaryWriter == null) { mBinaryDictionary.close(); - final File file = getDictFile(); - if (file.exists() && !FileUtils.deleteRecursively(file)) { - Log.e(TAG, "Can't remove a file: " + file.getName()); - } + final File file = new File(mContext.getFilesDir(), mFilename); BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(), DICTIONARY_FORMAT_VERSION, getHeaderAttributeMap()); mBinaryDictionary = new BinaryDictionary( @@ -314,7 +286,8 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { * Check whether GC is needed and run GC if required. */ protected void runGCIfRequired(final boolean mindsBlockByGC) { - getExecutor(mDictName).execute(new Runnable() { + if (!ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) return; + getExecutor(mFilename).execute(new Runnable() { @Override public void run() { runGCIfRequiredInternalLocked(mindsBlockByGC); @@ -323,17 +296,18 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } private void runGCIfRequiredInternalLocked(final boolean mindsBlockByGC) { + if (!ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) return; // Calls to needsToRunGC() need to be serialized. if (mBinaryDictionary.needsToRunGC(mindsBlockByGC)) { - if (setProcessingLargeTaskIfNot()) { + if (setIsRegeneratingIfNotRegenerating()) { // Run GC after currently existing time sensitive operations. - getExecutor(mDictName).executePrioritized(new Runnable() { + getExecutor(mFilename).executePrioritized(new Runnable() { @Override public void run() { try { mBinaryDictionary.flushWithGC(); } finally { - mDictNameDictionaryUpdateController.mProcessingLargeTask.set(false); + mFilenameDictionaryUpdateController.mIsRegenerating.set(false); } } }); @@ -344,19 +318,23 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { /** * Dynamically adds a word unigram to the dictionary. May overwrite an existing entry. */ - protected void addWordDynamically(final String word, final int frequency, - final String shortcutTarget, final int shortcutFreq, final boolean isNotAWord, - final boolean isBlacklisted, final int timestamp) { + protected void addWordDynamically(final String word, final String shortcutTarget, + final int frequency, final int shortcutFreq, final boolean isNotAWord) { if (!mIsUpdatable) { - Log.w(TAG, "addWordDynamically is called for non-updatable dictionary: " + mDictName); + Log.w(TAG, "addWordDynamically is called for non-updatable dictionary: " + mFilename); return; } - getExecutor(mDictName).execute(new Runnable() { + getExecutor(mFilename).execute(new Runnable() { @Override public void run() { - runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); - mBinaryDictionary.addUnigramWord(word, frequency, shortcutTarget, shortcutFreq, - isNotAWord, isBlacklisted, timestamp); + if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { + runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); + mBinaryDictionary.addUnigramWord(word, frequency); + } else { + // TODO: Remove. + mDictionaryWriter.addUnigramWord(word, shortcutTarget, frequency, shortcutFreq, + isNotAWord); + } } }); } @@ -365,17 +343,23 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { * Dynamically adds a word bigram in the dictionary. May overwrite an existing entry. */ protected void addBigramDynamically(final String word0, final String word1, - final int frequency, final int timestamp) { + final int frequency, final boolean isValid) { if (!mIsUpdatable) { Log.w(TAG, "addBigramDynamically is called for non-updatable dictionary: " - + mDictName); + + mFilename); return; } - getExecutor(mDictName).execute(new Runnable() { + getExecutor(mFilename).execute(new Runnable() { @Override public void run() { - runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); - mBinaryDictionary.addBigramWords(word0, word1, frequency, timestamp); + if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { + runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); + mBinaryDictionary.addBigramWords(word0, word1, frequency); + } else { + // TODO: Remove. + mDictionaryWriter.addBigramWords(word0, word1, frequency, isValid, + 0 /* lastTouchedTime */); + } } }); } @@ -386,48 +370,18 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { protected void removeBigramDynamically(final String word0, final String word1) { if (!mIsUpdatable) { Log.w(TAG, "removeBigramDynamically is called for non-updatable dictionary: " - + mDictName); + + mFilename); return; } - getExecutor(mDictName).execute(new Runnable() { + getExecutor(mFilename).execute(new Runnable() { @Override public void run() { - runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); - mBinaryDictionary.removeBigramWords(word0, word1); - } - }); - } - - public interface AddMultipleDictionaryEntriesCallback { - public void onFinished(); - } - - /** - * Dynamically add multiple entries to the dictionary. - */ - protected void addMultipleDictionaryEntriesDynamically( - final ArrayList<LanguageModelParam> languageModelParams, - final AddMultipleDictionaryEntriesCallback callback) { - if (!mIsUpdatable) { - Log.w(TAG, "addMultipleDictionaryEntriesDynamically is called for non-updatable " + - "dictionary: " + mDictName); - return; - } - getExecutor(mDictName).execute(new Runnable() { - @Override - public void run() { - final boolean locked = setProcessingLargeTaskIfNot(); - try { - mBinaryDictionary.addMultipleDictionaryEntries( - languageModelParams.toArray( - new LanguageModelParam[languageModelParams.size()])); - } finally { - if (callback != null) { - callback.onFinished(); - } - if (locked) { - mDictNameDictionaryUpdateController.mProcessingLargeTask.set(false); - } + if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { + runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); + mBinaryDictionary.removeBigramWords(word0, word1); + } else { + // TODO: Remove. + mDictionaryWriter.removeBigramWords(word0, word1); } } }); @@ -439,23 +393,49 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, final int sessionId) { reloadDictionaryIfRequired(); - if (processingLargeTask()) { + if (isRegenerating()) { return null; } + final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList(); final AsyncResultHolder<ArrayList<SuggestedWordInfo>> holder = new AsyncResultHolder<ArrayList<SuggestedWordInfo>>(); - getExecutor(mDictName).executePrioritized(new Runnable() { + getExecutor(mFilename).executePrioritized(new Runnable() { @Override public void run() { - if (mBinaryDictionary == null) { - holder.set(null); - return; + if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { + if (mBinaryDictionary == null) { + holder.set(null); + return; + } + final ArrayList<SuggestedWordInfo> binarySuggestion = + mBinaryDictionary.getSuggestionsWithSessionId(composer, prevWord, + proximityInfo, blockOffensiveWords, additionalFeaturesOptions, + sessionId); + holder.set(binarySuggestion); + } else { + final ArrayList<SuggestedWordInfo> inMemDictSuggestion = + composer.isBatchMode() ? null : + mDictionaryWriter.getSuggestionsWithSessionId(composer, + prevWord, proximityInfo, blockOffensiveWords, + additionalFeaturesOptions, sessionId); + // TODO: Remove checking mIsUpdatable and use native suggestion. + if (mBinaryDictionary != null && !mIsUpdatable) { + final ArrayList<SuggestedWordInfo> binarySuggestion = + mBinaryDictionary.getSuggestionsWithSessionId(composer, prevWord, + proximityInfo, blockOffensiveWords, + additionalFeaturesOptions, sessionId); + if (inMemDictSuggestion == null) { + holder.set(binarySuggestion); + } else if (binarySuggestion == null) { + holder.set(inMemDictSuggestion); + } else { + binarySuggestion.addAll(inMemDictSuggestion); + holder.set(binarySuggestion); + } + } else { + holder.set(inMemDictSuggestion); + } } - final ArrayList<SuggestedWordInfo> binarySuggestion = - mBinaryDictionary.getSuggestionsWithSessionId(composer, prevWord, - proximityInfo, blockOffensiveWords, additionalFeaturesOptions, - sessionId); - holder.set(binarySuggestion); } }); return holder.get(null, TIMEOUT_FOR_READ_OPS_IN_MILLISECONDS); @@ -476,11 +456,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } protected boolean isValidWordInner(final String word) { - if (processingLargeTask()) { + if (isRegenerating()) { return false; } final AsyncResultHolder<Boolean> holder = new AsyncResultHolder<Boolean>(); - getExecutor(mDictName).executePrioritized(new Runnable() { + getExecutor(mFilename).executePrioritized(new Runnable() { @Override public void run() { holder.set(isValidWordLocked(word)); @@ -514,22 +494,12 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { */ private void loadBinaryDictionary() { if (DEBUG) { - Log.d(TAG, "Loading binary dictionary: " + mDictName + " request=" - + mDictNameDictionaryUpdateController.mLastUpdateRequestTime + " update=" - + mDictNameDictionaryUpdateController.mLastUpdateTime); - } - if (DBG_STRESS_TEST) { - // Test if this class does not cause problems when it takes long time to load binary - // dictionary. - try { - Log.w(TAG, "Start stress in loading: " + mDictName); - Thread.sleep(15000); - Log.w(TAG, "End stress in loading"); - } catch (InterruptedException e) { - } + Log.d(TAG, "Loading binary dictionary: " + mFilename + " request=" + + mFilenameDictionaryUpdateController.mLastUpdateRequestTime + " update=" + + mFilenameDictionaryUpdateController.mLastUpdateTime); } - final File file = getDictFile(); + final File file = new File(mContext.getFilesDir(), mFilename); final String filename = file.getAbsolutePath(); final long length = file.length(); @@ -541,7 +511,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { // swapping in the new one. // TODO: Ensure multi-thread assignment of mBinaryDictionary. final BinaryDictionary oldBinaryDictionary = mBinaryDictionary; - getExecutor(mDictName).executePrioritized(new Runnable() { + getExecutor(mFilename).executePrioritized(new Runnable() { @Override public void run() { mBinaryDictionary = newBinaryDictionary; @@ -563,31 +533,29 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { */ private void writeBinaryDictionary() { if (DEBUG) { - Log.d(TAG, "Generating binary dictionary: " + mDictName + " request=" - + mDictNameDictionaryUpdateController.mLastUpdateRequestTime + " update=" - + mDictNameDictionaryUpdateController.mLastUpdateTime); + Log.d(TAG, "Generating binary dictionary: " + mFilename + " request=" + + mFilenameDictionaryUpdateController.mLastUpdateRequestTime + " update=" + + mFilenameDictionaryUpdateController.mLastUpdateTime); } if (needsToReloadBeforeWriting()) { mDictionaryWriter.clear(); loadDictionaryAsync(); - mDictionaryWriter.write(getDictFile(), getHeaderAttributeMap()); + mDictionaryWriter.write(mFilename, getHeaderAttributeMap()); } else { - if (mBinaryDictionary == null || !isValidDictionary() - // TODO: remove the check below - || !matchesExpectedBinaryDictFormatVersionForThisType( - mBinaryDictionary.getFormatVersion())) { - final File file = getDictFile(); - if (file.exists() && !FileUtils.deleteRecursively(file)) { - Log.e(TAG, "Can't remove a file: " + file.getName()); - } - BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(), - DICTIONARY_FORMAT_VERSION, getHeaderAttributeMap()); - } else { - if (mBinaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) { - mBinaryDictionary.flushWithGC(); + if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { + if (mBinaryDictionary == null || !mBinaryDictionary.isValidDictionary()) { + final File file = new File(mContext.getFilesDir(), mFilename); + BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(), + DICTIONARY_FORMAT_VERSION, getHeaderAttributeMap()); } else { - mBinaryDictionary.flush(); + if (mBinaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) { + mBinaryDictionary.flushWithGC(); + } else { + mBinaryDictionary.flush(); + } } + } else { + mDictionaryWriter.write(mFilename, getHeaderAttributeMap()); } } } @@ -602,10 +570,10 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { protected void setRequiresReload(final boolean requiresRebuild) { final long time = SystemClock.uptimeMillis(); mPerInstanceDictionaryUpdateController.mLastUpdateRequestTime = time; - mDictNameDictionaryUpdateController.mLastUpdateRequestTime = time; + mFilenameDictionaryUpdateController.mLastUpdateRequestTime = time; if (DEBUG) { - Log.d(TAG, "Reload request: " + mDictName + ": request=" + time + " update=" - + mDictNameDictionaryUpdateController.mLastUpdateTime); + Log.d(TAG, "Reload request: " + mFilename + ": request=" + time + " update=" + + mFilenameDictionaryUpdateController.mLastUpdateTime); } } @@ -614,7 +582,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { */ public final void reloadDictionaryIfRequired() { if (!isReloadRequired()) return; - if (setProcessingLargeTaskIfNot()) { + if (setIsRegeneratingIfNotRegenerating()) { reloadDictionary(); } } @@ -626,14 +594,13 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { return mBinaryDictionary == null || mPerInstanceDictionaryUpdateController.isOutOfDate(); } - private boolean processingLargeTask() { - return mDictNameDictionaryUpdateController.mProcessingLargeTask.get(); + private boolean isRegenerating() { + return mFilenameDictionaryUpdateController.mIsRegenerating.get(); } - // Returns whether the dictionary is being used for a large task. If true, we should not use - // this dictionary for latency sensitive operations. - private boolean setProcessingLargeTaskIfNot() { - return mDictNameDictionaryUpdateController.mProcessingLargeTask.compareAndSet( + // Returns whether the dictionary can be regenerated. + private boolean setIsRegeneratingIfNotRegenerating() { + return mFilenameDictionaryUpdateController.mIsRegenerating.compareAndSet( false /* expect */ , true /* update */); } @@ -644,13 +611,13 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { private final void reloadDictionary() { // Ensure that only one thread attempts to read or write to the shared binary dictionary // file at the same time. - getExecutor(mDictName).execute(new Runnable() { + getExecutor(mFilename).execute(new Runnable() { @Override public void run() { try { final long time = SystemClock.uptimeMillis(); final boolean dictionaryFileExists = dictionaryFileExists(); - if (mDictNameDictionaryUpdateController.isOutOfDate() + if (mFilenameDictionaryUpdateController.isOutOfDate() || !dictionaryFileExists) { // If the shared dictionary file does not exist or is out of date, the // first instance that acquires the lock will generate a new one. @@ -659,44 +626,31 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { // rebuild the binary dictionary. Empty dictionaries are supported (in // the case where loadDictionaryAsync() adds nothing) in order to // provide a uniform framework. - mDictNameDictionaryUpdateController.mLastUpdateTime = time; + mFilenameDictionaryUpdateController.mLastUpdateTime = time; writeBinaryDictionary(); loadBinaryDictionary(); } else { // If not, the reload request was unnecessary so revert // LastUpdateRequestTime to LastUpdateTime. - mDictNameDictionaryUpdateController.mLastUpdateRequestTime = - mDictNameDictionaryUpdateController.mLastUpdateTime; + mFilenameDictionaryUpdateController.mLastUpdateRequestTime = + mFilenameDictionaryUpdateController.mLastUpdateTime; } } else if (mBinaryDictionary == null || mPerInstanceDictionaryUpdateController.mLastUpdateTime - < mDictNameDictionaryUpdateController.mLastUpdateTime) { + < mFilenameDictionaryUpdateController.mLastUpdateTime) { // Otherwise, if the local dictionary is older than the shared dictionary, // load the shared dictionary. loadBinaryDictionary(); } - // If we just loaded the binary dictionary, then mBinaryDictionary is not - // up-to-date yet so it's useless to test it right away. Schedule the check - // for right after it's loaded instead. - getExecutor(mDictName).executePrioritized(new Runnable() { - @Override - public void run() { - if (mBinaryDictionary != null && !(isValidDictionary() - // TODO: remove the check below - && matchesExpectedBinaryDictFormatVersionForThisType( - mBinaryDictionary.getFormatVersion()))) { - // Binary dictionary or its format version is not valid. Regenerate - // the dictionary file. writeBinaryDictionary will remove the - // existing files if appropriate. - mDictNameDictionaryUpdateController.mLastUpdateTime = time; - writeBinaryDictionary(); - loadBinaryDictionary(); - } - mPerInstanceDictionaryUpdateController.mLastUpdateTime = time; - } - }); + if (mBinaryDictionary != null && !mBinaryDictionary.isValidDictionary()) { + // Binary dictionary is not valid. Regenerate the dictionary file. + mFilenameDictionaryUpdateController.mLastUpdateTime = time; + writeBinaryDictionary(); + loadBinaryDictionary(); + } + mPerInstanceDictionaryUpdateController.mLastUpdateTime = time; } finally { - mDictNameDictionaryUpdateController.mProcessingLargeTask.set(false); + mFilenameDictionaryUpdateController.mIsRegenerating.set(false); } } }); @@ -704,13 +658,28 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { // TODO: cache the file's existence so that we avoid doing a disk access each time. private boolean dictionaryFileExists() { - return getDictFile().exists(); + final File file = new File(mContext.getFilesDir(), mFilename); + return file.exists(); + } + + /** + * Load the dictionary to memory. + */ + protected void asyncLoadDictionaryToMemory() { + getExecutor(mFilename).executePrioritized(new Runnable() { + @Override + public void run() { + if (!ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { + loadDictionaryAsync(); + } + } + }); } /** * Generate binary dictionary using DictionaryWriter. */ - protected void asyncFlushBinaryDictionary() { + protected void asyncFlashAllBinaryDictionary() { final Runnable newTask = new Runnable() { @Override public void run() { @@ -718,32 +687,37 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } }; final Runnable oldTask = mUnfinishedFlushingTask.getAndSet(newTask); - getExecutor(mDictName).replaceAndExecute(oldTask, newTask); + getExecutor(mFilename).replaceAndExecute(oldTask, newTask); } /** - * For tracking whether the dictionary is out of date and the dictionary is used in a large - * task. Can be shared across multiple dictionary instances that access the same filename. + * For tracking whether the dictionary is out of date and the dictionary is regenerating. + * Can be shared across multiple dictionary instances that access the same filename. */ private static class DictionaryUpdateController { public volatile long mLastUpdateTime = 0; public volatile long mLastUpdateRequestTime = 0; - public volatile AtomicBoolean mProcessingLargeTask = new AtomicBoolean(); + public volatile AtomicBoolean mIsRegenerating = new AtomicBoolean(); public boolean isOutOfDate() { return (mLastUpdateRequestTime > mLastUpdateTime); } } - // TODO: Implement BinaryDictionary.isInDictionary(). + // TODO: Implement native binary methods once the dynamic dictionary implementation is done. @UsedForTesting public boolean isInDictionaryForTests(final String word) { final AsyncResultHolder<Boolean> holder = new AsyncResultHolder<Boolean>(); - getExecutor(mDictName).executePrioritized(new Runnable() { + getExecutor(mFilename).executePrioritized(new Runnable() { @Override public void run() { if (mDictType == Dictionary.TYPE_USER_HISTORY) { - holder.set(mBinaryDictionary.isValidWord(word)); + if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { + holder.set(mBinaryDictionary.isValidWord(word)); + } else { + holder.set(((DynamicPersonalizationDictionaryWriter) mDictionaryWriter) + .isInBigramListForTests(word)); + } } } }); @@ -751,33 +725,12 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } @UsedForTesting - public void waitAllTasksForTests() { - final CountDownLatch countDownLatch = new CountDownLatch(1); - getExecutor(mDictName).execute(new Runnable() { - @Override - public void run() { - countDownLatch.countDown(); - } - }); - try { - countDownLatch.await(); - } catch (InterruptedException e) { - Log.e(TAG, "Interrupted while waiting for finishing dictionary operations.", e); - } + public void shutdownExecutorForTests() { + getExecutor(mFilename).shutdown(); } @UsedForTesting - protected void runAfterGcForDebug(final Runnable r) { - getExecutor(mDictName).executePrioritized(new Runnable() { - @Override - public void run() { - try { - mBinaryDictionary.flushWithGC(); - r.run(); - } finally { - mDictNameDictionaryUpdateController.mProcessingLargeTask.set(false); - } - } - }); + public boolean isTerminatedForTests() { + return getExecutor(mFilename).isTerminated(); } } diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java new file mode 100644 index 000000000..95c9bcab9 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -0,0 +1,894 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin; + +import android.text.TextUtils; +import android.util.Log; + +import com.android.inputmethod.annotations.UsedForTesting; +import com.android.inputmethod.keyboard.ProximityInfo; +import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.utils.CollectionUtils; +import com.android.inputmethod.latin.utils.UserHistoryForgettingCurveUtils.ForgettingCurveParams; + +import java.util.ArrayList; +import java.util.LinkedList; + +/** + * Class for an in-memory dictionary that can grow dynamically and can + * be searched for suggestions and valid words. + */ +// TODO: Remove after binary dictionary supports dynamic update. +public class ExpandableDictionary extends Dictionary { + private static final String TAG = ExpandableDictionary.class.getSimpleName(); + /** + * The weight to give to a word if it's length is the same as the number of typed characters. + */ + private static final int FULL_WORD_SCORE_MULTIPLIER = 2; + + private char[] mWordBuilder = new char[Constants.DICTIONARY_MAX_WORD_LENGTH]; + private int mMaxDepth; + private int mInputLength; + + private static final class Node { + char mCode; + int mFrequency; + boolean mTerminal; + Node mParent; + NodeArray mChildren; + ArrayList<char[]> mShortcutTargets; + boolean mShortcutOnly; + LinkedList<NextWord> mNGrams; // Supports ngram + } + + private static final class NodeArray { + Node[] mData; + int mLength = 0; + private static final int INCREMENT = 2; + + NodeArray() { + mData = new Node[INCREMENT]; + } + + void add(final Node n) { + if (mLength + 1 > mData.length) { + Node[] tempData = new Node[mLength + INCREMENT]; + if (mLength > 0) { + System.arraycopy(mData, 0, tempData, 0, mLength); + } + mData = tempData; + } + mData[mLength++] = n; + } + } + + public interface NextWord { + public Node getWordNode(); + public int getFrequency(); + public ForgettingCurveParams getFcParams(); + public int notifyTypedAgainAndGetFrequency(); + } + + private static final class NextStaticWord implements NextWord { + public final Node mWord; + private final int mFrequency; + public NextStaticWord(Node word, int frequency) { + mWord = word; + mFrequency = frequency; + } + + @Override + public Node getWordNode() { + return mWord; + } + + @Override + public int getFrequency() { + return mFrequency; + } + + @Override + public ForgettingCurveParams getFcParams() { + return null; + } + + @Override + public int notifyTypedAgainAndGetFrequency() { + return mFrequency; + } + } + + private static final class NextHistoryWord implements NextWord { + public final Node mWord; + public final ForgettingCurveParams mFcp; + + public NextHistoryWord(Node word, ForgettingCurveParams fcp) { + mWord = word; + mFcp = fcp; + } + + @Override + public Node getWordNode() { + return mWord; + } + + @Override + public int getFrequency() { + return mFcp.getFrequency(); + } + + @Override + public ForgettingCurveParams getFcParams() { + return mFcp; + } + + @Override + public int notifyTypedAgainAndGetFrequency() { + return mFcp.notifyTypedAgainAndGetFrequency(); + } + } + + private NodeArray mRoots; + + private int[][] mCodes; + + public ExpandableDictionary(final String dictType) { + super(dictType); + clearDictionary(); + mCodes = new int[Constants.DICTIONARY_MAX_WORD_LENGTH][]; + } + + public int getMaxWordLength() { + return Constants.DICTIONARY_MAX_WORD_LENGTH; + } + + /** + * Add a word with an optional shortcut to the dictionary. + * @param word The word to add. + * @param shortcutTarget A shortcut target for this word, or null if none. + * @param frequency The frequency for this unigram. + * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist). Ignored + * if shortcutTarget is null. + */ + public void addWord(final String word, final String shortcutTarget, final int frequency, + final int shortcutFreq) { + if (word.length() >= Constants.DICTIONARY_MAX_WORD_LENGTH) { + return; + } + addWordRec(mRoots, word, 0, shortcutTarget, frequency, shortcutFreq, null); + } + + /** + * Add a word, recursively searching for its correct place in the trie tree. + * @param children The node to recursively search for addition. Initially, the root of the tree. + * @param word The word to add. + * @param depth The current depth in the tree. + * @param shortcutTarget A shortcut target for this word, or null if none. + * @param frequency The frequency for this unigram. + * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist). Ignored + * if shortcutTarget is null. + * @param parentNode The parent node, for up linking. Initially null, as the root has no parent. + */ + private void addWordRec(final NodeArray children, final String word, final int depth, + final String shortcutTarget, final int frequency, final int shortcutFreq, + final Node parentNode) { + final int wordLength = word.length(); + if (wordLength <= depth) return; + final char c = word.charAt(depth); + // Does children have the current character? + final int childrenLength = children.mLength; + Node childNode = null; + for (int i = 0; i < childrenLength; i++) { + final Node node = children.mData[i]; + if (node.mCode == c) { + childNode = node; + break; + } + } + final boolean isShortcutOnly = (null != shortcutTarget); + if (childNode == null) { + childNode = new Node(); + childNode.mCode = c; + childNode.mParent = parentNode; + childNode.mShortcutOnly = isShortcutOnly; + children.add(childNode); + } + if (wordLength == depth + 1) { + // Terminate this word + childNode.mTerminal = true; + if (isShortcutOnly) { + if (null == childNode.mShortcutTargets) { + childNode.mShortcutTargets = CollectionUtils.newArrayList(); + } + childNode.mShortcutTargets.add(shortcutTarget.toCharArray()); + } else { + childNode.mShortcutOnly = false; + } + childNode.mFrequency = Math.max(frequency, childNode.mFrequency); + if (childNode.mFrequency > 255) childNode.mFrequency = 255; + return; + } + if (childNode.mChildren == null) { + childNode.mChildren = new NodeArray(); + } + addWordRec(childNode.mChildren, word, depth + 1, shortcutTarget, frequency, shortcutFreq, + childNode); + } + + @Override + public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, + final String prevWord, final ProximityInfo proximityInfo, + final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) { + if (composer.size() > 1) { + if (composer.size() >= Constants.DICTIONARY_MAX_WORD_LENGTH) { + return null; + } + final ArrayList<SuggestedWordInfo> suggestions = + getWordsInner(composer, prevWord, proximityInfo); + return suggestions; + } else { + if (TextUtils.isEmpty(prevWord)) return null; + final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList(); + runBigramReverseLookUp(prevWord, suggestions); + return suggestions; + } + } + + private ArrayList<SuggestedWordInfo> getWordsInner(final WordComposer codes, + final String prevWordForBigrams, final ProximityInfo proximityInfo) { + final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList(); + mInputLength = codes.size(); + if (mCodes.length < mInputLength) mCodes = new int[mInputLength][]; + final InputPointers ips = codes.getInputPointers(); + final int[] xCoordinates = ips.getXCoordinates(); + final int[] yCoordinates = ips.getYCoordinates(); + // Cache the codes so that we don't have to lookup an array list + for (int i = 0; i < mInputLength; i++) { + // TODO: Calculate proximity info here. + if (mCodes[i] == null || mCodes[i].length < 1) { + mCodes[i] = new int[ProximityInfo.MAX_PROXIMITY_CHARS_SIZE]; + } + final int x = xCoordinates != null && i < xCoordinates.length ? + xCoordinates[i] : Constants.NOT_A_COORDINATE; + final int y = xCoordinates != null && i < yCoordinates.length ? + yCoordinates[i] : Constants.NOT_A_COORDINATE; + proximityInfo.fillArrayWithNearestKeyCodes(x, y, codes.getCodeAt(i), mCodes[i]); + } + mMaxDepth = mInputLength * 3; + getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, -1, suggestions); + for (int i = 0; i < mInputLength; i++) { + getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, i, suggestions); + } + return suggestions; + } + + @Override + public synchronized boolean isValidWord(final String word) { + final Node node = searchNode(mRoots, word, 0, word.length()); + // If node is null, we didn't find the word, so it's not valid. + // If node.mShortcutOnly is true, then it exists as a shortcut but not as a word, + // so that means it's not a valid word. + // If node.mShortcutOnly is false, then it exists as a word (it may also exist as + // a shortcut, but this does not matter), so it's a valid word. + return (node == null) ? false : !node.mShortcutOnly; + } + + public boolean removeBigram(final String word0, final String word1) { + // Refer to addOrSetBigram() about word1.toLowerCase() + final Node firstWord = searchWord(mRoots, word0.toLowerCase(), 0, null); + final Node secondWord = searchWord(mRoots, word1, 0, null); + LinkedList<NextWord> bigrams = firstWord.mNGrams; + NextWord bigramNode = null; + if (bigrams == null || bigrams.size() == 0) { + return false; + } else { + for (NextWord nw : bigrams) { + if (nw.getWordNode() == secondWord) { + bigramNode = nw; + break; + } + } + } + if (bigramNode == null) { + return false; + } + return bigrams.remove(bigramNode); + } + + /** + * Returns the word's frequency or -1 if not found + */ + @UsedForTesting + public int getWordFrequency(final String word) { + // Case-sensitive search + final Node node = searchNode(mRoots, word, 0, word.length()); + return (node == null) ? -1 : node.mFrequency; + } + + public NextWord getBigramWord(final String word0, final String word1) { + // Refer to addOrSetBigram() about word0.toLowerCase() + final Node firstWord = searchWord(mRoots, word0.toLowerCase(), 0, null); + final Node secondWord = searchWord(mRoots, word1, 0, null); + LinkedList<NextWord> bigrams = firstWord.mNGrams; + if (bigrams == null || bigrams.size() == 0) { + return null; + } else { + for (NextWord nw : bigrams) { + if (nw.getWordNode() == secondWord) { + return nw; + } + } + } + return null; + } + + private static int computeSkippedWordFinalFreq(final int freq, final int snr, + final int inputLength) { + // The computation itself makes sense for >= 2, but the == 2 case returns 0 + // anyway so we may as well test against 3 instead and return the constant + if (inputLength >= 3) { + return (freq * snr * (inputLength - 2)) / (inputLength - 1); + } else { + return 0; + } + } + + /** + * Helper method to add a word and its shortcuts. + * + * @param node the terminal node + * @param word the word to insert, as an array of code points + * @param depth the depth of the node in the tree + * @param finalFreq the frequency for this word + * @param suggestions the suggestion collection to add the suggestions to + * @return whether there is still space for more words. + */ + private boolean addWordAndShortcutsFromNode(final Node node, final char[] word, final int depth, + final int finalFreq, final ArrayList<SuggestedWordInfo> suggestions) { + if (finalFreq > 0 && !node.mShortcutOnly) { + // Use KIND_CORRECTION always. This dictionary does not really have a notion of + // COMPLETION against CORRECTION; we could artificially add one by looking at + // the respective size of the typed word and the suggestion if it matters sometime + // in the future. + suggestions.add(new SuggestedWordInfo(new String(word, 0, depth + 1), finalFreq, + SuggestedWordInfo.KIND_CORRECTION, this /* sourceDict */, + SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */, + SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */)); + if (suggestions.size() >= Suggest.MAX_SUGGESTIONS) return false; + } + if (null != node.mShortcutTargets) { + final int length = node.mShortcutTargets.size(); + for (int shortcutIndex = 0; shortcutIndex < length; ++shortcutIndex) { + final char[] shortcut = node.mShortcutTargets.get(shortcutIndex); + suggestions.add(new SuggestedWordInfo(new String(shortcut, 0, shortcut.length), + finalFreq, SuggestedWordInfo.KIND_SHORTCUT, this /* sourceDict */, + SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */, + SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */)); + if (suggestions.size() > Suggest.MAX_SUGGESTIONS) return false; + } + } + return true; + } + + /** + * Recursively traverse the tree for words that match the input. Input consists of + * a list of arrays. Each item in the list is one input character position. An input + * character is actually an array of multiple possible candidates. This function is not + * optimized for speed, assuming that the user dictionary will only be a few hundred words in + * size. + * @param roots node whose children have to be search for matches + * @param codes the input character codes + * @param word the word being composed as a possible match + * @param depth the depth of traversal - the length of the word being composed thus far + * @param completion whether the traversal is now in completion mode - meaning that we've + * exhausted the input and we're looking for all possible suffixes. + * @param snr current weight of the word being formed + * @param inputIndex position in the input characters. This can be off from the depth in + * case we skip over some punctuations such as apostrophe in the traversal. That is, if you type + * "wouldve", it could be matching "would've", so the depth will be one more than the + * inputIndex + * @param suggestions the list in which to add suggestions + */ + // TODO: Share this routine with the native code for BinaryDictionary + private void getWordsRec(final NodeArray roots, final WordComposer codes, final char[] word, + final int depth, final boolean completion, final int snr, final int inputIndex, + final int skipPos, final ArrayList<SuggestedWordInfo> suggestions) { + final int count = roots.mLength; + final int codeSize = mInputLength; + // Optimization: Prune out words that are too long compared to how much was typed. + if (depth > mMaxDepth) { + return; + } + final int[] currentChars; + if (codeSize <= inputIndex) { + currentChars = null; + } else { + currentChars = mCodes[inputIndex]; + } + + for (int i = 0; i < count; i++) { + final Node node = roots.mData[i]; + final char c = node.mCode; + final char lowerC = toLowerCase(c); + final boolean terminal = node.mTerminal; + final NodeArray children = node.mChildren; + final int freq = node.mFrequency; + if (completion || currentChars == null) { + word[depth] = c; + if (terminal) { + final int finalFreq; + if (skipPos < 0) { + finalFreq = freq * snr; + } else { + finalFreq = computeSkippedWordFinalFreq(freq, snr, mInputLength); + } + if (!addWordAndShortcutsFromNode(node, word, depth, finalFreq, suggestions)) { + // No space left in the queue, bail out + return; + } + } + if (children != null) { + getWordsRec(children, codes, word, depth + 1, true, snr, inputIndex, + skipPos, suggestions); + } + } else if ((c == Constants.CODE_SINGLE_QUOTE + && currentChars[0] != Constants.CODE_SINGLE_QUOTE) || depth == skipPos) { + // Skip the ' and continue deeper + word[depth] = c; + if (children != null) { + getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex, + skipPos, suggestions); + } + } else { + // Don't use alternatives if we're looking for missing characters + final int alternativesSize = skipPos >= 0 ? 1 : currentChars.length; + for (int j = 0; j < alternativesSize; j++) { + final int addedAttenuation = (j > 0 ? 1 : 2); + final int currentChar = currentChars[j]; + if (currentChar == Constants.NOT_A_CODE) { + break; + } + if (currentChar == lowerC || currentChar == c) { + word[depth] = c; + + if (codeSize == inputIndex + 1) { + if (terminal) { + final int finalFreq; + if (skipPos < 0) { + finalFreq = freq * snr * addedAttenuation + * FULL_WORD_SCORE_MULTIPLIER; + } else { + finalFreq = computeSkippedWordFinalFreq(freq, + snr * addedAttenuation, mInputLength); + } + if (!addWordAndShortcutsFromNode(node, word, depth, finalFreq, + suggestions)) { + // No space left in the queue, bail out + return; + } + } + if (children != null) { + getWordsRec(children, codes, word, depth + 1, + true, snr * addedAttenuation, inputIndex + 1, + skipPos, suggestions); + } + } else if (children != null) { + getWordsRec(children, codes, word, depth + 1, + false, snr * addedAttenuation, inputIndex + 1, + skipPos, suggestions); + } + } + } + } + } + } + + public int setBigramAndGetFrequency(final String word0, final String word1, + final int frequency) { + return setBigramAndGetFrequency(word0, word1, frequency, null /* unused */); + } + + public int setBigramAndGetFrequency(final String word0, final String word1, + final ForgettingCurveParams fcp) { + return setBigramAndGetFrequency(word0, word1, 0 /* unused */, fcp); + } + + /** + * Adds bigrams to the in-memory trie structure that is being used to retrieve any word + * @param word0 the first word of this bigram + * @param word1 the second word of this bigram + * @param frequency frequency for this bigram + * @param fcp an instance of ForgettingCurveParams to use for decay policy + * @return returns the final bigram frequency + */ + private int setBigramAndGetFrequency(final String word0, final String word1, + final int frequency, final ForgettingCurveParams fcp) { + if (TextUtils.isEmpty(word0)) { + Log.e(TAG, "Invalid bigram previous word: " + word0); + return frequency; + } + // We don't want results to be different according to case of the looked up left hand side + // word. We do want however to return the correct case for the right hand side. + // So we want to squash the case of the left hand side, and preserve that of the right + // hand side word. + final String word0Lower = word0.toLowerCase(); + if (TextUtils.isEmpty(word0Lower) || TextUtils.isEmpty(word1)) { + Log.e(TAG, "Invalid bigram pair: " + word0 + ", " + word0Lower + ", " + word1); + return frequency; + } + final Node firstWord = searchWord(mRoots, word0Lower, 0, null); + final Node secondWord = searchWord(mRoots, word1, 0, null); + LinkedList<NextWord> bigrams = firstWord.mNGrams; + if (bigrams == null || bigrams.size() == 0) { + firstWord.mNGrams = CollectionUtils.newLinkedList(); + bigrams = firstWord.mNGrams; + } else { + for (NextWord nw : bigrams) { + if (nw.getWordNode() == secondWord) { + return nw.notifyTypedAgainAndGetFrequency(); + } + } + } + if (fcp != null) { + // history + firstWord.mNGrams.add(new NextHistoryWord(secondWord, fcp)); + } else { + firstWord.mNGrams.add(new NextStaticWord(secondWord, frequency)); + } + return frequency; + } + + /** + * Searches for the word and add the word if it does not exist. + * @return Returns the terminal node of the word we are searching for. + */ + private Node searchWord(final NodeArray children, final String word, final int depth, + final Node parentNode) { + final int wordLength = word.length(); + final char c = word.charAt(depth); + // Does children have the current character? + final int childrenLength = children.mLength; + Node childNode = null; + for (int i = 0; i < childrenLength; i++) { + final Node node = children.mData[i]; + if (node.mCode == c) { + childNode = node; + break; + } + } + if (childNode == null) { + childNode = new Node(); + childNode.mCode = c; + childNode.mParent = parentNode; + children.add(childNode); + } + if (wordLength == depth + 1) { + // Terminate this word + childNode.mTerminal = true; + return childNode; + } + if (childNode.mChildren == null) { + childNode.mChildren = new NodeArray(); + } + return searchWord(childNode.mChildren, word, depth + 1, childNode); + } + + private void runBigramReverseLookUp(final String previousWord, + final ArrayList<SuggestedWordInfo> suggestions) { + // Search for the lowercase version of the word only, because that's where bigrams + // store their sons. + final Node prevWord = searchNode(mRoots, previousWord.toLowerCase(), 0, + previousWord.length()); + if (prevWord != null && prevWord.mNGrams != null) { + reverseLookUp(prevWord.mNGrams, suggestions); + } + } + + // Local to reverseLookUp, but do not allocate each time. + private final char[] mLookedUpString = new char[Constants.DICTIONARY_MAX_WORD_LENGTH]; + + /** + * reverseLookUp retrieves the full word given a list of terminal nodes and adds those words + * to the suggestions list passed as an argument. + * @param terminalNodes list of terminal nodes we want to add + * @param suggestions the suggestion collection to add the word to + */ + private void reverseLookUp(final LinkedList<NextWord> terminalNodes, + final ArrayList<SuggestedWordInfo> suggestions) { + Node node; + int freq; + for (NextWord nextWord : terminalNodes) { + node = nextWord.getWordNode(); + freq = nextWord.getFrequency(); + int index = Constants.DICTIONARY_MAX_WORD_LENGTH; + do { + --index; + mLookedUpString[index] = node.mCode; + node = node.mParent; + } while (node != null && index > 0); + + // If node is null, we have a word longer than MAX_WORD_LENGTH in the dictionary. + // It's a little unclear how this can happen, but just in case it does it's safer + // to ignore the word in this case. + if (freq >= 0 && node == null) { + suggestions.add(new SuggestedWordInfo(new String(mLookedUpString, index, + Constants.DICTIONARY_MAX_WORD_LENGTH - index), + freq, SuggestedWordInfo.KIND_CORRECTION, this /* sourceDict */, + SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */, + SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */)); + } + } + } + + /** + * Recursively search for the terminal node of the word. + * + * One iteration takes the full word to search for and the current index of the recursion. + * + * @param children the node of the trie to search under. + * @param word the word to search for. Only read [offset..length] so there may be trailing chars + * @param offset the index in {@code word} this recursion should operate on. + * @param length the length of the input word. + * @return Returns the terminal node of the word if the word exists + */ + private Node searchNode(final NodeArray children, final CharSequence word, final int offset, + final int length) { + final int count = children.mLength; + final char currentChar = word.charAt(offset); + for (int j = 0; j < count; j++) { + final Node node = children.mData[j]; + if (node.mCode == currentChar) { + if (offset == length - 1) { + if (node.mTerminal) { + return node; + } + } else { + if (node.mChildren != null) { + Node returnNode = searchNode(node.mChildren, word, offset + 1, length); + if (returnNode != null) return returnNode; + } + } + } + } + return null; + } + + public void clearDictionary() { + mRoots = new NodeArray(); + } + + private static char toLowerCase(final char c) { + char baseChar = c; + if (c < BASE_CHARS.length) { + baseChar = BASE_CHARS[c]; + } + if (baseChar >= 'A' && baseChar <= 'Z') { + return (char)(baseChar | 32); + } else if (baseChar > 127) { + return Character.toLowerCase(baseChar); + } + return baseChar; + } + + /** + * Table mapping most combined Latin, Greek, and Cyrillic characters + * to their base characters. If c is in range, BASE_CHARS[c] == c + * if c is not a combined character, or the base character if it + * is combined. + * + * cf. native/jni/src/utils/char_utils.cpp + */ + private static final char BASE_CHARS[] = { + /* U+0000 */ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + /* U+0008 */ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + /* U+0010 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + /* U+0018 */ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, + /* U+0020 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + /* U+0028 */ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + /* U+0030 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + /* U+0038 */ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, + /* U+0040 */ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + /* U+0048 */ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, + /* U+0050 */ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + /* U+0058 */ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, + /* U+0060 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + /* U+0068 */ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + /* U+0070 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + /* U+0078 */ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, + /* U+0080 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + /* U+0088 */ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + /* U+0090 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + /* U+0098 */ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + /* U+00A0 */ 0x0020, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + /* U+00A8 */ 0x0020, 0x00A9, 0x0061, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0020, + /* U+00B0 */ 0x00B0, 0x00B1, 0x0032, 0x0033, 0x0020, 0x03BC, 0x00B6, 0x00B7, + /* U+00B8 */ 0x0020, 0x0031, 0x006F, 0x00BB, 0x0031, 0x0031, 0x0033, 0x00BF, + /* U+00C0 */ 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x00C6, 0x0043, + /* U+00C8 */ 0x0045, 0x0045, 0x0045, 0x0045, 0x0049, 0x0049, 0x0049, 0x0049, + /* U+00D0 */ 0x00D0, 0x004E, 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, 0x00D7, + /* U+00D8 */ 0x004F, 0x0055, 0x0055, 0x0055, 0x0055, 0x0059, 0x00DE, 0x0073, + // U+00D8: Manually changed from 00D8 to 004F + // TODO: Check if it's really acceptable to consider Ø a diacritical variant of O + // U+00DF: Manually changed from 00DF to 0073 + /* U+00E0 */ 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x00E6, 0x0063, + /* U+00E8 */ 0x0065, 0x0065, 0x0065, 0x0065, 0x0069, 0x0069, 0x0069, 0x0069, + /* U+00F0 */ 0x00F0, 0x006E, 0x006F, 0x006F, 0x006F, 0x006F, 0x006F, 0x00F7, + /* U+00F8 */ 0x006F, 0x0075, 0x0075, 0x0075, 0x0075, 0x0079, 0x00FE, 0x0079, + // U+00F8: Manually changed from 00F8 to 006F + // TODO: Check if it's really acceptable to consider ø a diacritical variant of o + /* U+0100 */ 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0043, 0x0063, + /* U+0108 */ 0x0043, 0x0063, 0x0043, 0x0063, 0x0043, 0x0063, 0x0044, 0x0064, + /* U+0110 */ 0x0110, 0x0111, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065, + /* U+0118 */ 0x0045, 0x0065, 0x0045, 0x0065, 0x0047, 0x0067, 0x0047, 0x0067, + /* U+0120 */ 0x0047, 0x0067, 0x0047, 0x0067, 0x0048, 0x0068, 0x0126, 0x0127, + /* U+0128 */ 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069, + /* U+0130 */ 0x0049, 0x0131, 0x0049, 0x0069, 0x004A, 0x006A, 0x004B, 0x006B, + /* U+0138 */ 0x0138, 0x004C, 0x006C, 0x004C, 0x006C, 0x004C, 0x006C, 0x004C, + /* U+0140 */ 0x006C, 0x004C, 0x006C, 0x004E, 0x006E, 0x004E, 0x006E, 0x004E, + // U+0141: Manually changed from 0141 to 004C + // U+0142: Manually changed from 0142 to 006C + /* U+0148 */ 0x006E, 0x02BC, 0x014A, 0x014B, 0x004F, 0x006F, 0x004F, 0x006F, + /* U+0150 */ 0x004F, 0x006F, 0x0152, 0x0153, 0x0052, 0x0072, 0x0052, 0x0072, + /* U+0158 */ 0x0052, 0x0072, 0x0053, 0x0073, 0x0053, 0x0073, 0x0053, 0x0073, + /* U+0160 */ 0x0053, 0x0073, 0x0054, 0x0074, 0x0054, 0x0074, 0x0166, 0x0167, + /* U+0168 */ 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, + /* U+0170 */ 0x0055, 0x0075, 0x0055, 0x0075, 0x0057, 0x0077, 0x0059, 0x0079, + /* U+0178 */ 0x0059, 0x005A, 0x007A, 0x005A, 0x007A, 0x005A, 0x007A, 0x0073, + /* U+0180 */ 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185, 0x0186, 0x0187, + /* U+0188 */ 0x0188, 0x0189, 0x018A, 0x018B, 0x018C, 0x018D, 0x018E, 0x018F, + /* U+0190 */ 0x0190, 0x0191, 0x0192, 0x0193, 0x0194, 0x0195, 0x0196, 0x0197, + /* U+0198 */ 0x0198, 0x0199, 0x019A, 0x019B, 0x019C, 0x019D, 0x019E, 0x019F, + /* U+01A0 */ 0x004F, 0x006F, 0x01A2, 0x01A3, 0x01A4, 0x01A5, 0x01A6, 0x01A7, + /* U+01A8 */ 0x01A8, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AD, 0x01AE, 0x0055, + /* U+01B0 */ 0x0075, 0x01B1, 0x01B2, 0x01B3, 0x01B4, 0x01B5, 0x01B6, 0x01B7, + /* U+01B8 */ 0x01B8, 0x01B9, 0x01BA, 0x01BB, 0x01BC, 0x01BD, 0x01BE, 0x01BF, + /* U+01C0 */ 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x0044, 0x0044, 0x0064, 0x004C, + /* U+01C8 */ 0x004C, 0x006C, 0x004E, 0x004E, 0x006E, 0x0041, 0x0061, 0x0049, + /* U+01D0 */ 0x0069, 0x004F, 0x006F, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, + // U+01D5: Manually changed from 00DC to 0055 + // U+01D6: Manually changed from 00FC to 0075 + // U+01D7: Manually changed from 00DC to 0055 + /* U+01D8 */ 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x01DD, 0x0041, 0x0061, + // U+01D8: Manually changed from 00FC to 0075 + // U+01D9: Manually changed from 00DC to 0055 + // U+01DA: Manually changed from 00FC to 0075 + // U+01DB: Manually changed from 00DC to 0055 + // U+01DC: Manually changed from 00FC to 0075 + // U+01DE: Manually changed from 00C4 to 0041 + // U+01DF: Manually changed from 00E4 to 0061 + /* U+01E0 */ 0x0041, 0x0061, 0x00C6, 0x00E6, 0x01E4, 0x01E5, 0x0047, 0x0067, + // U+01E0: Manually changed from 0226 to 0041 + // U+01E1: Manually changed from 0227 to 0061 + /* U+01E8 */ 0x004B, 0x006B, 0x004F, 0x006F, 0x004F, 0x006F, 0x01B7, 0x0292, + // U+01EC: Manually changed from 01EA to 004F + // U+01ED: Manually changed from 01EB to 006F + /* U+01F0 */ 0x006A, 0x0044, 0x0044, 0x0064, 0x0047, 0x0067, 0x01F6, 0x01F7, + /* U+01F8 */ 0x004E, 0x006E, 0x0041, 0x0061, 0x00C6, 0x00E6, 0x004F, 0x006F, + // U+01FA: Manually changed from 00C5 to 0041 + // U+01FB: Manually changed from 00E5 to 0061 + // U+01FE: Manually changed from 00D8 to 004F + // TODO: Check if it's really acceptable to consider Ø a diacritical variant of O + // U+01FF: Manually changed from 00F8 to 006F + // TODO: Check if it's really acceptable to consider ø a diacritical variant of o + /* U+0200 */ 0x0041, 0x0061, 0x0041, 0x0061, 0x0045, 0x0065, 0x0045, 0x0065, + /* U+0208 */ 0x0049, 0x0069, 0x0049, 0x0069, 0x004F, 0x006F, 0x004F, 0x006F, + /* U+0210 */ 0x0052, 0x0072, 0x0052, 0x0072, 0x0055, 0x0075, 0x0055, 0x0075, + /* U+0218 */ 0x0053, 0x0073, 0x0054, 0x0074, 0x021C, 0x021D, 0x0048, 0x0068, + /* U+0220 */ 0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0041, 0x0061, + /* U+0228 */ 0x0045, 0x0065, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F, + // U+022A: Manually changed from 00D6 to 004F + // U+022B: Manually changed from 00F6 to 006F + // U+022C: Manually changed from 00D5 to 004F + // U+022D: Manually changed from 00F5 to 006F + /* U+0230 */ 0x004F, 0x006F, 0x0059, 0x0079, 0x0234, 0x0235, 0x0236, 0x0237, + // U+0230: Manually changed from 022E to 004F + // U+0231: Manually changed from 022F to 006F + /* U+0238 */ 0x0238, 0x0239, 0x023A, 0x023B, 0x023C, 0x023D, 0x023E, 0x023F, + /* U+0240 */ 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247, + /* U+0248 */ 0x0248, 0x0249, 0x024A, 0x024B, 0x024C, 0x024D, 0x024E, 0x024F, + /* U+0250 */ 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257, + /* U+0258 */ 0x0258, 0x0259, 0x025A, 0x025B, 0x025C, 0x025D, 0x025E, 0x025F, + /* U+0260 */ 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267, + /* U+0268 */ 0x0268, 0x0269, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x026F, + /* U+0270 */ 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277, + /* U+0278 */ 0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F, + /* U+0280 */ 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287, + /* U+0288 */ 0x0288, 0x0289, 0x028A, 0x028B, 0x028C, 0x028D, 0x028E, 0x028F, + /* U+0290 */ 0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, + /* U+0298 */ 0x0298, 0x0299, 0x029A, 0x029B, 0x029C, 0x029D, 0x029E, 0x029F, + /* U+02A0 */ 0x02A0, 0x02A1, 0x02A2, 0x02A3, 0x02A4, 0x02A5, 0x02A6, 0x02A7, + /* U+02A8 */ 0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC, 0x02AD, 0x02AE, 0x02AF, + /* U+02B0 */ 0x0068, 0x0266, 0x006A, 0x0072, 0x0279, 0x027B, 0x0281, 0x0077, + /* U+02B8 */ 0x0079, 0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF, + /* U+02C0 */ 0x02C0, 0x02C1, 0x02C2, 0x02C3, 0x02C4, 0x02C5, 0x02C6, 0x02C7, + /* U+02C8 */ 0x02C8, 0x02C9, 0x02CA, 0x02CB, 0x02CC, 0x02CD, 0x02CE, 0x02CF, + /* U+02D0 */ 0x02D0, 0x02D1, 0x02D2, 0x02D3, 0x02D4, 0x02D5, 0x02D6, 0x02D7, + /* U+02D8 */ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x02DE, 0x02DF, + /* U+02E0 */ 0x0263, 0x006C, 0x0073, 0x0078, 0x0295, 0x02E5, 0x02E6, 0x02E7, + /* U+02E8 */ 0x02E8, 0x02E9, 0x02EA, 0x02EB, 0x02EC, 0x02ED, 0x02EE, 0x02EF, + /* U+02F0 */ 0x02F0, 0x02F1, 0x02F2, 0x02F3, 0x02F4, 0x02F5, 0x02F6, 0x02F7, + /* U+02F8 */ 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, 0x02FD, 0x02FE, 0x02FF, + /* U+0300 */ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, + /* U+0308 */ 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F, + /* U+0310 */ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, + /* U+0318 */ 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, + /* U+0320 */ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, + /* U+0328 */ 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, + /* U+0330 */ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, + /* U+0338 */ 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F, + /* U+0340 */ 0x0300, 0x0301, 0x0342, 0x0313, 0x0308, 0x0345, 0x0346, 0x0347, + /* U+0348 */ 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F, + /* U+0350 */ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, + /* U+0358 */ 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, + /* U+0360 */ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, + /* U+0368 */ 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F, + /* U+0370 */ 0x0370, 0x0371, 0x0372, 0x0373, 0x02B9, 0x0375, 0x0376, 0x0377, + /* U+0378 */ 0x0378, 0x0379, 0x0020, 0x037B, 0x037C, 0x037D, 0x003B, 0x037F, + /* U+0380 */ 0x0380, 0x0381, 0x0382, 0x0383, 0x0020, 0x00A8, 0x0391, 0x00B7, + /* U+0388 */ 0x0395, 0x0397, 0x0399, 0x038B, 0x039F, 0x038D, 0x03A5, 0x03A9, + /* U+0390 */ 0x03CA, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + /* U+0398 */ 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + /* U+03A0 */ 0x03A0, 0x03A1, 0x03A2, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, + /* U+03A8 */ 0x03A8, 0x03A9, 0x0399, 0x03A5, 0x03B1, 0x03B5, 0x03B7, 0x03B9, + /* U+03B0 */ 0x03CB, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + /* U+03B8 */ 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + /* U+03C0 */ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + /* U+03C8 */ 0x03C8, 0x03C9, 0x03B9, 0x03C5, 0x03BF, 0x03C5, 0x03C9, 0x03CF, + /* U+03D0 */ 0x03B2, 0x03B8, 0x03A5, 0x03D2, 0x03D2, 0x03C6, 0x03C0, 0x03D7, + /* U+03D8 */ 0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF, + /* U+03E0 */ 0x03E0, 0x03E1, 0x03E2, 0x03E3, 0x03E4, 0x03E5, 0x03E6, 0x03E7, + /* U+03E8 */ 0x03E8, 0x03E9, 0x03EA, 0x03EB, 0x03EC, 0x03ED, 0x03EE, 0x03EF, + /* U+03F0 */ 0x03BA, 0x03C1, 0x03C2, 0x03F3, 0x0398, 0x03B5, 0x03F6, 0x03F7, + /* U+03F8 */ 0x03F8, 0x03A3, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, + /* U+0400 */ 0x0415, 0x0415, 0x0402, 0x0413, 0x0404, 0x0405, 0x0406, 0x0406, + /* U+0408 */ 0x0408, 0x0409, 0x040A, 0x040B, 0x041A, 0x0418, 0x0423, 0x040F, + /* U+0410 */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + /* U+0418 */ 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + // U+0419: Manually changed from 0418 to 0419 + /* U+0420 */ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + /* U+0428 */ 0x0428, 0x0429, 0x042C, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + // U+042A: Manually changed from 042A to 042C + /* U+0430 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + /* U+0438 */ 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + // U+0439: Manually changed from 0438 to 0439 + /* U+0440 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + /* U+0448 */ 0x0448, 0x0449, 0x044C, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + // U+044A: Manually changed from 044A to 044C + /* U+0450 */ 0x0435, 0x0435, 0x0452, 0x0433, 0x0454, 0x0455, 0x0456, 0x0456, + /* U+0458 */ 0x0458, 0x0459, 0x045A, 0x045B, 0x043A, 0x0438, 0x0443, 0x045F, + /* U+0460 */ 0x0460, 0x0461, 0x0462, 0x0463, 0x0464, 0x0465, 0x0466, 0x0467, + /* U+0468 */ 0x0468, 0x0469, 0x046A, 0x046B, 0x046C, 0x046D, 0x046E, 0x046F, + /* U+0470 */ 0x0470, 0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0474, 0x0475, + /* U+0478 */ 0x0478, 0x0479, 0x047A, 0x047B, 0x047C, 0x047D, 0x047E, 0x047F, + /* U+0480 */ 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, + /* U+0488 */ 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F, + /* U+0490 */ 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, + /* U+0498 */ 0x0498, 0x0499, 0x049A, 0x049B, 0x049C, 0x049D, 0x049E, 0x049F, + /* U+04A0 */ 0x04A0, 0x04A1, 0x04A2, 0x04A3, 0x04A4, 0x04A5, 0x04A6, 0x04A7, + /* U+04A8 */ 0x04A8, 0x04A9, 0x04AA, 0x04AB, 0x04AC, 0x04AD, 0x04AE, 0x04AF, + /* U+04B0 */ 0x04B0, 0x04B1, 0x04B2, 0x04B3, 0x04B4, 0x04B5, 0x04B6, 0x04B7, + /* U+04B8 */ 0x04B8, 0x04B9, 0x04BA, 0x04BB, 0x04BC, 0x04BD, 0x04BE, 0x04BF, + /* U+04C0 */ 0x04C0, 0x0416, 0x0436, 0x04C3, 0x04C4, 0x04C5, 0x04C6, 0x04C7, + /* U+04C8 */ 0x04C8, 0x04C9, 0x04CA, 0x04CB, 0x04CC, 0x04CD, 0x04CE, 0x04CF, + /* U+04D0 */ 0x0410, 0x0430, 0x0410, 0x0430, 0x04D4, 0x04D5, 0x0415, 0x0435, + /* U+04D8 */ 0x04D8, 0x04D9, 0x04D8, 0x04D9, 0x0416, 0x0436, 0x0417, 0x0437, + /* U+04E0 */ 0x04E0, 0x04E1, 0x0418, 0x0438, 0x0418, 0x0438, 0x041E, 0x043E, + /* U+04E8 */ 0x04E8, 0x04E9, 0x04E8, 0x04E9, 0x042D, 0x044D, 0x0423, 0x0443, + /* U+04F0 */ 0x0423, 0x0443, 0x0423, 0x0443, 0x0427, 0x0447, 0x04F6, 0x04F7, + /* U+04F8 */ 0x042B, 0x044B, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF, + }; +} diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java index fcf043031..8caf6f17f 100644 --- a/java/src/com/android/inputmethod/latin/InputAttributes.java +++ b/java/src/com/android/inputmethod/latin/InputAttributes.java @@ -52,7 +52,8 @@ public final class InputAttributes { } else if (inputClass == 0) { // TODO: is this check still necessary? Log.w(TAG, String.format("Unexpected input class: inputType=0x%08x" - + " imeOptions=0x%08x", inputType, editorInfo.imeOptions)); + + " imeOptions=0x%08x", + inputType, editorInfo.imeOptions)); } mIsSettingsSuggestionStripOn = false; mInputTypeNoAutoCorrect = false; @@ -203,7 +204,8 @@ public final class InputAttributes { public static boolean inPrivateImeOptions(String packageName, String key, EditorInfo editorInfo) { if (editorInfo == null) return false; - final String findingKey = (packageName != null) ? packageName + "." + key : key; + final String findingKey = (packageName != null) ? packageName + "." + key + : key; return StringUtils.containsInCommaSplittableText(findingKey, editorInfo.privateImeOptions); } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 6a10131b0..77d07019f 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -68,6 +68,7 @@ import com.android.inputmethod.compat.InputMethodServiceCompatUtils; import com.android.inputmethod.compat.SuggestionSpanUtils; import com.android.inputmethod.dictionarypack.DictionaryPackConstants; import com.android.inputmethod.event.EventInterpreter; +import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardActionListener; import com.android.inputmethod.keyboard.KeyboardId; @@ -80,6 +81,7 @@ import com.android.inputmethod.latin.personalization.DictionaryDecayBroadcastRec import com.android.inputmethod.latin.personalization.PersonalizationDictionary; import com.android.inputmethod.latin.personalization.PersonalizationDictionarySessionRegister; import com.android.inputmethod.latin.personalization.PersonalizationHelper; +import com.android.inputmethod.latin.personalization.PersonalizationPredictionDictionary; import com.android.inputmethod.latin.personalization.UserHistoryDictionary; import com.android.inputmethod.latin.settings.Settings; import com.android.inputmethod.latin.settings.SettingsActivity; @@ -95,8 +97,8 @@ import com.android.inputmethod.latin.utils.InputTypeUtils; import com.android.inputmethod.latin.utils.IntentUtils; import com.android.inputmethod.latin.utils.JniUtils; import com.android.inputmethod.latin.utils.LatinImeLoggerUtils; -import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper; import com.android.inputmethod.latin.utils.RecapitalizeStatus; +import com.android.inputmethod.latin.utils.StaticInnerHandlerWrapper; import com.android.inputmethod.latin.utils.StringUtils; import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask; import com.android.inputmethod.latin.utils.TextRange; @@ -108,7 +110,6 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Locale; import java.util.TreeSet; -import java.util.concurrent.TimeUnit; /** * Input method implementation for Qwerty'ish keyboard. @@ -181,6 +182,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private boolean mIsMainDictionaryAvailable; private UserBinaryDictionary mUserDictionary; private UserHistoryDictionary mUserHistoryDictionary; + private PersonalizationPredictionDictionary mPersonalizationPredictionDictionary; private PersonalizationDictionary mPersonalizationDictionary; private boolean mIsUserDictionaryAvailable; @@ -194,6 +196,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private int mLastSelectionStart = NOT_A_CURSOR_POSITION; private int mLastSelectionEnd = NOT_A_CURSOR_POSITION; + // Whether we are expecting an onUpdateSelection event to fire. If it does when we don't + // "expect" it, it means the user actually moved the cursor. + private boolean mExpectingUpdateSelection; private int mDeleteCount; private long mLastKeyTime; private final TreeSet<Long> mCurrentlyPressedHardwareKeys = CollectionUtils.newTreeSet(); @@ -222,7 +227,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen public final UIHandler mHandler = new UIHandler(this); private InputUpdater mInputUpdater; - public static final class UIHandler extends LeakGuardHandlerWrapper<LatinIME> { + public static final class UIHandler extends StaticInnerHandlerWrapper<LatinIME> { private static final int MSG_UPDATE_SHIFT_STATE = 0; private static final int MSG_PENDING_IMS_CALLBACK = 1; private static final int MSG_UPDATE_SUGGESTION_STRIP = 2; @@ -231,8 +236,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private static final int MSG_REOPEN_DICTIONARIES = 5; private static final int MSG_ON_END_BATCH_INPUT = 6; private static final int MSG_RESET_CACHES = 7; - // Update this when adding new messages - private static final int MSG_LAST = MSG_RESET_CACHES; private static final int ARG1_NOT_GESTURE_INPUT = 0; private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1; @@ -245,12 +248,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private long mDoubleSpacePeriodTimeout; private long mDoubleSpacePeriodTimerStart; - public UIHandler(final LatinIME ownerInstance) { - super(ownerInstance); + public UIHandler(final LatinIME outerInstance) { + super(outerInstance); } public void onCreate() { - final Resources res = getOwnerInstance().getResources(); + final Resources res = getOuterInstance().getResources(); mDelayUpdateSuggestions = res.getInteger(R.integer.config_delay_update_suggestions); mDelayUpdateShiftState = @@ -261,7 +264,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen @Override public void handleMessage(final Message msg) { - final LatinIME latinIme = getOwnerInstance(); + final LatinIME latinIme = getOuterInstance(); final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher; switch (msg.what) { case MSG_UPDATE_SUGGESTION_STRIP: @@ -344,13 +347,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen removeMessages(MSG_UPDATE_SHIFT_STATE); } - @UsedForTesting - public void removeAllMessages() { - for (int i = 0; i <= MSG_LAST; ++i) { - removeMessages(i); - } - } - public void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords, final boolean dismissGestureFloatingPreviewText) { removeMessages(MSG_SHOW_GESTURE_PREVIEW_AND_SUGGESTION_STRIP); @@ -405,7 +401,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen removeMessages(MSG_PENDING_IMS_CALLBACK); resetPendingImsCallback(); mIsOrientationChanging = true; - final LatinIME latinIme = getOwnerInstance(); + final LatinIME latinIme = getOuterInstance(); if (latinIme.isInputViewShown()) { latinIme.mKeyboardSwitcher.saveKeyboardState(); } @@ -438,7 +434,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mIsOrientationChanging = false; mPendingSuccessiveImsCallback = true; } - final LatinIME latinIme = getOwnerInstance(); + final LatinIME latinIme = getOuterInstance(); executePendingImsCallback(latinIme, editorInfo, restarting); latinIme.onStartInputInternal(editorInfo, restarting); } @@ -457,7 +453,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK), PENDING_IMS_CALLBACK_DURATION); } - final LatinIME latinIme = getOwnerInstance(); + final LatinIME latinIme = getOuterInstance(); executePendingImsCallback(latinIme, editorInfo, restarting); latinIme.onStartInputViewInternal(editorInfo, restarting); mAppliedEditorInfo = editorInfo; @@ -469,7 +465,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Typically this is the first onFinishInputView after orientation changed. mHasPendingFinishInputView = true; } else { - final LatinIME latinIme = getOwnerInstance(); + final LatinIME latinIme = getOuterInstance(); latinIme.onFinishInputViewInternal(finishingInput); mAppliedEditorInfo = null; } @@ -480,7 +476,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Typically this is the first onFinishInput after orientation changed. mHasPendingFinishInput = true; } else { - final LatinIME latinIme = getOwnerInstance(); + final LatinIME latinIme = getOuterInstance(); executePendingImsCallback(latinIme, null, false); latinIme.onFinishInputInternal(); } @@ -613,6 +609,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final Locale switcherSubtypeLocale = mSubtypeSwitcher.getCurrentSubtypeLocale(); final String switcherLocaleStr = switcherSubtypeLocale.toString(); final Locale subtypeLocale; + final String localeStr; if (TextUtils.isEmpty(switcherLocaleStr)) { // This happens in very rare corner cases - for example, immediately after a switch // to LatinIME has been requested, about a frame later another switch happens. In this @@ -622,8 +619,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // of knowing anyway. Log.e(TAG, "System is reporting no current subtype."); subtypeLocale = getResources().getConfiguration().locale; + localeStr = subtypeLocale.toString(); } else { subtypeLocale = switcherSubtypeLocale; + localeStr = switcherLocaleStr; } final Suggest newSuggest = new Suggest(this /* Context */, subtypeLocale, @@ -638,16 +637,21 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen ResearchLogger.getInstance().initSuggest(newSuggest); } - mUserDictionary = new UserBinaryDictionary(this, subtypeLocale); + mUserDictionary = new UserBinaryDictionary(this, localeStr); mIsUserDictionaryAvailable = mUserDictionary.isEnabled(); newSuggest.setUserDictionary(mUserDictionary); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + mUserHistoryDictionary = PersonalizationHelper.getUserHistoryDictionary( - this, subtypeLocale); + this, localeStr, prefs); newSuggest.setUserHistoryDictionary(mUserHistoryDictionary); - mPersonalizationDictionary = - PersonalizationHelper.getPersonalizationDictionary(this, subtypeLocale); + mPersonalizationDictionary = PersonalizationHelper + .getPersonalizationDictionary(this, localeStr, prefs); newSuggest.setPersonalizationDictionary(mPersonalizationDictionary); + mPersonalizationPredictionDictionary = PersonalizationHelper + .getPersonalizationPredictionDictionary(this, localeStr, prefs); + newSuggest.setPersonalizationPredictionDictionary(mPersonalizationPredictionDictionary); final Suggest oldSuggest = mSuggest; resetContactsDictionary(null != oldSuggest ? oldSuggest.getContactsDictionary() : null); @@ -756,9 +760,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen .findViewById(android.R.id.extractArea); mKeyPreviewBackingView = view.findViewById(R.id.key_preview_backing); mSuggestionStripView = (SuggestionStripView)view.findViewById(R.id.suggestion_strip_view); - if (mSuggestionStripView != null) { + if (mSuggestionStripView != null) mSuggestionStripView.setListener(this, view); - } if (LatinImeLogger.sVISUALDEBUG) { mKeyPreviewBackingView.setBackgroundColor(0x10FF0000); } @@ -904,7 +907,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // refresh later. final boolean canReachInputConnection; if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess(editorInfo.initialSelStart, - editorInfo.initialSelEnd, false /* shouldFinishComposition */)) { + false /* shouldFinishComposition */)) { // We try resetting the caches up to 5 times before giving up. mHandler.postResetCaches(isDifferentTextField, 5 /* remainingTries */); // mLastSelection{Start,End} are reset later in this method, don't need to do it here @@ -1085,9 +1088,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen + ", ce=" + composingSpanEnd); } if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { + final boolean expectingUpdateSelectionFromLogger = + ResearchLogger.getAndClearLatinIMEExpectingUpdateSelection(); ResearchLogger.latinIME_onUpdateSelection(mLastSelectionStart, mLastSelectionEnd, oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, - composingSpanEnd, mConnection); + composingSpanEnd, mExpectingUpdateSelection, + expectingUpdateSelectionFromLogger, mConnection); + if (expectingUpdateSelectionFromLogger) { + // TODO: Investigate. Quitting now sounds wrong - we won't do the resetting work + return; + } } final boolean selectionChanged = mLastSelectionStart != newSelStart @@ -1106,8 +1116,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // TODO: revisit this when LatinIME supports hardware keyboards. // NOTE: the test harness subclasses LatinIME and overrides isInputViewShown(). // TODO: find a better way to simulate actual execution. - if (isInputViewShown() && !mConnection.isBelatedExpectedUpdate(oldSelStart, newSelStart, - oldSelEnd, newSelEnd)) { + if (isInputViewShown() && !mExpectingUpdateSelection + && !mConnection.isBelatedExpectedUpdate(oldSelStart, newSelStart)) { + // TAKE CARE: there is a race condition when we enter this test even when the user + // did not explicitly move the cursor. This happens when typing fast, where two keys + // turn this flag on in succession and both onUpdateSelection() calls arrive after + // the second one - the first call successfully avoids this test, but the second one + // enters. For the moment we rely on noComposingSpan to further reduce the impact. + // TODO: the following is probably better done in resetEntireInputState(). // it should only happen when the cursor moved, and the very purpose of the // test below is to narrow down whether this happened or not. Likewise with @@ -1133,13 +1149,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Another option would be to send suggestions each time we set the composing // text, but that is probably too expensive to do, so we decided to leave things // as is. - resetEntireInputState(newSelStart, newSelEnd); + resetEntireInputState(newSelStart); } else { - // resetEntireInputState calls resetCachesUponCursorMove, but forcing the - // composition to end. But in all cases where we don't reset the entire input - // state, we still want to tell the rich input connection about the new cursor - // position so that it can update its caches. - mConnection.resetCachesUponCursorMoveAndReturnSuccess(newSelStart, newSelEnd, + // resetEntireInputState calls resetCachesUponCursorMove, but with the second + // argument as true. But in all cases where we don't reset the entire input state, + // we still want to tell the rich input connection about the new cursor position so + // that it can update its caches. + mConnection.resetCachesUponCursorMoveAndReturnSuccess(newSelStart, false /* shouldFinishComposition */); } @@ -1152,6 +1168,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mRecapitalizeStatus.deactivate(); mKeyboardSwitcher.updateShiftState(); } + mExpectingUpdateSelection = false; // Make a note of the cursor position mLastSelectionStart = newSelStart; @@ -1337,7 +1354,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen @Override public boolean onEvaluateFullscreenMode() { // Reread resource value here, because this method is called by framework anytime as needed. - final boolean isFullscreenModeAllowed = Settings.readUseFullscreenMode(getResources()); + final boolean isFullscreenModeAllowed = + Settings.readUseFullscreenMode(getResources()); if (super.onEvaluateFullscreenMode() && isFullscreenModeAllowed) { // TODO: Remove this hack. Actually we should not really assume NO_EXTRACT_UI // implies NO_FULLSCREEN. However, the framework mistakenly does. i.e. NO_EXTRACT_UI @@ -1362,7 +1380,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // This will reset the whole input state to the starting state. It will clear // the composing word, reset the last composed word, tell the inputconnection about it. - private void resetEntireInputState(final int newSelStart, final int newSelEnd) { + private void resetEntireInputState(final int newCursorPosition) { final boolean shouldFinishComposition = mWordComposer.isComposingWord(); resetComposingState(true /* alsoResetLastComposedWord */); final SettingsValues settingsValues = mSettings.getCurrent(); @@ -1371,15 +1389,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } else { setSuggestedWords(settingsValues.mSuggestPuncList, false); } - mConnection.resetCachesUponCursorMoveAndReturnSuccess(newSelStart, newSelEnd, + mConnection.resetCachesUponCursorMoveAndReturnSuccess(newCursorPosition, shouldFinishComposition); } private void resetComposingState(final boolean alsoResetLastComposedWord) { mWordComposer.reset(); - if (alsoResetLastComposedWord) { + if (alsoResetLastComposedWord) mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; - } } private void commitTyped(final String separatorString) { @@ -1426,16 +1443,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (0 != (auto & TextUtils.CAP_MODE_CHARACTERS)) { return WordComposer.CAPS_MODE_AUTO_SHIFT_LOCKED; } - if (0 != auto) { - return WordComposer.CAPS_MODE_AUTO_SHIFTED; - } + if (0 != auto) return WordComposer.CAPS_MODE_AUTO_SHIFTED; return WordComposer.CAPS_MODE_OFF; } private void swapSwapperAndSpace() { final CharSequence lastTwo = mConnection.getTextBeforeCursor(2, 0); // It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called. - if (lastTwo != null && lastTwo.length() == 2 && lastTwo.charAt(0) == Constants.CODE_SPACE) { + if (lastTwo != null && lastTwo.length() == 2 + && lastTwo.charAt(0) == Constants.CODE_SPACE) { mConnection.deleteSurroundingText(2, 0); final String text = lastTwo.charAt(1) + " "; mConnection.commitText(text, 1); @@ -1714,7 +1730,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can insert the character at the current cursor position. - resetEntireInputState(mLastSelectionStart, mLastSelectionEnd); + resetEntireInputState(mLastSelectionStart); } else { commitTyped(LastComposedWord.NOT_A_SEPARATOR); } @@ -1730,6 +1746,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } handleCharacter(primaryCode, keyX, keyY, spaceState); } + mExpectingUpdateSelection = true; return didAutoCorrect; } @@ -1769,9 +1786,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mInputUpdater.onStartBatchInput(); mHandler.cancelUpdateSuggestionStrip(); mConnection.beginBatchEdit(); - final SettingsValues currentSettingsValues = mSettings.getCurrent(); + final SettingsValues settingsValues = mSettings.getCurrent(); if (mWordComposer.isComposingWord()) { - if (currentSettingsValues.mIsInternal) { + if (settingsValues.mIsInternal) { if (mWordComposer.isBatchMode()) { LatinImeLoggerUtils.onAutoCorrection( "", mWordComposer.getTypedWord(), " ", mWordComposer); @@ -1782,7 +1799,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can insert the batch input at the current cursor position. - resetEntireInputState(mLastSelectionStart, mLastSelectionEnd); + resetEntireInputState(mLastSelectionStart); } else if (wordComposerSize <= 1) { // We auto-correct the previous (typed, not gestured) string iff it's one character // long. The reason for this is, even in the middle of gesture typing, you'll still @@ -1795,17 +1812,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } else { commitTyped(LastComposedWord.NOT_A_SEPARATOR); } + mExpectingUpdateSelection = true; } final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor(); if (Character.isLetterOrDigit(codePointBeforeCursor) - || currentSettingsValues.isUsuallyFollowedBySpace(codePointBeforeCursor)) { + || settingsValues.isUsuallyFollowedBySpace(codePointBeforeCursor)) { mSpaceState = SPACE_STATE_PHANTOM; } mConnection.endBatchEdit(); - mKeyboardSwitcher.updateShiftState(); - mWordComposer.setCapitalizedModeAndPreviousWordAtStartComposingTime(getActualCapsMode(), - // Prev word is 1st word before cursor - getNthPreviousWordForSuggestion(currentSettingsValues, 1 /* nthPreviousWord */)); + mWordComposer.setCapitalizedModeAtStartComposingTime(getActualCapsMode()); } static final class InputUpdater implements Handler.Callback { @@ -1978,8 +1993,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mConnection.commitText(commitParts[0], 0); mSpaceState = SPACE_STATE_PHANTOM; mKeyboardSwitcher.updateShiftState(); - mWordComposer.setCapitalizedModeAndPreviousWordAtStartComposingTime( - getActualCapsMode(), commitParts[0]); + mWordComposer.setCapitalizedModeAtStartComposingTime(getActualCapsMode()); ++mAutoCommitSequenceNumber; } } @@ -1989,7 +2003,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // This method must run in UI Thread. public void onEndBatchInputAsyncInternal(final SuggestedWords suggestedWords) { - final String batchInputText = suggestedWords.isEmpty() ? null : suggestedWords.getWord(0); + final String batchInputText = suggestedWords.isEmpty() + ? null : suggestedWords.getWord(0); if (TextUtils.isEmpty(batchInputText)) { return; } @@ -2011,6 +2026,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mWordComposer.setBatchInputWord(batchInputText); mConnection.setComposingText(batchInputText, 1); } + mExpectingUpdateSelection = true; mConnection.endBatchEdit(); if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.latinIME_onEndBatchInput(batchInputText, 0, suggestedWords); @@ -2064,7 +2080,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } private void handleBackspace(final int spaceState) { + // We revert these in this method if the deletion doesn't happen. mDeleteCount++; + mExpectingUpdateSelection = true; // In many cases, we may have to put the keyboard in auto-shift state again. However // we want to wait a few milliseconds before doing it to avoid the keyboard flashing @@ -2074,7 +2092,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can remove the character at the current cursor position. - resetEntireInputState(mLastSelectionStart, mLastSelectionEnd); + resetEntireInputState(mLastSelectionStart); // When we exit this if-clause, mWordComposer.isComposingWord() will return false. } if (mWordComposer.isComposingWord()) { @@ -2145,10 +2163,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // later (typically, in a subsequent press on backspace). mLastSelectionEnd = mLastSelectionStart; mConnection.deleteSurroundingText(numCharsDeleted, 0); - if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { - ResearchLogger.latinIME_handleBackspace(numCharsDeleted, - false /* shouldUncommitLogUnit */); - } } else { // There is no selection, just delete one character. if (NOT_A_CURSOR_POSITION == mLastSelectionEnd) { @@ -2171,27 +2185,22 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } else { final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor(); if (codePointBeforeCursor == Constants.NOT_A_CODE) { - // Nothing to delete before the cursor. + // Nothing to delete before the cursor. We have to revert the deletion + // states that were updated at the beginning of this method. + mDeleteCount--; + mExpectingUpdateSelection = false; return; } final int lengthToDelete = Character.isSupplementaryCodePoint(codePointBeforeCursor) ? 2 : 1; mConnection.deleteSurroundingText(lengthToDelete, 0); - if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { - ResearchLogger.latinIME_handleBackspace(lengthToDelete, - true /* shouldUncommitLogUnit */); - } if (mDeleteCount > DELETE_ACCELERATE_AT) { final int codePointBeforeCursorToDeleteAgain = mConnection.getCodePointBeforeCursor(); if (codePointBeforeCursorToDeleteAgain != Constants.NOT_A_CODE) { final int lengthToDeleteAgain = Character.isSupplementaryCodePoint( - codePointBeforeCursorToDeleteAgain) ? 2 : 1; + codePointBeforeCursorToDeleteAgain) ? 2 : 1; mConnection.deleteSurroundingText(lengthToDeleteAgain, 0); - if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { - ResearchLogger.latinIME_handleBackspace(lengthToDeleteAgain, - true /* shouldUncommitLogUnit */); - } } } } @@ -2208,8 +2217,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen /* * Strip a trailing space if necessary and returns whether it's a swap weak space situation. */ - private boolean maybeStripSpace(final int code, final int spaceState, - final boolean isFromSuggestionStrip) { + private boolean maybeStripSpace(final int code, + final int spaceState, final boolean isFromSuggestionStrip) { if (Constants.CODE_ENTER == code && SPACE_STATE_SWAP_PUNCTUATION == spaceState) { mConnection.removeTrailingSpace(); return false; @@ -2224,8 +2233,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen return false; } - private void handleCharacter(final int primaryCode, final int x, final int y, - final int spaceState) { + private void handleCharacter(final int primaryCode, final int x, + final int y, final int spaceState) { // TODO: refactor this method to stop flipping isComposingWord around all the time, and // make it shorter (possibly cut into several pieces). Also factor handleNonSpecialCharacter // which has the same name as other handle* methods but is not the same. @@ -2245,7 +2254,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can insert the character at the current cursor position. - resetEntireInputState(mLastSelectionStart, mLastSelectionEnd); + resetEntireInputState(mLastSelectionStart); isComposingWord = false; } // We want to find out whether to start composing a new word with this character. If so, @@ -2275,24 +2284,25 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen resetComposingState(false /* alsoResetLastComposedWord */); } if (isComposingWord) { - final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); - // TODO: We should reconsider which coordinate system should be used to represent - // keyboard event. - final int keyX = mainKeyboardView.getKeyX(x); - final int keyY = mainKeyboardView.getKeyY(y); + final int keyX, keyY; + if (Constants.isValidCoordinate(x) && Constants.isValidCoordinate(y)) { + final KeyDetector keyDetector = + mKeyboardSwitcher.getMainKeyboardView().getKeyDetector(); + keyX = keyDetector.getTouchX(x); + keyY = keyDetector.getTouchY(y); + } else { + keyX = x; + keyY = y; + } mWordComposer.add(primaryCode, keyX, keyY); // If it's the first letter, make note of auto-caps state if (mWordComposer.size() == 1) { - // We pass 1 to getPreviousWordForSuggestion because we were not composing a word - // yet, so the word we want is the 1st word before the cursor. - mWordComposer.setCapitalizedModeAndPreviousWordAtStartComposingTime( - getActualCapsMode(), - getNthPreviousWordForSuggestion(currentSettings, 1 /* nthPreviousWord */)); + mWordComposer.setCapitalizedModeAtStartComposingTime(getActualCapsMode()); } mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); } else { - final boolean swapWeakSpace = maybeStripSpace(primaryCode, spaceState, - Constants.SUGGESTION_STRIP_COORDINATE == x); + final boolean swapWeakSpace = maybeStripSpace(primaryCode, + spaceState, Constants.SUGGESTION_STRIP_COORDINATE == x); sendKeyCodePoint(primaryCode); @@ -2356,7 +2366,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can insert the separator at the current cursor position. - resetEntireInputState(mLastSelectionStart, mLastSelectionEnd); + resetEntireInputState(mLastSelectionStart); } if (mWordComposer.isComposingWord()) { // May have changed since we stored wasComposing if (currentSettings.mCorrectionEnabled) { @@ -2529,24 +2539,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } - /** - * Get the nth previous word before the cursor as context for the suggestion process. - * @param currentSettings the current settings values. - * @param nthPreviousWord reverse index of the word to get (1-indexed) - * @return the nth previous word before the cursor. - */ - private String getNthPreviousWordForSuggestion(final SettingsValues currentSettings, - final int nthPreviousWord) { - if (currentSettings.mCurrentLanguageHasSpaces) { - // If we are typing in a language with spaces we can just look up the previous - // word from textview. - return mConnection.getNthPreviousWord(currentSettings, nthPreviousWord); - } else { - return LastComposedWord.NOT_A_COMPOSED_WORD == mLastComposedWord ? null - : mLastComposedWord.mCommittedWord; - } - } - private void getSuggestedWords(final int sessionId, final int sequenceNumber, final OnGetSuggestedWordsCallback callback) { final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); @@ -2560,31 +2552,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // should just skip whitespace if any, so 1. final SettingsValues currentSettings = mSettings.getCurrent(); final int[] additionalFeaturesOptions = currentSettings.mAdditionalFeaturesSettingValues; - - final String previousWord; - if (mWordComposer.isComposingWord() || mWordComposer.isBatchMode()) { - previousWord = mWordComposer.getPreviousWord(); - } else { - // Not composing: this is for prediction. - // TODO: read the previous word earlier for prediction, like we are doing for - // normal suggestions. - previousWord = getNthPreviousWordForSuggestion(currentSettings, 1 /* nthPreviousWord*/); - } - if (DEBUG) { - // TODO: this is for checking consistency with older versions. Remove this when - // we are confident this is stable. - // We're checking the previous word in the text field against the memorized previous - // word. If we are composing a word we should have the second word before the cursor - // memorized, otherwise we should have the first. - final String rereadPrevWord = getNthPreviousWordForSuggestion(currentSettings, + final String prevWord; + if (currentSettings.mCurrentLanguageHasSpaces) { + // If we are typing in a language with spaces we can just look up the previous + // word from textview. + prevWord = mConnection.getNthPreviousWord(currentSettings.mWordSeparators, mWordComposer.isComposingWord() ? 2 : 1); - if (!TextUtils.equals(previousWord, rereadPrevWord)) { - throw new RuntimeException("Unexpected previous word: " - + previousWord + " <> " + rereadPrevWord); - } + } else { + prevWord = LastComposedWord.NOT_A_COMPOSED_WORD == mLastComposedWord ? null + : mLastComposedWord.mCommittedWord; } - suggest.getSuggestedWords(mWordComposer, mWordComposer.getPreviousWord(), - keyboard.getProximityInfo(), + suggest.getSuggestedWords(mWordComposer, prevWord, keyboard.getProximityInfo(), currentSettings.mBlockPotentiallyOffensive, currentSettings.mCorrectionEnabled, additionalFeaturesOptions, sessionId, sequenceNumber, callback); } @@ -2701,6 +2679,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen ResearchLogger.latinIme_commitCurrentAutoCorrection(typedWord, autoCorrection, separator, mWordComposer.isBatchMode(), suggestedWords); } + mExpectingUpdateSelection = true; commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD, separator); if (!typedWord.equals(autoCorrection)) { @@ -2771,6 +2750,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // typed word. final String replacedWord = mWordComposer.getTypedWord(); LatinImeLogger.logOnManualSuggestion(replacedWord, suggestion, index, suggestedWords); + mExpectingUpdateSelection = true; commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK, LastComposedWord.NOT_A_SEPARATOR); if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { @@ -2853,7 +2833,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final UserHistoryDictionary userHistoryDictionary = mUserHistoryDictionary; if (userHistoryDictionary == null) return null; - final String prevWord = mConnection.getNthPreviousWord(currentSettings, 2); + final String prevWord = mConnection.getNthPreviousWord(currentSettings.mWordSeparators, 2); final String secondWord; if (mWordComposer.wasAutoCapitalized() && !mWordComposer.isMostlyCaps()) { secondWord = suggestion.toLowerCase(mSubtypeSwitcher.getCurrentSubtypeLocale()); @@ -2865,8 +2845,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final int maxFreq = AutoCorrectionUtils.getMaxFrequency( suggest.getUnigramDictionaries(), suggestion); if (maxFreq == 0) return null; - userHistoryDictionary.addToDictionary(prevWord, secondWord, maxFreq > 0, - (int)TimeUnit.MILLISECONDS.toSeconds((System.currentTimeMillis()))); + userHistoryDictionary.addToDictionary(prevWord, secondWord, maxFreq > 0); return prevWord; } @@ -2922,13 +2901,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } } - mWordComposer.setComposingWord(typedWord, - getNthPreviousWordForSuggestion(currentSettings, - // We want the previous word for suggestion. If we have chars in the word - // before the cursor, then we want the word before that, hence 2; otherwise, - // we want the word immediately before the cursor, hence 1. - 0 == numberOfCharsInWordBeforeCursor ? 1 : 2), - mKeyboardSwitcher.getKeyboard()); + mWordComposer.setComposingWord(typedWord, mKeyboardSwitcher.getKeyboard()); mWordComposer.setCursorPositionWithinWord( typedWord.codePointCount(0, numberOfCharsInWordBeforeCursor)); mConnection.setComposingRegion( @@ -3006,11 +2979,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } private void restartSuggestionsOnWordBeforeCursor(final String word) { - mWordComposer.setComposingWord(word, - // Previous word is the 2nd word before cursor because we are restarting on the - // 1st word before cursor. - getNthPreviousWordForSuggestion(mSettings.getCurrent(), 2 /* nthPreviousWord */), - mKeyboardSwitcher.getKeyboard()); + mWordComposer.setComposingWord(word, mKeyboardSwitcher.getKeyboard()); final int length = word.length(); mConnection.deleteSurroundingText(length, 0); mConnection.setComposingText(word, 1); @@ -3028,8 +2997,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen * @param remainingTries How many times we may try again before giving up. */ private void retryResetCaches(final boolean tryResumeSuggestions, final int remainingTries) { - if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess(mLastSelectionStart, - mLastSelectionEnd, false)) { + if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess(mLastSelectionStart, false)) { if (0 < remainingTries) { mHandler.postResetCaches(tryResumeSuggestions, remainingTries - 1); return; @@ -3056,7 +3024,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen throw new RuntimeException("revertCommit, but we are composing a word"); } final CharSequence wordBeforeCursor = - mConnection.getTextBeforeCursor(deleteLength, 0).subSequence(0, cancelLength); + mConnection.getTextBeforeCursor(deleteLength, 0) + .subSequence(0, cancelLength); if (!TextUtils.equals(committedWord, wordBeforeCursor)) { throw new RuntimeException("revertCommit check failed: we thought we were " + "reverting \"" + committedWord @@ -3076,8 +3045,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } else { // For languages without spaces, we revert the typed string but the cursor is flush // with the typed word, so we need to resume suggestions right away. - mWordComposer.setComposingWord(stringToCommit, previousWord, - mKeyboardSwitcher.getKeyboard()); + mWordComposer.setComposingWord(stringToCommit, mKeyboardSwitcher.getKeyboard()); mConnection.setComposingText(stringToCommit, 1); } if (mSettings.isInternal()) { @@ -3127,8 +3095,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private void hapticAndAudioFeedback(final int code, final int repeatCount) { final MainKeyboardView keyboardView = mKeyboardSwitcher.getMainKeyboardView(); - if (keyboardView != null && keyboardView.isInDraggingFinger()) { - // No need to feedback while finger is dragging. + if (keyboardView != null && keyboardView.isInSlidingKeyInput()) { + // No need to feedback while sliding input. return; } if (repeatCount > 0) { @@ -3258,8 +3226,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final Intent intent = IntentUtils.getInputLanguageSelectionIntent( mRichImm.getInputMethodIdOfThisIme(), Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED - | Intent.FLAG_ACTIVITY_CLEAR_TOP); + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED + | Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); break; case 1: @@ -3268,8 +3236,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } }; - final AlertDialog.Builder builder = - new AlertDialog.Builder(this).setItems(items, listener).setTitle(title); + final AlertDialog.Builder builder = new AlertDialog.Builder(this) + .setItems(items, listener) + .setTitle(title); showOptionDialog(builder.create()); } @@ -3330,13 +3299,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final Printer p = new PrintWriterPrinter(fout); p.println("LatinIME state :"); - p.println(" VersionCode = " + ApplicationUtils.getVersionCode(this)); - p.println(" VersionName = " + ApplicationUtils.getVersionName(this)); 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(" mIsSuggestionsRequested = " + p.println(" mIsSuggestionsSuggestionsRequested = " + settingsValues.isSuggestionsRequested(mDisplayOrientation)); p.println(" mCorrectionEnabled=" + settingsValues.mCorrectionEnabled); p.println(" isComposingWord=" + mWordComposer.isComposingWord()); diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index 37311acf2..673d1b4c2 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -57,19 +57,14 @@ public final class RichInputConnection { private static final int INVALID_CURSOR_POSITION = -1; /** - * This variable contains an expected value for the selection start position. This is where the - * cursor or selection start may end up after all the keyboard-triggered updates have passed. We - * keep this to compare it to the actual selection start to guess whether the move was caused by - * a keyboard command or not. - * It's not really the selection start position: the selection start may not be there yet, and - * in some cases, it may never arrive there. + * This variable contains an expected value for the cursor position. This is where the + * cursor may end up after all the keyboard-triggered updates have passed. We keep this to + * compare it to the actual cursor position to guess whether the move was caused by a + * keyboard command or not. + * It's not really the cursor position: the cursor may not be there yet, and it's also expected + * there be cases where it never actually comes to be there. */ - private int mExpectedSelStart = INVALID_CURSOR_POSITION; // in chars, not code points - /** - * The expected selection end. Only differs from mExpectedSelStart if a non-empty selection is - * expected. The same caveats as mExpectedSelStart apply. - */ - private int mExpectedSelEnd = INVALID_CURSOR_POSITION; // in chars, not code points + private int mExpectedCursorPosition = INVALID_CURSOR_POSITION; // in chars, not code points /** * This contains the committed text immediately preceding the cursor and the composing * text if any. It is refreshed when the cursor moves by calling upon the TextView. @@ -108,16 +103,16 @@ public final class RichInputConnection { final String reference = (beforeCursor.length() <= actualLength) ? beforeCursor.toString() : beforeCursor.subSequence(beforeCursor.length() - actualLength, beforeCursor.length()).toString(); - if (et.selectionStart != mExpectedSelStart + if (et.selectionStart != mExpectedCursorPosition || !(reference.equals(internal.toString()))) { - final String context = "Expected selection start = " + mExpectedSelStart - + "\nActual selection start = " + et.selectionStart + final String context = "Expected cursor position = " + mExpectedCursorPosition + + "\nActual cursor position = " + et.selectionStart + "\nExpected text = " + internal.length() + " " + internal + "\nActual text = " + reference.length() + " " + reference; ((LatinIME)mParent).debugDumpStateAndCrashWithException(context); } else { Log.e(TAG, DebugLogUtils.getStackTrace(2)); - Log.e(TAG, "Exp <> Actual : " + mExpectedSelStart + " <> " + et.selectionStart); + Log.e(TAG, "Exp <> Actual : " + mExpectedCursorPosition + " <> " + et.selectionStart); } } @@ -155,50 +150,16 @@ public final class RichInputConnection { * data, so we empty the cache and note that we don't know the new cursor position, and we * return false so that the caller knows about this and can retry later. * - * @param newSelStart the new position of the selection start, as received from the system. - * @param newSelEnd the new position of the selection end, as received from the system. - * @param shouldFinishComposition whether we should finish the composition in progress. + * @param newCursorPosition The new position of the cursor, as received from the system. + * @param shouldFinishComposition Whether we should finish the composition in progress. * @return true if we were able to connect to the editor successfully, false otherwise. When * this method returns false, the caches could not be correctly refreshed so they were only * reset: the caller should try again later to return to normal operation. */ - public boolean resetCachesUponCursorMoveAndReturnSuccess(final int newSelStart, - final int newSelEnd, final boolean shouldFinishComposition) { - mExpectedSelStart = newSelStart; - mExpectedSelEnd = newSelEnd; + public boolean resetCachesUponCursorMoveAndReturnSuccess(final int newCursorPosition, + final boolean shouldFinishComposition) { + mExpectedCursorPosition = newCursorPosition; mComposingText.setLength(0); - final boolean didReloadTextSuccessfully = reloadTextCache(); - if (!didReloadTextSuccessfully) { - Log.d(TAG, "Will try to retrieve text later."); - return false; - } - final int lengthOfTextBeforeCursor = mCommittedTextBeforeComposingText.length(); - if (lengthOfTextBeforeCursor > newSelStart - || (lengthOfTextBeforeCursor < Constants.EDITOR_CONTENTS_CACHE_SIZE - && newSelStart < Constants.EDITOR_CONTENTS_CACHE_SIZE)) { - // newSelStart and newSelEnd may be lying -- when rotating the device (probably a - // framework bug). If we have less chars than we asked for, then we know how many chars - // we have, and if we got more than newSelStart says, then we know it was lying. In both - // cases the length is more reliable. Note that we only have to check newSelStart (not - // newSelEnd) since if newSelEnd is wrong, the newSelStart will be wrong as well. - mExpectedSelStart = lengthOfTextBeforeCursor; - mExpectedSelEnd = lengthOfTextBeforeCursor; - } - if (null != mIC && shouldFinishComposition) { - mIC.finishComposingText(); - if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { - ResearchLogger.richInputConnection_finishComposingText(); - } - } - return true; - } - - /** - * Reload the cached text from the InputConnection. - * - * @return true if successful - */ - private boolean reloadTextCache() { mCommittedTextBeforeComposingText.setLength(0); mIC = mParent.getCurrentInputConnection(); // Call upon the inputconnection directly since our own method is using the cache, and @@ -208,12 +169,27 @@ public final class RichInputConnection { if (null == textBeforeCursor) { // For some reason the app thinks we are not connected to it. This looks like a // framework bug... Fall back to ground state and return false. - mExpectedSelStart = INVALID_CURSOR_POSITION; - mExpectedSelEnd = INVALID_CURSOR_POSITION; - Log.e(TAG, "Unable to connect to the editor to retrieve text."); + mExpectedCursorPosition = INVALID_CURSOR_POSITION; + Log.e(TAG, "Unable to connect to the editor to retrieve text... will retry later"); return false; } mCommittedTextBeforeComposingText.append(textBeforeCursor); + final int lengthOfTextBeforeCursor = textBeforeCursor.length(); + if (lengthOfTextBeforeCursor > newCursorPosition + || (lengthOfTextBeforeCursor < Constants.EDITOR_CONTENTS_CACHE_SIZE + && newCursorPosition < Constants.EDITOR_CONTENTS_CACHE_SIZE)) { + // newCursorPosition may be lying -- when rotating the device (probably a framework + // bug). If we have less chars than we asked for, then we know how many chars we have, + // and if we got more than newCursorPosition says, then we know it was lying. In both + // cases the length is more reliable + mExpectedCursorPosition = lengthOfTextBeforeCursor; + } + if (null != mIC && shouldFinishComposition) { + mIC.finishComposingText(); + if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { + ResearchLogger.richInputConnection_finishComposingText(); + } + } return true; } @@ -242,8 +218,7 @@ public final class RichInputConnection { if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); mCommittedTextBeforeComposingText.append(text); - mExpectedSelStart += text.length() - mComposingText.length(); - mExpectedSelEnd = mExpectedSelStart; + mExpectedCursorPosition += text.length() - mComposingText.length(); mComposingText.setLength(0); if (null != mIC) { mIC.commitText(text, i); @@ -256,7 +231,7 @@ public final class RichInputConnection { } public boolean canDeleteCharacters() { - return mExpectedSelStart > 0; + return mExpectedCursorPosition > 0; } /** @@ -293,10 +268,11 @@ public final class RichInputConnection { // heavy pressing of delete, for example DEFAULT_TEXT_CACHE_SIZE - 5 times or so. // getCapsMode should be updated to be able to return a "not enough info" result so that // we can get more context only when needed. - if (TextUtils.isEmpty(mCommittedTextBeforeComposingText) && 0 != mExpectedSelStart) { - if (!reloadTextCache()) { - Log.w(TAG, "Unable to connect to the editor. " - + "Setting caps mode without knowing text."); + if (TextUtils.isEmpty(mCommittedTextBeforeComposingText) && 0 != mExpectedCursorPosition) { + final CharSequence textBeforeCursor = getTextBeforeCursor( + Constants.EDITOR_CONTENTS_CACHE_SIZE, 0); + if (!TextUtils.isEmpty(textBeforeCursor)) { + mCommittedTextBeforeComposingText.append(textBeforeCursor); } } // This never calls InputConnection#getCapsMode - in fact, it's a static method that @@ -319,8 +295,8 @@ public final class RichInputConnection { // However, if we don't have an expected cursor position, then we should always // go fetch the cache again (as it happens, INVALID_CURSOR_POSITION < 0, so we need to // test for this explicitly) - if (INVALID_CURSOR_POSITION != mExpectedSelStart - && (cachedLength >= n || cachedLength >= mExpectedSelStart)) { + if (INVALID_CURSOR_POSITION != mExpectedCursorPosition + && (cachedLength >= n || cachedLength >= mExpectedCursorPosition)) { final StringBuilder s = new StringBuilder(mCommittedTextBeforeComposingText); // We call #toString() here to create a temporary object. // In some situations, this method is called on a worker thread, and it's possible @@ -360,14 +336,10 @@ public final class RichInputConnection { + remainingChars, 0); mCommittedTextBeforeComposingText.setLength(len); } - if (mExpectedSelStart > beforeLength) { - mExpectedSelStart -= beforeLength; - mExpectedSelEnd -= beforeLength; + if (mExpectedCursorPosition > beforeLength) { + mExpectedCursorPosition -= beforeLength; } else { - // There are fewer characters before the cursor in the buffer than we are being asked to - // delete. Only delete what is there. - mExpectedSelStart = 0; - mExpectedSelEnd -= mExpectedSelStart; + mExpectedCursorPosition = 0; } if (null != mIC) { mIC.deleteSurroundingText(beforeLength, afterLength); @@ -401,8 +373,7 @@ public final class RichInputConnection { switch (keyEvent.getKeyCode()) { case KeyEvent.KEYCODE_ENTER: mCommittedTextBeforeComposingText.append("\n"); - mExpectedSelStart += 1; - mExpectedSelEnd = mExpectedSelStart; + mExpectedCursorPosition += 1; break; case KeyEvent.KEYCODE_DEL: if (0 == mComposingText.length()) { @@ -414,24 +385,18 @@ public final class RichInputConnection { } else { mComposingText.delete(mComposingText.length() - 1, mComposingText.length()); } - if (mExpectedSelStart > 0 && mExpectedSelStart == mExpectedSelEnd) { - // TODO: Handle surrogate pairs. - mExpectedSelStart -= 1; - } - mExpectedSelEnd = mExpectedSelStart; + if (mExpectedCursorPosition > 0) mExpectedCursorPosition -= 1; break; case KeyEvent.KEYCODE_UNKNOWN: if (null != keyEvent.getCharacters()) { mCommittedTextBeforeComposingText.append(keyEvent.getCharacters()); - mExpectedSelStart += keyEvent.getCharacters().length(); - mExpectedSelEnd = mExpectedSelStart; + mExpectedCursorPosition += keyEvent.getCharacters().length(); } break; default: - final String text = StringUtils.newSingleCodePointString(keyEvent.getUnicodeChar()); + final String text = new String(new int[] { keyEvent.getUnicodeChar() }, 0, 1); mCommittedTextBeforeComposingText.append(text); - mExpectedSelStart += text.length(); - mExpectedSelEnd = mExpectedSelStart; + mExpectedCursorPosition += text.length(); break; } } @@ -465,12 +430,10 @@ public final class RichInputConnection { public void setComposingText(final CharSequence text, final int newCursorPosition) { if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); - mExpectedSelStart += text.length() - mComposingText.length(); - mExpectedSelEnd = mExpectedSelStart; + mExpectedCursorPosition += text.length() - mComposingText.length(); mComposingText.setLength(0); mComposingText.append(text); - // TODO: support values of newCursorPosition != 1. At this time, this is never called with - // newCursorPosition != 1. + // TODO: support values of i != 1. At this time, this is never called with i != 1. if (null != mIC) { mIC.setComposingText(text, newCursorPosition); if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { @@ -480,31 +443,19 @@ public final class RichInputConnection { if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); } - /** - * Set the selection of the text editor. - * - * Calls through to {@link InputConnection#setSelection(int, int)}. - * - * @param start the character index where the selection should start. - * @param end the character index where the selection should end. - * @return Returns true on success, false if the input connection is no longer valid either when - * setting the selection or when retrieving the text cache at that point. - */ - public boolean setSelection(final int start, final int end) { + public void setSelection(final int start, final int end) { if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); - mExpectedSelStart = start; - mExpectedSelEnd = end; if (null != mIC) { - final boolean isIcValid = mIC.setSelection(start, end); - if (!isIcValid) { - return false; - } + mIC.setSelection(start, end); if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.richInputConnection_setSelection(start, end); } } - return reloadTextCache(); + mExpectedCursorPosition = start; + mCommittedTextBeforeComposingText.setLength(0); + mCommittedTextBeforeComposingText.append( + getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE, 0)); } public void commitCorrection(final CorrectionInfo correctionInfo) { @@ -525,8 +476,7 @@ public final class RichInputConnection { // text should never be null, but just in case, it's better to insert nothing than to crash if (null == text) text = ""; mCommittedTextBeforeComposingText.append(text); - mExpectedSelStart += text.length() - mComposingText.length(); - mExpectedSelEnd = mExpectedSelStart; + mExpectedCursorPosition += text.length() - mComposingText.length(); mComposingText.setLength(0); if (null != mIC) { mIC.commitCompletion(completionInfo); @@ -538,7 +488,7 @@ public final class RichInputConnection { } @SuppressWarnings("unused") - public String getNthPreviousWord(final SettingsValues currentSettingsValues, final int n) { + public String getNthPreviousWord(final String sentenceSeperators, final int n) { mIC = mParent.getCurrentInputConnection(); if (null == mIC) return null; final CharSequence prev = getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); @@ -557,7 +507,7 @@ public final class RichInputConnection { } } } - return getNthPreviousWord(prev, currentSettingsValues, n); + return getNthPreviousWord(prev, sentenceSeperators, n); } private static boolean isSeparator(int code, String sep) { @@ -581,7 +531,7 @@ public final class RichInputConnection { // (n = 2) "abc |" -> null // (n = 2) "abc. def|" -> null public static String getNthPreviousWord(final CharSequence prev, - final SettingsValues currentSettingsValues, final int n) { + final String sentenceSeperators, final int n) { if (prev == null) return null; final String[] w = spaceRegex.split(prev); @@ -593,8 +543,7 @@ public final class RichInputConnection { // If ends in a separator, return null final char lastChar = nthPrevWord.charAt(length - 1); - if (currentSettingsValues.isWordSeparator(lastChar) - || currentSettingsValues.isWordConnector(lastChar)) return null; + if (sentenceSeperators.contains(String.valueOf(lastChar))) return null; return nthPrevWord; } @@ -809,30 +758,20 @@ public final class RichInputConnection { * this update and not the ones in-between. This is almost impossible to achieve even trying * very very hard. * - * @param oldSelStart The value of the old selection in the update. - * @param newSelStart The value of the new selection in the update. - * @param oldSelEnd The value of the old selection end in the update. - * @param newSelEnd The value of the new selection end in the update. + * @param oldSelStart The value of the old cursor position in the update. + * @param newSelStart The value of the new cursor position in the update. * @return whether this is a belated expected update or not. */ - public boolean isBelatedExpectedUpdate(final int oldSelStart, final int newSelStart, - final int oldSelEnd, final int newSelEnd) { - // This update is "belated" if we are expecting it. That is, mExpectedSelStart and - // mExpectedSelEnd match the new values that the TextView is updating TO. - if (mExpectedSelStart == newSelStart && mExpectedSelEnd == newSelEnd) return true; - // This update is not belated if mExpectedSelStart and mExpeectedSelend match the old - // values, and one of newSelStart or newSelEnd is updated to a different value. In this - // case, there is likely something other than the IME that has moved the selection endpoint - // to the new value. - if (mExpectedSelStart == oldSelStart && mExpectedSelEnd == oldSelEnd - && (oldSelStart != newSelStart || oldSelEnd != newSelEnd)) return false; - // If nether of the above two cases holds, then the system may be having trouble keeping up - // with updates. If 1) the selection is a cursor, 2) newSelStart is between oldSelStart - // and mExpectedSelStart, and 3) newSelEnd is between oldSelEnd and mExpectedSelEnd, then - // assume a belated update. - return (newSelStart == newSelEnd) - && (newSelStart - oldSelStart) * (mExpectedSelStart - newSelStart) >= 0 - && (newSelEnd - oldSelEnd) * (mExpectedSelEnd - newSelEnd) >= 0; + public boolean isBelatedExpectedUpdate(final int oldSelStart, final int newSelStart) { + // If this is an update that arrives at our expected position, it's a belated update. + if (newSelStart == mExpectedCursorPosition) return true; + // If this is an update that moves the cursor from our expected position, it must be + // an explicit move. + if (oldSelStart == mExpectedCursorPosition) return false; + // The following returns true if newSelStart is between oldSelStart and + // mCurrentCursorPosition. We assume that if the updated position is between the old + // position and the expected position, then it must be a belated update. + return (newSelStart - oldSelStart) * (mExpectedCursorPosition - newSelStart) >= 0; } /** diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index 379eaaa3d..cd9c89f04 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -32,9 +32,7 @@ import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils; import com.android.inputmethod.keyboard.KeyboardSwitcher; -import com.android.inputmethod.latin.utils.LocaleUtils; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; import java.util.List; @@ -58,34 +56,23 @@ public final class SubtypeSwitcher { private InputMethodSubtype mEmojiSubtype; private boolean mIsNetworkConnected; - private static final String KEYBOARD_MODE = "keyboard"; // Dummy no language QWERTY subtype. See {@link R.xml.method}. - private static final int SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE = 0xdde0bfd3; - private static final String EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE = - "KeyboardLayoutSet=" + SubtypeLocaleUtils.QWERTY - + "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE - + "," + Constants.Subtype.ExtraValue.ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE - + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE; - private static final InputMethodSubtype DUMMY_NO_LANGUAGE_SUBTYPE = - InputMethodSubtypeCompatUtils.newInputMethodSubtype( - R.string.subtype_no_language_qwerty, R.drawable.ic_ime_switcher_dark, - SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE, - EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE, - false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */, - SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE); + private static final InputMethodSubtype DUMMY_NO_LANGUAGE_SUBTYPE = new InputMethodSubtype( + R.string.subtype_no_language_qwerty, R.drawable.ic_ime_switcher_dark, + SubtypeLocaleUtils.NO_LANGUAGE, "keyboard", "KeyboardLayoutSet=" + + SubtypeLocaleUtils.QWERTY + + "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE + + ",EnabledWhenDefaultIsNotAsciiCapable," + + Constants.Subtype.ExtraValue.EMOJI_CAPABLE, + false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */); // Caveat: We probably should remove this when we add an Emoji subtype in {@link R.xml.method}. // Dummy Emoji subtype. See {@link R.xml.method}. - private static final int SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE = 0xd78b2ed0; - private static final String EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE = - "KeyboardLayoutSet=" + SubtypeLocaleUtils.EMOJI - + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE; - private static final InputMethodSubtype DUMMY_EMOJI_SUBTYPE = - InputMethodSubtypeCompatUtils.newInputMethodSubtype( - R.string.subtype_emoji, R.drawable.ic_ime_switcher_dark, - SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE, - EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE, - false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */, - SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE); + private static final InputMethodSubtype DUMMY_EMOJI_SUBTYPE = new InputMethodSubtype( + R.string.subtype_emoji, R.drawable.ic_ime_switcher_dark, + SubtypeLocaleUtils.NO_LANGUAGE, "keyboard", "KeyboardLayoutSet=" + + SubtypeLocaleUtils.EMOJI + "," + + Constants.Subtype.ExtraValue.EMOJI_CAPABLE, + false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */); static final class NeedsToDisplayLanguage { private int mEnabledSubtypeCount; @@ -269,23 +256,18 @@ public final class SubtypeSwitcher { return mNeedsToDisplayLanguage.getValue(); } - private static InputMethodSubtype sForcedSubtypeForTesting = null; + private static Locale sForcedLocaleForTesting = null; @UsedForTesting - void forceSubtype(final InputMethodSubtype subtype) { - sForcedSubtypeForTesting = subtype; + void forceLocale(final Locale locale) { + sForcedLocaleForTesting = locale; } public Locale getCurrentSubtypeLocale() { - if (null != sForcedSubtypeForTesting) { - return LocaleUtils.constructLocaleFromString(sForcedSubtypeForTesting.getLocale()); - } + if (null != sForcedLocaleForTesting) return sForcedLocaleForTesting; return SubtypeLocaleUtils.getSubtypeLocale(getCurrentSubtype()); } public InputMethodSubtype getCurrentSubtype() { - if (null != sForcedSubtypeForTesting) { - return sForcedSubtypeForTesting; - } return mRichImm.getCurrentInputMethodSubtype(getNoLanguageSubtype()); } @@ -297,8 +279,8 @@ public final class SubtypeSwitcher { if (mNoLanguageSubtype != null) { return mNoLanguageSubtype; } - Log.w(TAG, "Can't find any language with QWERTY subtype"); - Log.w(TAG, "No input method subtype found; returning dummy subtype: " + Log.w(TAG, "Can't find no lanugage with QWERTY subtype"); + Log.w(TAG, "No input method subtype found; return dummy subtype: " + DUMMY_NO_LANGUAGE_SUBTYPE); return DUMMY_NO_LANGUAGE_SUBTYPE; } @@ -311,9 +293,8 @@ public final class SubtypeSwitcher { if (mEmojiSubtype != null) { return mEmojiSubtype; } - Log.w(TAG, "Can't find emoji subtype"); - Log.w(TAG, "No input method subtype found; returning dummy subtype: " - + DUMMY_EMOJI_SUBTYPE); + Log.w(TAG, "Can't find Emoji subtype"); + Log.w(TAG, "No input method subtype found; return dummy subtype: " + DUMMY_EMOJI_SUBTYPE); return DUMMY_EMOJI_SUBTYPE; } } diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 0ecb41100..0a4c7a55d 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -25,6 +25,7 @@ import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.personalization.PersonalizationDictionary; +import com.android.inputmethod.latin.personalization.PersonalizationPredictionDictionary; import com.android.inputmethod.latin.personalization.UserHistoryDictionary; import com.android.inputmethod.latin.settings.Settings; import com.android.inputmethod.latin.utils.AutoCorrectionUtils; @@ -89,6 +90,7 @@ public final class Suggest { PreferenceManager.getDefaultSharedPreferences(context))) { mOnlyDictionarySetForDebug = new HashSet<String>(); mOnlyDictionarySetForDebug.add(Dictionary.TYPE_PERSONALIZATION); + mOnlyDictionarySetForDebug.add(Dictionary.TYPE_PERSONALIZATION_PREDICTION_IN_JAVA); } } @@ -192,6 +194,12 @@ public final class Suggest { addOrReplaceDictionaryInternal(Dictionary.TYPE_USER_HISTORY, userHistoryDictionary); } + public void setPersonalizationPredictionDictionary( + final PersonalizationPredictionDictionary personalizationPredictionDictionary) { + addOrReplaceDictionaryInternal(Dictionary.TYPE_PERSONALIZATION_PREDICTION_IN_JAVA, + personalizationPredictionDictionary); + } + public void setPersonalizationDictionary( final PersonalizationDictionary personalizationDictionary) { addOrReplaceDictionaryInternal(Dictionary.TYPE_PERSONALIZATION, @@ -424,8 +432,7 @@ public final class Suggest { final String scoreInfoString; if (normalizedScore > 0) { scoreInfoString = String.format( - Locale.ROOT, "%d (%4.2f), %s", cur.mScore, normalizedScore, - cur.mSourceDict.mDictType); + Locale.ROOT, "%d (%4.2f)", cur.mScore, normalizedScore); } else { scoreInfoString = Integer.toString(cur.mScore); } diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java index 9cb2f5bc4..6405b5e46 100644 --- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java @@ -22,15 +22,14 @@ import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import java.util.ArrayList; -import java.util.Locale; public final class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDictionary { - public SynchronouslyLoadedUserBinaryDictionary(final Context context, final Locale locale) { + public SynchronouslyLoadedUserBinaryDictionary(final Context context, final String locale) { this(context, locale, false); } - public SynchronouslyLoadedUserBinaryDictionary(final Context context, final Locale locale, + public SynchronouslyLoadedUserBinaryDictionary(final Context context, final String locale, final boolean alsoUseMoreRestrictiveLocales) { super(context, locale, alsoUseMoreRestrictiveLocales); } diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java index 1dc3c54bb..15b3d8d02 100644 --- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java @@ -18,6 +18,7 @@ package com.android.inputmethod.latin; import android.content.ContentProviderClient; import android.content.ContentResolver; +import android.content.ContentUris; import android.content.Context; import android.database.ContentObserver; import android.database.Cursor; @@ -74,21 +75,20 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { final private String mLocale; final private boolean mAlsoUseMoreRestrictiveLocales; - public UserBinaryDictionary(final Context context, final Locale locale) { + public UserBinaryDictionary(final Context context, final String locale) { this(context, locale, false); } - public UserBinaryDictionary(final Context context, final Locale locale, + public UserBinaryDictionary(final Context context, final String locale, final boolean alsoUseMoreRestrictiveLocales) { - super(context, getDictNameWithLocale(NAME, locale), locale, Dictionary.TYPE_USER, + super(context, getFilenameWithLocale(NAME, locale), Dictionary.TYPE_USER, false /* isUpdatable */); if (null == locale) throw new NullPointerException(); // Catch the error earlier - final String localeStr = locale.toString(); - if (SubtypeLocaleUtils.NO_LANGUAGE.equals(localeStr)) { + if (SubtypeLocaleUtils.NO_LANGUAGE.equals(locale)) { // If we don't have a locale, insert into the "all locales" user dictionary. mLocale = USER_DICTIONARY_ALL_LANGUAGES; } else { - mLocale = localeStr; + mLocale = locale; } mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales; // Perform a managed query. The Activity will handle closing and re-querying the cursor diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index 2f81d15d5..039dadc66 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -48,10 +48,6 @@ public final class WordComposer { // at any given time. However this is not limited in size, while mPrimaryKeyCodes is limited // to MAX_WORD_LENGTH code points. private final StringBuilder mTypedWord; - // The previous word (before the composing word). Used as context for suggestions. May be null - // after resetting and before starting a new composing word, or when there is no context like - // at the start of text for example. - private String mPreviousWord; private String mAutoCorrection; private boolean mIsResumed; private boolean mIsBatchMode; @@ -89,7 +85,6 @@ public final class WordComposer { mIsBatchMode = false; mCursorPositionWithinWord = 0; mRejectedBatchModeSuggestion = null; - mPreviousWord = null; refreshSize(); } @@ -106,7 +101,6 @@ public final class WordComposer { mIsBatchMode = source.mIsBatchMode; mCursorPositionWithinWord = source.mCursorPositionWithinWord; mRejectedBatchModeSuggestion = source.mRejectedBatchModeSuggestion; - mPreviousWord = source.mPreviousWord; refreshSize(); } @@ -124,7 +118,6 @@ public final class WordComposer { mIsBatchMode = false; mCursorPositionWithinWord = 0; mRejectedBatchModeSuggestion = null; - mPreviousWord = null; refreshSize(); } @@ -291,13 +284,8 @@ public final class WordComposer { /** * Set the currently composing word to the one passed as an argument. * This will register NOT_A_COORDINATE for X and Ys, and use the passed keyboard for proximity. - * @param word the char sequence to set as the composing word. - * @param previousWord the previous word, to use as context for suggestions. Can be null if - * the context is nil (typically, at start of text). - * @param keyboard the keyboard this is typed on, for coordinate info/proximity. */ - public void setComposingWord(final CharSequence word, final String previousWord, - final Keyboard keyboard) { + public void setComposingWord(final CharSequence word, final Keyboard keyboard) { reset(); final int length = word.length(); for (int i = 0; i < length; i = Character.offsetByCodePoints(word, i, 1)) { @@ -305,7 +293,6 @@ public final class WordComposer { addKeyInfo(codePoint, keyboard); } mIsResumed = true; - mPreviousWord = previousWord; } /** @@ -356,10 +343,6 @@ public final class WordComposer { return mTypedWord.toString(); } - public String getPreviousWord() { - return mPreviousWord; - } - /** * Whether or not the user typed a capital letter as the first letter in the word * @return capitalization preference @@ -405,21 +388,18 @@ public final class WordComposer { } /** - * Saves the caps mode and the previous word at the start of composing. + * Saves the caps mode at the start of composing. * - * WordComposer needs to know about the caps mode for several reasons. The first is, we need - * to know after the fact what the reason was, to register the correct form into the user - * history dictionary: if the word was automatically capitalized, we should insert it in - * all-lower case but if it's a manual pressing of shift, then it should be inserted as is. + * WordComposer needs to know about this for several reasons. The first is, we need to know + * after the fact what the reason was, to register the correct form into the user history + * dictionary: if the word was automatically capitalized, we should insert it in all-lower + * case but if it's a manual pressing of shift, then it should be inserted as is. * Also, batch input needs to know about the current caps mode to display correctly * capitalized suggestions. * @param mode the mode at the time of start - * @param previousWord the previous word as context for suggestions. May be null if none. */ - public void setCapitalizedModeAndPreviousWordAtStartComposingTime(final int mode, - final String previousWord) { + public void setCapitalizedModeAtStartComposingTime(final int mode) { mCapitalizedMode = mode; - mPreviousWord = previousWord; } /** @@ -471,7 +451,6 @@ public final class WordComposer { mCapsCount = 0; mDigitsCount = 0; mIsBatchMode = false; - mPreviousWord = mTypedWord.toString(); mTypedWord.setLength(0); mCodePointSize = 0; mTrailingSingleQuotesCount = 0; @@ -485,8 +464,7 @@ public final class WordComposer { return lastComposedWord; } - public void resumeSuggestionOnLastComposedWord(final LastComposedWord lastComposedWord, - final String previousWord) { + public void resumeSuggestionOnLastComposedWord(final LastComposedWord lastComposedWord) { mPrimaryKeyCodes = lastComposedWord.mPrimaryKeyCodes; mInputPointers.set(lastComposedWord.mInputPointers); mTypedWord.setLength(0); @@ -497,7 +475,6 @@ public final class WordComposer { mCursorPositionWithinWord = mCodePointSize; mRejectedBatchModeSuggestion = null; mIsResumed = true; - mPreviousWord = previousWord; } public boolean isBatchMode() { diff --git a/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java index f8fa68f45..fda97dafc 100644 --- a/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java +++ b/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java @@ -32,35 +32,36 @@ import java.util.TreeMap; * A base class of the binary dictionary decoder. */ public abstract class AbstractDictDecoder implements DictDecoder { - private static final int SUCCESS = 0; - private static final int ERROR_CANNOT_READ = 1; - private static final int ERROR_WRONG_FORMAT = 2; - - protected FileHeader readHeader(final DictBuffer headerBuffer) + protected FileHeader readHeader(final DictBuffer dictBuffer) throws IOException, UnsupportedFormatException { - if (headerBuffer == null) { + if (dictBuffer == null) { openDictBuffer(); } - final int version = HeaderReader.readVersion(headerBuffer); + final int version = HeaderReader.readVersion(dictBuffer); if (version < FormatSpec.MINIMUM_SUPPORTED_VERSION || version > FormatSpec.MAXIMUM_SUPPORTED_VERSION) { throw new UnsupportedFormatException("Unsupported version : " + version); } // TODO: Remove this field. - final int optionsFlags = HeaderReader.readOptionFlags(headerBuffer); - final int headerSize = HeaderReader.readHeaderSize(headerBuffer); + final int optionsFlags = HeaderReader.readOptionFlags(dictBuffer); + + final int headerSize = HeaderReader.readHeaderSize(dictBuffer); + if (headerSize < 0) { throw new UnsupportedFormatException("header size can't be negative."); } - final HashMap<String, String> attributes = HeaderReader.readAttributes(headerBuffer, + final HashMap<String, String> attributes = HeaderReader.readAttributes(dictBuffer, headerSize); final FileHeader header = new FileHeader(headerSize, - new FusionDictionary.DictionaryOptions(attributes), - new FormatOptions(version, - 0 != (optionsFlags & FormatSpec.CONTAINS_TIMESTAMP_FLAG))); + new FusionDictionary.DictionaryOptions(attributes, + 0 != (optionsFlags & FormatSpec.GERMAN_UMLAUT_PROCESSING_FLAG), + 0 != (optionsFlags & FormatSpec.FRENCH_LIGATURE_PROCESSING_FLAG)), + new FormatOptions(version, + 0 != (optionsFlags & FormatSpec.SUPPORTS_DYNAMIC_UPDATE), + 0 != (optionsFlags & FormatSpec.CONTAINS_TIMESTAMP_FLAG))); return header; } @@ -203,25 +204,4 @@ public abstract class AbstractDictDecoder implements DictDecoder { return readLength; } } - - /** - * Check whether the header contains the expected information. This is a no-error method, - * that will return an error code and never throw a checked exception. - * @return an error code, either ERROR_* or SUCCESS. - */ - private int checkHeader() { - try { - readHeader(); - } catch (IOException e) { - return ERROR_CANNOT_READ; - } catch (UnsupportedFormatException e) { - return ERROR_WRONG_FORMAT; - } - return SUCCESS; - } - - @Override - public boolean hasValidRawBinaryDictionary() { - return checkHeader() == SUCCESS; - } } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java index 7f0aa777f..216492b4d 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java @@ -24,9 +24,12 @@ import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray; import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.Map; import java.util.TreeMap; @@ -166,14 +169,6 @@ public final class BinaryDictDecoderUtils { return size; } - static int getCharArraySize(final int[] chars, final int start, final int end) { - int size = 0; - for (int i = start; i < end; ++i) { - size += getCharSize(chars[i]); - } - return size; - } - /** * Writes a char array to a byte buffer. * @@ -205,7 +200,8 @@ public final class BinaryDictDecoderUtils { * @param word the string to write. * @return the size written, in bytes. */ - static int writeString(final byte[] buffer, final int origin, final String word) { + static int writeString(final byte[] buffer, final int origin, + final String word) { final int length = word.length(); int index = origin; for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) { @@ -227,62 +223,22 @@ public final class BinaryDictDecoderUtils { * * This will also write the terminator byte. * - * @param stream the OutputStream to write to. + * @param buffer the OutputStream to write to. * @param word the string to write. - * @return the size written, in bytes. */ - static int writeString(final OutputStream stream, final String word) throws IOException { + static void writeString(final OutputStream buffer, final String word) throws IOException { final int length = word.length(); - int written = 0; for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) { final int codePoint = word.codePointAt(i); - final int charSize = getCharSize(codePoint); - if (1 == charSize) { - stream.write((byte) codePoint); - } else { - stream.write((byte) (0xFF & (codePoint >> 16))); - stream.write((byte) (0xFF & (codePoint >> 8))); - stream.write((byte) (0xFF & codePoint)); - } - written += charSize; - } - stream.write(FormatSpec.PTNODE_CHARACTERS_TERMINATOR); - written += FormatSpec.PTNODE_TERMINATOR_SIZE; - return written; - } - - /** - * Writes an array of code points with our character format to an OutputStream. - * - * This will also write the terminator byte. - * - * @param stream the OutputStream to write to. - * @param codePoints the array of code points - * @return the size written, in bytes. - */ - // TODO: Merge this method with writeCharArray and rename the various write* methods to - // make the difference clear. - static int writeCodePoints(final OutputStream stream, final int[] codePoints, - final int startIndex, final int endIndex) - throws IOException { - int written = 0; - for (int i = startIndex; i < endIndex; ++i) { - final int codePoint = codePoints[i]; - final int charSize = getCharSize(codePoint); - if (1 == charSize) { - stream.write((byte) codePoint); + if (1 == getCharSize(codePoint)) { + buffer.write((byte) codePoint); } else { - stream.write((byte) (0xFF & (codePoint >> 16))); - stream.write((byte) (0xFF & (codePoint >> 8))); - stream.write((byte) (0xFF & codePoint)); + buffer.write((byte) (0xFF & (codePoint >> 16))); + buffer.write((byte) (0xFF & (codePoint >> 8))); + buffer.write((byte) (0xFF & codePoint)); } - written += charSize; } - if (endIndex - startIndex > 1) { - stream.write(FormatSpec.PTNODE_CHARACTERS_TERMINATOR); - written += FormatSpec.PTNODE_TERMINATOR_SIZE; - } - return written; + buffer.write(FormatSpec.PTNODE_CHARACTERS_TERMINATOR); } /** @@ -330,7 +286,7 @@ public final class BinaryDictDecoderUtils { static int readChildrenAddress(final DictBuffer dictBuffer, final int optionFlags, final FormatOptions options) { - if (options.supportsDynamicUpdate()) { + if (options.mSupportsDynamicUpdate) { final int address = dictBuffer.readUnsignedInt24(); if (address == 0) return FormatSpec.NO_CHILDREN_ADDRESS; if ((address & FormatSpec.MSB24) != 0) { @@ -540,11 +496,11 @@ public final class BinaryDictDecoderUtils { } // reach the end of the array. - if (options.supportsDynamicUpdate()) { + if (options.mSupportsDynamicUpdate) { final boolean hasValidForwardLink = dictDecoder.readAndFollowForwardLink(); if (!hasValidForwardLink) break; } - } while (options.supportsDynamicUpdate() && dictDecoder.hasNextPtNodeArray()); + } while (options.mSupportsDynamicUpdate && dictDecoder.hasNextPtNodeArray()); final PtNodeArray nodeArray = new PtNodeArray(nodeArrayContents); nodeArray.mCachedAddressBeforeUpdate = nodeArrayOriginPos; @@ -600,7 +556,7 @@ public final class BinaryDictDecoderUtils { Map<Integer, PtNodeArray> reverseNodeArrayMapping = new TreeMap<Integer, PtNodeArray>(); Map<Integer, PtNode> reversePtNodeMapping = new TreeMap<Integer, PtNode>(); - final PtNodeArray root = readNodeArray(dictDecoder, fileHeader.mBodyOffset, + final PtNodeArray root = readNodeArray(dictDecoder, fileHeader.mHeaderSize, reverseNodeArrayMapping, reversePtNodeMapping, fileHeader.mFormatOptions); FusionDictionary newDict = new FusionDictionary(root, fileHeader.mDictionaryOptions); @@ -636,10 +592,32 @@ public final class BinaryDictDecoderUtils { /** * Basic test to find out whether the file is a binary dictionary or not. * + * Concretely this only tests the magic number. + * * @param file The file to test. * @return true if it's a binary dictionary, false otherwise */ public static boolean isBinaryDictionary(final File file) { - return FormatSpec.getDictDecoder(file).hasValidRawBinaryDictionary(); + FileInputStream inStream = null; + try { + inStream = new FileInputStream(file); + final ByteBuffer buffer = inStream.getChannel().map( + FileChannel.MapMode.READ_ONLY, 0, file.length()); + final int version = getFormatVersion(new ByteBufferDictBuffer(buffer)); + return (version >= FormatSpec.MINIMUM_SUPPORTED_VERSION + && version <= FormatSpec.MAXIMUM_SUPPORTED_VERSION); + } catch (FileNotFoundException e) { + return false; + } catch (IOException e) { + return false; + } finally { + if (inStream != null) { + try { + inStream.close(); + } catch (IOException e) { + // do nothing + } + } + } } } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java index 8ba0797de..f761829de 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java @@ -17,9 +17,9 @@ package com.android.inputmethod.latin.makedict; import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding; -import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer; import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions; import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode; +import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions; import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray; import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; @@ -160,7 +160,7 @@ public class BinaryDictEncoderUtils { node.mCachedSize = nodeSize; size += nodeSize; } - if (options.supportsDynamicUpdate()) { + if (options.mSupportsDynamicUpdate) { size += FormatSpec.FORWARD_LINK_ADDRESS_SIZE; } ptNodeArray.mCachedSize = size; @@ -245,26 +245,6 @@ public class BinaryDictEncoderUtils { } } - static void writeUIntToDictBuffer(final DictBuffer dictBuffer, final int value, - final int size) { - switch(size) { - case 4: - dictBuffer.put((byte) ((value >> 24) & 0xFF)); - /* fall through */ - case 3: - dictBuffer.put((byte) ((value >> 16) & 0xFF)); - /* fall through */ - case 2: - dictBuffer.put((byte) ((value >> 8) & 0xFF)); - /* fall through */ - case 1: - dictBuffer.put((byte) (value & 0xFF)); - break; - default: - /* nop */ - } - } - // End utility methods // This method is responsible for finding a nice ordering of the nodes that favors run-time @@ -397,7 +377,7 @@ public class BinaryDictEncoderUtils { nodeSize += FormatSpec.PTNODE_FREQUENCY_SIZE; } } - if (formatOptions.supportsDynamicUpdate()) { + if (formatOptions.mSupportsDynamicUpdate) { nodeSize += FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE; } else if (null != ptNode.mChildren) { nodeSize += getByteSize(getOffsetToTargetNodeArrayDuringUpdate(ptNodeArray, @@ -417,7 +397,7 @@ public class BinaryDictEncoderUtils { ptNode.mCachedSize = nodeSize; size += nodeSize; } - if (formatOptions.supportsDynamicUpdate()) { + if (formatOptions.mSupportsDynamicUpdate) { size += FormatSpec.FORWARD_LINK_ADDRESS_SIZE; } if (ptNodeArray.mCachedSize != size) { @@ -533,7 +513,7 @@ public class BinaryDictEncoderUtils { if (passes > MAX_PASSES) throw new RuntimeException("Too many passes - probably a bug"); } while (changesDone); - if (formatOptions.supportsDynamicUpdate()) { + if (formatOptions.mSupportsDynamicUpdate) { computeParentAddresses(flatNodes); } final PtNodeArray lastPtNodeArray = flatNodes.get(flatNodes.size() - 1); @@ -642,7 +622,7 @@ public class BinaryDictEncoderUtils { byte flags = 0; if (hasMultipleChars) flags |= FormatSpec.FLAG_HAS_MULTIPLE_CHARS; if (isTerminal) flags |= FormatSpec.FLAG_IS_TERMINAL; - if (formatOptions.supportsDynamicUpdate()) { + if (formatOptions.mSupportsDynamicUpdate) { flags |= FormatSpec.FLAG_IS_NOT_MOVED; } else if (true) { switch (childrenAddressSize) { @@ -710,13 +690,6 @@ public class BinaryDictEncoderUtils { + word + " is " + unigramFrequency); bigramFrequency = unigramFrequency; } - bigramFlags += getBigramFrequencyDiff(unigramFrequency, bigramFrequency) - & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY; - return bigramFlags; - } - - public static int getBigramFrequencyDiff(final int unigramFrequency, - final int bigramFrequency) { // We compute the difference between 255 (which means probability = 1) and the // unigram score. We split this into a number of discrete steps. // Now, the steps are numbered 0~15; 0 represents an increase of 1 step while 15 @@ -750,15 +723,22 @@ public class BinaryDictEncoderUtils { // include this bigram in the dictionary. For now, register as 0, and live with the // small over-estimation that we get in this case. TODO: actually remove this bigram // if discretizedFrequency < 0. - return discretizedFrequency > 0 ? discretizedFrequency : 0; + final int finalBigramFrequency = discretizedFrequency > 0 ? discretizedFrequency : 0; + bigramFlags += finalBigramFrequency & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY; + return bigramFlags; } /** - * Makes the 2-byte value for options flags. Unused at the moment, and always 0. + * Makes the 2-byte value for options flags. */ - private static final int makeOptionsValue(final FormatOptions formatOptions) { - // TODO: why doesn't this handle CONTAINS_TIMESTAMP_FLAG? - return 0; + private static final int makeOptionsValue(final FusionDictionary dictionary, + final FormatOptions formatOptions) { + final DictionaryOptions options = dictionary.mOptions; + final boolean hasBigrams = dictionary.hasBigrams(); + return (options.mFrenchLigatureProcessing ? FormatSpec.FRENCH_LIGATURE_PROCESSING_FLAG : 0) + + (options.mGermanUmlautProcessing ? FormatSpec.GERMAN_UMLAUT_PROCESSING_FLAG : 0) + + (hasBigrams ? FormatSpec.CONTAINS_BIGRAMS_FLAG : 0) + + (formatOptions.mSupportsDynamicUpdate ? FormatSpec.SUPPORTS_DYNAMIC_UPDATE : 0); } /** @@ -846,7 +826,7 @@ public class BinaryDictEncoderUtils { } dictEncoder.writePtNode(ptNode, parentPosition, formatOptions, dict); } - if (formatOptions.supportsDynamicUpdate()) { + if (formatOptions.mSupportsDynamicUpdate) { dictEncoder.writeForwardLinkAddress(FormatSpec.NO_FORWARD_LINK_ADDRESS); } if (dictEncoder.getPosition() != ptNodeArray.mCachedAddressAfterUpdate @@ -947,7 +927,7 @@ public class BinaryDictEncoderUtils { headerBuffer.write((byte) (0xFF & version)); // Options flags - final int options = makeOptionsValue(formatOptions); + final int options = makeOptionsValue(dict, formatOptions); headerBuffer.write((byte) (0xFF & (options >> 8))); headerBuffer.write((byte) (0xFF & options)); final int headerSizeOffset = headerBuffer.size(); diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 640d778bb..d5516ef46 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -62,7 +62,7 @@ public final class BinaryDictIOUtils { * Retrieves all node arrays without recursive call. */ private static void readUnigramsAndBigramsBinaryInner(final DictDecoder dictDecoder, - final int bodyOffset, final Map<Integer, String> words, + final int headerSize, final Map<Integer, String> words, final Map<Integer, Integer> frequencies, final Map<Integer, ArrayList<PendingAttribute>> bigrams, final FormatOptions formatOptions) { @@ -71,7 +71,7 @@ public final class BinaryDictIOUtils { Stack<Position> stack = new Stack<Position>(); int index = 0; - Position initPos = new Position(bodyOffset, 0); + Position initPos = new Position(headerSize, 0); stack.push(initPos); while (!stack.empty()) { @@ -112,7 +112,7 @@ public final class BinaryDictIOUtils { } if (p.mPosition == p.mNumOfPtNode) { - if (formatOptions.supportsDynamicUpdate()) { + if (formatOptions.mSupportsDynamicUpdate) { final boolean hasValidForwardLinkAddress = dictDecoder.readAndFollowForwardLink(); if (hasValidForwardLinkAddress && dictDecoder.hasNextPtNodeArray()) { @@ -154,7 +154,7 @@ public final class BinaryDictIOUtils { UnsupportedFormatException { // Read header final FileHeader header = dictDecoder.readHeader(); - readUnigramsAndBigramsBinaryInner(dictDecoder, header.mBodyOffset, words, + readUnigramsAndBigramsBinaryInner(dictDecoder, header.mHeaderSize, words, frequencies, bigrams, header.mFormatOptions); } @@ -228,7 +228,7 @@ public final class BinaryDictIOUtils { // a forward link address that we need to consult and possibly resume // search on the next node array in the linked list. if (foundNextPtNode) break; - if (!header.mFormatOptions.supportsDynamicUpdate()) { + if (!header.mFormatOptions.mSupportsDynamicUpdate) { return FormatSpec.NOT_VALID_WORD; } @@ -245,7 +245,8 @@ public final class BinaryDictIOUtils { /** * @return the size written, in bytes. Always 3 bytes. */ - static int writeSInt24ToBuffer(final DictBuffer dictBuffer, final int value) { + static int writeSInt24ToBuffer(final DictBuffer dictBuffer, + final int value) { final int absValue = Math.abs(value); dictBuffer.put((byte)(((value < 0 ? 0x80 : 0) | (absValue >> 16)) & 0xFF)); dictBuffer.put((byte)((absValue >> 8) & 0xFF)); @@ -300,6 +301,35 @@ public final class BinaryDictIOUtils { } /** + * Write a string to a stream. + * + * @param destination the stream to write. + * @param word the string to be written. + * @return the size written, in bytes. + * @throws IOException + */ + private static int writeString(final OutputStream destination, final String word) + throws IOException { + int size = 0; + final int length = word.length(); + for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) { + final int codePoint = word.codePointAt(i); + if (CharEncoding.getCharSize(codePoint) == 1) { + destination.write((byte)codePoint); + size++; + } else { + destination.write((byte)(0xFF & (codePoint >> 16))); + destination.write((byte)(0xFF & (codePoint >> 8))); + destination.write((byte)(0xFF & codePoint)); + size += 3; + } + } + destination.write((byte)FormatSpec.PTNODE_CHARACTERS_TERMINATOR); + size += FormatSpec.PTNODE_TERMINATOR_SIZE; + return size; + } + + /** * Write a PtNode to an output stream from a PtNodeInfo. * A PtNode is an in-memory representation of a node in the patricia trie. * A PtNode info is a container for low-level information about how the @@ -357,7 +387,7 @@ public final class BinaryDictIOUtils { destination.write((byte)BinaryDictEncoderUtils.makeShortcutFlags( shortcutIterator.hasNext(), target.mFrequency)); size++; - size += CharEncoding.writeString(destination, target.mWord); + size += writeString(destination, target.mWord); } } @@ -415,27 +445,6 @@ public final class BinaryDictIOUtils { } /** - * Writes a PtNodeCount to the stream. - * - * @param destination the stream to write. - * @param ptNodeCount the count. - * @return the size written in bytes. - */ - static int writePtNodeCount(final OutputStream destination, final int ptNodeCount) - throws IOException { - final int countSize = BinaryDictIOUtils.getPtNodeCountSize(ptNodeCount); - // the count must fit on one byte or two bytes. - // Please see comments in FormatSpec. - if (countSize != 1 && countSize != 2) { - throw new RuntimeException("Strange size from getPtNodeCountSize : " + countSize); - } - final int encodedPtNodeCount = (countSize == 2) ? - (ptNodeCount | FormatSpec.LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE_FLAG) : ptNodeCount; - BinaryDictEncoderUtils.writeUIntToStream(destination, encodedPtNodeCount, countSize); - return countSize; - } - - /** * Write a node array to the stream. * * @param destination the stream to write. @@ -445,7 +454,20 @@ public final class BinaryDictIOUtils { */ static int writeNodes(final OutputStream destination, final PtNodeInfo[] infos) throws IOException { - int size = writePtNodeCount(destination, infos.length); + int size = getPtNodeCountSize(infos.length); + switch (getPtNodeCountSize(infos.length)) { + case 1: + destination.write((byte)infos.length); + break; + case 2: + final int encodedPtNodeCount = + infos.length | FormatSpec.LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE_FLAG; + destination.write((byte)(encodedPtNodeCount >> 8)); + destination.write((byte)(encodedPtNodeCount & 0xFF)); + break; + default: + throw new RuntimeException("Invalid node count size."); + } for (final PtNodeInfo info : infos) size += writePtNode(destination, info); writeSInt24ToStream(destination, FormatSpec.NO_FORWARD_LINK_ADDRESS); return size + FormatSpec.FORWARD_LINK_ADDRESS_SIZE; @@ -507,7 +529,7 @@ public final class BinaryDictIOUtils { * Helper method to check whether the node is moved. */ public static boolean isMovedPtNode(final int flags, final FormatOptions options) { - return options.supportsDynamicUpdate() + return options.mSupportsDynamicUpdate && ((flags & FormatSpec.MASK_CHILDREN_ADDRESS_TYPE) == FormatSpec.FLAG_IS_MOVED); } @@ -516,14 +538,14 @@ public final class BinaryDictIOUtils { */ public static boolean supportsDynamicUpdate(final FormatOptions options) { return options.mVersion >= FormatSpec.FIRST_VERSION_WITH_DYNAMIC_UPDATE - && options.supportsDynamicUpdate(); + && options.mSupportsDynamicUpdate; } /** * Helper method to check whether the node is deleted. */ public static boolean isDeletedPtNode(final int flags, final FormatOptions formatOptions) { - return formatOptions.supportsDynamicUpdate() + return formatOptions.mSupportsDynamicUpdate && ((flags & FormatSpec.MASK_CHILDREN_ADDRESS_TYPE) == FormatSpec.FLAG_IS_DELETED); } @@ -546,7 +568,7 @@ public final class BinaryDictIOUtils { static int getChildrenAddressSize(final int optionFlags, final FormatOptions formatOptions) { - if (formatOptions.supportsDynamicUpdate()) return FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE; + if (formatOptions.mSupportsDynamicUpdate) return FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE; switch (optionFlags & FormatSpec.MASK_CHILDREN_ADDRESS_TYPE) { case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE: return 1; diff --git a/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java index b4838f00f..3dbeee099 100644 --- a/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java +++ b/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java @@ -35,7 +35,6 @@ import java.util.TreeMap; /** * An interface of binary dictionary decoders. */ -// TODO: Straighten out responsibility for the buffer's file pointer. public interface DictDecoder { /** @@ -44,7 +43,7 @@ public interface DictDecoder { public FileHeader readHeader() throws IOException, UnsupportedFormatException; /** - * Reads PtNode from ptNodePos. + * Reads PtNode from nodeAddress. * @param ptNodePos the position of PtNode. * @param formatOptions the format options. * @return PtNodeInfo. @@ -128,8 +127,7 @@ public interface DictDecoder { * Opens the dictionary file and makes DictBuffer. */ @UsedForTesting - public void openDictBuffer() throws FileNotFoundException, IOException, - UnsupportedFormatException; + public void openDictBuffer() throws FileNotFoundException, IOException; @UsedForTesting public boolean isDictBufferOpen(); @@ -230,9 +228,4 @@ public interface DictDecoder { } public void skipPtNode(final FormatOptions formatOptions); - - /** - * @return whether this decoder has a valid binary dictionary that it can decode. - */ - public boolean hasValidRawBinaryDictionary(); } diff --git a/java/src/com/android/inputmethod/latin/makedict/DynamicBinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/DynamicBinaryDictIOUtils.java index ff03190a3..28da9ffdd 100644 --- a/java/src/com/android/inputmethod/latin/makedict/DynamicBinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/DynamicBinaryDictIOUtils.java @@ -37,7 +37,7 @@ import java.util.Arrays; @UsedForTesting public final class DynamicBinaryDictIOUtils { private static final boolean DBG = false; - static final int MAX_JUMPS = 10000; + private static final int MAX_JUMPS = 10000; private DynamicBinaryDictIOUtils() { // This utility class is not publicly instantiable. @@ -61,7 +61,7 @@ public final class DynamicBinaryDictIOUtils { final DictBuffer dictBuffer = dictUpdater.getDictBuffer(); final int originalPosition = dictBuffer.position(); dictBuffer.position(ptNodeOriginAddress); - if (!formatOptions.supportsDynamicUpdate()) { + if (!formatOptions.mSupportsDynamicUpdate) { throw new RuntimeException("this file format does not support parent addresses"); } final int flags = dictBuffer.readUnsignedByte(); @@ -102,7 +102,7 @@ public final class DynamicBinaryDictIOUtils { } if (!dictUpdater.readAndFollowForwardLink()) break; if (dictUpdater.getPosition() == FormatSpec.NO_FORWARD_LINK_ADDRESS) break; - } while (formatOptions.supportsDynamicUpdate()); + } while (formatOptions.mSupportsDynamicUpdate); dictUpdater.setPosition(originalPosition); } diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index 20ddba836..b56234f6d 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -40,8 +40,12 @@ public final class FormatSpec { * p | not used 3 bits * t | each unigram and bigram entry has a time stamp? * i | 1 bit, 1 = yes, 0 = no : CONTAINS_TIMESTAMP_FLAG - * o | - * nflags + * o | has bigrams ? 1 bit, 1 = yes, 0 = no : CONTAINS_BIGRAMS_FLAG + * n | FRENCH_LIGATURE_PROCESSING_FLAG + * f | supports dynamic updates ? 1 bit, 1 = yes, 0 = no : SUPPORTS_DYNAMIC_UPDATE + * l | GERMAN_UMLAUT_PROCESSING_FLAG + * a | + * gs * * h | * e | size of the file header, 4bytes @@ -78,36 +82,45 @@ public final class FormatSpec { * s * * f | - * o | forward link address, 3byte - * r | 1 byte = bbbbbbbb match - * w | case 1xxxxxxx => -((xxxxxxx << 16) + (next byte << 8) + next byte) - * a | otherwise => (xxxxxxx << 16) + (next byte << 8) + next byte - * r | - * dlinkaddress + * o | IF SUPPORTS_DYNAMIC_UPDATE (defined in the file header) + * r | forward link address, 3byte + * w | 1 byte = bbbbbbbb match + * a | case 1xxxxxxx => -((xxxxxxx << 16) + (next byte << 8) + next byte) + * r | otherwise => (xxxxxxx << 16) + (next byte << 8) + next byte + * d | + * linkaddress */ /* Node (FusionDictionary.PtNode) layout is as follows: - * | is moved ? 2 bits, 11 = no : FLAG_IS_NOT_MOVED - * | This must be the same as FLAG_CHILDREN_ADDRESS_TYPE_THREEBYTES - * | 01 = yes : FLAG_IS_MOVED - * f | the new address is stored in the same place as the parent address - * l | is deleted? 10 = yes : FLAG_IS_DELETED - * a | has several chars ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_MULTIPLE_CHARS - * g | has a terminal ? 1 bit, 1 = yes, 0 = no : FLAG_IS_TERMINAL - * s | has shortcut targets ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_SHORTCUT_TARGETS + * | IF !SUPPORTS_DYNAMIC_UPDATE + * | addressType xx : mask with MASK_CHILDREN_ADDRESS_TYPE + * | 2 bits, 00 = no children : FLAG_CHILDREN_ADDRESS_TYPE_NOADDRESS + * f | 01 = 1 byte : FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE + * l | 10 = 2 bytes : FLAG_CHILDREN_ADDRESS_TYPE_TWOBYTES + * a | 11 = 3 bytes : FLAG_CHILDREN_ADDRESS_TYPE_THREEBYTES + * g | ELSE + * s | is moved ? 2 bits, 11 = no : FLAG_IS_NOT_MOVED + * | This must be the same as FLAG_CHILDREN_ADDRESS_TYPE_THREEBYTES + * | 01 = yes : FLAG_IS_MOVED + * | the new address is stored in the same place as the parent address + * | is deleted? 10 = yes : FLAG_IS_DELETED + * | has several chars ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_MULTIPLE_CHARS + * | has a terminal ? 1 bit, 1 = yes, 0 = no : FLAG_IS_TERMINAL + * | has shortcut targets ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_SHORTCUT_TARGETS * | has bigrams ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_BIGRAMS * | is not a word ? 1 bit, 1 = yes, 0 = no : FLAG_IS_NOT_A_WORD * | is blacklisted ? 1 bit, 1 = yes, 0 = no : FLAG_IS_BLACKLISTED * * p | - * a | parent address, 3byte - * r | 1 byte = bbbbbbbb match - * e | case 1xxxxxxx => -((0xxxxxxx << 16) + (next byte << 8) + next byte) - * n | otherwise => (bbbbbbbb << 16) + (next byte << 8) + next byte - * t | This address is relative to the head of the PtNode. - * a | If the node doesn't have a parent, this field is set to 0. + * a | IF SUPPORTS_DYNAMIC_UPDATE (defined in the file header) + * r | parent address, 3byte + * e | 1 byte = bbbbbbbb match + * n | case 1xxxxxxx => -((0xxxxxxx << 16) + (next byte << 8) + next byte) + * t | otherwise => (bbbbbbbb << 16) + (next byte << 8) + next byte + * a | This address is relative to the head of the PtNode. + * d | If the node doesn't have a parent, this field is set to 0. * d | - * dress + * ress * * c | IF FLAG_HAS_MULTIPLE_CHARS * h | char, char, char, char n * (1 or 3 bytes) : use PtNodeInfo for i/o helpers @@ -121,16 +134,23 @@ public final class FormatSpec { * e | frequency 1 byte * q | * - * c | - * h | children address, 3 bytes - * i | 1 byte = bbbbbbbb match - * l | case 1xxxxxxx => -((0xxxxxxx << 16) + (next byte << 8) + next byte) - * d | otherwise => (bbbbbbbb<<16) + (next byte << 8) + next byte - * r | if this node doesn't have children, this field is set to 0. - * e | (see BinaryDictEncoderUtils#writeVariableSignedAddress) - * n | This address is relative to the position of this field. - * a | - * ddress + * c | IF SUPPORTS_DYNAMIC_UPDATE + * h | children address, 3 bytes + * i | 1 byte = bbbbbbbb match + * l | case 1xxxxxxx => -((0xxxxxxx << 16) + (next byte << 8) + next byte) + * d | otherwise => (bbbbbbbb<<16) + (next byte << 8) + next byte + * r | if this node doesn't have children, this field is set to 0. + * e | (see BinaryDictEncoderUtils#writeVariableSignedAddress) + * n | ELSIF 00 = FLAG_CHILDREN_ADDRESS_TYPE_NOADDRESS == addressType + * a | // nothing + * d | ELSIF 01 = FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE == addressType + * d | children address, 1 byte + * r | ELSIF 10 = FLAG_CHILDREN_ADDRESS_TYPE_TWOBYTES == addressType + * e | children address, 2 bytes + * s | ELSE // 11 = FLAG_CHILDREN_ADDRESS_TYPE_THREEBYTES = addressType + * s | children address, 3 bytes + * | END + * | This address is relative to the position of this field. * * | IF FLAG_IS_TERMINAL && FLAG_HAS_SHORTCUT_TARGETS * | shortcut string list @@ -179,22 +199,20 @@ public final class FormatSpec { */ public static final int MAGIC_NUMBER = 0x9BC13AFE; + static final int MINIMUM_SUPPORTED_VERSION = 2; + static final int MAXIMUM_SUPPORTED_VERSION = 4; static final int NOT_A_VERSION_NUMBER = -1; static final int FIRST_VERSION_WITH_DYNAMIC_UPDATE = 3; static final int FIRST_VERSION_WITH_TERMINAL_ID = 4; - - // These MUST have the same values as the relevant constants in format_utils.h. - // From version 4 on, we use version * 100 + revision as a version number. That allows - // us to change the format during development while having testing devices remove - // older files with each upgrade, while still having a readable versioning scheme. - public static final int VERSION2 = 2; - public static final int VERSION3 = 3; - public static final int VERSION4 = 400; - static final int MINIMUM_SUPPORTED_VERSION = VERSION2; - static final int MAXIMUM_SUPPORTED_VERSION = VERSION4; + static final int VERSION3 = 3; + static final int VERSION4 = 4; // These options need to be the same numeric values as the one in the native reading code. + static final int GERMAN_UMLAUT_PROCESSING_FLAG = 0x1; // TODO: Make the native reading code read this variable. + static final int SUPPORTS_DYNAMIC_UPDATE = 0x2; + static final int FRENCH_LIGATURE_PROCESSING_FLAG = 0x4; + static final int CONTAINS_BIGRAMS_FLAG = 0x8; static final int CONTAINS_TIMESTAMP_FLAG = 0x10; // TODO: Make this value adaptative to content data, store it in the header, and @@ -245,10 +263,8 @@ public final class FormatSpec { static final int PTNODE_ATTRIBUTE_MAX_ADDRESS_SIZE = 3; static final int PTNODE_SHORTCUT_LIST_SIZE_SIZE = 2; - // These values are used only by version 4 or later. They MUST match the definitions in - // ver4_dict_constants.cpp. + // These values are used only by version 4 or later. static final String TRIE_FILE_EXTENSION = ".trie"; - public static final String HEADER_FILE_EXTENSION = ".header"; static final String FREQ_FILE_EXTENSION = ".freq"; static final String UNIGRAM_TIMESTAMP_FILE_EXTENSION = ".timestamp"; // tat = Terminal Address Table @@ -262,9 +278,9 @@ public final class FormatSpec { static final int UNIGRAM_TIMESTAMP_SIZE = 4; // With the English main dictionary as of October 2013, the size of bigram address table is - // is 345KB with the block size being 16. - // This is 54% of that of full address table. - static final int BIGRAM_ADDRESS_TABLE_BLOCK_SIZE = 16; + // is 584KB with the block size being 4. + // This is 91% of that of full address table. + static final int BIGRAM_ADDRESS_TABLE_BLOCK_SIZE = 4; static final int BIGRAM_CONTENT_COUNT = 2; static final int BIGRAM_FREQ_CONTENT_INDEX = 0; static final int BIGRAM_TIMESTAMP_CONTENT_INDEX = 1; @@ -277,7 +293,7 @@ public final class FormatSpec { static final int SHORTCUT_CONTENT_COUNT = 1; static final int SHORTCUT_CONTENT_INDEX = 0; // With the English main dictionary as of October 2013, the size of shortcut address table is - // 26KB with the block size being 64. + // 29KB with the block size being 64. // This is only 4.4% of that of full address table. static final int SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE = 64; static final String SHORTCUT_CONTENT_ID = "_shortcut"; @@ -315,36 +331,43 @@ public final class FormatSpec { */ public static final class FormatOptions { public final int mVersion; + public final boolean mSupportsDynamicUpdate; public final boolean mHasTerminalId; public final boolean mHasTimestamp; - @UsedForTesting public FormatOptions(final int version) { - this(version, false /* hasTimestamp */); + this(version, false); } - public FormatOptions(final int version, final boolean hasTimestamp) { + @UsedForTesting + public FormatOptions(final int version, final boolean supportsDynamicUpdate) { + this(version, supportsDynamicUpdate, false /* hasTimestamp */); + } + + public FormatOptions(final int version, final boolean supportsDynamicUpdate, + final boolean hasTimestamp) { mVersion = version; + if (version < FIRST_VERSION_WITH_DYNAMIC_UPDATE && supportsDynamicUpdate) { + throw new RuntimeException("Dynamic updates are only supported with versions " + + FIRST_VERSION_WITH_DYNAMIC_UPDATE + " and ulterior."); + } + mSupportsDynamicUpdate = supportsDynamicUpdate; mHasTerminalId = (version >= FIRST_VERSION_WITH_TERMINAL_ID); mHasTimestamp = hasTimestamp; } - - public boolean supportsDynamicUpdate() { - return mVersion >= FIRST_VERSION_WITH_DYNAMIC_UPDATE; - } } /** * Class representing file header. */ public static final class FileHeader { - public final int mBodyOffset; + public final int mHeaderSize; public final DictionaryOptions mDictionaryOptions; public final FormatOptions mFormatOptions; // Note that these are corresponding definitions in native code in latinime::HeaderPolicy // and latinime::HeaderReadWriteUtils. + public static final String SUPPORTS_DYNAMIC_UPDATE_ATTRIBUTE = "SUPPORTS_DYNAMIC_UPDATE"; public static final String USES_FORGETTING_CURVE_ATTRIBUTE = "USES_FORGETTING_CURVE"; - public static final String HAS_HISTORICAL_INFO_ATTRIBUTE = "HAS_HISTORICAL_INFO"; public static final String ATTRIBUTE_VALUE_TRUE = "1"; public static final String DICTIONARY_VERSION_ATTRIBUTE = "version"; @@ -353,18 +376,9 @@ public final class FormatSpec { private static final String DICTIONARY_DESCRIPTION_ATTRIBUTE = "description"; public FileHeader(final int headerSize, final DictionaryOptions dictionaryOptions, final FormatOptions formatOptions) { + mHeaderSize = headerSize; mDictionaryOptions = dictionaryOptions; mFormatOptions = formatOptions; - mBodyOffset = formatOptions.mVersion < VERSION4 ? headerSize : 0; - if (null == getLocaleString()) { - throw new RuntimeException("Cannot create a FileHeader without a locale"); - } - if (null == getVersion()) { - throw new RuntimeException("Cannot create a FileHeader without a version"); - } - if (null == getId()) { - throw new RuntimeException("Cannot create a FileHeader without an ID"); - } } // Helper method to get the locale as a String diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java index fdf2ae7b5..3bb218bea 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java +++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java @@ -303,9 +303,14 @@ public final class FusionDictionary implements Iterable<Word> { * Options global to the dictionary. */ public static final class DictionaryOptions { + public final boolean mGermanUmlautProcessing; + public final boolean mFrenchLigatureProcessing; public final HashMap<String, String> mAttributes; - public DictionaryOptions(final HashMap<String, String> attributes) { + public DictionaryOptions(final HashMap<String, String> attributes, + final boolean germanUmlautProcessing, final boolean frenchLigatureProcessing) { mAttributes = attributes; + mGermanUmlautProcessing = germanUmlautProcessing; + mFrenchLigatureProcessing = frenchLigatureProcessing; } @Override public String toString() { // Convenience method @@ -334,6 +339,14 @@ public final class FusionDictionary implements Iterable<Word> { } s.append("\n"); } + if (mGermanUmlautProcessing) { + s.append(indent); + s.append("Needs German umlaut processing\n"); + } + if (mFrenchLigatureProcessing) { + s.append(indent); + s.append("Needs French ligature processing\n"); + } return s.toString(); } } @@ -688,6 +701,138 @@ public final class FusionDictionary implements Iterable<Word> { } /** + * Recursively count the number of nodes in a given branch of the trie. + * + * @param nodeArray the node array to count. + * @return the number of nodes in this branch. + */ + public static int countNodeArrays(final PtNodeArray nodeArray) { + int size = 1; + for (int i = nodeArray.mData.size() - 1; i >= 0; --i) { + PtNode ptNode = nodeArray.mData.get(i); + if (null != ptNode.mChildren) + size += countNodeArrays(ptNode.mChildren); + } + return size; + } + + // Recursively find out whether there are any bigrams. + // This can be pretty expensive especially if there aren't any (we return as soon + // as we find one, so it's much cheaper if there are bigrams) + private static boolean hasBigramsInternal(final PtNodeArray nodeArray) { + if (null == nodeArray) return false; + for (int i = nodeArray.mData.size() - 1; i >= 0; --i) { + PtNode ptNode = nodeArray.mData.get(i); + if (null != ptNode.mBigrams) return true; + if (hasBigramsInternal(ptNode.mChildren)) return true; + } + return false; + } + + /** + * Finds out whether there are any bigrams in this dictionary. + * + * @return true if there is any bigram, false otherwise. + */ + // TODO: this is expensive especially for large dictionaries without any bigram. + // The up side is, this is always accurate and correct and uses no memory. We should + // find a more efficient way of doing this, without compromising too much on memory + // and ease of use. + public boolean hasBigrams() { + return hasBigramsInternal(mRootNodeArray); + } + + // Historically, the tails of the words were going to be merged to save space. + // However, that would prevent the code to search for a specific address in log(n) + // time so this was abandoned. + // The code is still of interest as it does add some compression to any dictionary + // that has no need for attributes. Implementations that does not read attributes should be + // able to read a dictionary with merged tails. + // Also, the following code does support frequencies, as in, it will only merges + // tails that share the same frequency. Though it would result in the above loss of + // performance while searching by address, it is still technically possible to merge + // tails that contain attributes, but this code does not take that into account - it does + // not compare attributes and will merge terminals with different attributes regardless. + public void mergeTails() { + MakedictLog.i("Do not merge tails"); + return; + +// MakedictLog.i("Merging PtNodes. Number of PtNodes : " + countPtNodes(root)); +// MakedictLog.i("Number of PtNodes : " + countPtNodes(root)); +// +// final HashMap<String, ArrayList<PtNodeArray>> repository = +// new HashMap<String, ArrayList<PtNodeArray>>(); +// mergeTailsInner(repository, root); +// +// MakedictLog.i("Number of different pseudohashes : " + repository.size()); +// int size = 0; +// for (ArrayList<PtNodeArray> a : repository.values()) { +// size += a.size(); +// } +// MakedictLog.i("Number of nodes after merge : " + (1 + size)); +// MakedictLog.i("Recursively seen nodes : " + countNodes(root)); + } + + // The following methods are used by the deactivated mergeTails() +// private static boolean isEqual(PtNodeArray a, PtNodeArray b) { +// if (null == a && null == b) return true; +// if (null == a || null == b) return false; +// if (a.data.size() != b.data.size()) return false; +// final int size = a.data.size(); +// for (int i = size - 1; i >= 0; --i) { +// PtNode aPtNode = a.data.get(i); +// PtNode bPtNode = b.data.get(i); +// if (aPtNode.frequency != bPtNode.frequency) return false; +// if (aPtNode.alternates == null && bPtNode.alternates != null) return false; +// if (aPtNode.alternates != null && !aPtNode.equals(bPtNode.alternates)) return false; +// if (!Arrays.equals(aPtNode.chars, bPtNode.chars)) return false; +// if (!isEqual(aPtNode.children, bPtNode.children)) return false; +// } +// return true; +// } + +// static private HashMap<String, ArrayList<PtNodeArray>> mergeTailsInner( +// final HashMap<String, ArrayList<PtNodeArray>> map, final PtNodeArray nodeArray) { +// final ArrayList<PtNode> branches = nodeArray.data; +// final int nodeSize = branches.size(); +// for (int i = 0; i < nodeSize; ++i) { +// PtNode ptNode = branches.get(i); +// if (null != ptNode.children) { +// String pseudoHash = getPseudoHash(ptNode.children); +// ArrayList<PtNodeArray> similarList = map.get(pseudoHash); +// if (null == similarList) { +// similarList = new ArrayList<PtNodeArray>(); +// map.put(pseudoHash, similarList); +// } +// boolean merged = false; +// for (PtNodeArray similar : similarList) { +// if (isEqual(ptNode.children, similar)) { +// ptNode.children = similar; +// merged = true; +// break; +// } +// } +// if (!merged) { +// similarList.add(ptNode.children); +// } +// mergeTailsInner(map, ptNode.children); +// } +// } +// return map; +// } + +// private static String getPseudoHash(final PtNodeArray nodeArray) { +// StringBuilder s = new StringBuilder(); +// for (PtNode ptNode : nodeArray.data) { +// s.append(ptNode.frequency); +// for (int ch : ptNode.chars) { +// s.append(Character.toChars(ch)); +// } +// } +// return s.toString(); +// } + + /** * Iterator to walk through a dictionary. * * This is purely for convenience. diff --git a/java/src/com/android/inputmethod/latin/makedict/SparseTableContentReader.java b/java/src/com/android/inputmethod/latin/makedict/SparseTableContentReader.java deleted file mode 100644 index 06088b651..000000000 --- a/java/src/com/android/inputmethod/latin/makedict/SparseTableContentReader.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 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.makedict; - -import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer; -import com.android.inputmethod.latin.makedict.DictDecoder.DictionaryBufferFactory; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; - -/** - * An auxiliary class for reading SparseTable and data written by SparseTableContentWriter. - */ -public class SparseTableContentReader { - - /** - * An interface of a function which is passed to SparseTableContentReader.read. - */ - public interface SparseTableContentReaderInterface { - /** - * Reads data. - * - * @param buffer the DictBuffer. The position of the buffer is set to the head of data. - */ - public void read(final DictBuffer buffer); - } - - protected final int mContentCount; - protected final int mBlockSize; - protected final File mBaseDir; - protected final File mLookupTableFile; - protected final File[] mAddressTableFiles; - protected final File[] mContentFiles; - protected DictBuffer mLookupTableBuffer; - protected final DictBuffer[] mAddressTableBuffers; - private final DictBuffer[] mContentBuffers; - protected final DictionaryBufferFactory mFactory; - - /** - * Sole constructor of SparseTableContentReader. - * - * @param name the name of SparseTable. - * @param blockSize the block size of the content table. - * @param baseDir the directory which contains the files of the content table. - * @param contentFilenames the file names of content files. - * @param contentIds the ids of contents. These ids are used for a suffix of a name of - * address files and content files. - * @param factory the DictionaryBufferFactory which is used for opening the files. - */ - public SparseTableContentReader(final String name, final int blockSize, final File baseDir, - final String[] contentFilenames, final String[] contentIds, - final DictionaryBufferFactory factory) { - if (contentFilenames.length != contentIds.length) { - throw new RuntimeException("The length of contentFilenames and the length of" - + " contentIds are different " + contentFilenames.length + ", " - + contentIds.length); - } - mBlockSize = blockSize; - mBaseDir = baseDir; - mFactory = factory; - mContentCount = contentFilenames.length; - mLookupTableFile = new File(baseDir, name + FormatSpec.LOOKUP_TABLE_FILE_SUFFIX); - mAddressTableFiles = new File[mContentCount]; - mContentFiles = new File[mContentCount]; - for (int i = 0; i < mContentCount; ++i) { - mAddressTableFiles[i] = new File(mBaseDir, - name + FormatSpec.CONTENT_TABLE_FILE_SUFFIX + contentIds[i]); - mContentFiles[i] = new File(mBaseDir, contentFilenames[i] + contentIds[i]); - } - mAddressTableBuffers = new DictBuffer[mContentCount]; - mContentBuffers = new DictBuffer[mContentCount]; - } - - public void openBuffers() throws FileNotFoundException, IOException { - mLookupTableBuffer = mFactory.getDictionaryBuffer(mLookupTableFile); - for (int i = 0; i < mContentCount; ++i) { - mAddressTableBuffers[i] = mFactory.getDictionaryBuffer(mAddressTableFiles[i]); - mContentBuffers[i] = mFactory.getDictionaryBuffer(mContentFiles[i]); - } - } - - protected void read(final int contentIndex, final int index, - final SparseTableContentReaderInterface reader) { - if (index < 0 || (index / mBlockSize) * SparseTable.SIZE_OF_INT_IN_BYTES - >= mLookupTableBuffer.limit()) { - return; - } - - mLookupTableBuffer.position((index / mBlockSize) * SparseTable.SIZE_OF_INT_IN_BYTES); - final int posInAddressTable = mLookupTableBuffer.readInt(); - if (posInAddressTable == SparseTable.NOT_EXIST) { - return; - } - - mAddressTableBuffers[contentIndex].position( - (posInAddressTable + index % mBlockSize) * SparseTable.SIZE_OF_INT_IN_BYTES); - final int address = mAddressTableBuffers[contentIndex].readInt(); - if (address == SparseTable.NOT_EXIST) { - return; - } - - mContentBuffers[contentIndex].position(address); - reader.read(mContentBuffers[contentIndex]); - } -}
\ No newline at end of file diff --git a/java/src/com/android/inputmethod/latin/makedict/SparseTableContentUpdater.java b/java/src/com/android/inputmethod/latin/makedict/SparseTableContentUpdater.java deleted file mode 100644 index 4518f21b9..000000000 --- a/java/src/com/android/inputmethod/latin/makedict/SparseTableContentUpdater.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 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.makedict; - -import com.android.inputmethod.latin.makedict.DictDecoder.DictionaryBufferFactory; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * An auxiliary class for updating data associated with SparseTable. - */ -public class SparseTableContentUpdater extends SparseTableContentReader { - protected OutputStream mLookupTableOutStream; - protected OutputStream[] mAddressTableOutStreams; - protected OutputStream[] mContentOutStreams; - - public SparseTableContentUpdater(final String name, final int blockSize, - final File baseDir, final String[] contentFilenames, final String[] contentIds, - final DictionaryBufferFactory factory) { - super(name, blockSize, baseDir, contentFilenames, contentIds, factory); - mAddressTableOutStreams = new OutputStream[mContentCount]; - mContentOutStreams = new OutputStream[mContentCount]; - } - - protected void openStreamsAndBuffers() throws IOException { - openBuffers(); - mLookupTableOutStream = new FileOutputStream(mLookupTableFile, true /* append */); - for (int i = 0; i < mContentCount; ++i) { - mAddressTableOutStreams[i] = new FileOutputStream(mAddressTableFiles[i], - true /* append */); - mContentOutStreams[i] = new FileOutputStream(mContentFiles[i], true /* append */); - } - } - - /** - * Set the contentIndex-th elements of contentId-th table. - * - * @param contentId the id of the content table. - * @param contentIndex the index where to set the valie. - * @param value the value to set. - */ - protected void setContentValue(final int contentId, final int contentIndex, final int value) - throws IOException { - if ((contentIndex / mBlockSize) * SparseTable.SIZE_OF_INT_IN_BYTES - >= mLookupTableBuffer.limit()) { - // Need to extend the lookup table - final int currentSize = mLookupTableBuffer.limit() - / SparseTable.SIZE_OF_INT_IN_BYTES; - final int target = contentIndex / mBlockSize + 1; - for (int i = currentSize; i < target; ++i) { - BinaryDictEncoderUtils.writeUIntToStream(mLookupTableOutStream, - SparseTable.NOT_EXIST, SparseTable.SIZE_OF_INT_IN_BYTES); - } - // We need to reopen the byte buffer of the lookup table because a MappedByteBuffer in - // Java isn't expanded automatically when the underlying file is expanded. - reopenLookupTable(); - } - - mLookupTableBuffer.position((contentIndex / mBlockSize) * SparseTable.SIZE_OF_INT_IN_BYTES); - int posInAddressTable = mLookupTableBuffer.readInt(); - if (posInAddressTable == SparseTable.NOT_EXIST) { - // Need to extend the address table - mLookupTableBuffer.position(mLookupTableBuffer.position() - - SparseTable.SIZE_OF_INT_IN_BYTES); - posInAddressTable = mAddressTableBuffers[0].limit() / mBlockSize; - BinaryDictEncoderUtils.writeUIntToDictBuffer(mLookupTableBuffer, - posInAddressTable, SparseTable.SIZE_OF_INT_IN_BYTES); - for (int i = 0; i < mContentCount; ++i) { - for (int j = 0; j < mBlockSize; ++j) { - BinaryDictEncoderUtils.writeUIntToStream(mAddressTableOutStreams[i], - SparseTable.NOT_EXIST, SparseTable.SIZE_OF_INT_IN_BYTES); - } - } - // We need to reopen the byte buffers of the address tables because a MappedByteBuffer - // in Java isn't expanded automatically when the underlying file is expanded. - reopenAddressTables(); - } - posInAddressTable += (contentIndex % mBlockSize) * SparseTable.SIZE_OF_INT_IN_BYTES; - - mAddressTableBuffers[contentId].position(posInAddressTable); - BinaryDictEncoderUtils.writeUIntToDictBuffer(mAddressTableBuffers[contentId], - value, SparseTable.SIZE_OF_INT_IN_BYTES); - } - - private void reopenLookupTable() throws IOException { - mLookupTableOutStream.flush(); - mLookupTableBuffer = mFactory.getDictionaryBuffer(mLookupTableFile); - } - - private void reopenAddressTables() throws IOException { - for (int i = 0; i < mContentCount; ++i) { - mAddressTableOutStreams[i].flush(); - mAddressTableBuffers[i] = mFactory.getDictionaryBuffer(mAddressTableFiles[i]); - } - } - - protected void close() throws IOException { - mLookupTableOutStream.close(); - for (final OutputStream stream : mAddressTableOutStreams) { - stream.close(); - } - for (final OutputStream stream : mContentOutStreams) { - stream.close(); - } - } -} diff --git a/java/src/com/android/inputmethod/latin/makedict/SparseTableContentWriter.java b/java/src/com/android/inputmethod/latin/makedict/SparseTableContentWriter.java deleted file mode 100644 index 49f0fd624..000000000 --- a/java/src/com/android/inputmethod/latin/makedict/SparseTableContentWriter.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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 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.makedict; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * An auxiliary class for writing data associated with SparseTable to files. - */ -public class SparseTableContentWriter { - public interface SparseTableContentWriterInterface { - public void write(final OutputStream outStream) throws IOException; - } - - private final int mContentCount; - private final SparseTable mSparseTable; - private final File mLookupTableFile; - protected final File mBaseDir; - private final File[] mAddressTableFiles; - private final File[] mContentFiles; - protected final OutputStream[] mContentOutStreams; - - /** - * Sole constructor of SparseTableContentWriter. - * - * @param name the name of SparseTable. - * @param initialCapacity the initial capacity of SparseTable. - * @param blockSize the block size of the content table. - * @param baseDir the directory which contains the files of the content table. - * @param contentFilenames the file names of content files. - * @param contentIds the ids of contents. These ids are used for a suffix of a name of address - * files and content files. - */ - public SparseTableContentWriter(final String name, final int initialCapacity, - final int blockSize, final File baseDir, final String[] contentFilenames, - final String[] contentIds) { - if (contentFilenames.length != contentIds.length) { - throw new RuntimeException("The length of contentFilenames and the length of" - + " contentIds are different " + contentFilenames.length + ", " - + contentIds.length); - } - mContentCount = contentFilenames.length; - mSparseTable = new SparseTable(initialCapacity, blockSize, mContentCount); - mLookupTableFile = new File(baseDir, name + FormatSpec.LOOKUP_TABLE_FILE_SUFFIX); - mAddressTableFiles = new File[mContentCount]; - mContentFiles = new File[mContentCount]; - mBaseDir = baseDir; - for (int i = 0; i < mContentCount; ++i) { - mAddressTableFiles[i] = new File(mBaseDir, - name + FormatSpec.CONTENT_TABLE_FILE_SUFFIX + contentIds[i]); - mContentFiles[i] = new File(mBaseDir, contentFilenames[i] + contentIds[i]); - } - mContentOutStreams = new OutputStream[mContentCount]; - } - - public void openStreams() throws FileNotFoundException { - for (int i = 0; i < mContentCount; ++i) { - mContentOutStreams[i] = new FileOutputStream(mContentFiles[i]); - } - } - - protected void write(final int contentIndex, final int index, - final SparseTableContentWriterInterface writer) throws IOException { - mSparseTable.set(contentIndex, index, (int) mContentFiles[contentIndex].length()); - writer.write(mContentOutStreams[contentIndex]); - mContentOutStreams[contentIndex].flush(); - } - - public void closeStreams() throws IOException { - mSparseTable.writeToFiles(mLookupTableFile, mAddressTableFiles); - for (int i = 0; i < mContentCount; ++i) { - mContentOutStreams[i].close(); - } - } -}
\ No newline at end of file diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver3DictEncoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver3DictEncoder.java index 92eb861d6..5da34534e 100644 --- a/java/src/com/android/inputmethod/latin/makedict/Ver3DictEncoder.java +++ b/java/src/com/android/inputmethod/latin/makedict/Ver3DictEncoder.java @@ -169,7 +169,7 @@ public class Ver3DictEncoder implements DictEncoder { private void writeChildrenPosition(final PtNode ptNode, final FormatOptions formatOptions) { final int childrenPos = BinaryDictEncoderUtils.getChildrenPosition(ptNode, formatOptions); - if (formatOptions.supportsDynamicUpdate()) { + if (formatOptions.mSupportsDynamicUpdate) { mPosition += BinaryDictEncoderUtils.writeSignedChildrenPosition(mBuffer, mPosition, childrenPos); } else { diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java index 3be62f066..734223ec2 100644 --- a/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java +++ b/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java @@ -40,52 +40,26 @@ import java.util.Arrays; public class Ver4DictDecoder extends AbstractDictDecoder { private static final String TAG = Ver4DictDecoder.class.getSimpleName(); - protected static final int FILETYPE_TRIE = 1; - protected static final int FILETYPE_FREQUENCY = 2; - protected static final int FILETYPE_TERMINAL_ADDRESS_TABLE = 3; - protected static final int FILETYPE_BIGRAM_FREQ = 4; - protected static final int FILETYPE_SHORTCUT = 5; - protected static final int FILETYPE_HEADER = 6; - - protected final File mDictDirectory; - protected final DictionaryBufferFactory mBufferFactory; + private static final int FILETYPE_TRIE = 1; + private static final int FILETYPE_FREQUENCY = 2; + private static final int FILETYPE_TERMINAL_ADDRESS_TABLE = 3; + private static final int FILETYPE_BIGRAM_FREQ = 4; + private static final int FILETYPE_SHORTCUT = 5; + + private final File mDictDirectory; + private final DictionaryBufferFactory mBufferFactory; protected DictBuffer mDictBuffer; - protected DictBuffer mHeaderBuffer; - protected DictBuffer mFrequencyBuffer; - protected DictBuffer mTerminalAddressTableBuffer; - private BigramContentReader mBigramReader; - private ShortcutContentReader mShortcutReader; - - /** - * Raw PtNode info straight out of a trie file in version 4 dictionary. - */ - protected static final class Ver4PtNodeInfo { - public final int mFlags; - public final int[] mCharacters; - public final int mTerminalId; - public final int mChildrenPos; - public final int mParentPos; - public final int mNodeSize; - public int mStartIndexOfCharacters; - public int mEndIndexOfCharacters; // exclusive - - public Ver4PtNodeInfo(final int flags, final int[] characters, final int terminalId, - final int childrenPos, final int parentPos, final int nodeSize) { - mFlags = flags; - mCharacters = characters; - mTerminalId = terminalId; - mChildrenPos = childrenPos; - mParentPos = parentPos; - mNodeSize = nodeSize; - mStartIndexOfCharacters = 0; - mEndIndexOfCharacters = characters.length; - } - } + private DictBuffer mFrequencyBuffer; + private DictBuffer mTerminalAddressTableBuffer; + private DictBuffer mBigramBuffer; + private DictBuffer mShortcutBuffer; + private SparseTable mBigramAddressTable; + private SparseTable mShortcutAddressTable; @UsedForTesting /* package */ Ver4DictDecoder(final File dictDirectory, final int factoryFlag) { mDictDirectory = dictDirectory; - mDictBuffer = mHeaderBuffer = mFrequencyBuffer = null; + mDictBuffer = mFrequencyBuffer = null; if ((factoryFlag & MASK_DICTBUFFER) == USE_READONLY_BYTEBUFFER) { mBufferFactory = new DictionaryBufferFromReadOnlyByteBufferFactory(); @@ -102,16 +76,13 @@ public class Ver4DictDecoder extends AbstractDictDecoder { /* package */ Ver4DictDecoder(final File dictDirectory, final DictionaryBufferFactory factory) { mDictDirectory = dictDirectory; mBufferFactory = factory; - mDictBuffer = mHeaderBuffer = mFrequencyBuffer = null; + mDictBuffer = mFrequencyBuffer = null; } - protected File getFile(final int fileType) throws UnsupportedFormatException { + private File getFile(final int fileType) { if (fileType == FILETYPE_TRIE) { return new File(mDictDirectory, mDictDirectory.getName() + FormatSpec.TRIE_FILE_EXTENSION); - } else if (fileType == FILETYPE_HEADER) { - return new File(mDictDirectory, - mDictDirectory.getName() + FormatSpec.HEADER_FILE_EXTENSION); } else if (fileType == FILETYPE_FREQUENCY) { return new File(mDictDirectory, mDictDirectory.getName() + FormatSpec.FREQ_FILE_EXTENSION); @@ -127,27 +98,20 @@ public class Ver4DictDecoder extends AbstractDictDecoder { mDictDirectory.getName() + FormatSpec.SHORTCUT_FILE_EXTENSION + FormatSpec.SHORTCUT_CONTENT_ID); } else { - throw new UnsupportedFormatException("Unsupported kind of file : " + fileType); + throw new RuntimeException("Unsupported kind of file : " + fileType); } } @Override - public void openDictBuffer() throws FileNotFoundException, IOException, - UnsupportedFormatException { - if (!mDictDirectory.isDirectory()) { - throw new UnsupportedFormatException("Format 4 dictionary needs a directory"); - } - mHeaderBuffer = mBufferFactory.getDictionaryBuffer(getFile(FILETYPE_HEADER)); + public void openDictBuffer() throws FileNotFoundException, IOException { mDictBuffer = mBufferFactory.getDictionaryBuffer(getFile(FILETYPE_TRIE)); mFrequencyBuffer = mBufferFactory.getDictionaryBuffer(getFile(FILETYPE_FREQUENCY)); mTerminalAddressTableBuffer = mBufferFactory.getDictionaryBuffer( getFile(FILETYPE_TERMINAL_ADDRESS_TABLE)); - mBigramReader = new BigramContentReader(mDictDirectory.getName(), - mDictDirectory, mBufferFactory, false); - mBigramReader.openBuffers(); - mShortcutReader = new ShortcutContentReader(mDictDirectory.getName(), mDictDirectory, - mBufferFactory); - mShortcutReader.openBuffers(); + mBigramBuffer = mBufferFactory.getDictionaryBuffer(getFile(FILETYPE_BIGRAM_FREQ)); + loadBigramAddressSparseTable(); + mShortcutBuffer = mBufferFactory.getDictionaryBuffer(getFile(FILETYPE_SHORTCUT)); + loadShortcutAddressSparseTable(); } @Override @@ -155,134 +119,46 @@ public class Ver4DictDecoder extends AbstractDictDecoder { return mDictBuffer != null; } - @UsedForTesting - /* package */ DictBuffer getHeaderBuffer() { - return mHeaderBuffer; - } - - @UsedForTesting /* package */ DictBuffer getDictBuffer() { return mDictBuffer; } @Override public FileHeader readHeader() throws IOException, UnsupportedFormatException { - if (mHeaderBuffer == null) { + if (mDictBuffer == null) { openDictBuffer(); } - mHeaderBuffer.position(0); - final FileHeader header = super.readHeader(mHeaderBuffer); + final FileHeader header = super.readHeader(mDictBuffer); final int version = header.mFormatOptions.mVersion; - if (version != FormatSpec.VERSION4) { + if (version != 4) { throw new UnsupportedFormatException("File header has a wrong version : " + version); } return header; } - /** - * An auxiliary class for reading bigrams. - */ - protected static class BigramContentReader extends SparseTableContentReader { - public BigramContentReader(final String name, final File baseDir, - final DictionaryBufferFactory factory, final boolean hasTimestamp) { - super(name + FormatSpec.BIGRAM_FILE_EXTENSION, - FormatSpec.BIGRAM_ADDRESS_TABLE_BLOCK_SIZE, baseDir, - getContentFilenames(name, hasTimestamp), getContentIds(hasTimestamp), factory); - } - - // TODO: Consolidate this method and BigramContentWriter.getContentFilenames. - protected static String[] getContentFilenames(final String name, - final boolean hasTimestamp) { - final String[] contentFilenames; - if (hasTimestamp) { - contentFilenames = new String[] { name + FormatSpec.BIGRAM_FILE_EXTENSION, - name + FormatSpec.BIGRAM_FILE_EXTENSION }; - } else { - contentFilenames = new String[] { name + FormatSpec.BIGRAM_FILE_EXTENSION }; - } - return contentFilenames; - } - - // TODO: Consolidate this method and BigramContentWriter.getContentIds. - protected static String[] getContentIds(final boolean hasTimestamp) { - final String[] contentIds; - if (hasTimestamp) { - contentIds = new String[] { FormatSpec.BIGRAM_FREQ_CONTENT_ID, - FormatSpec.BIGRAM_TIMESTAMP_CONTENT_ID }; - } else { - contentIds = new String[] { FormatSpec.BIGRAM_FREQ_CONTENT_ID }; - } - return contentIds; - } - - public ArrayList<PendingAttribute> readTargetsAndFrequencies(final int terminalId, - final DictBuffer terminalAddressTableBuffer) { - final ArrayList<PendingAttribute> bigrams = CollectionUtils.newArrayList(); - read(FormatSpec.BIGRAM_FREQ_CONTENT_INDEX, terminalId, - new SparseTableContentReaderInterface() { - @Override - public void read(final DictBuffer buffer) { - while (bigrams.size() < FormatSpec.MAX_BIGRAMS_IN_A_PTNODE) { - // If bigrams.size() reaches FormatSpec.MAX_BIGRAMS_IN_A_PTNODE, - // remaining bigram entries are ignored. - final int bigramFlags = buffer.readUnsignedByte(); - final int targetTerminalId = buffer.readUnsignedInt24(); - terminalAddressTableBuffer.position(targetTerminalId - * FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE); - final int targetAddress = - terminalAddressTableBuffer.readUnsignedInt24(); - bigrams.add(new PendingAttribute(bigramFlags - & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY, - targetAddress)); - if (0 == (bigramFlags - & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT)) { - break; - } - } - if (bigrams.size() >= FormatSpec.MAX_BIGRAMS_IN_A_PTNODE) { - throw new RuntimeException("Too many bigrams in a PtNode (" - + bigrams.size() + " but max is " - + FormatSpec.MAX_BIGRAMS_IN_A_PTNODE + ")"); - } - } - }); - if (bigrams.isEmpty()) return null; - return bigrams; - } + private void loadBigramAddressSparseTable() throws IOException { + final File lookupIndexFile = new File(mDictDirectory, mDictDirectory.getName() + + FormatSpec.BIGRAM_FILE_EXTENSION + FormatSpec.LOOKUP_TABLE_FILE_SUFFIX); + final File freqsFile = new File(mDictDirectory, mDictDirectory.getName() + + FormatSpec.BIGRAM_FILE_EXTENSION + FormatSpec.CONTENT_TABLE_FILE_SUFFIX + + FormatSpec.BIGRAM_FREQ_CONTENT_ID); + mBigramAddressTable = SparseTable.readFromFiles(lookupIndexFile, new File[] { freqsFile }, + FormatSpec.BIGRAM_ADDRESS_TABLE_BLOCK_SIZE); } - /** - * An auxiliary class for reading shortcuts. - */ - protected static class ShortcutContentReader extends SparseTableContentReader { - public ShortcutContentReader(final String name, final File baseDir, - final DictionaryBufferFactory factory) { - super(name + FormatSpec.SHORTCUT_FILE_EXTENSION, - FormatSpec.SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE, baseDir, - new String[] { name + FormatSpec.SHORTCUT_FILE_EXTENSION }, - new String[] { FormatSpec.SHORTCUT_CONTENT_ID }, factory); - } - - public ArrayList<WeightedString> readShortcuts(final int terminalId) { - final ArrayList<WeightedString> shortcuts = CollectionUtils.newArrayList(); - read(FormatSpec.SHORTCUT_CONTENT_INDEX, terminalId, - new SparseTableContentReaderInterface() { - @Override - public void read(final DictBuffer buffer) { - while (true) { - final int flags = buffer.readUnsignedByte(); - final String word = CharEncoding.readString(buffer); - shortcuts.add(new WeightedString(word, - flags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY)); - if (0 == (flags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT)) { - break; - } - } - } - }); - if (shortcuts.isEmpty()) return null; - return shortcuts; - } + // TODO: Let's have something like SparseTableContentsReader in this class. + private void loadShortcutAddressSparseTable() throws IOException { + final File lookupIndexFile = new File(mDictDirectory, mDictDirectory.getName() + + FormatSpec.SHORTCUT_FILE_EXTENSION + FormatSpec.LOOKUP_TABLE_FILE_SUFFIX); + final File contentFile = new File(mDictDirectory, mDictDirectory.getName() + + FormatSpec.SHORTCUT_FILE_EXTENSION + FormatSpec.CONTENT_TABLE_FILE_SUFFIX + + FormatSpec.SHORTCUT_CONTENT_ID); + final File timestampsFile = new File(mDictDirectory, mDictDirectory.getName() + + FormatSpec.SHORTCUT_FILE_EXTENSION + FormatSpec.CONTENT_TABLE_FILE_SUFFIX + + FormatSpec.SHORTCUT_CONTENT_ID); + mShortcutAddressTable = SparseTable.readFromFiles(lookupIndexFile, + new File[] { contentFile, timestampsFile }, + FormatSpec.SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE); } protected static class PtNodeReader extends AbstractDictDecoder.PtNodeReader { @@ -296,82 +172,102 @@ public class Ver4DictDecoder extends AbstractDictDecoder { } } - private final int[] mCharacterBufferForReadingVer4PtNodeInfo - = new int[FormatSpec.MAX_WORD_LENGTH]; + private ArrayList<WeightedString> readShortcuts(final int terminalId) { + if (mShortcutAddressTable.get(0, terminalId) == SparseTable.NOT_EXIST) return null; + + final ArrayList<WeightedString> ret = CollectionUtils.newArrayList(); + final int posOfShortcuts = mShortcutAddressTable.get(FormatSpec.SHORTCUT_CONTENT_INDEX, + terminalId); + mShortcutBuffer.position(posOfShortcuts); + while (true) { + final int flags = mShortcutBuffer.readUnsignedByte(); + final String word = CharEncoding.readString(mShortcutBuffer); + ret.add(new WeightedString(word, + flags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY)); + if (0 == (flags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT)) break; + } + return ret; + } - /** - * Reads PtNode from ptNodePos in the trie file and returns Ver4PtNodeInfo. - * - * @param ptNodePos the position of PtNode. - * @param options the format options. - * @return Ver4PtNodeInfo. - */ // TODO: Make this buffer thread safe. // TODO: Support words longer than FormatSpec.MAX_WORD_LENGTH. - protected Ver4PtNodeInfo readVer4PtNodeInfo(final int ptNodePos, final FormatOptions options) { - int readingPos = ptNodePos; + private final int[] mCharacterBuffer = new int[FormatSpec.MAX_WORD_LENGTH]; + @Override + public PtNodeInfo readPtNode(int ptNodePos, FormatOptions options) { + int addressPointer = ptNodePos; final int flags = PtNodeReader.readPtNodeOptionFlags(mDictBuffer); - readingPos += FormatSpec.PTNODE_FLAGS_SIZE; + addressPointer += FormatSpec.PTNODE_FLAGS_SIZE; - final int parentPos = PtNodeReader.readParentAddress(mDictBuffer, options); + final int parentAddress = PtNodeReader.readParentAddress(mDictBuffer, options); if (BinaryDictIOUtils.supportsDynamicUpdate(options)) { - readingPos += FormatSpec.PARENT_ADDRESS_SIZE; + addressPointer += FormatSpec.PARENT_ADDRESS_SIZE; } final int characters[]; if (0 != (flags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS)) { int index = 0; int character = CharEncoding.readChar(mDictBuffer); - readingPos += CharEncoding.getCharSize(character); + addressPointer += CharEncoding.getCharSize(character); while (FormatSpec.INVALID_CHARACTER != character && index < FormatSpec.MAX_WORD_LENGTH) { - mCharacterBufferForReadingVer4PtNodeInfo[index++] = character; + mCharacterBuffer[index++] = character; character = CharEncoding.readChar(mDictBuffer); - readingPos += CharEncoding.getCharSize(character); + addressPointer += CharEncoding.getCharSize(character); } - characters = Arrays.copyOfRange(mCharacterBufferForReadingVer4PtNodeInfo, 0, index); + characters = Arrays.copyOfRange(mCharacterBuffer, 0, index); } else { final int character = CharEncoding.readChar(mDictBuffer); - readingPos += CharEncoding.getCharSize(character); + addressPointer += CharEncoding.getCharSize(character); characters = new int[] { character }; } final int terminalId; if (0 != (FormatSpec.FLAG_IS_TERMINAL & flags)) { terminalId = PtNodeReader.readTerminalId(mDictBuffer); - readingPos += FormatSpec.PTNODE_TERMINAL_ID_SIZE; + addressPointer += FormatSpec.PTNODE_TERMINAL_ID_SIZE; } else { terminalId = PtNode.NOT_A_TERMINAL; } - int childrenPos = PtNodeReader.readChildrenAddress(mDictBuffer, flags, options); - if (childrenPos != FormatSpec.NO_CHILDREN_ADDRESS) { - childrenPos += readingPos; - } - readingPos += BinaryDictIOUtils.getChildrenAddressSize(flags, options); - - return new Ver4PtNodeInfo(flags, characters, terminalId, childrenPos, parentPos, - readingPos - ptNodePos); - } - - @Override - public PtNodeInfo readPtNode(int ptNodePos, FormatOptions options) { - final Ver4PtNodeInfo nodeInfo = readVer4PtNodeInfo(ptNodePos, options); - final int frequency; - if (0 != (FormatSpec.FLAG_IS_TERMINAL & nodeInfo.mFlags)) { - frequency = PtNodeReader.readFrequency(mFrequencyBuffer, nodeInfo.mTerminalId); + if (0 != (FormatSpec.FLAG_IS_TERMINAL & flags)) { + frequency = PtNodeReader.readFrequency(mFrequencyBuffer, terminalId); } else { frequency = PtNode.NOT_A_TERMINAL; } - - final ArrayList<WeightedString> shortcutTargets = mShortcutReader.readShortcuts( - nodeInfo.mTerminalId); - final ArrayList<PendingAttribute> bigrams = mBigramReader.readTargetsAndFrequencies( - nodeInfo.mTerminalId, mTerminalAddressTableBuffer); - - return new PtNodeInfo(ptNodePos, ptNodePos + nodeInfo.mNodeSize, nodeInfo.mFlags, - nodeInfo.mCharacters, frequency, nodeInfo.mParentPos, nodeInfo.mChildrenPos, - shortcutTargets, bigrams); + int childrenAddress = PtNodeReader.readChildrenAddress(mDictBuffer, flags, options); + if (childrenAddress != FormatSpec.NO_CHILDREN_ADDRESS) { + childrenAddress += addressPointer; + } + addressPointer += BinaryDictIOUtils.getChildrenAddressSize(flags, options); + final ArrayList<WeightedString> shortcutTargets = readShortcuts(terminalId); + + final ArrayList<PendingAttribute> bigrams; + if (0 != (flags & FormatSpec.FLAG_HAS_BIGRAMS)) { + bigrams = new ArrayList<PendingAttribute>(); + final int posOfBigrams = mBigramAddressTable.get(0 /* contentTableIndex */, terminalId); + mBigramBuffer.position(posOfBigrams); + while (bigrams.size() < FormatSpec.MAX_BIGRAMS_IN_A_PTNODE) { + // If bigrams.size() reaches FormatSpec.MAX_BIGRAMS_IN_A_PTNODE, + // remaining bigram entries are ignored. + final int bigramFlags = mBigramBuffer.readUnsignedByte(); + final int targetTerminalId = mBigramBuffer.readUnsignedInt24(); + mTerminalAddressTableBuffer.position( + targetTerminalId * FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE); + final int targetAddress = mTerminalAddressTableBuffer.readUnsignedInt24(); + bigrams.add(new PendingAttribute( + bigramFlags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY, + targetAddress)); + if (0 == (bigramFlags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT)) break; + } + if (bigrams.size() >= FormatSpec.MAX_BIGRAMS_IN_A_PTNODE) { + throw new RuntimeException("Too many bigrams in a PtNode (" + bigrams.size() + + " but max is " + FormatSpec.MAX_BIGRAMS_IN_A_PTNODE + ")"); + } + } else { + bigrams = null; + } + return new PtNodeInfo(ptNodePos, addressPointer, flags, characters, frequency, + parentAddress, childrenAddress, shortcutTargets, bigrams); } private void deleteDictFiles() { @@ -422,14 +318,10 @@ public class Ver4DictDecoder extends AbstractDictDecoder { @Override public boolean readAndFollowForwardLink() { - final int forwardLinkPos = mDictBuffer.position(); - int nextRelativePos = BinaryDictDecoderUtils.readSInt24(mDictBuffer); - if (nextRelativePos != FormatSpec.NO_FORWARD_LINK_ADDRESS) { - final int nextPos = forwardLinkPos + nextRelativePos; - if (nextPos >= 0 && nextPos < mDictBuffer.limit()) { - mDictBuffer.position(nextPos); - return true; - } + final int nextAddress = mDictBuffer.readUnsignedInt24(); + if (nextAddress >= 0 && nextAddress < mDictBuffer.limit()) { + mDictBuffer.position(nextAddress); + return true; } return false; } diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java index 8b80ebe63..8d5b48a9b 100644 --- a/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java +++ b/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java @@ -25,8 +25,6 @@ import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode; import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray; import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; -import com.android.inputmethod.latin.utils.CollectionUtils; -import com.android.inputmethod.latin.utils.FileUtils; import java.io.File; import java.io.FileNotFoundException; @@ -34,8 +32,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.Iterator; /** @@ -46,8 +42,8 @@ public class Ver4DictEncoder implements DictEncoder { private final File mDictPlacedDir; private byte[] mTrieBuf; private int mTriePos; + private int mHeaderSize; private OutputStream mTrieOutStream; - private OutputStream mHeaderOutStream; private OutputStream mFreqOutStream; private OutputStream mUnigramTimestampOutStream; private OutputStream mTerminalAddressTableOutStream; @@ -61,6 +57,62 @@ public class Ver4DictEncoder implements DictEncoder { mDictPlacedDir = dictPlacedDir; } + private interface SparseTableContentWriterInterface { + public void write(final OutputStream outStream) throws IOException; + } + + private static class SparseTableContentWriter { + private final int mContentCount; + private final SparseTable mSparseTable; + private final File mLookupTableFile; + protected final File mBaseDir; + private final File[] mAddressTableFiles; + private final File[] mContentFiles; + protected final OutputStream[] mContentOutStreams; + + public SparseTableContentWriter(final String name, final int initialCapacity, + final int blockSize, final File baseDir, final String[] contentFilenames, + final String[] contentIds) { + if (contentFilenames.length != contentIds.length) { + throw new RuntimeException("The length of contentFilenames and the length of" + + " contentIds are different " + contentFilenames.length + ", " + + contentIds.length); + } + mContentCount = contentFilenames.length; + mSparseTable = new SparseTable(initialCapacity, blockSize, mContentCount); + mLookupTableFile = new File(baseDir, name + FormatSpec.LOOKUP_TABLE_FILE_SUFFIX); + mAddressTableFiles = new File[mContentCount]; + mContentFiles = new File[mContentCount]; + mBaseDir = baseDir; + for (int i = 0; i < mContentCount; ++i) { + mAddressTableFiles[i] = new File(mBaseDir, + name + FormatSpec.CONTENT_TABLE_FILE_SUFFIX + contentIds[i]); + mContentFiles[i] = new File(mBaseDir, contentFilenames[i] + contentIds[i]); + } + mContentOutStreams = new OutputStream[mContentCount]; + } + + public void openStreams() throws FileNotFoundException { + for (int i = 0; i < mContentCount; ++i) { + mContentOutStreams[i] = new FileOutputStream(mContentFiles[i]); + } + } + + protected void write(final int contentIndex, final int index, + final SparseTableContentWriterInterface writer) throws IOException { + mSparseTable.set(contentIndex, index, (int) mContentFiles[contentIndex].length()); + writer.write(mContentOutStreams[contentIndex]); + mContentOutStreams[contentIndex].flush(); + } + + public void closeStreams() throws IOException { + mSparseTable.writeToFiles(mLookupTableFile, mAddressTableFiles); + for (int i = 0; i < mContentCount; ++i) { + mContentOutStreams[i].close(); + } + } + } + private static class BigramContentWriter extends SparseTableContentWriter { private final boolean mWriteTimestamp; @@ -186,21 +238,16 @@ public class Ver4DictEncoder implements DictEncoder { mBaseFilename = header.getId() + "." + header.getVersion(); mDictDir = new File(mDictPlacedDir, mBaseFilename); final File trieFile = new File(mDictDir, mBaseFilename + FormatSpec.TRIE_FILE_EXTENSION); - final File headerFile = new File(mDictDir, - mBaseFilename + FormatSpec.HEADER_FILE_EXTENSION); final File freqFile = new File(mDictDir, mBaseFilename + FormatSpec.FREQ_FILE_EXTENSION); final File timestampFile = new File(mDictDir, mBaseFilename + FormatSpec.UNIGRAM_TIMESTAMP_FILE_EXTENSION); final File terminalAddressTableFile = new File(mDictDir, mBaseFilename + FormatSpec.TERMINAL_ADDRESS_TABLE_FILE_EXTENSION); if (!mDictDir.isDirectory()) { - if (mDictDir.exists()) { - FileUtils.deleteRecursively(mDictDir); - } + if (mDictDir.exists()) mDictDir.delete(); mDictDir.mkdirs(); } mTrieOutStream = new FileOutputStream(trieFile); - mHeaderOutStream = new FileOutputStream(headerFile); mFreqOutStream = new FileOutputStream(freqFile); mTerminalAddressTableOutStream = new FileOutputStream(terminalAddressTableFile); if (formatOptions.mHasTimestamp) { @@ -213,9 +260,6 @@ public class Ver4DictEncoder implements DictEncoder { if (mTrieOutStream != null) { mTrieOutStream.close(); } - if (mHeaderOutStream != null) { - mHeaderOutStream.close(); - } if (mFreqOutStream != null) { mFreqOutStream.close(); } @@ -227,7 +271,6 @@ public class Ver4DictEncoder implements DictEncoder { } } finally { mTrieOutStream = null; - mHeaderOutStream = null; mFreqOutStream = null; mTerminalAddressTableOutStream = null; } @@ -248,34 +291,16 @@ public class Ver4DictEncoder implements DictEncoder { openStreams(formatOptions, dict.mOptions); } - BinaryDictEncoderUtils.writeDictionaryHeader(mHeaderOutStream, dict, formatOptions); + mHeaderSize = BinaryDictEncoderUtils.writeDictionaryHeader(mTrieOutStream, dict, + formatOptions); MakedictLog.i("Flattening the tree..."); ArrayList<PtNodeArray> flatNodes = BinaryDictEncoderUtils.flattenTree(dict.mRootNodeArray); int terminalCount = 0; - final ArrayList<PtNode> nodes = CollectionUtils.newArrayList(); for (final PtNodeArray array : flatNodes) { for (final PtNode node : array.mData) { - if (node.isTerminal()) { - nodes.add(node); - node.mTerminalId = terminalCount++; - } - } - } - Collections.sort(nodes, new Comparator<PtNode>() { - @Override - public int compare(final PtNode lhs, final PtNode rhs) { - if (lhs.mFrequency != rhs.mFrequency) { - return lhs.mFrequency < rhs.mFrequency ? -1 : 1; - } - if (lhs.mTerminalId < rhs.mTerminalId) return -1; - if (lhs.mTerminalId > rhs.mTerminalId) return 1; - return 0; + if (node.isTerminal()) node.mTerminalId = terminalCount++; } - }); - int count = 0; - for (final PtNode node : nodes) { - node.mTerminalId = count++; } MakedictLog.i("Computing addresses..."); @@ -312,7 +337,7 @@ public class Ver4DictEncoder implements DictEncoder { @Override public void setPosition(int position) { - if (mTrieBuf == null || position < 0 || position > mTrieBuf.length) return; + if (mTrieBuf == null || position < 0 || position >- mTrieBuf.length) return; mTriePos = position; } @@ -365,7 +390,7 @@ public class Ver4DictEncoder implements DictEncoder { private void writeChildrenPosition(PtNode ptNode, FormatOptions formatOptions) { final int childrenPos = BinaryDictEncoderUtils.getChildrenPosition(ptNode, formatOptions); - if (formatOptions.supportsDynamicUpdate()) { + if (formatOptions.mSupportsDynamicUpdate) { mTriePos += BinaryDictEncoderUtils.writeSignedChildrenPosition(mTrieBuf, mTriePos, childrenPos); } else { @@ -432,7 +457,7 @@ public class Ver4DictEncoder implements DictEncoder { ptNode.mFrequency, FormatSpec.FREQUENCY_AND_FLAGS_SIZE); BinaryDictEncoderUtils.writeUIntToBuffer(terminalAddressTableBuf, ptNode.mTerminalId * FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, - ptNode.mCachedAddressAfterUpdate, + ptNode.mCachedAddressAfterUpdate + mHeaderSize, FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE); } } diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver4DictUpdater.java b/java/src/com/android/inputmethod/latin/makedict/Ver4DictUpdater.java index c46bc36bb..3d8f186ba 100644 --- a/java/src/com/android/inputmethod/latin/makedict/Ver4DictUpdater.java +++ b/java/src/com/android/inputmethod/latin/makedict/Ver4DictUpdater.java @@ -17,130 +17,29 @@ package com.android.inputmethod.latin.makedict; import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding; -import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader; -import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions; -import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode; import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; -import com.android.inputmethod.latin.utils.CollectionUtils; - -import android.util.Log; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; /** * An implementation of DictUpdater for version 4 binary dictionary. */ @UsedForTesting public class Ver4DictUpdater extends Ver4DictDecoder implements DictUpdater { - private static final String TAG = Ver4DictUpdater.class.getSimpleName(); - - private OutputStream mDictStream; - private final File mFrequencyFile; @UsedForTesting - public Ver4DictUpdater(final File dictDirectory, final int factoryType) - throws UnsupportedFormatException { + public Ver4DictUpdater(final File dictDirectory, final int factoryType) { // DictUpdater must have an updatable DictBuffer. super(dictDirectory, ((factoryType & MASK_DICTBUFFER) == USE_BYTEARRAY) ? USE_BYTEARRAY : USE_WRITABLE_BYTEBUFFER); - mFrequencyFile = getFile(FILETYPE_FREQUENCY); - } - - private static class BigramContentUpdater extends SparseTableContentUpdater { - public BigramContentUpdater(final String name, final File baseDir, - final boolean hasTimestamp) { - super(name + FormatSpec.BIGRAM_FILE_EXTENSION, - FormatSpec.BIGRAM_ADDRESS_TABLE_BLOCK_SIZE, baseDir, - BigramContentReader.getContentFilenames(name, hasTimestamp), - BigramContentReader.getContentIds(hasTimestamp), - new DictionaryBufferFromWritableByteBufferFactory()); - } - - public void insertBigramEntries(final int terminalId, final int frequency, - final ArrayList<PendingAttribute> entries) throws IOException { - if (terminalId < 0) { - throw new RuntimeException("Invalid terminal id : " + terminalId); - } - openStreamsAndBuffers(); - - if (entries == null || entries.isEmpty()) { - setContentValue(FormatSpec.BIGRAM_FREQ_CONTENT_INDEX, terminalId, - SparseTable.NOT_EXIST); - return; - } - final int positionOfEntries = - (int) mContentFiles[FormatSpec.BIGRAM_FREQ_CONTENT_INDEX].length(); - setContentValue(FormatSpec.BIGRAM_FREQ_CONTENT_INDEX, terminalId, positionOfEntries); - - final Iterator<PendingAttribute> bigramIterator = entries.iterator(); - while (bigramIterator.hasNext()) { - final PendingAttribute entry = bigramIterator.next(); - final int flags = BinaryDictEncoderUtils.makeBigramFlags(bigramIterator.hasNext(), - 0 /* offset */, entry.mFrequency, frequency, "" /* word */); - BinaryDictEncoderUtils.writeUIntToStream( - mContentOutStreams[FormatSpec.BIGRAM_FREQ_CONTENT_INDEX], flags, - FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE); - BinaryDictEncoderUtils.writeUIntToStream( - mContentOutStreams[FormatSpec.BIGRAM_FREQ_CONTENT_INDEX], entry.mAddress, - FormatSpec.PTNODE_ATTRIBUTE_MAX_ADDRESS_SIZE); - } - close(); - } - } - - private static class ShortcutContentUpdater extends SparseTableContentUpdater { - public ShortcutContentUpdater(final String name, final File baseDir) { - super(name + FormatSpec.SHORTCUT_FILE_EXTENSION, - FormatSpec.SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE, baseDir, - new String[] { name + FormatSpec.SHORTCUT_FILE_EXTENSION }, - new String[] { FormatSpec.SHORTCUT_CONTENT_ID }, - new DictionaryBufferFromWritableByteBufferFactory()); - } - - public void insertShortcuts(final int terminalId, - final ArrayList<WeightedString> shortcuts) throws IOException { - if (terminalId < 0) { - throw new RuntimeException("Invalid terminal id : " + terminalId); - } - openStreamsAndBuffers(); - if (shortcuts == null || shortcuts.isEmpty()) { - setContentValue(FormatSpec.SHORTCUT_CONTENT_INDEX, terminalId, - SparseTable.NOT_EXIST); - return; - } - - final int positionOfShortcuts = - (int) mContentFiles[FormatSpec.SHORTCUT_CONTENT_INDEX].length(); - setContentValue(FormatSpec.SHORTCUT_CONTENT_INDEX, terminalId, positionOfShortcuts); - - final Iterator<WeightedString> shortcutIterator = shortcuts.iterator(); - while (shortcutIterator.hasNext()) { - final WeightedString target = shortcutIterator.next(); - final int shortcutFlags = BinaryDictEncoderUtils.makeShortcutFlags( - shortcutIterator.hasNext(), target.mFrequency); - BinaryDictEncoderUtils.writeUIntToStream( - mContentOutStreams[FormatSpec.SHORTCUT_CONTENT_INDEX], shortcutFlags, - FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE); - CharEncoding.writeString(mContentOutStreams[FormatSpec.SHORTCUT_CONTENT_INDEX], - target.mWord); - } - close(); - } } @Override public void deleteWord(final String word) throws IOException, UnsupportedFormatException { - if (mDictBuffer == null) { - openDictBuffer(); - readHeader(); - } + if (mDictBuffer == null) openDictBuffer(); + readHeader(); final int wordPos = getTerminalPosition(word); if (wordPos != FormatSpec.NOT_VALID_WORD) { mDictBuffer.position(wordPos); @@ -150,623 +49,11 @@ public class Ver4DictUpdater extends Ver4DictDecoder implements DictUpdater { } } - private int getNewTerminalId() { - // The size of frequency file is FormatSpec.FREQUENCY_AND_FLAGS_SIZE * number of terminals - // because each terminal always has a frequency. - // So we can get a fresh terminal id by this logic. - // CAVEAT: we are reading the file size from the disk each time: beware of race conditions, - // even on one thread. - return (int) (mFrequencyFile.length() / FormatSpec.FREQUENCY_AND_FLAGS_SIZE); - } - - private void updateParentPosIfNotMoved(final int nodePos, final int newParentPos, - final FormatOptions formatOptions) { - final int originalPos = getPosition(); - setPosition(nodePos); - final int flags = PtNodeReader.readPtNodeOptionFlags(mDictBuffer); - if (!BinaryDictIOUtils.isMovedPtNode(flags, formatOptions)) { - final int parentOffset = newParentPos - nodePos; - BinaryDictIOUtils.writeSInt24ToBuffer(mDictBuffer, parentOffset); - } - setPosition(originalPos); - } - - private void updateParentPositions(final int nodeArrayPos, final int newParentPos, - final FormatOptions formatOptions) { - final int originalPos = mDictBuffer.position(); - mDictBuffer.position(nodeArrayPos); - int jumpCount = 0; - do { - final int count = readPtNodeCount(); - for (int i = 0; i < count; ++i) { - updateParentPosIfNotMoved(getPosition(), newParentPos, formatOptions); - skipPtNode(formatOptions); - } - if (!readAndFollowForwardLink()) break; - } while (jumpCount++ < DynamicBinaryDictIOUtils.MAX_JUMPS); - setPosition(originalPos); - } - - private void updateChildrenPos(final int nodePos, final int newChildrenPos, - final FormatOptions options) { - final int originalPos = getPosition(); - setPosition(nodePos); - final int flags = PtNodeReader.readPtNodeOptionFlags(mDictBuffer); - PtNodeReader.readParentAddress(mDictBuffer, options); - BinaryDictIOUtils.skipString(mDictBuffer, - (flags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS) != 0); - if ((flags & FormatSpec.FLAG_IS_TERMINAL) != 0) PtNodeReader.readTerminalId(mDictBuffer); - final int basePos = getPosition(); - BinaryDictIOUtils.writeSInt24ToBuffer(mDictBuffer, newChildrenPos - basePos); - setPosition(originalPos); - } - - private void updateTerminalPosition(final int terminalId, final int position) { - if (terminalId == PtNode.NOT_A_TERMINAL - || terminalId * FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE - >= mTerminalAddressTableBuffer.limit()) return; - mTerminalAddressTableBuffer.position(terminalId - * FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE); - BinaryDictEncoderUtils.writeUIntToDictBuffer(mTerminalAddressTableBuffer, position, - FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE); - } - - private void updateForwardLink(final int nodeArrayPos, final int newForwardLink, - final FormatOptions formatOptions) { - final int originalPos = getPosition(); - setPosition(nodeArrayPos); - int jumpCount = 0; - while (jumpCount++ < DynamicBinaryDictIOUtils.MAX_JUMPS) { - final int ptNodeCount = readPtNodeCount(); - for (int i = 0; i < ptNodeCount; ++i) { - skipPtNode(formatOptions); - } - final int forwardLinkPos = getPosition(); - if (!readAndFollowForwardLink()) { - setPosition(forwardLinkPos); - BinaryDictIOUtils.writeSInt24ToBuffer(mDictBuffer, newForwardLink - forwardLinkPos); - break; - } - } - setPosition(originalPos); - } - - private void markPtNodeAsMoved(final int nodePos, final int newNodePos, - final FormatOptions options) { - final int originalPos = getPosition(); - updateParentPosIfNotMoved(nodePos, newNodePos, options); - setPosition(nodePos); - final int currentFlags = PtNodeReader.readPtNodeOptionFlags(mDictBuffer); - setPosition(nodePos); - mDictBuffer.put((byte) (FormatSpec.FLAG_IS_MOVED - | (currentFlags & (~FormatSpec.MASK_MOVE_AND_DELETE_FLAG)))); - final int offset = newNodePos - nodePos; - BinaryDictIOUtils.writeSInt24ToBuffer(mDictBuffer, offset); - setPosition(originalPos); - } - - /** - * Writes a PtNode to an output stream from a Ver4PtNodeInfo. - * - * @param nodePos the position of the head of the PtNode. - * @param info the PtNode info to be written. - * @return the size written, in bytes. - */ - private int writePtNode(final int nodePos, final Ver4PtNodeInfo info) throws IOException { - int written = 0; - - // Write flags. - mDictStream.write((byte) (info.mFlags & 0xFF)); - written += FormatSpec.PTNODE_FLAGS_SIZE; - - // Write the parent position. - final int parentOffset = info.mParentPos == FormatSpec.NO_PARENT_ADDRESS ? - FormatSpec.NO_PARENT_ADDRESS : info.mParentPos - nodePos; - BinaryDictIOUtils.writeSInt24ToStream(mDictStream, parentOffset); - written += FormatSpec.PARENT_ADDRESS_SIZE; - - // Write a string. - if (((info.mFlags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS) != 0) - != (info.mEndIndexOfCharacters - info.mStartIndexOfCharacters > 1)) { - throw new RuntimeException("Inconsistent flags : hasMultipleChars = " - + ((info.mFlags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS) != 0) + ", length = " - + (info.mEndIndexOfCharacters - info.mStartIndexOfCharacters)); - } - written += CharEncoding.writeCodePoints(mDictStream, info.mCharacters, - info.mStartIndexOfCharacters, info.mEndIndexOfCharacters); - - // Write the terminal id. - if ((info.mFlags & FormatSpec.FLAG_IS_TERMINAL) != 0) { - BinaryDictEncoderUtils.writeUIntToStream(mDictStream, info.mTerminalId, - FormatSpec.PTNODE_TERMINAL_ID_SIZE); - written += FormatSpec.PTNODE_TERMINAL_ID_SIZE; - } - - // Write the children position. - final int childrenOffset = info.mChildrenPos == FormatSpec.NO_CHILDREN_ADDRESS - ? 0 : info.mChildrenPos - (nodePos + written); - BinaryDictIOUtils.writeSInt24ToStream(mDictStream, childrenOffset); - written += FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE; - - return written; - } - - /** - * Helper method to split and move PtNode. - * - * @param ptNodeArrayPos the position of PtNodeArray which contains the split and moved PtNode. - * @param splittedPtNodeToMovePos the position of the split and moved PtNode. - * @param newParent the parent PtNode after splitting. - * @param newChildren the children PtNodes after splitting. - * @param newParentStartPos where to write the new parent. - * @param formatOptions the format options. - */ - private void writeSplittedPtNodes(final int ptNodeArrayPos, final int splittedPtNodeToMovePos, - final Ver4PtNodeInfo newParent, final Ver4PtNodeInfo[] newChildren, - final int newParentStartPos, - final FormatOptions formatOptions) throws IOException { - updateTerminalPosition(newParent.mTerminalId, - newParentStartPos + 1 /* size of PtNodeCount */); - int written = writePtNodeArray(newParentStartPos, new Ver4PtNodeInfo[] { newParent }, - FormatSpec.NO_FORWARD_LINK_ADDRESS); - final int childrenStartPos = newParentStartPos + written; - writePtNodeArray(childrenStartPos, newChildren, FormatSpec.NO_FORWARD_LINK_ADDRESS); - int childrenNodePos = childrenStartPos + 1 /* size of PtNodeCount */; - for (final Ver4PtNodeInfo info : newChildren) { - updateTerminalPosition(info.mTerminalId, childrenNodePos); - childrenNodePos += computePtNodeSize(info.mCharacters, info.mStartIndexOfCharacters, - info.mEndIndexOfCharacters, - (info.mFlags & FormatSpec.FLAG_IS_TERMINAL) != 0); - } - - // Mark as moved. - markPtNodeAsMoved(splittedPtNodeToMovePos, newParentStartPos + 1 /* size of PtNodeCount */, - formatOptions); - updateForwardLink(ptNodeArrayPos, newParentStartPos, formatOptions); - } - - /** - * Writes a node array to the stream. - * - * @param nodeArrayPos the position of the head of the node array. - * @param infos an array of Ver4PtNodeInfo to be written. - * @return the written length in bytes. - */ - private int writePtNodeArray(final int nodeArrayPos, final Ver4PtNodeInfo[] infos, - final int forwardLink) throws IOException { - int written = BinaryDictIOUtils.writePtNodeCount(mDictStream, infos.length); - for (int i = 0; i < infos.length; ++i) { - written += writePtNode(nodeArrayPos + written, infos[i]); - } - BinaryDictIOUtils.writeSInt24ToStream(mDictStream, forwardLink); - written += FormatSpec.FORWARD_LINK_ADDRESS_SIZE; - return written; - } - - private int computePtNodeSize(final int[] codePoints, final int startIndex, final int endIndex, - final boolean isTerminal) { - return FormatSpec.PTNODE_FLAGS_SIZE + FormatSpec.PARENT_ADDRESS_SIZE - + CharEncoding.getCharArraySize(codePoints, startIndex, endIndex) - + (endIndex - startIndex > 1 ? FormatSpec.PTNODE_TERMINATOR_SIZE : 0) - + (isTerminal ? FormatSpec.PTNODE_TERMINAL_ID_SIZE : 0) - + FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE; - } - - private void writeNewSinglePtNodeWithAttributes(final int[] codePoints, - final boolean hasShortcuts, final int terminalId, final boolean hasBigrams, - final boolean isNotAWord, final boolean isBlackListEntry, final int parentPos, - final FormatOptions formatOptions) throws IOException { - final int newNodeArrayPos = mDictBuffer.limit(); - final int newNodeFlags = BinaryDictEncoderUtils.makePtNodeFlags(codePoints.length > 1, - terminalId != PtNode.NOT_A_TERMINAL, FormatSpec.FLAG_IS_NOT_MOVED, hasShortcuts, - hasBigrams, isNotAWord, isBlackListEntry, formatOptions); - final Ver4PtNodeInfo info = new Ver4PtNodeInfo(newNodeFlags, codePoints, terminalId, - FormatSpec.NO_CHILDREN_ADDRESS, parentPos, 0 /* nodeSize */); - writePtNodeArray(newNodeArrayPos, new Ver4PtNodeInfo[] { info }, - FormatSpec.NO_FORWARD_LINK_ADDRESS); - } - - private int setMultipleCharsInFlags(final int currentFlags, final boolean hasMultipleChars) { - final int flags; - if (hasMultipleChars) { - flags = currentFlags | FormatSpec.FLAG_HAS_MULTIPLE_CHARS; - } else { - flags = currentFlags & (~FormatSpec.FLAG_HAS_MULTIPLE_CHARS); - } - return flags; - } - - private int setIsNotAWordInFlags(final int currentFlags, final boolean isNotAWord) { - final int flags; - if (isNotAWord) { - flags = currentFlags | FormatSpec.FLAG_IS_NOT_A_WORD; - } else { - flags = currentFlags & (~FormatSpec.FLAG_IS_NOT_A_WORD); - } - return flags; - } - - private int setIsBlackListEntryInFlags(final int currentFlags, final boolean isBlackListEntry) { - final int flags; - if (isBlackListEntry) { - flags = currentFlags | FormatSpec.FLAG_IS_BLACKLISTED; - } else { - flags = currentFlags & (~FormatSpec.FLAG_IS_BLACKLISTED); - } - return flags; - } - - /** - * Splits a PtNode. - * - * abcd - ef - * - * -> inserting "abc" - * - * abc - d - ef - * - * @param nodeArrayToSplitPos the position of PtNodeArray which contains the PtNode to split. - * @param nodeToSplitPos the position of the PtNode to split. - * @param nodeToSplitInfo the information of the PtNode to split. - * @param indexToSplit the index where to split in the code points array. - * @param parentOfNodeToSplitPos the absolute position of a parent of the node to split. - * @param newTerminalId the terminal id of the inserted node (corresponds to "d"). - * @param hasShortcuts whether the inserted word should have shortcuts. - * @param hasBigrams whether the inserted word should have bigrams. - * @param isNotAWord whether the inserted word should be not a word. - * @param isBlackListEntry whether the inserted word should be a black list entry. - * @param formatOptions the format options. - */ - private void splitOnly(final int nodeArrayToSplitPos, final int nodeToSplitPos, - final Ver4PtNodeInfo nodeToSplitInfo, final int indexToSplit, - final int parentOfNodeToSplitPos, final int newTerminalId, final boolean hasShortcuts, - final boolean hasBigrams, final boolean isNotAWord, final boolean isBlackListEntry, - final FormatOptions formatOptions) throws IOException { - final int parentNodeArrayStartPos = mDictBuffer.limit(); - final int parentNodeStartPos = parentNodeArrayStartPos + 1 /* size of PtNodeCount */; - final int parentFlags = BinaryDictEncoderUtils.makePtNodeFlags(indexToSplit > 1, - true /* isTerminal */, FormatSpec.FLAG_IS_NOT_MOVED, hasShortcuts, hasBigrams, - isNotAWord, isBlackListEntry, formatOptions); - final Ver4PtNodeInfo parentInfo = new Ver4PtNodeInfo(parentFlags, - nodeToSplitInfo.mCharacters, newTerminalId, parentNodeStartPos - + computePtNodeSize(nodeToSplitInfo.mCharacters, 0, indexToSplit, true) - + FormatSpec.FORWARD_LINK_ADDRESS_SIZE, - parentOfNodeToSplitPos, 0 /* nodeSize */); - parentInfo.mStartIndexOfCharacters = 0; - parentInfo.mEndIndexOfCharacters = indexToSplit; - - // Write the child. - final int childrenFlags = setMultipleCharsInFlags(nodeToSplitInfo.mFlags, - nodeToSplitInfo.mCharacters.length - indexToSplit > 1); - final Ver4PtNodeInfo childrenInfo = new Ver4PtNodeInfo(childrenFlags, - nodeToSplitInfo.mCharacters, nodeToSplitInfo.mTerminalId, - nodeToSplitInfo.mChildrenPos, parentNodeStartPos, 0 /* nodeSize */); - childrenInfo.mStartIndexOfCharacters = indexToSplit; - childrenInfo.mEndIndexOfCharacters = nodeToSplitInfo.mCharacters.length; - if (nodeToSplitInfo.mChildrenPos != FormatSpec.NO_CHILDREN_ADDRESS) { - updateParentPositions(nodeToSplitInfo.mChildrenPos, - parentInfo.mChildrenPos + 1 /* size of PtNodeCount */, formatOptions); - } - - writeSplittedPtNodes(nodeArrayToSplitPos, nodeToSplitPos, parentInfo, - new Ver4PtNodeInfo[] { childrenInfo }, parentNodeArrayStartPos, formatOptions); - } - - /** - * Split and branch a PtNode. - * - * ab - cd - * - * -> inserting "ac" - * - * a - b - cd - * | - * - c - * - * @param nodeArrayToSplitPos the position of PtNodeArray which contains the PtNode to split. - * @param nodeToSplitPos the position of the PtNode to split. - * @param nodeToSplitInfo the information of the PtNode to split. - * @param indexToSplit the index where to split in the code points array. - * @param parentOfNodeToSplitPos the absolute position of parent of the node to split. - * @param newWordSuffixCodePoints the suffix of the newly inserted word (corresponds to "c"). - * @param startIndexOfNewWordSuffixCodePoints the start index in newWordSuffixCodePoints where - * the suffix starts. - * @param newTerminalId the terminal id of the inserted node (correspond to "c"). - * @param hasShortcuts whether the inserted word should have shortcuts. - * @param hasBigrams whether the inserted word should have bigrams. - * @param isNotAWord whether the inserted word should be not a word. - * @param isBlackListEntry whether the inserted word should be a black list entry. - * @param formatOptions the format options. - */ - private void splitAndBranch(final int nodeArrayToSplitPos, final int nodeToSplitPos, - final Ver4PtNodeInfo nodeToSplitInfo, final int indexToSplit, - final int parentOfNodeToSplitPos, final int[] newWordSuffixCodePoints, - final int startIndexOfNewWordSuffixCodePoints, - final int newTerminalId, - final boolean hasShortcuts, final boolean hasBigrams, final boolean isNotAWord, - final boolean isBlackListEntry, final FormatOptions formatOptions) throws IOException { - final int parentNodeArrayStartPos = mDictBuffer.limit(); - final int parentNodeStartPos = parentNodeArrayStartPos + 1 /* size of PtNodeCount */; - final int parentFlags = BinaryDictEncoderUtils.makePtNodeFlags( - indexToSplit > 1, - false /* isTerminal */, FormatSpec.FLAG_IS_NOT_MOVED, - false /* hasShortcut */, false /* hasBigrams */, - false /* isNotAWord */, false /* isBlackListEntry */, formatOptions); - final Ver4PtNodeInfo parentInfo = new Ver4PtNodeInfo(parentFlags, - nodeToSplitInfo.mCharacters, PtNode.NOT_A_TERMINAL, - parentNodeStartPos - + computePtNodeSize(nodeToSplitInfo.mCharacters, 0, indexToSplit, false) - + FormatSpec.FORWARD_LINK_ADDRESS_SIZE, - parentOfNodeToSplitPos, 0 /* nodeSize */); - parentInfo.mStartIndexOfCharacters = 0; - parentInfo.mEndIndexOfCharacters = indexToSplit; - - final int childrenNodeArrayStartPos = parentNodeStartPos - + computePtNodeSize(nodeToSplitInfo.mCharacters, 0, indexToSplit, false) - + FormatSpec.FORWARD_LINK_ADDRESS_SIZE; - final int firstChildrenFlags = BinaryDictEncoderUtils.makePtNodeFlags( - newWordSuffixCodePoints.length - startIndexOfNewWordSuffixCodePoints > 1, - true /* isTerminal */, FormatSpec.FLAG_IS_NOT_MOVED, hasShortcuts, hasBigrams, - isNotAWord, isBlackListEntry, formatOptions); - final Ver4PtNodeInfo firstChildrenInfo = new Ver4PtNodeInfo(firstChildrenFlags, - newWordSuffixCodePoints, newTerminalId, - FormatSpec.NO_CHILDREN_ADDRESS, parentNodeStartPos, - 0 /* nodeSize */); - firstChildrenInfo.mStartIndexOfCharacters = startIndexOfNewWordSuffixCodePoints; - firstChildrenInfo.mEndIndexOfCharacters = newWordSuffixCodePoints.length; - - final int secondChildrenStartPos = childrenNodeArrayStartPos + 1 /* size of ptNodeCount */ - + computePtNodeSize(newWordSuffixCodePoints, startIndexOfNewWordSuffixCodePoints, - newWordSuffixCodePoints.length, true /* isTerminal */); - final int secondChildrenFlags = setMultipleCharsInFlags(nodeToSplitInfo.mFlags, - nodeToSplitInfo.mCharacters.length - indexToSplit > 1); - final Ver4PtNodeInfo secondChildrenInfo = new Ver4PtNodeInfo(secondChildrenFlags, - nodeToSplitInfo.mCharacters, nodeToSplitInfo.mTerminalId, - nodeToSplitInfo.mChildrenPos, parentNodeStartPos, 0 /* nodeSize */); - secondChildrenInfo.mStartIndexOfCharacters = indexToSplit; - secondChildrenInfo.mEndIndexOfCharacters = nodeToSplitInfo.mCharacters.length; - if (nodeToSplitInfo.mChildrenPos != FormatSpec.NO_CHILDREN_ADDRESS) { - updateParentPositions(nodeToSplitInfo.mChildrenPos, secondChildrenStartPos, - formatOptions); - } - - writeSplittedPtNodes(nodeArrayToSplitPos, nodeToSplitPos, parentInfo, - new Ver4PtNodeInfo[] { firstChildrenInfo, secondChildrenInfo }, - parentNodeArrayStartPos, formatOptions); - } - - /** - * Inserts a word into the trie file and returns the position of inserted terminal node. - * If the insertion is failed, returns FormatSpec.NOT_VALID_WORD. - */ - @UsedForTesting - private int insertWordToTrie(final String word, final int newTerminalId, - final boolean isNotAWord, final boolean isBlackListEntry, final boolean hasBigrams, - final boolean hasShortcuts) throws IOException, UnsupportedFormatException { - setPosition(0); - final FileHeader header = readHeader(); - - final int[] codePoints = FusionDictionary.getCodePoints(word); - final int wordLen = codePoints.length; - - int wordPos = 0; - for (int depth = 0; depth < FormatSpec.MAX_WORD_LENGTH; /* nop */) { - final int nodeArrayPos = getPosition(); - final int ptNodeCount = readPtNodeCount(); - boolean goToChildren = false; - int parentPos = FormatSpec.NO_PARENT_ADDRESS; - for (int i = 0; i < ptNodeCount; ++i) { - final int nodePos = getPosition(); - final Ver4PtNodeInfo nodeInfo = readVer4PtNodeInfo(nodePos, header.mFormatOptions); - if (BinaryDictIOUtils.isMovedPtNode(nodeInfo.mFlags, header.mFormatOptions)) { - continue; - } - if (nodeInfo.mParentPos != FormatSpec.NO_PARENT_ADDRESS) { - parentPos = nodePos + nodeInfo.mParentPos; - } - - final boolean firstCharacterMatched = - codePoints[wordPos] == nodeInfo.mCharacters[0]; - boolean allCharactersMatched = true; - int firstDifferentCharacterIndex = -1; - for (int p = 0; p < nodeInfo.mCharacters.length; ++p) { - if (wordPos + p >= codePoints.length) break; - if (codePoints[wordPos + p] != nodeInfo.mCharacters[p]) { - if (firstDifferentCharacterIndex == -1) { - firstDifferentCharacterIndex = p; - } - allCharactersMatched = false; - } - } - - if (!firstCharacterMatched) { - // Go to the next sibling node. - continue; - } - - if (!allCharactersMatched) { - final int parentNodeArrayStartPos = mDictBuffer.limit(); - splitAndBranch(nodeArrayPos, nodePos, nodeInfo, firstDifferentCharacterIndex, - parentPos, codePoints, wordPos + firstDifferentCharacterIndex, - newTerminalId, hasShortcuts, hasBigrams, isNotAWord, - isBlackListEntry, header.mFormatOptions); - - return parentNodeArrayStartPos + computePtNodeSize(codePoints, wordPos, - wordPos + firstDifferentCharacterIndex, false) - + FormatSpec.FORWARD_LINK_ADDRESS_SIZE + 1 /* size of PtNodeCount */; - } - - if (wordLen - wordPos < nodeInfo.mCharacters.length) { - final int parentNodeArrayStartPos = mDictBuffer.limit(); - splitOnly(nodeArrayPos, nodePos, nodeInfo, wordLen - wordPos, parentPos, - newTerminalId, hasShortcuts, hasBigrams, isNotAWord, isBlackListEntry, - header.mFormatOptions); - - // Return the position of the inserted word. - return parentNodeArrayStartPos + 1 /* size of PtNodeCount */; - } - - wordPos += nodeInfo.mCharacters.length; - if (wordPos == wordLen) { - // This dictionary already contains the word. - Log.e(TAG, "Something went wrong. If the word is already contained, " - + " there is no need to insert new PtNode."); - return FormatSpec.NOT_VALID_WORD; - } - if (nodeInfo.mChildrenPos == FormatSpec.NO_CHILDREN_ADDRESS) { - // There are no children. - // We need to add a new node as a child of this node. - final int newNodeArrayPos = mDictBuffer.limit(); - final int[] newNodeCodePoints = Arrays.copyOfRange(codePoints, wordPos, - codePoints.length); - writeNewSinglePtNodeWithAttributes(newNodeCodePoints, hasShortcuts, - newTerminalId, hasBigrams, isNotAWord, isBlackListEntry, nodePos, - header.mFormatOptions); - updateChildrenPos(nodePos, newNodeArrayPos, header.mFormatOptions); - return newNodeArrayPos + 1 /* size of PtNodeCount */; - } else { - // Found the matched node. - // Go to the children of this node. - setPosition(nodeInfo.mChildrenPos); - goToChildren = true; - depth++; - break; - } - } - - if (goToChildren) continue; - if (!readAndFollowForwardLink()) { - // Add a new node that contains [wordPos, word.length()-1]. - // and update the forward link. - final int newNodeArrayPos = mDictBuffer.limit(); - final int[] newCodePoints = Arrays.copyOfRange(codePoints, wordPos, - codePoints.length); - writeNewSinglePtNodeWithAttributes(newCodePoints, hasShortcuts, newTerminalId, - hasBigrams, isNotAWord, isBlackListEntry, parentPos, header.mFormatOptions); - updateForwardLink(nodeArrayPos, newNodeArrayPos, header.mFormatOptions); - return newNodeArrayPos + 1 /* size of PtNodeCount */; - } - } - return FormatSpec.NOT_VALID_WORD; - } - - private void updateFrequency(final int terminalId, final int frequency) { - mFrequencyBuffer.position(terminalId * FormatSpec.FREQUENCY_AND_FLAGS_SIZE); - BinaryDictEncoderUtils.writeUIntToDictBuffer(mFrequencyBuffer, frequency, - FormatSpec.FREQUENCY_AND_FLAGS_SIZE); - } - - private void insertFrequency(final int frequency) throws IOException { - final OutputStream frequencyStream = new FileOutputStream(mFrequencyFile, - true /* append */); - BinaryDictEncoderUtils.writeUIntToStream(frequencyStream, frequency, - FormatSpec.FREQUENCY_AND_FLAGS_SIZE); - frequencyStream.close(); - } - - private void insertTerminalPosition(final int posOfTerminal) throws IOException, - UnsupportedFormatException { - final OutputStream terminalPosStream = new FileOutputStream( - getFile(FILETYPE_TERMINAL_ADDRESS_TABLE), true /* append */); - BinaryDictEncoderUtils.writeUIntToStream(terminalPosStream, posOfTerminal, - FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE); - terminalPosStream.close(); - } - - private void insertBigrams(final int terminalId, final int frequency, - final ArrayList<PendingAttribute> bigramAddresses) - throws IOException, UnsupportedFormatException { - openDictBuffer(); - final BigramContentUpdater updater = new BigramContentUpdater(mDictDirectory.getName(), - mDictDirectory, false); - - // Convert addresses to terminal ids. - final ArrayList<PendingAttribute> bigrams = CollectionUtils.newArrayList(); - mDictBuffer.position(0); - final FileHeader header = readHeader(); - for (PendingAttribute attr : bigramAddresses) { - mDictBuffer.position(attr.mAddress); - final Ver4PtNodeInfo info = readVer4PtNodeInfo(attr.mAddress, header.mFormatOptions); - if (info.mTerminalId == PtNode.NOT_A_TERMINAL) { - throw new RuntimeException("We can't have a bigram target that's not a terminal."); - } - bigrams.add(new PendingAttribute(frequency, info.mTerminalId)); - } - updater.insertBigramEntries(terminalId, frequency, bigrams); - close(); - } - - private void insertShortcuts(final int terminalId, final ArrayList<WeightedString> shortcuts) - throws IOException { - final ShortcutContentUpdater updater = new ShortcutContentUpdater(mDictDirectory.getName(), - mDictDirectory); - updater.insertShortcuts(terminalId, shortcuts); - } - - private void openBuffersAndStream() throws IOException, UnsupportedFormatException { - openDictBuffer(); - mDictStream = new FileOutputStream(getFile(FILETYPE_TRIE), true /* append */); - } - - private void close() throws IOException { - if (mDictStream != null) { - mDictStream.close(); - mDictStream = null; - } - mDictBuffer = null; - mFrequencyBuffer = null; - mTerminalAddressTableBuffer = null; - } - - private void updateAttributes(final int posOfWord, final int frequency, - final ArrayList<WeightedString> bigramStrings, - final ArrayList<WeightedString> shortcuts, final boolean isNotAWord, - final boolean isBlackListEntry) throws IOException, UnsupportedFormatException { - mDictBuffer.position(0); - final FileHeader header = readHeader(); - mDictBuffer.position(posOfWord); - final Ver4PtNodeInfo info = readVer4PtNodeInfo(posOfWord, header.mFormatOptions); - final int terminalId = info.mTerminalId; - - // Update the flags. - final int newFlags = setIsNotAWordInFlags( - setIsBlackListEntryInFlags(info.mFlags, isBlackListEntry), isNotAWord); - mDictBuffer.position(posOfWord); - mDictBuffer.put((byte) newFlags); - - updateFrequency(terminalId, frequency); - insertBigrams(terminalId, frequency, - DynamicBinaryDictIOUtils.resolveBigramPositions(this, bigramStrings)); - insertShortcuts(terminalId, shortcuts); - } - - @Override @UsedForTesting + @Override public void insertWord(final String word, final int frequency, final ArrayList<WeightedString> bigramStrings, final ArrayList<WeightedString> shortcuts, final boolean isNotAWord, final boolean isBlackListEntry) throws IOException, UnsupportedFormatException { - final int newTerminalId = getNewTerminalId(); - - openBuffersAndStream(); - final int posOfWord = getTerminalPosition(word); - if (posOfWord != FormatSpec.NOT_VALID_WORD) { - // The word is already contained in the dictionary. - updateAttributes(posOfWord, frequency, bigramStrings, shortcuts, isNotAWord, - isBlackListEntry); - close(); - return; - } - - // Insert new PtNode into trie. - final int posOfTerminal = insertWordToTrie(word, newTerminalId, isNotAWord, - isBlackListEntry, bigramStrings != null && !bigramStrings.isEmpty(), - shortcuts != null && !shortcuts.isEmpty()); - insertFrequency(frequency); - insertTerminalPosition(posOfTerminal); - close(); - - insertBigrams(newTerminalId, frequency, - DynamicBinaryDictIOUtils.resolveBigramPositions(this, bigramStrings)); - insertShortcuts(newTerminalId, shortcuts); + // TODO: Implement this method. } } diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java index 9b573b4b8..1de15a333 100644 --- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java +++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java @@ -17,16 +17,18 @@ package com.android.inputmethod.latin.personalization; import android.content.Context; +import android.content.SharedPreferences; import android.util.Log; import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.latin.BinaryDictionary.LanguageModelParam; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.ExpandableBinaryDictionary; +import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.makedict.DictDecoder; import com.android.inputmethod.latin.makedict.FormatSpec; -import com.android.inputmethod.latin.makedict.UnsupportedFormatException; +import com.android.inputmethod.latin.settings.Settings; +import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.UserHistoryDictIOUtils; import com.android.inputmethod.latin.utils.UserHistoryDictIOUtils.OnAddWordListener; @@ -34,9 +36,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; -import java.util.Locale; import java.util.Map; -import java.util.concurrent.TimeUnit; /** * This class is a base class of a dictionary that supports decaying for the personalized language @@ -45,7 +45,8 @@ import java.util.concurrent.TimeUnit; public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableBinaryDictionary { private static final String TAG = DecayingExpandableBinaryDictionaryBase.class.getSimpleName(); public static final boolean DBG_SAVE_RESTORE = false; - private static final boolean DBG_DUMP_ON_CLOSE = false; + private static final boolean DBG_STRESS_TEST = false; + private static final boolean PROFILE_SAVE_RESTORE = LatinImeLogger.sDBG; /** Any pair being typed or picked */ public static final int FREQUENCY_FOR_TYPED = 2; @@ -53,56 +54,52 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB public static final int FREQUENCY_FOR_WORDS_IN_DICTS = FREQUENCY_FOR_TYPED; public static final int FREQUENCY_FOR_WORDS_NOT_IN_DICTS = Dictionary.NOT_A_PROBABILITY; - public static final int REQUIRED_BINARY_DICTIONARY_VERSION = 4; - /** Locale for which this user history dictionary is storing words */ - private final Locale mLocale; + private final String mLocale; - private final String mDictName; + private final String mFileName; - /* package */ DecayingExpandableBinaryDictionaryBase(final Context context, - final Locale locale, final String dictionaryType, final String dictName) { - super(context, dictName, locale, dictionaryType, true); - mLocale = locale; - mDictName = dictName; - if (mLocale != null && mLocale.toString().length() > 1) { - reloadDictionaryIfRequired(); - } - } + private final SharedPreferences mPrefs; + + private final ArrayList<PersonalizationDictionaryUpdateSession> mSessions = + CollectionUtils.newArrayList(); + + // Should always be false except when we use this class for test + @UsedForTesting boolean mIsTest = false; - // Creates an instance that uses a given dictionary file for testing. - @UsedForTesting /* package */ DecayingExpandableBinaryDictionaryBase(final Context context, - final Locale locale, final String dictionaryType, final String dictName, - final File dictFile) { - super(context, dictName, locale, dictionaryType, true, dictFile); + final String locale, final SharedPreferences sp, final String dictionaryType, + final String fileName) { + super(context, fileName, dictionaryType, true); mLocale = locale; - mDictName = dictName; - if (mLocale != null && mLocale.toString().length() > 1) { + mFileName = fileName; + mPrefs = sp; + if (mLocale != null && mLocale.length() > 1) { + asyncLoadDictionaryToMemory(); reloadDictionaryIfRequired(); } } @Override public void close() { - if (DBG_DUMP_ON_CLOSE) { - dumpAllWordsForDebug(); + if (!ExpandableBinaryDictionary.ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { + closeBinaryDictionary(); } // Flush pending writes. - asyncFlushBinaryDictionary(); + // TODO: Remove after this class become to use a dynamic binary dictionary. + asyncFlashAllBinaryDictionary(); + Settings.writeLastUserHistoryWriteTime(mPrefs, mLocale); } @Override protected Map<String, String> getHeaderAttributeMap() { HashMap<String, String> attributeMap = new HashMap<String, String>(); - attributeMap.put(FormatSpec.FileHeader.USES_FORGETTING_CURVE_ATTRIBUTE, + attributeMap.put(FormatSpec.FileHeader.SUPPORTS_DYNAMIC_UPDATE_ATTRIBUTE, FormatSpec.FileHeader.ATTRIBUTE_VALUE_TRUE); - attributeMap.put(FormatSpec.FileHeader.HAS_HISTORICAL_INFO_ATTRIBUTE, + attributeMap.put(FormatSpec.FileHeader.USES_FORGETTING_CURVE_ATTRIBUTE, FormatSpec.FileHeader.ATTRIBUTE_VALUE_TRUE); - attributeMap.put(FormatSpec.FileHeader.DICTIONARY_ID_ATTRIBUTE, mDictName); - attributeMap.put(FormatSpec.FileHeader.DICTIONARY_LOCALE_ATTRIBUTE, mLocale.toString()); - attributeMap.put(FormatSpec.FileHeader.DICTIONARY_VERSION_ATTRIBUTE, - String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()))); + attributeMap.put(FormatSpec.FileHeader.DICTIONARY_ID_ATTRIBUTE, mFileName); + attributeMap.put(FormatSpec.FileHeader.DICTIONARY_LOCALE_ATTRIBUTE, mLocale); return attributeMap; } @@ -116,25 +113,6 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB return false; } - @Override - protected boolean matchesExpectedBinaryDictFormatVersionForThisType(final int formatVersion) { - // This class is using format 4 because it's used by all version 4 dictionaries. - // TODO: remove this when all dynamically generated dicts use version 4. - return formatVersion == REQUIRED_BINARY_DICTIONARY_VERSION; - } - - public void addMultipleDictionaryEntriesToDictionary( - final ArrayList<LanguageModelParam> languageModelParams, - final ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback callback) { - if (languageModelParams == null || languageModelParams.isEmpty()) { - if (callback != null) { - callback.onFinished(); - } - return; - } - addMultipleDictionaryEntriesDynamically(languageModelParams, callback); - } - /** * Pair will be added to the decaying dictionary. * @@ -143,63 +121,70 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB * context, as in beginning of a sentence for example. * The second word may not be null (a NullPointerException would be thrown). */ - public void addToDictionary(final String word0, final String word1, final boolean isValid, - final int timestamp) { + public void addToDictionary(final String word0, final String word1, final boolean isValid) { if (word1.length() >= Constants.DICTIONARY_MAX_WORD_LENGTH || (word0 != null && word0.length() >= Constants.DICTIONARY_MAX_WORD_LENGTH)) { return; } - final int frequency = isValid ? - FREQUENCY_FOR_WORDS_IN_DICTS : FREQUENCY_FOR_WORDS_NOT_IN_DICTS; - addWordDynamically(word1, frequency, null /* shortcutTarget */, 0 /* shortcutFreq */, - false /* isNotAWord */, false /* isBlacklisted */, timestamp); + final int frequency = ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE ? + (isValid ? FREQUENCY_FOR_WORDS_IN_DICTS : FREQUENCY_FOR_WORDS_NOT_IN_DICTS) : + FREQUENCY_FOR_TYPED; + addWordDynamically(word1, null /* shortcutTarget */, frequency, 0 /* shortcutFreq */, + false /* isNotAWord */); // Do not insert a word as a bigram of itself if (word1.equals(word0)) { return; } if (null != word0) { - addBigramDynamically(word0, word1, frequency, timestamp); + addBigramDynamically(word0, word1, frequency, isValid); } } - @Override - protected void loadDictionaryAsync() { - // Never loaded to memory in Java side. + public void cancelAddingUserHistory(final String word0, final String word1) { + removeBigramDynamically(word0, word1); } - @UsedForTesting - public void dumpAllWordsForDebug() { - runAfterGcForDebug(new Runnable() { - @Override - public void run() { - dumpAllWordsForDebugLocked(); + @Override + protected void loadDictionaryAsync() { + final int[] profTotalCount = { 0 }; + final String locale = getLocale(); + if (DBG_STRESS_TEST) { + try { + Log.w(TAG, "Start stress in loading: " + locale); + Thread.sleep(15000); + Log.w(TAG, "End stress in loading"); + } catch (InterruptedException e) { } - }); - } - - private void dumpAllWordsForDebugLocked() { - Log.d(TAG, "dumpAllWordsForDebug started."); + } + final long last = Settings.readLastUserHistoryWriteTime(mPrefs, locale); + final long now = System.currentTimeMillis(); + final ExpandableBinaryDictionary dictionary = this; final OnAddWordListener listener = new OnAddWordListener() { @Override public void setUnigram(final String word, final String shortcutTarget, final int frequency, final int shortcutFreq) { - Log.d(TAG, "load unigram: " + word + "," + frequency); + if (DBG_SAVE_RESTORE) { + Log.d(TAG, "load unigram: " + word + "," + frequency); + } + addWord(word, shortcutTarget, frequency, shortcutFreq, false /* isNotAWord */); + ++profTotalCount[0]; } @Override public void setBigram(final String word0, final String word1, final int frequency) { if (word0.length() < Constants.DICTIONARY_MAX_WORD_LENGTH && word1.length() < Constants.DICTIONARY_MAX_WORD_LENGTH) { - Log.d(TAG, "load bigram: " + word0 + "," + word1 + "," + frequency); - } else { - Log.d(TAG, "Skip inserting a too long bigram: " + word0 + "," + word1 + "," - + frequency); + if (DBG_SAVE_RESTORE) { + Log.d(TAG, "load bigram: " + word0 + "," + word1 + "," + frequency); + } + ++profTotalCount[0]; + addBigram(word0, word1, frequency, last); } } }; // Load the dictionary from binary file - final File dictFile = new File(mContext.getFilesDir(), mDictName); + final File dictFile = new File(mContext.getFilesDir(), mFileName); final DictDecoder dictDecoder = FormatSpec.getDictDecoder(dictFile, DictDecoder.USE_BYTEARRAY); if (dictDecoder == null) { @@ -213,17 +198,35 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB UserHistoryDictIOUtils.readDictionaryBinary(dictDecoder, listener); } catch (IOException e) { Log.d(TAG, "IOException on opening a bytebuffer", e); - } catch (UnsupportedFormatException e) { - Log.d(TAG, "Unsupported format, can't read the dictionary", e); + } finally { + if (PROFILE_SAVE_RESTORE) { + final long diff = System.currentTimeMillis() - now; + Log.d(TAG, "PROF: Load UserHistoryDictionary: " + + locale + ", " + diff + "ms. load " + profTotalCount[0] + "entries."); + } } } + protected String getLocale() { + return mLocale; + } + + public void registerUpdateSession(PersonalizationDictionaryUpdateSession session) { + session.setPredictionDictionary(this); + mSessions.add(session); + session.onDictionaryReady(); + } + + public void unRegisterUpdateSession(PersonalizationDictionaryUpdateSession session) { + mSessions.remove(session); + } + @UsedForTesting public void clearAndFlushDictionary() { // Clear the node structure on memory clear(); // Then flush the cleared state of the dictionary on disk. - asyncFlushBinaryDictionary(); + asyncFlashAllBinaryDictionary(); } /* package */ void decayIfNeeded() { diff --git a/java/src/com/android/inputmethod/latin/personalization/DynamicPersonalizationDictionaryWriter.java b/java/src/com/android/inputmethod/latin/personalization/DynamicPersonalizationDictionaryWriter.java new file mode 100644 index 000000000..6f152bb91 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/personalization/DynamicPersonalizationDictionaryWriter.java @@ -0,0 +1,190 @@ +/* + * 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 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.personalization; + +import android.content.Context; + +import com.android.inputmethod.annotations.UsedForTesting; +import com.android.inputmethod.compat.ActivityManagerCompatUtils; +import com.android.inputmethod.keyboard.ProximityInfo; +import com.android.inputmethod.latin.AbstractDictionaryWriter; +import com.android.inputmethod.latin.ExpandableDictionary; +import com.android.inputmethod.latin.WordComposer; +import com.android.inputmethod.latin.ExpandableDictionary.NextWord; +import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.makedict.DictEncoder; +import com.android.inputmethod.latin.makedict.FormatSpec; +import com.android.inputmethod.latin.makedict.UnsupportedFormatException; +import com.android.inputmethod.latin.utils.UserHistoryDictIOUtils; +import com.android.inputmethod.latin.utils.UserHistoryDictIOUtils.BigramDictionaryInterface; +import com.android.inputmethod.latin.utils.UserHistoryForgettingCurveUtils; +import com.android.inputmethod.latin.utils.UserHistoryForgettingCurveUtils.ForgettingCurveParams; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Map; + +// Currently this class is used to implement dynamic prodiction dictionary. +// TODO: Move to native code. +public class DynamicPersonalizationDictionaryWriter extends AbstractDictionaryWriter { + private static final String TAG = DynamicPersonalizationDictionaryWriter.class.getSimpleName(); + /** Maximum number of pairs. Pruning will start when databases goes above this number. */ + public static final int DEFAULT_MAX_HISTORY_BIGRAMS = 10000; + public static final int LOW_MEMORY_MAX_HISTORY_BIGRAMS = 2000; + + /** Any pair being typed or picked */ + private static final int FREQUENCY_FOR_TYPED = 2; + + private static final int BINARY_DICT_VERSION = 3; + private static final FormatSpec.FormatOptions FORMAT_OPTIONS = + new FormatSpec.FormatOptions(BINARY_DICT_VERSION, true /* supportsDynamicUpdate */); + + private final UserHistoryDictionaryBigramList mBigramList = + new UserHistoryDictionaryBigramList(); + private final ExpandableDictionary mExpandableDictionary; + private final int mMaxHistoryBigrams; + + public DynamicPersonalizationDictionaryWriter(final Context context, final String dictType) { + super(context, dictType); + mExpandableDictionary = new ExpandableDictionary(dictType); + final boolean isLowRamDevice = ActivityManagerCompatUtils.isLowRamDevice(context); + mMaxHistoryBigrams = isLowRamDevice ? + LOW_MEMORY_MAX_HISTORY_BIGRAMS : DEFAULT_MAX_HISTORY_BIGRAMS; + } + + @Override + public void clear() { + mBigramList.evictAll(); + mExpandableDictionary.clearDictionary(); + } + + /** + * Adds a word unigram to the fusion dictionary. Call updateBinaryDictionary when all changes + * are done to update the binary dictionary. + * @param word The word to add. + * @param shortcutTarget A shortcut target for this word, or null if none. + * @param frequency The frequency for this unigram. + * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist). Ignored + * if shortcutTarget is null. + * @param isNotAWord true if this is not a word, i.e. shortcut only. + */ + @Override + public void addUnigramWord(final String word, final String shortcutTarget, final int frequency, + final int shortcutFreq, final boolean isNotAWord) { + if (mBigramList.size() > mMaxHistoryBigrams * 2) { + // Too many entries: just stop adding new vocabulary and wait next refresh. + return; + } + mExpandableDictionary.addWord(word, shortcutTarget, frequency, shortcutFreq); + mBigramList.addBigram(null, word, (byte)frequency); + } + + @Override + public void addBigramWords(final String word0, final String word1, final int frequency, + final boolean isValid, final long lastModifiedTime) { + if (mBigramList.size() > mMaxHistoryBigrams * 2) { + // Too many entries: just stop adding new vocabulary and wait next refresh. + return; + } + if (lastModifiedTime > 0) { + mExpandableDictionary.setBigramAndGetFrequency(word0, word1, + new ForgettingCurveParams(frequency, System.currentTimeMillis(), + lastModifiedTime)); + mBigramList.addBigram(word0, word1, (byte)frequency); + } else { + mExpandableDictionary.setBigramAndGetFrequency(word0, word1, + new ForgettingCurveParams(isValid)); + mBigramList.addBigram(word0, word1, (byte)frequency); + } + } + + @Override + public void removeBigramWords(final String word0, final String word1) { + if (mBigramList.removeBigram(word0, word1)) { + mExpandableDictionary.removeBigram(word0, word1); + } + } + + @Override + protected void writeDictionary(final DictEncoder dictEncoder, + final Map<String, String> attributeMap) throws IOException, UnsupportedFormatException { + UserHistoryDictIOUtils.writeDictionary(dictEncoder, + new FrequencyProvider(mBigramList, mExpandableDictionary, mMaxHistoryBigrams), + mBigramList, FORMAT_OPTIONS); + } + + private static class FrequencyProvider implements BigramDictionaryInterface { + private final UserHistoryDictionaryBigramList mBigramList; + private final ExpandableDictionary mExpandableDictionary; + private final int mMaxHistoryBigrams; + + public FrequencyProvider(final UserHistoryDictionaryBigramList bigramList, + final ExpandableDictionary expandableDictionary, final int maxHistoryBigrams) { + mBigramList = bigramList; + mExpandableDictionary = expandableDictionary; + mMaxHistoryBigrams = maxHistoryBigrams; + } + + @Override + public int getFrequency(final String word0, final String word1) { + final int freq; + if (word0 == null) { // unigram + freq = FREQUENCY_FOR_TYPED; + } else { // bigram + final NextWord nw = mExpandableDictionary.getBigramWord(word0, word1); + if (nw != null) { + final ForgettingCurveParams forgettingCurveParams = nw.getFcParams(); + final byte prevFc = mBigramList.getBigrams(word0).get(word1); + final byte fc = forgettingCurveParams.getFc(); + final boolean isValid = forgettingCurveParams.isValid(); + if (prevFc > 0 && prevFc == fc) { + freq = fc & 0xFF; + } else if (UserHistoryForgettingCurveUtils. + needsToSave(fc, isValid, mBigramList.size() <= mMaxHistoryBigrams)) { + freq = fc & 0xFF; + } else { + // Delete this entry + freq = -1; + } + } else { + // Delete this entry + freq = -1; + } + } + return freq; + } + } + + @Override + public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, + final String prevWord, final ProximityInfo proximityInfo, + boolean blockOffensiveWords, final int[] additionalFeaturesOptions) { + return mExpandableDictionary.getSuggestions(composer, prevWord, proximityInfo, + blockOffensiveWords, additionalFeaturesOptions); + } + + @Override + public boolean isValidWord(final String word) { + return mExpandableDictionary.isValidWord(word); + } + + @UsedForTesting + public boolean isInBigramListForTests(final String word) { + // TODO: Use native method to determine whether the word is in dictionary or not + return mBigramList.containsKey(word) || mBigramList.getBigrams(null).containsKey(word); + } +} diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java index 596562f1d..f257165cb 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java @@ -16,37 +16,53 @@ package com.android.inputmethod.latin.personalization; -import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.Dictionary; +import com.android.inputmethod.latin.ExpandableBinaryDictionary; import com.android.inputmethod.latin.utils.CollectionUtils; -import java.io.File; -import java.util.ArrayList; -import java.util.Locale; - import android.content.Context; +import android.content.SharedPreferences; -public class PersonalizationDictionary extends DecayingExpandableBinaryDictionaryBase { - private static final String NAME = PersonalizationDictionary.class.getSimpleName(); +import java.util.ArrayList; +/** + * This class is a dictionary for the personalized language model that uses binary dictionary. + */ +public class PersonalizationDictionary extends ExpandableBinaryDictionary { + private static final String NAME = "personalization"; private final ArrayList<PersonalizationDictionaryUpdateSession> mSessions = CollectionUtils.newArrayList(); - /* package */ PersonalizationDictionary(final Context context, final Locale locale) { - super(context, locale, Dictionary.TYPE_PERSONALIZATION, - getDictNameWithLocale(NAME, locale)); + /** Locale for which this user history dictionary is storing words */ + private final String mLocale; + + public PersonalizationDictionary(final Context context, final String locale, + final SharedPreferences prefs) { + // TODO: Make isUpdatable true. + super(context, getFilenameWithLocale(NAME, locale), Dictionary.TYPE_PERSONALIZATION, + false /* isUpdatable */); + mLocale = locale; + // TODO: Restore last updated time + loadDictionary(); + } + + @Override + protected void loadDictionaryAsync() { + // TODO: Implement + } + + @Override + protected boolean hasContentChanged() { + return false; } - // Creates an instance that uses a given dictionary file for testing. - @UsedForTesting - public PersonalizationDictionary(final Context context, final Locale locale, - final File dictFile) { - super(context, locale, Dictionary.TYPE_PERSONALIZATION, getDictNameWithLocale(NAME, locale), - dictFile); + @Override + protected boolean needsToReloadBeforeWriting() { + return false; } public void registerUpdateSession(PersonalizationDictionaryUpdateSession session) { - session.setPredictionDictionary(this); + session.setDictionary(this); mSessions.add(session); session.onDictionaryReady(); } diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionarySessionRegister.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionarySessionRegister.java index 542bda621..c1833ff14 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionarySessionRegister.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionarySessionRegister.java @@ -20,18 +20,18 @@ import android.content.Context; import android.content.res.Configuration; public class PersonalizationDictionarySessionRegister { - public static void init(final Context context) { + public static void init(Context context) { } public static void onConfigurationChanged(final Context context, final Configuration conf) { } - public static void onUpdateData(final Context context, final String type) { + public static void onUpdateData(Context context, String type) { } - public static void onRemoveData(final Context context, final String type) { + public static void onRemoveData(Context context, String type) { } - public static void onDestroy(final Context context) { + public static void onDestroy(Context context) { } } diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java index 61354762b..a86f6e584 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java @@ -18,37 +18,61 @@ package com.android.inputmethod.latin.personalization; import android.content.Context; -import com.android.inputmethod.latin.BinaryDictionary.LanguageModelParam; -import com.android.inputmethod.latin.ExpandableBinaryDictionary; - import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Locale; /** * This class is a session where a data provider can communicate with a personalization * dictionary. */ public abstract class PersonalizationDictionaryUpdateSession { - public WeakReference<PersonalizationDictionary> mDictionary; - public final Locale mSystemLocale; + /** + * This class is a parameter for a new unigram or bigram word which will be added + * to the personalization dictionary. + */ + public static class PersonalizationLanguageModelParam { + public final String mWord0; + public final String mWord1; + public final boolean mIsValid; + public final int mFrequency; + public PersonalizationLanguageModelParam(String word0, String word1, boolean isValid, + int frequency) { + mWord0 = word0; + mWord1 = word1; + mIsValid = isValid; + mFrequency = frequency; + } + } - public PersonalizationDictionaryUpdateSession(final Locale locale) { + // TODO: Use a dynamic binary dictionary instead + public WeakReference<PersonalizationDictionary> mDictionary; + public WeakReference<DecayingExpandableBinaryDictionaryBase> mPredictionDictionary; + public final String mSystemLocale; + public PersonalizationDictionaryUpdateSession(String locale) { mSystemLocale = locale; } public abstract void onDictionaryReady(); - public abstract void onDictionaryClosed(final Context context); + public abstract void onDictionaryClosed(Context context); - public void setPredictionDictionary(final PersonalizationDictionary dictionary) { + public void setDictionary(PersonalizationDictionary dictionary) { mDictionary = new WeakReference<PersonalizationDictionary>(dictionary); } + public void setPredictionDictionary(DecayingExpandableBinaryDictionaryBase dictionary) { + mPredictionDictionary = + new WeakReference<DecayingExpandableBinaryDictionaryBase>(dictionary); + } + protected PersonalizationDictionary getDictionary() { return mDictionary == null ? null : mDictionary.get(); } + protected DecayingExpandableBinaryDictionaryBase getPredictionDictionary() { + return mPredictionDictionary == null ? null : mPredictionDictionary.get(); + } + private void unsetDictionary() { final PersonalizationDictionary dictionary = getDictionary(); if (dictionary == null) { @@ -57,30 +81,48 @@ public abstract class PersonalizationDictionaryUpdateSession { dictionary.unRegisterUpdateSession(this); } - public void clearAndFlushDictionary(final Context context) { - final PersonalizationDictionary dictionary = getDictionary(); + private void unsetPredictionDictionary() { + final DecayingExpandableBinaryDictionaryBase dictionary = getPredictionDictionary(); + if (dictionary == null) { + return; + } + dictionary.unRegisterUpdateSession(this); + } + + public void clearAndFlushPredictionDictionary(Context context) { + final DecayingExpandableBinaryDictionaryBase dictionary = getPredictionDictionary(); if (dictionary == null) { return; } dictionary.clearAndFlushDictionary(); } - public void closeSession(final Context context) { + public void closeSession(Context context) { unsetDictionary(); + unsetPredictionDictionary(); onDictionaryClosed(context); } - // TODO: Support multi locale. - public void addMultipleDictionaryEntriesToDictionary( - final ArrayList<LanguageModelParam> languageModelParams, - final ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback callback) { - final PersonalizationDictionary dictionary = getDictionary(); + // TODO: Support multi locale to add bigram + public void addBigramToPersonalizationDictionary(String word0, String word1, boolean isValid, + int frequency) { + final DecayingExpandableBinaryDictionaryBase dictionary = getPredictionDictionary(); if (dictionary == null) { - if (callback != null) { - callback.onFinished(); - } return; } - dictionary.addMultipleDictionaryEntriesToDictionary(languageModelParams, callback); + dictionary.addToDictionary(word0, word1, isValid); + } + + // Bulk import + // TODO: Support multi locale to add bigram + public void addBigramsToPersonalizationDictionary( + final ArrayList<PersonalizationLanguageModelParam> lmParams) { + final DecayingExpandableBinaryDictionaryBase dictionary = getPredictionDictionary(); + if (dictionary == null) { + return; + } + for (final PersonalizationLanguageModelParam lmParam : lmParams) { + dictionary.addToDictionary(lmParam.mWord0, lmParam.mWord1, lmParam.mIsValid); + } } } diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java index d55cae132..221ddeeba 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java @@ -19,10 +19,11 @@ package com.android.inputmethod.latin.personalization; import com.android.inputmethod.latin.utils.CollectionUtils; import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; import android.util.Log; import java.lang.ref.SoftReference; -import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; public class PersonalizationHelper { @@ -30,16 +31,21 @@ public class PersonalizationHelper { private static final boolean DEBUG = false; private static final ConcurrentHashMap<String, SoftReference<UserHistoryDictionary>> sLangUserHistoryDictCache = CollectionUtils.newConcurrentHashMap(); + private static final ConcurrentHashMap<String, SoftReference<PersonalizationDictionary>> sLangPersonalizationDictCache = CollectionUtils.newConcurrentHashMap(); + private static final ConcurrentHashMap<String, + SoftReference<PersonalizationPredictionDictionary>> + sLangPersonalizationPredictionDictCache = + CollectionUtils.newConcurrentHashMap(); + public static UserHistoryDictionary getUserHistoryDictionary( - final Context context, final Locale locale) { - final String localeStr = locale.toString(); + final Context context, final String locale, final SharedPreferences sp) { synchronized (sLangUserHistoryDictCache) { - if (sLangUserHistoryDictCache.containsKey(localeStr)) { + if (sLangUserHistoryDictCache.containsKey(locale)) { final SoftReference<UserHistoryDictionary> ref = - sLangUserHistoryDictCache.get(localeStr); + sLangUserHistoryDictCache.get(locale); final UserHistoryDictionary dict = ref == null ? null : ref.get(); if (dict != null) { if (DEBUG) { @@ -49,9 +55,8 @@ public class PersonalizationHelper { return dict; } } - final UserHistoryDictionary dict = new UserHistoryDictionary(context, locale); - sLangUserHistoryDictCache.put(localeStr, - new SoftReference<UserHistoryDictionary>(dict)); + final UserHistoryDictionary dict = new UserHistoryDictionary(context, locale, sp); + sLangUserHistoryDictCache.put(locale, new SoftReference<UserHistoryDictionary>(dict)); return dict; } } @@ -69,30 +74,57 @@ public class PersonalizationHelper { } public static void registerPersonalizationDictionaryUpdateSession(final Context context, - final PersonalizationDictionaryUpdateSession session, final Locale locale) { - final PersonalizationDictionary personalizationDictionary = - getPersonalizationDictionary(context, locale); - personalizationDictionary.registerUpdateSession(session); + final PersonalizationDictionaryUpdateSession session, String locale) { + final PersonalizationPredictionDictionary predictionDictionary = + getPersonalizationPredictionDictionary(context, locale, + PreferenceManager.getDefaultSharedPreferences(context)); + predictionDictionary.registerUpdateSession(session); + final PersonalizationDictionary dictionary = + getPersonalizationDictionary(context, locale, + PreferenceManager.getDefaultSharedPreferences(context)); + dictionary.registerUpdateSession(session); } public static PersonalizationDictionary getPersonalizationDictionary( - final Context context, final Locale locale) { - final String localeStr = locale.toString(); + final Context context, final String locale, final SharedPreferences sp) { synchronized (sLangPersonalizationDictCache) { - if (sLangPersonalizationDictCache.containsKey(localeStr)) { + if (sLangPersonalizationDictCache.containsKey(locale)) { final SoftReference<PersonalizationDictionary> ref = - sLangPersonalizationDictCache.get(localeStr); + sLangPersonalizationDictCache.get(locale); final PersonalizationDictionary dict = ref == null ? null : ref.get(); if (dict != null) { if (DEBUG) { - Log.w(TAG, "Use cached PersonalizationDictionary for " + locale); + Log.w(TAG, "Use cached PersonalizationDictCache for " + locale); } return dict; } } - final PersonalizationDictionary dict = new PersonalizationDictionary(context, locale); + final PersonalizationDictionary dict = + new PersonalizationDictionary(context, locale, sp); sLangPersonalizationDictCache.put( - localeStr, new SoftReference<PersonalizationDictionary>(dict)); + locale, new SoftReference<PersonalizationDictionary>(dict)); + return dict; + } + } + + public static PersonalizationPredictionDictionary getPersonalizationPredictionDictionary( + final Context context, final String locale, final SharedPreferences sp) { + synchronized (sLangPersonalizationPredictionDictCache) { + if (sLangPersonalizationPredictionDictCache.containsKey(locale)) { + final SoftReference<PersonalizationPredictionDictionary> ref = + sLangPersonalizationPredictionDictCache.get(locale); + final PersonalizationPredictionDictionary dict = ref == null ? null : ref.get(); + if (dict != null) { + if (DEBUG) { + Log.w(TAG, "Use cached PersonalizationPredictionDictionary for " + locale); + } + return dict; + } + } + final PersonalizationPredictionDictionary dict = + new PersonalizationPredictionDictionary(context, locale, sp); + sLangPersonalizationPredictionDictCache.put( + locale, new SoftReference<PersonalizationPredictionDictionary>(dict)); return dict; } } diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationPredictionDictionary.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationPredictionDictionary.java new file mode 100644 index 000000000..432954453 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationPredictionDictionary.java @@ -0,0 +1,37 @@ +/* + * 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 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.personalization; + +import com.android.inputmethod.latin.Dictionary; +import com.android.inputmethod.latin.ExpandableBinaryDictionary; + +import android.content.Context; +import android.content.SharedPreferences; + +public class PersonalizationPredictionDictionary extends DecayingExpandableBinaryDictionaryBase { + private static final String NAME = PersonalizationPredictionDictionary.class.getSimpleName(); + + /* package */ PersonalizationPredictionDictionary(final Context context, final String locale, + final SharedPreferences sp) { + super(context, locale, sp, Dictionary.TYPE_PERSONALIZATION_PREDICTION_IN_JAVA, + getDictionaryFileName(locale)); + } + + private static String getDictionaryFileName(final String locale) { + return NAME + "." + locale + ExpandableBinaryDictionary.DICT_FILE_EXTENSION; + } +} diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java index 868f21cbc..a60226d7e 100644 --- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java @@ -16,13 +16,11 @@ package com.android.inputmethod.latin.personalization; -import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.Dictionary; - -import java.io.File; -import java.util.Locale; +import com.android.inputmethod.latin.ExpandableBinaryDictionary; import android.content.Context; +import android.content.SharedPreferences; /** * Locally gathers stats about the words user types and various other signals like auto-correction @@ -31,19 +29,12 @@ import android.content.Context; public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase { /* package for tests */ static final String NAME = UserHistoryDictionary.class.getSimpleName(); - /* package */ UserHistoryDictionary(final Context context, final Locale locale) { - super(context, locale, Dictionary.TYPE_USER_HISTORY, getDictNameWithLocale(NAME, locale)); - } - - // Creates an instance that uses a given dictionary file for testing. - @UsedForTesting - public UserHistoryDictionary(final Context context, final Locale locale, - final File dictFile) { - super(context, locale, Dictionary.TYPE_USER_HISTORY, getDictNameWithLocale(NAME, locale), - dictFile); + /* package */ UserHistoryDictionary(final Context context, final String locale, + final SharedPreferences sp) { + super(context, locale, sp, Dictionary.TYPE_USER_HISTORY, getDictionaryFileName(locale)); } - public void cancelAddingUserHistory(final String word0, final String word1) { - removeBigramDynamically(word0, word1); + private static String getDictionaryFileName(final String locale) { + return NAME + "." + locale + ExpandableBinaryDictionary.DICT_FILE_EXTENSION; } } diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java index d060485bd..da1fb73fe 100644 --- a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java +++ b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java @@ -112,7 +112,8 @@ public final class DebugSettings extends PreferenceFragment updateDebugMode(); mServiceNeedsRestart = true; } - } else if (key.equals(PREF_FORCE_NON_DISTINCT_MULTITOUCH)) { + } else if (key.equals(PREF_FORCE_NON_DISTINCT_MULTITOUCH) + || key.equals(PREF_USE_ONLY_PERSONALIZATION_DICTIONARY_FOR_DEBUG)) { mServiceNeedsRestart = true; } } diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java index 714c3a97a..df2c6907f 100644 --- a/java/src/com/android/inputmethod/latin/settings/Settings.java +++ b/java/src/com/android/inputmethod/latin/settings/Settings.java @@ -27,10 +27,12 @@ import com.android.inputmethod.latin.AudioAndHapticFeedbackManager; import com.android.inputmethod.latin.InputAttributes; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils; +import com.android.inputmethod.latin.utils.LocaleUtils; import com.android.inputmethod.latin.utils.ResourceUtils; import com.android.inputmethod.latin.utils.RunInLocale; import com.android.inputmethod.latin.utils.StringUtils; +import java.util.HashMap; import java.util.Locale; import java.util.concurrent.locks.ReentrantLock; @@ -51,6 +53,8 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold"; public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting"; public static final String PREF_MISC_SETTINGS = "misc_settings"; + public static final String PREF_LAST_USER_DICTIONARY_WRITE_TIME = + "last_user_dictionary_write_time"; public static final String PREF_ADVANCED_SETTINGS = "pref_advanced_settings"; public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict"; public static final String PREF_KEY_USE_DOUBLE_SPACE_PERIOD = @@ -225,15 +229,16 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang res.getBoolean(R.bool.config_default_phrase_gesture_enabled)); } - public static boolean readFromBuildConfigIfToShowKeyPreviewPopupOption(final Resources res) { - return res.getBoolean(R.bool.config_enable_show_key_preview_popup_option); + public static boolean readFromBuildConfigIfToShowKeyPreviewPopupSettingsOption( + final Resources res) { + return res.getBoolean(R.bool.config_enable_show_option_of_key_preview_popup); } public static boolean readKeyPreviewPopupEnabled(final SharedPreferences prefs, final Resources res) { final boolean defaultKeyPreviewPopup = res.getBoolean( R.bool.config_default_key_preview_popup); - if (!readFromBuildConfigIfToShowKeyPreviewPopupOption(res)) { + if (!readFromBuildConfigIfToShowKeyPreviewPopupSettingsOption(res)) { return defaultKeyPreviewPopup; } return prefs.getBoolean(PREF_POPUP_ON, defaultKeyPreviewPopup); @@ -328,6 +333,25 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang return prefs.getBoolean(DebugSettings.PREF_USABILITY_STUDY_MODE, true); } + public static long readLastUserHistoryWriteTime(final SharedPreferences prefs, + final String locale) { + final String str = prefs.getString(PREF_LAST_USER_DICTIONARY_WRITE_TIME, ""); + final HashMap<String, Long> map = LocaleUtils.localeAndTimeStrToHashMap(str); + if (map.containsKey(locale)) { + return map.get(locale); + } + return 0; + } + + public static void writeLastUserHistoryWriteTime(final SharedPreferences prefs, + final String locale) { + final String oldStr = prefs.getString(PREF_LAST_USER_DICTIONARY_WRITE_TIME, ""); + final HashMap<String, Long> map = LocaleUtils.localeAndTimeStrToHashMap(oldStr); + map.put(locale, System.currentTimeMillis()); + final String newStr = LocaleUtils.localeAndTimeHashMapToStr(map); + prefs.edit().putString(PREF_LAST_USER_DICTIONARY_WRITE_TIME, newStr).apply(); + } + public static boolean readUseFullscreenMode(final Resources res) { return res.getBoolean(R.bool.config_use_fullscreen_mode); } diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java index d7a3e95b3..5c60a7350 100644 --- a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java @@ -48,6 +48,7 @@ import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils; import com.android.inputmethod.latin.utils.ApplicationUtils; import com.android.inputmethod.latin.utils.FeedbackUtils; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; +import com.android.inputmethod.research.ResearchLogger; import com.android.inputmethodcommon.InputMethodSettingsFragment; import java.util.TreeSet; @@ -60,6 +61,13 @@ public final class SettingsFragment extends InputMethodSettingsFragment DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS || Build.VERSION.SDK_INT <= 18 /* Build.VERSION.JELLY_BEAN_MR2 */; + private CheckBoxPreference mVoiceInputKeyPreference; + 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 void setPreferenceEnabled(final String preferenceKey, final boolean enabled) { final Preference preference = findPreference(preferenceKey); if (preference != null) { @@ -67,18 +75,6 @@ public final class SettingsFragment extends InputMethodSettingsFragment } } - private void updateListPreferenceSummaryToCurrentValue(final String prefKey) { - // Because the "%s" summary trick of {@link ListPreference} doesn't work properly before - // KitKat, we need to update the summary programmatically. - final ListPreference listPreference = (ListPreference)findPreference(prefKey); - if (listPreference == null) { - return; - } - final CharSequence entries[] = listPreference.getEntries(); - final int entryIndex = listPreference.findIndexOfValue(listPreference.getValue()); - listPreference.setSummary(entryIndex < 0 ? null : entries[entryIndex]); - } - private static void removePreference(final String preferenceKey, final PreferenceGroup parent) { if (parent == null) { return; @@ -111,9 +107,16 @@ public final class SettingsFragment extends InputMethodSettingsFragment SubtypeLocaleUtils.init(context); AudioAndHapticFeedbackManager.init(context); + mVoiceInputKeyPreference = + (CheckBoxPreference) findPreference(Settings.PREF_VOICE_INPUT_KEY); + 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 = @@ -140,7 +143,12 @@ public final class SettingsFragment extends InputMethodSettingsFragment feedbackSettings.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(final Preference pref) { - FeedbackUtils.showFeedbackForm(getActivity()); + if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { + // Use development-only feedback mechanism + ResearchLogger.getInstance().presentFeedbackDialogFromSettings(); + } else { + FeedbackUtils.showFeedbackForm(getActivity()); + } return true; } }); @@ -159,7 +167,7 @@ public final class SettingsFragment extends InputMethodSettingsFragment final boolean showVoiceKeyOption = res.getBoolean( R.bool.config_enable_show_voice_key_option); if (!showVoiceKeyOption) { - removePreference(Settings.PREF_VOICE_INPUT_KEY, generalSettings); + generalSettings.removePreference(mVoiceInputKeyPreference); } final PreferenceGroup advancedSettings = @@ -169,27 +177,26 @@ public final class SettingsFragment extends InputMethodSettingsFragment removePreference(Settings.PREF_VIBRATION_DURATION_SETTINGS, advancedSettings); } - if (!Settings.readFromBuildConfigIfToShowKeyPreviewPopupOption(res)) { + mKeyPreviewPopupDismissDelay = + (ListPreference) findPreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY); + if (!Settings.readFromBuildConfigIfToShowKeyPreviewPopupSettingsOption(res)) { removePreference(Settings.PREF_POPUP_ON, generalSettings); removePreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, advancedSettings); } else { - // TODO: Cleanup this setup. - final ListPreference keyPreviewPopupDismissDelay = - (ListPreference) findPreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY); final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger( R.integer.config_key_preview_linger_timeout)); - keyPreviewPopupDismissDelay.setEntries(new String[] { + mKeyPreviewPopupDismissDelay.setEntries(new String[] { res.getString(R.string.key_preview_popup_dismiss_no_delay), res.getString(R.string.key_preview_popup_dismiss_default_delay), }); - keyPreviewPopupDismissDelay.setEntryValues(new String[] { + mKeyPreviewPopupDismissDelay.setEntryValues(new String[] { "0", popupDismissDelayDefaultValue }); - if (null == keyPreviewPopupDismissDelay.getValue()) { - keyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue); + if (null == mKeyPreviewPopupDismissDelay.getValue()) { + mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue); } - keyPreviewPopupDismissDelay.setEnabled( + mKeyPreviewPopupDismissDelay.setEnabled( Settings.readKeyPreviewPopupEnabled(prefs, res)); } @@ -236,19 +243,20 @@ public final class SettingsFragment extends InputMethodSettingsFragment @Override public void onResume() { super.onResume(); - final SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); - final Resources res = getResources(); final boolean isShortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled(); - setPreferenceEnabled(Settings.PREF_VOICE_INPUT_KEY, isShortcutImeEnabled); + if (!isShortcutImeEnabled) { + getPreferenceScreen().removePreference(mVoiceInputKeyPreference); + } + final SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); final CheckBoxPreference showSetupWizardIcon = (CheckBoxPreference)findPreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON); if (showSetupWizardIcon != null) { showSetupWizardIcon.setChecked(Settings.readShowSetupWizardIcon(prefs, getActivity())); } - updateListPreferenceSummaryToCurrentValue(Settings.PREF_SHOW_SUGGESTIONS_SETTING); - updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY); - updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEYBOARD_LAYOUT); - updateCustomInputStylesSummary(prefs, res); + updateShowCorrectionSuggestionsSummary(); + updateKeyPreviewPopupDelaySummary(); + updateColorSchemeSummary(prefs, getResources()); + updateCustomInputStylesSummary(); } @Override @@ -279,26 +287,50 @@ public final class SettingsFragment extends InputMethodSettingsFragment LauncherIconVisibilityManager.updateSetupWizardIconVisibility(getActivity()); } ensureConsistencyOfAutoCorrectionSettings(); - updateListPreferenceSummaryToCurrentValue(Settings.PREF_SHOW_SUGGESTIONS_SETTING); - updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY); - updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEYBOARD_LAYOUT); + updateShowCorrectionSuggestionsSummary(); + updateKeyPreviewPopupDelaySummary(); + updateColorSchemeSummary(prefs, res); refreshEnablingsOfKeypressSoundAndVibrationSettings(prefs, getResources()); } private void ensureConsistencyOfAutoCorrectionSettings() { final String autoCorrectionOff = getResources().getString( R.string.auto_correction_threshold_mode_index_off); - final ListPreference autoCorrectionThresholdPref = (ListPreference)findPreference( - Settings.PREF_AUTO_CORRECTION_THRESHOLD); - final String currentSetting = autoCorrectionThresholdPref.getValue(); - setPreferenceEnabled( - Settings.PREF_BIGRAM_PREDICTIONS, !currentSetting.equals(autoCorrectionOff)); + final String currentSetting = mAutoCorrectionThresholdPreference.getValue(); + mBigramPrediction.setEnabled(!currentSetting.equals(autoCorrectionOff)); } - private void updateCustomInputStylesSummary(final SharedPreferences prefs, - final Resources res) { + private void updateShowCorrectionSuggestionsSummary() { + mShowCorrectionSuggestionsPreference.setSummary( + getResources().getStringArray(R.array.prefs_suggestion_visibilities) + [mShowCorrectionSuggestionsPreference.findIndexOfValue( + mShowCorrectionSuggestionsPreference.getValue())]); + } + + private void updateColorSchemeSummary(final SharedPreferences prefs, final Resources res) { + // Because the "%s" summary trick of {@link ListPreference} doesn't work properly before + // KitKat, we need to update the summary by code. + final Preference preference = findPreference(Settings.PREF_KEYBOARD_LAYOUT); + if (!(preference instanceof ListPreference)) { + Log.w(TAG, "Can't find Keyboard Color Scheme preference"); + return; + } + final ListPreference colorSchemePreference = (ListPreference)preference; + final int themeIndex = Settings.readKeyboardThemeIndex(prefs, res); + int entryIndex = colorSchemePreference.findIndexOfValue(Integer.toString(themeIndex)); + if (entryIndex < 0) { + final int defaultThemeIndex = Settings.resetAndGetDefaultKeyboardThemeIndex(prefs, res); + entryIndex = colorSchemePreference.findIndexOfValue( + Integer.toString(defaultThemeIndex)); + } + colorSchemePreference.setSummary(colorSchemePreference.getEntries()[entryIndex]); + } + + 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 = Settings.readPrefAdditionalSubtypes(prefs, res); final InputMethodSubtype[] subtypes = AdditionalSubtypeUtils.createAdditionalSubtypesArray(prefSubtype); @@ -310,6 +342,13 @@ public final class SettingsFragment extends InputMethodSettingsFragment 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 refreshEnablingsOfKeypressSoundAndVibrationSettings( final SharedPreferences sp, final Resources res) { setPreferenceEnabled(Settings.PREF_VIBRATION_DURATION_SETTINGS, diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java index 06406c19b..f331c78e5 100644 --- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java @@ -67,7 +67,7 @@ public final class SettingsValues { public final boolean mVibrateOn; public final boolean mSoundOn; public final boolean mKeyPreviewPopupOn; - public final boolean mShowsVoiceInputKey; + private final boolean mShowsVoiceInputKey; public final boolean mIncludesOtherImesInLanguageSwitchList; public final boolean mShowsLanguageSwitchKey; public final boolean mUseContactsDict; @@ -271,6 +271,13 @@ public final class SettingsValues { return mInputAttributes.mShouldInsertSpacesAutomatically; } + public boolean isVoiceKeyEnabled(final EditorInfo editorInfo) { + final boolean shortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled(); + final int inputType = (editorInfo != null) ? editorInfo.inputType : 0; + return shortcutImeEnabled && mShowsVoiceInputKey + && !InputTypeUtils.isPasswordInputType(inputType); + } + public boolean isLanguageSwitchKeyEnabled() { if (!mShowsLanguageSwitchKey) { return false; @@ -367,20 +374,16 @@ public final class SettingsValues { return autoCorrectionThreshold; } - private static boolean needsToShowVoiceInputKey(final SharedPreferences prefs, - final Resources res) { - if (!prefs.contains(Settings.PREF_VOICE_INPUT_KEY)) { - // Migrate preference from {@link Settings#PREF_VOICE_MODE_OBSOLETE} to - // {@link Settings#PREF_VOICE_INPUT_KEY}. - final String voiceModeMain = res.getString(R.string.voice_mode_main); - final String voiceMode = prefs.getString( - Settings.PREF_VOICE_MODE_OBSOLETE, voiceModeMain); - final boolean shouldShowVoiceInputKey = voiceModeMain.equals(voiceMode); - prefs.edit().putBoolean(Settings.PREF_VOICE_INPUT_KEY, shouldShowVoiceInputKey).apply(); - } - // Remove the obsolete preference if exists. - if (prefs.contains(Settings.PREF_VOICE_MODE_OBSOLETE)) { - prefs.edit().remove(Settings.PREF_VOICE_MODE_OBSOLETE).apply(); + private static boolean needsToShowVoiceInputKey(SharedPreferences prefs, Resources res) { + final String voiceModeMain = res.getString(R.string.voice_mode_main); + final String voiceMode = prefs.getString(Settings.PREF_VOICE_MODE_OBSOLETE, voiceModeMain); + final boolean showsVoiceInputKey = voiceMode == null || voiceMode.equals(voiceModeMain); + if (!showsVoiceInputKey) { + // Migrate settings from PREF_VOICE_MODE_OBSOLETE to PREF_VOICE_INPUT_KEY + // Set voiceModeMain as a value of obsolete voice mode settings. + prefs.edit().putString(Settings.PREF_VOICE_MODE_OBSOLETE, voiceModeMain).apply(); + // Disable voice input key. + prefs.edit().putBoolean(Settings.PREF_VOICE_INPUT_KEY, false).apply(); } return prefs.getBoolean(Settings.PREF_VOICE_INPUT_KEY, true); } diff --git a/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java index 5072fabd6..c4a813c24 100644 --- a/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java +++ b/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java @@ -38,7 +38,7 @@ import com.android.inputmethod.compat.ViewCompatUtils; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.settings.SettingsActivity; import com.android.inputmethod.latin.utils.CollectionUtils; -import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper; +import com.android.inputmethod.latin.utils.StaticInnerHandlerWrapper; import java.util.ArrayList; @@ -74,21 +74,21 @@ public final class SetupWizardActivity extends Activity implements View.OnClickL private SettingsPoolingHandler mHandler; private static final class SettingsPoolingHandler - extends LeakGuardHandlerWrapper<SetupWizardActivity> { + extends StaticInnerHandlerWrapper<SetupWizardActivity> { private static final int MSG_POLLING_IME_SETTINGS = 0; private static final long IME_SETTINGS_POLLING_INTERVAL = 200; private final InputMethodManager mImmInHandler; - public SettingsPoolingHandler(final SetupWizardActivity ownerInstance, + public SettingsPoolingHandler(final SetupWizardActivity outerInstance, final InputMethodManager imm) { - super(ownerInstance); + super(outerInstance); mImmInHandler = imm; } @Override public void handleMessage(final Message msg) { - final SetupWizardActivity setupWizardActivity = getOwnerInstance(); + final SetupWizardActivity setupWizardActivity = getOuterInstance(); if (setupWizardActivity == null) { return; } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index c108b20ed..503b18b1b 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -428,7 +428,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService final String localeStr = locale.toString(); UserBinaryDictionary userDictionary = mUserDictionaries.get(localeStr); if (null == userDictionary) { - userDictionary = new SynchronouslyLoadedUserBinaryDictionary(this, locale, true); + userDictionary = new SynchronouslyLoadedUserBinaryDictionary(this, localeStr, true); mUserDictionaries.put(localeStr, userDictionary); } dictionaryCollection.addDictionary(userDictionary); diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java index b7a5a4026..a0aed2829 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java @@ -49,7 +49,6 @@ public final class DictionaryPool extends LinkedBlockingQueue<DictAndKeyboard> { final static ArrayList<SuggestedWordInfo> noSuggestions = CollectionUtils.newArrayList(); private final static DictAndKeyboard dummyDict = new DictAndKeyboard( new Dictionary(Dictionary.TYPE_MAIN) { - // TODO: this dummy dictionary should be a singleton in the Dictionary class. @Override public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, final String prevWord, final ProximityInfo proximityInfo, diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index 52012c846..acd47450b 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -66,8 +66,7 @@ public final class MoreSuggestions extends Keyboard { clearKeys(); mDivider = res.getDrawable(R.drawable.more_suggestions_divider); mDividerWidth = mDivider.getIntrinsicWidth(); - final float padding = res.getDimension( - R.dimen.config_more_suggestions_key_horizontal_padding); + final float padding = res.getDimension(R.dimen.more_suggestions_key_horizontal_padding); int row = 0; int index = fromIndex; @@ -76,7 +75,7 @@ public final class MoreSuggestions extends Keyboard { while (index < size) { final String word = suggestedWords.getWord(index); // TODO: Should take care of text x-scaling. - mWidths[index] = (int)(TypefaceUtils.getStringWidth(word, paint) + padding); + mWidths[index] = (int)(TypefaceUtils.getLabelWidth(word, paint) + padding); final int numColumn = index - rowStartIndex + 1; final int columnWidth = (maxWidth - mDividerWidth * (numColumn - 1)) / numColumn; diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java index 549ff0d9d..0ebe37782 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java @@ -54,7 +54,7 @@ public final class MoreSuggestionsView extends MoreKeysKeyboardView { public void adjustVerticalCorrectionForModalMode() { // Set vertical correction to zero (Reset more keys keyboard sliding allowance - // {@link R#dimen.config_more_keys_keyboard_slide_allowance}). + // {@link R#dimen.more_keys_keyboard_slide_allowance}). mKeyDetector.setKeyboard(getKeyboard(), -getPaddingLeft(), -getPaddingTop()); } diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java index 72281e62c..faa5560e4 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java @@ -119,8 +119,7 @@ final class SuggestionStripLayoutHelper { mDividerWidth = dividerView.getMeasuredWidth(); final Resources res = wordView.getResources(); - mSuggestionsStripHeight = res.getDimensionPixelSize( - R.dimen.config_suggestions_strip_height); + mSuggestionsStripHeight = res.getDimensionPixelSize(R.dimen.suggestions_strip_height); final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SuggestionStripView, defStyle, R.style.SuggestionStripView); @@ -146,17 +145,15 @@ final class SuggestionStripLayoutHelper { a.recycle(); mMoreSuggestionsHint = getMoreSuggestionsHint(res, - res.getDimension(R.dimen.config_more_suggestions_hint_text_size), - mColorAutoCorrect); + res.getDimension(R.dimen.more_suggestions_hint_text_size), mColorAutoCorrect); mCenterPositionInStrip = mSuggestionsCountInStrip / 2; // Assuming there are at least three suggestions. Also, note that the suggestions are // laid out according to script direction, so this is left of the center for LTR scripts // and right of the center for RTL scripts. mTypedWordPositionWhenAutocorrect = mCenterPositionInStrip - 1; mMoreSuggestionsBottomGap = res.getDimensionPixelOffset( - R.dimen.config_more_suggestions_bottom_gap); - mMoreSuggestionsRowHeight = res.getDimensionPixelSize( - R.dimen.config_more_suggestions_row_height); + R.dimen.more_suggestions_bottom_gap); + mMoreSuggestionsRowHeight = res.getDimensionPixelSize(R.dimen.more_suggestions_row_height); final LayoutInflater inflater = LayoutInflater.from(context); mWordToSaveView = (TextView)inflater.inflate(R.layout.suggestion_word, null); diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index aa87affa2..75f17c559 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -112,7 +112,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick final Resources res = context.getResources(); mMoreSuggestionsModalTolerance = res.getDimensionPixelOffset( - R.dimen.config_more_suggestions_modal_tolerance); + R.dimen.more_suggestions_modal_tolerance); mMoreSuggestionsSlidingDetector = new GestureDetector( context, mMoreSuggestionsSlidingListener); } diff --git a/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java b/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java index ef1d0f42c..d87f6f3c4 100644 --- a/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java @@ -17,25 +17,21 @@ package com.android.inputmethod.latin.utils; import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE; -import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.EMOJI_CAPABLE; import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE; import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET; import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME; import android.os.Build; import android.text.TextUtils; -import android.util.Log; import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils; +import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; import java.util.ArrayList; -import java.util.Arrays; public final class AdditionalSubtypeUtils { - private static final String TAG = AdditionalSubtypeUtils.class.getSimpleName(); - private static final InputMethodSubtype[] EMPTY_SUBTYPE_ARRAY = new InputMethodSubtype[0]; private AdditionalSubtypeUtils() { @@ -47,11 +43,6 @@ public final class AdditionalSubtypeUtils { } private static final String LOCALE_AND_LAYOUT_SEPARATOR = ":"; - private static final int INDEX_OF_LOCALE = 0; - private static final int INDEX_OF_KEYBOARD_LAYOUT = 1; - private static final int INDEX_OF_EXTRA_VALUE = 2; - private static final int LENGTH_WITHOUT_EXTRA_VALUE = (INDEX_OF_KEYBOARD_LAYOUT + 1); - private static final int LENGTH_WITH_EXTRA_VALUE = (INDEX_OF_EXTRA_VALUE + 1); private static final String PREF_SUBTYPE_SEPARATOR = ";"; public static InputMethodSubtype createAdditionalSubtype(final String localeString, @@ -88,6 +79,17 @@ public final class AdditionalSubtypeUtils { : basePrefSubtype + LOCALE_AND_LAYOUT_SEPARATOR + extraValue; } + public static InputMethodSubtype createAdditionalSubtype(final String prefSubtype) { + final String elems[] = prefSubtype.split(LOCALE_AND_LAYOUT_SEPARATOR); + if (elems.length < 2 || elems.length > 3) { + throw new RuntimeException("Unknown additional subtype specified: " + prefSubtype); + } + final String localeString = elems[0]; + final String keyboardLayoutSetName = elems[1]; + final String extraValue = (elems.length == 3) ? elems[2] : null; + return createAdditionalSubtype(localeString, keyboardLayoutSetName, extraValue); + } + public static InputMethodSubtype[] createAdditionalSubtypesArray(final String prefSubtypes) { if (TextUtils.isEmpty(prefSubtypes)) { return EMPTY_SUBTYPE_ARRAY; @@ -96,19 +98,7 @@ public final class AdditionalSubtypeUtils { final ArrayList<InputMethodSubtype> subtypesList = CollectionUtils.newArrayList(prefSubtypeArray.length); for (final String prefSubtype : prefSubtypeArray) { - final String elems[] = prefSubtype.split(LOCALE_AND_LAYOUT_SEPARATOR); - if (elems.length != LENGTH_WITHOUT_EXTRA_VALUE - && elems.length != LENGTH_WITH_EXTRA_VALUE) { - Log.w(TAG, "Unknown additional subtype specified: " + prefSubtype + " in " - + prefSubtypes); - continue; - } - final String localeString = elems[INDEX_OF_LOCALE]; - final String keyboardLayoutSetName = elems[INDEX_OF_KEYBOARD_LAYOUT]; - final String extraValue = (elems.length == LENGTH_WITH_EXTRA_VALUE) - ? elems[INDEX_OF_EXTRA_VALUE] : null; - final InputMethodSubtype subtype = createAdditionalSubtype( - localeString, keyboardLayoutSetName, extraValue); + final InputMethodSubtype subtype = createAdditionalSubtype(prefSubtype); if (subtype.getNameResId() == SubtypeLocaleUtils.UNKNOWN_KEYBOARD_LAYOUT) { // Skip unknown keyboard layout subtype. This may happen when predefined keyboard // layout has been removed. @@ -147,36 +137,31 @@ public final class AdditionalSubtypeUtils { return sb.toString(); } - private static InputMethodSubtype buildInputMethodSubtype(final int nameId, - final String localeString, final String layoutExtraValue, - final String additionalSubtypeExtraValue) { - // To preserve additional subtype settings and user's selection across OS updates, subtype - // id shouldn't be changed. New attributes, such as emojiCapable, are carefully excluded - // from the calculation of subtype id. - final String compatibleExtraValue = StringUtils.joinCommaSplittableText( - layoutExtraValue, additionalSubtypeExtraValue); - final int compatibleSubtypeId = getInputMethodSubtypeId(localeString, compatibleExtraValue); + private static InputMethodSubtype buildInputMethodSubtype(int nameId, String localeString, + String layoutExtraValue, String additionalSubtypeExtraValue) { + // CAVEAT! If you want to change subtypeId after changing the extra values, + // you must change "getInputMethodSubtypeId". But it will remove the additional keyboard + // from the current users. So, you should be really careful to change it. + final int subtypeId = getInputMethodSubtypeId(nameId, localeString, layoutExtraValue, + additionalSubtypeExtraValue); final String extraValue; - // Color Emoji is supported from KitKat. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - extraValue = StringUtils.appendToCommaSplittableTextIfNotExists( - EMOJI_CAPABLE, compatibleExtraValue); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + extraValue = layoutExtraValue + "," + additionalSubtypeExtraValue + + "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE + + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE; } else { - extraValue = compatibleExtraValue; + extraValue = layoutExtraValue + "," + additionalSubtypeExtraValue; } return InputMethodSubtypeCompatUtils.newInputMethodSubtype(nameId, R.drawable.ic_ime_switcher_dark, localeString, KEYBOARD_MODE, extraValue, - false, false, compatibleSubtypeId); + false, false, subtypeId); } - private static int getInputMethodSubtypeId(final String localeString, final String extraValue) { - // From the compatibility point of view, the calculation of subtype id has been copied from - // {@link InputMethodSubtype} of JellyBean MR2. - return Arrays.hashCode(new Object[] { - localeString, - KEYBOARD_MODE, - extraValue, - false /* isAuxiliary */, - false /* overrideImplicitlyEnabledSubtype */ }); + private static int getInputMethodSubtypeId(int nameId, String localeString, + String layoutExtraValue, String additionalSubtypeExtraValue) { + // TODO: Use InputMethodSubtypeBuilder once we use SDK version 19. + return (new InputMethodSubtype(nameId, R.drawable.ic_ime_switcher_dark, + localeString, KEYBOARD_MODE, layoutExtraValue + "," + additionalSubtypeExtraValue, + false, false)).hashCode(); } } diff --git a/java/src/com/android/inputmethod/latin/utils/ApplicationUtils.java b/java/src/com/android/inputmethod/latin/utils/ApplicationUtils.java index e521ec807..08a2a8c5a 100644 --- a/java/src/com/android/inputmethod/latin/utils/ApplicationUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ApplicationUtils.java @@ -62,22 +62,4 @@ public final class ApplicationUtils { } return ""; } - - /** - * A utility method to get the application's PackageInfo.versionCode - * @return the application's PackageInfo.versionCode - */ - public static int getVersionCode(final Context context) { - try { - if (context == null) { - return 0; - } - final String packageName = context.getPackageName(); - final PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0); - return info.versionCode; - } catch (final NameNotFoundException e) { - Log.e(TAG, "Could not find version info.", e); - } - return 0; - } } diff --git a/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java b/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java index d12aad639..c2e97a36f 100644 --- a/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java +++ b/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java @@ -20,7 +20,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** - * This class is a holder of the result of an asynchronous computation. + * This class is a holder of a result of asynchronous computation. * * @param <E> the type of the result. */ @@ -36,9 +36,9 @@ public class AsyncResultHolder<E> { } /** - * Sets the result value of this holder. + * Sets the result value to this holder. * - * @param result the value to set. + * @param result the value which is set. */ public void set(final E result) { synchronized(mLock) { @@ -54,12 +54,12 @@ public class AsyncResultHolder<E> { * Causes the current thread to wait unless the value is set or the specified time is elapsed. * * @param defaultValue the default value. - * @param timeOut the maximum time to wait. - * @return if the result is set before the time limit then the result, otherwise defaultValue. + * @param timeOut the time to wait. + * @return if the result is set until the time limit then the result, otherwise defaultValue. */ public E get(final E defaultValue, final long timeOut) { try { - if (mLatch.await(timeOut, TimeUnit.MILLISECONDS)) { + if(mLatch.await(timeOut, TimeUnit.MILLISECONDS)) { return mResult; } else { return defaultValue; diff --git a/java/src/com/android/inputmethod/latin/utils/FileUtils.java b/java/src/com/android/inputmethod/latin/utils/FileUtils.java deleted file mode 100644 index 83c1e7c4d..000000000 --- a/java/src/com/android/inputmethod/latin/utils/FileUtils.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 - * 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.utils; - -import java.io.File; - -/** - * A simple class to help with removing directories recursively. - */ -public class FileUtils { - public static boolean deleteRecursively(final File path) { - if (path.isDirectory()) { - for (final File child : path.listFiles()) { - deleteRecursively(child); - } - } - return path.delete(); - } -} diff --git a/java/src/com/android/inputmethod/latin/utils/JsonUtils.java b/java/src/com/android/inputmethod/latin/utils/JsonUtils.java deleted file mode 100644 index 764ef72ce..000000000 --- a/java/src/com/android/inputmethod/latin/utils/JsonUtils.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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 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.utils; - -import android.util.JsonReader; -import android.util.JsonWriter; -import android.util.Log; - -import java.io.Closeable; -import java.io.IOException; -import java.io.StringReader; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public final class JsonUtils { - private static final String TAG = JsonUtils.class.getSimpleName(); - - private static final String INTEGER_CLASS_NAME = Integer.class.getSimpleName(); - private static final String STRING_CLASS_NAME = String.class.getSimpleName(); - - private static final String EMPTY_STRING = ""; - - public static List<Object> jsonStrToList(final String s) { - final ArrayList<Object> list = CollectionUtils.newArrayList(); - final JsonReader reader = new JsonReader(new StringReader(s)); - try { - reader.beginArray(); - while (reader.hasNext()) { - reader.beginObject(); - while (reader.hasNext()) { - final String name = reader.nextName(); - if (name.equals(INTEGER_CLASS_NAME)) { - list.add(reader.nextInt()); - } else if (name.equals(STRING_CLASS_NAME)) { - list.add(reader.nextString()); - } else { - Log.w(TAG, "Invalid name: " + name); - reader.skipValue(); - } - } - reader.endObject(); - } - reader.endArray(); - return list; - } catch (final IOException e) { - } finally { - close(reader); - } - return Collections.<Object>emptyList(); - } - - public static String listToJsonStr(final List<Object> list) { - if (list == null || list.isEmpty()) { - return EMPTY_STRING; - } - final StringWriter sw = new StringWriter(); - final JsonWriter writer = new JsonWriter(sw); - try { - writer.beginArray(); - for (final Object o : list) { - writer.beginObject(); - if (o instanceof Integer) { - writer.name(INTEGER_CLASS_NAME).value((Integer)o); - } else if (o instanceof String) { - writer.name(STRING_CLASS_NAME).value((String)o); - } - writer.endObject(); - } - writer.endArray(); - return sw.toString(); - } catch (final IOException e) { - } finally { - close(writer); - } - return EMPTY_STRING; - } - - private static void close(final Closeable closeable) { - try { - if (closeable != null) { - closeable.close(); - } - } catch (final IOException e) { - // Ignore - } - } -} diff --git a/java/src/com/android/inputmethod/latin/utils/LatinImeLoggerUtils.java b/java/src/com/android/inputmethod/latin/utils/LatinImeLoggerUtils.java index d14ba508b..e958a7e71 100644 --- a/java/src/com/android/inputmethod/latin/utils/LatinImeLoggerUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/LatinImeLoggerUtils.java @@ -35,7 +35,7 @@ public final class LatinImeLoggerUtils { public static void onSeparator(final int code, final int x, final int y) { // Helper method to log a single code point separator // TODO: cache this mapping of a code point to a string in a sparse array in StringUtils - onSeparator(StringUtils.newSingleCodePointString(code), x, y); + onSeparator(new String(new int[]{code}, 0, 1), x, y); } public static void onSeparator(final String separator, final int x, final int y) { diff --git a/java/src/com/android/inputmethod/latin/utils/LocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/LocaleUtils.java index 0c55484b4..22045aa38 100644 --- a/java/src/com/android/inputmethod/latin/utils/LocaleUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/LocaleUtils.java @@ -30,6 +30,9 @@ import java.util.Locale; * dictionary pack. */ public final class LocaleUtils { + private static final HashMap<String, Long> EMPTY_LT_HASH_MAP = CollectionUtils.newHashMap(); + private static final String LOCALE_AND_TIME_STR_SEPARATER = ","; + private LocaleUtils() { // Intentional empty constructor for utility class. } @@ -165,14 +168,12 @@ public final class LocaleUtils { * Creates a locale from a string specification. */ public static Locale constructLocaleFromString(final String localeStr) { - if (localeStr == null) { + if (localeStr == null) return null; - } synchronized (sLocaleCache) { - Locale retval = sLocaleCache.get(localeStr); - if (retval != null) { - return retval; - } + if (sLocaleCache.containsKey(localeStr)) + return sLocaleCache.get(localeStr); + Locale retval = null; String[] localeParams = localeStr.split("_", 3); if (localeParams.length == 1) { retval = new Locale(localeParams[0]); @@ -187,4 +188,38 @@ public final class LocaleUtils { return retval; } } + + public static HashMap<String, Long> localeAndTimeStrToHashMap(String str) { + if (TextUtils.isEmpty(str)) { + return EMPTY_LT_HASH_MAP; + } + final String[] ss = str.split(LOCALE_AND_TIME_STR_SEPARATER); + final int N = ss.length; + if (N < 2 || N % 2 != 0) { + return EMPTY_LT_HASH_MAP; + } + final HashMap<String, Long> retval = CollectionUtils.newHashMap(); + for (int i = 0; i < N / 2; ++i) { + final String localeStr = ss[i * 2]; + final long time = Long.valueOf(ss[i * 2 + 1]); + retval.put(localeStr, time); + } + return retval; + } + + public static String localeAndTimeHashMapToStr(HashMap<String, Long> map) { + if (map == null || map.isEmpty()) { + return ""; + } + final StringBuilder builder = new StringBuilder(); + for (String localeStr : map.keySet()) { + if (builder.length() > 0) { + builder.append(LOCALE_AND_TIME_STR_SEPARATER); + } + final Long time = map.get(localeStr); + builder.append(localeStr).append(LOCALE_AND_TIME_STR_SEPARATER); + builder.append(String.valueOf(time)); + } + return builder.toString(); + } } diff --git a/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java b/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java index deb28a08d..22c92446a 100644 --- a/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java @@ -227,19 +227,19 @@ public final class ResourceUtils { final String keyboardHeightString = getDeviceOverrideValue(res, R.array.keyboard_heights); final float keyboardHeight; if (TextUtils.isEmpty(keyboardHeightString)) { - keyboardHeight = res.getDimension(R.dimen.config_default_keyboard_height); + keyboardHeight = res.getDimension(R.dimen.keyboardHeight); } else { keyboardHeight = Float.parseFloat(keyboardHeightString) * dm.density; } final float maxKeyboardHeight = res.getFraction( - R.fraction.config_max_keyboard_height, dm.heightPixels, dm.heightPixels); + R.fraction.maxKeyboardHeight, dm.heightPixels, dm.heightPixels); float minKeyboardHeight = res.getFraction( - R.fraction.config_min_keyboard_height, dm.heightPixels, dm.heightPixels); + R.fraction.minKeyboardHeight, dm.heightPixels, dm.heightPixels); if (minKeyboardHeight < 0.0f) { // Specified fraction was negative, so it should be calculated against display // width. minKeyboardHeight = -res.getFraction( - R.fraction.config_min_keyboard_height, dm.widthPixels, dm.widthPixels); + R.fraction.minKeyboardHeight, dm.widthPixels, dm.widthPixels); } // Keyboard height will not exceed maxKeyboardHeight and will not be less than // minKeyboardHeight. diff --git a/java/src/com/android/inputmethod/latin/utils/LeakGuardHandlerWrapper.java b/java/src/com/android/inputmethod/latin/utils/StaticInnerHandlerWrapper.java index 8469c87b0..44e5d17b4 100644 --- a/java/src/com/android/inputmethod/latin/utils/LeakGuardHandlerWrapper.java +++ b/java/src/com/android/inputmethod/latin/utils/StaticInnerHandlerWrapper.java @@ -21,22 +21,22 @@ import android.os.Looper; import java.lang.ref.WeakReference; -public class LeakGuardHandlerWrapper<T> extends Handler { - private final WeakReference<T> mOwnerInstanceRef; +public class StaticInnerHandlerWrapper<T> extends Handler { + private final WeakReference<T> mOuterInstanceRef; - public LeakGuardHandlerWrapper(final T ownerInstance) { - this(ownerInstance, Looper.myLooper()); + public StaticInnerHandlerWrapper(final T outerInstance) { + this(outerInstance, Looper.myLooper()); } - public LeakGuardHandlerWrapper(final T ownerInstance, final Looper looper) { + public StaticInnerHandlerWrapper(final T outerInstance, final Looper looper) { super(looper); - if (ownerInstance == null) { - throw new NullPointerException("ownerInstance is null"); + if (outerInstance == null) { + throw new NullPointerException("outerInstance is null"); } - mOwnerInstanceRef = new WeakReference<T>(ownerInstance); + mOuterInstanceRef = new WeakReference<T>(outerInstance); } - public T getOwnerInstance() { - return mOwnerInstanceRef.get(); + public T getOuterInstance() { + return mOuterInstanceRef.get(); } } diff --git a/java/src/com/android/inputmethod/latin/utils/StringUtils.java b/java/src/com/android/inputmethod/latin/utils/StringUtils.java index df420417d..a36548392 100644 --- a/java/src/com/android/inputmethod/latin/utils/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/StringUtils.java @@ -16,15 +16,20 @@ package com.android.inputmethod.latin.utils; -import android.text.TextUtils; -import android.util.Log; - import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.settings.SettingsValues; +import android.text.TextUtils; +import android.util.JsonReader; +import android.util.JsonWriter; +import android.util.Log; + import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Locale; @@ -34,8 +39,6 @@ public final class StringUtils { public static final int CAPITALIZE_FIRST = 1; // First only public static final int CAPITALIZE_ALL = 2; // All caps - private static final String EMPTY_STRING = ""; - private StringUtils() { // This utility class is not publicly instantiable. } @@ -77,20 +80,6 @@ public final class StringUtils { return containsInArray(text, extraValues.split(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT)); } - public static String joinCommaSplittableText(final String head, final String tail) { - if (TextUtils.isEmpty(head) && TextUtils.isEmpty(tail)) { - return EMPTY_STRING; - } - // Here either head or tail is not null. - if (TextUtils.isEmpty(head)) { - return tail; - } - if (TextUtils.isEmpty(tail)) { - return head; - } - return head + SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT + tail; - } - public static String appendToCommaSplittableTextIfNotExists(final String text, final String extraValues) { if (TextUtils.isEmpty(extraValues)) { @@ -105,7 +94,7 @@ public final class StringUtils { public static String removeFromCommaSplittableTextIfExists(final String text, final String extraValues) { if (TextUtils.isEmpty(extraValues)) { - return EMPTY_STRING; + return ""; } final String[] elements = extraValues.split(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT); if (!containsInArray(text, elements)) { @@ -378,7 +367,7 @@ public final class StringUtils { return false; } - public static boolean isEmptyStringOrWhiteSpaces(final String s) { + public static boolean isEmptyStringOrWhiteSpaces(String s) { final int N = codePointCount(s); for (int i = 0; i < N; ++i) { if (!Character.isWhitespace(s.codePointAt(i))) { @@ -389,9 +378,9 @@ public final class StringUtils { } @UsedForTesting - public static String byteArrayToHexString(final byte[] bytes) { + public static String byteArrayToHexString(byte[] bytes) { if (bytes == null || bytes.length == 0) { - return EMPTY_STRING; + return ""; } final StringBuilder sb = new StringBuilder(); for (byte b : bytes) { @@ -404,7 +393,7 @@ public final class StringUtils { * Convert hex string to byte array. The string length must be an even number. */ @UsedForTesting - public static byte[] hexStringToByteArray(final String hexString) { + public static byte[] hexStringToByteArray(String hexString) { if (TextUtils.isEmpty(hexString)) { return null; } @@ -420,4 +409,67 @@ public final class StringUtils { } return bytes; } + + public static List<Object> jsonStrToList(String s) { + final ArrayList<Object> retval = CollectionUtils.newArrayList(); + final JsonReader reader = new JsonReader(new StringReader(s)); + try { + reader.beginArray(); + while(reader.hasNext()) { + reader.beginObject(); + while (reader.hasNext()) { + final String name = reader.nextName(); + if (name.equals(Integer.class.getSimpleName())) { + retval.add(reader.nextInt()); + } else if (name.equals(String.class.getSimpleName())) { + retval.add(reader.nextString()); + } else { + Log.w(TAG, "Invalid name: " + name); + reader.skipValue(); + } + } + reader.endObject(); + } + reader.endArray(); + return retval; + } catch (IOException e) { + } finally { + try { + reader.close(); + } catch (IOException e) { + } + } + return Collections.<Object>emptyList(); + } + + public static String listToJsonStr(List<Object> list) { + if (list == null || list.isEmpty()) { + return ""; + } + final StringWriter sw = new StringWriter(); + final JsonWriter writer = new JsonWriter(sw); + try { + writer.beginArray(); + for (final Object o : list) { + writer.beginObject(); + if (o instanceof Integer) { + writer.name(Integer.class.getSimpleName()).value((Integer)o); + } else if (o instanceof String) { + writer.name(String.class.getSimpleName()).value((String)o); + } + writer.endObject(); + } + writer.endArray(); + return sw.toString(); + } catch (IOException e) { + } finally { + try { + if (writer != null) { + writer.close(); + } + } catch (IOException e) { + } + } + return ""; + } } diff --git a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java index fdbe81ab6..102a41b4e 100644 --- a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java @@ -197,9 +197,7 @@ public final class SubtypeLocaleUtils { // es_US spanish F Español (EE.UU.) exception // fr azerty F Français // fr_CA qwerty F Français (Canada) - // fr_CH swiss F Français (Suisse) // de qwertz F Deutsch - // de_CH swiss T Deutsch (Schweiz) // zz qwerty F No language (QWERTY) in system locale // fr qwertz T Français (QWERTZ) // de qwerty T Deutsch (QWERTY) @@ -300,9 +298,7 @@ public final class SubtypeLocaleUtils { // es_US spanish F Es Español Español (EE.UU.) exception // fr azerty F Fr Français Français // fr_CA qwerty F Fr Français Français (Canada) - // fr_CH swiss F Fr Français Français (Suisse) // de qwertz F De Deutsch Deutsch - // de_CH swiss T De Deutsch Deutsch (Schweiz) // zz qwerty F QWERTY QWERTY // fr qwertz T Fr Français Français // de qwerty T De Deutsch Deutsch diff --git a/java/src/com/android/inputmethod/latin/utils/TypefaceUtils.java b/java/src/com/android/inputmethod/latin/utils/TypefaceUtils.java index 087a7f255..47ea1ea75 100644 --- a/java/src/com/android/inputmethod/latin/utils/TypefaceUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/TypefaceUtils.java @@ -22,9 +22,6 @@ import android.graphics.Typeface; import android.util.SparseArray; public final class TypefaceUtils { - private static final char[] KEY_LABEL_REFERENCE_CHAR = { 'M' }; - private static final char[] KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR = { '8' }; - private TypefaceUtils() { // This utility class is not publicly instantiable. } @@ -34,7 +31,7 @@ public final class TypefaceUtils { // Working variable for the following method. private static final Rect sTextHeightBounds = new Rect(); - private static float getCharHeight(final char[] referenceChar, final Paint paint) { + public static float getCharHeight(final char[] referenceChar, final Paint paint) { final int key = getCharGeometryCacheKey(referenceChar[0], paint); synchronized (sTextHeightCache) { final Float cachedValue = sTextHeightCache.get(key); @@ -54,7 +51,7 @@ public final class TypefaceUtils { // Working variable for the following method. private static final Rect sTextWidthBounds = new Rect(); - private static float getCharWidth(final char[] referenceChar, final Paint paint) { + public static float getCharWidth(final char[] referenceChar, final Paint paint) { final int key = getCharGeometryCacheKey(referenceChar[0], paint); synchronized (sTextWidthCache) { final Float cachedValue = sTextWidthCache.get(key); @@ -69,6 +66,11 @@ public final class TypefaceUtils { } } + public static float getStringWidth(final String string, final Paint paint) { + paint.getTextBounds(string, 0, string.length(), sTextWidthBounds); + return sTextWidthBounds.width(); + } + private static int getCharGeometryCacheKey(final char referenceChar, final Paint paint) { final int labelSize = (int)paint.getTextSize(); final Typeface face = paint.getTypeface(); @@ -84,25 +86,9 @@ public final class TypefaceUtils { } } - public static float getReferenceCharHeight(final Paint paint) { - return getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint); - } - - public static float getReferenceCharWidth(final Paint paint) { - return getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint); - } - - public static float getReferenceDigitWidth(final Paint paint) { - return getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint); - } - - // Working variable for the following method. - private static final Rect sStringWidthBounds = new Rect(); - - public static float getStringWidth(final String string, final Paint paint) { - synchronized (sStringWidthBounds) { - paint.getTextBounds(string, 0, string.length(), sStringWidthBounds); - return sStringWidthBounds.width(); - } + public static float getLabelWidth(final String label, final Paint paint) { + final Rect textBounds = new Rect(); + paint.getTextBounds(label, 0, label.length(), textBounds); + return textBounds.width(); } } diff --git a/java/src/com/android/inputmethod/latin/utils/UnigramProperty.java b/java/src/com/android/inputmethod/latin/utils/UnigramProperty.java deleted file mode 100644 index 4feee4393..000000000 --- a/java/src/com/android/inputmethod/latin/utils/UnigramProperty.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 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.utils; - -import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.latin.BinaryDictionary; -import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; - -import java.util.ArrayList; - -// This has information that belong to a unigram. This class has some detailed attributes such as -// historical information but they have to be checked only for testing purpose. -@UsedForTesting -public class UnigramProperty { - public final String mCodePoints; - public final boolean mIsNotAWord; - public final boolean mIsBlacklisted; - public final boolean mHasBigrams; - public final boolean mHasShortcuts; - public final int mProbability; - // mTimestamp, mLevel and mCount are historical info. These values are depend on the - // implementation in native code; thus, we must not use them and have any assumptions about - // them except for tests. - public final int mTimestamp; - public final int mLevel; - public final int mCount; - public final ArrayList<WeightedString> mShortcutTargets = CollectionUtils.newArrayList(); - - private static int getCodePointCount(final int[] codePoints) { - for (int i = 0; i < codePoints.length; i++) { - if (codePoints[i] == 0) { - return i; - } - } - return codePoints.length; - } - - // This represents invalid unigram when the probability is BinaryDictionary.NOT_A_PROBABILITY. - public UnigramProperty(final int[] codePoints, final boolean isNotAWord, - final boolean isBlacklisted, final boolean hasBigram, - final boolean hasShortcuts, final int probability, final int timestamp, - final int level, final int count, final ArrayList<int[]> shortcutTargets, - final ArrayList<Integer> shortcutProbabilities) { - mCodePoints = new String(codePoints, 0 /* offset */, getCodePointCount(codePoints)); - mIsNotAWord = isNotAWord; - mIsBlacklisted = isBlacklisted; - mHasBigrams = hasBigram; - mHasShortcuts = hasShortcuts; - mProbability = probability; - mTimestamp = timestamp; - mLevel = level; - mCount = count; - final int shortcutTargetCount = shortcutTargets.size(); - for (int i = 0; i < shortcutTargetCount; i++) { - final int[] shortcutTargetCodePointArray = shortcutTargets.get(i); - final String shortcutTargetString = new String(shortcutTargetCodePointArray, - 0 /* offset */, getCodePointCount(shortcutTargetCodePointArray)); - mShortcutTargets.add( - new WeightedString(shortcutTargetString, shortcutProbabilities.get(i))); - } - } - - @UsedForTesting - public boolean isValid() { - return mProbability != BinaryDictionary.NOT_A_PROBABILITY; - } -}
\ No newline at end of file diff --git a/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java index db628fe18..635afe7cc 100644 --- a/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java @@ -70,11 +70,10 @@ public final class UserHistoryDictIOUtils { /** * Writes dictionary to file. */ - @UsedForTesting public static void writeDictionary(final DictEncoder dictEncoder, final BigramDictionaryInterface dict, final UserHistoryDictionaryBigramList bigrams, - final FormatOptions formatOptions, final HashMap<String, String> options) { - final FusionDictionary fusionDict = constructFusionDictionary(dict, bigrams, options); + final FormatOptions formatOptions) { + final FusionDictionary fusionDict = constructFusionDictionary(dict, bigrams); fusionDict.addOptionAttribute(USES_FORGETTING_CURVE_KEY, USES_FORGETTING_CURVE_VALUE); fusionDict.addOptionAttribute(LAST_UPDATED_TIME_KEY, String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()))); @@ -92,10 +91,11 @@ public final class UserHistoryDictIOUtils { * Constructs a new FusionDictionary from BigramDictionaryInterface. */ @UsedForTesting - static FusionDictionary constructFusionDictionary(final BigramDictionaryInterface dict, - final UserHistoryDictionaryBigramList bigrams, final HashMap<String, String> options) { + static FusionDictionary constructFusionDictionary( + final BigramDictionaryInterface dict, final UserHistoryDictionaryBigramList bigrams) { final FusionDictionary fusionDict = new FusionDictionary(new PtNodeArray(), - new FusionDictionary.DictionaryOptions(options)); + new FusionDictionary.DictionaryOptions(new HashMap<String, String>(), false, + false)); int profTotal = 0; for (final String word1 : bigrams.keySet()) { final HashMap<String, Byte> word1Bigrams = bigrams.getBigrams(word1); diff --git a/java/src/com/android/inputmethod/latin/utils/UserHistoryForgettingCurveUtils.java b/java/src/com/android/inputmethod/latin/utils/UserHistoryForgettingCurveUtils.java index 677035ed6..1992b2f5d 100644 --- a/java/src/com/android/inputmethod/latin/utils/UserHistoryForgettingCurveUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/UserHistoryForgettingCurveUtils.java @@ -20,9 +20,6 @@ import android.util.Log; import java.util.concurrent.TimeUnit; -import com.android.inputmethod.annotations.UsedForTesting; - -@UsedForTesting public final class UserHistoryForgettingCurveUtils { private static final String TAG = UserHistoryForgettingCurveUtils.class.getSimpleName(); private static final boolean DEBUG = false; @@ -121,22 +118,18 @@ public final class UserHistoryForgettingCurveUtils { } } - @UsedForTesting /* package */ static int fcToElapsedTime(byte fc) { return fc & 0x0F; } - @UsedForTesting /* package */ static int fcToCount(byte fc) { return (fc >> 4) & 0x03; } - @UsedForTesting /* package */ static int fcToLevel(byte fc) { return (fc >> 6) & 0x03; } - @UsedForTesting private static int calcFreq(int elapsedTime, int count, int level) { if (level <= 0) { // Reserved words, just return -1 @@ -165,7 +158,6 @@ public final class UserHistoryForgettingCurveUtils { return calcFreq(elapsedTime, count, level); } - @UsedForTesting public static byte pushElapsedTime(byte fc) { int elapsedTime = fcToElapsedTime(fc); int count = fcToCount(fc); @@ -181,7 +173,6 @@ public final class UserHistoryForgettingCurveUtils { return calcFc(elapsedTime, count, level); } - @UsedForTesting public static byte pushCount(byte fc, boolean isValid) { final int elapsedTime = fcToElapsedTime(fc); int count = fcToCount(fc); diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java index 28a647b02..da9c61103 100644 --- a/java/src/com/android/inputmethod/research/ResearchLogger.java +++ b/java/src/com/android/inputmethod/research/ResearchLogger.java @@ -102,6 +102,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG; private static final boolean DEBUG_REPLAY_AFTER_FEEDBACK = false && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG; + // Whether the TextView contents are logged at the end of the session. true will disclose + // private info. + private static final boolean LOG_FULL_TEXTVIEW_CONTENTS = false + && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG; // Whether the feedback dialog preserves the editable text across invocations. Should be false // for normal research builds so users do not have to delete the same feedback string they // entered earlier. Should be true for builds internal to a development team so when the text @@ -164,6 +168,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang // U+E001 is in the "private-use area" /* package for test */ static final String WORD_REPLACEMENT_STRING = "\uE001"; protected static final int SUSPEND_DURATION_IN_MINUTES = 1; + // set when LatinIME should ignore an onUpdateSelection() callback that + // arises from operations in this class + private static boolean sLatinIMEExpectingUpdateSelection = false; // used to check whether words are not unique private Suggest mSuggest; @@ -1119,6 +1126,12 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang new Object[] { applicationSpecifiedCompletions }); } + public static boolean getAndClearLatinIMEExpectingUpdateSelection() { + boolean returnValue = sLatinIMEExpectingUpdateSelection; + sLatinIMEExpectingUpdateSelection = false; + return returnValue; + } + /** * The IME is finishing; it is either being destroyed, or is about to be hidden. * @@ -1136,12 +1149,51 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang // if called from finishViews(), which is called from hideWindow() and onDestroy(). These // are the situations in which we want to finish up the researchLog. if (ic != null && !finishingInput) { + final boolean isTextTruncated; + final String text; + if (LOG_FULL_TEXTVIEW_CONTENTS) { + // Capture the TextView contents. This will trigger onUpdateSelection(), so we + // set sLatinIMEExpectingUpdateSelection so that when onUpdateSelection() is called, + // it can tell that it was generated by the logging code, and not by the user, and + // therefore keep user-visible state as is. + ic.beginBatchEdit(); + ic.performContextMenuAction(android.R.id.selectAll); + CharSequence charSequence = ic.getSelectedText(0); + if (savedSelectionStart != -1 && savedSelectionEnd != -1) { + ic.setSelection(savedSelectionStart, savedSelectionEnd); + } + ic.endBatchEdit(); + sLatinIMEExpectingUpdateSelection = true; + if (TextUtils.isEmpty(charSequence)) { + isTextTruncated = false; + text = ""; + } else { + if (charSequence.length() > MAX_INPUTVIEW_LENGTH_TO_CAPTURE) { + int length = MAX_INPUTVIEW_LENGTH_TO_CAPTURE; + // do not cut in the middle of a supplementary character + final char c = charSequence.charAt(length - 1); + if (Character.isHighSurrogate(c)) { + length--; + } + final CharSequence truncatedCharSequence = charSequence.subSequence(0, + length); + isTextTruncated = true; + text = truncatedCharSequence.toString(); + } else { + isTextTruncated = false; + text = charSequence.toString(); + } + } + } else { + isTextTruncated = true; + text = ""; + } final ResearchLogger researchLogger = getInstance(); // Assume that OUTPUT_ENTIRE_BUFFER is only true when we don't care about privacy (e.g. // during a live user test), so the normal isPotentiallyPrivate and // isPotentiallyRevealing flags do not apply researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONFINISHINPUTVIEWINTERNAL, - true /* isTextTruncated */, "" /* text */); + isTextTruncated, text); researchLogger.commitCurrentLogUnit(); getInstance().stop(); } @@ -1161,7 +1213,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public static void latinIME_onUpdateSelection(final int lastSelectionStart, final int lastSelectionEnd, final int oldSelStart, final int oldSelEnd, final int newSelStart, final int newSelEnd, final int composingSpanStart, - final int composingSpanEnd, final RichInputConnection connection) { + final int composingSpanEnd, final boolean expectingUpdateSelection, + final boolean expectingUpdateSelectionFromLogger, + final RichInputConnection connection) { String word = ""; if (connection != null) { TextRange range = connection.getWordRangeAtCursor(WHITESPACE_SEPARATORS, 1); @@ -1173,8 +1227,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final String scrubbedWord = researchLogger.scrubWord(word); researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONUPDATESELECTION, lastSelectionStart, lastSelectionEnd, oldSelStart, oldSelEnd, newSelStart, newSelEnd, - composingSpanStart, composingSpanEnd, false /* expectingUpdateSelection */, - false /* expectingUpdateSelectionFromLogger */, scrubbedWord); + composingSpanStart, composingSpanEnd, expectingUpdateSelection, + expectingUpdateSelectionFromLogger, scrubbedWord); } /** @@ -1357,9 +1411,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final LogStatement LOGSTATEMENT_MAINKEYBOARDVIEW_SETKEYBOARD = new LogStatement("MainKeyboardViewSetKeyboard", false, false, "elementId", "locale", "orientation", "width", "modeName", "action", "navigateNext", - "navigatePrevious", "clobberSettingsKey", "passwordInput", - "supportsSwitchingToShortcutIme", "hasShortcutKey", "languageSwitchKeyEnabled", - "isMultiLine", "tw", "th", + "navigatePrevious", "clobberSettingsKey", "passwordInput", "shortcutKeyEnabled", + "hasShortcutKey", "languageSwitchKeyEnabled", "isMultiLine", "tw", "th", "keys"); public static void mainKeyboardView_setKeyboard(final Keyboard keyboard, final int orientation) { @@ -1372,7 +1425,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang kid.mLocale + ":" + kid.mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET), orientation, kid.mWidth, KeyboardId.modeName(kid.mMode), kid.imeAction(), kid.navigateNext(), kid.navigatePrevious(), kid.mClobberSettingsKey, - isPasswordView, kid.mSupportsSwitchingToShortcutIme, kid.mHasShortcutKey, + isPasswordView, kid.mShortcutKeyEnabled, kid.mHasShortcutKey, kid.mLanguageSwitchKeyEnabled, kid.isMultiLine(), keyboard.mOccupiedWidth, keyboard.mOccupiedHeight, keyboard.getKeys()); } |