Merge remote-tracking branch 'goog/master' into mergescriptpackage

Conflicts:
	java/res/values-af/strings.xml
	java/res/values-cs/strings.xml
	java/res/values-et/strings.xml
	java/res/values-fi/strings.xml
	java/res/values-hi/strings.xml
	java/res/values-hr/strings.xml
	java/res/values-hu/strings.xml
	java/res/values-in/strings.xml
	java/res/values-ja/strings.xml
	java/res/values-ko/strings.xml
	java/res/values-lt/strings.xml
	java/res/values-lv/strings.xml
	java/res/values-ms/strings.xml
	java/res/values-pt/strings.xml
	java/res/values-ro/strings.xml
	java/res/values-ru/strings.xml
	java/res/values-sk/strings.xml
	java/res/values-sl/strings.xml
	java/res/values-sr/strings.xml
	java/res/values-sw/strings.xml
	java/res/values-tr/strings.xml
	java/res/values-vi/strings.xml
	java/res/values-zh-rCN/strings.xml
	java/res/values-zh-rTW/strings.xml

Change-Id: Ib4141aca0b35148d62d22d4f32309f890c84303a
main
Satoshi Kataoka 2012-08-06 16:04:07 +09:00
commit 44456dcbf2
159 changed files with 3839 additions and 2114 deletions

View File

@ -28,9 +28,7 @@ LOCAL_JNI_SHARED_LIBRARIES := libjni_latinime
# We want to install libjni_latinime.so to the system partition if LatinIME gets installed.
LOCAL_REQUIRED_MODULES := libjni_latinime
LOCAL_STATIC_JAVA_LIBRARIES := android-common
LOCAL_STATIC_JAVA_LIBRARIES += inputmethod-common
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4
LOCAL_STATIC_JAVA_LIBRARIES := android-common inputmethod-common android-support-v4
# Do not compress dictionary files to mmap dict data runtime
LOCAL_AAPT_FLAGS := -0 .dict

View File

@ -18,6 +18,8 @@
coreApp="true"
package="com.android.inputmethod.latin">
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
@ -26,7 +28,8 @@
<application android:label="@string/aosp_android_keyboard_ime_name"
android:icon="@drawable/ic_ime_settings"
android:backupAgent="BackupAgent"
android:killAfterRestore="false">
android:killAfterRestore="false"
android:supportsRtl="true">
<service android:name="LatinIME"
android:label="@string/aosp_android_keyboard_ime_name"

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Gebaseer op vorige woord"</string>
<string name="gesture_input" msgid="3310827802759290774">"Gebaarinvoer"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Voer \'n woord in deur die letters van \'n woord te trek"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Wys gebaarspoor"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Wys gebaar se woord"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Wys swewende voorskouwoord saam met die gebaar"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Gestoor"</string>
<string name="label_go_key" msgid="1635148082137219148">"Gaan"</string>
<string name="label_next_key" msgid="362972844525672568">"Volgende"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Soek"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punt"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Verander taal"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Volgende"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Vorige"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift geaktiveer"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Kasslot geaktiveer"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift gedeaktiveer"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"በቀዳሚው ቃል ላይ የተመሠረተ"</string>
<string name="gesture_input" msgid="3310827802759290774">"የእጅ ምልክት ግብዓት"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"የአንድ ቃል ፊደሎችን በመከታተል አንድ ቃል አስገባ"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"ምልክት የሚሄድበት መንገድ አሳይ"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"የምልክት ቃል አሳይ"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"ተንሳፋፊ የቅድመ እይታ ቃል ከምልክት ጋር አሳይ"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : ተቀምጧል"</string>
<string name="label_go_key" msgid="1635148082137219148">"ሂድ"</string>
<string name="label_next_key" msgid="362972844525672568">"በመቀጠል"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"ተመለስ"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"ፍለጋ"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"ነጥብ"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"ቋንቋ ቀይር"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"ቀጣይ"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"ቀዳሚ"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"ቅያር ቁልፍ ነቅቷል"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"አቢያት ማድረጊያ ነቅቷል"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"ቅያር ተሰናክሏል"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"استنادًا إلى الكلمة السابقة"</string>
<string name="gesture_input" msgid="3310827802759290774">"إدخال الإيماءة"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"يمكنك إدخال كلمة من خلال تتبع أحرف كلمة ما"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"عرض مسار الإيماءة"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"عرض كلمة الإيماءة"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"عرض كلمة معاينة متحركة مع الإيماءة"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : تم الحفظ"</string>
<string name="label_go_key" msgid="1635148082137219148">"تنفيذ"</string>
<string name="label_next_key" msgid="362972844525672568">"التالي"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"رجوع"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"بحث"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"نقطة"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"تبديل اللغة"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"التالي"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"السابق"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"تم تمكين Shift"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"تم تمكين Caps lock"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"تم تعطيل Shift"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"На аснове папярэдняга слова"</string>
<string name="gesture_input" msgid="3310827802759290774">"Уваход жэстам"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Увядзiце слова, адсочваючы лiтары"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Паказаць след жэста"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Паказаць слова жэста"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Паказаць плаваючы прагляд слова з жэстам"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Захаваныя"</string>
<string name="label_go_key" msgid="1635148082137219148">"Пачаць"</string>
<string name="label_next_key" msgid="362972844525672568">"Далей"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Увод"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Пошук"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Кропка"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Пераключыць мову"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Далей"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Назад"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift уключаны"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock уключаны"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift адключаны"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Въз основа на предишната дума"</string>
<string name="gesture_input" msgid="3310827802759290774">"Въвеждане чрез жест"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Въвеждане на дума чрез проследяване на буквите й"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Следа на жестовете: Показване"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Показване на дума при жестове"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Показване на дума с плаваща визуализация при жест"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Запазено"</string>
<string name="label_go_key" msgid="1635148082137219148">"Старт"</string>
<string name="label_next_key" msgid="362972844525672568">"Напред"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Търсене"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Точка"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Смяна на езика"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Следващ"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Предишен"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"„Shift“ е активиран"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"„Caps Lock“ е активиран"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"„Shift“ е деактивиран"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"En funció de la paraula anterior"</string>
<string name="gesture_input" msgid="3310827802759290774">"Entrada de gestos"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Dibuixa les lletres d\'una paraula per escriure-la"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Mostra el recorregut del gest"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Mostra paraules en fer gestos"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Mostra la paraula de visualització prèvia flotant en fer gestos"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: desada"</string>
<string name="label_go_key" msgid="1635148082137219148">"Vés"</string>
<string name="label_next_key" msgid="362972844525672568">"Següent"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Retorn"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Cerca"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punt"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Canvia l\'idioma"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Següent"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Anterior"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Maj activat"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Bloq Maj activat"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Maj desactivat"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Na základě předchozího slova"</string>
<string name="gesture_input" msgid="3310827802759290774">"Zadávání gesty"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Napište slovo zadáním jeho písmen."</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Zobrazovat stopu gesta"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Zobrazovat slovo gesta"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Zobrazovat plovoucí náhled slova gesta"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Uloženo"</string>
<string name="label_go_key" msgid="1635148082137219148">"Přejít"</string>
<string name="label_next_key" msgid="362972844525672568">"Další"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"vyhledávací tlačítko"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Tečka"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Přepnout jazyk"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Další"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Předchozí"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Klávesa Shift je aktivní"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Klávesa Caps Lock je aktivní"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Klávesa Shift je neaktivní"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Baseret på tidligere ord"</string>
<string name="gesture_input" msgid="3310827802759290774">"Berøringsindtastning"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Indtast et ord ved at skrive bogstaverne for et ord med fingeren"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Vis spor af berøring"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Vis berøringsord"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Vis flydende eksempelord under berøring"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Gemt"</string>
<string name="label_go_key" msgid="1635148082137219148">"Gå"</string>
<string name="label_next_key" msgid="362972844525672568">"Næste"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Tilbage"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Søg"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punktum"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Skift sprog"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Næste"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Forrige"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Skift er aktiveret"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock er aktiveret"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Skift er deaktiveret"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Auf Grundlage des vorherigen Wortes"</string>
<string name="gesture_input" msgid="3310827802759290774">"Bewegungseingabe"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Wort durch Nachzeichnen der Buchstaben eingeben"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Spur der Bewegung anzeigen"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Wort bei Bewegung anzeigen"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Vorgeschlagenes Wort bei Bewegung anzeigen"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: gespeichert"</string>
<string name="label_go_key" msgid="1635148082137219148">"Los"</string>
<string name="label_next_key" msgid="362972844525672568">"Weiter"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Eingabe"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Suchen"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Aufzählungspunkt"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Sprache wechseln"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Nächste"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Vorherige"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Umschalttaste aktiviert"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Feststelltaste aktiviert"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Umschalttaste deaktiviert"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Βάσει προηγούμενης λέξης"</string>
<string name="gesture_input" msgid="3310827802759290774">"Καταχώριση κίνησης"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Καταχώριση μιας λέξης με εντοπισμό των γραμμάτων μιας λέξης"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Εμφάνιση διαδρομής χειρονομίας"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Εμφάνιση λέξης χειρονομίας"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Εμφάνιση κινούμενης προεπισκόπησης λέξης με χειρονομία"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Αποθηκεύτηκε"</string>
<string name="label_go_key" msgid="1635148082137219148">"Μετ."</string>
<string name="label_next_key" msgid="362972844525672568">"Επόμενο"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Πλήκτρο Return"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Αναζήτηση"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Κουκκίδα"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Αλλαγή γλώσσας"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Επόμενο"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Προηγούμενο"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Το Shift ενεργοποιημένο"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Το Caps lock είναι ενεργοποιημένο"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Το Shift είναι απενεργοποιημένο"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Based on previous word"</string>
<string name="gesture_input" msgid="3310827802759290774">"Gesture input"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Input a word by tracing the letters of a word"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Show gesture trail"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Show gesture word"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Show floating preview word with gesture"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Saved"</string>
<string name="label_go_key" msgid="1635148082137219148">"Go"</string>
<string name="label_next_key" msgid="362972844525672568">"Next"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Search"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Dot"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Switch language"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Next"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Previous"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift enabled"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock enabled"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift disabled"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Según la palabra anterior"</string>
<string name="gesture_input" msgid="3310827802759290774">"Entrada de gestos"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Ingresa una palabra trazando sus letras."</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Mostrar recorrido de gesto"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Mostrar palabra de gesto"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Mostrar palabra de vista previa flotante al realizar gestos"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string>
<string name="label_go_key" msgid="1635148082137219148">"Ir"</string>
<string name="label_next_key" msgid="362972844525672568">"Siguiente"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Volver"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Buscar"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punto"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Cambiar idioma"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Siguiente"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Anterior"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Se activó el modo Mayúscula."</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Se activó el bloqueo de mayúsculas."</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Se desactivó el modo Mayúscula"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Según la palabra anterior"</string>
<string name="gesture_input" msgid="3310827802759290774">"Entrada de gestos"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Trazar las letras de una palabra para introducirla"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Mostrar recorrido del gesto"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Mostrar palabra del gesto"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Mostrar la palabra de vista previa flotante al realizar un gesto"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string>
<string name="label_go_key" msgid="1635148082137219148">"Ir"</string>
<string name="label_next_key" msgid="362972844525672568">"Sig."</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Tecla Intro"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Buscar"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punto"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Cambiar idioma"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Siguiente"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Anterior"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Mayúsculas habilitadas"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Bloqueo de mayúsculas habilitado"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Mayúsculas inhabilitadas"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Eelmise sõna põhjal"</string>
<string name="gesture_input" msgid="3310827802759290774">"Liigutusega sisest."</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Sisestage sõna, kirjutades sõna tähed sõrmega"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Näita liigutuse jälge"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Näita liigutuse sõna"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Ujuva sõna eelvaate näitamine koos liigutusega"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : salvestatud"</string>
<string name="label_go_key" msgid="1635148082137219148">"Mine"</string>
<string name="label_next_key" msgid="362972844525672568">"Edasi"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Tagasi"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Otsing"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punkt"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Keele vahetamine"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Järgmine"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Eelmine"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Tõstuklahv on lubatud"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Suurtähelukk on lubatud"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Tõstuklahv on keelatud"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"بر اساس کلمه قبلی"</string>
<string name="gesture_input" msgid="3310827802759290774">"ورودی اشاره"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"با دنبال کردن حروف یک کلمه، کلمه را وارد کنید"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"نمایش نسخه آزمایشی حرکت"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"نمایش کلمه در طول ورودی حرکتی"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"نمایش کلمه پیش‌نمایش متحرک با حرکت"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : ذخیره شد"</string>
<string name="label_go_key" msgid="1635148082137219148">"برو"</string>
<string name="label_next_key" msgid="362972844525672568">"بعدی"</string>
@ -94,6 +97,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"جستجو"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"نقطه"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"تغییر زبان"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"بعدی"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"قبلی"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift فعال است"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock فعال شد"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift غیرفعال است"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Perustuu edelliseen sanan"</string>
<string name="gesture_input" msgid="3310827802759290774">"Eleiden syöttö"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Syötä sana piirtämällä kirjaimet sormella"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Näytä eleen jälki"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Näytä elesanat"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Näytä eleen yhteydessä kelluva esikatselusana"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Tallennettu"</string>
<string name="label_go_key" msgid="1635148082137219148">"Siirry"</string>
<string name="label_next_key" msgid="362972844525672568">"Seur."</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Haku"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Piste"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Vaihda kieli"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Seuraava"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Edellinen"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Vaihto päällä"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock päällä"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Vaihto pois käytöstä"</string>

View File

