Merge "Make makedict able to write binary format versions 1 and 2"
diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml
index f0ea8ce..76eacb6 100644
--- a/java/res/xml/key_styles_common.xml
+++ b/java/res/xml/key_styles_common.xml
@@ -79,6 +79,15 @@
<include
latin:keyboardLayout="@xml/key_styles_enter" />
<switch>
+ <!-- Shift + Enter in textMultiLine field. -->
+ <case
+ latin:isMultiLine="true"
+ latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ </case>
<!-- Smiley in textShortMessage field.
Overrides common enter key style. -->
<case
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 9a0fe1e..4329595 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -42,7 +42,6 @@
import com.android.inputmethod.deprecated.VoiceProxy;
import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy;
import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
-import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
@@ -81,8 +80,6 @@
private float mSpacebarTextSize;
private final int mSpacebarTextColor;
private final int mSpacebarTextShadowColor;
- // Height in space key the language name will be drawn. (proportional to space key height)
- private static final float SPACEBAR_LANGUAGE_BASELINE = 0.6f;
// If the full language name needs to be smaller than this value to be drawn on space key,
// its short language name will be used instead.
private static final float MINIMUM_SCALE_OF_LANGUAGE_NAME = 0.8f;
@@ -399,7 +396,7 @@
mMoreKeysPanelCache.clear();
mSpaceKey = keyboard.getKey(Keyboard.CODE_SPACE);
- mSpaceIcon = keyboard.mIconsSet.getIconDrawable(KeyboardIconsSet.ICON_SPACE);
+ mSpaceIcon = (mSpaceKey != null) ? mSpaceKey.getIcon(keyboard.mIconsSet) : null;
final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
mSpacebarTextSize = keyHeight * mSpacebarTextRatio;
mSpacebarLocale = keyboard.mId.mLocale;
@@ -787,8 +784,6 @@
@Override
protected void onDrawKeyTopVisuals(Key key, Canvas canvas, Paint paint, KeyDrawParams params) {
- super.onDrawKeyTopVisuals(key, canvas, paint, params);
-
if (key.mCode == Keyboard.CODE_SPACE) {
drawSpacebar(key, canvas, paint);
@@ -797,6 +792,8 @@
&& Utils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) {
drawKeyPopupHint(key, canvas, paint, params);
}
+ } else {
+ super.onDrawKeyTopVisuals(key, canvas, paint, params);
}
}
@@ -851,7 +848,7 @@
private void drawSpacebar(Key key, Canvas canvas, Paint paint) {
final int width = key.mWidth;
- final int height = mSpaceIcon != null ? mSpaceIcon.getIntrinsicHeight() : key.mHeight;
+ final int height = key.mHeight;
// If application locales are explicitly selected.
if (mNeedsToDisplayLanguage) {
@@ -862,8 +859,7 @@
// spacebar.
final float descent = paint.descent();
final float textHeight = -paint.ascent() + descent;
- final float baseline = (mSpaceIcon != null) ? height * SPACEBAR_LANGUAGE_BASELINE
- : height / 2 + textHeight / 2;
+ final float baseline = height / 2 + textHeight / 2;
paint.setColor(getSpacebarTextColor(mSpacebarTextShadowColor, mSpacebarTextFadeFactor));
canvas.drawText(language, width / 2, baseline - descent - 1, paint);
paint.setColor(getSpacebarTextColor(mSpacebarTextColor, mSpacebarTextFadeFactor));
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index 162e96d..7c8fd12 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -29,9 +29,8 @@
public class KeyboardIconsSet {
private static final String TAG = KeyboardIconsSet.class.getSimpleName();
- public static final int ICON_UNDEFINED = 0;
// The value should be aligned with the enum value of Key.keyIcon.
- public static final int ICON_SPACE = 4;
+ public static final int ICON_UNDEFINED = 0;
private static final int NUM_ICONS = 13;
private final Drawable[] mIcons = new Drawable[NUM_ICONS + 1];
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 6a8a036..18a3f97 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -546,16 +546,19 @@
|| code == Keyboard.CODE_OUTPUT_TEXT)) {
mSwitchState = SWITCH_STATE_SYMBOL;
}
- // Switch back to alpha keyboard mode immediately if user types a quote character.
+ // Switch back to alpha keyboard mode immediately if user types one of the switch back
+ // characters.
if (isLayoutSwitchBackCharacter(code)) {
toggleAlphabetAndSymbols();
+ mPrevSymbolsKeyboardWasShifted = false;
}
break;
case SWITCH_STATE_SYMBOL:
// Switch back to alpha keyboard mode if user types one or more non-space/enter
- // characters followed by a space/enter or a quote character.
+ // characters followed by a space/enter or one of the switch back characters.
if (isSpaceCharacter(code) || isLayoutSwitchBackCharacter(code)) {
toggleAlphabetAndSymbols();
+ mPrevSymbolsKeyboardWasShifted = false;
}
break;
}
diff --git a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
index f80534c..e6a59d0 100644
--- a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
@@ -212,7 +212,8 @@
@Override
public void loadDictionaryAsync() {
// Load the words that correspond to the current input locale
- Cursor cursor = query(MAIN_COLUMN_LOCALE + "=?", new String[] { mLocale });
+ final Cursor cursor = query(MAIN_COLUMN_LOCALE + "=?", new String[] { mLocale });
+ if (null == cursor) return;
try {
if (cursor.moveToFirst()) {
int word1Index = cursor.getColumnIndex(MAIN_COLUMN_WORD1);
@@ -249,11 +250,17 @@
qb.setProjectionMap(sDictProjectionMap);
// Get the database and run the query
- SQLiteDatabase db = sOpenHelper.getReadableDatabase();
- Cursor c = qb.query(db,
- new String[] { MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD2, FREQ_COLUMN_FREQUENCY },
- selection, selectionArgs, null, null, null);
- return c;
+ try {
+ SQLiteDatabase db = sOpenHelper.getReadableDatabase();
+ Cursor c = qb.query(db,
+ new String[] { MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD2, FREQ_COLUMN_FREQUENCY },
+ selection, selectionArgs, null, null, null);
+ return c;
+ } catch (android.database.sqlite.SQLiteCantOpenDatabaseException e) {
+ // Can't open the database : presumably we can't access storage. That may happen
+ // when the device is wedged; do a best effort to still start the keyboard.
+ return null;
+ }
}
/**
@@ -344,7 +351,18 @@
@Override
protected Void doInBackground(Void... v) {
- SQLiteDatabase db = mDbHelper.getWritableDatabase();
+ SQLiteDatabase db = null;
+ try {
+ db = mDbHelper.getWritableDatabase();
+ } catch (android.database.sqlite.SQLiteCantOpenDatabaseException e) {
+ // If we can't open the db, don't do anything. Exit through the next test
+ // for non-nullity of the db variable.
+ }
+ if (null == db) {
+ // Not much we can do. Just exit.
+ sUpdatingDB = false;
+ return null;
+ }
db.execSQL("PRAGMA foreign_keys = ON;");
// Write all the entries to the db
Iterator<Bigram> iterator = mMap.iterator();
diff --git a/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java b/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java
index a7f57ae..869865d 100644
--- a/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java
@@ -121,7 +121,8 @@
public void loadDictionaryAsync() {
if (!ENABLE_USER_UNIGRAM_DICTIONARY) return;
// Load the words that correspond to the current input locale
- Cursor cursor = query(COLUMN_LOCALE + "=?", new String[] { mLocale });
+ final Cursor cursor = query(COLUMN_LOCALE + "=?", new String[] { mLocale });
+ if (null == cursor) return;
try {
if (cursor.moveToFirst()) {
int wordIndex = cursor.getColumnIndex(COLUMN_WORD);
@@ -212,10 +213,16 @@
qb.setProjectionMap(sDictProjectionMap);
// Get the database and run the query
- SQLiteDatabase db = sOpenHelper.getReadableDatabase();
- Cursor c = qb.query(db, null, selection, selectionArgs, null, null,
- DEFAULT_SORT_ORDER);
- return c;
+ try {
+ SQLiteDatabase db = sOpenHelper.getReadableDatabase();
+ Cursor c = qb.query(db, null, selection, selectionArgs, null, null,
+ DEFAULT_SORT_ORDER);
+ return c;
+ } catch (android.database.sqlite.SQLiteCantOpenDatabaseException e) {
+ // Can't open the database : presumably we can't access storage. That may happen
+ // when the device is wedged; do a best effort to still start the keyboard.
+ return null;
+ }
}
/**
@@ -236,7 +243,14 @@
@Override
protected Void doInBackground(Void... v) {
- SQLiteDatabase db = mDbHelper.getWritableDatabase();
+ SQLiteDatabase db = null;
+ try {
+ db = mDbHelper.getWritableDatabase();
+ } catch (android.database.sqlite.SQLiteCantOpenDatabaseException e) {
+ // With no access to the DB, this is moot. Do nothing: we'll exit through the
+ // test for null == db.
+ }
+ if (null == db) return null;
// Write all the entries to the db
Set<Entry<String,Integer>> mEntries = mMap.entrySet();
for (Entry<String,Integer> entry : mEntries) {
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java
index ef0facf..de2a50f 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java
@@ -122,6 +122,8 @@
pressAndReleaseKey('~', SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
// Enter space, switch back to alphabet.
pressAndReleaseKey(CODE_SPACE, SYMBOLS_SHIFTED, ALPHABET_UNSHIFTED);
+ // Press/release "?123" key, enter into symbols (not symbols shifted).
+ pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
}
// Automatic switch back to alphabet shift locked test by space key.
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
index 78bd4d7..6286019 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -19,6 +19,8 @@
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.os.Looper;
+import android.os.MessageQueue;
import android.preference.PreferenceManager;
import android.test.ServiceTestCase;
import android.text.InputType;
@@ -127,6 +129,51 @@
}
}
+ // We need to run the messages added to the handler from LatinIME. The only way to do
+ // that is to call Looper#loop() on the right looper, so we're going to get the looper
+ // object and call #loop() here. The messages in the handler actually run on the UI
+ // thread of the keyboard by design of the handler, so we want to call it synchronously
+ // on the same thread that the tests are running on to mimic the actual environment as
+ // closely as possible.
+ // Now, Looper#loop() never exits in normal operation unless the Looper#quit() method
+ // is called, so we need to do that at the right time so that #loop() returns at some
+ // point and we don't end up in an infinite loop.
+ // After we quit, the looper is still technically ready to process more messages but
+ // the handler will refuse to enqueue any because #quit() has been called and it
+ // explicitly tests for it on message enqueuing, so we'll have to reset it so that
+ // it lets us continue normal operation.
+ private void runMessages() {
+ // Here begins deep magic.
+ final Looper looper = mLatinIME.mHandler.getLooper();
+ mLatinIME.mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ looper.quit();
+ }
+ });
+ // The only way to get out of Looper#loop() is to call #quit() on it (or on its queue).
+ // Once #quit() is called remaining messages are not processed, which is why we post
+ // a message that calls it instead of calling it directly.
+ looper.loop();
+
+ // Once #quit() has been called, the message queue has an "mQuiting" field that prevents
+ // any subsequent post in this queue. However the queue itself is still fully functional!
+ // If we have a way of resetting "queue.mQuiting" then we can continue using it as normal,
+ // coming back to this method to run the messages.
+ MessageQueue queue = looper.getQueue();
+ try {
+ // However there is no way of doing it externally, and mQuiting is private.
+ // So... get out the big guns.
+ java.lang.reflect.Field f = MessageQueue.class.getDeclaredField("mQuiting");
+ f.setAccessible(true); // What do you mean "private"?
+ f.setBoolean(queue, false);
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
// type(int) and type(String): helper methods to send a code point resp. a string to LatinIME.
private void type(final int codePoint) {
// onPressKey and onReleaseKey are explicitly deactivated here, but they do happen in the