aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.pngbin506 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_lmp.9.pngbin0 -> 135 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_lmp.9.pngbin639 -> 130 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.pngbin972 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_lmp.9.pngbin537 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_lmp.9.pngbin655 -> 138 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.pngbin1440 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_lmp.9.pngbin670 -> 130 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.pngbin505 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.pngbin301 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.pngbin835 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_light_pressed_lmp.9.pngbin517 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_suggestion_pressed.9.pngbin1234 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_mic_holo_dark.pngbin778 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.pngbin458 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_lmp.9.pngbin0 -> 120 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_lmp.9.pngbin453 -> 114 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.pngbin849 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_lmp.9.pngbin380 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_lmp.9.pngbin468 -> 124 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.pngbin1293 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_lmp.9.pngbin458 -> 114 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_light_normal.9.pngbin454 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.pngbin258 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.pngbin717 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_light_pressed_lmp.9.pngbin368 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_suggestion_pressed.9.pngbin11006 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_mic_holo_dark.pngbin590 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_normal.9.pngbin571 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_lmp.9.pngbin0 -> 153 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_lmp.9.pngbin787 -> 149 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed.9.pngbin1007 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_lmp.9.pngbin657 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.pngbin848 -> 159 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on.9.pngbin1486 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.pngbin867 -> 149 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_light_normal.9.pngbin548 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_light_popup_selected.9.pngbin359 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_light_pressed.9.pngbin860 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_lmp.9.pngbin634 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_suggestion_pressed.9.pngbin1266 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_mic_holo_dark.pngbin942 -> 0 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_off_lmp.9.pngbin0 -> 180 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_lmp.9.pngbin1998 -> 182 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_lmp.9.pngbin1861 -> 0 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.pngbin2073 -> 186 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.pngbin2091 -> 182 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_lmp.9.pngbin1799 -> 0 bytes
-rw-r--r--java/res/drawable-xxhdpi/sym_keyboard_mic_holo_dark.pngbin1566 -> 0 bytes
-rw-r--r--java/res/drawable/btn_keyboard_key_functional_lmp.xml4
-rw-r--r--java/res/drawable/btn_keyboard_key_ics.xml6
-rw-r--r--java/res/drawable/btn_keyboard_key_klp.xml6
-rw-r--r--java/res/drawable/btn_keyboard_key_lmp.xml20
-rw-r--r--java/res/drawable/btn_keyboard_spacebar_lmp.xml4
-rw-r--r--java/res/drawable/btn_suggestion_lmp.xml2
-rw-r--r--java/res/layout/suggestions_strip.xml1
-rw-r--r--java/res/values-km-rKH/strings.xml18
-rw-r--r--java/res/values/attrs.xml22
-rw-r--r--java/res/values/colors.xml17
-rw-r--r--java/res/values/config-common.xml2
-rw-r--r--java/res/values/keyboard-icons-lmp.xml6
-rw-r--r--java/res/values/strings-talkback-descriptions.xml12
-rw-r--r--java/res/values/themes-common.xml7
-rw-r--r--java/res/values/themes-ics.xml11
-rw-r--r--java/res/values/themes-klp.xml11
-rw-r--r--java/res/values/themes-lmp.xml27
-rw-r--r--java/res/xml-sw600dp/key_styles_enter.xml50
-rw-r--r--java/res/xml/key_styles_enter.xml50
-rw-r--r--java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java7
-rw-r--r--java/src/com/android/inputmethod/event/MyanmarReordering.java227
-rw-r--r--java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java5
-rw-r--r--java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java486
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java51
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java34
-rw-r--r--java/src/com/android/inputmethod/keyboard/MainKeyboardView.java41
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java4
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/EmojiCategory.java359
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java3
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java1
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/EmojiPalettesAdapter.java147
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java19
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java10
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java4
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java10
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java17
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java2
-rw-r--r--java/src/com/android/inputmethod/latin/settings/SettingsValues.java3
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java5
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java6
-rw-r--r--java/src/com/android/inputmethod/latin/utils/DistracterFilter.java94
-rw-r--r--java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java3
-rw-r--r--native/jni/NativeFileList.mk9
-rw-r--r--native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp39
-rw-r--r--native/jni/src/suggest/core/dictionary/dictionary.cpp7
-rw-r--r--native/jni/src/suggest/core/dictionary/dictionary.h4
-rw-r--r--native/jni/src/suggest/core/dictionary/property/word_property.cpp15
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info.cpp2
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info_state_utils.h2
-rw-r--r--native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h4
-rw-r--r--native/jni/src/suggest/core/result/suggestion_results.cpp12
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.cpp (renamed from native/jni/src/suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.cpp)2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h (renamed from native/jni/src/suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.h)0
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp6
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h5
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h5
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h3
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.cpp (renamed from native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.cpp)4
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h (renamed from native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.h)0
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v2/bigram/bigram_list_policy.h (renamed from native/jni/src/suggest/policyimpl/dictionary/bigram/bigram_list_policy.h)2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp16
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h8
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v2/shortcut/shortcut_list_policy.h (renamed from native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_policy.h)2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.cpp (renamed from native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.cpp)26
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h (renamed from native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h)7
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h (renamed from native/jni/src/suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h)2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp1
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp15
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp22
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h8
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp4
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp14
-rw-r--r--native/jni/src/utils/char_utils.cpp3
-rw-r--r--native/jni/src/utils/char_utils.h7
-rw-r--r--native/jni/src/utils/jni_data_utils.h12
-rw-r--r--tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java10
-rw-r--r--tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java85
-rw-r--r--tests/src/com/android/inputmethod/latin/DistracterFilterTest.java73
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java232
-rw-r--r--tests/src/com/android/inputmethod/latin/InputTestsBase.java13
-rw-r--r--tests/src/com/android/inputmethod/latin/LatinImeStressTests.java6
132 files changed, 1748 insertions, 757 deletions
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png
deleted file mode 100644
index bc130cab6..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_lmp.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_lmp.9.png
new file mode 100644
index 000000000..44308bfd8
--- /dev/null
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_lmp.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
index 814e40235..674783d7d 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png
deleted file mode 100644
index af5ea6bd2..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_lmp.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_lmp.9.png
deleted file mode 100644
index 90abe3940..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
index 48eeb3f54..96b625bd6 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png
deleted file mode 100644
index fc7ba2aeb..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
index 71e0683cd..20e53c2e5 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png
deleted file mode 100644
index 005c4e498..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png
deleted file mode 100644
index 9a07acd91..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png
deleted file mode 100644
index be420a7af..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_lmp.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_lmp.9.png
deleted file mode 100644
index 6768241a7..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_suggestion_pressed.9.png b/java/res/drawable-hdpi/btn_suggestion_pressed.9.png
deleted file mode 100644
index 7acceaee7..000000000
--- a/java/res/drawable-hdpi/btn_suggestion_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_mic_holo_dark.png b/java/res/drawable-hdpi/sym_keyboard_mic_holo_dark.png
deleted file mode 100644
index 3c5469403..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_mic_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.png
deleted file mode 100644
index 49329f094..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_lmp.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_lmp.9.png
new file mode 100644
index 000000000..837df83ce
--- /dev/null
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_lmp.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
index b7b2dca43..977265214 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.png
deleted file mode 100644
index c6876f76e..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_lmp.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_lmp.9.png
deleted file mode 100644
index 4a92b80dd..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
index 72125a065..d21363316 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png
deleted file mode 100644
index 2bb7b64f4..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
index 82413d4cc..6d20c540b 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_normal.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_normal.9.png
deleted file mode 100644
index f5ce40cf6..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png
deleted file mode 100644
index ca73b9249..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png
deleted file mode 100644
index 73f2006d4..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_lmp.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_lmp.9.png
deleted file mode 100644
index 049385984..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_suggestion_pressed.9.png b/java/res/drawable-mdpi/btn_suggestion_pressed.9.png
deleted file mode 100644
index 02b4e9a53..000000000
--- a/java/res/drawable-mdpi/btn_suggestion_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_mic_holo_dark.png b/java/res/drawable-mdpi/sym_keyboard_mic_holo_dark.png
deleted file mode 100644
index 5e58866a7..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_mic_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal.9.png
deleted file mode 100644
index d0090a305..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_lmp.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_lmp.9.png
new file mode 100644
index 000000000..eeb447cc3
--- /dev/null
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_lmp.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
index 20251a000..624ba8c27 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed.9.png
deleted file mode 100644
index a932249a8..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_lmp.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_lmp.9.png
deleted file mode 100644
index 84d173967..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
index ee4490eac..2bc16cfeb 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on.9.png
deleted file mode 100644
index 3ca93fdb3..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
index e8124776c..80dedd228 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_normal.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_normal.9.png
deleted file mode 100644
index aa4f44fdd..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_light_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_popup_selected.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_popup_selected.9.png
deleted file mode 100644
index 4539255c2..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_light_popup_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed.9.png
deleted file mode 100644
index 568392444..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_lmp.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_lmp.9.png
deleted file mode 100644
index f770962c3..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_suggestion_pressed.9.png b/java/res/drawable-xhdpi/btn_suggestion_pressed.9.png
deleted file mode 100644
index 41e126a73..000000000
--- a/java/res/drawable-xhdpi/btn_suggestion_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_mic_holo_dark.png b/java/res/drawable-xhdpi/sym_keyboard_mic_holo_dark.png
deleted file mode 100644
index 566ba1fcd..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_mic_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_off_lmp.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_off_lmp.9.png
new file mode 100644
index 000000000..97b049eb0
--- /dev/null
+++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_off_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_lmp.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
index 97f96258e..2e8149709 100644
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
+++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_lmp.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_lmp.9.png
deleted file mode 100644
index dfb16a76b..000000000
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
index bf1d34686..d844b1713 100644
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
+++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
index 962277165..9661f4a6e 100644
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
+++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_lmp.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_lmp.9.png
deleted file mode 100644
index 17144b673..000000000
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xxhdpi/sym_keyboard_mic_holo_dark.png b/java/res/drawable-xxhdpi/sym_keyboard_mic_holo_dark.png
deleted file mode 100644
index f55af308c..000000000
--- a/java/res/drawable-xxhdpi/sym_keyboard_mic_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable/btn_keyboard_key_functional_lmp.xml b/java/res/drawable/btn_keyboard_key_functional_lmp.xml
index 427b8d568..57a835596 100644
--- a/java/res/drawable/btn_keyboard_key_functional_lmp.xml
+++ b/java/res/drawable/btn_keyboard_key_functional_lmp.xml
@@ -17,6 +17,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Functional keys. -->
<item android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_dark_pressed_lmp" />
- <item android:drawable="@android:color/transparent" />
+ android:drawable="@color/key_background_pressed_lmp" />
+ <item android:drawable="@color/key_background_lmp" />
</selector>
diff --git a/java/res/drawable/btn_keyboard_key_ics.xml b/java/res/drawable/btn_keyboard_key_ics.xml
index 9db0eeef4..af14cd51c 100644
--- a/java/res/drawable/btn_keyboard_key_ics.xml
+++ b/java/res/drawable/btn_keyboard_key_ics.xml
@@ -15,12 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <!-- Functional keys. -->
- <item android:state_single="true" android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_dark_pressed_ics" />
- <item android:state_single="true"
- android:drawable="@drawable/btn_keyboard_key_dark_normal_holo" />
-
<!-- Action keys. -->
<item android:state_active="true" android:state_pressed="true"
android:drawable="@drawable/btn_keyboard_key_dark_pressed_ics" />
diff --git a/java/res/drawable/btn_keyboard_key_klp.xml b/java/res/drawable/btn_keyboard_key_klp.xml
index 500e3ea75..56c295f14 100644
--- a/java/res/drawable/btn_keyboard_key_klp.xml
+++ b/java/res/drawable/btn_keyboard_key_klp.xml
@@ -15,12 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <!-- Functional keys. -->
- <item android:state_single="true" android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_dark_pressed_klp" />
- <item android:state_single="true"
- android:drawable="@drawable/btn_keyboard_key_dark_normal_holo" />
-
<!-- Action keys. -->
<item android:state_active="true" android:state_pressed="true"
android:drawable="@drawable/btn_keyboard_key_dark_pressed_klp" />
diff --git a/java/res/drawable/btn_keyboard_key_lmp.xml b/java/res/drawable/btn_keyboard_key_lmp.xml
index fdd19df68..636b6374d 100644
--- a/java/res/drawable/btn_keyboard_key_lmp.xml
+++ b/java/res/drawable/btn_keyboard_key_lmp.xml
@@ -15,34 +15,28 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <!-- Functional keys. -->
- <item android:state_single="true" android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_dark_pressed_lmp" />
- <item android:state_single="true"
- android:drawable="@android:color/transparent" />
-
<!-- Action keys. -->
<item android:state_active="true" android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_dark_pressed_lmp" />
+ android:drawable="@color/key_background_pressed_lmp" />
<item android:state_active="true"
- android:drawable="@android:color/transparent" />
+ android:drawable="@color/key_background_lmp" />
<!-- Toggle keys. Use checkable/checked state. -->
<item android:state_checkable="true" android:state_checked="true" android:state_pressed="true"
android:drawable="@drawable/btn_keyboard_key_dark_pressed_on_lmp" />
<item android:state_checkable="true" android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_dark_pressed_lmp" />
+ android:drawable="@drawable/btn_keyboard_key_dark_pressed_off_lmp" />
<item android:state_checkable="true" android:state_checked="true"
android:drawable="@drawable/btn_keyboard_key_dark_normal_on_lmp" />
<item android:state_checkable="true"
- android:drawable="@android:color/transparent" />
+ android:drawable="@drawable/btn_keyboard_key_dark_normal_off_lmp" />
<!-- Empty background keys. -->
<item android:state_empty="true"
- android:drawable="@android:color/transparent" />
+ android:drawable="@color/key_background_lmp" />
<!-- Normal keys. -->
<item android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_light_pressed_lmp" />
- <item android:drawable="@android:color/transparent" />
+ android:drawable="@color/key_background_pressed_lmp" />
+ <item android:drawable="@color/key_background_lmp" />
</selector>
diff --git a/java/res/drawable/btn_keyboard_spacebar_lmp.xml b/java/res/drawable/btn_keyboard_spacebar_lmp.xml
index 516cb0731..d05972fa1 100644
--- a/java/res/drawable/btn_keyboard_spacebar_lmp.xml
+++ b/java/res/drawable/btn_keyboard_spacebar_lmp.xml
@@ -16,6 +16,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_light_pressed_lmp" />
- <item android:drawable="@android:color/transparent" />
+ android:drawable="@color/key_background_pressed_lmp" />
+ <item android:drawable="@color/key_background_lmp" />
</selector>
diff --git a/java/res/drawable/btn_suggestion_lmp.xml b/java/res/drawable/btn_suggestion_lmp.xml
index c778e236f..5c6b373f7 100644
--- a/java/res/drawable/btn_suggestion_lmp.xml
+++ b/java/res/drawable/btn_suggestion_lmp.xml
@@ -23,5 +23,5 @@
>
<item
android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_popup_selected_lmp" />
+ android:drawable="@color/suggested_word_background_selected_lmp" />
</selector>
diff --git a/java/res/layout/suggestions_strip.xml b/java/res/layout/suggestions_strip.xml
index 36898c890..3d2f07f7b 100644
--- a/java/res/layout/suggestions_strip.xml
+++ b/java/res/layout/suggestions_strip.xml
@@ -71,5 +71,6 @@
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
+ android:contentDescription="@string/spoken_description_mic"
style="?attr/suggestionWordStyle" />
</merge>
diff --git a/java/res/values-km-rKH/strings.xml b/java/res/values-km-rKH/strings.xml
index 519aa44d0..4d7de93c8 100644
--- a/java/res/values-km-rKH/strings.xml
+++ b/java/res/values-km-rKH/strings.xml
@@ -29,7 +29,7 @@
<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="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">"ជម្រើស​សម្រាប់​អ្នក​ជំនាញ"</string>
@@ -39,7 +39,7 @@
<string name="show_language_switch_key_summary" msgid="7343403647474265713">"បង្ហាញ​នៅ​ពេល​ដែល​បើក​ភាសា​បញ្ចូល​ច្រើន"</string>
<string name="sliding_key_input_preview" msgid="6604262359510068370">"បង្ហាញ​ទ្រនិច​បង្ហាញ​ស្លាយ"</string>
<string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"បង្ហាញ​​សញ្ញា​មើល​​ឃើញ​ខណៈ​ពេល​ដែល​រុញ​ពី​ឆ្វេង ឬ​​គ្រាប់​ចុច​​និមិត្ត​សញ្ញា"</string>
- <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"​សោ​លេចឡើង​បោះបង់​ការ​​ពន្យារពេល"</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>
@@ -49,7 +49,7 @@
<string name="use_personalized_dicts" msgid="5167396352105467626">"ការ​ស្នើ​ផ្ទាល់​ខ្លួន"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"រយៈ​ពេល​ចុច​ដកឃ្លា​ពីរដង"</string>
<string name="use_double_space_period_summary" msgid="6532892187247952799">"ប៉ះ​ដកឃ្លា​ពីរ​​ដង​បញ្ចូល​​​រយៈ​ពេល​ដែល​អនុវត្ត​តាម​ដកឃ្លា"</string>
- <string name="auto_cap" msgid="1719746674854628252">"ការ​សរសេរ​ជា​អក្សរ​ធំ​​ស្វ័យប្រវត្តិ"</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>
@@ -60,7 +60,7 @@
<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="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>
@@ -123,7 +123,7 @@
<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_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="4782116251651288054">"ពិត​ជា​ដំឡើង​ឯកសារ​នេះ​សម្រាប់ <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"មាន​កំហុស"</string>
@@ -154,7 +154,7 @@
<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_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>
@@ -170,10 +170,10 @@
<string name="message_updating" msgid="4457761393932375219">"ពិនិត្យមើល​បច្ចុប្បន្នភាព"</string>
<string name="message_loading" msgid="5638680861387748936">"កំពុង​ផ្ទុក..."</string>
<string name="main_dict_description" msgid="3072821352793492143">"វចនានុក្រម​ចម្បង"</string>
- <string name="cancel" msgid="6830980399865683324">"បោះ​បង់"</string>
+ <string name="cancel" msgid="6830980399865683324">"បោះ​បង់​"</string>
<string name="go_to_settings" msgid="3876892339342569259">"ការ​កំណត់"</string>
<string name="install_dict" msgid="180852772562189365">"ដំឡើង"</string>
- <string name="cancel_download_dict" msgid="7843340278507019303">"បោះ​បង់"</string>
+ <string name="cancel_download_dict" msgid="7843340278507019303">"បោះ​បង់​"</string>
<string name="delete_dict" msgid="756853268088330054">"លុប"</string>
<string name="should_download_over_metered_prompt" msgid="1583881200688185508">"ភាសា​ដែល​បាន​ជ្រើស​នៅ​លើ​ឧបករណ៍​ចល័ត​មាន​វចនានុក្រម​អាច​ប្រើ​បាន។&lt;br/&gt; យើង​ផ្ដល់​អនុសាសន៍​ឲ្យ &lt;b&gt;ទាញ​យក&lt;/b&gt; វចនានុក្រម​ភាសា <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> ដើម្បី​បង្កើន​បទពិសោធន៍​វាយ​បញ្ចូល​របស់​អ្នក។&lt;br/&gt; &lt;br/&gt; ការ​ទាញ​យក​អាច​ចំណាយ​ពេល​ប្រហែល​ពីរ​នាទី​នៅ​តាម 3G។ ការ​គិត​ថ្លៃ​អាច​អនុវត្ត​ប្រសិន​បើ​អ្នក​មិន​ប្រើ &lt;b&gt;ផែនការ​ទិន្នន័យ​គ្មាន​ដែន​កំណត់&lt;/b&gt;.&lt;br/&gt; បើ​អ្នក​មិន​ប្រាកដ​​ថា​ផែនការ​ណា​មួយ​ដែល​អ្នក​មាន យើង​ផ្ដល់​អនុសាសន៍​ឲ្យ​​ភ្ជាប់​វ៉ាយហ្វាយ ដើម្បី​ចាប់ផ្ដើម​ទាញ​យក​ដោយ​ស្វ័យ​ប្រវត្តិ។&lt;br/&gt; &lt;br/&gt; ជំនួយ៖ អ្នក​អាច​ទាញ​យក និង​លុប​វចនានុក្រម​ដោយ​ចូល​ទៅ​ &lt;b&gt;ភាសា &amp; ការ​បញ្ចូល&lt;/b&gt; នៅ​ក្នុង​ម៉ឺនុយ &lt;b&gt;ការ​កំណត់&lt;/b&gt; សម្រាប់​ឧបករណ៍​ចល័ត។"</string>
<string name="download_over_metered" msgid="1643065851159409546">"ទាញ​យក​ឥឡូវ​នេះ (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> មេកាបៃ)"</string>
@@ -191,7 +191,7 @@
<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_word_hint" msgid="4902434148985906707">"វាយ​បញ្ចូល​ពាក្យ​"</string>
<string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"ផ្លូវកាត់​ជា​ជម្រើស"</string>
<string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"កែ​ពាក្យ"</string>
<string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"កែ"</string>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 475e92f2e..79cc139a2 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -41,13 +41,16 @@
</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,
+ <!-- Background 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. -->
<attr name="keyBackground" format="reference" />
- <!-- Image for the functional key used in Emoji layout. -->
- <attr name="keyBackgroundEmojiFunctional" format="reference" />
-
+ <!-- Background image for the functional key. This image needs to be a
+ {@link StateListDrawable}, with the following possible states: normal, pressed. -->
+ <attr name="functionalKeyBackground" format="reference" />
+ <!-- Background image for the spacebar. This image needs to be a
+ {@link StateListDrawable}, with the following possible states: normal, pressed. -->
+ <attr name="spacebarBackground" format="reference" />
<!-- Horizontal padding of left/right aligned key label to the edge of the key. -->
<attr name="keyLabelHorizontalPadding" format="dimension" />
<!-- Right padding of hint letter to the edge of the key.-->
@@ -74,9 +77,8 @@
<!-- 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="languageOnSpacebarTextShadowRadius" format="float" />
<attr name="languageOnSpacebarTextShadowColor" format="color" />
- <!-- Background image for the spacebar. -->
- <attr name="spacebarBackground" format="reference" />
<!-- Fadeout animator for spacebar language label. -->
<attr name="languageOnSpacebarFinalAlpha" format="integer" />
<attr name="languageOnSpacebarFadeoutAnimator" format="reference" />
@@ -217,7 +219,12 @@
<attr name="iconSettingsKey" format="reference" />
<attr name="iconSpaceKey" format="reference" />
<attr name="iconEnterKey" format="reference" />
+ <attr name="iconGoKey" format="reference" />
<attr name="iconSearchKey" format="reference" />
+ <attr name="iconSendKey" format="reference" />
+ <attr name="iconNextKey" format="reference" />
+ <attr name="iconDoneKey" format="reference" />
+ <attr name="iconPreviousKey" format="reference" />
<attr name="iconTabKey" format="reference" />
<attr name="iconShortcutKey" format="reference" />
<attr name="iconSpaceKeyForNumberLayout" format="reference" />
@@ -431,6 +438,7 @@
<!-- This should be aligned with KeyboardId.IME_ACTION_* -->
<enum name="actionCustomLabel" value="0x100" />
</attr>
+ <attr name="isIconDefined" format="string" />
<attr name="localeCode" format="string" />
<attr name="languageCode" format="string" />
<attr name="countryCode" format="string" />
diff --git a/java/res/values/colors.xml b/java/res/values/colors.xml
index dabb4d65e..db9a27ae6 100644
--- a/java/res/values/colors.xml
+++ b/java/res/values/colors.xml
@@ -26,7 +26,6 @@
<color name="suggested_word_color_ics">#B233B5E5</color>
<color name="highlight_translucent_color_ics">#9933B5E5</color>
<color name="key_text_color_holo">@android:color/white</color>
- <color name="key_text_shadow_color_holo">@android:color/transparent</color>
<color name="key_text_inactivated_color_holo">#66E0E4E5</color>
<color name="key_hint_letter_color_holo">#80000000</color>
<color name="key_hint_label_color_holo">#A0FFFFFF</color>
@@ -41,11 +40,17 @@
<color name="suggested_word_color_klp">#B2F0F0F0</color>
<color name="highlight_translucent_color_klp">#99E0E0E0</color>
<!-- Color resources for LMP theme. Base color = F0F0F0 -->
- <color name="key_hint_letter_color_lmp">@android:color/white</color>
- <color name="highlight_color_lmp">#FFF0F0F0</color>
- <color name="typed_word_color_lmp">#D8F0F0F0</color>
- <color name="suggested_word_color_lmp">#B2F0F0F0</color>
- <color name="highlight_translucent_color_lmp">#99E0E0E0</color>
+ <color name="key_text_inactive_color_lmp">#808184</color>
+ <color name="key_hint_letter_color_lmp">#808184</color>
+ <color name="highlight_color_lmp">#7FCAC3</color>
+ <color name="typed_word_color_lmp">#D87FCAC3</color>
+ <color name="suggested_word_color_lmp">#B27FCAC3</color>
+ <color name="highlight_translucent_color_lmp">#997FCAC3</color>
+ <color name="keyboard_background_lmp">#384248</color>
+ <color name="key_background_lmp">#384248</color>
+ <color name="key_background_pressed_lmp">#546872</color>
+ <color name="suggestions_strip_background_lmp">#263238</color>
+ <color name="suggested_word_background_selected_lmp">#384248</color>
<!-- Color resources for setup wizard and tutorial -->
<color name="setup_background">#FFEBEBEB</color>
<color name="setup_text_dark">#FF707070</color>
diff --git a/java/res/values/config-common.xml b/java/res/values/config-common.xml
index 1962c0d45..ad27ab427 100644
--- a/java/res/values/config-common.xml
+++ b/java/res/values/config-common.xml
@@ -133,7 +133,7 @@
<integer name="config_gesture_trail_shadow_ratio">-1</integer>
<!-- Common configuration of Emoji keyboard -->
- <dimen name="config_emoji_category_page_id_height">3dp</dimen>
+ <dimen name="config_emoji_category_page_id_height">2dp</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>
diff --git a/java/res/values/keyboard-icons-lmp.xml b/java/res/values/keyboard-icons-lmp.xml
index a9cbabca6..39e0fe306 100644
--- a/java/res/values/keyboard-icons-lmp.xml
+++ b/java/res/values/keyboard-icons-lmp.xml
@@ -26,7 +26,13 @@
<item name="iconSettingsKey">@drawable/sym_keyboard_settings_holo_dark</item>
<item name="iconSpaceKey">@drawable/sym_keyboard_space_holo_dark</item>
<item name="iconEnterKey">@drawable/sym_keyboard_return_holo_dark</item>
+ <!-- TODO: Uncomment those icon definitions once we have those icon assets. -->
+ <!-- <item name="iconGoKey">@drawable/sym_keyboard_go_holo_dark</item> -->
<item name="iconSearchKey">@drawable/sym_keyboard_search_holo_dark</item>
+ <!-- <item name="iconSendKey">@drawable/sym_keyboard_send_holo_dark</item> -->
+ <!-- <item name="iconNextKey">@drawable/sym_keyboard_next_holo_dark</item> -->
+ <!-- <item name="iconDoneKey">@drawable/sym_keyboard_done_holo_dark</item> -->
+ <!-- <item name="iconPreviousKey">@drawable/sym_keyboard_previous_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="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space_holo_dark</item>
diff --git a/java/res/values/strings-talkback-descriptions.xml b/java/res/values/strings-talkback-descriptions.xml
index 4ffca10c8..80406d02f 100644
--- a/java/res/values/strings-talkback-descriptions.xml
+++ b/java/res/values/strings-talkback-descriptions.xml
@@ -35,10 +35,14 @@
<string name="spoken_description_unknown">Key code %d</string>
<!-- Spoken description for the "Shift" keyboard key when "Shift" is off. -->
<string name="spoken_description_shift">Shift</string>
+ <!-- Spoken description for the "Shift" keyboard key in symbols mode. -->
+ <string name="spoken_description_symbols_shift">More symbols</string>
<!-- Spoken description for the "Shift" keyboard key when "Shift" is on. -->
- <string name="spoken_description_shift_shifted">Shift on (tap to disable)</string>
+ <string name="spoken_description_shift_shifted">Shift</string>
+ <!-- Spoken description for the "Shift" keyboard key in 2nd symbols (a.k.a. symbols shift) mode. -->
+ <string name="spoken_description_symbols_shift_shifted">Symbols</string>
<!-- Spoken description for the "Shift" keyboard key when "Caps lock" is on. -->
- <string name="spoken_description_caps_lock">Caps lock on (tap to disable)</string>
+ <string name="spoken_description_caps_lock">Shift</string>
<!-- Spoken description for the "Delete" keyboard key. -->
<string name="spoken_description_delete">Delete</string>
<!-- Spoken description for the "To Symbol" keyboard key. -->
@@ -76,8 +80,8 @@
<string name="spoken_description_shiftmode_locked">Caps lock enabled</string>
<!-- Spoken feedback after changing to the symbols keyboard. -->
<string name="spoken_description_mode_symbol">Symbols mode</string>
- <!-- Spoken feedback after changing to the symbols shift keyboard. -->
- <string name="spoken_description_mode_symbol_shift">Symbols shift mode</string>
+ <!-- Spoken feedback after changing to the 2nd symbols (a.k.a. symbols shift) keyboard. -->
+ <string name="spoken_description_mode_symbol_shift">More symbols mode</string>
<!-- Spoken feedback after changing to the alphanumeric keyboard. -->
<string name="spoken_description_mode_alpha">Letters mode</string>
<!-- Spoken feedback after changing to the phone dialer keyboard. -->
diff --git a/java/res/values/themes-common.xml b/java/res/values/themes-common.xml
index 76abb10fb..df26fb3b4 100644
--- a/java/res/values/themes-common.xml
+++ b/java/res/values/themes-common.xml
@@ -109,12 +109,7 @@
<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
- name="EmojiPalettesView"
- parent="KeyboardView"
- >
- <item name="emojiTabLabelColor">@color/emoji_tab_label_color_holo</item>
- </style>
+ <style name="EmojiPalettesView" />
<style name="MoreKeysKeyboard" />
<style
name="MoreKeysKeyboardView"
diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml
index 616dbd82c..560cfc505 100644
--- a/java/res/values/themes-ics.xml
+++ b/java/res/values/themes-ics.xml
@@ -48,6 +48,8 @@
>
<item name="android:background">@drawable/keyboard_background_holo</item>
<item name="keyBackground">@drawable/btn_keyboard_key_ics</item>
+ <item name="functionalKeyBackground">@drawable/btn_keyboard_key_functional_ics</item>
+ <item name="spacebarBackground">@drawable/btn_keyboard_spacebar_ics</item>
<item name="keyTypeface">bold</item>
<item name="keyTextColor">@color/key_text_color_holo</item>
<item name="keyTextInactivatedColor">@color/key_text_inactivated_color_holo</item>
@@ -56,8 +58,8 @@
<item name="keyShiftedLetterHintInactivatedColor">@color/key_shifted_letter_hint_inactivated_color_holo</item>
<item name="keyShiftedLetterHintActivatedColor">@color/key_shifted_letter_hint_activated_color_holo</item>
<item name="keyPreviewTextColor">@color/key_text_color_holo</item>
- <item name="keyTextShadowColor">@color/key_text_shadow_color_holo</item>
- <item name="keyTextShadowRadius">0.0</item>
+ <!-- A negative value to disable key text shadow layer. -->
+ <item name="keyTextShadowRadius">-1.0</item>
</style>
<style
name="MainKeyboardView.ICS"
@@ -71,8 +73,8 @@
<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="languageOnSpacebarTextShadowRadius">1.0</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"
@@ -84,9 +86,8 @@
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style
name="EmojiPalettesView.ICS"
- parent="KeyboardView.ICS"
+ parent="MainKeyboardView.ICS"
>
- <item name="keyBackgroundEmojiFunctional">@drawable/btn_keyboard_key_functional_ics</item>
<item name="emojiTabLabelColor">@color/emoji_tab_label_color_holo</item>
</style>
<style
diff --git a/java/res/values/themes-klp.xml b/java/res/values/themes-klp.xml
index 9bb3d79a7..453e5cbce 100644
--- a/java/res/values/themes-klp.xml
+++ b/java/res/values/themes-klp.xml
@@ -48,6 +48,8 @@
>
<item name="android:background">@drawable/keyboard_background_holo</item>
<item name="keyBackground">@drawable/btn_keyboard_key_klp</item>
+ <item name="functionalKeyBackground">@drawable/btn_keyboard_key_functional_klp</item>
+ <item name="spacebarBackground">@drawable/btn_keyboard_spacebar_klp</item>
<item name="keyTypeface">bold</item>
<item name="keyTextColor">@color/key_text_color_holo</item>
<item name="keyTextInactivatedColor">@color/key_text_inactivated_color_holo</item>
@@ -56,8 +58,8 @@
<item name="keyShiftedLetterHintInactivatedColor">@color/key_shifted_letter_hint_inactivated_color_holo</item>
<item name="keyShiftedLetterHintActivatedColor">@color/key_shifted_letter_hint_activated_color_holo</item>
<item name="keyPreviewTextColor">@color/key_text_color_holo</item>
- <item name="keyTextShadowColor">@color/key_text_shadow_color_holo</item>
- <item name="keyTextShadowRadius">0.0</item>
+ <!-- A negative value to disable key text shadow layer. -->
+ <item name="keyTextShadowRadius">-1.0</item>
</style>
<style
name="MainKeyboardView.KLP"
@@ -71,8 +73,8 @@
<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="languageOnSpacebarTextShadowRadius">1.0</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"
@@ -84,9 +86,8 @@
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style
name="EmojiPalettesView.KLP"
- parent="KeyboardView.KLP"
+ parent="MainKeyboardView.KLP"
>
- <item name="keyBackgroundEmojiFunctional">@drawable/btn_keyboard_key_functional_klp</item>
<item name="emojiTabLabelColor">@color/emoji_tab_label_color_holo</item>
</style>
<style
diff --git a/java/res/values/themes-lmp.xml b/java/res/values/themes-lmp.xml
index 773da196d..a9b8a93cc 100644
--- a/java/res/values/themes-lmp.xml
+++ b/java/res/values/themes-lmp.xml
@@ -35,7 +35,7 @@
parent="Keyboard"
>
<!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] -->
- <item name="themeId">0</item>
+ <item name="themeId">3</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>
@@ -46,18 +46,20 @@
name="KeyboardView.LMP"
parent="KeyboardView"
>
- <item name="android:background">@drawable/keyboard_background_holo</item>
+ <item name="android:background">@color/keyboard_background_lmp</item>
<item name="keyBackground">@drawable/btn_keyboard_key_lmp</item>
+ <item name="functionalKeyBackground">@drawable/btn_keyboard_key_functional_lmp</item>
+ <item name="spacebarBackground">@drawable/btn_keyboard_spacebar_lmp</item>
<item name="keyTypeface">bold</item>
<item name="keyTextColor">@color/key_text_color_holo</item>
- <item name="keyTextInactivatedColor">@color/key_text_inactivated_color_holo</item>
+ <item name="keyTextInactivatedColor">@color/key_text_inactive_color_lmp</item>
<item name="keyHintLetterColor">@color/key_hint_letter_color_lmp</item>
- <item name="keyHintLabelColor">@color/key_hint_label_color_holo</item>
- <item name="keyShiftedLetterHintInactivatedColor">@color/key_shifted_letter_hint_inactivated_color_holo</item>
- <item name="keyShiftedLetterHintActivatedColor">@color/key_shifted_letter_hint_activated_color_holo</item>
+ <item name="keyHintLabelColor">@color/key_text_inactive_color_lmp</item>
+ <item name="keyShiftedLetterHintInactivatedColor">@color/key_text_inactive_color_lmp</item>
+ <item name="keyShiftedLetterHintActivatedColor">@color/key_text_color_holo</item>
<item name="keyPreviewTextColor">@color/key_text_color_holo</item>
- <item name="keyTextShadowColor">@color/key_text_shadow_color_holo</item>
- <item name="keyTextShadowRadius">0.0</item>
+ <!-- A negative value to disable key text shadow layer. -->
+ <item name="keyTextShadowRadius">-1.0</item>
</style>
<style
name="MainKeyboardView.LMP"
@@ -70,9 +72,9 @@
<item name="slidingKeyInputPreviewColor">@color/highlight_translucent_color_lmp</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_lmp</item>
+ <item name="languageOnSpacebarTextColor">@color/key_text_inactive_color_lmp</item>
+ <!-- A negative value to disable text shadow layer. -->
+ <item name="languageOnSpacebarTextShadowRadius">-1.0</item>
</style>
<style
name="KeyPreviewTextView.LMP"
@@ -84,9 +86,8 @@
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style
name="EmojiPalettesView.LMP"
- parent="KeyboardView.LMP"
+ parent="MainKeyboardView.LMP"
>
- <item name="keyBackgroundEmojiFunctional">@drawable/btn_keyboard_key_functional_lmp</item>
<item name="emojiTabLabelColor">@color/emoji_tab_label_color_holo</item>
</style>
<style
diff --git a/java/res/xml-sw600dp/key_styles_enter.xml b/java/res/xml-sw600dp/key_styles_enter.xml
index 0699e4527..99ac10873 100644
--- a/java/res/xml-sw600dp/key_styles_enter.xml
+++ b/java/res/xml-sw600dp/key_styles_enter.xml
@@ -117,6 +117,16 @@
</case>
<case
latin:imeAction="actionGo"
+ latin:isIconDefined="go_key"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keySpec="!icon/go_key|!code/key_enter"
+ latin:backgroundType="action"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionGo"
>
<key-style
latin:styleName="enterKeyStyle"
@@ -126,6 +136,16 @@
</case>
<case
latin:imeAction="actionNext"
+ latin:isIconDefined="next_key"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keySpec="!icon/next_key|!code/key_enter"
+ latin:backgroundType="action"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionNext"
>
<key-style
latin:styleName="enterKeyStyle"
@@ -135,6 +155,16 @@
</case>
<case
latin:imeAction="actionPrevious"
+ latin:isIconDefined="previous_key"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keySpec="!icon/previous_key|!code/key_enter"
+ latin:backgroundType="action"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionPrevious"
>
<key-style
latin:styleName="enterKeyStyle"
@@ -144,6 +174,16 @@
</case>
<case
latin:imeAction="actionDone"
+ latin:isIconDefined="done_key"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keySpec="!icon/done_key|!code/key_enter"
+ latin:backgroundType="action"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionDone"
>
<key-style
latin:styleName="enterKeyStyle"
@@ -153,6 +193,16 @@
</case>
<case
latin:imeAction="actionSend"
+ latin:isIconDefined="send_key"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keySpec="!icon/send_key|!code/key_enter"
+ latin:backgroundType="action"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionSend"
>
<key-style
latin:styleName="enterKeyStyle"
diff --git a/java/res/xml/key_styles_enter.xml b/java/res/xml/key_styles_enter.xml
index acb27abb1..8bba136bd 100644
--- a/java/res/xml/key_styles_enter.xml
+++ b/java/res/xml/key_styles_enter.xml
@@ -284,6 +284,16 @@
</case>
<case
latin:imeAction="actionGo"
+ latin:isIconDefined="go_key"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keySpec="!icon/go_key|!code/key_enter"
+ latin:backgroundType="action"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionGo"
>
<key-style
latin:styleName="enterKeyStyle"
@@ -293,6 +303,16 @@
</case>
<case
latin:imeAction="actionNext"
+ latin:isIconDefined="next_key"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keySpec="!icon/next_key|!code/key_enter"
+ latin:backgroundType="action"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionNext"
>
<key-style
latin:styleName="enterKeyStyle"
@@ -302,6 +322,16 @@
</case>
<case
latin:imeAction="actionPrevious"
+ latin:isIconDefined="previous_key"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keySpec="!icon/previous_key|!code/key_enter"
+ latin:backgroundType="action"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionPrevious"
>
<key-style
latin:styleName="enterKeyStyle"
@@ -311,6 +341,16 @@
</case>
<case
latin:imeAction="actionDone"
+ latin:isIconDefined="done_key"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keySpec="!icon/done_key|!code/key_enter"
+ latin:backgroundType="action"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionDone"
>
<key-style
latin:styleName="enterKeyStyle"
@@ -320,6 +360,16 @@
</case>
<case
latin:imeAction="actionSend"
+ latin:isIconDefined="send_key"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keySpec="!icon/send_key|!code/key_enter"
+ latin:backgroundType="action"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionSend"
>
<key-style
latin:styleName="enterKeyStyle"
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index 2e6649bf2..0499a3456 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -189,9 +189,14 @@ public final class KeyCodeDescriptionMapper {
break;
case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
- case KeyboardId.ELEMENT_SYMBOLS_SHIFTED:
resId = R.string.spoken_description_shift_shifted;
break;
+ case KeyboardId.ELEMENT_SYMBOLS:
+ resId = R.string.spoken_description_symbols_shift;
+ break;
+ case KeyboardId.ELEMENT_SYMBOLS_SHIFTED:
+ resId = R.string.spoken_description_symbols_shift_shifted;
+ break;
default:
resId = R.string.spoken_description_shift;
}
diff --git a/java/src/com/android/inputmethod/event/MyanmarReordering.java b/java/src/com/android/inputmethod/event/MyanmarReordering.java
index 0831b63ec..da0228bd2 100644
--- a/java/src/com/android/inputmethod/event/MyanmarReordering.java
+++ b/java/src/com/android/inputmethod/event/MyanmarReordering.java
@@ -16,23 +16,244 @@
package com.android.inputmethod.event;
+import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+
import java.util.ArrayList;
+import java.util.Arrays;
/**
* A combiner that reorders input for Myanmar.
*/
public class MyanmarReordering implements Combiner {
+ // U+1031 MYANMAR VOWEL SIGN E
+ private final static int VOWEL_E = 0x1031; // Code point for vowel E that we need to reorder
+ // U+200C ZERO WIDTH NON-JOINER
+ // U+200B ZERO WIDTH SPACE
+ private final static int ZERO_WIDTH_NON_JOINER = 0x200B; // should be 0x200C
+
+ private final ArrayList<Event> mCurrentEvents = CollectionUtils.newArrayList();
+
+ // List of consonants :
+ // U+1000 MYANMAR LETTER KA
+ // U+1001 MYANMAR LETTER KHA
+ // U+1002 MYANMAR LETTER GA
+ // U+1003 MYANMAR LETTER GHA
+ // U+1004 MYANMAR LETTER NGA
+ // U+1005 MYANMAR LETTER CA
+ // U+1006 MYANMAR LETTER CHA
+ // U+1007 MYANMAR LETTER JA
+ // U+1008 MYANMAR LETTER JHA
+ // U+1009 MYANMAR LETTER NYA
+ // U+100A MYANMAR LETTER NNYA
+ // U+100B MYANMAR LETTER TTA
+ // U+100C MYANMAR LETTER TTHA
+ // U+100D MYANMAR LETTER DDA
+ // U+100E MYANMAR LETTER DDHA
+ // U+100F MYANMAR LETTER NNA
+ // U+1010 MYANMAR LETTER TA
+ // U+1011 MYANMAR LETTER THA
+ // U+1012 MYANMAR LETTER DA
+ // U+1013 MYANMAR LETTER DHA
+ // U+1014 MYANMAR LETTER NA
+ // U+1015 MYANMAR LETTER PA
+ // U+1016 MYANMAR LETTER PHA
+ // U+1017 MYANMAR LETTER BA
+ // U+1018 MYANMAR LETTER BHA
+ // U+1019 MYANMAR LETTER MA
+ // U+101A MYANMAR LETTER YA
+ // U+101B MYANMAR LETTER RA
+ // U+101C MYANMAR LETTER LA
+ // U+101D MYANMAR LETTER WA
+ // U+101E MYANMAR LETTER SA
+ // U+101F MYANMAR LETTER HA
+ // U+1020 MYANMAR LETTER LLA
+ // U+103F MYANMAR LETTER GREAT SA
+ private static boolean isConsonant(final int codePoint) {
+ return (codePoint >= 0x1000 && codePoint <= 0x1020) || 0x103F == codePoint;
+ }
+
+ // List of medials :
+ // U+103B MYANMAR CONSONANT SIGN MEDIAL YA
+ // U+103C MYANMAR CONSONANT SIGN MEDIAL RA
+ // U+103D MYANMAR CONSONANT SIGN MEDIAL WA
+ // U+103E MYANMAR CONSONANT SIGN MEDIAL HA
+ // U+105E MYANMAR CONSONANT SIGN MON MEDIAL NA
+ // U+105F MYANMAR CONSONANT SIGN MON MEDIAL MA
+ // U+1060 MYANMAR CONSONANT SIGN MON MEDIAL LA
+ // U+1082 MYANMAR CONSONANT SIGN SHAN MEDIAL WA
+ private static int[] MEDIAL_LIST = { 0x103B, 0x103C, 0x103D, 0x103E,
+ 0x105E, 0x105F, 0x1060, 0x1082};
+ private static boolean isMedial(final int codePoint) {
+ return Arrays.binarySearch(MEDIAL_LIST, codePoint) >= 0;
+ }
+
+ private static boolean isConsonantOrMedial(final int codePoint) {
+ return isConsonant(codePoint) || isMedial(codePoint);
+ }
+
+ private Event getLastEvent() {
+ final int size = mCurrentEvents.size();
+ if (size <= 0) {
+ return null;
+ }
+ return mCurrentEvents.get(size - 1);
+ }
+
+ private CharSequence getCharSequence() {
+ final StringBuilder s = new StringBuilder();
+ for (final Event e : mCurrentEvents) {
+ s.appendCodePoint(e.mCodePoint);
+ }
+ return s;
+ }
+
+ /**
+ * Clears the currently combining stream of events and returns the resulting software text
+ * event corresponding to the stream. Optionally adds a new event to the cleared stream.
+ * @param newEvent the new event to add to the stream. null if none.
+ * @return the resulting software text event. Null if none.
+ */
+ private Event clearAndGetResultingEvent(final Event newEvent) {
+ final CharSequence combinedText;
+ if (mCurrentEvents.size() > 0) {
+ combinedText = getCharSequence();
+ mCurrentEvents.clear();
+ } else {
+ combinedText = null;
+ }
+ if (null != newEvent) {
+ mCurrentEvents.add(newEvent);
+ }
+ return null == combinedText ? null
+ : Event.createSoftwareTextEvent(combinedText, Event.NOT_A_KEY_CODE);
+ }
+
@Override
- public Event processEvent(ArrayList<Event> previousEvents, Event event) {
- return event;
+ public Event processEvent(ArrayList<Event> previousEvents, Event newEvent) {
+ final int codePoint = newEvent.mCodePoint;
+ if (VOWEL_E == codePoint) {
+ final Event lastEvent = getLastEvent();
+ if (null == lastEvent) {
+ mCurrentEvents.add(newEvent);
+ return null;
+ } else if (isConsonantOrMedial(lastEvent.mCodePoint)) {
+ final Event resultingEvent = clearAndGetResultingEvent(null);
+ mCurrentEvents.add(Event.createSoftwareKeypressEvent(ZERO_WIDTH_NON_JOINER,
+ Event.NOT_A_KEY_CODE,
+ Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
+ false /* isKeyRepeat */));
+ mCurrentEvents.add(newEvent);
+ return resultingEvent;
+ } else { // VOWEL_E == lastCodePoint. But if that was anything else this is correct too.
+ return clearAndGetResultingEvent(newEvent);
+ }
+ } if (isConsonant(codePoint)) {
+ final Event lastEvent = getLastEvent();
+ if (null == lastEvent) {
+ mCurrentEvents.add(newEvent);
+ return null;
+ } else if (VOWEL_E == lastEvent.mCodePoint) {
+ final int eventSize = mCurrentEvents.size();
+ if (eventSize >= 2
+ && mCurrentEvents.get(eventSize - 2).mCodePoint == ZERO_WIDTH_NON_JOINER) {
+ // We have a ZWJN before a vowel E. We need to remove the ZWNJ and then
+ // reorder the vowel with respect to the consonant.
+ mCurrentEvents.remove(eventSize - 1);
+ mCurrentEvents.remove(eventSize - 2);
+ mCurrentEvents.add(newEvent);
+ mCurrentEvents.add(lastEvent);
+ return null;
+ }
+ // If there is already a consonant, then we are starting a new syllable.
+ for (int i = eventSize - 2; i >= 0; --i) {
+ if (isConsonant(mCurrentEvents.get(i).mCodePoint)) {
+ return clearAndGetResultingEvent(newEvent);
+ }
+ }
+ // If we come here, we didn't have a consonant so we reorder
+ mCurrentEvents.remove(eventSize - 1);
+ mCurrentEvents.add(newEvent);
+ mCurrentEvents.add(lastEvent);
+ return null;
+ } else { // lastCodePoint is a consonant/medial. But if it's something else it's fine
+ return clearAndGetResultingEvent(newEvent);
+ }
+ } else if (isMedial(codePoint)) {
+ final Event lastEvent = getLastEvent();
+ if (null == lastEvent) {
+ mCurrentEvents.add(newEvent);
+ return null;
+ } else if (VOWEL_E == lastEvent.mCodePoint) {
+ final int eventSize = mCurrentEvents.size();
+ // If there is already a consonant, then we are in the middle of a syllable, and we
+ // need to reorder.
+ boolean hasConsonant = false;
+ for (int i = eventSize - 2; i >= 0; --i) {
+ if (isConsonant(mCurrentEvents.get(i).mCodePoint)) {
+ hasConsonant = true;
+ break;
+ }
+ }
+ if (hasConsonant) {
+ mCurrentEvents.remove(eventSize - 1);
+ mCurrentEvents.add(newEvent);
+ mCurrentEvents.add(lastEvent);
+ return null;
+ }
+ // Otherwise, we just commit everything.
+ return clearAndGetResultingEvent(null);
+ } else { // lastCodePoint is a consonant/medial. But if it's something else it's fine
+ return clearAndGetResultingEvent(newEvent);
+ }
+ } else if (Constants.CODE_DELETE == newEvent.mKeyCode) {
+ final Event lastEvent = getLastEvent();
+ final int eventSize = mCurrentEvents.size();
+ if (null != lastEvent) {
+ if (VOWEL_E == lastEvent.mCodePoint) {
+ // We have a VOWEL_E at the end. There are four cases.
+ // - The vowel is the only code point in the buffer. Remove it.
+ // - The vowel is preceded by a ZWNJ. Remove both vowel E and ZWNJ.
+ // - The vowel is preceded by a consonant/medial, remove the consonant/medial.
+ // - In all other cases, it's strange, so just remove the last code point.
+ if (eventSize <= 1) {
+ mCurrentEvents.clear();
+ } else { // eventSize >= 2
+ final int previousCodePoint = mCurrentEvents.get(eventSize - 2).mCodePoint;
+ if (previousCodePoint == ZERO_WIDTH_NON_JOINER) {
+ mCurrentEvents.remove(eventSize - 1);
+ mCurrentEvents.remove(eventSize - 2);
+ } else if (isConsonantOrMedial(previousCodePoint)) {
+ mCurrentEvents.remove(eventSize - 2);
+ } else {
+ mCurrentEvents.remove(eventSize - 1);
+ }
+ }
+ return null;
+ } else if (eventSize > 0) {
+ mCurrentEvents.remove(eventSize - 1);
+ return null;
+ }
+ }
+ }
+ // This character is not part of the combining scheme, so we should reset everything.
+ if (mCurrentEvents.size() > 0) {
+ // If we have events in flight, then add the new event and return the resulting event.
+ mCurrentEvents.add(newEvent);
+ return clearAndGetResultingEvent(null);
+ } else {
+ // If we don't have any events in flight, then just pass this one through.
+ return newEvent;
+ }
}
@Override
public CharSequence getCombiningStateFeedback() {
- return "";
+ return getCharSequence();
}
@Override
public void reset() {
+ mCurrentEvents.clear();
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java b/java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java
index d56a3cf25..9922f9024 100644
--- a/java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java
+++ b/java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java
@@ -24,8 +24,9 @@ import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.LinearLayout;
-public class EmojiCategoryPageIndicatorView extends LinearLayout {
- private static final float BOTTOM_MARGIN_RATIO = 0.66f;
+//TODO: Move this class to com.android.inputmethod.emoji package.
+public final class EmojiCategoryPageIndicatorView extends LinearLayout {
+ private static final float BOTTOM_MARGIN_RATIO = 1.0f;
private final Paint mPaint = new Paint();
private int mCategoryPageSize = 0;
private int mCurrentCategoryPageId = 0;
diff --git a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
index d8b5758a6..2012d34c4 100644
--- a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
+++ b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
@@ -19,50 +19,37 @@ package com.android.inputmethod.keyboard;
import static com.android.inputmethod.latin.Constants.NOT_A_COORDINATE;
import android.content.Context;
-import android.content.SharedPreferences;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
-import android.graphics.Rect;
-import android.os.Build;
+import android.graphics.Typeface;
import android.os.CountDownTimer;
import android.preference.PreferenceManager;
-import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.Pair;
-import android.util.SparseArray;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TabHost;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TextView;
-import com.android.inputmethod.keyboard.internal.DynamicGridKeyboard;
+import com.android.inputmethod.keyboard.internal.EmojiCategory;
import com.android.inputmethod.keyboard.internal.EmojiLayoutParams;
import com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView;
+import com.android.inputmethod.keyboard.internal.EmojiPalettesAdapter;
import com.android.inputmethod.keyboard.internal.KeyDrawParams;
import com.android.inputmethod.keyboard.internal.KeyVisualAttributes;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SubtypeSwitcher;
-import com.android.inputmethod.latin.settings.Settings;
-import com.android.inputmethod.latin.utils.CollectionUtils;
import com.android.inputmethod.latin.utils.ResourceUtils;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
/**
@@ -76,13 +63,12 @@ import java.util.concurrent.TimeUnit;
* </ol>
* Because of the above reasons, this class doesn't extend {@link KeyboardView}.
*/
+// TODO: Move this class to com.android.inputmethod.emoji package.
public final class EmojiPalettesView extends LinearLayout implements OnTabChangeListener,
ViewPager.OnPageChangeListener, View.OnClickListener, View.OnTouchListener,
EmojiPageKeyboardView.OnKeyEventListener {
- static final String TAG = EmojiPalettesView.class.getSimpleName();
- private static final boolean DEBUG_PAGER = false;
- private final int mKeyBackgroundId;
- private final int mEmojiFunctionalKeyBackgroundId;
+ private final int mFunctionalKeyBackgroundId;
+ private final int mSpacebarBackgroundId;
private final ColorStateList mTabLabelColor;
private final DeleteKeyOnTouchListener mDeleteKeyOnTouchListener;
private EmojiPalettesAdapter mEmojiPalettesAdapter;
@@ -97,317 +83,6 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
private KeyboardActionListener mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER;
- private static final int CATEGORY_ID_UNSPECIFIED = -1;
- public static final int CATEGORY_ID_RECENTS = 0;
- public static final int CATEGORY_ID_PEOPLE = 1;
- public static final int CATEGORY_ID_OBJECTS = 2;
- public static final int CATEGORY_ID_NATURE = 3;
- public static final int CATEGORY_ID_PLACES = 4;
- public static final int CATEGORY_ID_SYMBOLS = 5;
- public static final int CATEGORY_ID_EMOTICONS = 6;
-
- private static class CategoryProperties {
- public int mCategoryId;
- public int mPageCount;
- public CategoryProperties(final int categoryId, final int pageCount) {
- mCategoryId = categoryId;
- mPageCount = pageCount;
- }
- }
-
- private static class EmojiCategory {
- private static final String[] sCategoryName = {
- "recents",
- "people",
- "objects",
- "nature",
- "places",
- "symbols",
- "emoticons" };
- private static final int[] sCategoryIcon = {
- R.drawable.ic_emoji_recent_light,
- R.drawable.ic_emoji_people_light,
- R.drawable.ic_emoji_objects_light,
- R.drawable.ic_emoji_nature_light,
- R.drawable.ic_emoji_places_light,
- R.drawable.ic_emoji_symbols_light,
- 0 };
- private static final String[] sCategoryLabel =
- { null, null, null, null, null, null, ":-)" };
- private static final int[] sAccessibilityDescriptionResourceIdsForCategories = {
- R.string.spoken_descrption_emoji_category_recents,
- R.string.spoken_descrption_emoji_category_people,
- R.string.spoken_descrption_emoji_category_objects,
- R.string.spoken_descrption_emoji_category_nature,
- R.string.spoken_descrption_emoji_category_places,
- R.string.spoken_descrption_emoji_category_symbols,
- R.string.spoken_descrption_emoji_category_emoticons };
- private static final int[] sCategoryElementId = {
- KeyboardId.ELEMENT_EMOJI_RECENTS,
- KeyboardId.ELEMENT_EMOJI_CATEGORY1,
- KeyboardId.ELEMENT_EMOJI_CATEGORY2,
- KeyboardId.ELEMENT_EMOJI_CATEGORY3,
- KeyboardId.ELEMENT_EMOJI_CATEGORY4,
- KeyboardId.ELEMENT_EMOJI_CATEGORY5,
- KeyboardId.ELEMENT_EMOJI_CATEGORY6 };
- private final SharedPreferences mPrefs;
- private final Resources mRes;
- private final int mMaxPageKeyCount;
- private final KeyboardLayoutSet mLayoutSet;
- private final HashMap<String, Integer> mCategoryNameToIdMap = CollectionUtils.newHashMap();
- private final ArrayList<CategoryProperties> mShownCategories =
- CollectionUtils.newArrayList();
- private final ConcurrentHashMap<Long, DynamicGridKeyboard>
- mCategoryKeyboardMap = new ConcurrentHashMap<Long, DynamicGridKeyboard>();
-
- private int mCurrentCategoryId = CATEGORY_ID_UNSPECIFIED;
- private int mCurrentCategoryPageId = 0;
-
- public EmojiCategory(final SharedPreferences prefs, final Resources res,
- final KeyboardLayoutSet layoutSet) {
- mPrefs = prefs;
- mRes = res;
- mMaxPageKeyCount = res.getInteger(R.integer.config_emoji_keyboard_max_page_key_count);
- mLayoutSet = layoutSet;
- for (int i = 0; i < sCategoryName.length; ++i) {
- mCategoryNameToIdMap.put(sCategoryName[i], i);
- }
- addShownCategoryId(CATEGORY_ID_RECENTS);
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2
- || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KeyLimePie")
- || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KitKat")) {
- addShownCategoryId(CATEGORY_ID_PEOPLE);
- addShownCategoryId(CATEGORY_ID_OBJECTS);
- addShownCategoryId(CATEGORY_ID_NATURE);
- addShownCategoryId(CATEGORY_ID_PLACES);
- mCurrentCategoryId =
- Settings.readLastShownEmojiCategoryId(mPrefs, CATEGORY_ID_PEOPLE);
- } else {
- mCurrentCategoryId =
- Settings.readLastShownEmojiCategoryId(mPrefs, CATEGORY_ID_SYMBOLS);
- }
- addShownCategoryId(CATEGORY_ID_SYMBOLS);
- addShownCategoryId(CATEGORY_ID_EMOTICONS);
- getKeyboard(CATEGORY_ID_RECENTS, 0 /* cagetoryPageId */)
- .loadRecentKeys(mCategoryKeyboardMap.values());
- }
-
- private void addShownCategoryId(final int categoryId) {
- // Load a keyboard of categoryId
- getKeyboard(categoryId, 0 /* cagetoryPageId */);
- final CategoryProperties properties =
- new CategoryProperties(categoryId, getCategoryPageCount(categoryId));
- mShownCategories.add(properties);
- }
-
- public String getCategoryName(final int categoryId, final int categoryPageId) {
- return sCategoryName[categoryId] + "-" + categoryPageId;
- }
-
- public int getCategoryId(final String name) {
- final String[] strings = name.split("-");
- return mCategoryNameToIdMap.get(strings[0]);
- }
-
- public int getCategoryIcon(final int categoryId) {
- return sCategoryIcon[categoryId];
- }
-
- public String getCategoryLabel(final int categoryId) {
- return sCategoryLabel[categoryId];
- }
-
- public String getAccessibilityDescription(final int categoryId) {
- return mRes.getString(sAccessibilityDescriptionResourceIdsForCategories[categoryId]);
- }
-
- public ArrayList<CategoryProperties> getShownCategories() {
- return mShownCategories;
- }
-
- public int getCurrentCategoryId() {
- return mCurrentCategoryId;
- }
-
- public int getCurrentCategoryPageSize() {
- return getCategoryPageSize(mCurrentCategoryId);
- }
-
- public int getCategoryPageSize(final int categoryId) {
- for (final CategoryProperties prop : mShownCategories) {
- if (prop.mCategoryId == categoryId) {
- return prop.mPageCount;
- }
- }
- Log.w(TAG, "Invalid category id: " + categoryId);
- // Should not reach here.
- return 0;
- }
-
- public void setCurrentCategoryId(final int categoryId) {
- mCurrentCategoryId = categoryId;
- Settings.writeLastShownEmojiCategoryId(mPrefs, categoryId);
- }
-
- public void setCurrentCategoryPageId(final int id) {
- mCurrentCategoryPageId = id;
- }
-
- public int getCurrentCategoryPageId() {
- return mCurrentCategoryPageId;
- }
-
- public void saveLastTypedCategoryPage() {
- Settings.writeLastTypedEmojiCategoryPageId(
- mPrefs, mCurrentCategoryId, mCurrentCategoryPageId);
- }
-
- public boolean isInRecentTab() {
- return mCurrentCategoryId == CATEGORY_ID_RECENTS;
- }
-
- public int getTabIdFromCategoryId(final int categoryId) {
- for (int i = 0; i < mShownCategories.size(); ++i) {
- if (mShownCategories.get(i).mCategoryId == categoryId) {
- return i;
- }
- }
- Log.w(TAG, "categoryId not found: " + categoryId);
- return 0;
- }
-
- // Returns the view pager's page position for the categoryId
- public int getPageIdFromCategoryId(final int categoryId) {
- final int lastSavedCategoryPageId =
- Settings.readLastTypedEmojiCategoryPageId(mPrefs, categoryId);
- int sum = 0;
- for (int i = 0; i < mShownCategories.size(); ++i) {
- final CategoryProperties props = mShownCategories.get(i);
- if (props.mCategoryId == categoryId) {
- return sum + lastSavedCategoryPageId;
- }
- sum += props.mPageCount;
- }
- Log.w(TAG, "categoryId not found: " + categoryId);
- return 0;
- }
-
- public int getRecentTabId() {
- return getTabIdFromCategoryId(CATEGORY_ID_RECENTS);
- }
-
- private int getCategoryPageCount(final int categoryId) {
- final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[categoryId]);
- return (keyboard.getSortedKeys().size() - 1) / mMaxPageKeyCount + 1;
- }
-
- // Returns a pair of the category id and the category page id from the view pager's page
- // 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) {
- int sum = 0;
- for (final CategoryProperties properties : mShownCategories) {
- final int temp = sum;
- sum += properties.mPageCount;
- if (sum > position) {
- return new Pair<Integer, Integer>(properties.mCategoryId, position - temp);
- }
- }
- return null;
- }
-
- // Returns a keyboard from the view pager's page position.
- public DynamicGridKeyboard getKeyboardFromPagePosition(final int position) {
- final Pair<Integer, Integer> categoryAndId =
- getCategoryIdAndPageIdFromPagePosition(position);
- if (categoryAndId != null) {
- return getKeyboard(categoryAndId.first, categoryAndId.second);
- }
- 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.getSortedKeys(), 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;
- }
- tempKeyboard.addKeyLast(emojiKey);
- }
- mCategoryKeyboardMap.put(
- getCategoryKeyboardMapKey(categoryId, pageId), tempKeyboard);
- }
- return mCategoryKeyboardMap.get(categotyKeyboardMapKey);
- }
- }
-
- public int getTotalPageCountOfAllCategories() {
- int sum = 0;
- for (CategoryProperties properties : mShownCategories) {
- sum += properties.mPageCount;
- }
- 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;
- }
- return lhs.getCode() < rhs.getCode() ? -1 : 1;
- }
- };
-
- private static Key[][] sortKeysIntoPages(final List<Key> inKeys, final int maxPageCount) {
- final ArrayList<Key> keys = CollectionUtils.newArrayList(inKeys);
- Collections.sort(keys, EMOJI_KEY_COMPARATOR);
- final int pageCount = (keys.size() - 1) / maxPageCount + 1;
- final Key[][] retval = new Key[pageCount][maxPageCount];
- for (int i = 0; i < keys.size(); ++i) {
- retval[i / maxPageCount][i % maxPageCount] = keys.get(i);
- }
- return retval;
- }
- }
-
private final EmojiCategory mEmojiCategory;
public EmojiPalettesView(final Context context, final AttributeSet attrs) {
@@ -418,10 +93,12 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
super(context, attrs, defStyle);
final TypedArray keyboardViewAttr = context.obtainStyledAttributes(attrs,
R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
- mKeyBackgroundId = keyboardViewAttr.getResourceId(
+ final int keyBackgroundId = keyboardViewAttr.getResourceId(
R.styleable.KeyboardView_keyBackground, 0);
- mEmojiFunctionalKeyBackgroundId = keyboardViewAttr.getResourceId(
- R.styleable.KeyboardView_keyBackgroundEmojiFunctional, 0);
+ mFunctionalKeyBackgroundId = keyboardViewAttr.getResourceId(
+ R.styleable.KeyboardView_functionalKeyBackground, keyBackgroundId);
+ mSpacebarBackgroundId = keyboardViewAttr.getResourceId(
+ R.styleable.KeyboardView_spacebarBackground, keyBackgroundId);
keyboardViewAttr.recycle();
final TypedArray emojiPalettesViewAttr = context.obtainStyledAttributes(attrs,
R.styleable.EmojiPalettesView, defStyle, R.style.EmojiPalettesView);
@@ -481,7 +158,8 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
protected void onFinishInflate() {
mTabHost = (TabHost)findViewById(R.id.emoji_category_tabhost);
mTabHost.setup();
- for (final CategoryProperties properties : mEmojiCategory.getShownCategories()) {
+ for (final EmojiCategory.CategoryProperties properties
+ : mEmojiCategory.getShownCategories()) {
addTab(mTabHost, properties.mCategoryId);
}
mTabHost.setOnTabChangedListener(this);
@@ -507,6 +185,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
// deleteKey depends only on OnTouchListener.
final ImageView deleteKey = (ImageView)findViewById(R.id.emoji_keyboard_delete);
+ deleteKey.setBackgroundResource(mFunctionalKeyBackgroundId);
deleteKey.setTag(Constants.CODE_DELETE);
deleteKey.setOnTouchListener(mDeleteKeyOnTouchListener);
@@ -518,17 +197,17 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
// The text on alphabet keys are set at
// {@link #startEmojiPalettes(String,int,float,Typeface)}.
mAlphabetKeyLeft = (TextView)findViewById(R.id.emoji_keyboard_alphabet_left);
- mAlphabetKeyLeft.setBackgroundResource(mEmojiFunctionalKeyBackgroundId);
+ mAlphabetKeyLeft.setBackgroundResource(mFunctionalKeyBackgroundId);
mAlphabetKeyLeft.setTag(Constants.CODE_ALPHA_FROM_EMOJI);
mAlphabetKeyLeft.setOnTouchListener(this);
mAlphabetKeyLeft.setOnClickListener(this);
mAlphabetKeyRight = (TextView)findViewById(R.id.emoji_keyboard_alphabet_right);
- mAlphabetKeyRight.setBackgroundResource(mEmojiFunctionalKeyBackgroundId);
+ mAlphabetKeyRight.setBackgroundResource(mFunctionalKeyBackgroundId);
mAlphabetKeyRight.setTag(Constants.CODE_ALPHA_FROM_EMOJI);
mAlphabetKeyRight.setOnTouchListener(this);
mAlphabetKeyRight.setOnClickListener(this);
final ImageView spaceKey = (ImageView)findViewById(R.id.emoji_keyboard_space);
- spaceKey.setBackgroundResource(mKeyBackgroundId);
+ spaceKey.setBackgroundResource(mSpacebarBackgroundId);
spaceKey.setTag(Constants.CODE_SPACE);
spaceKey.setOnTouchListener(this);
spaceKey.setOnClickListener(this);
@@ -675,9 +354,6 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
public void startEmojiPalettes(final String switchToAlphaLabel,
final KeyVisualAttributes keyVisualAttr) {
- if (DEBUG_PAGER) {
- Log.d(TAG, "allocate emoji palettes memory " + mCurrentPagerPosition);
- }
final KeyDrawParams params = new KeyDrawParams();
params.updateParams(mEmojiLayoutParams.getActionBarHeight(), keyVisualAttr);
setupAlphabetKey(mAlphabetKeyLeft, switchToAlphaLabel, params);
@@ -687,9 +363,6 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
}
public void stopEmojiPalettes() {
- if (DEBUG_PAGER) {
- Log.d(TAG, "deallocate emoji palettes memory");
- }
mEmojiPalettesAdapter.flushPendingRecentKeys();
mEmojiPager.setAdapter(null);
}
@@ -714,7 +387,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
return;
}
- if (oldCategoryId == CATEGORY_ID_RECENTS) {
+ if (oldCategoryId == EmojiCategory.ID_RECENTS) {
// Needs to save pending updates for recent keys when we get out of the recents
// category because we don't want to move the recent emojis around while the user
// is in the recents category.
@@ -733,124 +406,11 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
}
}
- private static class EmojiPalettesAdapter extends PagerAdapter {
- private final EmojiPageKeyboardView.OnKeyEventListener mListener;
- private final DynamicGridKeyboard mRecentsKeyboard;
- private final SparseArray<EmojiPageKeyboardView> mActiveKeyboardViews =
- CollectionUtils.newSparseArray();
- private final EmojiCategory mEmojiCategory;
- private int mActivePosition = 0;
-
- public EmojiPalettesAdapter(final EmojiCategory emojiCategory,
- final EmojiPageKeyboardView.OnKeyEventListener listener) {
- mEmojiCategory = emojiCategory;
- mListener = listener;
- mRecentsKeyboard = mEmojiCategory.getKeyboard(CATEGORY_ID_RECENTS, 0);
- }
-
- public void flushPendingRecentKeys() {
- mRecentsKeyboard.flushPendingRecentKeys();
- final KeyboardView recentKeyboardView =
- mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
- if (recentKeyboardView != null) {
- recentKeyboardView.invalidateAllKeys();
- }
- }
-
- public void addRecentKey(final Key key) {
- if (mEmojiCategory.isInRecentTab()) {
- mRecentsKeyboard.addPendingKey(key);
- return;
- }
- mRecentsKeyboard.addKeyFirst(key);
- final KeyboardView recentKeyboardView =
- mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
- if (recentKeyboardView != null) {
- recentKeyboardView.invalidateAllKeys();
- }
- }
-
- public void onPageScrolled() {
- // Make sure the delayed key-down event (highlight effect and haptic feedback) will be
- // canceled.
- final EmojiPageKeyboardView currentKeyboardView =
- mActiveKeyboardViews.get(mActivePosition);
- if (currentKeyboardView != null) {
- currentKeyboardView.releaseCurrentKey();
- }
- }
-
- @Override
- public int getCount() {
- return mEmojiCategory.getTotalPageCountOfAllCategories();
- }
-
- @Override
- public void setPrimaryItem(final ViewGroup container, final int position,
- final Object object) {
- if (mActivePosition == position) {
- return;
- }
- final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition);
- if (oldKeyboardView != null) {
- oldKeyboardView.releaseCurrentKey();
- oldKeyboardView.deallocateMemory();
- }
- mActivePosition = position;
- }
-
- @Override
- public Object instantiateItem(final ViewGroup container, final int position) {
- if (DEBUG_PAGER) {
- Log.d(TAG, "instantiate item: " + position);
- }
- final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position);
- if (oldKeyboardView != null) {
- oldKeyboardView.deallocateMemory();
- // This may be redundant but wanted to be safer..
- mActiveKeyboardViews.remove(position);
- }
- final Keyboard keyboard =
- mEmojiCategory.getKeyboardFromPagePosition(position);
- final LayoutInflater inflater = LayoutInflater.from(container.getContext());
- final EmojiPageKeyboardView keyboardView = (EmojiPageKeyboardView)inflater.inflate(
- R.layout.emoji_keyboard_page, container, false /* attachToRoot */);
- keyboardView.setKeyboard(keyboard);
- keyboardView.setOnKeyEventListener(mListener);
- container.addView(keyboardView);
- mActiveKeyboardViews.put(position, keyboardView);
- return keyboardView;
- }
-
- @Override
- public boolean isViewFromObject(final View view, final Object object) {
- return view == object;
- }
-
- @Override
- public void destroyItem(final ViewGroup container, final int position,
- final Object object) {
- if (DEBUG_PAGER) {
- Log.d(TAG, "destroy item: " + position + ", " + object.getClass().getSimpleName());
- }
- final EmojiPageKeyboardView keyboardView = mActiveKeyboardViews.get(position);
- if (keyboardView != null) {
- keyboardView.deallocateMemory();
- mActiveKeyboardViews.remove(position);
- }
- if (object instanceof View) {
- container.removeView((View)object);
- } else {
- Log.w(TAG, "Warning!!! Emoji palette may be leaking. " + object);
- }
- }
- }
-
private static class DeleteKeyOnTouchListener implements OnTouchListener {
- private static final long MAX_REPEAT_COUNT_TIME = TimeUnit.SECONDS.toMillis(30);
- private final int mDeleteKeyPressedBackgroundColor;
- private final long mKeyRepeatStartTimeout;
- private final long mKeyRepeatInterval;
+ static final long MAX_REPEAT_COUNT_TIME = TimeUnit.SECONDS.toMillis(30);
+ final int mDeleteKeyPressedBackgroundColor;
+ final long mKeyRepeatStartTimeout;
+ final long mKeyRepeatInterval;
public DeleteKeyOnTouchListener(Context context) {
final Resources res = context.getResources();
@@ -953,7 +513,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
}
// Called by {@link #mTimer} in the UI thread as an auto key-repeat signal.
- private void onKeyRepeat() {
+ void onKeyRepeat() {
switch (mState) {
case KEY_REPEAT_STATE_INITIALIZED:
// Basically this should not happen.
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 816a94300..4c2250740 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -218,7 +218,7 @@ public class Key implements Comparable<Key> {
*
* @param keySpec the key specification.
* @param keyAttr the Key XML attributes array.
- * @param keyStyle the {@link KeyStyle} of this key.
+ * @param style the {@link KeyStyle} of this key.
* @param params the keyboard building parameters.
* @param row the row that this key belongs to. row's x-coordinate will be the right edge of
* this key.
@@ -857,17 +857,6 @@ public class Key implements Comparable<Key> {
android.R.attr.state_empty
};
- // functional normal state (with properties)
- private static final int[] KEY_STATE_FUNCTIONAL_NORMAL = {
- android.R.attr.state_single
- };
-
- // functional pressed state (with properties)
- private static final int[] KEY_STATE_FUNCTIONAL_PRESSED = {
- android.R.attr.state_single,
- android.R.attr.state_pressed
- };
-
// action normal state (with properties)
private static final int[] KEY_STATE_ACTIVE_NORMAL = {
android.R.attr.state_active
@@ -880,25 +869,43 @@ public class Key implements Comparable<Key> {
};
/**
- * Returns the drawable state for the key, based on the current state and type of the key.
- * @return the drawable state of the key.
+ * Returns the background drawable for the key, based on the current state and type of the key.
+ * @return the background drawable of the key.
* @see android.graphics.drawable.StateListDrawable#setState(int[])
*/
- public final int[] getCurrentDrawableState() {
+ public final Drawable selectBackgroundDrawable(final Drawable keyBackground,
+ final Drawable functionalKeyBackground, final Drawable spacebarBackground) {
+ final Drawable background;
+ if (mBackgroundType == BACKGROUND_TYPE_FUNCTIONAL) {
+ background = functionalKeyBackground;
+ } else if (getCode() == Constants.CODE_SPACE) {
+ background = spacebarBackground;
+ } else {
+ background = keyBackground;
+ }
+ final int[] stateSet;
switch (mBackgroundType) {
- case BACKGROUND_TYPE_FUNCTIONAL:
- return mPressed ? KEY_STATE_FUNCTIONAL_PRESSED : KEY_STATE_FUNCTIONAL_NORMAL;
case BACKGROUND_TYPE_ACTION:
- return mPressed ? KEY_STATE_ACTIVE_PRESSED : KEY_STATE_ACTIVE_NORMAL;
+ stateSet = mPressed ? KEY_STATE_ACTIVE_PRESSED : KEY_STATE_ACTIVE_NORMAL;
+ break;
case BACKGROUND_TYPE_STICKY_OFF:
- return mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_OFF : KEY_STATE_NORMAL_HIGHLIGHT_OFF;
+ stateSet = mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_OFF : KEY_STATE_NORMAL_HIGHLIGHT_OFF;
+ break;
case BACKGROUND_TYPE_STICKY_ON:
- return mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_ON : KEY_STATE_NORMAL_HIGHLIGHT_ON;
+ stateSet = mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_ON : KEY_STATE_NORMAL_HIGHLIGHT_ON;
+ break;
case BACKGROUND_TYPE_EMPTY:
- return mPressed ? KEY_STATE_PRESSED : KEY_STATE_EMPTY;
+ stateSet = mPressed ? KEY_STATE_PRESSED : KEY_STATE_EMPTY;
+ break;
+ case BACKGROUND_TYPE_FUNCTIONAL:
+ stateSet = mPressed ? KEY_STATE_PRESSED : KEY_STATE_NORMAL;
+ break;
default: /* BACKGROUND_TYPE_NORMAL */
- return mPressed ? KEY_STATE_PRESSED : KEY_STATE_NORMAL;
+ stateSet = mPressed ? KEY_STATE_PRESSED : KEY_STATE_NORMAL;
+ break;
}
+ background.setState(stateSet);
+ return background;
}
public static class Spacer extends Key {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 8ca00b005..a6eac4cd7 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -47,6 +47,8 @@ import java.util.HashSet;
* A view that renders a virtual {@link Keyboard}.
*
* @attr ref R.styleable#KeyboardView_keyBackground
+ * @attr ref R.styleable#KeyboardView_functionalKeyBackground
+ * @attr ref R.styleable#KeyboardView_spacebarBackground
* @attr ref R.styleable#KeyboardView_keyLabelHorizontalPadding
* @attr ref R.styleable#KeyboardView_keyHintLetterPadding
* @attr ref R.styleable#KeyboardView_keyPopupHintLetterPadding
@@ -81,7 +83,10 @@ public class KeyboardView extends View {
private final float mKeyTextShadowRadius;
private final float mVerticalCorrection;
private final Drawable mKeyBackground;
+ private final Drawable mFunctionalKeyBackground;
+ private final Drawable mSpacebarBackground;
private final Rect mKeyBackgroundPadding = new Rect();
+ private static final float KET_TEXT_SHADOW_RADIUS_DISABLED = -1.0f;
// HORIZONTAL ELLIPSIS "...", character for popup hint.
private static final String POPUP_HINT_CHAR = "\u2026";
@@ -124,6 +129,14 @@ public class KeyboardView extends View {
R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
mKeyBackground = keyboardViewAttr.getDrawable(R.styleable.KeyboardView_keyBackground);
mKeyBackground.getPadding(mKeyBackgroundPadding);
+ final Drawable functionalKeyBackground = keyboardViewAttr.getDrawable(
+ R.styleable.KeyboardView_functionalKeyBackground);
+ mFunctionalKeyBackground = (functionalKeyBackground != null) ? functionalKeyBackground
+ : mKeyBackground;
+ final Drawable spacebarBackground = keyboardViewAttr.getDrawable(
+ R.styleable.KeyboardView_spacebarBackground);
+ mSpacebarBackground = (spacebarBackground != null) ? spacebarBackground
+ : mKeyBackground;
mKeyLabelHorizontalPadding = keyboardViewAttr.getDimensionPixelOffset(
R.styleable.KeyboardView_keyLabelHorizontalPadding, 0);
mKeyHintLetterPadding = keyboardViewAttr.getDimension(
@@ -133,7 +146,7 @@ public class KeyboardView extends View {
mKeyShiftedLetterHintPadding = keyboardViewAttr.getDimension(
R.styleable.KeyboardView_keyShiftedLetterHintPadding, 0.0f);
mKeyTextShadowRadius = keyboardViewAttr.getFloat(
- R.styleable.KeyboardView_keyTextShadowRadius, 0.0f);
+ R.styleable.KeyboardView_keyTextShadowRadius, KET_TEXT_SHADOW_RADIUS_DISABLED);
mVerticalCorrection = keyboardViewAttr.getDimension(
R.styleable.KeyboardView_verticalCorrection, 0.0f);
keyboardViewAttr.recycle();
@@ -323,7 +336,9 @@ public class KeyboardView extends View {
params.mAnimAlpha = Constants.Color.ALPHA_OPAQUE;
if (!key.isSpacer()) {
- onDrawKeyBackground(key, canvas, mKeyBackground);
+ final Drawable background = key.selectBackgroundDrawable(
+ mKeyBackground, mFunctionalKeyBackground, mSpacebarBackground);
+ onDrawKeyBackground(key, canvas, background);
}
onDrawKeyTopVisuals(key, canvas, paint, params);
@@ -338,8 +353,6 @@ public class KeyboardView extends View {
final int bgHeight = key.getHeight() + padding.top + padding.bottom;
final int bgX = -padding.left;
final int bgY = -padding.top;
- final int[] drawableState = key.getCurrentDrawableState();
- background.setState(drawableState);
final Rect bounds = background.getBounds();
if (bgWidth != bounds.right || bgHeight != bounds.bottom) {
background.setBounds(0, 0, bgWidth, bgHeight);
@@ -414,18 +427,23 @@ public class KeyboardView extends View {
}
}
- paint.setColor(key.selectTextColor(params));
if (key.isEnabled()) {
- // Set a drop shadow for the text
- paint.setShadowLayer(mKeyTextShadowRadius, 0.0f, 0.0f, params.mTextShadowColor);
+ paint.setColor(key.selectTextColor(params));
+ // Set a drop shadow for the text if the shadow radius is positive value.
+ if (mKeyTextShadowRadius > 0.0f) {
+ paint.setShadowLayer(mKeyTextShadowRadius, 0.0f, 0.0f, params.mTextShadowColor);
+ } else {
+ paint.clearShadowLayer();
+ }
} else {
// Make label invisible
paint.setColor(Color.TRANSPARENT);
+ paint.clearShadowLayer();
}
blendAlpha(paint, params.mAnimAlpha);
canvas.drawText(label, 0, label.length(), positionX, baseline, paint);
// Turn off drop shadow and reset x-scale.
- paint.setShadowLayer(0.0f, 0.0f, 0.0f, Color.TRANSPARENT);
+ paint.clearShadowLayer();
paint.setTextScaleX(1.0f);
if (icon != null) {
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 8f79a9128..4a0976845 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -74,8 +74,8 @@ import java.util.WeakHashMap;
* @attr ref R.styleable#MainKeyboardView_autoCorrectionSpacebarLedIcon
* @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextRatio
* @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextColor
+ * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextShadowRadius
* @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextShadowColor
- * @attr ref R.styleable#MainKeyboardView_spacebarBackground
* @attr ref R.styleable#MainKeyboardView_languageOnSpacebarFinalAlpha
* @attr ref R.styleable#MainKeyboardView_languageOnSpacebarFadeoutAnimator
* @attr ref R.styleable#MainKeyboardView_altCodeKeyWhileTypingFadeoutAnimator
@@ -119,7 +119,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
/* Space key and its icon and background. */
private Key mSpaceKey;
private Drawable mSpacebarIcon;
- private final Drawable mSpacebarBackground;
// Stuff to draw language name on spacebar.
private final int mLanguageOnSpacebarFinalAlpha;
private ObjectAnimator mLanguageOnSpacebarFadeoutAnimator;
@@ -129,7 +128,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
private final float mLanguageOnSpacebarTextRatio;
private float mLanguageOnSpacebarTextSize;
private final int mLanguageOnSpacebarTextColor;
+ private final float mLanguageOnSpacebarTextShadowRadius;
private final int mLanguageOnSpacebarTextShadowColor;
+ private static final float LANGUAGE_ON_SPACEBAR_TEXT_SHADOW_RADIUS_DISABLED = -1.0f;
// 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.
@@ -151,7 +152,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
private final SlidingKeyInputDrawingPreview mSlidingKeyInputDrawingPreview;
// Key preview
- private static final boolean FADE_OUT_KEY_TOP_LETTER_WHEN_KEY_IS_PRESSED = false;
private final KeyPreviewDrawParams mKeyPreviewDrawParams;
private final KeyPreviewChoreographer mKeyPreviewChoreographer;
@@ -221,8 +221,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
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(
@@ -231,6 +229,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
R.styleable.MainKeyboardView_languageOnSpacebarTextRatio, 1, 1, 1.0f);
mLanguageOnSpacebarTextColor = mainKeyboardViewAttr.getColor(
R.styleable.MainKeyboardView_languageOnSpacebarTextColor, 0);
+ mLanguageOnSpacebarTextShadowRadius = mainKeyboardViewAttr.getFloat(
+ R.styleable.MainKeyboardView_languageOnSpacebarTextShadowRadius,
+ LANGUAGE_ON_SPACEBAR_TEXT_SHADOW_RADIUS_DISABLED);
mLanguageOnSpacebarTextShadowColor = mainKeyboardViewAttr.getColor(
R.styleable.MainKeyboardView_languageOnSpacebarTextShadowColor, 0);
mLanguageOnSpacebarFinalAlpha = mainKeyboardViewAttr.getInt(
@@ -551,6 +552,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
}
// Note that this method is called from a non-UI thread.
+ @SuppressWarnings("static-method")
public void setMainDictionaryAvailability(final boolean mainDictionaryAvailable) {
PointerTracker.setMainDictionaryAvailability(mainDictionaryAvailable);
}
@@ -858,30 +860,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
- && mKeyPreviewChoreographer.isShowingKeyPreview(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);
@@ -948,12 +932,17 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
final float descent = paint.descent();
final float textHeight = -paint.ascent() + descent;
final float baseline = height / 2 + textHeight / 2;
- paint.setColor(mLanguageOnSpacebarTextShadowColor);
- paint.setAlpha(mLanguageOnSpacebarAnimAlpha);
- canvas.drawText(language, width / 2, baseline - descent - 1, paint);
+ if (mLanguageOnSpacebarTextShadowRadius > 0.0f) {
+ paint.setShadowLayer(mLanguageOnSpacebarTextShadowRadius, 0, 0,
+ mLanguageOnSpacebarTextShadowColor);
+ } else {
+ paint.clearShadowLayer();
+ }
paint.setColor(mLanguageOnSpacebarTextColor);
paint.setAlpha(mLanguageOnSpacebarAnimAlpha);
canvas.drawText(language, width / 2, baseline - descent, paint);
+ paint.clearShadowLayer();
+ paint.setTextScaleX(1.0f);
}
// Draw the spacebar icon at the bottom
diff --git a/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java b/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java
index 67a222732..a4879b852 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java
@@ -20,7 +20,6 @@ import android.content.SharedPreferences;
import android.text.TextUtils;
import android.util.Log;
-import com.android.inputmethod.keyboard.EmojiPalettesView;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.settings.Settings;
@@ -36,6 +35,7 @@ import java.util.List;
/**
* This is a Keyboard class where you can add keys dynamically shown in a grid layout
*/
+// TODO: Move this class to com.android.inputmethod.emoji package.
public class DynamicGridKeyboard extends Keyboard {
private static final String TAG = DynamicGridKeyboard.class.getSimpleName();
private static final int TEMPLATE_KEY_CODE_0 = 0x30;
@@ -62,7 +62,7 @@ public class DynamicGridKeyboard extends Keyboard {
mVerticalStep = key0.getHeight() + mVerticalGap;
mColumnsNum = mBaseWidth / mHorizontalStep;
mMaxKeyCount = maxKeyCount;
- mIsRecents = categoryId == EmojiPalettesView.CATEGORY_ID_RECENTS;
+ mIsRecents = categoryId == EmojiCategory.ID_RECENTS;
mPrefs = prefs;
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiCategory.java b/java/src/com/android/inputmethod/keyboard/internal/EmojiCategory.java
new file mode 100644
index 000000000..10bd621e5
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/EmojiCategory.java
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2014 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.SharedPreferences;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.os.Build;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.KeyboardLayoutSet;
+import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.settings.Settings;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+// TODO: Move this class to com.android.inputmethod.emoji package.
+public final class EmojiCategory {
+ private final String TAG = EmojiCategory.class.getSimpleName();
+
+ private static final int ID_UNSPECIFIED = -1;
+ public static final int ID_RECENTS = 0;
+ private static final int ID_PEOPLE = 1;
+ private static final int ID_OBJECTS = 2;
+ private static final int ID_NATURE = 3;
+ private static final int ID_PLACES = 4;
+ private static final int ID_SYMBOLS = 5;
+ private static final int ID_EMOTICONS = 6;
+
+ public final class CategoryProperties {
+ public final int mCategoryId;
+ public final int mPageCount;
+ public CategoryProperties(final int categoryId, final int pageCount) {
+ mCategoryId = categoryId;
+ mPageCount = pageCount;
+ }
+ }
+
+ private static final String[] sCategoryName = {
+ "recents",
+ "people",
+ "objects",
+ "nature",
+ "places",
+ "symbols",
+ "emoticons" };
+
+ private static final int[] sCategoryIcon = {
+ R.drawable.ic_emoji_recent_light,
+ R.drawable.ic_emoji_people_light,
+ R.drawable.ic_emoji_objects_light,
+ R.drawable.ic_emoji_nature_light,
+ R.drawable.ic_emoji_places_light,
+ R.drawable.ic_emoji_symbols_light,
+ 0 };
+
+ private static final String[] sCategoryLabel =
+ { null, null, null, null, null, null, ":-)" };
+
+ private static final int[] sAccessibilityDescriptionResourceIdsForCategories = {
+ R.string.spoken_descrption_emoji_category_recents,
+ R.string.spoken_descrption_emoji_category_people,
+ R.string.spoken_descrption_emoji_category_objects,
+ R.string.spoken_descrption_emoji_category_nature,
+ R.string.spoken_descrption_emoji_category_places,
+ R.string.spoken_descrption_emoji_category_symbols,
+ R.string.spoken_descrption_emoji_category_emoticons };
+
+ private static final int[] sCategoryElementId = {
+ KeyboardId.ELEMENT_EMOJI_RECENTS,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY1,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY2,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY3,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY4,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY5,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY6 };
+
+ private final SharedPreferences mPrefs;
+ private final Resources mRes;
+ private final int mMaxPageKeyCount;
+ private final KeyboardLayoutSet mLayoutSet;
+ private final HashMap<String, Integer> mCategoryNameToIdMap = CollectionUtils.newHashMap();
+ private final ArrayList<CategoryProperties> mShownCategories =
+ CollectionUtils.newArrayList();
+ private final ConcurrentHashMap<Long, DynamicGridKeyboard>
+ mCategoryKeyboardMap = new ConcurrentHashMap<Long, DynamicGridKeyboard>();
+
+ private int mCurrentCategoryId = EmojiCategory.ID_UNSPECIFIED;
+ private int mCurrentCategoryPageId = 0;
+
+ public EmojiCategory(final SharedPreferences prefs, final Resources res,
+ final KeyboardLayoutSet layoutSet) {
+ mPrefs = prefs;
+ mRes = res;
+ mMaxPageKeyCount = res.getInteger(R.integer.config_emoji_keyboard_max_page_key_count);
+ mLayoutSet = layoutSet;
+ for (int i = 0; i < sCategoryName.length; ++i) {
+ mCategoryNameToIdMap.put(sCategoryName[i], i);
+ }
+ addShownCategoryId(EmojiCategory.ID_RECENTS);
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2
+ || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KeyLimePie")
+ || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KitKat")) {
+ addShownCategoryId(EmojiCategory.ID_PEOPLE);
+ addShownCategoryId(EmojiCategory.ID_OBJECTS);
+ addShownCategoryId(EmojiCategory.ID_NATURE);
+ addShownCategoryId(EmojiCategory.ID_PLACES);
+ mCurrentCategoryId =
+ Settings.readLastShownEmojiCategoryId(mPrefs, EmojiCategory.ID_PEOPLE);
+ } else {
+ mCurrentCategoryId =
+ Settings.readLastShownEmojiCategoryId(mPrefs, EmojiCategory.ID_SYMBOLS);
+ }
+ addShownCategoryId(EmojiCategory.ID_SYMBOLS);
+ addShownCategoryId(EmojiCategory.ID_EMOTICONS);
+ getKeyboard(EmojiCategory.ID_RECENTS, 0 /* cagetoryPageId */)
+ .loadRecentKeys(mCategoryKeyboardMap.values());
+ }
+
+ private void addShownCategoryId(final int categoryId) {
+ // Load a keyboard of categoryId
+ getKeyboard(categoryId, 0 /* cagetoryPageId */);
+ final CategoryProperties properties =
+ new CategoryProperties(categoryId, getCategoryPageCount(categoryId));
+ mShownCategories.add(properties);
+ }
+
+ public String getCategoryName(final int categoryId, final int categoryPageId) {
+ return sCategoryName[categoryId] + "-" + categoryPageId;
+ }
+
+ public int getCategoryId(final String name) {
+ final String[] strings = name.split("-");
+ return mCategoryNameToIdMap.get(strings[0]);
+ }
+
+ public int getCategoryIcon(final int categoryId) {
+ return sCategoryIcon[categoryId];
+ }
+
+ public String getCategoryLabel(final int categoryId) {
+ return sCategoryLabel[categoryId];
+ }
+
+ public String getAccessibilityDescription(final int categoryId) {
+ return mRes.getString(sAccessibilityDescriptionResourceIdsForCategories[categoryId]);
+ }
+
+ public ArrayList<CategoryProperties> getShownCategories() {
+ return mShownCategories;
+ }
+
+ public int getCurrentCategoryId() {
+ return mCurrentCategoryId;
+ }
+
+ public int getCurrentCategoryPageSize() {
+ return getCategoryPageSize(mCurrentCategoryId);
+ }
+
+ public int getCategoryPageSize(final int categoryId) {
+ for (final CategoryProperties prop : mShownCategories) {
+ if (prop.mCategoryId == categoryId) {
+ return prop.mPageCount;
+ }
+ }
+ Log.w(TAG, "Invalid category id: " + categoryId);
+ // Should not reach here.
+ return 0;
+ }
+
+ public void setCurrentCategoryId(final int categoryId) {
+ mCurrentCategoryId = categoryId;
+ Settings.writeLastShownEmojiCategoryId(mPrefs, categoryId);
+ }
+
+ public void setCurrentCategoryPageId(final int id) {
+ mCurrentCategoryPageId = id;
+ }
+
+ public int getCurrentCategoryPageId() {
+ return mCurrentCategoryPageId;
+ }
+
+ public void saveLastTypedCategoryPage() {
+ Settings.writeLastTypedEmojiCategoryPageId(
+ mPrefs, mCurrentCategoryId, mCurrentCategoryPageId);
+ }
+
+ public boolean isInRecentTab() {
+ return mCurrentCategoryId == EmojiCategory.ID_RECENTS;
+ }
+
+ public int getTabIdFromCategoryId(final int categoryId) {
+ for (int i = 0; i < mShownCategories.size(); ++i) {
+ if (mShownCategories.get(i).mCategoryId == categoryId) {
+ return i;
+ }
+ }
+ Log.w(TAG, "categoryId not found: " + categoryId);
+ return 0;
+ }
+
+ // Returns the view pager's page position for the categoryId
+ public int getPageIdFromCategoryId(final int categoryId) {
+ final int lastSavedCategoryPageId =
+ Settings.readLastTypedEmojiCategoryPageId(mPrefs, categoryId);
+ int sum = 0;
+ for (int i = 0; i < mShownCategories.size(); ++i) {
+ final CategoryProperties props = mShownCategories.get(i);
+ if (props.mCategoryId == categoryId) {
+ return sum + lastSavedCategoryPageId;
+ }
+ sum += props.mPageCount;
+ }
+ Log.w(TAG, "categoryId not found: " + categoryId);
+ return 0;
+ }
+
+ public int getRecentTabId() {
+ return getTabIdFromCategoryId(EmojiCategory.ID_RECENTS);
+ }
+
+ private int getCategoryPageCount(final int categoryId) {
+ final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[categoryId]);
+ return (keyboard.getSortedKeys().size() - 1) / mMaxPageKeyCount + 1;
+ }
+
+ // Returns a pair of the category id and the category page id from the view pager's page
+ // 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) {
+ int sum = 0;
+ for (final CategoryProperties properties : mShownCategories) {
+ final int temp = sum;
+ sum += properties.mPageCount;
+ if (sum > position) {
+ return new Pair<Integer, Integer>(properties.mCategoryId, position - temp);
+ }
+ }
+ return null;
+ }
+
+ // Returns a keyboard from the view pager's page position.
+ public DynamicGridKeyboard getKeyboardFromPagePosition(final int position) {
+ final Pair<Integer, Integer> categoryAndId =
+ getCategoryIdAndPageIdFromPagePosition(position);
+ if (categoryAndId != null) {
+ return getKeyboard(categoryAndId.first, categoryAndId.second);
+ }
+ 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 == EmojiCategory.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.getSortedKeys(), 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;
+ }
+ tempKeyboard.addKeyLast(emojiKey);
+ }
+ mCategoryKeyboardMap.put(
+ getCategoryKeyboardMapKey(categoryId, pageId), tempKeyboard);
+ }
+ return mCategoryKeyboardMap.get(categotyKeyboardMapKey);
+ }
+ }
+
+ public int getTotalPageCountOfAllCategories() {
+ int sum = 0;
+ for (CategoryProperties properties : mShownCategories) {
+ sum += properties.mPageCount;
+ }
+ 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;
+ }
+ return lhs.getCode() < rhs.getCode() ? -1 : 1;
+ }
+ };
+
+ private static Key[][] sortKeysIntoPages(final List<Key> inKeys, final int maxPageCount) {
+ final ArrayList<Key> keys = CollectionUtils.newArrayList(inKeys);
+ Collections.sort(keys, EMOJI_KEY_COMPARATOR);
+ final int pageCount = (keys.size() - 1) / maxPageCount + 1;
+ final Key[][] retval = new Key[pageCount][maxPageCount];
+ for (int i = 0; i < keys.size(); ++i) {
+ retval[i / maxPageCount][i % maxPageCount] = keys.get(i);
+ }
+ return retval;
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java b/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java
index d57ea5a94..78af66b9a 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java
@@ -24,7 +24,8 @@ import android.support.v4.view.ViewPager;
import android.widget.ImageView;
import android.widget.LinearLayout;
-public class EmojiLayoutParams {
+//TODO: Move this class to com.android.inputmethod.emoji package.
+public final class EmojiLayoutParams {
private static final int DEFAULT_KEYBOARD_ROWS = 4;
public final int mEmojiPagerHeight;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java b/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java
index e175a051e..2f67d194e 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java
@@ -33,6 +33,7 @@ import com.android.inputmethod.latin.R;
* This is an extended {@link KeyboardView} class that hosts an emoji page keyboard.
* Multi-touch unsupported. No {@link PointerTracker}s. No gesture support.
*/
+// TODO: Move this class to com.android.inputmethod.emoji package.
// TODO: Implement key popup preview.
public final class EmojiPageKeyboardView extends KeyboardView implements
GestureDetector.OnGestureListener {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiPalettesAdapter.java b/java/src/com/android/inputmethod/keyboard/internal/EmojiPalettesAdapter.java
new file mode 100644
index 000000000..a44d13407
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/EmojiPalettesAdapter.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2014 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.support.v4.view.PagerAdapter;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardView;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+
+// TODO: Move this class to com.android.inputmethod.emoji package.
+public final class EmojiPalettesAdapter extends PagerAdapter {
+ private static final String TAG = EmojiPalettesAdapter.class.getSimpleName();
+ private static final boolean DEBUG_PAGER = false;
+
+ private final EmojiPageKeyboardView.OnKeyEventListener mListener;
+ private final DynamicGridKeyboard mRecentsKeyboard;
+ private final SparseArray<EmojiPageKeyboardView> mActiveKeyboardViews =
+ CollectionUtils.newSparseArray();
+ private final EmojiCategory mEmojiCategory;
+ private int mActivePosition = 0;
+
+ public EmojiPalettesAdapter(final EmojiCategory emojiCategory,
+ final EmojiPageKeyboardView.OnKeyEventListener listener) {
+ mEmojiCategory = emojiCategory;
+ mListener = listener;
+ mRecentsKeyboard = mEmojiCategory.getKeyboard(EmojiCategory.ID_RECENTS, 0);
+ }
+
+ public void flushPendingRecentKeys() {
+ mRecentsKeyboard.flushPendingRecentKeys();
+ final KeyboardView recentKeyboardView =
+ mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
+ if (recentKeyboardView != null) {
+ recentKeyboardView.invalidateAllKeys();
+ }
+ }
+
+ public void addRecentKey(final Key key) {
+ if (mEmojiCategory.isInRecentTab()) {
+ mRecentsKeyboard.addPendingKey(key);
+ return;
+ }
+ mRecentsKeyboard.addKeyFirst(key);
+ final KeyboardView recentKeyboardView =
+ mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
+ if (recentKeyboardView != null) {
+ recentKeyboardView.invalidateAllKeys();
+ }
+ }
+
+ public void onPageScrolled() {
+ // Make sure the delayed key-down event (highlight effect and haptic feedback) will be
+ // canceled.
+ final EmojiPageKeyboardView currentKeyboardView =
+ mActiveKeyboardViews.get(mActivePosition);
+ if (currentKeyboardView != null) {
+ currentKeyboardView.releaseCurrentKey();
+ }
+ }
+
+ @Override
+ public int getCount() {
+ return mEmojiCategory.getTotalPageCountOfAllCategories();
+ }
+
+ @Override
+ public void setPrimaryItem(final ViewGroup container, final int position,
+ final Object object) {
+ if (mActivePosition == position) {
+ return;
+ }
+ final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition);
+ if (oldKeyboardView != null) {
+ oldKeyboardView.releaseCurrentKey();
+ oldKeyboardView.deallocateMemory();
+ }
+ mActivePosition = position;
+ }
+
+ @Override
+ public Object instantiateItem(final ViewGroup container, final int position) {
+ if (DEBUG_PAGER) {
+ Log.d(TAG, "instantiate item: " + position);
+ }
+ final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position);
+ if (oldKeyboardView != null) {
+ oldKeyboardView.deallocateMemory();
+ // This may be redundant but wanted to be safer..
+ mActiveKeyboardViews.remove(position);
+ }
+ final Keyboard keyboard =
+ mEmojiCategory.getKeyboardFromPagePosition(position);
+ final LayoutInflater inflater = LayoutInflater.from(container.getContext());
+ final EmojiPageKeyboardView keyboardView = (EmojiPageKeyboardView)inflater.inflate(
+ R.layout.emoji_keyboard_page, container, false /* attachToRoot */);
+ keyboardView.setKeyboard(keyboard);
+ keyboardView.setOnKeyEventListener(mListener);
+ container.addView(keyboardView);
+ mActiveKeyboardViews.put(position, keyboardView);
+ return keyboardView;
+ }
+
+ @Override
+ public boolean isViewFromObject(final View view, final Object object) {
+ return view == object;
+ }
+
+ @Override
+ public void destroyItem(final ViewGroup container, final int position,
+ final Object object) {
+ if (DEBUG_PAGER) {
+ Log.d(TAG, "destroy item: " + position + ", " + object.getClass().getSimpleName());
+ }
+ final EmojiPageKeyboardView keyboardView = mActiveKeyboardViews.get(position);
+ if (keyboardView != null) {
+ keyboardView.deallocateMemory();
+ mActiveKeyboardViews.remove(position);
+ }
+ if (object instanceof View) {
+ container.removeView((View)object);
+ } else {
+ Log.w(TAG, "Warning!!! Emoji palette may be leaking. " + object);
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index dfe0df04c..2aeeed87f 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -664,6 +664,8 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
R.styleable.Keyboard_Case_isMultiLine, id.isMultiLine());
final boolean imeActionMatched = matchInteger(caseAttr,
R.styleable.Keyboard_Case_imeAction, id.imeAction());
+ final boolean isIconDefinedMatched = isIconDefined(caseAttr,
+ R.styleable.Keyboard_Case_isIconDefined, mParams.mIconsSet);
final boolean localeCodeMatched = matchString(caseAttr,
R.styleable.Keyboard_Case_localeCode, id.mLocale.toString());
final boolean languageCodeMatched = matchString(caseAttr,
@@ -675,10 +677,11 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
&& passwordInputMatched && clobberSettingsKeyMatched
&& supportsSwitchingToShortcutImeMatched && hasShortcutKeyMatched
&& languageSwitchKeyEnabledMatched && isMultiLineMatched && imeActionMatched
- && localeCodeMatched && languageCodeMatched && countryCodeMatched;
+ && isIconDefinedMatched && 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(
@@ -704,6 +707,8 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
"languageSwitchKeyEnabled"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_isMultiLine,
"isMultiLine"),
+ textAttr(caseAttr.getString(R.styleable.Keyboard_Case_isIconDefined),
+ "isIconDefined"),
textAttr(caseAttr.getString(R.styleable.Keyboard_Case_localeCode),
"localeCode"),
textAttr(caseAttr.getString(R.styleable.Keyboard_Case_languageCode),
@@ -755,6 +760,16 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
return false;
}
+ private static boolean isIconDefined(final TypedArray a, final int index,
+ final KeyboardIconsSet iconsSet) {
+ if (!a.hasValue(index)) {
+ return true;
+ }
+ final String iconName = a.getString(index);
+ final int iconId = KeyboardIconsSet.getIconId(iconName);
+ return iconsSet.getIconDrawable(iconId) != null;
+ }
+
private boolean parseDefault(final XmlPullParser parser, final KeyboardRow row,
final boolean skip) throws XmlPullParserException, IOException {
if (DEBUG) startTag("<%s>", TAG_DEFAULT);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index 6c9b5adc3..65d6a5633 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -42,7 +42,12 @@ public final class KeyboardIconsSet {
public static final String NAME_SPACE_KEY = "space_key";
public static final String NAME_SPACE_KEY_FOR_NUMBER_LAYOUT = "space_key_for_number_layout";
public static final String NAME_ENTER_KEY = "enter_key";
+ public static final String NAME_GO_KEY = "go_key";
public static final String NAME_SEARCH_KEY = "search_key";
+ public static final String NAME_SEND_KEY = "send_key";
+ public static final String NAME_NEXT_KEY = "next_key";
+ public static final String NAME_DONE_KEY = "done_key";
+ public static final String NAME_PREVIOUS_KEY = "previous_key";
public static final String NAME_TAB_KEY = "tab_key";
public static final String NANE_TAB_KEY_PREVIEW = "tab_key_preview";
public static final String NAME_SHORTCUT_KEY = "shortcut_key";
@@ -64,7 +69,12 @@ public final class KeyboardIconsSet {
NAME_SETTINGS_KEY, R.styleable.Keyboard_iconSettingsKey,
NAME_SPACE_KEY, R.styleable.Keyboard_iconSpaceKey,
NAME_ENTER_KEY, R.styleable.Keyboard_iconEnterKey,
+ NAME_GO_KEY, R.styleable.Keyboard_iconGoKey,
NAME_SEARCH_KEY, R.styleable.Keyboard_iconSearchKey,
+ NAME_SEND_KEY, R.styleable.Keyboard_iconSendKey,
+ NAME_NEXT_KEY, R.styleable.Keyboard_iconNextKey,
+ NAME_DONE_KEY, R.styleable.Keyboard_iconDoneKey,
+ NAME_PREVIOUS_KEY, R.styleable.Keyboard_iconPreviousKey,
NAME_TAB_KEY, R.styleable.Keyboard_iconTabKey,
NAME_SHORTCUT_KEY, R.styleable.Keyboard_iconShortcutKey,
NAME_SPACE_KEY_FOR_NUMBER_LAYOUT, R.styleable.Keyboard_iconSpaceKeyForNumberLayout,
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 94a1e3658..999508e92 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -414,8 +414,8 @@ public final class BinaryDictionary extends Dictionary {
public WordProperty mWordProperty;
public int mNextToken;
- public GetNextWordPropertyResult(final WordProperty wordPreperty, final int nextToken) {
- mWordProperty = wordPreperty;
+ public GetNextWordPropertyResult(final WordProperty wordProperty, final int nextToken) {
+ mWordProperty = wordProperty;
mNextToken = nextToken;
}
}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
index 3babb4195..e0220e137 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
@@ -370,7 +370,8 @@ public class DictionaryFacilitatorForSuggest {
}
public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
- final String previousWord, final int timeStampInSeconds) {
+ final String previousWord, final int timeStampInSeconds,
+ final boolean blockPotentiallyOffensive) {
final Dictionaries dictionaries = mDictionaries;
final String[] words = suggestion.split(Constants.WORD_SEPARATOR);
for (int i = 0; i < words.length; i++) {
@@ -378,19 +379,20 @@ public class DictionaryFacilitatorForSuggest {
final String prevWord = (i == 0) ? previousWord : words[i - 1];
final boolean wasCurrentWordAutoCapitalized = (i == 0) ? wasAutoCapitalized : false;
addWordToUserHistory(dictionaries, prevWord, currentWord,
- wasCurrentWordAutoCapitalized, timeStampInSeconds);
+ wasCurrentWordAutoCapitalized, timeStampInSeconds, blockPotentiallyOffensive);
}
}
private void addWordToUserHistory(final Dictionaries dictionaries, final String prevWord,
- final String word, final boolean wasAutoCapitalized, final int timeStampInSeconds) {
+ final String word, final boolean wasAutoCapitalized, final int timeStampInSeconds,
+ final boolean blockPotentiallyOffensive) {
final ExpandableBinaryDictionary userHistoryDictionary =
dictionaries.getSubDict(Dictionary.TYPE_USER_HISTORY);
if (userHistoryDictionary == null) {
return;
}
final int maxFreq = getMaxFrequency(word);
- if (maxFreq == 0) {
+ if (maxFreq == 0 && blockPotentiallyOffensive) {
return;
}
final String lowerCasedWord = word.toLowerCase(dictionaries.mLocale);
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 7dc566a14..8a2ed1088 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -540,18 +540,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
refreshPersonalizationDictionarySession();
}
- private DistracterFilter createDistracterFilter() {
- final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
- // TODO: Create Keyboard when mainKeyboardView is null.
- // TODO: Figure out the most reasonable keyboard for the filter. Refer to the
- // spellchecker's logic.
- final Keyboard keyboard = (mainKeyboardView != null) ?
- mainKeyboardView.getKeyboard() : null;
- final DistracterFilter distracterFilter = new DistracterFilter(mInputLogic.mSuggest,
- keyboard);
- return distracterFilter;
- }
-
private void refreshPersonalizationDictionarySession() {
final DictionaryFacilitatorForSuggest dictionaryFacilitator =
mInputLogic.mSuggest.mDictionaryFacilitator;
@@ -1755,6 +1743,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mInputLogic.mSuggest.mDictionaryFacilitator.clearPersonalizationDictionary();
}
+ @UsedForTesting
+ /* package for test */ DistracterFilter createDistracterFilter() {
+ return DistracterFilter.createDistracterFilter(mInputLogic.mSuggest, mKeyboardSwitcher);
+ }
+
public void dumpDictionaryForDebug(final String dictName) {
final DictionaryFacilitatorForSuggest dictionaryFacilitator =
mInputLogic.mSuggest.mDictionaryFacilitator;
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 6a420748c..8b795b82f 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -1241,7 +1241,7 @@ public final class InputLogic {
final int timeStampInSeconds = (int)TimeUnit.MILLISECONDS.toSeconds(
System.currentTimeMillis());
mSuggest.mDictionaryFacilitator.addToUserHistory(suggestion, wasAutoCapitalized, prevWord,
- timeStampInSeconds);
+ timeStampInSeconds, settingsValues.mBlockPotentiallyOffensive);
}
public void performUpdateSuggestionStripSync(final SettingsValues settingsValues) {
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index dde50ccaf..de2eb951e 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -205,7 +205,8 @@ public final class SettingsValues {
}
public boolean isWordCodePoint(final int code) {
- return Character.isLetter(code) || isWordConnector(code);
+ return Character.isLetter(code) || isWordConnector(code)
+ || Character.COMBINING_SPACING_MARK == Character.getType(code);
}
public boolean isUsuallyPrecededBySpace(final int code) {
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
index 8bfa63c3c..810bda758 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
@@ -381,6 +381,7 @@ final class SuggestionStripLayoutHelper {
}
// Disable this suggestion if the suggestion is null or empty.
+ // TODO: Fix disabled {@link TextView}'s content description.
wordView.setEnabled(!TextUtils.isEmpty(word));
final CharSequence text = getEllipsizedText(word, width, wordView.getPaint());
final float scaleX = getTextScaleX(word, width, wordView.getPaint());
@@ -424,7 +425,9 @@ final class SuggestionStripLayoutHelper {
final int countInStrip) {
// Clear all suggestions first
for (int positionInStrip = 0; positionInStrip < countInStrip; ++positionInStrip) {
- mWordViews.get(positionInStrip).setText(null);
+ final TextView wordView = mWordViews.get(positionInStrip);
+ wordView.setText(null);
+ wordView.setTag(null);
// Make this inactive for touches in {@link #layoutWord(int,int)}.
if (SuggestionStripView.DBG) {
mDebugInfoViews.get(positionInStrip).setText(null);
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index d4f7f36da..619804afa 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -124,9 +124,9 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
mImportantNoticeStrip.setVisibility(INVISIBLE);
}
- public void showImportantNoticeStrip() {
+ public void showImportantNoticeStrip(final boolean enableVoiceKey) {
mSuggestionsStrip.setVisibility(INVISIBLE);
- mVoiceKey.setVisibility(INVISIBLE);
+ mVoiceKey.setVisibility(enableVoiceKey ? VISIBLE : INVISIBLE);
mAddToDictionaryStrip.setVisibility(INVISIBLE);
mImportantNoticeStrip.setVisibility(VISIBLE);
}
@@ -274,7 +274,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
dismissMoreSuggestionsPanel();
}
mLayoutHelper.layoutImportantNotice(mImportantNoticeStrip, importantNoticeTitle);
- mStripVisibilityGroup.showImportantNoticeStrip();
+ mStripVisibilityGroup.showImportantNoticeStrip(isVoiceKeyEnabled());
mImportantNoticeStrip.setOnClickListener(this);
return true;
}
diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
index 48e43d6ef..55cbf79b3 100644
--- a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
+++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
@@ -17,21 +17,35 @@
package com.android.inputmethod.latin.utils;
import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardSwitcher;
+import com.android.inputmethod.keyboard.MainKeyboardView;
+import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.Suggest;
+import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
+import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.WordComposer;
/**
- * This class is used to prevent distracters/misspellings being added to personalization
+ * This class is used to prevent distracters being added to personalization
* or user history dictionaries
*/
public class DistracterFilter {
private final Suggest mSuggest;
private final Keyboard mKeyboard;
+ // If the score of the top suggestion exceeds this value, the tested word (e.g.,
+ // an OOV, a misspelling, or an in-vocabulary word) would be considered as a distracter to
+ // words in dictionary. The greater the threshold is, the less likely the tested word would
+ // become a distracter, which means the tested word will be more likely to be added to
+ // the dictionary.
+ private static final float DISTRACTER_WORD_SCORE_THRESHOLD = 2.0f;
+
/**
* Create a DistracterFilter instance.
*
* @param suggest an instance of Suggest which will be used to obtain a list of suggestions
- * for a potential distracter/misspelling
+ * for a potential distracter
* @param keyboard the keyboard that is currently being used. This information is needed
* when calling mSuggest.getSuggestedWords(...) to obtain a list of suggestions.
*/
@@ -40,9 +54,79 @@ public class DistracterFilter {
mKeyboard = keyboard;
}
- public boolean isDistracterToWordsInDictionaries(final String prevWord,
- final String targetWord) {
- // TODO: to be implemented
+ public static DistracterFilter createDistracterFilter(final Suggest suggest,
+ final KeyboardSwitcher keyboardSwitcher) {
+ final MainKeyboardView mainKeyboardView = keyboardSwitcher.getMainKeyboardView();
+ // TODO: Create Keyboard when mainKeyboardView is null.
+ // TODO: Figure out the most reasonable keyboard for the filter. Refer to the
+ // spellchecker's logic.
+ final Keyboard keyboard = (mainKeyboardView != null) ?
+ mainKeyboardView.getKeyboard() : null;
+ final DistracterFilter distracterFilter = new DistracterFilter(suggest, keyboard);
+ return distracterFilter;
+ }
+
+ private static boolean suggestionExceedsDistracterThreshold(
+ final SuggestedWordInfo suggestion, final String consideredWord,
+ final float distracterThreshold) {
+ if (null != suggestion) {
+ final int suggestionScore = suggestion.mScore;
+ final float normalizedScore = BinaryDictionaryUtils.calcNormalizedScore(
+ consideredWord, suggestion.mWord, suggestionScore);
+ if (normalizedScore > distracterThreshold) {
+ return true;
+ }
+ }
return false;
}
+
+ /**
+ * Determine whether a word is a distracter to words in dictionaries.
+ *
+ * @param prevWord the previous word, or null if none.
+ * @param testedWord the word that will be tested to see whether it is a distracter to words
+ * in dictionaries.
+ * @return true if testedWord is a distracter, otherwise false.
+ */
+ public boolean isDistracterToWordsInDictionaries(final String prevWord,
+ final String testedWord) {
+ if (mSuggest == null) {
+ return false;
+ }
+
+ final WordComposer composer = new WordComposer();
+ final int[] codePoints = StringUtils.toCodePointArray(testedWord);
+ final int[] coordinates;
+ if (null == mKeyboard) {
+ coordinates = CoordinateUtils.newCoordinateArray(codePoints.length,
+ Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
+ } else {
+ coordinates = mKeyboard.getCoordinates(codePoints);
+ }
+ composer.setComposingWord(codePoints, coordinates, prevWord);
+
+ final int trailingSingleQuotesCount = composer.trailingSingleQuotesCount();
+ final String consideredWord = trailingSingleQuotesCount > 0 ? testedWord.substring(0,
+ testedWord.length() - trailingSingleQuotesCount) : testedWord;
+ final AsyncResultHolder<Boolean> holder = new AsyncResultHolder<Boolean>();
+ final OnGetSuggestedWordsCallback callback = new OnGetSuggestedWordsCallback() {
+ @Override
+ public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
+ if (suggestedWords != null && suggestedWords.size() > 1) {
+ // The suggestedWordInfo at 0 is the typed word. The 1st suggestion from
+ // the decoder is at index 1.
+ final SuggestedWordInfo firstSuggestion = suggestedWords.getInfo(1);
+ final boolean hasStrongDistractor = suggestionExceedsDistracterThreshold(
+ firstSuggestion, consideredWord, DISTRACTER_WORD_SCORE_THRESHOLD);
+ holder.set(hasStrongDistractor);
+ }
+ }
+ };
+ mSuggest.getSuggestedWords(composer, prevWord, mKeyboard.getProximityInfo(),
+ true /* blockOffensiveWords */, true /* isCorrectionEnbaled */,
+ null /* additionalFeaturesOptions */, 0 /* sessionId */,
+ SuggestedWords.NOT_A_SEQUENCE_NUMBER, callback);
+
+ return holder.get(false /* defaultValue */, Constants.GET_SUGGESTED_WORDS_TIMEOUT);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
index 55061f45f..74e7db901 100644
--- a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
+++ b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
@@ -129,6 +129,9 @@ public final class LanguageModelParam {
if (locale == null) {
return null;
}
+ // TODO: Though targetWord is an IV (in-vocabulary) word, we should still apply
+ // distracterFilter in the following code. If targetWord is a distracter,
+ // it should be filtered out.
if (dictionaryFacilitator.isValidWord(targetWord, false /* ignoreCase */)) {
return createAndGetLanguageModelParamOfWord(prevWord, targetWord, timestamp,
true /* isValidWord */, locale);
diff --git a/native/jni/NativeFileList.mk b/native/jni/NativeFileList.mk
index 34c190718..6ccfec911 100644
--- a/native/jni/NativeFileList.mk
+++ b/native/jni/NativeFileList.mk
@@ -46,23 +46,22 @@ LATIN_IME_CORE_SRC_FILES := \
$(addprefix suggest/policyimpl/dictionary/, \
header/header_policy.cpp \
header/header_read_write_utils.cpp \
- shortcut/shortcut_list_reading_utils.cpp \
structure/dictionary_structure_with_buffer_policy_factory.cpp) \
- $(addprefix suggest/policyimpl/dictionary/bigram/, \
- bigram_list_read_write_utils.cpp \
- ver4_bigram_list_policy.cpp) \
$(addprefix suggest/policyimpl/dictionary/structure/pt_common/, \
+ bigram/bigram_list_read_write_utils.cpp \
dynamic_pt_gc_event_listeners.cpp \
dynamic_pt_reading_helper.cpp \
dynamic_pt_reading_utils.cpp \
dynamic_pt_updating_helper.cpp \
dynamic_pt_writing_utils.cpp \
- patricia_trie_reading_utils.cpp) \
+ patricia_trie_reading_utils.cpp \
+ shortcut/shortcut_list_reading_utils.cpp ) \
$(addprefix suggest/policyimpl/dictionary/structure/v2/, \
patricia_trie_policy.cpp \
ver2_patricia_trie_node_reader.cpp \
ver2_pt_node_array_reader.cpp) \
$(addprefix suggest/policyimpl/dictionary/structure/v4/, \
+ bigram/ver4_bigram_list_policy.cpp \
ver4_dict_buffers.cpp \
ver4_dict_constants.cpp \
ver4_patricia_trie_node_reader.cpp \
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index a3d8ec158..9098b714b 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -149,14 +149,16 @@ static void latinime_BinaryDictionary_getHeaderInfo(JNIEnv *env, jclass clazz, j
it != attributeMap->end(); ++it) {
// Output key
jintArray keyCodePointArray = env->NewIntArray(it->first.size());
- env->SetIntArrayRegion(
- keyCodePointArray, 0 /* start */, it->first.size(), &it->first.at(0));
+ JniDataUtils::outputCodePoints(env, keyCodePointArray, 0 /* start */,
+ it->first.size(), it->first.data(), it->first.size(),
+ false /* needsNullTermination */);
env->CallBooleanMethod(outAttributeKeys, addMethodId, keyCodePointArray);
env->DeleteLocalRef(keyCodePointArray);
// Output value
jintArray valueCodePointArray = env->NewIntArray(it->second.size());
- env->SetIntArrayRegion(
- valueCodePointArray, 0 /* start */, it->second.size(), &it->second.at(0));
+ JniDataUtils::outputCodePoints(env, valueCodePointArray, 0 /* start */,
+ it->second.size(), it->second.data(), it->second.size(),
+ false /* needsNullTermination */);
env->CallBooleanMethod(outAttributeValues, addMethodId, valueCodePointArray);
env->DeleteLocalRef(valueCodePointArray);
}
@@ -301,6 +303,9 @@ static jint latinime_BinaryDictionary_getNextWord(JNIEnv *env, jclass clazz,
memset(wordCodePoints, 0, sizeof(wordCodePoints));
const int nextToken = dictionary->getNextWordAndNextToken(token, wordCodePoints);
env->SetIntArrayRegion(outCodePoints, 0, outCodePointsLength, wordCodePoints);
+ JniDataUtils::outputCodePoints(env, outCodePoints, 0 /* start */,
+ MAX_WORD_LENGTH /* maxLength */, wordCodePoints, outCodePointsLength,
+ false /* needsNullTermination */);
return nextToken;
}
@@ -335,7 +340,7 @@ static void latinime_BinaryDictionary_addUnigramWord(JNIEnv *env, jclass clazz,
if (!shortcutTargetCodePoints.empty()) {
shortcuts.emplace_back(&shortcutTargetCodePoints, shortcutProbability);
}
- // Use 1 for count to indicate the word has inputed.
+ // Use 1 for count to indicate the word has inputted.
const UnigramProperty unigramProperty(isNotAWord, isBlacklisted,
probability, timestamp, 0 /* level */, 1 /* count */, &shortcuts);
dictionary->addUnigramWord(codePoints, codePointCount, &unigramProperty);
@@ -353,8 +358,12 @@ static void latinime_BinaryDictionary_addBigramWords(JNIEnv *env, jclass clazz,
jsize word1Length = env->GetArrayLength(word1);
int word1CodePoints[word1Length];
env->GetIntArrayRegion(word1, 0, word1Length, word1CodePoints);
- dictionary->addBigramWords(word0CodePoints, word0Length, word1CodePoints,
- word1Length, probability, timestamp);
+ const std::vector<int> bigramTargetCodePoints(
+ word1CodePoints, word1CodePoints + word1Length);
+ // Use 1 for count to indicate the bigram has inputted.
+ const BigramProperty bigramProperty(&bigramTargetCodePoints, probability,
+ timestamp, 0 /* level */, 1 /* count */);
+ dictionary->addBigramWords(word0CodePoints, word0Length, &bigramProperty);
}
static void latinime_BinaryDictionary_removeBigramWords(JNIEnv *env, jclass clazz, jlong dict,
@@ -437,14 +446,18 @@ static int latinime_BinaryDictionary_addMultipleDictionaryEntries(JNIEnv *env, j
env->GetIntField(languageModelParam, shortcutProbabilityFieldId);
shortcuts.emplace_back(&shortcutTargetCodePoints, shortcutProbability);
}
- // Use 1 for count to indicate the word has inputed.
+ // Use 1 for count to indicate the word has inputted.
const UnigramProperty unigramProperty(isNotAWord, isBlacklisted,
unigramProbability, timestamp, 0 /* level */, 1 /* count */, &shortcuts);
dictionary->addUnigramWord(word1CodePoints, word1Length, &unigramProperty);
if (word0) {
jint bigramProbability = env->GetIntField(languageModelParam, bigramProbabilityFieldId);
- dictionary->addBigramWords(word0CodePoints, word0Length, word1CodePoints, word1Length,
- bigramProbability, timestamp);
+ const std::vector<int> bigramTargetCodePoints(
+ word1CodePoints, word1CodePoints + word1Length);
+ // Use 1 for count to indicate the bigram has inputted.
+ const BigramProperty bigramProperty(&bigramTargetCodePoints, bigramProbability,
+ timestamp, 0 /* level */, 1 /* count */);
+ dictionary->addBigramWords(word0CodePoints, word0Length, &bigramProperty);
}
if (dictionary->needsToRunGC(true /* mindsBlockByGC */)) {
return i + 1;
@@ -558,11 +571,9 @@ static bool latinime_BinaryDictionary_migrateNative(JNIEnv *env, jclass clazz, j
return false;
}
}
- for (const BigramProperty &bigarmProperty : *wordProperty.getBigramProperties()) {
- const std::vector<int> *targetCodePoints = bigarmProperty.getTargetCodePoints();
+ for (const BigramProperty &bigramProperty : *wordProperty.getBigramProperties()) {
if (!dictionaryStructureWithBufferPolicy->addBigramWords(wordCodePoints, wordLength,
- targetCodePoints->data(), targetCodePoints->size(),
- bigarmProperty.getProbability(), bigarmProperty.getTimestamp())) {
+ &bigramProperty)) {
LogUtils::logToJava(env, "Cannot add bigram to the new dict.");
return false;
}
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.cpp b/native/jni/src/suggest/core/dictionary/dictionary.cpp
index e288413a3..fdc893653 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.cpp
+++ b/native/jni/src/suggest/core/dictionary/dictionary.cpp
@@ -88,11 +88,10 @@ void Dictionary::addUnigramWord(const int *const word, const int length,
mDictionaryStructureWithBufferPolicy->addUnigramWord(word, length, unigramProperty);
}
-void Dictionary::addBigramWords(const int *const word0, const int length0, const int *const word1,
- const int length1, const int probability, const int timestamp) {
+void Dictionary::addBigramWords(const int *const word0, const int length0,
+ const BigramProperty *const bigramProperty) {
TimeKeeper::setCurrentTime();
- mDictionaryStructureWithBufferPolicy->addBigramWords(word0, length0, word1, length1,
- probability, timestamp);
+ mDictionaryStructureWithBufferPolicy->addBigramWords(word0, length0, bigramProperty);
}
void Dictionary::removeBigramWords(const int *const word0, const int length0,
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.h b/native/jni/src/suggest/core/dictionary/dictionary.h
index b6149b338..f0a7e5b6a 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.h
+++ b/native/jni/src/suggest/core/dictionary/dictionary.h
@@ -76,8 +76,8 @@ class Dictionary {
void addUnigramWord(const int *const codePoints, const int codePointCount,
const UnigramProperty *const unigramProperty);
- void addBigramWords(const int *const word0, const int length0, const int *const word1,
- const int length1, const int probability, const int timestamp);
+ void addBigramWords(const int *const word0, const int length0,
+ const BigramProperty *const bigramProperty);
void removeBigramWords(const int *const word0, const int length0, const int *const word1,
const int length1);
diff --git a/native/jni/src/suggest/core/dictionary/property/word_property.cpp b/native/jni/src/suggest/core/dictionary/property/word_property.cpp
index 95608dcf8..6f5f808f8 100644
--- a/native/jni/src/suggest/core/dictionary/property/word_property.cpp
+++ b/native/jni/src/suggest/core/dictionary/property/word_property.cpp
@@ -16,14 +16,17 @@
#include "suggest/core/dictionary/property/word_property.h"
+#include "utils/jni_data_utils.h"
+
namespace latinime {
void WordProperty::outputProperties(JNIEnv *const env, jintArray outCodePoints,
jbooleanArray outFlags, jintArray outProbabilityInfo, jobject outBigramTargets,
jobject outBigramProbabilities, jobject outShortcutTargets,
jobject outShortcutProbabilities) const {
- env->SetIntArrayRegion(outCodePoints, 0 /* start */, mCodePoints.size(), &mCodePoints[0]);
-
+ JniDataUtils::outputCodePoints(env, outCodePoints, 0 /* start */,
+ MAX_WORD_LENGTH /* maxLength */, mCodePoints.data(), mCodePoints.size(),
+ false /* needsNullTermination */);
jboolean flags[] = {mUnigramProperty.isNotAWord(), mUnigramProperty.isBlacklisted(),
!mBigrams.empty(), mUnigramProperty.hasShortcuts()};
env->SetBooleanArrayRegion(outFlags, 0 /* start */, NELEMS(flags), flags);
@@ -41,8 +44,9 @@ void WordProperty::outputProperties(JNIEnv *const env, jintArray outCodePoints,
for (const auto &bigramProperty : mBigrams) {
const std::vector<int> *const word1CodePoints = bigramProperty.getTargetCodePoints();
jintArray bigramWord1CodePointArray = env->NewIntArray(word1CodePoints->size());
- env->SetIntArrayRegion(bigramWord1CodePointArray, 0 /* start */,
- word1CodePoints->size(), word1CodePoints->data());
+ JniDataUtils::outputCodePoints(env, bigramWord1CodePointArray, 0 /* start */,
+ word1CodePoints->size(), word1CodePoints->data(), word1CodePoints->size(),
+ false /* needsNullTermination */);
env->CallBooleanMethod(outBigramTargets, addMethodId, bigramWord1CodePointArray);
env->DeleteLocalRef(bigramWord1CodePointArray);
@@ -62,6 +66,9 @@ void WordProperty::outputProperties(JNIEnv *const env, jintArray outCodePoints,
jintArray shortcutTargetCodePointArray = env->NewIntArray(targetCodePoints->size());
env->SetIntArrayRegion(shortcutTargetCodePointArray, 0 /* start */,
targetCodePoints->size(), targetCodePoints->data());
+ JniDataUtils::outputCodePoints(env, shortcutTargetCodePointArray, 0 /* start */,
+ targetCodePoints->size(), targetCodePoints->data(), targetCodePoints->size(),
+ false /* needsNullTermination */);
env->CallBooleanMethod(outShortcutTargets, addMethodId, shortcutTargetCodePointArray);
env->DeleteLocalRef(shortcutTargetCodePointArray);
jobject integerProbability = env->NewObject(integerClass, intToIntegerConstructorId,
diff --git a/native/jni/src/suggest/core/layout/proximity_info.cpp b/native/jni/src/suggest/core/layout/proximity_info.cpp
index c40a2bdca..4c75a188e 100644
--- a/native/jni/src/suggest/core/layout/proximity_info.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info.cpp
@@ -226,7 +226,7 @@ int ProximityInfo::getKeyCenterXOfKeyIdG(
// When the referencePointY is NOT_A_COORDINATE, this method calculates the return value without
// using the line segment.
int ProximityInfo::getKeyCenterYOfKeyIdG(
- const int keyId, const int referencePointY, const bool isGeometric) const {
+ const int keyId, const int referencePointY, const bool isGeometric) const {
// TODO: Remove "isGeometric" and have separate "proximity_info"s for gesture and typing.
if (keyId < 0) {
return 0;
diff --git a/native/jni/src/suggest/core/layout/proximity_info_state_utils.h b/native/jni/src/suggest/core/layout/proximity_info_state_utils.h
index 71e83a80c..211a79737 100644
--- a/native/jni/src/suggest/core/layout/proximity_info_state_utils.h
+++ b/native/jni/src/suggest/core/layout/proximity_info_state_utils.h
@@ -56,7 +56,7 @@ class ProximityInfoStateUtils {
const std::vector<int> *const sampledLengthCache,
const std::vector<int> *const sampledInputIndice,
std::vector<float> *sampledSpeedRates, std::vector<float> *sampledDirections);
- static void refreshBeelineSpeedRates(const int mostCommonKeyWidth, const float averageSpeed,
+ static void refreshBeelineSpeedRates(const int mostCommonKeyWidth, const float averageSpeed,
const int inputSize, const int *const xCoordinates, const int *const yCoordinates,
const int *times, const int sampledInputSize,
const std::vector<int> *const sampledInputXs,
diff --git a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
index 807f9b8dd..ce5a49f83 100644
--- a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
+++ b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
@@ -73,8 +73,8 @@ class DictionaryStructureWithBufferPolicy {
const UnigramProperty *const unigramProperty) = 0;
// Returns whether the update was success or not.
- virtual bool addBigramWords(const int *const word0, const int length0, const int *const word1,
- const int length1, const int probability, const int timestamp) = 0;
+ virtual bool addBigramWords(const int *const word0, const int length0,
+ const BigramProperty *const bigramProperty) = 0;
// Returns whether the update was success or not.
virtual bool removeBigramWords(const int *const word0, const int length0,
diff --git a/native/jni/src/suggest/core/result/suggestion_results.cpp b/native/jni/src/suggest/core/result/suggestion_results.cpp
index 088a55f6f..6594a1292 100644
--- a/native/jni/src/suggest/core/result/suggestion_results.cpp
+++ b/native/jni/src/suggest/core/result/suggestion_results.cpp
@@ -16,6 +16,8 @@
#include "suggest/core/result/suggestion_results.h"
+#include "utils/jni_data_utils.h"
+
namespace latinime {
void SuggestionResults::outputSuggestions(JNIEnv *env, jintArray outSuggestionCount,
@@ -27,13 +29,9 @@ void SuggestionResults::outputSuggestions(JNIEnv *env, jintArray outSuggestionCo
const SuggestedWord &suggestedWord = mSuggestedWords.top();
suggestedWord.getCodePointCount();
const int start = outputIndex * MAX_WORD_LENGTH;
- env->SetIntArrayRegion(outputCodePointsArray, start, suggestedWord.getCodePointCount(),
- suggestedWord.getCodePoint());
- if (suggestedWord.getCodePointCount() < MAX_WORD_LENGTH) {
- const int terminal = 0;
- env->SetIntArrayRegion(outputCodePointsArray, start + suggestedWord.getCodePointCount(),
- 1 /* len */, &terminal);
- }
+ JniDataUtils::outputCodePoints(env, outputCodePointsArray, start,
+ MAX_WORD_LENGTH /* maxLength */, suggestedWord.getCodePoint(),
+ suggestedWord.getCodePointCount(), true /* needsNullTermination */);
const int score = suggestedWord.getScore();
env->SetIntArrayRegion(outScoresArray, outputIndex, 1 /* len */, &score);
const int indexToPartialCommit = suggestedWord.getIndexToPartialCommit();
diff --git a/native/jni/src/suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.cpp
index 7d0d09631..08b4e0b5e 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h"
#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
diff --git a/native/jni/src/suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h
index 15f924a6a..15f924a6a 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp
index a527f03bd..9e575858a 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp
@@ -85,13 +85,13 @@ bool DynamicPtUpdatingHelper::addUnigramWord(
}
bool DynamicPtUpdatingHelper::addBigramWords(const int word0Pos, const int word1Pos,
- const int probability, const int timestamp, bool *const outAddedNewBigram) {
+ const BigramProperty *const bigramProperty, bool *const outAddedNewBigram) {
const PtNodeParams sourcePtNodeParams(
mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(word0Pos));
const PtNodeParams targetPtNodeParams(
mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(word1Pos));
- return mPtNodeWriter->addNewBigramEntry(&sourcePtNodeParams, &targetPtNodeParams, probability,
- timestamp, outAddedNewBigram);
+ return mPtNodeWriter->addNewBigramEntry(&sourcePtNodeParams, &targetPtNodeParams,
+ bigramProperty, outAddedNewBigram);
}
// Remove a bigram relation from word0Pos to word1Pos.
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h
index 44914fe4c..f10d15a9b 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h
@@ -22,6 +22,7 @@
namespace latinime {
+class BigramProperty;
class BufferWithExtendableBuffer;
class DynamicPtReadingHelper;
class PtNodeReader;
@@ -42,8 +43,8 @@ class DynamicPtUpdatingHelper {
const UnigramProperty *const unigramProperty, bool *const outAddedNewUnigram);
// Add a bigram relation from word0Pos to word1Pos.
- bool addBigramWords(const int word0Pos, const int word1Pos, const int probability,
- const int timestamp, bool *const outAddedNewBigram);
+ bool addBigramWords(const int word0Pos, const int word1Pos,
+ const BigramProperty *const bigramProperty, bool *const outAddedNewBigram);
// Remove a bigram relation from word0Pos to word1Pos.
bool removeBigramWords(const int word0Pos, const int word1Pos);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h
index 91192fc57..bef401f87 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h
@@ -23,6 +23,7 @@
#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
+#include "utils/char_utils.h"
namespace latinime {
@@ -158,6 +159,10 @@ class PtNodeParams {
return PatriciaTrieReadingUtils::hasShortcutTargets(mFlags);
}
+ AK_FORCE_INLINE bool representsNonWordInfo() const {
+ return getCodePointCount() > 0 && CharUtils::isInUnicodeSpace(getCodePoints()[0]);
+ }
+
// Parent node position
AK_FORCE_INLINE int getParentPos() const {
return mParentPos;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h
index cbca3fe35..a8029f73f 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h
@@ -24,6 +24,7 @@
namespace latinime {
+class BigramProperty;
class UnigramProperty;
// Interface class used to write PtNode information.
@@ -70,7 +71,7 @@ class PtNodeWriter {
const UnigramProperty *const unigramProperty, int *const ptNodeWritingPos) = 0;
virtual bool addNewBigramEntry(const PtNodeParams *const sourcePtNodeParams,
- const PtNodeParams *const targetPtNodeParam, const int probability, const int timestamp,
+ const PtNodeParams *const targetPtNodeParam, const BigramProperty *const bigramProperty,
bool *const outAddedNewBigram) = 0;
virtual bool removeBigramEntry(const PtNodeParams *const sourcePtNodeParams,
diff --git a/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.cpp
index 847dcdee5..91c76941c 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h"
#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
@@ -44,7 +44,7 @@ const int ShortcutListReadingUtils::WHITELIST_SHORTCUT_PROBABILITY = 15;
}
/* static */ int ShortcutListReadingUtils::readShortcutTarget(
- const uint8_t *const dictRoot, const int maxLength, int *const outWord, int *const pos) {
+ const uint8_t *const dictRoot, const int maxLength, int *const outWord, int *const pos) {
return ByteArrayUtils::readStringAndAdvancePosition(dictRoot, maxLength, outWord, pos);
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h
index d065bf7fd..d065bf7fd 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h
diff --git a/native/jni/src/suggest/policyimpl/dictionary/bigram/bigram_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/bigram/bigram_list_policy.h
index a898e2afc..00bb502dc 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/bigram/bigram_list_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/bigram/bigram_list_policy.h
@@ -21,7 +21,7 @@
#include "defines.h"
#include "suggest/core/policy/dictionary_bigrams_structure_policy.h"
-#include "suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h"
namespace latinime {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
index b3af1f47a..30dcfba37 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
@@ -24,6 +24,7 @@
#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
#include "suggest/policyimpl/dictionary/utils/probability_utils.h"
+#include "utils/char_utils.h"
namespace latinime {
@@ -318,12 +319,15 @@ int PatriciaTriePolicy::createAndGetLeavingChildNode(const DicNode *const dicNod
PatriciaTrieReadingUtils::readPtNodeInfo(mDictRoot, ptNodePos, getShortcutsStructurePolicy(),
getBigramsStructurePolicy(), &flags, &mergedNodeCodePointCount, mergedNodeCodePoints,
&probability, &childrenPos, &shortcutPos, &bigramPos, &siblingPos);
- childDicNodes->pushLeavingChild(dicNode, ptNodePos, childrenPos, probability,
- PatriciaTrieReadingUtils::isTerminal(flags),
- PatriciaTrieReadingUtils::hasChildrenInFlags(flags),
- PatriciaTrieReadingUtils::isBlacklisted(flags)
- || PatriciaTrieReadingUtils::isNotAWord(flags),
- mergedNodeCodePointCount, mergedNodeCodePoints);
+ // Skip PtNodes don't start with Unicode code point because they represent non-word information.
+ if (CharUtils::isInUnicodeSpace(mergedNodeCodePoints[0])) {
+ childDicNodes->pushLeavingChild(dicNode, ptNodePos, childrenPos, probability,
+ PatriciaTrieReadingUtils::isTerminal(flags),
+ PatriciaTrieReadingUtils::hasChildrenInFlags(flags),
+ PatriciaTrieReadingUtils::isBlacklisted(flags)
+ || PatriciaTrieReadingUtils::isNotAWord(flags),
+ mergedNodeCodePointCount, mergedNodeCodePoints);
+ }
return siblingPos;
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
index 85f46603e..54d1e0f6d 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
@@ -22,9 +22,9 @@
#include "defines.h"
#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
-#include "suggest/policyimpl/dictionary/bigram/bigram_list_policy.h"
#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/shortcut/shortcut_list_policy.h"
+#include "suggest/policyimpl/dictionary/structure/v2/bigram/bigram_list_policy.h"
+#include "suggest/policyimpl/dictionary/structure/v2/shortcut/shortcut_list_policy.h"
#include "suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.h"
#include "suggest/policyimpl/dictionary/structure/v2/ver2_pt_node_array_reader.h"
#include "suggest/policyimpl/dictionary/utils/format_utils.h"
@@ -88,8 +88,8 @@ class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
return false;
}
- bool addBigramWords(const int *const word0, const int length0, const int *const word1,
- const int length1, const int probability, const int timestamp) {
+ bool addBigramWords(const int *const word0, const int length0,
+ const BigramProperty *const bigramProperty) {
// This method should not be called for non-updatable dictionary.
AKLOGI("Warning: addBigramWords() is called for non-updatable dictionary.");
return false;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/shortcut/shortcut_list_policy.h
index 6d2b4778c..8e16ccc05 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/shortcut/shortcut_list_policy.h
@@ -21,7 +21,7 @@
#include "defines.h"
#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
-#include "suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h"
namespace latinime {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.cpp
index 1645039d3..7a52fd180 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.cpp
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#include "suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h"
+#include "suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h"
-#include "suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.h"
+#include "suggest/core/dictionary/property/bigram_property.h"
#include "suggest/policyimpl/dictionary/header/header_policy.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h"
#include "suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h"
#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h"
#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
@@ -49,13 +50,12 @@ void Ver4BigramListPolicy::getNextBigram(int *const outBigramPos, int *const out
}
bool Ver4BigramListPolicy::addNewEntry(const int terminalId, const int newTargetTerminalId,
- const int newProbability, const int timestamp, bool *const outAddedNewEntry) {
+ const BigramProperty *const bigramProperty, bool *const outAddedNewEntry) {
// 1. The word has no bigrams yet.
// 2. The word has bigrams, and there is the target in the list.
// 3. The word has bigrams, and there is an invalid entry that can be reclaimed.
// 4. The word has bigrams. We have to append new bigram entry to the list.
// 5. Same as 4, but the list is the last entry of the content file.
-
if (outAddedNewEntry) {
*outAddedNewEntry = false;
}
@@ -69,7 +69,7 @@ bool Ver4BigramListPolicy::addNewEntry(const int terminalId, const int newTarget
const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
newTargetTerminalId);
const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(&newBigramEntry,
- newProbability, timestamp);
+ bigramProperty);
// Write an entry.
const int writingPos = mBigramDictContent->getBigramListHeadPos(terminalId);
if (!mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, writingPos)) {
@@ -102,7 +102,7 @@ bool Ver4BigramListPolicy::addNewEntry(const int terminalId, const int newTarget
const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
newTargetTerminalId);
const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(
- &newBigramEntry, newProbability, timestamp);
+ &newBigramEntry, bigramProperty);
if (!mBigramDictContent->writeBigramEntryAtTail(&bigramEntryToWrite)) {
return false;
}
@@ -128,7 +128,7 @@ bool Ver4BigramListPolicy::addNewEntry(const int terminalId, const int newTarget
const BigramEntry updatedBigramEntry =
originalBigramEntry.updateTargetTerminalIdAndGetEntry(newTargetTerminalId);
const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(
- &updatedBigramEntry, newProbability, timestamp);
+ &updatedBigramEntry, bigramProperty);
return mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, entryPosToUpdate);
}
@@ -253,19 +253,19 @@ int Ver4BigramListPolicy::getEntryPosToUpdate(const int targetTerminalIdToFind,
}
const BigramEntry Ver4BigramListPolicy::createUpdatedBigramEntryFrom(
- const BigramEntry *const originalBigramEntry, const int newProbability,
- const int timestamp) const {
+ const BigramEntry *const originalBigramEntry,
+ const BigramProperty *const bigramProperty) const {
// TODO: Consolidate historical info and probability.
if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
- // Use 1 for count to indicate the bigram has inputed.
- const HistoricalInfo historicalInfoForUpdate(timestamp, 0 /* level */, 1 /* count */);
+ const HistoricalInfo historicalInfoForUpdate(bigramProperty->getTimestamp(),
+ bigramProperty->getLevel(), bigramProperty->getCount());
const HistoricalInfo updatedHistoricalInfo =
ForgettingCurveUtils::createUpdatedHistoricalInfo(
- originalBigramEntry->getHistoricalInfo(), newProbability,
+ originalBigramEntry->getHistoricalInfo(), bigramProperty->getProbability(),
&historicalInfoForUpdate, mHeaderPolicy);
return originalBigramEntry->updateHistoricalInfoAndGetEntry(&updatedHistoricalInfo);
} else {
- return originalBigramEntry->updateProbabilityAndGetEntry(newProbability);
+ return originalBigramEntry->updateProbabilityAndGetEntry(bigramProperty->getProbability());
}
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h
index c1f33359b..1613941c4 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h
@@ -24,6 +24,7 @@
namespace latinime {
class BigramDictContent;
+class BigramProperty;
class HeaderPolicy;
class TerminalPositionLookupTable;
@@ -43,8 +44,8 @@ class Ver4BigramListPolicy : public DictionaryBigramsStructurePolicy {
// Do nothing because we don't need to skip bigram lists in ver4 dictionaries.
}
- bool addNewEntry(const int terminalId, const int newTargetTerminalId, const int newProbability,
- const int timestamp, bool *const outAddedNewEntry);
+ bool addNewEntry(const int terminalId, const int newTargetTerminalId,
+ const BigramProperty *const bigramProperty, bool *const outAddedNewEntry);
bool removeEntry(const int terminalId, const int targetTerminalId);
@@ -60,7 +61,7 @@ class Ver4BigramListPolicy : public DictionaryBigramsStructurePolicy {
int *const outTailEntryPos) const;
const BigramEntry createUpdatedBigramEntryFrom(const BigramEntry *const originalBigramEntry,
- const int newProbability, const int timestamp) const;
+ const BigramProperty *const bigramProperty) const;
bool updateHasNextFlag(const bool hasNext, const int bigramEntryPos);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h
index fe984615c..790273541 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h
@@ -19,7 +19,7 @@
#include "defines.h"
#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
-#include "suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h"
#include "suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h"
#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h"
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
index 77ed38b89..5aa6b9a92 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
@@ -56,6 +56,7 @@ bool Ver4DictBuffers::flushHeaderAndDictBuffers(const char *const dictDirPath,
return false;
}
}
+ umask(S_IWGRP | S_IWOTH);
if (mkdir(tmpDirPath, S_IRWXU) == -1) {
AKLOGE("Cannot create directory: %s. errno: %d.", tmpDirPath, errno);
return false;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp
index 67420a252..0a435e91c 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp
@@ -95,4 +95,4 @@ const PtNodeParams Ver4PatriciaTrieNodeReader::fetchPtNodeInfoFromBufferAndProce
}
}
-}
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
index cc3a24a22..f89d3d7a0 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
@@ -17,13 +17,13 @@
#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h"
#include "suggest/core/dictionary/property/unigram_property.h"
-#include "suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h"
#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h"
#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h"
#include "suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h"
+#include "suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h"
#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
@@ -76,7 +76,7 @@ bool Ver4PatriciaTrieNodeWriter::markPtNodeAsMoved(
PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
DynamicPtReadingUtils::updateAndGetFlags(originalFlags, true /* isMoved */,
- false /* isDeleted */, false /* willBecomeNonTerminal */);
+ false /* isDeleted */, false /* willBecomeNonTerminal */);
int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
// Update flags.
if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
@@ -223,11 +223,10 @@ bool Ver4PatriciaTrieNodeWriter::writeNewTerminalPtNodeAndAdvancePosition(
}
bool Ver4PatriciaTrieNodeWriter::addNewBigramEntry(
- const PtNodeParams *const sourcePtNodeParams,
- const PtNodeParams *const targetPtNodeParam, const int probability, const int timestamp,
- bool *const outAddedNewBigram) {
+ const PtNodeParams *const sourcePtNodeParams, const PtNodeParams *const targetPtNodeParam,
+ const BigramProperty *const bigramProperty, bool *const outAddedNewBigram) {
if (!mBigramPolicy->addNewEntry(sourcePtNodeParams->getTerminalId(),
- targetPtNodeParam->getTerminalId(), probability, timestamp, outAddedNewBigram)) {
+ targetPtNodeParam->getTerminalId(), bigramProperty, outAddedNewBigram)) {
AKLOGE("Cannot add new bigram entry. terminalId: %d, targetTerminalId: %d",
sourcePtNodeParams->getTerminalId(), targetPtNodeParam->getTerminalId());
return false;
@@ -416,4 +415,4 @@ bool Ver4PatriciaTrieNodeWriter::updatePtNodeFlags(const int ptNodePos,
return true;
}
-}
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
index f20d3a241..e90bc44c0 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
@@ -76,7 +76,7 @@ class Ver4PatriciaTrieNodeWriter : public PtNodeWriter {
const UnigramProperty *const unigramProperty, int *const ptNodeWritingPos);
virtual bool addNewBigramEntry(const PtNodeParams *const sourcePtNodeParams,
- const PtNodeParams *const targetPtNodeParam, const int probability, const int timestamp,
+ const PtNodeParams *const targetPtNodeParam, const BigramProperty *const bigramProperty,
bool *const outAddedNewBigram);
virtual bool removeBigramEntry(const PtNodeParams *const sourcePtNodeParams,
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
index 9999e0692..8373dc549 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
@@ -59,13 +59,17 @@ void Ver4PatriciaTriePolicy::createAndGetAllChildDicNodes(const DicNode *const d
// valid terminal DicNode.
isTerminal = ptNodeParams.getProbability() != NOT_A_PROBABILITY;
}
+ readingHelper.readNextSiblingNode(ptNodeParams);
+ if (!ptNodeParams.representsNonWordInfo()) {
+ // Skip PtNodes that represent non-word information.
+ continue;
+ }
childDicNodes->pushLeavingChild(dicNode, ptNodeParams.getHeadPos(),
ptNodeParams.getChildrenPos(), ptNodeParams.getProbability(), isTerminal,
ptNodeParams.hasChildren(),
ptNodeParams.isBlacklisted()
|| ptNodeParams.isNotAWord() /* isBlacklistedOrNotAWord */,
ptNodeParams.getCodePointCount(), ptNodeParams.getCodePoints());
- readingHelper.readNextSiblingNode(ptNodeParams);
}
if (readingHelper.isError()) {
mIsCorrupted = true;
@@ -209,8 +213,7 @@ bool Ver4PatriciaTriePolicy::addUnigramWord(const int *const word, const int len
}
bool Ver4PatriciaTriePolicy::addBigramWords(const int *const word0, const int length0,
- const int *const word1, const int length1, const int probability,
- const int timestamp) {
+ const BigramProperty *const bigramProperty) {
if (!mBuffers->isUpdatable()) {
AKLOGI("Warning: addBigramWords() is called for non-updatable dictionary.");
return false;
@@ -220,9 +223,10 @@ bool Ver4PatriciaTriePolicy::addBigramWords(const int *const word0, const int le
mDictBuffer->getTailPosition());
return false;
}
- if (length0 > MAX_WORD_LENGTH || length1 > MAX_WORD_LENGTH) {
+ if (length0 > MAX_WORD_LENGTH
+ || bigramProperty->getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
AKLOGE("Either src word or target word is too long to insert the bigram to the dictionary. "
- "length0: %d, length1: %d", length0, length1);
+ "length0: %d, length1: %d", length0, bigramProperty->getTargetCodePoints()->size());
return false;
}
const int word0Pos = getTerminalPtNodePositionOfWord(word0, length0,
@@ -230,14 +234,14 @@ bool Ver4PatriciaTriePolicy::addBigramWords(const int *const word0, const int le
if (word0Pos == NOT_A_DICT_POS) {
return false;
}
- const int word1Pos = getTerminalPtNodePositionOfWord(word1, length1,
- false /* forceLowerCaseSearch */);
+ const int word1Pos = getTerminalPtNodePositionOfWord(
+ bigramProperty->getTargetCodePoints()->data(),
+ bigramProperty->getTargetCodePoints()->size(), false /* forceLowerCaseSearch */);
if (word1Pos == NOT_A_DICT_POS) {
return false;
}
bool addedNewBigram = false;
- if (mUpdatingHelper.addBigramWords(word0Pos, word1Pos, probability, timestamp,
- &addedNewBigram)) {
+ if (mUpdatingHelper.addBigramWords(word0Pos, word1Pos, bigramProperty, &addedNewBigram)) {
if (addedNewBigram) {
mBigramCount++;
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
index 8f981def5..b78576484 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
@@ -21,10 +21,10 @@
#include "defines.h"
#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
-#include "suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h"
#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h"
#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h"
+#include "suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h"
+#include "suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h"
#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h"
@@ -93,8 +93,8 @@ class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
bool addUnigramWord(const int *const word, const int length,
const UnigramProperty *const unigramProperty);
- bool addBigramWords(const int *const word0, const int length0, const int *const word1,
- const int length1, const int probability, const int timestamp);
+ bool addBigramWords(const int *const word0, const int length0,
+ const BigramProperty *const bigramProperty);
bool removeBigramWords(const int *const word0, const int length0, const int *const word1,
const int length1);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
index 12298d967..f31c50253 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
@@ -19,9 +19,9 @@
#include <cstring>
#include <queue>
-#include "suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h"
#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h"
+#include "suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h"
+#include "suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h"
#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
index 7bc7b0a48..80970c7f8 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
@@ -17,6 +17,10 @@
#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
#include <cstdio>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include "suggest/policyimpl/dictionary/header/header_policy.h"
#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
@@ -100,9 +104,15 @@ const char *const DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE =
/* static */ bool DictFileWritingUtils::flushBufferToFile(const char *const filePath,
const BufferWithExtendableBuffer *const buffer) {
- FILE *const file = fopen(filePath, "wb");
+ const int fd = open(filePath, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+ if (fd == -1) {
+ AKLOGE("File %s cannot be opened. errno: %d", filePath, errno);
+ ASSERT(false);
+ return false;
+ }
+ FILE *const file = fdopen(fd, "wb");
if (!file) {
- AKLOGE("File %s cannot be opened.", filePath);
+ AKLOGE("fdopen failed for the file %s. errno: %d", filePath, errno);
ASSERT(false);
return false;
}
diff --git a/native/jni/src/utils/char_utils.cpp b/native/jni/src/utils/char_utils.cpp
index adc474b4c..b17e0847d 100644
--- a/native/jni/src/utils/char_utils.cpp
+++ b/native/jni/src/utils/char_utils.cpp
@@ -22,6 +22,9 @@
namespace latinime {
+const int CharUtils::MIN_UNICODE_CODE_POINT = 0;
+const int CharUtils::MAX_UNICODE_CODE_POINT = 0x10FFFF;
+
struct LatinCapitalSmallPair {
unsigned short capital;
unsigned short small;
diff --git a/native/jni/src/utils/char_utils.h b/native/jni/src/utils/char_utils.h
index 239419d5b..634c45b04 100644
--- a/native/jni/src/utils/char_utils.h
+++ b/native/jni/src/utils/char_utils.h
@@ -86,12 +86,19 @@ class CharUtils {
return spaceCount;
}
+ static AK_FORCE_INLINE int isInUnicodeSpace(const int codePoint) {
+ return codePoint >= MIN_UNICODE_CODE_POINT && codePoint <= MAX_UNICODE_CODE_POINT;
+ }
+
static unsigned short latin_tolower(const unsigned short c);
static const std::vector<int> EMPTY_STRING;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(CharUtils);
+ static const int MIN_UNICODE_CODE_POINT;
+ static const int MAX_UNICODE_CODE_POINT;
+
/**
* Table mapping most combined Latin, Greek, and Cyrillic characters
* to their base characters. If c is in range, BASE_CHARS[c] == c
diff --git a/native/jni/src/utils/jni_data_utils.h b/native/jni/src/utils/jni_data_utils.h
index 2ce02dc05..0e393e315 100644
--- a/native/jni/src/utils/jni_data_utils.h
+++ b/native/jni/src/utils/jni_data_utils.h
@@ -65,6 +65,18 @@ class JniDataUtils {
return attributeMap;
}
+ static void outputCodePoints(JNIEnv *env, jintArray intArrayToOutputCodePoints, const int start,
+ const int maxLength, const int *const codePoints, const int codePointCount,
+ const bool needsNullTermination) {
+ const int outputCodePointCount = std::min(maxLength, codePointCount);
+ env->SetIntArrayRegion(intArrayToOutputCodePoints, start, outputCodePointCount, codePoints);
+ if (needsNullTermination && outputCodePointCount < maxLength) {
+ const int terminal = 0;
+ env->SetIntArrayRegion(intArrayToOutputCodePoints, start + outputCodePointCount,
+ 1 /* len */, &terminal);
+ }
+ }
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JniDataUtils);
};
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
index aed24c56e..35d9a4e18 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
@@ -580,7 +580,6 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
- // TODO: Add tests for bigrams when the implementation gets ready.
addUnigramWord(binaryDictionary, "aaa", DUMMY_PROBABILITY);
assertTrue(binaryDictionary.isValidWord("aaa"));
addUnigramWord(binaryDictionary, "bbb", Dictionary.NOT_A_PROBABILITY);
@@ -590,6 +589,11 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
addUnigramWord(binaryDictionary, "ccc", DUMMY_PROBABILITY);
addUnigramWord(binaryDictionary, "ccc", DUMMY_PROBABILITY);
addUnigramWord(binaryDictionary, "ccc", DUMMY_PROBABILITY);
+ addUnigramWord(binaryDictionary, "abc", DUMMY_PROBABILITY);
+ addBigramWords(binaryDictionary, "aaa", "abc", DUMMY_PROBABILITY);
+ assertTrue(binaryDictionary.isValidBigram("aaa", "abc"));
+ addBigramWords(binaryDictionary, "aaa", "bbb", Dictionary.NOT_A_PROBABILITY);
+ assertFalse(binaryDictionary.isValidBigram("aaa", "bbb"));
assertEquals(fromFormatVersion, binaryDictionary.getFormatVersion());
assertTrue(binaryDictionary.migrateTo(toFormatVersion));
@@ -600,6 +604,10 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
assertTrue(binaryDictionary.getFrequency("aaa") < binaryDictionary.getFrequency("ccc"));
addUnigramWord(binaryDictionary, "bbb", Dictionary.NOT_A_PROBABILITY);
assertTrue(binaryDictionary.isValidWord("bbb"));
+ assertTrue(binaryDictionary.isValidBigram("aaa", "abc"));
+ assertFalse(binaryDictionary.isValidBigram("aaa", "bbb"));
+ addBigramWords(binaryDictionary, "aaa", "bbb", Dictionary.NOT_A_PROBABILITY);
+ assertTrue(binaryDictionary.isValidBigram("aaa", "bbb"));
binaryDictionary.close();
dictFile.delete();
}
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
index 9ceafa705..770e76e5f 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -1245,6 +1245,12 @@ public class BinaryDictionaryTests extends AndroidTestCase {
addUnigramWord(binaryDictionary, "bbb", unigramProbability);
final int bigramProbability = 10;
addBigramWords(binaryDictionary, "aaa", "bbb", bigramProbability);
+ final int shortcutProbability = 10;
+ binaryDictionary.addUnigramWord("ccc", unigramProbability, "xxx", shortcutProbability,
+ false /* isNotAWord */, false /* isBlacklisted */, 0 /* timestamp */);
+ binaryDictionary.addUnigramWord("ddd", unigramProbability, null /* shortcutTarget */,
+ Dictionary.NOT_A_PROBABILITY, true /* isNotAWord */,
+ true /* isBlacklisted */, 0 /* timestamp */);
assertEquals(unigramProbability, binaryDictionary.getFrequency("aaa"));
assertEquals(unigramProbability, binaryDictionary.getFrequency("bbb"));
assertTrue(binaryDictionary.isValidBigram("aaa", "bbb"));
@@ -1256,5 +1262,84 @@ public class BinaryDictionaryTests extends AndroidTestCase {
assertEquals(unigramProbability, binaryDictionary.getFrequency("bbb"));
// TODO: Add tests for bigram frequency when the implementation gets ready.
assertTrue(binaryDictionary.isValidBigram("aaa", "bbb"));
+ WordProperty wordProperty = binaryDictionary.getWordProperty("ccc");
+ assertEquals(1, wordProperty.mShortcutTargets.size());
+ assertEquals("xxx", wordProperty.mShortcutTargets.get(0).mWord);
+ wordProperty = binaryDictionary.getWordProperty("ddd");
+ assertTrue(wordProperty.mIsBlacklistEntry);
+ assertTrue(wordProperty.mIsNotAWord);
+ }
+
+ public void testLargeDictMigration() {
+ testLargeDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, FormatSpec.VERSION4);
+ }
+
+ private void testLargeDictMigration(final int fromFormatVersion, final int toFormatVersion) {
+ final int UNIGRAM_COUNT = 3000;
+ final int BIGRAM_COUNT = 3000;
+ final int codePointSetSize = 50;
+ final long seed = System.currentTimeMillis();
+ final Random random = new Random(seed);
+
+ File dictFile = null;
+ try {
+ dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", fromFormatVersion);
+ } catch (IOException e) {
+ fail("IOException while writing an initial dictionary : " + e);
+ }
+ final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+
+ final ArrayList<String> words = new ArrayList<String>();
+ final ArrayList<Pair<String, String>> bigrams = new ArrayList<Pair<String,String>>();
+ final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
+ final HashMap<String, Integer> unigramProbabilities = new HashMap<String, Integer>();
+ final HashMap<Pair<String, String>, Integer> bigramProbabilities =
+ new HashMap<Pair<String, String>, Integer>();
+
+ for (int i = 0; i < UNIGRAM_COUNT; i++) {
+ final String word = CodePointUtils.generateWord(random, codePointSet);
+ final int unigramProbability = random.nextInt(0xFF);
+ addUnigramWord(binaryDictionary, word, unigramProbability);
+ if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
+ binaryDictionary.flushWithGC();
+ }
+ words.add(word);
+ unigramProbabilities.put(word, unigramProbability);
+ }
+
+ for (int i = 0; i < BIGRAM_COUNT; i++) {
+ final int word0Index = random.nextInt(words.size());
+ final int word1Index = random.nextInt(words.size());
+ if (word0Index == word1Index) {
+ continue;
+ }
+ final String word0 = words.get(word0Index);
+ final String word1 = words.get(word1Index);
+ final int bigramProbability = random.nextInt(0xF);
+ binaryDictionary.addBigramWords(word0, word1, bigramProbability,
+ BinaryDictionary.NOT_A_VALID_TIMESTAMP);
+ if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
+ binaryDictionary.flushWithGC();
+ }
+ final Pair<String, String> bigram = new Pair<String, String>(word0, word1);
+ bigrams.add(bigram);
+ bigramProbabilities.put(bigram, bigramProbability);
+ }
+ assertTrue(binaryDictionary.migrateTo(toFormatVersion));
+
+ for (final String word : words) {
+ assertEquals((int)unigramProbabilities.get(word), binaryDictionary.getFrequency(word));
+ }
+ assertEquals(unigramProbabilities.size(), Integer.parseInt(
+ binaryDictionary.getPropertyForTest(BinaryDictionary.UNIGRAM_COUNT_QUERY)));
+
+ for (final Pair<String, String> bigram : bigrams) {
+ // TODO: Add tests for bigram frequency when the implementation gets ready.
+ assertTrue(binaryDictionary.isValidBigram(bigram.first, bigram.second));
+ }
+ assertEquals(bigramProbabilities.size(), Integer.parseInt(
+ binaryDictionary.getPropertyForTest(BinaryDictionary.BIGRAM_COUNT_QUERY)));
}
}
diff --git a/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java b/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java
new file mode 100644
index 000000000..186542ae5
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2014 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.test.suitebuilder.annotation.LargeTest;
+
+import com.android.inputmethod.latin.utils.DistracterFilter;
+
+/**
+ * Unit test for DistracterFilter
+ */
+@LargeTest
+public class DistracterFilterTest extends InputTestsBase {
+ private DistracterFilter mDistracterFilter;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDistracterFilter = mLatinIME.createDistracterFilter();
+ }
+
+ public void testIsDistractorToWordsInDictionaries() {
+ final String EMPTY_PREV_WORD = null;
+ String typedWord = "alot";
+ // For this test case, we consider "alot" is a distracter to "a lot".
+ assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+
+ typedWord = "mot";
+ // For this test case, we consider "mot" is a distracter to "not".
+ assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+
+ typedWord = "wierd";
+ // For this test case, we consider "wierd" is a distracter to "weird".
+ assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+
+ typedWord = "hoe";
+ // For this test case, we consider "hoe" is a distracter to "how".
+ assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+
+ typedWord = "nit";
+ // For this test case, we consider "nit" is a distracter to "not".
+ assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+
+ typedWord = "ill";
+ // For this test case, we consider "ill" is a distracter to "I'll".
+ assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+
+ typedWord = "asdfd";
+ // For this test case, we consider "asdfd" is not a distracter to any word in dictionaries.
+ assertFalse(
+ mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+
+ typedWord = "thank";
+ // For this test case, we consider "thank" is not a distracter to any other word
+ // in dictionaries.
+ assertFalse(
+ mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
new file mode 100644
index 000000000..bb36a2a16
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Pair;
+
+/*
+ * Relevant characters for this test :
+ * Spurs the need to reorder :
+ * U+1031 MYANMAR VOWEL SIGN E : ေ
+ * U+1004 U+103A U+1039 Kinzi. It's a compound character.
+ *
+ * List of consonants :
+ * U+1000 MYANMAR LETTER KA က
+ * U+1001 MYANMAR LETTER KHA ခ
+ * U+1002 MYANMAR LETTER GA ဂ
+ * U+1003 MYANMAR LETTER GHA ဃ
+ * U+1004 MYANMAR LETTER NGA င
+ * U+1005 MYANMAR LETTER CA စ
+ * U+1006 MYANMAR LETTER CHA ဆ
+ * U+1007 MYANMAR LETTER JA ဇ
+ * U+1008 MYANMAR LETTER JHA ဈ
+ * U+1009 MYANMAR LETTER NYA ဉ
+ * U+100A MYANMAR LETTER NNYA ည
+ * U+100B MYANMAR LETTER TTA ဋ
+ * U+100C MYANMAR LETTER TTHA ဌ
+ * U+100D MYANMAR LETTER DDA ဍ
+ * U+100E MYANMAR LETTER DDHA ဎ
+ * U+100F MYANMAR LETTER NNA ဏ
+ * U+1010 MYANMAR LETTER TA တ
+ * U+1011 MYANMAR LETTER THA ထ
+ * U+1012 MYANMAR LETTER DA ဒ
+ * U+1013 MYANMAR LETTER DHA ဓ
+ * U+1014 MYANMAR LETTER NA န
+ * U+1015 MYANMAR LETTER PA ပ
+ * U+1016 MYANMAR LETTER PHA ဖ
+ * U+1017 MYANMAR LETTER BA ဗ
+ * U+1018 MYANMAR LETTER BHA ဘ
+ * U+1019 MYANMAR LETTER MA မ
+ * U+101A MYANMAR LETTER YA ယ
+ * U+101B MYANMAR LETTER RA ရ
+ * U+101C MYANMAR LETTER LA လ
+ * U+101D MYANMAR LETTER WA ဝ
+ * U+101E MYANMAR LETTER SA သ
+ * U+101F MYANMAR LETTER HA ဟ
+ * U+1020 MYANMAR LETTER LLA ဠ
+ * U+103F MYANMAR LETTER GREAT SA ဿ
+ *
+ * List of medials :
+ * U+103B MYANMAR CONSONANT SIGN MEDIAL YA ျ
+ * U+103C MYANMAR CONSONANT SIGN MEDIAL RA ြ
+ * U+103D MYANMAR CONSONANT SIGN MEDIAL WA ွ
+ * U+103E MYANMAR CONSONANT SIGN MEDIAL HA ှ
+ * U+105E MYANMAR CONSONANT SIGN MON MEDIAL NA ၞ
+ * U+105F MYANMAR CONSONANT SIGN MON MEDIAL MA ၟ
+ * U+1060 MYANMAR CONSONANT SIGN MON MEDIAL LA ၠ
+ * U+1082 MYANMAR CONSONANT SIGN SHAN MEDIAL WA ႂ
+ *
+ * Other relevant characters :
+ * U+200C ZERO WIDTH NON-JOINER
+ * U+200B ZERO WIDTH SPACE
+ */
+
+@LargeTest
+public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
+ // The tests are formatted as follows.
+ // Each test is an entry in the array of Pair arrays.
+
+ // One test is an array of pairs. Each pair contains, in the `first' member,
+ // the code points that the next key press should contain. In the `second'
+ // member is stored the string that should be in the text view after this
+ // key press.
+
+ private static final Pair[][] TESTS = {
+
+ // Tests for U+1031 MYANMAR VOWEL SIGN E : ေ
+ new Pair[] { // Type : U+1031 U+1000 U+101F ေ က ဟ
+ Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
+ Pair.create(new int[] { 0x1000 }, "\u1000\u1031"), // ကေ
+ Pair.create(new int[] { 0x101F }, "\u1000\u1031\u101F") // ကေဟ
+ },
+
+ new Pair[] { // Type : U+1000 U+1031 U+101F က ေ ဟ
+ Pair.create(new int[] { 0x1000 }, "\u1000"), // က
+ Pair.create(new int[] { 0x1031 }, "\u1000\u200B\u1031"), // က‌ေ
+ Pair.create(new int[] { 0x101F }, "\u1000\u101F\u1031") // ကဟေ
+ },
+
+ new Pair[] { // Type : U+1031 U+101D U+103E U+1018 ေ ဝ ှ ဘ
+ Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
+ Pair.create(new int[] { 0x101D }, "\u101D\u1031"), // ဝေ
+ Pair.create(new int[] { 0x103E }, "\u101D\u103E\u1031"), // ဝှေ
+ Pair.create(new int[] { 0x1018 }, "\u101D\u103E\u1031\u1018") // ဝှေဘ
+ },
+
+ new Pair[] { // Type : U+1031 U+1014 U+1031 U+1000 U+102C U+1004 U+103A U+1038 U+101C
+ // U+102C U+1038 U+104B ေ န ေ က ာ င ် း လ ာ း ။
+ Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
+ Pair.create(new int[] { 0x1014 }, "\u1014\u1031"), // နေ
+ Pair.create(new int[] { 0x1031 }, "\u1014\u1031\u1031"), // နေ‌ေ
+ Pair.create(new int[] { 0x1000 }, "\u1014\u1031\u1000\u1031"), // နေကေ
+ Pair.create(new int[] { 0x102C }, "\u1014\u1031\u1000\u1031\u102C"), // နေကော
+ Pair.create(new int[] { 0x1004 }, "\u1014\u1031\u1000\u1031\u102C\u1004"), // နေကောင
+ Pair.create(new int[] { 0x103A }, // နေကောင်
+ "\u1014\u1031\u1000\u1031\u102C\u1004\u103A"),
+ Pair.create(new int[] { 0x1038 }, // နေကောင်း
+ "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038"),
+ Pair.create(new int[] { 0x101C }, // နေကောင်းလ
+ "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038\u101C"),
+ Pair.create(new int[] { 0x102C }, // နေကောင်းလာ
+ "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038\u101C\u102C"),
+ Pair.create(new int[] { 0x1038 }, // နေကောင်းလား
+ "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038\u101C\u102C\u1038"),
+ Pair.create(new int[] { 0x104B }, // နေကောင်းလား။
+ "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038\u101C\u102C\u1038\u104B")
+ },
+
+ new Pair[] { // Type : U+1031 U+1031 U+1031 U+1000 ေ ေ ေ က
+ Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
+ Pair.create(new int[] { 0x1031 }, "\u1031\u1031"), // ေေ
+ Pair.create(new int[] { 0x1031 }, "\u1031\u1031\u1031"), // U+1031ေေေ
+ Pair.create(new int[] { 0x1000 }, "\u1031\u1031\u1000\u1031") // ေေကေ
+ },
+
+ new Pair[] { // Type : U+1031 U+1001 U+103B U+103D U+1038 ေ ခ ျ ွ း
+ Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
+ Pair.create(new int[] { 0x1001 }, "\u1001\u1031"), // ခေ
+ Pair.create(new int[] { 0x103B }, "\u1001\u103B\u1031"), // ချေ
+ Pair.create(new int[] { 0x103D }, "\u1001\u103B\u103D\u1031"), // ချွေ
+ Pair.create(new int[] { 0x1038 }, "\u1001\u103B\u103D\u1031\u1038") // ချွေး
+ },
+
+ // Tests for Kinzi U+1004 U+103A U+1039 :
+
+ /* Kinzi reordering is not implemented yet. Uncomment these tests when it is.
+
+ new Pair[] { // Type : U+1021 U+1002 (U+1004 U+103A U+1039)
+ // U+101C U+1014 U+103A အ ဂ (င ် ္) လ န ်
+ Pair.create(new int[] { 0x1021 }, "\u1021"), // အ
+ Pair.create(new int[] { 0x1002 }, "\u1021\u1002"), // အဂ
+ Pair.create(new int[] { 0x1004, 0x103A, 0x1039 }, // အင်္ဂ
+ "\u1021\u1004\u103A\u1039\u1002"),
+ Pair.create(new int[] { 0x101C }, // အင်္ဂလ
+ "\u1021\u1004\u103A\u1039\u1002\u101C"),
+ Pair.create(new int[] { 0x1014 }, // အင်္ဂလန
+ "\u1021\u1004\u103A\u1039\u1002\u101C\u1014"),
+ Pair.create(new int[] { 0x103A }, // အင်္ဂလန်
+ "\u1021\u1004\u103A\u1039\u1002\u101C\u1014\u103A")
+ },
+
+ new Pair[] { //Type : kinzi after a whole syllable U+101E U+1001 U+103B U+102D U+102F
+ // (U+1004 U+103A U+1039) U+1004 U+103A U+1038 သ ခ ျ ိ ု င ် ္ င ် း
+ Pair.create(new int[] { 0x101E }, "\u101E"), // သခ
+ Pair.create(new int[] { 0x1001 }, "\u101E\u1001"), // သခ
+ Pair.create(new int[] { 0x103B }, "\u101E\u1001\u103B"), // သချ
+ Pair.create(new int[] { 0x102D }, "\u101E\u1001\u103B\u102D"), // သချိ
+ Pair.create(new int[] { 0x102F }, "\u101E\u1001\u103B\u102D\u102F"), // သချို
+ Pair.create(new int[] { 0x1004, 0x103A, 0x1039}, // သင်္ချို
+ "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F"),
+ Pair.create(new int[] { 0x1004 }, // သင်္ချိုင
+ "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004"),
+ Pair.create(new int[] { 0x103A }, // သင်္ချိုင်
+ "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004\u103A"),
+ Pair.create(new int[] { 0x1038 }, // သင်္ချိုင်း
+ "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004\u103A\u1038")
+ },
+
+ new Pair[] { // Type : kinzi after the consonant U+101E U+1001 (U+1004 U+103A U+1039)
+ // U+103B U+102D U+102F U+1004 U+103A U+1038 သ ခ င ် ္ ျ ိ ု င ် း
+ Pair.create(new int[] { 0x101E }, "\u101E"), // သခ
+ Pair.create(new int[] { 0x1001 }, "\u101E\u1001"), // သခ
+ Pair.create(new int[] { 0x1004, 0x103A, 0x1039 }, // သင်္ခ
+ "\u101E\u1004\u103A\u1039\u1001"),
+ Pair.create(new int[] { 0x103B }, // သင်္ချ
+ "\u101E\u1004\u103A\u1039\u1001\u103B"),
+ Pair.create(new int[] { 0x102D }, // သင်္ချိ
+ "\u101E\u1004\u103A\u1039\u1001\u103B\u102D"),
+ Pair.create(new int[] { 0x102F }, // သင်္ချို
+ "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F"),
+ Pair.create(new int[] { 0x1004 }, // သင်္ချိုင
+ "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004"),
+ Pair.create(new int[] { 0x103A }, // သင်္ချိုင်
+ "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004\u103A"),
+ Pair.create(new int[] { 0x1038 }, // သင်္ချိုင်း
+ "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004\u103A\u1038")
+ },
+ */
+ };
+
+ private void doMyanmarTest(final int testNumber, final Pair[] test) {
+ int stepNumber = 0;
+ for (final Pair<int[], String> step : test) {
+ ++stepNumber;
+ final int[] input = step.first;
+ final String expectedResult = step.second;
+ if (input.length > 1) {
+ mLatinIME.onTextInput(new String(input, 0, input.length));
+ } else {
+ type(input[0]);
+ }
+ assertEquals("Myanmar reordering test " + testNumber + ", step " + stepNumber,
+ expectedResult, mEditText.getText().toString());
+ }
+ }
+
+ public void testMyanmarReordering() {
+ int testNumber = 0;
+ changeLanguage("my_MM", "CombiningRules=MyanmarReordering");
+ for (final Pair[] test : TESTS) {
+ // Small trick to reset LatinIME : setText("") and send updateSelection with values
+ // LatinIME has never seen, and cursor pos 0,0.
+ mEditText.setText("");
+ mLatinIME.onUpdateSelection(1, 1, 0, 0, -1, -1);
+ doMyanmarTest(++testNumber, test);
+ }
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index 260e534ee..09c53204b 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -299,11 +299,15 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
}
protected void changeLanguage(final String locale) {
- changeLanguageWithoutWait(locale);
+ changeLanguage(locale, null);
+ }
+
+ protected void changeLanguage(final String locale, final String combiningSpec) {
+ changeLanguageWithoutWait(locale, combiningSpec);
waitForDictionariesToBeLoaded();
}
- protected void changeLanguageWithoutWait(final String locale) {
+ protected void changeLanguageWithoutWait(final String locale, final String combiningSpec) {
mEditText.mCurrentLocale = LocaleUtils.constructLocaleFromString(locale);
// TODO: this is forcing a QWERTY keyboard for all locales, which is wrong.
// It's still better than using whatever keyboard is the current one, but we
@@ -314,7 +318,8 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
"KeyboardLayoutSet=" + SubtypeLocaleUtils.QWERTY
+ "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE
+ "," + Constants.Subtype.ExtraValue.ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE
- + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
+ + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE
+ + null == combiningSpec ? "" : ("," + combiningSpec);
final InputMethodSubtype subtype = InputMethodSubtypeCompatUtils.newInputMethodSubtype(
R.string.subtype_no_language_qwerty,
R.drawable.ic_ime_switcher_dark,
@@ -325,7 +330,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
false /* overridesImplicitlyEnabledSubtype */,
0 /* id */);
SubtypeSwitcher.getInstance().forceSubtype(subtype);
- mLatinIME.loadKeyboard();
+ mLatinIME.onCurrentInputMethodSubtypeChanged(subtype);
runMessages();
mKeyboard = mLatinIME.mKeyboardSwitcher.getKeyboard();
mLatinIME.clearPersonalizedDictionariesForTest();
diff --git a/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java b/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java
index db14b8329..0a29d8326 100644
--- a/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java
+++ b/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java
@@ -33,7 +33,8 @@ public class LatinImeStressTests extends InputTestsBase {
final int codePointSetSize = 30;
final int[] codePointSet = CodePointUtils.LATIN_ALPHABETS_LOWER;
for (int i = 0; i < switchCount; ++i) {
- changeLanguageWithoutWait(locales[random.nextInt(locales.length)]);
+ changeLanguageWithoutWait(locales[random.nextInt(locales.length)],
+ null /* combiningSpec */);
final int wordCount = random.nextInt(maxWordCountToTypeInEachIteration);
for (int j = 0; j < wordCount; ++j) {
final String word = CodePointUtils.generateWord(random, codePointSet);
@@ -50,7 +51,8 @@ public class LatinImeStressTests extends InputTestsBase {
final int codePointSetSize = 30;
final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
for (int i = 0; i < switchCount; ++i) {
- changeLanguageWithoutWait(locales[random.nextInt(locales.length)]);
+ changeLanguageWithoutWait(locales[random.nextInt(locales.length)],
+ null /* combiningSpec */);
final int wordCount = random.nextInt(maxWordCountToTypeInEachIteration);
for (int j = 0; j < wordCount; ++j) {
final String word = CodePointUtils.generateWord(random, codePointSet);