@ -25,5 +25,7 @@
<!-- Symbols that should promote magic spaces into real space -->
<string name="phantom_space_promoting_symbols">;:!?([*&amp;@{&lt;&gt;+=|</string>
<!-- Symbols that do NOT separate words -->
<string name="symbols_excluded_from_word_separators">\'</string>
<!-- Note that this is identical to the default value, but since the above ones are different
and those variables only make sense together, this is kept here for readability. -->
<string name="symbols_excluded_from_word_separators">\'-</string>
</resources>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Suggestions basées sur le mot précédent"</string>
<string name="gesture_input" msgid="3310827802759290774">"Saisie gestuelle"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Saisir un mot en traçant ses lettres avec le doigt"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Afficher le tracé du geste"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Afficher un mot lors du geste"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Afficher un aperçu flottant du mot lors de la saisie gestuelle"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : enregistré"</string>
<string name="label_go_key" msgid="1635148082137219148">"OK"</string>
<string name="label_next_key" msgid="362972844525672568">"Suiv."</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Entrée"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Rechercher"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Point"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Changer de langue"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Touche suivante"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Touche précédente"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Touche Maj activée"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Verrouillage des majuscules activé"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Touche Maj désactivée"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"पिछले शब्द के आधार पर"</string>
<string name="gesture_input" msgid="3310827802759290774">"जेस्‍चर इनपुट"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"किसी शब्द के अक्षरों को ट्रेस करके कोई शब्द इनपुट करें"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"जेस्चर ट्रेल दिखाएं"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"जेस्चर शब्द दिखाएं"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"जेस्चर के साथ फ़्लोटिंग पूर्वावलोकन शब्द दिखाएं"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: सहेजा गया"</string>
<string name="label_go_key" msgid="1635148082137219148">"जाएं"</string>
<string name="label_next_key" msgid="362972844525672568">"अगला"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"रिटर्न"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"खोजें"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"बिंदु"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"भाषा स्विच करें"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"अगला"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"पिछला"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift सक्षम किया गया"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock सक्षम किया गया"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift अक्षम किया गया"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Na temelju prethodne riječi"</string>
<string name="gesture_input" msgid="3310827802759290774">"Unos pokretom"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Unos riječi ispisivanjem slova riječi"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Prikaži trag pokreta"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Prikaži riječ pokreta"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Prikaži lebdeći pregled riječi uz pokret"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Spremljeno"</string>
<string name="label_go_key" msgid="1635148082137219148">"Idi"</string>
<string name="label_next_key" msgid="362972844525672568">"Dalje"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Pretraživanje"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Točka"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Promijeni jezik"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Sljedeće"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Prethodno"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Omogućena tipka Shift"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Omogućeno pisanje velikih slova"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Onemogućena tipka Shift"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Az előző szó alapján"</string>
<string name="gesture_input" msgid="3310827802759290774">"Kézi bevitel"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Szó beírása a betűk megrajzolásával"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Mozdulat irányának mutatása"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Mozdulatot leíró szó mutatása"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Mozdulatot leíró szó mutatása lebegő előnézetben"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : mentve"</string>
<string name="label_go_key" msgid="1635148082137219148">"Ugrás"</string>
<string name="label_next_key" msgid="362972844525672568">"Tovább"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Keresés"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Pont"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Nyelvek felcserélése"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Következő"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Előző"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift bekapcsolva"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock bekapcsolva"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift kikapcsolva"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Berdasarkan kata sebelumnya"</string>
<string name="gesture_input" msgid="3310827802759290774">"Masukan isyarat"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Masukkan kata dengan melacak huruf dari sebuah kata"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Tampilkan jalur isyarat"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Tampilkan kata isyarat"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Tampilkan kata pratinjau melayang dengan isyarat"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Telah disimpan"</string>
<string name="label_go_key" msgid="1635148082137219148">"Buka"</string>
<string name="label_next_key" msgid="362972844525672568">"Berikutnya"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Kembali"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Telusuri"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Titik"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Ganti bahasa"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Berikutnya"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Sebelumnya"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift diaktifkan"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock diaktifkan"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift dinonaktifkan"</string>

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2009, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Symbols that do NOT separate words -->
<string name="symbols_excluded_from_word_separators"></string>
</resources>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"In base alla parola precedente"</string>
<string name="gesture_input" msgid="3310827802759290774">"Inserimento con gesti"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Inserisci una parola tracciandone le lettere"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Mostra traccia con gesto"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Mostra parola con gesto"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Mostra parola di anteprima floating con gesto"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : parola salvata"</string>
<string name="label_go_key" msgid="1635148082137219148">"Vai"</string>
<string name="label_next_key" msgid="362972844525672568">"Avanti"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Invio"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Cerca"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Pallino"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Cambia lingua"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Successivo"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Precedente"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Maiuscolo attivo"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Blocco maiuscole attivo"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Maiuscolo disattivato"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"בהתבסס על המילה הקודמת"</string>
<string name="gesture_input" msgid="3310827802759290774">"קלט מחווה"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"הזן מילה על ידי החלקת האצבע מאות לאות"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"הצג שובל מחווה"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"הצג מילת מחווה"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"הצג תצוגה מקדימה צפה של המילה בזמן המחווה"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : נשמרה"</string>
<string name="label_go_key" msgid="1635148082137219148">"בצע"</string>
<string name="label_next_key" msgid="362972844525672568">"הבא"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"חזור"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"חיפוש"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"נקודה"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"החלף שפה"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"הבא"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"הקודם"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift מופעל"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock מופעל"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift מושבת"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"前の語句に基づいた入力候補表示"</string>
<string name="gesture_input" msgid="3310827802759290774">"ジェスチャー入力"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"単語の文字をトレースして単語を入力"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"ジェスチャートレイルを表示"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"ジェスチャーワードを表示"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"ジェスチャーでプレビューワードをフローティング表示できます"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:保存しました"</string>
<string name="label_go_key" msgid="1635148082137219148">"実行"</string>
<string name="label_next_key" msgid="362972844525672568">"次へ"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"検索"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"中点"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"言語を切り替え"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"次へ"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"前へ"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift有効"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock有効"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift解除"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"이전 단어에 기반한 추천"</string>
<string name="gesture_input" msgid="3310827802759290774">"동작 입력"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"한번에 문자를 그려서 단어 입력"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"동작 흔적 표시"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"동작 단어 표시"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"동작에 따라 단어 미리보기 표시"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: 저장됨"</string>
<string name="label_go_key" msgid="1635148082137219148">"이동"</string>
<string name="label_next_key" msgid="362972844525672568">"다음"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"리턴 키"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"검색"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"점"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"언어 전환"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"다음"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"이전"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift 사용"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock 사용"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift 사용중지"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Pagal ankstesnį žodį"</string>
<string name="gesture_input" msgid="3310827802759290774">"Įvestis gestais"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Įveskite žodį brėždami jo raides"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Rodyti gestų kelią"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Rodyti gesto žodį"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Rodyti kintantį peržiūros žodį gestu"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: išsaugota"</string>
<string name="label_go_key" msgid="1635148082137219148">"Pradėti"</string>
<string name="label_next_key" msgid="362972844525672568">"Kitas"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Grįžti"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Ieškoti"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Taškas"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Keisti kalbą"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Kitas"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Ankstesnis"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Įgalintas antrasis lygis"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Įgalintos didžiosios raidės"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Antrasis lygis išjungtas"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Pamatojoties uz iepriekšējo vārdu"</string>
<string name="gesture_input" msgid="3310827802759290774">"Ievade ar žestu"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Ievadiet vārdu, norādot tā burtus."</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Rādīt žesta pēdas"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Rādīt žesta vārdu"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Rādīt peldošo priekšskatījuma vārdu ar žestu"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: saglabāts"</string>
<string name="label_go_key" msgid="1635148082137219148">"Sākt"</string>
<string name="label_next_key" msgid="362972844525672568">"Tālāk"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Ievadīšanas taustiņš"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Meklēt"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punkts"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Mainīt valodu"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Nākamā"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Iepriekšējā"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Pārslēgšanas režīms iespējots"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Burtslēgs iespējots"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Pārslēgšanas režīms atspējots"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Berdasarkan perkataan sebelumnya"</string>
<string name="gesture_input" msgid="3310827802759290774">"Input gerak isyarat"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Masukkan perkataan dengan menyurih huruf perkataan itu."</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Tunjukkan jejak gerak isyarat"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Tunjukkan perkataan gerak isyarat"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Tunjukkan perkataan pratonton terapung dengan gerak isyarat"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Disimpan"</string>
<string name="label_go_key" msgid="1635148082137219148">"Pergi"</string>
<string name="label_next_key" msgid="362972844525672568">"Seterusnya"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Carian"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Titik"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Tukar bahasa"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Seterusnya"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Sebelumnya"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Kunci anjak didayakan"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Kunci huruf besar didayakan"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Kunci anjak dilumpuhkan"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Basert på det forrige ordet"</string>
<string name="gesture_input" msgid="3310827802759290774">"Bevegelseskommandoer"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Angi et ord ved å skrive bokstavene på skjermen med fingeren"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Vis bevegelsesspor"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Vis bevegelsesord"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Vis flytende forhåndsvisningsord under bevegelser"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Lagret"</string>
<string name="label_go_key" msgid="1635148082137219148">"Utfør"</string>
<string name="label_next_key" msgid="362972844525672568">"Neste"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Søk"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Prikk"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Bytt språk"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Neste"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Forrige"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift er aktivert"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock er aktivert"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift er deaktivert"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Op basis van het vorige woord"</string>
<string name="gesture_input" msgid="3310827802759290774">"Invoer met gebaren"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Voer een woord in door de letters van een woord te volgen"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Gebarenspoor weergeven"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Woord met gebaar weergeven"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Zwevend voorbeeldwoord met gebaar weergeven"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: opgeslagen"</string>
<string name="label_go_key" msgid="1635148082137219148">"Start"</string>
<string name="label_next_key" msgid="362972844525672568">"Verder"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Zoeken"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Stip"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Taal wijzigen"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Volgende"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Vorige"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift ingeschakeld"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock ingeschakeld"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift uitgeschakeld"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Na podstawie poprzedniego słowa"</string>
<string name="gesture_input" msgid="3310827802759290774">"Wprowadzanie gestem"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Podaj słowo, pisząc litery palcem"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Pokazuj ślad gestu"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Podpowiadaj przy pisaniu gestem"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Pokazuj pływający podgląd słowa podczas pisania gestem"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Zapisano"</string>
<string name="label_go_key" msgid="1635148082137219148">"OK"</string>
<string name="label_next_key" msgid="362972844525672568">"Dalej"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Szukaj"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punkt"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Przełącz język"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Dalej"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Wstecz"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift włączony"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock włączony"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift wyłączony"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Com base na palavra anterior"</string>
<string name="gesture_input" msgid="3310827802759290774">"Introd. por gestos"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Introduza uma palavra, desenhando as letras de uma palavra"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Mostrar percurso do gesto"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Mostrar palavra gesto"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Mostrar palavra de visualização flutuante com gesto"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string>
<string name="label_go_key" msgid="1635148082137219148">"OK"</string>
<string name="label_next_key" msgid="362972844525672568">"Avançar"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Pesquisar"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Ponto"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Mudar de idioma"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Seguinte"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Anterior"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift ativado"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock ativado"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift desativado"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Com base na palavra anterior"</string>
<string name="gesture_input" msgid="3310827802759290774">"Entrada por gesto"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Introduza uma palavra traçando suas letras"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Mostrar percurso do gesto"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Mostrar palavra do gesto"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Mostrar visualização flutuante da palavra com gesto"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Salvo"</string>
<string name="label_go_key" msgid="1635148082137219148">"Ir"</string>
<string name="label_next_key" msgid="362972844525672568">"Avançar"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Voltar"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Pesquisar"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Ponto"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Alterar idioma"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Próximo"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Anterior"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift ativado"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock ativado"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift desativado"</string>

View File

@ -96,6 +96,12 @@
<skip />
<!-- no translation found for gesture_input_summary (7019742443455085809) -->
<skip />
<!-- no translation found for gesture_preview_trail (3802333369335722221) -->
<skip />
<!-- no translation found for gesture_floating_preview_text (6859416520117939680) -->
<skip />
<!-- no translation found for gesture_floating_preview_text_summary (3333754126434989709) -->
<skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Memorisà"</string>
<string name="label_go_key" msgid="1635148082137219148">"Dai"</string>
<string name="label_next_key" msgid="362972844525672568">"Vinavant"</string>
@ -151,6 +157,12 @@
<skip />
<!-- no translation found for spoken_description_dot (40711082435231673) -->
<skip />
<!-- no translation found for spoken_description_language_switch (5507091328222331316) -->
<skip />
<!-- no translation found for spoken_description_action_next (8636078276664150324) -->
<skip />
<!-- no translation found for spoken_description_action_previous (800872415009336208) -->
<skip />
<!-- no translation found for spoken_description_shiftmode_on (5700440798609574589) -->
<skip />
<!-- no translation found for spoken_description_shiftmode_locked (593175803181701830) -->

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Bazate pe cuvântul precedent"</string>
<string name="gesture_input" msgid="3310827802759290774">"Utilizaţi gesturi"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Introduceţi un cuvânt desenând literele acestuia"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Se afişează urma gestului"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Sugestie cuvinte la gesturi"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Se afişează previzualizarea cuvântului flotant la gesturi"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: salvat"</string>
<string name="label_go_key" msgid="1635148082137219148">"OK"</string>
<string name="label_next_key" msgid="362972844525672568">"Înainte"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Căutaţi"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punct"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Schimbaţi limba"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Înainte"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Înapoi"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Tasta Shift a fost activată"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Tasta Caps Lock a fost activată"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Tasta Shift a fost dezactivată"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Подсказки, основанные на предыдущих словах"</string>
<string name="gesture_input" msgid="3310827802759290774">"Ввод жестами"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Перемещайте палец от буквы к букве, чтобы составить слово"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Рисовать линию"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Подсказывать слово"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Показывать подсказку во время ввода"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: сохранено"</string>
<string name="label_go_key" msgid="1635148082137219148">"Поиск"</string>
<string name="label_next_key" msgid="362972844525672568">"Далее"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Клавиша \"Ввод\""</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Поиск"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Точка"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Сменить язык"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Далее"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Назад"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Верхний регистр включен"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock включен"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Верхний регистр отключен"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Na základe predchádzajúceho slova"</string>
<string name="gesture_input" msgid="3310827802759290774">"Zadávanie gestami"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Napíšte slovo zadaním jeho písmen"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Zobrazovať stopu gesta"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Zobrazovať slovo gesta"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Zobrazovať plávajúcu ukážku slova gesta"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Uložené"</string>
<string name="label_go_key" msgid="1635148082137219148">"Hľadať"</string>
<string name="label_next_key" msgid="362972844525672568">"Ďalej"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Hľadať"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Bodka"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Prepnúť jazyk"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Ďalšie"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Predchádzajúce"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Kláves Shift je povolený"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Kláves Caps Lock je povolený"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Kláves Shift je zakázaný"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Na podlagi prejšnje besede"</string>
<string name="gesture_input" msgid="3310827802759290774">"Vnos s potezo"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Vnašanje besede z drsenjem po zaslonu od črke do črke"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Prikaži pot poteze"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Pokaži besedo za potezo"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Pokaži plavajoči predogled besede za potezo"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: shranjeno"</string>
<string name="label_go_key" msgid="1635148082137219148">"Pojdi"</string>
<string name="label_next_key" msgid="362972844525672568">"Naprej"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Vračalka"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Iskanje"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Pika"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Preklop jezika"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Naprej"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Nazaj"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Način »Shift« je omogočen"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Način »Caps Lock« je omogočen"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Način »Shift« je onemogočen"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"На основу претходне речи"</string>
<string name="gesture_input" msgid="3310827802759290774">"Унос покретом"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Унесите реч исписивањем слова речи"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Прикажи траг покрета"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Прикажи реч уз покрет"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Приказ плутајућег прегледа речи уз покрет"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Сачувано"</string>
<string name="label_go_key" msgid="1635148082137219148">"Иди"</string>
<string name="label_next_key" msgid="362972844525672568">"Следеће"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Претражи"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Тачка"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Пребаци језик"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Следеће"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Претходно"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift је омогућен"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock је омогућен"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift је онемогућен"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Baserat på föregående ord"</string>
<string name="gesture_input" msgid="3310827802759290774">"Gestinmatning"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Skriv ett ord för hand genom att rita bokstäverna i ordet"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Visa spår efter rörelse"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Visa svävande ord för rörelse"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Visa förhandsgranskning av svävande ord med rörelse"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: sparat"</string>
<string name="label_go_key" msgid="1635148082137219148">"Kör"</string>
<string name="label_next_key" msgid="362972844525672568">"Nästa"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Retur"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Sök"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punkt"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Byt språk"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Nästa"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Föregående"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Skift är aktiverat"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock är aktiverat"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Skift är inaktiverat"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Kulingana na neno la awali"</string>
<string name="gesture_input" msgid="3310827802759290774">"Ingizo la ishara"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Ingiza neno kwa kufuatilia herufi za neno"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Onyesha njia ya ishara"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Onyesha neno la ishara"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Onyesha neno hakiki linaloelea lililo na ishara"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Imehifadhiwa"</string>
<string name="label_go_key" msgid="1635148082137219148">"Nenda"</string>
<string name="label_next_key" msgid="362972844525672568">"Ifuatayo"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Rudi"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Tafuta"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Nukta"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Badili lugha"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Inayofuata"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Iliyotangulia"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift imewezeshwa"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock imewezeshwa"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift imelemazwa"</string>

View File

@ -19,6 +19,8 @@
-->
<resources>
<!-- Device form factor. This value must be aligned with {@link KeyboardId.DEVICE_FORM_FACTOR_TABLET7} -->
<integer name="config_device_form_factor">1</integer>
<bool name="config_enable_show_voice_key_option">false</bool>
<bool name="config_enable_show_popup_on_keypress_option">false</bool>
<bool name="config_enable_bigram_suggestions_option">false</bool>

View File

@ -19,6 +19,8 @@
-->
<resources>
<!-- Device form factor. This value must be aligned with {@link KeyboardId.DEVICE_FORM_FACTOR_TABLET10} -->
<integer name="config_device_form_factor">2</integer>
<bool name="config_enable_show_voice_key_option">false</bool>
<bool name="config_enable_show_popup_on_keypress_option">false</bool>
<bool name="config_enable_bigram_suggestions_option">false</bool>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"ตามคำก่อนหน้า"</string>
<string name="gesture_input" msgid="3310827802759290774">"ป้อนท่าทางสัมผัส"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"ป้อนคำโดยลากนิ้วเป็นรูปตัวอักษรที่อยู่ในคำ โดยไม่ยกนิ้วขึ้น"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"แสดงรอยทางเดินของท่าทาง"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"แสดงคำแนะนำท่าทาง"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"แสดงตัวอย่างคำแนะนำพร้อมด้วยท่าทาง"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : บันทึกแล้ว"</string>
<string name="label_go_key" msgid="1635148082137219148">"ไป"</string>
<string name="label_next_key" msgid="362972844525672568">"ถัดไป"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"ค้นหา"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"เครื่องหมายจุด"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"เปลี่ยนภาษา"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"ถัดไป"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"ก่อนหน้า"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"เปิดใช้งาน Shift แล้ว"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"เปิดใช้งาน Caps Lock แล้ว"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"ปิดใช้งาน Shift แล้ว"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Batay sa nakaraang salita"</string>
<string name="gesture_input" msgid="3310827802759290774">"Pagpasok ng galaw"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Magpasok ng salita sa gamit ang pagsulat sa mga titik ng salita"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Ipakita ang trail ng galaw"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Ipakita ang salita ng galaw"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Ipakita ang lumulutang na preview ng salita na may galaw"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Na-save"</string>
<string name="label_go_key" msgid="1635148082137219148">"Punta"</string>
<string name="label_next_key" msgid="362972844525672568">"Susunod"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Bumalik"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Paghahanap"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Tuldok"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Magpalit ng wika"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Susunod"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Nakaraan"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Pinagana ang shift"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Pinagana ang caps lock"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Hindi pinagana ang shift"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Önceki kelimeye dayanarak"</string>
<string name="gesture_input" msgid="3310827802759290774">"Hareket girişi"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Bir kelimeyi harflerini izleyerek girin"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Hareket izini göster"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Hareketle yazılan kelimeyi göster"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Hareketle kayan önizleme kelimesini göster"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Kaydedildi"</string>
<string name="label_go_key" msgid="1635148082137219148">"Git"</string>
<string name="label_next_key" msgid="362972844525672568">"İleri"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Ara"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Nokta"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Dili değiştir"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Sonraki"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Önceki"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Üst karakter etkin"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Büyük harf kilidi etkin"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Üst karakter devre dışı"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"На основі попереднього слова"</string>
<string name="gesture_input" msgid="3310827802759290774">"Введення жестами"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Введіть слово, малюючи літери, з яких воно складається"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Показувати слід жестів"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Показувати слово для жесту"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Показувати спливаючий перегляд слова під час жесту"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : збережено"</string>
<string name="label_go_key" msgid="1635148082137219148">"Іти"</string>
<string name="label_next_key" msgid="362972844525672568">"Далі"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Клавіша Return"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Пошук"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Крапка"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Змінити мову"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Далі"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Назад"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift увімкнено"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock увімкнено"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift вимкнено"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Dựa trên từ trước đó"</string>
<string name="gesture_input" msgid="3310827802759290774">"Nhập bằng cử chỉ"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Nhập từ bằng cách lần theo các chữ cái của từ"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Hiển thị vệt cử chỉ"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Hiển thị từ theo cử chỉ"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Hiển thị từ xem trước nổi bằng cử chỉ"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Đã lưu"</string>
<string name="label_go_key" msgid="1635148082137219148">"Tìm"</string>
<string name="label_next_key" msgid="362972844525672568">"Tiếp theo"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Quay lại"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Tìm kiếm"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Dấu chấm"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Chuyển ngôn ngữ"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Tiếp theo"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Trước"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Đã bật Shift"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Đã bật Caps lock"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Đã tắt Shift"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"根据上一个字词提供建议"</string>
<string name="gesture_input" msgid="3310827802759290774">"手势输入"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"连笔书写输入字词"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"显示手指操作轨迹"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"显示手指操作文字"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"进行手指操作时显示浮动预览文字"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:已保存"</string>
<string name="label_go_key" msgid="1635148082137219148">"开始"</string>
<string name="label_next_key" msgid="362972844525672568">"下一步"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"返回"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"搜索"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"点"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"切换语言"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"下一个"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"上一个"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift 模式已启用"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"大写锁定已启用"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift 模式已停用"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"根據上一個字詞產生"</string>
<string name="gesture_input" msgid="3310827802759290774">"手勢輸入"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"以手指寫出字詞中字母的方式來輸入字詞"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"顯示手勢軌跡"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"顯示手勢字詞"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"使用手勢輸入時顯示浮動預覽字詞"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:已儲存"</string>
<string name="label_go_key" msgid="1635148082137219148">"開始"</string>
<string name="label_next_key" msgid="362972844525672568">"繼續"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"返回"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"搜尋"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"點"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"切換語言"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"下一步"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"上一步"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift 鍵已啟用"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"大寫鎖定已啟用"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift 鍵已停用"</string>

View File

@ -60,6 +60,9 @@
<string name="bigram_prediction_summary" msgid="3253961591626441019">"Ngokususela egameni langaphambilini"</string>
<string name="gesture_input" msgid="3310827802759290774">"Okokufaka kokuthinta"</string>
<string name="gesture_input_summary" msgid="7019742443455085809">"Faka igama ngokulandela ngomkhondo izinhlamvu zegama"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"Bonisa i-trail yokuthinta"</string>
<string name="gesture_floating_preview_text" msgid="6859416520117939680">"Bonisa igama lokuthinta"</string>
<string name="gesture_floating_preview_text_summary" msgid="3333754126434989709">"Bonisa igama lokuhlola kuqala elintantayo nokuthinta"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Kulondoloziwe"</string>
<string name="label_go_key" msgid="1635148082137219148">"Iya"</string>
<string name="label_next_key" msgid="362972844525672568">"Okulandelayo"</string>
@ -90,6 +93,9 @@
<string name="spoken_description_return" msgid="8178083177238315647">"Buyisela"</string>
<string name="spoken_description_search" msgid="1247236163755920808">"Sesha"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Icashazi"</string>
<string name="spoken_description_language_switch" msgid="5507091328222331316">"Shintsha ulimi"</string>
<string name="spoken_description_action_next" msgid="8636078276664150324">"Okulandelayo"</string>
<string name="spoken_description_action_previous" msgid="800872415009336208">"Okwangaphambilini"</string>
<string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"U-Shift uvunyelwe"</string>
<string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Ofeleba bavunyelwe"</string>
<string name="spoken_description_shiftmode_off" msgid="657219998449174808">"U-Shift uvimbelwe"</string>

View File

@ -118,6 +118,18 @@
<enum name="italic" value="2" />
<enum name="boldItalic" value="3" />
</attr>
<attr name="gestureFloatingPreviewTextSize" format="dimension" />
<attr name="gestureFloatingPreviewTextColor" format="color" />
<attr name="gestureFloatingPreviewTextOffset" format="dimension" />
<attr name="gestureFloatingPreviewTextShadingColor" format="color" />
<attr name="gestureFloatingPreviewTextShadingBorder" format="dimension" />
<attr name="gestureFloatingPreviewTextShadowColor" format="color" />
<attr name="gestureFloatingPreviewTextShadowBorder" format="dimension" />
<attr name="gestureFloatingPreviewTextConnectorColor" format="color" />
<attr name="gestureFloatingPreviewTextConnectorWidth" format="dimension" />
<attr name="gesturePreviewTrailColor" format="color" />
<attr name="gesturePreviewTrailWidth" format="dimension" />
</declare-styleable>
<declare-styleable name="MainKeyboardView">

View File

@ -19,6 +19,8 @@
-->
<resources>
<!-- Device form factor. This value must be aligned with {@link KeyboardId.DEVICE_FORM_FACTOR_PHONE} -->
<integer name="config_device_form_factor">0</integer>
<bool name="config_use_fullscreen_mode">false</bool>
<bool name="config_enable_show_voice_key_option">true</bool>
<bool name="config_enable_show_popup_on_keypress_option">true</bool>

View File

@ -93,4 +93,12 @@
<dimen name="more_suggestions_hint_text_size">27dp</dimen>
<integer name="suggestions_count_in_strip">3</integer>
<integer name="center_suggestion_percentile">36</integer>
<!-- Gesture preview parameters -->
<dimen name="gesture_preview_trail_width">2.5dp</dimen>
<dimen name="gesture_floating_preview_text_size">35dp</dimen>
<dimen name="gesture_floating_preview_text_offset">75dp</dimen>
<dimen name="gesture_floating_preview_text_shadow_border">17.5dp</dimen>
<dimen name="gesture_floating_preview_text_shading_border">7.5dp</dimen>
<dimen name="gesture_floating_preview_text_connector_width">1.0dp</dimen>
</resources>

View File

@ -111,10 +111,16 @@
<!-- Description for "next word suggestion" option. This displays suggestions even when there is no input, based on the previous word. -->
<string name="bigram_prediction_summary">Based on previous word</string>
<!-- Option to enable gesture input. The user can input a word by tracing the letters of a word without releasing the finger from the screen. [CHAR LIMIT=20]-->
<!-- Option to enable gesture input. The user can input a word by tracing the letters of a word without releasing the finger from the screen. [CHAR LIMIT=30]-->
<string name="gesture_input">Gesture input</string>
<!-- Description for "gesture_input" option. The user can input a word by tracing the letters of a word without releasing the finger from the screen. [CHAR LIMIT=65]-->
<string name="gesture_input_summary">Input a word by tracing the letters of a word</string>
<!-- Option to enable gesture trail preview. The user can see a trail of the gesture during gesture input. [CHAR LIMIT=30]-->
<string name="gesture_preview_trail">Show gesture trail</string>
<!-- Option to enable gesture floating text preview. The user can see a suggested word floating under the moving finger during a gesture input. [CHAR LIMIT=30]-->
<string name="gesture_floating_preview_text">Show gesture word</string>
<!-- Description for "gesture_floating_preview_text" option. The user can see a suggested word floating under the moving finger during a gesture input. [CHAR LIMIT=65]-->
<string name="gesture_floating_preview_text_summary">Show floating preview word with gesture</string>
<!-- Indicates that a word has been added to the dictionary -->
<string name="added_word"><xliff:g id="word">%s</xliff:g> : Saved</string>
@ -181,6 +187,12 @@
<string name="spoken_description_search">Search</string>
<!-- Spoken description for the "U+2022" (BULLET) keyboard key. -->
<string name="spoken_description_dot">Dot</string>
<!-- Spoken description for the "Switch language" keyboard key. -->
<string name="spoken_description_language_switch">Switch language</string>
<!-- Spoken description for the "Next" action keyboard key. -->
<string name="spoken_description_action_next">Next</string>
<!-- Spoken description for the "Previous" action keyboard key. -->
<string name="spoken_description_action_previous">Previous</string>
<!-- Spoken feedback after turning "Shift" mode on. -->
<string name="spoken_description_shiftmode_on">Shift enabled</string>
@ -303,6 +315,15 @@
<!-- Description for English (United States) keyboard subtype with explicit keyboard layout [CHAR LIMIT=25]
This should be identical to subtype_en_US aside from the trailing (%s). -->
<string name="subtype_with_layout_en_US">English (US) (<xliff:g id="layout">%s</xliff:g>)</string>
<!-- TODO: Uncomment once we can handle IETF language tag with script name specified.
Description for Serbian Cyrillic keyboard subtype [CHAR LIMIT=25]
<string name="subtype_serbian_cyrillic">Serbian (Cyrillic)</string>
Description for Serbian Latin keyboard subtype [CHAR LIMIT=25]
<string name="subtype_serbian_latin">Serbian (Latin)</string>
Description for Serbian Latin keyboard subtype with explicit keyboard layout [CHAR LIMIT=25]
This should be identical to subtype_serbian_latin aside from the trailing (%s).
<string name="subtype_with_layout_sr-Latn">Serbian (Latin) (<xliff:g id="layout">%s</xliff:g>)</string>
-->
<!-- Description for language agnostic keyboard subtype [CHAR LIMIT=25] -->
<string name="subtype_no_language">No language</string>
<!-- Description for language agnostic QWERTY keyboard subtype [CHAR LIMIT=25] -->

View File

@ -14,7 +14,7 @@
limitations under the License.
-->
<resources>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Theme "Basic" -->
<style name="Keyboard">
<!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] -->
@ -67,6 +67,18 @@
<item name="shadowColor">#BB000000</item>
<item name="shadowRadius">2.75</item>
<item name="backgroundDimAlpha">128</item>
<!-- android:color/holo_blue_light=#FF33B5E5 -->
<item name="gestureFloatingPreviewTextSize">@dimen/gesture_floating_preview_text_size</item>
<item name="gestureFloatingPreviewTextColor">@android:color/white</item>
<item name="gestureFloatingPreviewTextOffset">@dimen/gesture_floating_preview_text_offset</item>
<item name="gestureFloatingPreviewTextShadingColor">@android:color/holo_blue_light</item>
<item name="gestureFloatingPreviewTextShadingBorder">@dimen/gesture_floating_preview_text_shading_border</item>
<item name="gestureFloatingPreviewTextShadowColor">#FF252525</item>
<item name="gestureFloatingPreviewTextShadowBorder">@dimen/gesture_floating_preview_text_shadow_border</item>
<item name="gestureFloatingPreviewTextConnectorColor">@android:color/white</item>
<item name="gestureFloatingPreviewTextConnectorWidth">@dimen/gesture_floating_preview_text_connector_width</item>
<item name="gesturePreviewTrailColor">@android:color/holo_blue_light</item>
<item name="gesturePreviewTrailWidth">@dimen/gesture_preview_trail_width</item>
<!-- Common attributes of MainKeyboardView -->
<item name="keyHysteresisDistance">@dimen/config_key_hysteresis_distance</item>
<item name="touchNoiseThresholdTime">@integer/config_touch_noise_threshold_time</item>

View File

@ -24,15 +24,36 @@
<switch>
<case
latin:languageCode="fa"
latin:languageSwitchKeyEnabled="true"
>
<Key
latin:keyStyle="languageSwitchKeyStyle" />
<Key
latin:keyStyle="spaceKeyStyle"
latin:keyWidth="24.141%p" />
<Key
latin:keyStyle="zwnjKeyStyle" />
</case>
<case
latin:languageCode="fa"
latin:languageSwitchKeyEnabled="false"
>
<Key
latin:keyStyle="spaceKeyStyle"
latin:keyWidth="32.188%p" />
<!-- U+200C: "" ZERO WIDTH NON-JOINER
U+200D: "" ZERO WIDTH JOINER -->
<Key
latin:keyStyle="zwnjKeyStyle" />
</case>
<case
latin:languageSwitchKeyEnabled="true"
>
<Key
latin:keyStyle="languageSwitchKeyStyle" />
<Key
latin:keyStyle="spaceKeyStyle"
latin:keyWidth="32.188%p" />
</case>
<!-- languageSwitchKeyEnabled="false" -->
<default>
<Key
latin:keyStyle="spaceKeyStyle"

View File

@ -76,7 +76,7 @@
<key-style
latin:styleName="spaceKeyStyle"
latin:code="!code/key_space"
latin:keyActionFlags="noKeyPreview" />
latin:keyActionFlags="noKeyPreview|enableLongPress" />
<!-- U+200C: ZERO WIDTH NON-JOINER
U+200D: ZERO WIDTH JOINER -->
<key-style
@ -99,6 +99,12 @@
latin:keyIconDisabled="!icon/shortcut_key_disabled"
latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="languageSwitchKeyStyle"
latin:code="!code/key_language_switch"
latin:keyIcon="!icon/language_switch_key"
latin:keyActionFlags="noKeyPreview|altCodeWhileTyping|enableLongPress"
latin:altCode="!code/key_space" />
<key-style
latin:styleName="settingsKeyStyle"
latin:code="!code/key_settings"

View File

@ -33,9 +33,8 @@
<include
latin:keyboardLayout="@xml/rowkeys_east_slavic1"
latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
<!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN -->
<Key
latin:keyLabel="&#x044A;" />
latin:keyLabel="!text/keylabel_for_east_slavic_row1_12" />
<Key
latin:keyStyle="deleteKeyStyle"
latin:keyWidth="fillRight" />

View File

@ -22,10 +22,12 @@
<!-- Supported subtypes
keyboard_locale: script_name/keyboard_layout_set[:keyboard_locale]
af: Afrikaans/qwerty
ar: Arabic/arabic
be: Belarusian/east_slavic
bg: Bulgarian/bulgarian
bg: Bulgarian/bulgarian_bds
ca: Catalan/spanish
cs: Czech/qwertz
da: Danish/nordic
de: German/qwertz
@ -41,14 +43,16 @@
hi: Hindi/hindi
hr: Croatian/qwertz
hu: Hungarian/qwertz
in: Indonesian/qwerty # "id" is official language code of Indonesian.
is: Icelandic/qwerty
it: Italian/qwerty
iw: Hebrew/hebrew
iw: Hebrew/hebrew # "he" is official language code of Hebrew.
ka: Georgian/georgian
ky: Kyrgyz/east_slavic
lt: Lithuanian/qwerty
lv: Latvian/qwerty
mk: Macedonian/south_slavic
ms: Malay/qwerty
nb: Norwegian Bokmål/nordic
nl: Dutch/qwerty
pl: Polish/qwerty
@ -59,11 +63,15 @@
sk: Slovak/qwerty
sl: Slovenian/qwerty
sr: Serbian/south_slavic
(sr-Latn: Serbian/qwerty) # not yet implemented.
sv: Swedish/nordic
sw: Swahili/qwerty
th: Thai/thai
tl: Tagalog/spanish
tr: Turkish/qwerty
uk: Ukrainian/east_slavic
vi: Vietnamese/qwerty
zu: Zulu/qwerty
zz: QWERTY/qwerty
-->
<!-- TODO: use <lang>_keyboard icon instead of a common keyboard icon. -->
@ -84,6 +92,12 @@
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="af"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="ar"
@ -108,6 +122,12 @@
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="KeyboardLayoutSet=bulgarian_bds"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="ca"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,AsciiCapable"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="cs"
@ -186,6 +206,13 @@
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<!-- Java uses the deprecated "in" code instead of the standard "id" code for Indonesian. -->
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="in"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="is"
@ -235,6 +262,12 @@
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="KeyboardLayoutSet=south_slavic"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="ms"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="nb"
@ -295,18 +328,44 @@
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
/>
<!-- TODO: Uncomment once we can handle IETF language tag with script name specified.
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_serbian_cyrillic"
android:imeSubtypeLocale="sr"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_serbian_latin"
android:imeSubtypeLocale="sr-Latn"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
/>
-->
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="sv"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="sw"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="th"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="KeyboardLayoutSet=thai"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="tl"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,AsciiCapable"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="tr"
@ -325,6 +384,12 @@
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="zu"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_no_language_qwerty"
android:imeSubtypeLocale="zz"

View File

@ -101,6 +101,12 @@
android:key="pref_advanced_settings"
android:title="@string/advanced_settings"
android:summary="@string/advanced_settings_summary">
<CheckBoxPreference
android:key="pref_key_use_contacts_dict"
android:title="@string/use_contacts_dict"
android:summary="@string/use_contacts_dict_summary"
android:persistent="true"
android:defaultValue="true" />
<CheckBoxPreference
android:key="pref_suppress_language_switch_key"
android:title="@string/suppress_language_switch_key"
@ -120,18 +126,23 @@
<ListPreference
android:key="pref_key_preview_popup_dismiss_delay"
android:title="@string/key_preview_popup_dismiss_delay" />
<CheckBoxPreference
android:key="pref_key_use_contacts_dict"
android:title="@string/use_contacts_dict"
android:summary="@string/use_contacts_dict_summary"
android:persistent="true"
android:defaultValue="true" />
<PreferenceScreen
android:key="pref_vibration_duration_settings"
android:title="@string/prefs_keypress_vibration_duration_settings"/>
<PreferenceScreen
android:key="pref_keypress_sound_volume"
android:title="@string/prefs_keypress_sound_volume_settings" />
<CheckBoxPreference
android:key="pref_gesture_preview_trail"
android:title="@string/gesture_preview_trail"
android:persistent="true"
android:defaultValue="true" />
<CheckBoxPreference
android:key="pref_gesture_floating_preview_text"
android:title="@string/gesture_floating_preview_text"
android:summary="@string/gesture_floating_preview_text_summary"
android:persistent="true"
android:defaultValue="true" />
</PreferenceScreen>
</PreferenceCategory>
</PreferenceScreen>

View File

@ -47,7 +47,7 @@
latin:keyLabel="&#x0435;"
latin:keyHintLabel="5"
latin:additionalMoreKeys="5"
latin:moreKeys="!text/more_keys_for_cyrillic_ye" />
latin:moreKeys="!text/more_keys_for_cyrillic_ie" />
<!-- U+043D: "н" CYRILLIC SMALL LETTER EN -->
<Key
latin:keyLabel="&#x043D;"
@ -58,7 +58,8 @@
<Key
latin:keyLabel="&#x0433;"
latin:keyHintLabel="7"
latin:additionalMoreKeys="7" />
latin:additionalMoreKeys="7"
latin:moreKeys="!text/more_keys_for_cyrillic_ghe" />
<!-- U+0448: "ш" CYRILLIC SMALL LETTER SHA -->
<Key
latin:keyLabel="&#x0448;"
@ -75,6 +76,5 @@
latin:additionalMoreKeys="0" />
<!-- U+0445: "х" CYRILLIC SMALL LETTER HA -->
<Key
latin:keyLabel="&#x0445;"
latin:moreKeys="!text/more_keys_for_cyrillic_ha" />
latin:keyLabel="&#x0445;" />
</merge>

View File

@ -52,7 +52,6 @@
<!-- U+0436: "ж" CYRILLIC SMALL LETTER ZHE -->
<Key
latin:keyLabel="&#x0436;" />
<!-- U+044D: "э" CYRILLIC SMALL LETTER E -->
<Key
latin:keyLabel="&#x044D;" />
latin:keyLabel="!text/keylabel_for_east_slavic_row2_11" />
</merge>

View File

@ -60,10 +60,8 @@ public class KeyCodeDescriptionMapper {
// Manual label substitutions for key labels with no string resource
mKeyLabelMap.put(":-)", R.string.spoken_description_smiley);
// Symbols that most TTS engines can't speak
mKeyCodeMap.put(' ', R.string.spoken_description_space);
// Special non-character codes defined in Keyboard
mKeyCodeMap.put(Keyboard.CODE_SPACE, R.string.spoken_description_space);
mKeyCodeMap.put(Keyboard.CODE_DELETE, R.string.spoken_description_delete);
mKeyCodeMap.put(Keyboard.CODE_ENTER, R.string.spoken_description_return);
mKeyCodeMap.put(Keyboard.CODE_SETTINGS, R.string.spoken_description_settings);
@ -71,6 +69,9 @@ public class KeyCodeDescriptionMapper {
mKeyCodeMap.put(Keyboard.CODE_SHORTCUT, R.string.spoken_description_mic);
mKeyCodeMap.put(Keyboard.CODE_SWITCH_ALPHA_SYMBOL, R.string.spoken_description_to_symbol);
mKeyCodeMap.put(Keyboard.CODE_TAB, R.string.spoken_description_tab);
mKeyCodeMap.put(Keyboard.CODE_LANGUAGE_SWITCH, R.string.spoken_description_language_switch);
mKeyCodeMap.put(Keyboard.CODE_ACTION_NEXT, R.string.spoken_description_action_next);
mKeyCodeMap.put(Keyboard.CODE_ACTION_PREVIOUS, R.string.spoken_description_action_previous);
}
/**
@ -274,8 +275,7 @@ public class KeyCodeDescriptionMapper {
return context.getString(OBSCURED_KEY_RES_ID);
}
final int resId = mKeyCodeMap.get(code);
if (resId != 0) {
if (mKeyCodeMap.indexOfKey(code) >= 0) {
return context.getString(mKeyCodeMap.get(code));
} else if (isDefinedNonCtrl) {
return Character.toString((char) code);

View File

@ -0,0 +1,34 @@
/*
* 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.compat;
import android.inputmethodservice.InputMethodService;
import java.lang.reflect.Method;
public class InputMethodServiceCompatUtils {
private static final Method METHOD_enableHardwareAcceleration =
CompatUtils.getMethod(InputMethodService.class, "enableHardwareAcceleration");
private InputMethodServiceCompatUtils() {
// This utility class is not publicly instantiable.
}
public static boolean enableHardwareAcceleration(InputMethodService ims) {
return (Boolean)CompatUtils.invoke(ims, false, METHOD_enableHardwareAcceleration);
}
}

View File

@ -414,8 +414,14 @@ public class Key {
@Override
public String toString() {
return String.format("%s/%s %d,%d %dx%d %s/%s/%s",
Keyboard.printableCode(mCode), mLabel, mX, mY, mWidth, mHeight, mHintLabel,
final String label;
if (StringUtils.codePointCount(mLabel) == 1 && mLabel.codePointAt(0) == mCode) {
label = "";
} else {
label = "/" + mLabel;
}
return String.format("%s%s %d,%d %dx%d %s/%s/%s",
Keyboard.printableCode(mCode), label, mX, mY, mWidth, mHeight, mHintLabel,
KeyboardIconsSet.getIconName(mIconId), backgroundName(mBackgroundType));
}

View File

@ -25,7 +25,6 @@ public class KeyDetector {
private Keyboard mKeyboard;
private int mCorrectionX;
private int mCorrectionY;
private boolean mProximityCorrectOn;
/**
* This class handles key detection.
@ -38,8 +37,9 @@ public class KeyDetector {
}
public void setKeyboard(Keyboard keyboard, float correctionX, float correctionY) {
if (keyboard == null)
if (keyboard == null) {
throw new NullPointerException();
}
mCorrectionX = (int)correctionX;
mCorrectionY = (int)correctionY;
mKeyboard = keyboard;
@ -59,19 +59,9 @@ public class KeyDetector {
}
public Keyboard getKeyboard() {
if (mKeyboard == null)
throw new IllegalStateException("keyboard isn't set");
return mKeyboard;
}
public void setProximityCorrectionEnabled(boolean enabled) {
mProximityCorrectOn = enabled;
}
public boolean isProximityCorrectionEnabled() {
return mProximityCorrectOn;
}
public boolean alwaysAllowsSlidingInput() {
return false;
}

View File

@ -604,9 +604,6 @@ public class Keyboard {
}
public float getKeyX(TypedArray keyAttr) {
final int widthType = Builder.getEnumValue(keyAttr,
R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
final int keyboardRightEdge = mParams.mOccupiedWidth
- mParams.mHorizontalEdgesPadding;
if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyXPos)) {

View File

@ -55,10 +55,15 @@ public class KeyboardId {
public static final int ELEMENT_PHONE_SYMBOLS = 8;
public static final int ELEMENT_NUMBER = 9;
public static final int FORM_FACTOR_PHONE = 0;
public static final int FORM_FACTOR_TABLET7 = 1;
public static final int FORM_FACTOR_TABLET10 = 2;
private static final int IME_ACTION_CUSTOM_LABEL = EditorInfo.IME_MASK_ACTION + 1;
public final InputMethodSubtype mSubtype;
public final Locale mLocale;
public final int mDeviceFormFactor;
public final int mOrientation;
public final int mWidth;
public final int mMode;
@ -72,11 +77,12 @@ public class KeyboardId {
private final int mHashCode;
public KeyboardId(int elementId, InputMethodSubtype subtype, int orientation, int width,
int mode, EditorInfo editorInfo, boolean clobberSettingsKey, boolean shortcutKeyEnabled,
boolean hasShortcutKey, boolean languageSwitchKeyEnabled) {
public KeyboardId(int elementId, InputMethodSubtype subtype, int deviceFormFactor,
int orientation, int width, int mode, EditorInfo editorInfo, boolean clobberSettingsKey,
boolean shortcutKeyEnabled, boolean hasShortcutKey, boolean languageSwitchKeyEnabled) {
mSubtype = subtype;
mLocale = SubtypeLocale.getSubtypeLocale(subtype);
mDeviceFormFactor = deviceFormFactor;
mOrientation = orientation;
mWidth = width;
mMode = mode;
@ -94,6 +100,7 @@ public class KeyboardId {
private static int computeHashCode(KeyboardId id) {
return Arrays.hashCode(new Object[] {
id.mDeviceFormFactor,
id.mOrientation,
id.mElementId,
id.mMode,
@ -115,7 +122,8 @@ public class KeyboardId {
private boolean equals(KeyboardId other) {
if (other == this)
return true;
return other.mOrientation == mOrientation
return other.mDeviceFormFactor == mDeviceFormFactor
&& other.mOrientation == mOrientation
&& other.mElementId == mElementId
&& other.mMode == mMode
&& other.mWidth == mWidth
@ -184,11 +192,11 @@ public class KeyboardId {
@Override
public String toString() {
return String.format("[%s %s:%s %s%d %s %s %s%s%s%s%s%s%s%s]",
return String.format("[%s %s:%s %s-%s:%d %s %s %s%s%s%s%s%s%s%s]",
elementIdToName(mElementId),
mLocale,
mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
(mOrientation == 1 ? "port" : "land"), mWidth,
deviceFormFactor(mDeviceFormFactor), (mOrientation == 1 ? "port" : "land"), mWidth,
modeName(mMode),
imeAction(),
(navigateNext() ? "navigateNext" : ""),
@ -226,6 +234,15 @@ public class KeyboardId {
}
}
public static String deviceFormFactor(int devoceFormFactor) {
switch (devoceFormFactor) {
case FORM_FACTOR_PHONE: return "phone";
case FORM_FACTOR_TABLET7: return "tablet7";
case FORM_FACTOR_TABLET10: return "tablet10";
default: return null;
}
}
public static String modeName(int mode) {
switch (mode) {
case MODE_TEXT: return "text";

View File

@ -115,6 +115,7 @@ public class KeyboardLayoutSet {
boolean mNoSettingsKey;
boolean mLanguageSwitchKeyEnabled;
InputMethodSubtype mSubtype;
int mDeviceFormFactor;
int mOrientation;
int mWidth;
// Sparse array of KeyboardLayoutSet element parameters indexed by element's id.
@ -211,9 +212,10 @@ public class KeyboardLayoutSet {
final boolean noLanguage = SubtypeLocale.isNoLanguage(params.mSubtype);
final boolean voiceKeyEnabled = params.mVoiceKeyEnabled && !noLanguage;
final boolean hasShortcutKey = voiceKeyEnabled && (isSymbols != params.mVoiceKeyOnMain);
return new KeyboardId(keyboardLayoutSetElementId, params.mSubtype, params.mOrientation,
params.mWidth, params.mMode, params.mEditorInfo, params.mNoSettingsKey,
voiceKeyEnabled, hasShortcutKey, params.mLanguageSwitchKeyEnabled);
return new KeyboardId(keyboardLayoutSetElementId, params.mSubtype, params.mDeviceFormFactor,
params.mOrientation, params.mWidth, params.mMode, params.mEditorInfo,
params.mNoSettingsKey, voiceKeyEnabled, hasShortcutKey,
params.mLanguageSwitchKeyEnabled);
}
public static class Builder {
@ -239,9 +241,11 @@ public class KeyboardLayoutSet {
mPackageName, NO_SETTINGS_KEY, mEditorInfo);
}
public Builder setScreenGeometry(int orientation, int widthPixels) {
mParams.mOrientation = orientation;
mParams.mWidth = widthPixels;
public Builder setScreenGeometry(int deviceFormFactor, int orientation, int widthPixels) {
final Params params = mParams;
params.mDeviceFormFactor = deviceFormFactor;
params.mOrientation = orientation;
params.mWidth = widthPixels;
return this;
}

View File

@ -74,7 +74,6 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
private MainKeyboardView mKeyboardView;
private LatinIME mLatinIME;
private Resources mResources;
private SettingsValues mCurrentSettingsValues;
private KeyboardState mState;
@ -136,11 +135,11 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
}
public void loadKeyboard(EditorInfo editorInfo, SettingsValues settingsValues) {
mCurrentSettingsValues = settingsValues;
final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder(
mThemeContext, editorInfo);
builder.setScreenGeometry(mThemeContext.getResources().getConfiguration().orientation,
mThemeContext.getResources().getDisplayMetrics().widthPixels);
final Resources res = mThemeContext.getResources();
builder.setScreenGeometry(res.getInteger(R.integer.config_device_form_factor),
res.getConfiguration().orientation, res.getDisplayMetrics().widthPixels);
builder.setSubtype(mSubtypeSwitcher.getCurrentSubtype());
builder.setOptions(
settingsValues.isVoiceKeyEnabled(editorInfo),
@ -171,20 +170,20 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
}
private void setKeyboard(final Keyboard keyboard) {
final Keyboard oldKeyboard = mKeyboardView.getKeyboard();
mKeyboardView.setGestureInputEnabled(mCurrentSettingsValues.mGestureInputEnabled);
mKeyboardView.setKeyboard(keyboard);
final MainKeyboardView keyboardView = mKeyboardView;
final Keyboard oldKeyboard = keyboardView.getKeyboard();
keyboardView.setKeyboard(keyboard);
mCurrentInputView.setKeyboardGeometry(keyboard.mTopPadding);
mKeyboardView.setKeyPreviewPopupEnabled(
keyboardView.setKeyPreviewPopupEnabled(
SettingsValues.isKeyPreviewPopupEnabled(mPrefs, mResources),
SettingsValues.getKeyPreviewPopupDismissDelay(mPrefs, mResources));
mKeyboardView.updateAutoCorrectionState(mIsAutoCorrectionActive);
mKeyboardView.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady());
keyboardView.updateAutoCorrectionState(mIsAutoCorrectionActive);
keyboardView.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady());
final boolean subtypeChanged = (oldKeyboard == null)
|| !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
final boolean needsToDisplayLanguage = mSubtypeSwitcher.needsToDisplayLanguage(
keyboard.mId.mLocale);
mKeyboardView.startDisplayLanguageOnSpacebar(subtypeChanged, needsToDisplayLanguage,
keyboardView.startDisplayLanguageOnSpacebar(subtypeChanged, needsToDisplayLanguage,
ImfUtils.hasMultipleEnabledIMEsOrSubtypes(mLatinIME, true));
}
@ -350,7 +349,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
return mKeyboardView;
}
public View onCreateInputView() {
public View onCreateInputView(boolean isHardwareAcceleratedDrawingEnabled) {
if (mKeyboardView != null) {
mKeyboardView.closing();
}
@ -373,6 +372,10 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
}
mKeyboardView = (MainKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
if (isHardwareAcceleratedDrawingEnabled) {
mKeyboardView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
// TODO: Should use LAYER_TYPE_SOFTWARE when hardware acceleration is off?
}
mKeyboardView.setKeyboardActionListener(mLatinIME);
if (mForceNonDistinctMultitouch) {
mKeyboardView.setDistinctMultitouch(false);

View File

@ -25,7 +25,7 @@ import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Region.Op;
import android.graphics.Region;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Message;
@ -35,9 +35,9 @@ import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.inputmethod.keyboard.internal.PreviewPlacerView;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
@ -97,9 +97,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
// The maximum key label width in the proportion to the key width.
private static final float MAX_LABEL_RATIO = 0.90f;
private final static int GESTURE_DRAWING_WIDTH = 5;
private final static int GESTURE_DRAWING_COLOR = 0xff33b5e5;
// Main keyboard
private Keyboard mKeyboard;
protected final KeyDrawParams mKeyDrawParams;
@ -109,10 +106,10 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
protected final KeyPreviewDrawParams mKeyPreviewDrawParams;
private boolean mShowKeyPreviewPopup = true;
private int mDelayAfterPreview;
private ViewGroup mPreviewPlacer;
private final PreviewPlacerView mPreviewPlacerView;
/** True if the gesture input is enabled. */
protected boolean mGestureInputEnabled;
/** True if {@link KeyboardView} should handle gesture events. */
protected boolean mShouldHandleGesture;
// Drawing
/** True if the entire keyboard needs to be dimmed. */
@ -123,16 +120,15 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
private boolean mInvalidateAllKeys;
/** The keys that should be drawn */
private final HashSet<Key> mInvalidatedKeys = new HashSet<Key>();
/** The region of invalidated keys */
private final Rect mInvalidatedKeysRect = new Rect();
/** The region of invalidated gestures */
private final Rect mInvalidatedGesturesRect = new Rect();
/** The working rectangle variable */
private final Rect mWorkingRect = new Rect();
/** The keyboard bitmap buffer for faster updates */
private Bitmap mBuffer;
/** The clip region to draw keys */
private final Region mClipRegion = new Region();
private Bitmap mOffscreenBuffer;
/** The canvas for the above mutable keyboard bitmap */
private Canvas mCanvas;
private Canvas mOffscreenCanvas;
private final Paint mPaint = new Paint();
private final Paint mGesturePaint = new Paint();
private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics();
// This sparse array caches key label text height in pixel indexed by key label text size.
private static final SparseArray<Float> sTextHeightCache = new SparseArray<Float>();
@ -261,10 +257,12 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
public void updateKeyHeight(int keyHeight) {
if (mKeyLetterRatio >= 0.0f)
if (mKeyLetterRatio >= 0.0f) {
mKeyLetterSize = (int)(keyHeight * mKeyLetterRatio);
if (mKeyLabelRatio >= 0.0f)
}
if (mKeyLabelRatio >= 0.0f) {
mKeyLabelSize = (int)(keyHeight * mKeyLabelRatio);
}
mKeyLargeLabelSize = (int)(keyHeight * mKeyLargeLabelRatio);
mKeyLargeLetterSize = (int)(keyHeight * mKeyLargeLetterRatio);
mKeyHintLetterSize = (int)(keyHeight * mKeyHintLetterRatio);
@ -346,13 +344,16 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
public void updateKeyHeight(int keyHeight) {
mPreviewTextSize = (int)(keyHeight * mPreviewTextRatio);
mKeyLetterSize = (int)(keyHeight * mKeyLetterRatio);
if (mPreviewTextRatio >= 0.0f) {
mPreviewTextSize = (int)(keyHeight * mPreviewTextRatio);
}
if (mKeyLetterRatio >= 0.0f) {
mKeyLetterSize = (int)(keyHeight * mKeyLetterRatio);
}
}
private static void setAlpha(Drawable drawable, int alpha) {
if (drawable == null)
return;
if (drawable == null) return;
drawable.setAlpha(alpha);
}
}
@ -377,18 +378,12 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
R.styleable.KeyboardView_verticalCorrection, 0);
mMoreKeysLayout = a.getResourceId(R.styleable.KeyboardView_moreKeysLayout, 0);
mBackgroundDimAlpha = a.getInt(R.styleable.KeyboardView_backgroundDimAlpha, 0);
mPreviewPlacerView = new PreviewPlacerView(context, a);
a.recycle();
mDelayAfterPreview = mKeyPreviewDrawParams.mLingerTimeout;
mPaint.setAntiAlias(true);
// TODO: These paint parameters should be specified via attribute of the view and styleable.
mGesturePaint.setAntiAlias(true);
mGesturePaint.setStyle(Paint.Style.STROKE);
mGesturePaint.setStrokeJoin(Paint.Join.ROUND);
mGesturePaint.setColor(GESTURE_DRAWING_COLOR);
mGesturePaint.setStrokeWidth(GESTURE_DRAWING_WIDTH);
}
// Read fraction value in TypedArray as float.
@ -443,8 +438,11 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
return mShowKeyPreviewPopup;
}
public void setGestureInputEnabled(boolean gestureInputEnabled) {
mGestureInputEnabled = gestureInputEnabled;
public void setGestureHandlingMode(boolean shouldHandleGesture,
boolean drawsGesturePreviewTrail, boolean drawsGestureFloatingPreviewText) {
mShouldHandleGesture = shouldHandleGesture;
mPreviewPlacerView.setGesturePreviewMode(
drawsGesturePreviewTrail, drawsGestureFloatingPreviewText);
}
@Override
@ -461,65 +459,107 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mBufferNeedsUpdate || mBuffer == null) {
mBufferNeedsUpdate = false;
onBufferDraw();
if (canvas.isHardwareAccelerated()) {
onDrawKeyboard(canvas);
return;
}
canvas.drawBitmap(mBuffer, 0, 0, null);
if (mBufferNeedsUpdate || mOffscreenBuffer == null) {
mBufferNeedsUpdate = false;
if (maybeAllocateOffscreenBuffer()) {
mInvalidateAllKeys = true;
// TODO: Stop using the offscreen canvas even when in software rendering
if (mOffscreenCanvas != null) {
mOffscreenCanvas.setBitmap(mOffscreenBuffer);
} else {
mOffscreenCanvas = new Canvas(mOffscreenBuffer);
}
}
onDrawKeyboard(mOffscreenCanvas);
}
canvas.drawBitmap(mOffscreenBuffer, 0, 0, null);
}
private void onBufferDraw() {
private boolean maybeAllocateOffscreenBuffer() {
final int width = getWidth();
final int height = getHeight();
if (width == 0 || height == 0)
return;
if (mBuffer == null || mBuffer.getWidth() != width || mBuffer.getHeight() != height) {
if (mBuffer != null)
mBuffer.recycle();
mBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mInvalidateAllKeys = true;
if (mCanvas != null) {
mCanvas.setBitmap(mBuffer);
} else {
mCanvas = new Canvas(mBuffer);
}
if (width == 0 || height == 0) {
return false;
}
if (mOffscreenBuffer != null && mOffscreenBuffer.getWidth() == width
&& mOffscreenBuffer.getHeight() == height) {
return false;
}
freeOffscreenBuffer();
mOffscreenBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
return true;
}
private void freeOffscreenBuffer() {
if (mOffscreenBuffer != null) {
mOffscreenBuffer.recycle();
mOffscreenBuffer = null;
}
}
private void onDrawKeyboard(final Canvas canvas) {
if (mKeyboard == null) return;
final Canvas canvas = mCanvas;
final int width = getWidth();
final int height = getHeight();
final Paint paint = mPaint;
final KeyDrawParams params = mKeyDrawParams;
if (mInvalidateAllKeys || mInvalidatedKeys.isEmpty()) {
mInvalidatedKeysRect.set(0, 0, width, height);
canvas.clipRect(mInvalidatedKeysRect, Op.REPLACE);
canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
// Calculate clip region and set.
final boolean drawAllKeys = mInvalidateAllKeys || mInvalidatedKeys.isEmpty();
final boolean isHardwareAccelerated = canvas.isHardwareAccelerated();
// TODO: Confirm if it's really required to draw all keys when hardware acceleration is on.
if (drawAllKeys || isHardwareAccelerated) {
mClipRegion.set(0, 0, width, height);
} else {
mClipRegion.setEmpty();
for (final Key key : mInvalidatedKeys) {
if (mKeyboard.hasKey(key)) {
final int x = key.mX + getPaddingLeft();
final int y = key.mY + getPaddingTop();
mWorkingRect.set(x, y, x + key.mWidth, y + key.mHeight);
mClipRegion.union(mWorkingRect);
}
}
}
if (!isHardwareAccelerated) {
canvas.clipRegion(mClipRegion, Region.Op.REPLACE);
}
// Draw keyboard background.
canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
final Drawable background = getBackground();
if (background != null) {
background.draw(canvas);
}
// TODO: Confirm if it's really required to draw all keys when hardware acceleration is on.
if (drawAllKeys || isHardwareAccelerated) {
// Draw all keys.
for (final Key key : mKeyboard.mKeys) {
onDrawKey(key, canvas, paint, params);
}
if (mNeedsToDimEntireKeyboard) {
drawDimRectangle(canvas, mInvalidatedKeysRect, mBackgroundDimAlpha, paint);
}
} else {
// Draw invalidated keys.
for (final Key key : mInvalidatedKeys) {
if (!mKeyboard.hasKey(key)) {
continue;
}
final int x = key.mX + getPaddingLeft();
final int y = key.mY + getPaddingTop();
mInvalidatedKeysRect.set(x, y, x + key.mWidth, y + key.mHeight);
canvas.clipRect(mInvalidatedKeysRect, Op.REPLACE);
canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
onDrawKey(key, canvas, paint, params);
if (mNeedsToDimEntireKeyboard) {
drawDimRectangle(canvas, mInvalidatedKeysRect, mBackgroundDimAlpha, paint);
if (mKeyboard.hasKey(key)) {
onDrawKey(key, canvas, paint, params);
}
}
}
// Overlay a dark rectangle to dim.
if (mNeedsToDimEntireKeyboard) {
paint.setColor(Color.BLACK);
paint.setAlpha(mBackgroundDimAlpha);
// Note: clipRegion() above is in effect if it was called.
canvas.drawRect(0, 0, width, height, paint);
}
// ResearchLogging indicator.
// TODO: Reimplement using a keyboard background image specific to the ResearchLogger,
// and remove this call.
@ -528,7 +568,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
mInvalidatedKeys.clear();
mInvalidatedKeysRect.setEmpty();
mInvalidateAllKeys = false;
}
@ -853,13 +892,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
canvas.translate(-x, -y);
}
// Overlay a dark rectangle to dim.
private static void drawDimRectangle(Canvas canvas, Rect rect, int alpha, Paint paint) {
paint.setColor(Color.BLACK);
paint.setAlpha(alpha);
canvas.drawRect(rect, paint);
}
public Paint newDefaultLabelPaint() {
final Paint paint = new Paint();
paint.setAntiAlias(true);
@ -888,58 +920,33 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
mDrawingHandler.dismissKeyPreview(mDelayAfterPreview, tracker);
}
private static class PreviewView extends RelativeLayout {
KeyPreviewDrawParams mParams;
Paint mGesturePaint;
public PreviewView(Context context, KeyPreviewDrawParams params, Paint gesturePaint) {
super(context);
setWillNotDraw(false);
mParams = params;
mGesturePaint = gesturePaint;
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(mParams.mCoordinates[0], mParams.mCoordinates[1]);
PointerTracker.drawGestureTrailForAllPointerTrackers(canvas, mGesturePaint);
canvas.translate(-mParams.mCoordinates[0], -mParams.mCoordinates[1]);
}
}
private void addKeyPreview(TextView keyPreview) {
if (mPreviewPlacer == null) {
createPreviewPlacer();
}
mPreviewPlacer.addView(
keyPreview, ViewLayoutUtils.newLayoutParam(mPreviewPlacer, 0, 0));
locatePreviewPlacerView();
mPreviewPlacerView.addView(
keyPreview, ViewLayoutUtils.newLayoutParam(mPreviewPlacerView, 0, 0));
}
private void createPreviewPlacer() {
mPreviewPlacer = new PreviewView(getContext(), mKeyPreviewDrawParams, mGesturePaint);
private void locatePreviewPlacerView() {
if (mPreviewPlacerView.getParent() != null) {
return;
}
final int[] viewOrigin = new int[2];
getLocationInWindow(viewOrigin);
mPreviewPlacerView.setOrigin(viewOrigin[0], viewOrigin[1]);
final ViewGroup windowContentView =
(ViewGroup)getRootView().findViewById(android.R.id.content);
windowContentView.addView(mPreviewPlacer);
windowContentView.addView(mPreviewPlacerView);
}
public void showGestureFloatingPreviewText(String gestureFloatingPreviewText) {
locatePreviewPlacerView();
mPreviewPlacerView.setGestureFloatingPreviewText(gestureFloatingPreviewText);
}
@Override
public void showGestureTrail(PointerTracker tracker) {
if (mPreviewPlacer == null) {
createPreviewPlacer();
}
final Rect r = tracker.getBoundingBox();
if (!r.isEmpty()) {
// Invalidate the rectangular region encompassing the gesture. This is needed because
// past points along the gesture will fade and gradually disappear.
final KeyPreviewDrawParams params = mKeyPreviewDrawParams;
mInvalidatedGesturesRect.set(r);
mInvalidatedGesturesRect.offset(params.mCoordinates[0], params.mCoordinates[1]);
mInvalidatedGesturesRect.inset(-GESTURE_DRAWING_WIDTH, -GESTURE_DRAWING_WIDTH);
mPreviewPlacer.invalidate(mInvalidatedGesturesRect);
} else {
mPreviewPlacer.invalidate();
}
locatePreviewPlacerView();
mPreviewPlacerView.invalidatePointer(tracker);
}
@SuppressWarnings("deprecation") // setBackgroundDrawable is replaced by setBackground in API16
@ -1055,9 +1062,9 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
mInvalidatedKeys.add(key);
final int x = key.mX + getPaddingLeft();
final int y = key.mY + getPaddingTop();
mInvalidatedKeysRect.union(x, y, x + key.mWidth, y + key.mHeight);
mWorkingRect.set(x, y, x + key.mWidth, y + key.mHeight);
mBufferNeedsUpdate = true;
invalidate(mInvalidatedKeysRect);
invalidate(mWorkingRect);
}
public void closing() {
@ -1082,12 +1089,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
closing();
if (mPreviewPlacer != null) {
mPreviewPlacer.removeAllViews();
}
if (mBuffer != null) {
mBuffer.recycle();
mBuffer = null;
}
mPreviewPlacerView.removeAllViews();
freeOffscreenBuffer();
}
}

View File

@ -43,6 +43,7 @@ import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy;
import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
import com.android.inputmethod.keyboard.internal.SuddenJumpingTouchEventHandler;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
@ -153,8 +154,7 @@ public class MainKeyboardView extends KeyboardView implements PointerTracker.Key
}
break;
case MSG_TYPING_STATE_EXPIRED:
cancelAndStartAnimators(keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator,
keyboardView.mAltCodeKeyWhileTypingFadeinAnimator);
startWhileTypingFadeinAnimation(keyboardView);
break;
}
}
@ -228,7 +228,7 @@ public class MainKeyboardView extends KeyboardView implements PointerTracker.Key
removeMessages(MSG_LONGPRESS_KEY);
}
public static void cancelAndStartAnimators(final ObjectAnimator animatorToCancel,
private static void cancelAndStartAnimators(final ObjectAnimator animatorToCancel,
final ObjectAnimator animatorToStart) {
float startFraction = 0.0f;
if (animatorToCancel.isStarted()) {
@ -240,18 +240,39 @@ public class MainKeyboardView extends KeyboardView implements PointerTracker.Key
animatorToStart.setCurrentPlayTime(startTime);
}
private static void startWhileTypingFadeinAnimation(final MainKeyboardView keyboardView) {
cancelAndStartAnimators(keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator,
keyboardView.mAltCodeKeyWhileTypingFadeinAnimator);
}
private static void startWhileTypingFadeoutAnimation(final MainKeyboardView keyboardView) {
cancelAndStartAnimators(keyboardView.mAltCodeKeyWhileTypingFadeinAnimator,
keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator);
}
@Override
public void startTypingStateTimer() {
public void startTypingStateTimer(Key typedKey) {
if (typedKey.isModifier() || typedKey.altCodeWhileTyping()) {
return;
}
final boolean isTyping = isTypingState();
removeMessages(MSG_TYPING_STATE_EXPIRED);
final MainKeyboardView keyboardView = getOuterInstance();
// When user hits the space or the enter key, just cancel the while-typing timer.
final int typedCode = typedKey.mCode;
if (typedCode == Keyboard.CODE_SPACE || typedCode == Keyboard.CODE_ENTER) {
startWhileTypingFadeinAnimation(keyboardView);
return;
}
sendMessageDelayed(
obtainMessage(MSG_TYPING_STATE_EXPIRED), mParams.mIgnoreAltCodeKeyTimeout);
if (isTyping) {
return;
}
final MainKeyboardView keyboardView = getOuterInstance();
cancelAndStartAnimators(keyboardView.mAltCodeKeyWhileTypingFadeinAnimator,
keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator);
startWhileTypingFadeoutAnimation(keyboardView);
}
@Override
@ -461,7 +482,7 @@ public class MainKeyboardView extends KeyboardView implements PointerTracker.Key
super.setKeyboard(keyboard);
mKeyDetector.setKeyboard(
keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection);
PointerTracker.setKeyDetector(mKeyDetector, mGestureInputEnabled);
PointerTracker.setKeyDetector(mKeyDetector, mShouldHandleGesture);
mTouchScreenRegulator.setKeyboard(keyboard);
mMoreKeysPanelCache.clear();
@ -479,6 +500,14 @@ public class MainKeyboardView extends KeyboardView implements PointerTracker.Key
AccessibleKeyboardViewProxy.getInstance().setKeyboard(keyboard);
}
@Override
public void setGestureHandlingMode(final boolean shouldHandleGesture,
boolean drawsGesturePreviewTrail, boolean drawsGestureFloatingPreviewText) {
super.setGestureHandlingMode(shouldHandleGesture, drawsGesturePreviewTrail,
drawsGestureFloatingPreviewText);
PointerTracker.setKeyDetector(mKeyDetector, shouldHandleGesture);
}
/**
* Returns whether the device has distinct multi-touch panel.
* @return true if the device has distinct multi-touch panel.
@ -491,23 +520,6 @@ public class MainKeyboardView extends KeyboardView implements PointerTracker.Key
mHasDistinctMultitouch = hasDistinctMultitouch;
}
/**
* When enabled, calls to {@link KeyboardActionListener#onCodeInput} will include key
* codes for adjacent keys. When disabled, only the primary key code will be
* reported.
* @param enabled whether or not the proximity correction is enabled
*/
public void setProximityCorrectionEnabled(boolean enabled) {
mKeyDetector.setProximityCorrectionEnabled(enabled);
}
/**
* Returns true if proximity correction is enabled.
*/
public boolean isProximityCorrectionEnabled() {
return mKeyDetector.isProximityCorrectionEnabled();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();

View File

@ -39,7 +39,11 @@ public class MoreKeysDetector extends KeyDetector {
Key nearestKey = null;
int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
for (final Key key : getKeyboard().mKeys) {
final Keyboard keyboard = getKeyboard();
if (keyboard == null) {
throw new NullPointerException("Keyboard isn't set");
}
for (final Key key : keyboard.mKeys) {
final int dist = key.squaredDistanceToEdge(touchX, touchY);
if (dist < nearestDist) {
nearestKey = key;

View File

@ -18,7 +18,6 @@ package com.android.inputmethod.keyboard;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;
@ -42,8 +41,8 @@ public class PointerTracker {
private static final boolean DEBUG_LISTENER = false;
private static boolean DEBUG_MODE = LatinImeLogger.sDBG;
// TODO: There should be an option to turn on/off the gesture input.
private static boolean sIsGestureEnabled = true;
/** True if {@link PointerTracker}s should handle gesture events. */
private static boolean sShouldHandleGesture = false;
private static final int MIN_GESTURE_RECOGNITION_TIME = 100; // msec
@ -83,7 +82,7 @@ public class PointerTracker {
}
public interface TimerProxy {
public void startTypingStateTimer();
public void startTypingStateTimer(Key typedKey);
public boolean isTypingState();
public void startKeyRepeatTimer(PointerTracker tracker);
public void startLongPressTimer(PointerTracker tracker);
@ -96,7 +95,7 @@ public class PointerTracker {
public static class Adapter implements TimerProxy {
@Override
public void startTypingStateTimer() {}
public void startTypingStateTimer(Key typedKey) {}
@Override
public boolean isTypingState() { return false; }
@Override
@ -199,7 +198,7 @@ public class PointerTracker {
sNeedsPhantomSuddenMoveEventHack = needsPhantomSuddenMoveEventHack;
setParameters(MainKeyboardView.PointerTrackerParams.DEFAULT);
updateGestureInputEnabledState(null, false /* gestureInputEnabled */);
updateGestureHandlingMode(null, false /* shouldHandleGesture */);
}
public static void setParameters(MainKeyboardView.PointerTrackerParams params) {
@ -208,14 +207,13 @@ public class PointerTracker {
params.mTouchNoiseThresholdDistance * params.mTouchNoiseThresholdDistance);
}
private static void updateGestureInputEnabledState(Keyboard keyboard,
boolean gestureInputEnabled) {
if (!gestureInputEnabled
private static void updateGestureHandlingMode(Keyboard keyboard, boolean shouldHandleGesture) {
if (!shouldHandleGesture
|| AccessibilityUtils.getInstance().isTouchExplorationEnabled()
|| (keyboard != null && keyboard.mId.passwordInput())) {
sIsGestureEnabled = false;
sShouldHandleGesture = false;
} else {
sIsGestureEnabled = true;
sShouldHandleGesture = true;
}
}
@ -243,7 +241,7 @@ public class PointerTracker {
}
}
public static void setKeyDetector(KeyDetector keyDetector, boolean gestureInputEnabledByUser) {
public static void setKeyDetector(KeyDetector keyDetector, boolean shouldHandleGesture) {
final int trackersSize = sTrackers.size();
for (int i = 0; i < trackersSize; ++i) {
final PointerTracker tracker = sTrackers.get(i);
@ -252,7 +250,7 @@ public class PointerTracker {
tracker.mKeyboardLayoutHasBeenChanged = true;
}
final Keyboard keyboard = keyDetector.getKeyboard();
updateGestureInputEnabledState(keyboard, gestureInputEnabledByUser);
updateGestureHandlingMode(keyboard, shouldHandleGesture);
}
public static void dismissAllKeyPreviews() {
@ -297,17 +295,6 @@ public class PointerTracker {
sAggregratedPointers.reset();
}
// TODO: To handle multi-touch gestures we may want to move this method to
// {@link PointerTrackerQueue}.
public static void drawGestureTrailForAllPointerTrackers(Canvas canvas, Paint paint) {
final int trackersSize = sTrackers.size();
for (int i = 0; i < trackersSize; ++i) {
final PointerTracker tracker = sTrackers.get(i);
tracker.mGestureStroke.drawGestureTrail(canvas, paint, tracker.getLastX(),
tracker.getLastY());
}
}
private PointerTracker(int id, KeyEventHandler handler) {
if (handler == null)
throw new NullPointerException();
@ -342,9 +329,7 @@ public class PointerTracker {
mListener.onPressKey(key.mCode);
final boolean keyboardLayoutHasBeenChanged = mKeyboardLayoutHasBeenChanged;
mKeyboardLayoutHasBeenChanged = false;
if (!key.altCodeWhileTyping() && !key.isModifier()) {
mTimerProxy.startTypingStateTimer();
}
mTimerProxy.startTypingStateTimer(key);
return keyboardLayoutHasBeenChanged;
}
return false;
@ -423,7 +408,7 @@ public class PointerTracker {
if (mDrawingProxy != null) {
setReleasedKeyGraphics(mCurrentKey);
}
mCurrentKey = newKey;
// Keep {@link #mCurrentKey} that comes from previous keyboard.
}
final int keyQuarterWidth = mKeyboard.mMostCommonKeyWidth / 4;
mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth;
@ -525,6 +510,12 @@ public class PointerTracker {
mDrawingProxy.invalidateKey(key);
}
public void drawGestureTrail(Canvas canvas, Paint paint) {
if (mInGesture) {
mGestureStroke.drawGestureTrail(canvas, paint, mLastX, mLastY);
}
}
public int getLastX() {
return mLastX;
}
@ -536,9 +527,6 @@ public class PointerTracker {
public long getDownTime() {
return mDownTime;
}
public Rect getBoundingBox() {
return mGestureStroke.getBoundingBox();
}
private Key onDownKey(int x, int y, long eventTime) {
mDownTime = eventTime;
@ -669,8 +657,8 @@ public class PointerTracker {
if (queue != null && queue.size() == 1) {
mIsPossibleGesture = false;
// A gesture should start only from the letter key.
if (sIsGestureEnabled && mIsAlphabetKeyboard && !mIsShowingMoreKeysPanel && key != null
&& Keyboard.isLetterCode(key.mCode)) {
if (sShouldHandleGesture && mIsAlphabetKeyboard && !mIsShowingMoreKeysPanel
&& key != null && Keyboard.isLetterCode(key.mCode)) {
mIsPossibleGesture = true;
// TODO: pointer times should be relative to first down even in entire batch input
// instead of resetting to 0 for each new down event.
@ -714,7 +702,7 @@ public class PointerTracker {
private void onGestureMoveEvent(PointerTracker tracker, int x, int y, long eventTime,
boolean isHistorical, Key key) {
final int gestureTime = (int)(eventTime - tracker.getDownTime());
if (sIsGestureEnabled && mIsPossibleGesture) {
if (sShouldHandleGesture && mIsPossibleGesture) {
final GestureStroke stroke = mGestureStroke;
stroke.addPoint(x, y, gestureTime, isHistorical);
if (!mInGesture && stroke.isStartOfAGesture(gestureTime, sWasInGesture)) {
@ -804,13 +792,16 @@ public class PointerTracker {
final int dx = x - lastX;
final int dy = y - lastY;
final int lastMoveSquared = dx * dx + dy * dy;
// TODO: Should find a way to balance gesture detection and this hack.
if (sNeedsPhantomSuddenMoveEventHack
&& lastMoveSquared >= mKeyQuarterWidthSquared) {
&& lastMoveSquared >= mKeyQuarterWidthSquared
&& !mIsPossibleGesture) {
if (DEBUG_MODE) {
Log.w(TAG, String.format("onMoveEvent:"
+ " phantom sudden move event is translated to "
+ "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y));
}
// TODO: This should be moved to outside of this nested if-clause?
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.pointerTracker_onMoveEvent(x, y, lastX, lastY);
}
@ -826,7 +817,9 @@ public class PointerTracker {
&& !sPointerTrackerQueue.hasModifierKeyOlderThan(this)) {
onUpEventInternal(x, y, eventTime);
}
mKeyAlreadyProcessed = true;
if (!mIsPossibleGesture) {
mKeyAlreadyProcessed = true;
}
setReleasedKeyGraphics(oldKey);
}
}
@ -842,7 +835,9 @@ public class PointerTracker {
if (mIsAllowedSlidingKeyInput) {
onMoveToNewKey(key, x, y);
} else {
mKeyAlreadyProcessed = true;
if (!mIsPossibleGesture) {
mKeyAlreadyProcessed = true;
}
}
}
}
@ -881,6 +876,7 @@ public class PointerTracker {
private void onUpEventInternal(int x, int y, long eventTime) {
mTimerProxy.cancelKeyTimers();
mIsInSlidingKeyInput = false;
mIsPossibleGesture = false;
// Release the last pressed key.
setReleasedKeyGraphics(mCurrentKey);
if (mIsShowingMoreKeysPanel) {
@ -958,9 +954,7 @@ public class PointerTracker {
public void onRegisterKey(Key key) {
if (key != null) {
detectAndSendKey(key, key.mX, key.mY);
if (!key.altCodeWhileTyping() && !key.isModifier()) {
mTimerProxy.startTypingStateTimer();
}
mTimerProxy.startTypingStateTimer(key);
}
}

View File

@ -16,7 +16,6 @@ package com.android.inputmethod.keyboard.internal;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.FloatMath;
import com.android.inputmethod.latin.Constants;
@ -41,7 +40,6 @@ public class GestureStroke {
private int mMinGestureLength;
private int mMinGestureLengthWhileInGesture;
private int mMinGestureSampleLength;
private final Rect mDrawingRect = new Rect();
// TODO: Move some of these to resource.
private static final float MIN_GESTURE_LENGTH_RATIO_TO_KEY_WIDTH = 1.0f;
@ -90,7 +88,6 @@ public class GestureStroke {
mEventTimes.setLength(0);
mXCoordinates.setLength(0);
mYCoordinates.setLength(0);
mDrawingRect.setEmpty();
}
private void updateLastPoint(final int x, final int y, final int time) {
@ -198,8 +195,4 @@ public class GestureStroke {
}
}
}
public Rect getBoundingBox() {
return mDrawingRect;
}
}

View File

@ -84,6 +84,19 @@ public class KeySpecParser {
}
mIconId = getIconId(moreKeySpec);
}
@Override
public String toString() {
final String label = (mIconId == KeyboardIconsSet.ICON_UNDEFINED ? mLabel
: PREFIX_ICON + KeyboardIconsSet.getIconName(mIconId));
final String output = (mCode == Keyboard.CODE_OUTPUT_TEXT ? mOutputText
: Keyboard.printableCode(mCode));
if (StringUtils.codePointCount(label) == 1 && label.codePointAt(0) == mCode) {
return output;
} else {
return label + "|" + output;
}
}
}
private KeySpecParser() {

View File

@ -0,0 +1,185 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.inputmethod.keyboard.internal;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.text.TextUtils;
import android.util.SparseArray;
import android.widget.RelativeLayout;
import com.android.inputmethod.keyboard.PointerTracker;
import com.android.inputmethod.latin.R;
public class PreviewPlacerView extends RelativeLayout {
private final Paint mGesturePaint;
private final Paint mTextPaint;
private final int mGestureFloatingPreviewTextColor;
private final int mGestureFloatingPreviewTextOffset;
private final int mGestureFloatingPreviewTextShadowColor;
private final int mGestureFloatingPreviewTextShadowBorder;
private final int mGestureFloatingPreviewTextShadingColor;
private final int mGestureFloatingPreviewTextShadingBorder;
private final int mGestureFloatingPreviewTextConnectorColor;
private final int mGestureFloatingPreviewTextConnectorWidth;
private int mXOrigin;
private int mYOrigin;
private final SparseArray<PointerTracker> mPointers = new SparseArray<PointerTracker>();
private String mGestureFloatingPreviewText;
private boolean mDrawsGesturePreviewTrail;
private boolean mDrawsGestureFloatingPreviewText;
public PreviewPlacerView(Context context, TypedArray keyboardViewAttr) {
super(context);
setWillNotDraw(false);
final int gestureFloatingPreviewTextSize = keyboardViewAttr.getDimensionPixelSize(
R.styleable.KeyboardView_gestureFloatingPreviewTextSize, 0);
mGestureFloatingPreviewTextColor = keyboardViewAttr.getColor(
R.styleable.KeyboardView_gestureFloatingPreviewTextColor, 0);
mGestureFloatingPreviewTextOffset = keyboardViewAttr.getDimensionPixelOffset(
R.styleable.KeyboardView_gestureFloatingPreviewTextOffset, 0);
mGestureFloatingPreviewTextShadowColor = keyboardViewAttr.getColor(
R.styleable.KeyboardView_gestureFloatingPreviewTextShadowColor, 0);
mGestureFloatingPreviewTextShadowBorder = keyboardViewAttr.getDimensionPixelSize(
R.styleable.KeyboardView_gestureFloatingPreviewTextShadowBorder, 0);
mGestureFloatingPreviewTextShadingColor = keyboardViewAttr.getColor(
R.styleable.KeyboardView_gestureFloatingPreviewTextShadingColor, 0);
mGestureFloatingPreviewTextShadingBorder = keyboardViewAttr.getDimensionPixelSize(
R.styleable.KeyboardView_gestureFloatingPreviewTextShadingBorder, 0);
mGestureFloatingPreviewTextConnectorColor = keyboardViewAttr.getColor(
R.styleable.KeyboardView_gestureFloatingPreviewTextConnectorColor, 0);
mGestureFloatingPreviewTextConnectorWidth = keyboardViewAttr.getDimensionPixelSize(
R.styleable.KeyboardView_gestureFloatingPreviewTextConnectorWidth, 0);
final int gesturePreviewTrailColor = keyboardViewAttr.getColor(
R.styleable.KeyboardView_gesturePreviewTrailColor, 0);
final int gesturePreviewTrailWidth = keyboardViewAttr.getDimensionPixelSize(
R.styleable.KeyboardView_gesturePreviewTrailWidth, 0);
mGesturePaint = new Paint();
mGesturePaint.setAntiAlias(true);
mGesturePaint.setStyle(Paint.Style.STROKE);
mGesturePaint.setStrokeJoin(Paint.Join.ROUND);
mGesturePaint.setColor(gesturePreviewTrailColor);
mGesturePaint.setStrokeWidth(gesturePreviewTrailWidth);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setStrokeJoin(Paint.Join.ROUND);
mTextPaint.setTextAlign(Align.CENTER);
mTextPaint.setTextSize(gestureFloatingPreviewTextSize);
}
public void setOrigin(int x, int y) {
mXOrigin = x;
mYOrigin = y;
}
public void setGesturePreviewMode(boolean drawsGesturePreviewTrail,
boolean drawsGestureFloatingPreviewText) {
mDrawsGesturePreviewTrail = drawsGesturePreviewTrail;
mDrawsGestureFloatingPreviewText = drawsGestureFloatingPreviewText;
}
public void invalidatePointer(PointerTracker tracker) {
synchronized (mPointers) {
mPointers.put(tracker.mPointerId, tracker);
// TODO: Should narrow the invalidate region.
invalidate();
}
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
synchronized (mPointers) {
canvas.translate(mXOrigin, mYOrigin);
final int trackerCount = mPointers.size();
boolean hasDrawnFloatingPreviewText = false;
for (int index = 0; index < trackerCount; index++) {
final PointerTracker tracker = mPointers.valueAt(index);
if (mDrawsGesturePreviewTrail) {
tracker.drawGestureTrail(canvas, mGesturePaint);
}
// TODO: Figure out more cleaner way to draw gesture preview text.
if (mDrawsGestureFloatingPreviewText && !hasDrawnFloatingPreviewText) {
drawGestureFloatingPreviewText(canvas, tracker, mGestureFloatingPreviewText);
hasDrawnFloatingPreviewText = true;
}
}
canvas.translate(-mXOrigin, -mYOrigin);
}
}
public void setGestureFloatingPreviewText(String gestureFloatingPreviewText) {
mGestureFloatingPreviewText = gestureFloatingPreviewText;
invalidate();
}
private void drawGestureFloatingPreviewText(Canvas canvas, PointerTracker tracker,
String gestureFloatingPreviewText) {
if (TextUtils.isEmpty(gestureFloatingPreviewText)) {
return;
}
final Paint paint = mTextPaint;
final int lastX = tracker.getLastX();
final int lastY = tracker.getLastY();
final int textSize = (int)paint.getTextSize();
final int canvasWidth = canvas.getWidth();
final int halfTextWidth = (int)paint.measureText(gestureFloatingPreviewText) / 2 + textSize;
final int textX = Math.min(Math.max(lastX, halfTextWidth), canvasWidth - halfTextWidth);
int textY = Math.max(-textSize, lastY - mGestureFloatingPreviewTextOffset);
if (textY < 0) {
// Paint black text shadow if preview extends above keyboard region.
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setColor(mGestureFloatingPreviewTextShadowColor);
paint.setStrokeWidth(mGestureFloatingPreviewTextShadowBorder);
canvas.drawText(gestureFloatingPreviewText, textX, textY, paint);
}
// Paint the vertical line connecting the touch point to the preview text.
paint.setStyle(Paint.Style.STROKE);
paint.setColor(mGestureFloatingPreviewTextConnectorColor);
paint.setStrokeWidth(mGestureFloatingPreviewTextConnectorWidth);
final int lineTopY = textY - textSize / 4;
canvas.drawLine(lastX, lastY, lastX, lineTopY, paint);
if (lastX != textX) {
// Paint the horizontal line connection the touch point to the preview text.
canvas.drawLine(lastX, lineTopY, textX, lineTopY, paint);
}
// Paint the shading for the text preview
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setColor(mGestureFloatingPreviewTextShadingColor);
paint.setStrokeWidth(mGestureFloatingPreviewTextShadingBorder);
canvas.drawText(gestureFloatingPreviewText, textX, textY, paint);
// Paint the text preview
paint.setColor(mGestureFloatingPreviewTextColor);
paint.setStyle(Paint.Style.FILL);
canvas.drawText(gestureFloatingPreviewText, textX, textY, paint);
}
}

View File

@ -14,12 +14,14 @@
* the License.
*/
package com.android.inputmethod.keyboard;
package com.android.inputmethod.keyboard.internal;
import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.MainKeyboardView;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.Utils;

View File

@ -654,9 +654,12 @@ public class ExpandableDictionary extends Dictionary {
--index;
mLookedUpString[index] = node.mCode;
node = node.mParent;
} while (node != null);
} while (node != null && index > 0);
if (freq >= 0) {
// If node is null, we have a word longer than MAX_WORD_LENGTH in the dictionary.
// It's a little unclear how this can happen, but just in case it does it's safer
// to ignore the word in this case.
if (freq >= 0 && node == null) {
suggestions.add(new SuggestedWordInfo(new String(mLookedUpString, index,
BinaryDictionary.MAX_WORD_LENGTH - index),
freq, SuggestedWordInfo.KIND_CORRECTION, mDictType));

View File

@ -31,11 +31,7 @@ public class JniUtils {
try {
System.loadLibrary(JniLibName.JNI_LIB_NAME);
} catch (UnsatisfiedLinkError ule) {
Log.e(TAG, "Could not load native library " + JniLibName.JNI_LIB_NAME);
if (LatinImeLogger.sDBG) {
throw new RuntimeException(
"Could not load native library " + JniLibName.JNI_LIB_NAME);
}
Log.e(TAG, "Could not load native library " + JniLibName.JNI_LIB_NAME, ule);
}
}
}

View File

@ -60,6 +60,7 @@ import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
import com.android.inputmethod.compat.CompatUtils;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
import com.android.inputmethod.compat.SuggestionSpanUtils;
import com.android.inputmethod.keyboard.KeyDetector;
import com.android.inputmethod.keyboard.Keyboard;
@ -82,7 +83,8 @@ import java.util.Locale;
* Input method implementation for Qwerty'ish keyboard.
*/
public class LatinIME extends InputMethodService implements KeyboardActionListener,
SuggestionStripView.Listener, TargetApplicationGetter.OnTargetApplicationKnownListener {
SuggestionStripView.Listener, TargetApplicationGetter.OnTargetApplicationKnownListener,
Suggest.SuggestInitializationListener {
private static final String TAG = LatinIME.class.getSimpleName();
private static final boolean TRACE = false;
private static boolean DEBUG;
@ -174,6 +176,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private AlertDialog mOptionsDialog;
private final boolean mIsHardwareAcceleratedDrawingEnabled;
public final UIHandler mHandler = new UIHandler(this);
public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> {
@ -346,6 +350,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
super();
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
mIsHardwareAcceleratedDrawingEnabled =
InputMethodServiceCompatUtils.enableHardwareAcceleration(this);
Log.i(TAG, "Hardware accelerated drawing: " + mIsHardwareAcceleratedDrawingEnabled);
}
@Override
@ -426,6 +433,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
}
@Override
public void onUpdateMainDictionaryAvailability(boolean isMainDictionaryAvailable) {
mIsMainDictionaryAvailable = isMainDictionaryAvailable;
updateKeyboardViewGestureHandlingModeByMainDictionaryAvailability();
}
private void initSuggest() {
final Locale subtypeLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
final String localeStr = subtypeLocale.toString();
@ -437,7 +450,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} else {
oldContactsDictionary = null;
}
mSuggest = new Suggest(this, subtypeLocale);
mSuggest = new Suggest(this /* Context */, subtypeLocale,
this /* SuggestInitializationListener */);
if (mCurrentSettings.mCorrectionEnabled) {
mSuggest.setAutoCorrectionThreshold(mCurrentSettings.mAutoCorrectionThreshold);
}
@ -531,15 +545,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
commitTyped(LastComposedWord.NOT_A_SEPARATOR);
mConnection.finishComposingText();
mConnection.endBatchEdit();
if (isShowingOptionDialog())
if (isShowingOptionDialog()) {
mOptionsDialog.dismiss();
}
}
super.onConfigurationChanged(conf);
}
@Override
public View onCreateInputView() {
return mKeyboardSwitcher.onCreateInputView();
return mKeyboardSwitcher.onCreateInputView(mIsHardwareAcceleratedDrawingEnabled);
}
@Override
@ -651,40 +666,61 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
accessUtils.onStartInputViewInternal(editorInfo, restarting);
}
mSubtypeSwitcher.updateParametersOnStartInputView();
if (!restarting) {
mSubtypeSwitcher.updateParametersOnStartInputView();
}
// The EditorInfo might have a flag that affects fullscreen mode.
// Note: This call should be done by InputMethodService?
updateFullscreenMode();
mLastSelectionStart = editorInfo.initialSelStart;
mLastSelectionEnd = editorInfo.initialSelEnd;
mApplicationSpecifiedCompletions = null;
inputView.closing();
mEnteredText = null;
resetComposingState(true /* alsoResetLastComposedWord */);
mDeleteCount = 0;
mSpaceState = SPACE_STATE_NONE;
final boolean selectionChanged = mLastSelectionStart != editorInfo.initialSelStart
|| mLastSelectionEnd != editorInfo.initialSelEnd;
if (!restarting || selectionChanged) {
// If the selection changed, we reset the input state. Essentially, we come here with
// restarting == true when the app called setText() or similar. We should reset the
// state if the app set the text to something else, but keep it if it set a suggestion
// or something.
mEnteredText = null;
resetComposingState(true /* alsoResetLastComposedWord */);
mDeleteCount = 0;
mSpaceState = SPACE_STATE_NONE;
loadSettings();
if (mSuggest != null && mCurrentSettings.mCorrectionEnabled) {
mSuggest.setAutoCorrectionThreshold(mCurrentSettings.mAutoCorrectionThreshold);
if (mSuggestionStripView != null) {
mSuggestionStripView.clear();
}
}
switcher.loadKeyboard(editorInfo, mCurrentSettings);
if (!restarting) {
inputView.closing();
loadSettings();
if (mSuggestionStripView != null)
mSuggestionStripView.clear();
if (mSuggest != null && mCurrentSettings.mCorrectionEnabled) {
mSuggest.setAutoCorrectionThreshold(mCurrentSettings.mAutoCorrectionThreshold);
}
switcher.loadKeyboard(editorInfo, mCurrentSettings);
updateKeyboardViewGestureHandlingModeByMainDictionaryAvailability();
}
setSuggestionStripShownInternal(
isSuggestionsStripVisible(), /* needsInputViewShown */ false);
mLastSelectionStart = editorInfo.initialSelStart;
mLastSelectionEnd = editorInfo.initialSelEnd;
// If we come here something in the text state is very likely to have changed.
// We should update the shift state regardless of whether we are restarting or not, because
// this is not perceived as a layout change that may be disruptive like we may have with
// switcher.loadKeyboard; in apps like Talk, we come here when the text is sent and the
// field gets emptied and we need to re-evaluate the shift state, but not the whole layout
// which would be disruptive.
mKeyboardSwitcher.updateShiftState();
mHandler.cancelUpdateSuggestionStrip();
mHandler.cancelDoubleSpacesTimer();
inputView.setKeyPreviewPopupEnabled(mCurrentSettings.mKeyPreviewPopupOn,
mCurrentSettings.mKeyPreviewPopupDismissDelay);
inputView.setProximityCorrectionEnabled(true);
if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
}
@ -856,13 +892,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions);
}
if (!mCurrentSettings.isApplicationSpecifiedCompletionsOn()) return;
mApplicationSpecifiedCompletions = applicationSpecifiedCompletions;
if (applicationSpecifiedCompletions == null) {
clearSuggestionStrip();
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_onDisplayCompletions(null);
}
return;
}
@ -884,6 +920,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// this case? This says to keep whatever the user typed.
mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
setSuggestionStripShown(true);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions);
}
}
private void setSuggestionStripShownInternal(boolean shown, boolean needsInputViewShown) {
@ -1003,15 +1042,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final CharSequence typedWord = mWordComposer.getTypedWord();
if (typedWord.length() > 0) {
mConnection.commitText(typedWord, 1);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_commitText(typedWord);
}
final CharSequence prevWord = addToUserHistoryDictionary(typedWord);
mLastComposedWord = mWordComposer.commitWord(
LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(),
separatorCode, prevWord);
}
updateSuggestionStrip();
}
// Called from the KeyboardSwitcher which needs to know auto caps state to display
@ -1048,12 +1083,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (lastTwo != null && lastTwo.length() == 2
&& lastTwo.charAt(0) == Keyboard.CODE_SPACE) {
mConnection.deleteSurroundingText(2, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(2);
}
mConnection.commitText(lastTwo.charAt(1) + " ", 1);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_swapSwapperAndSpaceWhileInBatchEdit();
ResearchLogger.latinIME_swapSwapperAndSpace();
}
mKeyboardSwitcher.updateShiftState();
}
@ -1070,9 +1102,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mHandler.cancelDoubleSpacesTimer();
mConnection.deleteSurroundingText(2, 0);
mConnection.commitText(". ", 1);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_doubleSpaceAutoPeriod();
}
mKeyboardSwitcher.updateShiftState();
return true;
}
@ -1136,9 +1165,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void performEditorAction(int actionId) {
mConnection.performEditorAction(actionId);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_performEditorAction(actionId);
}
}
private void handleLanguageSwitchKey() {
@ -1175,6 +1201,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// For backward compatibility. See {@link InputMethodService#sendKeyChar(char)}.
if (code >= '0' && code <= '9') {
super.sendKeyChar((char)code);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_sendKeyCodePoint(code);
}
return;
}
@ -1191,9 +1220,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final String text = new String(new int[] { code }, 0, 1);
mConnection.commitText(text, text.length());
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_sendKeyCodePoint(code);
}
}
// Implementation of {@link KeyboardActionListener}.
@ -1205,11 +1231,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
mLastKeyTime = when;
mConnection.beginBatchEdit();
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_onCodeInput(primaryCode, x, y);
}
final KeyboardSwitcher switcher = mKeyboardSwitcher;
// The space state depends only on the last character pressed and its own previous
// state. Here, we revert the space state to neutral if the key is actually modifying
@ -1291,21 +1312,22 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mLastComposedWord.deactivate();
mEnteredText = null;
mConnection.endBatchEdit();
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_onCodeInput(primaryCode, x, y);
}
}
// Called from PointerTracker through the KeyboardActionListener interface
@Override
public void onTextInput(CharSequence text) {
public void onTextInput(CharSequence rawText) {
mConnection.beginBatchEdit();
commitTyped(LastComposedWord.NOT_A_SEPARATOR);
text = specificTldProcessingOnTextInput(text);
mHandler.postUpdateSuggestionStrip();
final CharSequence text = specificTldProcessingOnTextInput(rawText);
if (SPACE_STATE_PHANTOM == mSpaceState) {
sendKeyCodePoint(Keyboard.CODE_SPACE);
}
mConnection.commitText(text, 1);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_commitText(text);
}
mConnection.endBatchEdit();
mKeyboardSwitcher.updateShiftState();
mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT);
@ -1334,6 +1356,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mWordComposer.setBatchInputPointers(batchPointers);
final SuggestedWords suggestedWords = getSuggestedWords();
showSuggestionStrip(suggestedWords, null);
final String gestureFloatingPreviewText = (suggestedWords.size() > 0)
? suggestedWords.getWord(0) : null;
mKeyboardSwitcher.getKeyboardView()
.showGestureFloatingPreviewText(gestureFloatingPreviewText);
}
@Override
@ -1341,6 +1367,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mWordComposer.setBatchInputPointers(batchPointers);
final SuggestedWords suggestedWords = getSuggestedWords();
showSuggestionStrip(suggestedWords, null);
mKeyboardSwitcher.getKeyboardView().showGestureFloatingPreviewText(null);
if (suggestedWords == null || suggestedWords.size() == 0) {
return;
}
@ -1395,9 +1422,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// like the smiley key or the .com key.
final int length = mEnteredText.length();
mConnection.deleteSurroundingText(length, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(length);
}
// If we have mEnteredText, then we know that mHasUncommittedTypedChars == false.
// In addition we know that spaceState is false, and that we should not be
// reverting any autocorrect at this point. So we can safely return.
@ -1417,9 +1441,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mHandler.postUpdateSuggestionStrip();
} else {
mConnection.deleteSurroundingText(1, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(1);
}
}
} else {
if (mLastComposedWord.canRevertCommit()) {
@ -1448,9 +1469,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final int lengthToDelete = mLastSelectionEnd - mLastSelectionStart;
mConnection.setSelection(mLastSelectionEnd, mLastSelectionEnd);
mConnection.deleteSurroundingText(lengthToDelete, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(lengthToDelete);
}
} else {
// There is no selection, just delete one character.
if (NOT_A_CURSOR_POSITION == mLastSelectionEnd) {
@ -1469,14 +1487,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} else {
mConnection.deleteSurroundingText(1, 0);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(1);
}
if (mDeleteCount > DELETE_ACCELERATE_AT) {
mConnection.deleteSurroundingText(1, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(1);
}
}
}
if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
@ -1579,11 +1591,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
boolean didAutoCorrect = false;
// Handle separator
if (mWordComposer.isComposingWord()) {
// In certain languages where single quote is a separator, it's better
// not to auto correct, but accept the typed word. For instance,
// in Italian dov' should not be expanded to dove' because the elision
// requires the last vowel to be removed.
if (mCurrentSettings.mCorrectionEnabled && primaryCode != Keyboard.CODE_SINGLE_QUOTE) {
if (mCurrentSettings.mCorrectionEnabled) {
commitCurrentAutoCorrection(primaryCode);
didAutoCorrect = true;
} else {
@ -1617,13 +1625,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (swapWeakSpace) {
swapSwapperAndSpace();
mSpaceState = SPACE_STATE_SWAP_PUNCTUATION;
} else if (SPACE_STATE_PHANTOM == spaceState) {
} else if (SPACE_STATE_PHANTOM == spaceState
&& !mCurrentSettings.isWeakSpaceStripper(primaryCode)) {
// If we are in phantom space state, and the user presses a separator, we want to
// stay in phantom space state so that the next keypress has a chance to add the
// space. For example, if I type "Good dat", pick "day" from the suggestion strip
// then insert a comma and go on to typing the next word, I want the space to be
// inserted automatically before the next word, the same way it is when I don't
// input the comma.
// The case is a little different if the separator is a space stripper. Such a
// separator does not normally need a space on the right (that's the difference
// between swappers and strippers), so we should not stay in phantom space state if
// the separator is a stripper. Hence the additional test above.
mSpaceState = SPACE_STATE_PHANTOM;
}
@ -1647,8 +1660,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
commitTyped(LastComposedWord.NOT_A_SEPARATOR);
requestHideSelf(0);
MainKeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
if (inputView != null)
if (inputView != null) {
inputView.closing();
}
}
// TODO: make this private
@ -1799,10 +1813,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
+ "is empty? Impossible! I must commit suicide.");
}
Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_commitCurrentAutoCorrection(typedWord,
autoCorrection.toString());
}
mExpectingUpdateSelection = true;
commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD,
separatorCodePoint);
@ -1828,13 +1838,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// So, LatinImeLogger logs "" as a user's input.
LatinImeLogger.logOnManualSuggestion("", suggestion.toString(), index, suggestedWords);
// Rely on onCodeInput to do the complicated swapping/stripping logic consistently.
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_punctuationSuggestion(index, suggestion, x, y);
}
final int primaryCode = suggestion.charAt(0);
onCodeInput(primaryCode,
KeyboardActionListener.SUGGESTION_STRIP_COORDINATE,
KeyboardActionListener.SUGGESTION_STRIP_COORDINATE);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_punctuationSuggestion(index, suggestion, x, y);
}
return;
}
@ -1861,10 +1871,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index];
mConnection.commitCompletion(completionInfo);
mConnection.endBatchEdit();
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_pickApplicationSpecifiedCompletion(index,
completionInfo.getText(), x, y);
}
return;
}
@ -1873,12 +1879,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final String replacedWord = mWordComposer.getTypedWord().toString();
LatinImeLogger.logOnManualSuggestion(replacedWord,
suggestion.toString(), index, suggestedWords);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_pickSuggestionManually(replacedWord, index, suggestion, x, y);
}
mExpectingUpdateSelection = true;
commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK,
LastComposedWord.NOT_A_SEPARATOR);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_pickSuggestionManually(replacedWord, index, suggestion, x, y);
}
mConnection.endBatchEdit();
// Don't allow cancellation of manual pick
mLastComposedWord.deactivate();
@ -1913,9 +1919,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final SuggestedWords suggestedWords = mSuggestionStripView.getSuggestions();
mConnection.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan(
this, chosenWord, suggestedWords, mIsMainDictionaryAvailable), 1);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_commitText(chosenWord);
}
// Add the word to the user history dictionary
final CharSequence prevWord = addToUserHistoryDictionary(chosenWord);
// TODO: figure out here if this is an auto-correct or if the best word is actually
@ -1982,9 +1985,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mWordComposer.setComposingWord(word, mKeyboardSwitcher.getKeyboard());
final int length = word.length();
mConnection.deleteSurroundingText(length, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(length);
}
mConnection.setComposingText(word, 1);
mHandler.postUpdateSuggestionStrip();
}
@ -2012,9 +2012,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
mConnection.deleteSurroundingText(deleteLength, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(deleteLength);
}
if (!TextUtils.isEmpty(previousWord) && !TextUtils.isEmpty(committedWord)) {
mUserHistoryDictionary.cancelAddingUserHistory(
previousWord.toString(), committedWord.toString());
@ -2044,18 +2041,30 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void onRefreshKeyboard() {
// When the device locale is changed in SetupWizard etc., this method may get called via
// onConfigurationChanged before SoftInputWindow is shown.
initSuggest();
loadSettings();
if (mKeyboardSwitcher.getKeyboardView() != null) {
// Reload keyboard because the current language has been changed.
mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mCurrentSettings);
updateKeyboardViewGestureHandlingModeByMainDictionaryAvailability();
}
initSuggest();
loadSettings();
// Since we just changed languages, we should re-evaluate suggestions with whatever word
// we are currently composing. If we are not composing anything, we may want to display
// predictions or punctuation signs (which is done by the updateSuggestionStrip anyway).
mHandler.postUpdateSuggestionStrip();
}
private void updateKeyboardViewGestureHandlingModeByMainDictionaryAvailability() {
final MainKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView();
if (keyboardView != null) {
final boolean shouldHandleGesture = mCurrentSettings.mGestureInputEnabled
&& mIsMainDictionaryAvailable;
keyboardView.setGestureHandlingMode(shouldHandleGesture,
mCurrentSettings.mGesturePreviewTrailEnabled,
mCurrentSettings.mGestureFloatingPreviewTextEnabled);
}
}
// TODO: Remove this method from {@link LatinIME} and move {@link FeedbackManager} to
// {@link KeyboardSwitcher}. Called from KeyboardSwitcher
public void hapticAndAudioFeedback(final int primaryCode) {

View File

@ -55,7 +55,9 @@ public class RichInputConnection {
public void beginBatchEdit() {
if (++mNestLevel == 1) {
mIC = mParent.getCurrentInputConnection();
if (null != mIC) mIC.beginBatchEdit();
if (null != mIC) {
mIC.beginBatchEdit();
}
} else {
if (DBG) {
throw new RuntimeException("Nest level too deep");
@ -66,7 +68,9 @@ public class RichInputConnection {
}
public void endBatchEdit() {
if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
if (--mNestLevel == 0 && null != mIC) mIC.endBatchEdit();
if (--mNestLevel == 0 && null != mIC) {
mIC.endBatchEdit();
}
}
private void checkBatchEdit() {
@ -79,12 +83,22 @@ public class RichInputConnection {
public void finishComposingText() {
checkBatchEdit();
if (null != mIC) mIC.finishComposingText();
if (null != mIC) {
mIC.finishComposingText();
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.richInputConnection_finishComposingText();
}
}
}
public void commitText(final CharSequence text, final int i) {
checkBatchEdit();
if (null != mIC) mIC.commitText(text, i);
if (null != mIC) {
mIC.commitText(text, i);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.richInputConnection_commitText(text, i);
}
}
}
public int getCursorCapsMode(final int inputType) {
@ -107,37 +121,72 @@ public class RichInputConnection {
public void deleteSurroundingText(final int i, final int j) {
checkBatchEdit();
if (null != mIC) mIC.deleteSurroundingText(i, j);
if (null != mIC) {
mIC.deleteSurroundingText(i, j);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.richInputConnection_deleteSurroundingText(i, j);
}
}
}
public void performEditorAction(final int actionId) {
mIC = mParent.getCurrentInputConnection();
if (null != mIC) mIC.performEditorAction(actionId);
if (null != mIC) {
mIC.performEditorAction(actionId);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.richInputConnection_performEditorAction(actionId);
}
}
}
public void sendKeyEvent(final KeyEvent keyEvent) {
checkBatchEdit();
if (null != mIC) mIC.sendKeyEvent(keyEvent);
if (null != mIC) {
mIC.sendKeyEvent(keyEvent);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.richInputConnection_sendKeyEvent(keyEvent);
}
}
}
public void setComposingText(final CharSequence text, final int i) {
checkBatchEdit();
if (null != mIC) mIC.setComposingText(text, i);
if (null != mIC) {
mIC.setComposingText(text, i);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.richInputConnection_setComposingText(text, i);
}
}
}
public void setSelection(final int from, final int to) {
checkBatchEdit();
if (null != mIC) mIC.setSelection(from, to);
if (null != mIC) {
mIC.setSelection(from, to);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.richInputConnection_setSelection(from, to);
}
}
}
public void commitCorrection(final CorrectionInfo correctionInfo) {
checkBatchEdit();
if (null != mIC) mIC.commitCorrection(correctionInfo);
if (null != mIC) {
mIC.commitCorrection(correctionInfo);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.richInputConnection_commitCorrection(correctionInfo);
}
}
}
public void commitCompletion(final CompletionInfo completionInfo) {
checkBatchEdit();
if (null != mIC) mIC.commitCompletion(completionInfo);
if (null != mIC) {
mIC.commitCompletion(completionInfo);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.richInputConnection_commitCompletion(completionInfo);
}
}
}
public CharSequence getNthPreviousWord(final String sentenceSeperators, final int n) {
@ -315,9 +364,6 @@ public class RichInputConnection {
if (lastOne != null && lastOne.length() == 1
&& lastOne.charAt(0) == Keyboard.CODE_SPACE) {
deleteSurroundingText(1, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(1);
}
}
}
@ -382,13 +428,7 @@ public class RichInputConnection {
return false;
}
deleteSurroundingText(2, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(2);
}
commitText(" ", 1);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_revertDoubleSpaceWhileInBatchEdit();
}
return true;
}
@ -409,13 +449,7 @@ public class RichInputConnection {
return false;
}
deleteSurroundingText(2, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(2);
}
commitText(" " + textBeforeCursor.subSequence(0, 1), 1);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_revertSwapPunctuation();
}
return true;
}
}

View File

@ -62,6 +62,7 @@ public class Settings extends InputMethodSettingsFragment
public static final String PREF_LAST_USER_DICTIONARY_WRITE_TIME =
"last_user_dictionary_write_time";
public static final String PREF_ADVANCED_SETTINGS = "pref_advanced_settings";
public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict";
public static final String PREF_SUPPRESS_LANGUAGE_SWITCH_KEY =
"pref_suppress_language_switch_key";
public static final String PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST =
@ -69,13 +70,15 @@ public class Settings extends InputMethodSettingsFragment
public static final String PREF_CUSTOM_INPUT_STYLES = "custom_input_styles";
public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY =
"pref_key_preview_popup_dismiss_delay";
public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict";
public static final String PREF_BIGRAM_PREDICTIONS = "next_word_prediction";
public static final String PREF_GESTURE_INPUT = "gesture_input";
public static final String PREF_VIBRATION_DURATION_SETTINGS =
"pref_vibration_duration_settings";
public static final String PREF_KEYPRESS_SOUND_VOLUME =
"pref_keypress_sound_volume";
public static final String PREF_GESTURE_PREVIEW_TRAIL = "pref_gesture_preview_trail";
public static final String PREF_GESTURE_FLOATING_PREVIEW_TEXT =
"pref_gesture_floating_preview_text";
public static final String PREF_INPUT_LANGUAGE = "input_language";
public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
@ -94,13 +97,17 @@ public class Settings extends InputMethodSettingsFragment
private TextView mKeypressVibrationDurationSettingsTextView;
private TextView mKeypressSoundVolumeSettingsTextView;
private static void setPreferenceEnabled(Preference preference, boolean enabled) {
if (preference != null) {
preference.setEnabled(enabled);
}
}
private void ensureConsistencyOfAutoCorrectionSettings() {
final String autoCorrectionOff = getResources().getString(
R.string.auto_correction_threshold_mode_index_off);
final String currentSetting = mAutoCorrectionThresholdPreference.getValue();
if (null != mBigramPrediction) {
mBigramPrediction.setEnabled(!currentSetting.equals(autoCorrectionOff));
}
setPreferenceEnabled(mBigramPrediction, !currentSetting.equals(autoCorrectionOff));
}
@Override
@ -180,13 +187,11 @@ public class Settings extends InputMethodSettingsFragment
if (null == mKeyPreviewPopupDismissDelay.getValue()) {
mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
}
mKeyPreviewPopupDismissDelay.setEnabled(
setPreferenceEnabled(mKeyPreviewPopupDismissDelay,
SettingsValues.isKeyPreviewPopupEnabled(prefs, res));
}
final CheckBoxPreference includeOtherImesInLanguageSwitchList =
(CheckBoxPreference)findPreference(PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST);
includeOtherImesInLanguageSwitchList.setEnabled(
setPreferenceEnabled(findPreference(PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST),
!SettingsValues.isLanguageSwitchKeySupressed(prefs));
final PreferenceScreen dictionaryLink =
@ -200,10 +205,19 @@ public class Settings extends InputMethodSettingsFragment
final boolean gestureInputEnabledByBuildConfig = res.getBoolean(
R.bool.config_gesture_input_enabled_by_build_config);
final Preference gesturePreviewTrail = findPreference(PREF_GESTURE_PREVIEW_TRAIL);
final Preference gestureFloatingPreviewText = findPreference(
PREF_GESTURE_FLOATING_PREVIEW_TEXT);
if (!gestureInputEnabledByBuildConfig) {
final Preference gestureInputPref = findPreference(PREF_GESTURE_INPUT);
miscSettings.removePreference(gestureInputPref);
miscSettings.removePreference(findPreference(PREF_GESTURE_INPUT));
miscSettings.removePreference(gesturePreviewTrail);
miscSettings.removePreference(gestureFloatingPreviewText);
} else {
final boolean gestureInputEnabledByUser = prefs.getBoolean(PREF_GESTURE_INPUT, true);
setPreferenceEnabled(gesturePreviewTrail, gestureInputEnabledByUser);
setPreferenceEnabled(gestureFloatingPreviewText, gestureInputEnabledByUser);
}
final boolean showUsabilityStudyModeOption =
res.getBoolean(R.bool.config_enable_usability_study_mode_option)
|| ProductionFlag.IS_EXPERIMENTAL || ENABLE_EXPERIMENTAL_SETTINGS;
@ -277,17 +291,22 @@ public class Settings extends InputMethodSettingsFragment
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
(new BackupManager(getActivity())).dataChanged();
if (key.equals(PREF_POPUP_ON)) {
final ListPreference popupDismissDelay =
(ListPreference)findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
if (null != popupDismissDelay) {
popupDismissDelay.setEnabled(prefs.getBoolean(PREF_POPUP_ON, true));
}
setPreferenceEnabled(findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY),
prefs.getBoolean(PREF_POPUP_ON, true));
} else if (key.equals(PREF_SUPPRESS_LANGUAGE_SWITCH_KEY)) {
final CheckBoxPreference includeOtherImesInLanguageSwicthList =
(CheckBoxPreference)findPreference(
PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST);
includeOtherImesInLanguageSwicthList.setEnabled(
setPreferenceEnabled(findPreference(PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST),
!SettingsValues.isLanguageSwitchKeySupressed(prefs));
} else if (key.equals(PREF_GESTURE_INPUT)) {
final boolean gestureInputEnabledByConfig = getResources().getBoolean(
R.bool.config_gesture_input_enabled_by_build_config);
if (gestureInputEnabledByConfig) {
final boolean gestureInputEnabledByUser = prefs.getBoolean(
PREF_GESTURE_INPUT, true);
setPreferenceEnabled(findPreference(PREF_GESTURE_PREVIEW_TRAIL),
gestureInputEnabledByUser);
setPreferenceEnabled(findPreference(PREF_GESTURE_FLOATING_PREVIEW_TEXT),
gestureInputEnabledByUser);
}
}
ensureConsistencyOfAutoCorrectionSettings();
updateVoiceModeSummary();
@ -335,16 +354,18 @@ public class Settings extends InputMethodSettingsFragment
private void refreshEnablingsOfKeypressSoundAndVibrationSettings(
SharedPreferences sp, Resources res) {
if (mKeypressVibrationDurationSettingsPref != null) {
final boolean hasVibrator = VibratorUtils.getInstance(getActivity()).hasVibrator();
final boolean vibrateOn = hasVibrator && sp.getBoolean(Settings.PREF_VIBRATE_ON,
final boolean hasVibratorHardware = VibratorUtils.getInstance(getActivity())
.hasVibrator();
final boolean vibrateOnByUser = sp.getBoolean(Settings.PREF_VIBRATE_ON,
res.getBoolean(R.bool.config_default_vibration_enabled));
mKeypressVibrationDurationSettingsPref.setEnabled(vibrateOn);
setPreferenceEnabled(mKeypressVibrationDurationSettingsPref,
hasVibratorHardware && vibrateOnByUser);
}
if (mKeypressSoundVolumeSettingsPref != null) {
final boolean soundOn = sp.getBoolean(Settings.PREF_SOUND_ON,
res.getBoolean(R.bool.config_default_sound_enabled));
mKeypressSoundVolumeSettingsPref.setEnabled(soundOn);
setPreferenceEnabled(mKeypressSoundVolumeSettingsPref, soundOn);
}
}

View File

@ -84,6 +84,8 @@ public class SettingsValues {
private final float mKeypressSoundVolumeRawValue;
private final InputMethodSubtype[] mAdditionalSubtypes;
public final boolean mGestureInputEnabled;
public final boolean mGesturePreviewTrailEnabled;
public final boolean mGestureFloatingPreviewTextEnabled;
// From the input box
private final InputAttributes mInputAttributes;
@ -174,6 +176,9 @@ public class SettingsValues {
R.bool.config_gesture_input_enabled_by_build_config);
mGestureInputEnabled = gestureInputEnabledByBuildConfig
&& prefs.getBoolean(Settings.PREF_GESTURE_INPUT, true);
mGesturePreviewTrailEnabled = prefs.getBoolean(Settings.PREF_GESTURE_PREVIEW_TRAIL, true);
mGestureFloatingPreviewTextEnabled = prefs.getBoolean(
Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT, true);
mCorrectionEnabled = mAutoCorrectEnabled && !mInputAttributes.mInputTypeNoAutoCorrect;
mSuggestionVisibility = createSuggestionVisibility(res);
}

View File

@ -42,6 +42,10 @@ public class Suggest {
// TODO: rename this to CORRECTION_ON
public static final int CORRECTION_FULL = 1;
public interface SuggestInitializationListener {
public void onUpdateMainDictionaryAvailability(boolean isMainDictionaryAvailable);
}
private static final boolean DBG = LatinImeLogger.sDBG;
private Dictionary mMainDictionary;
@ -55,11 +59,14 @@ public class Suggest {
private float mAutoCorrectionThreshold;
// Locale used for upper- and title-casing words
final private Locale mLocale;
private final Locale mLocale;
private final SuggestInitializationListener mListener;
public Suggest(final Context context, final Locale locale) {
public Suggest(final Context context, final Locale locale,
final SuggestInitializationListener listener) {
initAsynchronously(context, locale);
mLocale = locale;
mListener = listener;
}
/* package for test */ Suggest(final Context context, final File dictionary,
@ -67,6 +74,7 @@ public class Suggest {
final Dictionary mainDict = DictionaryFactory.createDictionaryForTest(context, dictionary,
startOffset, length /* useFullEditDistance */, false, locale);
mLocale = locale;
mListener = null;
mMainDictionary = mainDict;
addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_MAIN, mainDict);
initWhitelistAndAutocorrectAndPool(context, locale);
@ -98,6 +106,9 @@ public class Suggest {
public void resetMainDict(final Context context, final Locale locale) {
mMainDictionary = null;
if (mListener != null) {
mListener.onUpdateMainDictionaryAvailability(hasMainDictionary());
}
new Thread("InitializeBinaryDictionary") {
@Override
public void run() {
@ -105,6 +116,9 @@ public class Suggest {
DictionaryFactory.createMainDictionaryFromManager(context, locale);
addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_MAIN, newMainDict);
mMainDictionary = newMainDict;
if (mListener != null) {
mListener.onUpdateMainDictionaryAvailability(hasMainDictionary());
}
}
}.start();
}
@ -219,7 +233,7 @@ public class Suggest {
// the current settings. It may also be useful to know, when the setting is off, whether
// the word *would* have been auto-corrected.
if (!isCorrectionEnabled || !allowsToBeAutoCorrected || !wordComposer.isComposingWord()
|| suggestionsSet.isEmpty()
|| suggestionsSet.isEmpty() || wordComposer.hasDigits()
|| wordComposer.isMostlyCaps() || wordComposer.isResumed()
|| !hasMainDictionary()) {
// If we don't have a main dictionary, we never want to auto-correct. The reason for

View File

@ -41,6 +41,7 @@ public class WordComposer {
// Cache these values for performance
private int mCapsCount;
private int mDigitsCount;
private boolean mAutoCapitalized;
private int mTrailingSingleQuotesCount;
private int mCodePointSize;
@ -65,6 +66,7 @@ public class WordComposer {
mTypedWord = new StringBuilder(source.mTypedWord);
mInputPointers.copy(source.mInputPointers);
mCapsCount = source.mCapsCount;
mDigitsCount = source.mDigitsCount;
mIsFirstCharCapitalized = source.mIsFirstCharCapitalized;
mAutoCapitalized = source.mAutoCapitalized;
mTrailingSingleQuotesCount = source.mTrailingSingleQuotesCount;
@ -80,6 +82,7 @@ public class WordComposer {
mTypedWord.setLength(0);
mAutoCorrection = null;
mCapsCount = 0;
mDigitsCount = 0;
mIsFirstCharCapitalized = false;
mTrailingSingleQuotesCount = 0;
mIsResumed = false;
@ -141,6 +144,7 @@ public class WordComposer {
mIsFirstCharCapitalized = isFirstCharCapitalized(
newIndex, primaryCode, mIsFirstCharCapitalized);
if (Character.isUpperCase(primaryCode)) mCapsCount++;
if (Character.isDigit(primaryCode)) mDigitsCount++;
if (Keyboard.CODE_SINGLE_QUOTE == primaryCode) {
++mTrailingSingleQuotesCount;
} else {
@ -213,6 +217,7 @@ public class WordComposer {
mTypedWord.deleteCharAt(stringBuilderLength - 1);
}
if (Character.isUpperCase(lastChar)) mCapsCount--;
if (Character.isDigit(lastChar)) mDigitsCount--;
refreshSize();
}
// We may have deleted the last one.
@ -267,6 +272,13 @@ public class WordComposer {
return mCapsCount > 1;
}
/**
* Returns true if we have digits in the composing word.
*/
public boolean hasDigits() {
return mDigitsCount > 0;
}
/**
* Saves the reason why the word is capitalized - whether it was automatic or
* due to the user hitting shift in the middle of a sentence.
@ -322,6 +334,7 @@ public class WordComposer {
lastComposedWord.deactivate();
}
mCapsCount = 0;
mDigitsCount = 0;
mIsBatchMode = false;
mTypedWord.setLength(0);
mTrailingSingleQuotesCount = 0;

View File

@ -61,8 +61,8 @@ public class FusionDictionary implements Iterable<Word> {
* This represents an "attribute", that is either a bigram or a shortcut.
*/
public static class WeightedString {
final String mWord;
int mFrequency;
public final String mWord;
public int mFrequency;
public WeightedString(String word, int frequency) {
mWord = word;
mFrequency = frequency;

View File

@ -27,10 +27,10 @@ import java.util.Arrays;
* This is chiefly used to iterate a dictionary.
*/
public class Word implements Comparable<Word> {
final String mWord;
final int mFrequency;
final ArrayList<WeightedString> mShortcutTargets;
final ArrayList<WeightedString> mBigrams;
public final String mWord;
public final int mFrequency;
public final ArrayList<WeightedString> mShortcutTargets;
public final ArrayList<WeightedString> mBigrams;
private int mHashCode = 0;

View File

@ -18,10 +18,7 @@ package com.android.inputmethod.research;
import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import com.android.inputmethod.latin.R;
@ -31,6 +28,11 @@ public class FeedbackActivity extends Activity {
super.onCreate(savedInstanceState);
setContentView(R.layout.research_feedback_activity);
final FeedbackLayout layout = (FeedbackLayout) findViewById(R.id.research_feedback_layout);
final CheckBox checkbox = (CheckBox) findViewById(R.id.research_feedback_include_history);
final CharSequence cs = checkbox.getText();
final String actualString = String.format(cs.toString(),
ResearchLogger.FEEDBACK_WORD_BUFFER_SIZE);
checkbox.setText(actualString);
layout.setActivity(this);
}

View File

@ -0,0 +1,111 @@
/*
* 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.research;
import java.util.LinkedList;
/**
* A buffer that holds a fixed number of LogUnits.
*
* LogUnits are added in and shifted out in temporal order. Only a subset of the LogUnits are
* actual words; the other LogUnits do not count toward the word limit. Once the buffer reaches
* capacity, adding another LogUnit that is a word evicts the oldest LogUnits out one at a time to
* stay under the capacity limit.
*/
public class LogBuffer {
protected final LinkedList<LogUnit> mLogUnits;
/* package for test */ int mWordCapacity;
// The number of members of mLogUnits that are actual words.
protected int mNumActualWords;
/**
* Create a new LogBuffer that can hold a fixed number of LogUnits that are words (and
* unlimited number of non-word LogUnits), and that outputs its result to a researchLog.
*
* @param wordCapacity maximum number of words
*/
LogBuffer(final int wordCapacity) {
if (wordCapacity <= 0) {
throw new IllegalArgumentException("wordCapacity must be 1 or greater.");
}
mLogUnits = new LinkedList<LogUnit>();
mWordCapacity = wordCapacity;
mNumActualWords = 0;
}
/**
* Adds a new LogUnit to the front of the LIFO queue, evicting existing LogUnit's
* (oldest first) if word capacity is reached.
*/
public void shiftIn(LogUnit newLogUnit) {
if (newLogUnit.getWord() == null) {
// This LogUnit isn't a word, so it doesn't count toward the word-limit.
mLogUnits.add(newLogUnit);
return;
}
if (mNumActualWords == mWordCapacity) {
shiftOutThroughFirstWord();
}
mLogUnits.add(newLogUnit);
mNumActualWords++; // Must be a word, or we wouldn't be here.
}
private void shiftOutThroughFirstWord() {
while (!mLogUnits.isEmpty()) {
final LogUnit logUnit = mLogUnits.removeFirst();
onShiftOut(logUnit);
if (logUnit.hasWord()) {
// Successfully shifted out a word-containing LogUnit and made space for the new
// LogUnit.
mNumActualWords--;
break;
}
}
}
/**
* Removes all LogUnits from the buffer without calling onShiftOut().
*/
public void clear() {
mLogUnits.clear();
mNumActualWords = 0;
}
/**
* Called when a LogUnit is removed from the LogBuffer as a result of a shiftIn. LogUnits are
* removed in the order entered. This method is not called when shiftOut is called directly.
*
* Base class does nothing; subclasses may override.
*/
protected void onShiftOut(LogUnit logUnit) {
}
/**
* Called to deliberately remove the oldest LogUnit. Usually called when draining the
* LogBuffer.
*/
public LogUnit shiftOut() {
if (mLogUnits.isEmpty()) {
return null;
}
final LogUnit logUnit = mLogUnits.removeFirst();
if (logUnit.hasWord()) {
mNumActualWords--;
}
return logUnit;
}
}

View File

@ -0,0 +1,81 @@
/*
* 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.research;
import java.util.ArrayList;
/**
* A group of log statements related to each other.
*
* A LogUnit is collection of LogStatements, each of which is generated by at a particular point
* in the code. (There is no LogStatement class; the data is stored across the instance variables
* here.) A single LogUnit's statements can correspond to all the calls made while in the same
* composing region, or all the calls between committing the last composing region, and the first
* character of the next composing region.
*
* Individual statements in a log may be marked as potentially private. If so, then they are only
* published to a ResearchLog if the ResearchLogger determines that publishing the entire LogUnit
* will not violate the user's privacy. Checks for this may include whether other LogUnits have
* been published recently, or whether the LogUnit contains numbers, etc.
*/
/* package */ class LogUnit {
private final ArrayList<String[]> mKeysList = new ArrayList<String[]>();
private final ArrayList<Object[]> mValuesList = new ArrayList<Object[]>();
private final ArrayList<Boolean> mIsPotentiallyPrivate = new ArrayList<Boolean>();
private String mWord;
private boolean mContainsDigit;
public void addLogStatement(final String[] keys, final Object[] values,
final Boolean isPotentiallyPrivate) {
mKeysList.add(keys);
mValuesList.add(values);
mIsPotentiallyPrivate.add(isPotentiallyPrivate);
}
public void publishTo(final ResearchLog researchLog, final boolean isIncludingPrivateData) {
final int size = mKeysList.size();
for (int i = 0; i < size; i++) {
if (!mIsPotentiallyPrivate.get(i) || isIncludingPrivateData) {
researchLog.outputEvent(mKeysList.get(i), mValuesList.get(i));
}
}
}
public void setWord(String word) {
mWord = word;
}
public String getWord() {
return mWord;
}
public boolean hasWord() {
return mWord != null;
}
public void setContainsDigit() {
mContainsDigit = true;
}
public boolean hasDigit() {
return mContainsDigit;
}
public boolean isEmpty() {
return mKeysList.isEmpty();
}
}

View File

@ -0,0 +1,127 @@
/*
* 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.research;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.Suggest;
import java.util.Random;
public class MainLogBuffer extends LogBuffer {
// The size of the n-grams logged. E.g. N_GRAM_SIZE = 2 means to sample bigrams.
private static final int N_GRAM_SIZE = 2;
// The number of words between n-grams to omit from the log.
private static final int DEFAULT_NUMBER_OF_WORDS_BETWEEN_SAMPLES = 18;
private final ResearchLog mResearchLog;
private Suggest mSuggest;
// The minimum periodicity with which n-grams can be sampled. E.g. mWinWordPeriod is 10 if
// every 10th bigram is sampled, i.e., words 1-8 are not, but the bigram at words 9 and 10, etc.
// for 11-18, and the bigram at words 19 and 20. If an n-gram is not safe (e.g. it contains a
// number in the middle or an out-of-vocabulary word), then sampling is delayed until a safe
// n-gram does appear.
/* package for test */ int mMinWordPeriod;
// Counter for words left to suppress before an n-gram can be sampled. Reset to mMinWordPeriod
// after a sample is taken.
/* package for test */ int mWordsUntilSafeToSample;
public MainLogBuffer(final ResearchLog researchLog) {
super(N_GRAM_SIZE);
mResearchLog = researchLog;
mMinWordPeriod = DEFAULT_NUMBER_OF_WORDS_BETWEEN_SAMPLES + N_GRAM_SIZE;
final Random random = new Random();
mWordsUntilSafeToSample = random.nextInt(mMinWordPeriod);
}
public void setSuggest(Suggest suggest) {
mSuggest = suggest;
}
@Override
public void shiftIn(final LogUnit newLogUnit) {
super.shiftIn(newLogUnit);
if (newLogUnit.hasWord()) {
if (mWordsUntilSafeToSample > 0) {
mWordsUntilSafeToSample--;
}
}
}
public void resetWordCounter() {
mWordsUntilSafeToSample = mMinWordPeriod;
}
/**
* Determines whether the content of the MainLogBuffer can be safely uploaded in its complete
* form and still protect the user's privacy.
*
* The size of the MainLogBuffer is just enough to hold one n-gram, its corrections, and any
* non-character data that is typed between words. The decision about privacy is made based on
* the buffer's entire content. If it is decided that the privacy risks are too great to upload
* the contents of this buffer, a censored version of the LogItems may still be uploaded. E.g.,
* the screen orientation and other characteristics about the device can be uploaded without
* revealing much about the user.
*/
public boolean isSafeToLog() {
// Check that we are not sampling too frequently. Having sampled recently might disclose
// too much of the user's intended meaning.
if (mWordsUntilSafeToSample > 0) {
return false;
}
if (mSuggest == null || !mSuggest.hasMainDictionary()) {
// Main dictionary is unavailable. Since we cannot check it, we cannot tell if a word
// is out-of-vocabulary or not. Therefore, we must judge the entire buffer contents to
// potentially pose a privacy risk.
return false;
}
// Reload the dictionary in case it has changed (e.g., because the user has changed
// languages).
final Dictionary dictionary = mSuggest.getMainDictionary();
if (dictionary == null) {
return false;
}
// Check each word in the buffer. If any word poses a privacy threat, we cannot upload the
// complete buffer contents in detail.
final int length = mLogUnits.size();
for (int i = 0; i < length; i++) {
final LogUnit logUnit = mLogUnits.get(i);
final String word = logUnit.getWord();
if (word == null) {
// Digits outside words are a privacy threat.
if (logUnit.hasDigit()) {
return false;
}
} else {
// Words not in the dictionary are a privacy threat.
if (!(dictionary.isValidWord(word))) {
return false;
}
}
}
// All checks have passed; this buffer's content can be safely uploaded.
return true;
}
@Override
protected void onShiftOut(LogUnit logUnit) {
if (mResearchLog != null) {
mResearchLog.publish(logUnit, false /* isIncludingPrivateData */);
}
}
}

View File

@ -26,7 +26,6 @@ import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethod.research.ResearchLogger.LogUnit;
import java.io.BufferedWriter;
import java.io.File;
@ -37,6 +36,7 @@ import java.io.OutputStreamWriter;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@ -51,21 +51,22 @@ import java.util.concurrent.TimeUnit;
*/
public class ResearchLog {
private static final String TAG = ResearchLog.class.getSimpleName();
private static final JsonWriter NULL_JSON_WRITER = new JsonWriter(
new OutputStreamWriter(new NullOutputStream()));
private static final boolean DEBUG = false;
private static final long FLUSH_DELAY_IN_MS = 1000 * 5;
private static final int ABORT_TIMEOUT_IN_MS = 1000 * 4;
final ScheduledExecutorService mExecutor;
/* package */ final ScheduledExecutorService mExecutor;
/* package */ final File mFile;
private JsonWriter mJsonWriter = NULL_JSON_WRITER;
// true if at least one byte of data has been written out to the log file. This must be
// remembered because JsonWriter requires that calls matching calls to beginObject and
// endObject, as well as beginArray and endArray, and the file is opened lazily, only when
// it is certain that data will be written. Alternatively, the matching call exceptions
// could be caught, but this might suppress other errors.
private boolean mHasWrittenData = false;
private int mLoggingState;
private static final int LOGGING_STATE_UNSTARTED = 0;
private static final int LOGGING_STATE_READY = 1; // don't create file until necessary
private static final int LOGGING_STATE_RUNNING = 2;
private static final int LOGGING_STATE_STOPPING = 3;
private static final int LOGGING_STATE_STOPPED = 4;
private static final long FLUSH_DELAY_IN_MS = 1000 * 5;
private static final JsonWriter NULL_JSON_WRITER = new JsonWriter(
new OutputStreamWriter(new NullOutputStream()));
private static class NullOutputStream extends OutputStream {
/** {@inheritDoc} */
@Override
@ -84,128 +85,81 @@ public class ResearchLog {
}
}
public ResearchLog(File outputFile) {
mExecutor = Executors.newSingleThreadScheduledExecutor();
public ResearchLog(final File outputFile) {
if (outputFile == null) {
throw new IllegalArgumentException();
}
mExecutor = Executors.newSingleThreadScheduledExecutor();
mFile = outputFile;
mLoggingState = LOGGING_STATE_UNSTARTED;
}
public synchronized void start() throws IOException {
switch (mLoggingState) {
case LOGGING_STATE_UNSTARTED:
mLoggingState = LOGGING_STATE_READY;
break;
case LOGGING_STATE_READY:
case LOGGING_STATE_RUNNING:
case LOGGING_STATE_STOPPING:
case LOGGING_STATE_STOPPED:
break;
}
}
public synchronized void stop() {
switch (mLoggingState) {
case LOGGING_STATE_UNSTARTED:
mLoggingState = LOGGING_STATE_STOPPED;
break;
case LOGGING_STATE_READY:
case LOGGING_STATE_RUNNING:
mExecutor.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
try {
mJsonWriter.endArray();
mJsonWriter.flush();
mJsonWriter.close();
} finally {
boolean success = mFile.setWritable(false, false);
mLoggingState = LOGGING_STATE_STOPPED;
}
return null;
public synchronized void close() {
mExecutor.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
try {
if (mHasWrittenData) {
mJsonWriter.endArray();
mJsonWriter.flush();
mJsonWriter.close();
mHasWrittenData = false;
}
});
removeAnyScheduledFlush();
mExecutor.shutdown();
mLoggingState = LOGGING_STATE_STOPPING;
break;
case LOGGING_STATE_STOPPING:
case LOGGING_STATE_STOPPED:
}
}
public boolean isAlive() {
switch (mLoggingState) {
case LOGGING_STATE_UNSTARTED:
case LOGGING_STATE_READY:
case LOGGING_STATE_RUNNING:
return true;
}
return false;
}
public void waitUntilStopped(final int timeoutInMs) throws InterruptedException {
} catch (Exception e) {
Log.d(TAG, "error when closing ResearchLog:");
e.printStackTrace();
} finally {
if (mFile.exists()) {
mFile.setWritable(false, false);
}
}
return null;
}
});
removeAnyScheduledFlush();
mExecutor.shutdown();
mExecutor.awaitTermination(timeoutInMs, TimeUnit.MILLISECONDS);
}
private boolean mIsAbortSuccessful;
public synchronized void abort() {
switch (mLoggingState) {
case LOGGING_STATE_UNSTARTED:
mLoggingState = LOGGING_STATE_STOPPED;
isAbortSuccessful = true;
break;
case LOGGING_STATE_READY:
case LOGGING_STATE_RUNNING:
mExecutor.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
try {
mJsonWriter.endArray();
mJsonWriter.close();
} finally {
isAbortSuccessful = mFile.delete();
}
return null;
mExecutor.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
try {
if (mHasWrittenData) {
mJsonWriter.endArray();
mJsonWriter.close();
mHasWrittenData = false;
}
});
removeAnyScheduledFlush();
mExecutor.shutdown();
mLoggingState = LOGGING_STATE_STOPPING;
break;
case LOGGING_STATE_STOPPING:
case LOGGING_STATE_STOPPED:
}
} finally {
mIsAbortSuccessful = mFile.delete();
}
return null;
}
});
removeAnyScheduledFlush();
mExecutor.shutdown();
}
private boolean isAbortSuccessful;
public boolean isAbortSuccessful() {
return isAbortSuccessful;
public boolean blockingAbort() throws InterruptedException {
abort();
mExecutor.awaitTermination(ABORT_TIMEOUT_IN_MS, TimeUnit.MILLISECONDS);
return mIsAbortSuccessful;
}
public void awaitTermination(int delay, TimeUnit timeUnit) throws InterruptedException {
mExecutor.awaitTermination(delay, timeUnit);
}
/* package */ synchronized void flush() {
switch (mLoggingState) {
case LOGGING_STATE_UNSTARTED:
break;
case LOGGING_STATE_READY:
case LOGGING_STATE_RUNNING:
removeAnyScheduledFlush();
mExecutor.submit(mFlushCallable);
break;
case LOGGING_STATE_STOPPING:
case LOGGING_STATE_STOPPED:
}
removeAnyScheduledFlush();
mExecutor.submit(mFlushCallable);
}
private Callable<Object> mFlushCallable = new Callable<Object>() {
private final Callable<Object> mFlushCallable = new Callable<Object>() {
@Override
public Object call() throws Exception {
if (mLoggingState == LOGGING_STATE_RUNNING) {
mJsonWriter.flush();
}
mJsonWriter.flush();
return null;
}
};
@ -224,56 +178,40 @@ public class ResearchLog {
mFlushFuture = mExecutor.schedule(mFlushCallable, FLUSH_DELAY_IN_MS, TimeUnit.MILLISECONDS);
}
public synchronized void publishPublicEvents(final LogUnit logUnit) {
switch (mLoggingState) {
case LOGGING_STATE_UNSTARTED:
break;
case LOGGING_STATE_READY:
case LOGGING_STATE_RUNNING:
mExecutor.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
logUnit.publishPublicEventsTo(ResearchLog.this);
scheduleFlush();
return null;
}
});
break;
case LOGGING_STATE_STOPPING:
case LOGGING_STATE_STOPPED:
}
}
public synchronized void publishAllEvents(final LogUnit logUnit) {
switch (mLoggingState) {
case LOGGING_STATE_UNSTARTED:
break;
case LOGGING_STATE_READY:
case LOGGING_STATE_RUNNING:
mExecutor.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
logUnit.publishAllEventsTo(ResearchLog.this);
scheduleFlush();
return null;
}
});
break;
case LOGGING_STATE_STOPPING:
case LOGGING_STATE_STOPPED:
public synchronized void publish(final LogUnit logUnit, final boolean isIncludingPrivateData) {
try {
mExecutor.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
logUnit.publishTo(ResearchLog.this, isIncludingPrivateData);
scheduleFlush();
return null;
}
});
} catch (RejectedExecutionException e) {
// TODO: Add code to record loss of data, and report.
}
}
private static final String CURRENT_TIME_KEY = "_ct";
private static final String UPTIME_KEY = "_ut";
private static final String EVENT_TYPE_KEY = "_ty";
void outputEvent(final String[] keys, final Object[] values) {
// not thread safe.
// Not thread safe.
if (keys.length == 0) {
return;
}
if (DEBUG) {
if (keys.length != values.length + 1) {
Log.d(TAG, "Key and Value list sizes do not match. " + keys[0]);
}
}
try {
if (mJsonWriter == NULL_JSON_WRITER) {
mJsonWriter = new JsonWriter(new BufferedWriter(new FileWriter(mFile)));
mJsonWriter.setLenient(true);
mJsonWriter.beginArray();
mHasWrittenData = true;
}
mJsonWriter.beginObject();
mJsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis());
@ -283,8 +221,8 @@ public class ResearchLog {
for (int i = 0; i < length; i++) {
mJsonWriter.name(keys[i + 1]);
Object value = values[i];
if (value instanceof String) {
mJsonWriter.value((String) value);
if (value instanceof CharSequence) {
mJsonWriter.value(value.toString());
} else if (value instanceof Number) {
mJsonWriter.value((Number) value);
} else if (value instanceof Boolean) {
@ -331,14 +269,11 @@ public class ResearchLog {
SuggestedWords words = (SuggestedWords) value;
mJsonWriter.beginObject();
mJsonWriter.name("typedWordValid").value(words.mTypedWordValid);
mJsonWriter.name("willAutoCorrect")
.value(words.mWillAutoCorrect);
mJsonWriter.name("willAutoCorrect").value(words.mWillAutoCorrect);
mJsonWriter.name("isPunctuationSuggestions")
.value(words.mIsPunctuationSuggestions);
mJsonWriter.name("isObsoleteSuggestions")
.value(words.mIsObsoleteSuggestions);
mJsonWriter.name("isPrediction")
.value(words.mIsPrediction);
.value(words.mIsPunctuationSuggestions);
mJsonWriter.name("isObsoleteSuggestions").value(words.mIsObsoleteSuggestions);
mJsonWriter.name("isPrediction").value(words.mIsPrediction);
mJsonWriter.name("words");
mJsonWriter.beginArray();
final int size = words.size();
@ -363,8 +298,8 @@ public class ResearchLog {
try {
mJsonWriter.close();
} catch (IllegalStateException e1) {
// assume that this is just the json not being terminated properly.
// ignore
// Assume that this is just the json not being terminated properly.
// Ignore
} catch (IOException e1) {
e1.printStackTrace();
} finally {

View File

@ -27,7 +27,6 @@ import android.os.BatteryManager;
import android.util.Log;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.R.string;
import java.io.BufferedReader;
import java.io.File;
@ -48,6 +47,7 @@ public final class ResearchLogUploader {
private static final String TAG = ResearchLogUploader.class.getSimpleName();
private static final int UPLOAD_INTERVAL_IN_MS = 1000 * 60 * 15; // every 15 min
private static final int BUF_SIZE = 1024 * 8;
protected static final int TIMEOUT_IN_MS = 1000 * 4;
private final boolean mCanUpload;
private final Context mContext;
@ -55,8 +55,6 @@ public final class ResearchLogUploader {
private final URL mUrl;
private final ScheduledExecutorService mExecutor;
private Runnable doUploadRunnable = new UploadRunnable(null, false);
public ResearchLogUploader(final Context context, final File filesDir) {
mContext = context;
mFilesDir = filesDir;
@ -93,11 +91,15 @@ public final class ResearchLogUploader {
public void start() {
if (mCanUpload) {
Log.d(TAG, "scheduling regular uploading");
mExecutor.scheduleWithFixedDelay(doUploadRunnable, UPLOAD_INTERVAL_IN_MS,
UPLOAD_INTERVAL_IN_MS, TimeUnit.MILLISECONDS);
} else {
Log.d(TAG, "no permission to upload");
mExecutor.scheduleWithFixedDelay(new UploadRunnable(null /* logToWaitFor */,
null /* callback */, false /* forceUpload */),
UPLOAD_INTERVAL_IN_MS, UPLOAD_INTERVAL_IN_MS, TimeUnit.MILLISECONDS);
}
}
public void uploadAfterCompletion(final ResearchLog researchLog, final Callback callback) {
if (mCanUpload) {
mExecutor.submit(new UploadRunnable(researchLog, callback, true /* forceUpload */));
}
}
@ -106,7 +108,8 @@ public final class ResearchLogUploader {
// another upload happening right now, as it may have missed the latest changes.
// TODO: Reschedule regular upload tests starting from now.
if (mCanUpload) {
mExecutor.submit(new UploadRunnable(callback, true));
mExecutor.submit(new UploadRunnable(null /* logToWaitFor */, callback,
true /* forceUpload */));
}
}
@ -130,19 +133,33 @@ public final class ResearchLogUploader {
}
class UploadRunnable implements Runnable {
private final ResearchLog mLogToWaitFor;
private final Callback mCallback;
private final boolean mForceUpload;
public UploadRunnable(final Callback callback, final boolean forceUpload) {
public UploadRunnable(final ResearchLog logToWaitFor, final Callback callback,
final boolean forceUpload) {
mLogToWaitFor = logToWaitFor;
mCallback = callback;
mForceUpload = forceUpload;
}
@Override
public void run() {
if (mLogToWaitFor != null) {
waitFor(mLogToWaitFor);
}
doUpload();
}
private void waitFor(final ResearchLog researchLog) {
try {
researchLog.awaitTermination(TIMEOUT_IN_MS, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void doUpload() {
if (!mForceUpload && (!isExternallyPowered() || !hasWifiConnection())) {
return;

Some files were not shown because too many files have changed in this diff Show More