diff --git a/java/res/drawable-mdpi/sym_keyboard_settings_holo.png b/java/res/drawable-mdpi/sym_keyboard_settings_holo.png
new file mode 100644
index 000000000..ad7618fa0
Binary files /dev/null and b/java/res/drawable-mdpi/sym_keyboard_settings_holo.png differ
diff --git a/java/res/drawable-xlarge/btn_center_default.9.png b/java/res/drawable-xlarge/btn_center_default.9.png
new file mode 100755
index 000000000..d5ec36ba4
Binary files /dev/null and b/java/res/drawable-xlarge/btn_center_default.9.png differ
diff --git a/java/res/drawable-xlarge/btn_center_pressed.9.png b/java/res/drawable-xlarge/btn_center_pressed.9.png
new file mode 100755
index 000000000..593a679d0
Binary files /dev/null and b/java/res/drawable-xlarge/btn_center_pressed.9.png differ
diff --git a/java/res/drawable-xlarge/btn_center_selected.9.png b/java/res/drawable-xlarge/btn_center_selected.9.png
new file mode 100644
index 000000000..f1914a886
Binary files /dev/null and b/java/res/drawable-xlarge/btn_center_selected.9.png differ
diff --git a/java/res/drawable-xlarge/caution.png b/java/res/drawable-xlarge/caution.png
new file mode 100755
index 000000000..eaef53425
Binary files /dev/null and b/java/res/drawable-xlarge/caution.png differ
diff --git a/java/res/drawable-xlarge/mic_base.png b/java/res/drawable-xlarge/mic_base.png
new file mode 100644
index 000000000..53e29ff4b
Binary files /dev/null and b/java/res/drawable-xlarge/mic_base.png differ
diff --git a/java/res/drawable-xlarge/mic_full.png b/java/res/drawable-xlarge/mic_full.png
new file mode 100644
index 000000000..e3e3dfac3
Binary files /dev/null and b/java/res/drawable-xlarge/mic_full.png differ
diff --git a/java/res/drawable-xlarge/mic_slash.png b/java/res/drawable-xlarge/mic_slash.png
new file mode 100644
index 000000000..1dd05c5b4
Binary files /dev/null and b/java/res/drawable-xlarge/mic_slash.png differ
diff --git a/java/res/drawable-xlarge/vs_dialog_blue.9.png b/java/res/drawable-xlarge/vs_dialog_blue.9.png
new file mode 100644
index 000000000..cf27e8f43
Binary files /dev/null and b/java/res/drawable-xlarge/vs_dialog_blue.9.png differ
diff --git a/java/res/drawable-xlarge/vs_dialog_red.9.png b/java/res/drawable-xlarge/vs_dialog_red.9.png
new file mode 100644
index 000000000..6c08d5a30
Binary files /dev/null and b/java/res/drawable-xlarge/vs_dialog_red.9.png differ
diff --git a/java/res/drawable-xlarge/vs_dialog_yellow.9.png b/java/res/drawable-xlarge/vs_dialog_yellow.9.png
new file mode 100644
index 000000000..2fb06c263
Binary files /dev/null and b/java/res/drawable-xlarge/vs_dialog_yellow.9.png differ
diff --git a/java/res/drawable-xlarge/vs_popup_mic_edge.png b/java/res/drawable-xlarge/vs_popup_mic_edge.png
new file mode 100644
index 000000000..4ff6337a2
Binary files /dev/null and b/java/res/drawable-xlarge/vs_popup_mic_edge.png differ
diff --git a/java/res/drawable/background_voice.xml b/java/res/drawable/background_voice.xml
new file mode 100644
index 000000000..3b6137df3
--- /dev/null
+++ b/java/res/drawable/background_voice.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/java/res/drawable/btn_center.xml b/java/res/drawable/btn_center.xml
new file mode 100644
index 000000000..19b298f75
--- /dev/null
+++ b/java/res/drawable/btn_center.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/java/res/drawable/btn_center_default.9.png b/java/res/drawable/btn_center_default.9.png
new file mode 100755
index 000000000..d5ec36ba4
Binary files /dev/null and b/java/res/drawable/btn_center_default.9.png differ
diff --git a/java/res/drawable/btn_center_pressed.9.png b/java/res/drawable/btn_center_pressed.9.png
new file mode 100755
index 000000000..593a679d0
Binary files /dev/null and b/java/res/drawable/btn_center_pressed.9.png differ
diff --git a/java/res/drawable/btn_center_selected.9.png b/java/res/drawable/btn_center_selected.9.png
new file mode 100644
index 000000000..f1914a886
Binary files /dev/null and b/java/res/drawable/btn_center_selected.9.png differ
diff --git a/java/res/drawable/caution.png b/java/res/drawable/caution.png
new file mode 100755
index 000000000..eaef53425
Binary files /dev/null and b/java/res/drawable/caution.png differ
diff --git a/java/res/drawable/mic_base.png b/java/res/drawable/mic_base.png
new file mode 100644
index 000000000..53e29ff4b
Binary files /dev/null and b/java/res/drawable/mic_base.png differ
diff --git a/java/res/drawable/mic_full.png b/java/res/drawable/mic_full.png
new file mode 100644
index 000000000..e3e3dfac3
Binary files /dev/null and b/java/res/drawable/mic_full.png differ
diff --git a/java/res/drawable/mic_slash.png b/java/res/drawable/mic_slash.png
new file mode 100644
index 000000000..1dd05c5b4
Binary files /dev/null and b/java/res/drawable/mic_slash.png differ
diff --git a/java/res/drawable/vs_dialog_blue.9.png b/java/res/drawable/vs_dialog_blue.9.png
new file mode 100644
index 000000000..cf27e8f43
Binary files /dev/null and b/java/res/drawable/vs_dialog_blue.9.png differ
diff --git a/java/res/drawable/vs_dialog_red.9.png b/java/res/drawable/vs_dialog_red.9.png
new file mode 100644
index 000000000..6c08d5a30
Binary files /dev/null and b/java/res/drawable/vs_dialog_red.9.png differ
diff --git a/java/res/drawable/vs_dialog_yellow.9.png b/java/res/drawable/vs_dialog_yellow.9.png
new file mode 100644
index 000000000..2fb06c263
Binary files /dev/null and b/java/res/drawable/vs_dialog_yellow.9.png differ
diff --git a/java/res/drawable/vs_popup_mic_edge.png b/java/res/drawable/vs_popup_mic_edge.png
new file mode 100644
index 000000000..4ff6337a2
Binary files /dev/null and b/java/res/drawable/vs_popup_mic_edge.png differ
diff --git a/java/res/layout/recognition_status.xml b/java/res/layout/recognition_status.xml
index ea2d9eefe..b2c9f4a51 100644
--- a/java/res/layout/recognition_status.xml
+++ b/java/res/layout/recognition_status.xml
@@ -16,83 +16,70 @@
** See the License for the specific language governing permissions and
** limitations under the License.
*/
--->
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+ android:background="@drawable/background_voice">
+
+
+
+
+
+
+
+
-
-
-
+
diff --git a/java/res/values-xlarge/config.xml b/java/res/values-xlarge/config.xml
index 56b9a166f..004b39b92 100644
--- a/java/res/values-xlarge/config.xml
+++ b/java/res/values-xlarge/config.xml
@@ -22,12 +22,19 @@
false
false
false
+ false
+ false
+ false
+ false
false
false
false
false
false
+ false
+
+ 1200
5
medium
diff --git a/java/res/values-xlarge/donottranslate.xml b/java/res/values-xlarge/donottranslate.xml
index 6f4e9b1f0..672dea589 100644
--- a/java/res/values-xlarge/donottranslate.xml
+++ b/java/res/values-xlarge/donottranslate.xml
@@ -19,5 +19,5 @@
-->
- 1
+ 2
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index 63af9a9ba..6a1b27a05 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -25,12 +25,25 @@
true
true
true
+ true
+ true
+ true
+ true
+ false
true
true
true
true
true
+
+ true
+ true
+ true
+
+ -1
+ 50
+ 15
0
10
0
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index 8dc212279..6a1069e99 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -138,4 +138,14 @@
- 4
- 5
+
+
+
+ - en_US
+ - en_GB
+
+
+ - English (US)
+ - English (UK)
+
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index b191e7fa0..7b8087a06 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -22,7 +22,7 @@
Android keyboard
Android keyboard settings
-
+
Input options
@@ -34,8 +34,11 @@
Popup on keypress
+
+ General
+
- Word suggestion settings
+ Text correction
Auto-capitalization
@@ -46,7 +49,7 @@
Corrects commonly typed mistakes
- Show suggestions
+ Show correction suggestions
Display suggested words while typing
Always show
@@ -111,15 +114,15 @@
Voice input is not currently supported for your language, but does work in English.
+ the first time, or turns it on in settings. [CHAR LIMIT=200] -->
Voice input uses Google\'s speech recognition. The Mobile Privacy Policy applies.
+ actually initiates voice input, rather than just turning it on in settings. [CHAR LIMIT=200] -->
To turn off voice input, go to input method settings.
+ "Press the microphone button"). [CHAR LIMIT=100] -->
To use voice input, press the microphone button.
diff --git a/java/res/xml-xlarge/kbd_key_styles.xml b/java/res/xml-xlarge/kbd_key_styles.xml
index c6b785896..26659a2ad 100644
--- a/java/res/xml-xlarge/kbd_key_styles.xml
+++ b/java/res/xml-xlarge/kbd_key_styles.xml
@@ -57,7 +57,6 @@
+
+
+ latin:horizontalGap="8.362%p" />
+
diff --git a/java/res/xml-xlarge/kbd_numkey_styles.xml b/java/res/xml-xlarge/kbd_numkey_styles.xml
index 3c62cb017..e27db94c7 100644
--- a/java/res/xml-xlarge/kbd_numkey_styles.xml
+++ b/java/res/xml-xlarge/kbd_numkey_styles.xml
@@ -81,7 +81,6 @@
diff --git a/java/res/xml-xlarge/kbd_phone.xml b/java/res/xml-xlarge/kbd_phone.xml
index c320ebbbc..b9444ad50 100644
--- a/java/res/xml-xlarge/kbd_phone.xml
+++ b/java/res/xml-xlarge/kbd_phone.xml
@@ -128,10 +128,13 @@
+ latin:horizontalGap="12.340%p" />
+
+ latin:keyWidth="16.084%p" />
+ latin:horizontalGap="8.362%p" />
+
diff --git a/java/res/xml-xlarge/kbd_qwerty_row4.xml b/java/res/xml-xlarge/kbd_qwerty_row4.xml
index 98acfc162..9d0fd81c7 100644
--- a/java/res/xml-xlarge/kbd_qwerty_row4.xml
+++ b/java/res/xml-xlarge/kbd_qwerty_row4.xml
@@ -26,7 +26,9 @@
latin:keyWidth="8.042%p"
>
+ latin:horizontalGap="8.362%p" />
+
+ latin:horizontalGap="8.362%p" />
+
+ latin:horizontalGap="24.446%p" />
+
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index 85b6d4767..e882320a3 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -4,9 +4,9 @@
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.
@@ -18,62 +18,68 @@
android:title="@string/english_ime_settings"
android:key="english_ime_settings">
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
-
-
+
+
" + this);
@@ -53,11 +65,21 @@ public class KeyboardShiftState {
public void setShiftLocked(boolean newShiftLockState) {
final int oldState = mState;
if (newShiftLockState) {
- if (oldState == NORMAL || oldState == MANUAL_SHIFTED || oldState == AUTO_SHIFTED)
+ switch (oldState) {
+ case NORMAL:
+ case MANUAL_SHIFTED:
+ case MANUAL_SHIFTED_FROM_AUTO:
+ case AUTO_SHIFTED:
mState = SHIFT_LOCKED;
+ break;
+ }
} else {
- if (oldState == SHIFT_LOCKED || oldState == SHIFT_LOCK_SHIFTED)
+ switch (oldState) {
+ case SHIFT_LOCKED:
+ case SHIFT_LOCK_SHIFTED:
mState = NORMAL;
+ break;
+ }
}
if (DEBUG)
Log.d(TAG, "setShiftLocked(" + newShiftLockState + "): " + toString(oldState)
@@ -84,7 +106,12 @@ public class KeyboardShiftState {
}
public boolean isManualTemporaryUpperCase() {
- return mState == MANUAL_SHIFTED || mState == SHIFT_LOCK_SHIFTED;
+ return mState == MANUAL_SHIFTED || mState == MANUAL_SHIFTED_FROM_AUTO
+ || mState == SHIFT_LOCK_SHIFTED;
+ }
+
+ public boolean isManualTemporaryUpperCaseFromAuto() {
+ return mState == MANUAL_SHIFTED_FROM_AUTO;
}
@Override
@@ -96,8 +123,9 @@ public class KeyboardShiftState {
switch (state) {
case NORMAL: return "NORMAL";
case MANUAL_SHIFTED: return "MANUAL_SHIFTED";
- case SHIFT_LOCKED: return "SHIFT_LOCKED";
+ case MANUAL_SHIFTED_FROM_AUTO: return "MANUAL_SHIFTED_FROM_AUTO";
case AUTO_SHIFTED: return "AUTO_SHIFTED";
+ case SHIFT_LOCKED: return "SHIFT_LOCKED";
case SHIFT_LOCK_SHIFTED: return "SHIFT_LOCK_SHIFTED";
default: return "UKNOWN";
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 331c8db6a..558de66a4 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -157,7 +157,15 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
boolean voiceButtonOnPrimary) {
mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA;
try {
+ if (mInputView == null) return;
+ final Keyboard oldKeyboard = mInputView.getKeyboard();
loadKeyboardInternal(mode, imeOptions, voiceKeyEnabled, voiceButtonOnPrimary, false);
+ final Keyboard newKeyboard = mInputView.getKeyboard();
+ if (newKeyboard.isAlphaKeyboard()) {
+ final boolean localeChanged = (oldKeyboard == null)
+ || !newKeyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
+ mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged);
+ }
} catch (RuntimeException e) {
Log.w(TAG, e);
LatinImeLogger.logOnException(mode + "," + imeOptions, e);
@@ -167,7 +175,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private void loadKeyboardInternal(int mode, int imeOptions, boolean voiceButtonEnabled,
boolean voiceButtonOnPrimary, boolean isSymbols) {
if (mInputView == null) return;
- mInputView.setPreviewEnabled(mInputMethodService.getPopupOn());
mMode = mode;
mImeOptions = imeOptions;
@@ -176,13 +183,16 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
mIsSymbols = isSymbols;
// Update the settings key state because number of enabled IMEs could have been changed
mHasSettingsKey = getSettingsKeyMode(mPrefs, mInputMethodService);
+ final KeyboardId id = getKeyboardId(mode, imeOptions, isSymbols);
+
+ final Keyboard oldKeyboard = mInputView.getKeyboard();
+ if (oldKeyboard != null && oldKeyboard.mId.equals(id))
+ return;
+
makeSymbolsKeyboardIds();
-
- KeyboardId id = getKeyboardId(mode, imeOptions, isSymbols);
- LatinKeyboard keyboard = getKeyboard(id);
-
mCurrentId = id;
- mInputView.setKeyboard(keyboard);
+ mInputView.setPreviewEnabled(mInputMethodService.getPopupOn());
+ mInputView.setKeyboard(getKeyboard(id));
}
private LatinKeyboard getKeyboard(KeyboardId id) {
@@ -210,6 +220,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
keyboard.onAutoCorrectionStateChanged(mIsAutoCorrectionActive);
keyboard.setShifted(false);
+ // If the cached keyboard had been switched to another keyboard while the language was
+ // displayed on its spacebar, it might have had arbitrary text fade factor. In such case,
+ // we should reset the text fade factor.
+ keyboard.setSpacebarTextFadeFactor(0.0f, null);
return keyboard;
}
@@ -313,6 +327,13 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
return false;
}
+ private boolean isManualTemporaryUpperCaseFromAuto() {
+ LatinKeyboard latinKeyboard = getLatinKeyboard();
+ if (latinKeyboard != null)
+ return latinKeyboard.isManualTemporaryUpperCaseFromAuto();
+ return false;
+ }
+
private void setManualTemporaryUpperCase(boolean shifted) {
LatinKeyboard latinKeyboard = getLatinKeyboard();
if (latinKeyboard != null) {
@@ -468,6 +489,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
} else if (isShiftedOrShiftLocked() && shiftKeyState.isPressingOnShifted()) {
// Shift has been pressed without chording while shifted state.
toggleShift();
+ } else if (isManualTemporaryUpperCaseFromAuto() && shiftKeyState.isPressing()) {
+ // Shift has been pressed without chording while manual temporary upper case
+ // transited from automatic temporary upper case.
+ toggleShift();
}
}
shiftKeyState.onRelease();
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index e7dd716fb..766fdf0e6 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -298,8 +298,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
- LayoutInflater inflate =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int previewLayout = 0;
int keyTextSize = 0;
@@ -365,7 +363,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
mPreviewPopup = new PopupWindow(context);
if (previewLayout != 0) {
- mPreviewText = (TextView) inflate.inflate(previewLayout, null);
+ mPreviewText = (TextView) LayoutInflater.from(context).inflate(previewLayout, null);
mPreviewTextSizeLarge = (int) res.getDimension(R.dimen.key_preview_text_size_large);
mPreviewPopup.setContentView(mPreviewText);
mPreviewPopup.setBackgroundDrawable(null);
@@ -912,9 +910,8 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
// We should re-draw popup preview when 1) we need to hide the preview, 2) we will show
// the space key preview and 3) pointer moves off the space key to other letter key, we
// should hide the preview of the previous key.
- @SuppressWarnings("unused")
final boolean hidePreviewOrShowSpaceKeyPreview = (tracker == null)
- || (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER
+ || (SubtypeSwitcher.getInstance().useSpacebarLanguageSwitcher()
&& SubtypeSwitcher.getInstance().needsToDisplayLanguage()
&& (tracker.isSpaceKey(keyIndex) || tracker.isSpaceKey(oldKeyIndex)));
// If key changed and preview is on or the key is space (language switch is enabled)
@@ -1081,9 +1078,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
private View inflateMiniKeyboardContainer(Key popupKey) {
int popupKeyboardResId = mKeyboard.getPopupKeyboardResId();
- LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- View container = inflater.inflate(mPopupLayout, null);
+ View container = LayoutInflater.from(getContext()).inflate(mPopupLayout, null);
if (container == null)
throw new NullPointerException();
@@ -1410,6 +1405,12 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
mBuffer = null;
mCanvas = null;
mMiniKeyboardCache.clear();
+ requestLayout();
+ }
+
+ public void purgeKeyboardAndClosing() {
+ mKeyboard = null;
+ closing();
}
@Override
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
index 77dde8d1b..888375b93 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
@@ -24,6 +24,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.PorterDuff;
@@ -47,7 +48,9 @@ public class LatinKeyboard extends Keyboard {
private final Drawable mSpaceAutoCorrectionIndicator;
private final Drawable mButtonArrowLeftIcon;
private final Drawable mButtonArrowRightIcon;
- private final int mSpaceBarTextShadowColor;
+ private final int mSpacebarTextColor;
+ private final int mSpacebarTextShadowColor;
+ private float mSpacebarTextFadeFactor = 0.0f;
private final int[] mSpaceKeyIndexArray;
private int mSpaceDragStartX;
private int mSpaceDragLastDiff;
@@ -80,11 +83,12 @@ public class LatinKeyboard extends Keyboard {
super(context, id.getXmlId(), id);
final Resources res = context.getResources();
mContext = context;
+ mSpacebarTextColor = res.getColor(R.color.latinkeyboard_bar_language_text);
if (id.mColorScheme == KeyboardView.COLOR_SCHEME_BLACK) {
- mSpaceBarTextShadowColor = res.getColor(
+ mSpacebarTextShadowColor = res.getColor(
R.color.latinkeyboard_bar_language_shadow_black);
} else { // default color scheme is KeyboardView.COLOR_SCHEME_WHITE
- mSpaceBarTextShadowColor = res.getColor(
+ mSpacebarTextShadowColor = res.getColor(
R.color.latinkeyboard_bar_language_shadow_white);
}
mSpaceAutoCorrectionIndicator = res.getDrawable(R.drawable.sym_keyboard_space_led);
@@ -96,25 +100,38 @@ public class LatinKeyboard extends Keyboard {
mSpaceKeyIndexArray = new int[] { indexOf(CODE_SPACE) };
}
+ public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboardView view) {
+ mSpacebarTextFadeFactor = fadeFactor;
+ updateSpacebarForLocale(false);
+ if (view != null)
+ view.invalidateKey(mSpaceKey);
+ }
+
+ private static int getSpacebarTextColor(int color, float fadeFactor) {
+ final int newColor = Color.argb((int)(Color.alpha(color) * fadeFactor),
+ Color.red(color), Color.green(color), Color.blue(color));
+ return newColor;
+ }
+
/**
* @return a key which should be invalidated.
*/
public Key onAutoCorrectionStateChanged(boolean isAutoCorrection) {
- updateSpaceBarForLocale(isAutoCorrection);
+ updateSpacebarForLocale(isAutoCorrection);
return mSpaceKey;
}
- private void updateSpaceBarForLocale(boolean isAutoCorrection) {
+ private void updateSpacebarForLocale(boolean isAutoCorrection) {
final Resources res = mContext.getResources();
// If application locales are explicitly selected.
if (SubtypeSwitcher.getInstance().needsToDisplayLanguage()) {
mSpaceKey.setIcon(new BitmapDrawable(res,
- drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCorrection)));
+ drawSpacebar(OPACITY_FULLY_OPAQUE, isAutoCorrection)));
} else {
// sym_keyboard_space_led can be shared with Black and White symbol themes.
if (isAutoCorrection) {
mSpaceKey.setIcon(new BitmapDrawable(res,
- drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCorrection)));
+ drawSpacebar(OPACITY_FULLY_OPAQUE, isAutoCorrection)));
} else {
mSpaceKey.setIcon(mSpaceIcon);
}
@@ -128,8 +145,8 @@ public class LatinKeyboard extends Keyboard {
return bounds.width();
}
- // Layout local language name and left and right arrow on space bar.
- private static String layoutSpaceBar(Paint paint, Locale locale, Drawable lArrow,
+ // Layout local language name and left and right arrow on spacebar.
+ private static String layoutSpacebar(Paint paint, Locale locale, Drawable lArrow,
Drawable rArrow, int width, int height, float origTextSize,
boolean allowVariableTextSize) {
final float arrowWidth = lArrow.getIntrinsicWidth();
@@ -138,7 +155,7 @@ public class LatinKeyboard extends Keyboard {
final Rect bounds = new Rect();
// Estimate appropriate language name text size to fit in maxTextWidth.
- String language = SubtypeSwitcher.getDisplayLanguage(locale);
+ String language = SubtypeSwitcher.getFullDisplayName(locale, true);
int textWidth = getTextWidth(paint, language, origTextSize, bounds);
// Assuming text width and text size are proportional to each other.
float textSize = origTextSize * Math.min(maxTextWidth / textWidth, 1.0f);
@@ -171,8 +188,7 @@ public class LatinKeyboard extends Keyboard {
return language;
}
- @SuppressWarnings("unused")
- private Bitmap drawSpaceBar(int opacity, boolean isAutoCorrection) {
+ private Bitmap drawSpacebar(int opacity, boolean isAutoCorrection) {
final int width = mSpaceKey.mWidth;
final int height = mSpaceIcon != null ? mSpaceIcon.getIntrinsicHeight() : mSpaceKey.mHeight;
final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
@@ -202,21 +218,25 @@ public class LatinKeyboard extends Keyboard {
}
final boolean allowVariableTextSize = true;
- final String language = layoutSpaceBar(paint, subtypeSwitcher.getInputLocale(),
+ final String language = layoutSpacebar(paint, subtypeSwitcher.getInputLocale(),
mButtonArrowLeftIcon, mButtonArrowRightIcon, width, height,
getTextSizeFromTheme(textStyle, defaultTextSize),
allowVariableTextSize);
// Draw language text with shadow
- final float baseline = height * SPACEBAR_LANGUAGE_BASELINE;
+ // In case there is no space icon, we will place the language text at the center of
+ // spacebar.
final float descent = paint.descent();
- paint.setColor(mSpaceBarTextShadowColor);
+ final float textHeight = -paint.ascent() + descent;
+ final float baseline = (mSpaceIcon != null) ? height * SPACEBAR_LANGUAGE_BASELINE
+ : height / 2 + textHeight / 2;
+ paint.setColor(getSpacebarTextColor(mSpacebarTextShadowColor, mSpacebarTextFadeFactor));
canvas.drawText(language, width / 2, baseline - descent - 1, paint);
- paint.setColor(res.getColor(R.color.latinkeyboard_bar_language_text));
+ paint.setColor(getSpacebarTextColor(mSpacebarTextColor, mSpacebarTextFadeFactor));
canvas.drawText(language, width / 2, baseline - descent, paint);
// Put arrows that are already layed out on either side of the text
- if (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER
+ if (SubtypeSwitcher.getInstance().useSpacebarLanguageSwitcher()
&& subtypeSwitcher.getEnabledKeyboardLocaleCount() > 1) {
mButtonArrowLeftIcon.draw(canvas);
mButtonArrowRightIcon.draw(canvas);
@@ -291,7 +311,6 @@ public class LatinKeyboard extends Keyboard {
* switching input languages.
*/
@Override
- @SuppressWarnings("unused") // SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER is constant
public boolean isInside(Key key, int pointX, int pointY) {
int x = pointX;
int y = pointY;
@@ -302,7 +321,7 @@ public class LatinKeyboard extends Keyboard {
if (code == CODE_DELETE) x -= key.mWidth / 6;
} else if (code == CODE_SPACE) {
y += LatinKeyboard.sSpacebarVerticalCorrection;
- if (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER
+ if (SubtypeSwitcher.getInstance().useSpacebarLanguageSwitcher()
&& SubtypeSwitcher.getInstance().getEnabledKeyboardLocaleCount() > 1) {
if (mCurrentlyInSpace) {
int diff = x - mSpaceDragStartX;
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 51bfbf1f9..e9d5580e8 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -85,6 +85,14 @@ public class LatinKeyboardView extends KeyboardView {
}
}
+ public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboard oldKeyboard) {
+ final LatinKeyboard currentKeyboard = getLatinKeyboard();
+ // We should not set text fade factor to the keyboard which does not display the language on
+ // its spacebar.
+ if (currentKeyboard != null && currentKeyboard == oldKeyboard)
+ currentKeyboard.setSpacebarTextFadeFactor(fadeFactor, this);
+ }
+
@Override
protected boolean onLongPress(Key key) {
int primaryCode = key.mCode;
@@ -197,10 +205,10 @@ public class LatinKeyboardView extends KeyboardView {
@Override
public boolean onTouchEvent(MotionEvent me) {
LatinKeyboard keyboard = getLatinKeyboard();
+ if (keyboard == null) return true;
// If there was a sudden jump, return without processing the actual motion event.
- if (handleSuddenJump(me))
- return true;
+ if (handleSuddenJump(me)) return true;
// Reset any bounding box controls in the keyboard
if (me.getAction() == MotionEvent.ACTION_DOWN) {
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java
index 458a9eed4..c150baadb 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java
@@ -71,7 +71,7 @@ public class MiniKeyboardBuilder {
for (CharSequence popupSpec : popupCharacters) {
final CharSequence label = PopupCharactersParser.getLabel(popupSpec.toString());
// If the label is single letter, minKeyWidth is enough to hold the label.
- if (label.length() > 1) {
+ if (label != null && label.length() > 1) {
if (paint == null) {
paint = new Paint();
paint.setAntiAlias(true);
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index af08742d3..b6035e15e 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -42,6 +42,7 @@ public class BinaryDictionary extends Dictionary {
private static final int TYPED_LETTER_MULTIPLIER = 2;
+ private static final BinaryDictionary sInstance = new BinaryDictionary();
private int mDicTypeId;
private int mNativeDict;
private long mDictLength;
@@ -59,16 +60,24 @@ public class BinaryDictionary extends Dictionary {
}
}
+ private BinaryDictionary() {
+ }
+
/**
- * Create a dictionary from a raw resource file
+ * Initialize a dictionary from a raw resource file
* @param context application context for reading resources
* @param resId the resource containing the raw binary dictionary
+ * @return initialized instance of BinaryDictionary
*/
- public BinaryDictionary(Context context, int resId, int dicTypeId) {
- if (resId != 0) {
- loadDictionary(context, resId);
+ public static BinaryDictionary initDictionary(Context context, int resId, int dicTypeId) {
+ synchronized (sInstance) {
+ sInstance.closeInternal();
+ if (resId != 0) {
+ sInstance.loadDictionary(context, resId);
+ sInstance.mDicTypeId = dicTypeId;
+ }
}
- mDicTypeId = dicTypeId;
+ return sInstance;
}
private native int openNative(String sourceDir, long dictOffset, long dictSize,
@@ -104,6 +113,8 @@ public class BinaryDictionary extends Dictionary {
@Override
public void getBigrams(final WordComposer codes, final CharSequence previousWord,
final WordCallback callback, int[] nextLettersFrequencies) {
+ if (mNativeDict == 0) return;
+
char[] chars = previousWord.toString().toCharArray();
Arrays.fill(mOutputChars_bigrams, (char) 0);
Arrays.fill(mFrequencies_bigrams, 0);
@@ -135,6 +146,8 @@ public class BinaryDictionary extends Dictionary {
@Override
public void getWords(final WordComposer codes, final WordCallback callback,
int[] nextLettersFrequencies) {
+ if (mNativeDict == 0) return;
+
final int codesSize = codes.size();
// Won't deal with really long words.
if (codesSize > MAX_WORD_LENGTH - 1) return;
@@ -179,6 +192,10 @@ public class BinaryDictionary extends Dictionary {
@Override
public synchronized void close() {
+ closeInternal();
+ }
+
+ private void closeInternal() {
if (mNativeDict != 0) {
closeNative(mNativeDict);
mNativeDict = 0;
@@ -188,7 +205,10 @@ public class BinaryDictionary extends Dictionary {
@Override
protected void finalize() throws Throwable {
- close();
- super.finalize();
+ try {
+ closeInternal();
+ } finally {
+ super.finalize();
+ }
}
}
diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java
index 30f4a59f9..d2d1f22dd 100644
--- a/java/src/com/android/inputmethod/latin/CandidateView.java
+++ b/java/src/com/android/inputmethod/latin/CandidateView.java
@@ -45,23 +45,22 @@ import android.widget.TextView;
import java.util.ArrayList;
public class CandidateView extends LinearLayout implements OnClickListener, OnLongClickListener {
- private LatinIME mService;
- private final ArrayList mWords = new ArrayList();
- private final TextView mPreviewText;
- private final PopupWindow mPreviewPopup;
-
+ private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
+ private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
private static final int MAX_SUGGESTIONS = 16;
+ private final ArrayList mWords = new ArrayList();
private final boolean mConfigCandidateHighlightFontColorEnabled;
+ private final CharacterStyle mInvertedForegroundColorSpan;
+ private final CharacterStyle mInvertedBackgroundColorSpan;
private final int mColorNormal;
private final int mColorRecommended;
private final int mColorOther;
- private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
- private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
- private final CharacterStyle mInvertedForegroundColorSpan;
- private final CharacterStyle mInvertedBackgroundColorSpan;
+ private final PopupWindow mPreviewPopup;
+ private final TextView mPreviewText;
+ private LatinIME mService;
private SuggestedWords mSuggestions = SuggestedWords.EMPTY;
private boolean mShowingAutoCorrectionInverted;
private boolean mShowingAddToDictionary;
@@ -186,9 +185,10 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
final TextView tv = (TextView)v.findViewById(R.id.candidate_word);
final TextView dv = (TextView)v.findViewById(R.id.candidate_debug_info);
tv.setTextColor(mColorNormal);
+ // TODO: Needs safety net?
if (suggestions.mHasMinimalSuggestion
- && ((i == 1 && !suggestions.mTypedWordValid) ||
- (i == 0 && suggestions.mTypedWordValid))) {
+ && ((i == 1 && !suggestions.mTypedWordValid)
+ || (i == 0 && suggestions.mTypedWordValid))) {
final CharacterStyle style;
if (mConfigCandidateHighlightFontColorEnabled) {
style = BOLD_SPAN;
@@ -329,7 +329,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
mService.pickSuggestionManually(index, word);
}
}
-
+
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
diff --git a/java/src/com/android/inputmethod/latin/InputLanguageSelection.java b/java/src/com/android/inputmethod/latin/InputLanguageSelection.java
index faee38eda..a9f2c2c22 100644
--- a/java/src/com/android/inputmethod/latin/InputLanguageSelection.java
+++ b/java/src/com/android/inputmethod/latin/InputLanguageSelection.java
@@ -107,7 +107,7 @@ public class InputLanguageSelection extends PreferenceActivity {
res.updateConfiguration(conf, res.getDisplayMetrics());
int mainDicResId = LatinIME.getMainDictionaryResourceId(res);
- BinaryDictionary bd = new BinaryDictionary(this, mainDicResId, Suggest.DIC_MAIN);
+ BinaryDictionary bd = BinaryDictionary.initDictionary(this, mainDicResId, Suggest.DIC_MAIN);
// Is the dictionary larger than a placeholder? Arbitrarily chose a lower limit of
// 4000-5000 words, whereas the LARGE_DICTIONARY is about 20000+ words.
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index ad7e4708a..b6042c769 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -22,6 +22,7 @@ import com.android.inputmethod.keyboard.KeyboardActionListener;
import com.android.inputmethod.keyboard.KeyboardId;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.KeyboardView;
+import com.android.inputmethod.keyboard.LatinKeyboard;
import com.android.inputmethod.keyboard.LatinKeyboardView;
import com.android.inputmethod.latin.Utils.RingCharBuffer;
import com.android.inputmethod.voice.VoiceIMEConnector;
@@ -132,14 +133,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private Resources mResources;
private SharedPreferences mPrefs;
+ // These variables are initialized according to the {@link EditorInfo#inputType}.
+ private boolean mAutoSpace;
+ private boolean mInputTypeNoAutoCorrect;
+ private boolean mIsSettingsSuggestionStripOn;
+ private boolean mApplicationSpecifiedCompletionOn;
+
private final StringBuilder mComposing = new StringBuilder();
private WordComposer mWord = new WordComposer();
private CharSequence mBestWord;
private boolean mHasValidSuggestions;
- private boolean mIsSettingsSuggestionStripOn;
- private boolean mApplicationSpecifiedCompletionOn;
private boolean mHasDictionary;
- private boolean mAutoSpace;
private boolean mJustAddedAutoSpace;
private boolean mAutoCorrectEnabled;
private boolean mReCorrectionEnabled;
@@ -151,6 +155,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private boolean mAutoCap;
private boolean mQuickFixes;
private boolean mConfigSwipeDownDismissKeyboardEnabled;
+ private int mConfigDelayBeforeFadeoutLanguageOnSpacebar;
+ private int mConfigDurationOfFadeoutLanguageOnSpacebar;
+ private float mConfigFinalFadeoutFactorOfLanguageOnSpacebar;
private int mCorrectionMode;
private int mCommittedLength;
@@ -160,9 +167,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private int mLastSelectionEnd;
private SuggestedWords mSuggestPuncList;
- // Input type is such that we should not auto-correct
- private boolean mInputTypeNoAutoCorrect;
-
// Indicates whether the suggestion strip is to be on in landscape
private boolean mJustAccepted;
private boolean mJustReverted;
@@ -241,9 +245,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private static final int MSG_UPDATE_OLD_SUGGESTIONS = 1;
private static final int MSG_UPDATE_SHIFT_STATE = 2;
private static final int MSG_VOICE_RESULTS = 3;
+ private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 4;
+ private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5;
@Override
public void handleMessage(Message msg) {
+ final KeyboardSwitcher switcher = mKeyboardSwitcher;
+ final LatinKeyboardView inputView = switcher.getInputView();
switch (msg.what) {
case MSG_UPDATE_SUGGESTIONS:
updateSuggestions();
@@ -252,12 +260,24 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
setOldSuggestions();
break;
case MSG_UPDATE_SHIFT_STATE:
- mKeyboardSwitcher.updateShiftState();
+ switcher.updateShiftState();
break;
case MSG_VOICE_RESULTS:
mVoiceConnector.handleVoiceResults(preferCapitalization()
- || (mKeyboardSwitcher.isAlphabetMode()
- && mKeyboardSwitcher.isShiftedOrShiftLocked()));
+ || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked()));
+ break;
+ case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR:
+ if (inputView != null)
+ inputView.setSpacebarTextFadeFactor(
+ (1.0f + mConfigFinalFadeoutFactorOfLanguageOnSpacebar) / 2,
+ (LatinKeyboard)msg.obj);
+ sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj),
+ mConfigDurationOfFadeoutLanguageOnSpacebar);
+ break;
+ case MSG_DISMISS_LANGUAGE_ON_SPACEBAR:
+ if (inputView != null)
+ inputView.setSpacebarTextFadeFactor(
+ mConfigFinalFadeoutFactorOfLanguageOnSpacebar, (LatinKeyboard)msg.obj);
break;
}
}
@@ -297,6 +317,24 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void updateVoiceResults() {
sendMessage(obtainMessage(MSG_VOICE_RESULTS));
}
+
+ public void startDisplayLanguageOnSpacebar(boolean localeChanged) {
+ removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR);
+ removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR);
+ final LatinKeyboardView inputView = mKeyboardSwitcher.getInputView();
+ if (inputView != null) {
+ final LatinKeyboard keyboard = inputView.getLatinKeyboard();
+ // The language is never displayed when the delay is zero.
+ if (mConfigDelayBeforeFadeoutLanguageOnSpacebar != 0)
+ inputView.setSpacebarTextFadeFactor(localeChanged ? 1.0f
+ : mConfigFinalFadeoutFactorOfLanguageOnSpacebar, keyboard);
+ // The language is always displayed when the delay is negative.
+ if (localeChanged && mConfigDelayBeforeFadeoutLanguageOnSpacebar > 0) {
+ sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard),
+ mConfigDelayBeforeFadeoutLanguageOnSpacebar);
+ }
+ }
+ }
}
@Override
@@ -315,10 +353,24 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final Resources res = getResources();
mResources = res;
- mReCorrectionEnabled = prefs.getBoolean(Settings.PREF_RECORRECTION_ENABLED,
- res.getBoolean(R.bool.default_recorrection_enabled));
+
+ // If the option should not be shown, do not read the recorrection preference
+ // but always use the default setting defined in the resources.
+ if (res.getBoolean(R.bool.config_enable_show_recorrection_option)) {
+ mReCorrectionEnabled = prefs.getBoolean(Settings.PREF_RECORRECTION_ENABLED,
+ res.getBoolean(R.bool.default_recorrection_enabled));
+ } else {
+ mReCorrectionEnabled = res.getBoolean(R.bool.default_recorrection_enabled);
+ }
+
mConfigSwipeDownDismissKeyboardEnabled = res.getBoolean(
R.bool.config_swipe_down_dismiss_keyboard_enabled);
+ mConfigDelayBeforeFadeoutLanguageOnSpacebar = res.getInteger(
+ R.integer.config_delay_before_fadeout_language_on_spacebar);
+ mConfigDurationOfFadeoutLanguageOnSpacebar = res.getInteger(
+ R.integer.config_duration_of_fadeout_language_on_spacebar);
+ mConfigFinalFadeoutFactorOfLanguageOnSpacebar = res.getInteger(
+ R.integer.config_final_fadeout_percentage_of_language_on_spacebar) / 100.0f;
Utils.GCUtils.getInstance().reset();
boolean tryGC = true;
@@ -360,7 +412,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mSuggest.close();
}
final SharedPreferences prefs = mPrefs;
- mQuickFixes = prefs.getBoolean(Settings.PREF_QUICK_FIXES, true);
+ mQuickFixes = isQuickFixesEnabled(prefs);
final Resources res = mResources;
int mainDicResId = getMainDictionaryResourceId(res);
@@ -402,27 +454,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void onConfigurationChanged(Configuration conf) {
mSubtypeSwitcher.onConfigurationChanged(conf);
- if (mSubtypeSwitcher.isKeyboardMode())
- onKeyboardLanguageChanged();
- updateAutoTextEnabled();
-
// If orientation changed while predicting, commit the change
if (conf.orientation != mOrientation) {
InputConnection ic = getCurrentInputConnection();
commitTyped(ic);
if (ic != null) ic.finishComposingText(); // For voice input
mOrientation = conf.orientation;
- final int mode = mKeyboardSwitcher.getKeyboardMode();
- final EditorInfo attribute = getCurrentInputEditorInfo();
- final int imeOptions = (attribute != null) ? attribute.imeOptions : 0;
- mKeyboardSwitcher.loadKeyboard(mode, imeOptions,
- mVoiceConnector.isVoiceButtonEnabled(),
- mVoiceConnector.isVoiceButtonOnPrimary());
}
mConfigurationChanging = true;
super.onConfigurationChanged(conf);
- mVoiceConnector.onConfigurationChanged(mConfigurationChanging);
+ mVoiceConnector.onConfigurationChanged(conf);
mConfigurationChanging = false;
}
@@ -473,24 +515,62 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mRefreshKeyboardRequired) {
mRefreshKeyboardRequired = false;
- onKeyboardLanguageChanged();
+ onRefreshKeyboard();
}
TextEntryState.newSession(this);
- // Most such things we decide below in the switch statement, but we need to know
- // now whether this is a password text field, because we need to know now (before
- // the switch statement) whether we want to enable the voice button.
- int variation = attribute.inputType & InputType.TYPE_MASK_VARIATION;
- mVoiceConnector.resetVoiceStates(isPasswordVariation(variation));
+ // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to
+ // know now whether this is a password text field, because we need to know now whether we
+ // want to enable the voice button.
+ mVoiceConnector.resetVoiceStates(isPasswordVariation(
+ attribute.inputType & InputType.TYPE_MASK_VARIATION));
+
+ final int mode = initializeInputAttributesAndGetMode(attribute.inputType);
+
+ inputView.closing();
+ mEnteredText = null;
+ mComposing.setLength(0);
+ mHasValidSuggestions = false;
+ mDeleteCount = 0;
+ mJustAddedAutoSpace = false;
+
+ loadSettings(attribute);
+ if (mSubtypeSwitcher.isKeyboardMode()) {
+ switcher.loadKeyboard(mode, attribute.imeOptions,
+ mVoiceConnector.isVoiceButtonEnabled(),
+ mVoiceConnector.isVoiceButtonOnPrimary());
+ switcher.updateShiftState();
+ }
+
+ setCandidatesViewShownInternal(isCandidateStripVisible(),
+ false /* needsInputViewShown */ );
+ // Delay updating suggestions because keyboard input view may not be shown at this point.
+ mHandler.postUpdateSuggestions();
+
+ updateCorrectionMode();
+
+ inputView.setPreviewEnabled(mPopupOn);
+ inputView.setProximityCorrectionEnabled(true);
+ // If we just entered a text field, maybe it has some old text that requires correction
+ checkReCorrectionOnStart();
+ inputView.setForeground(true);
+
+ mVoiceConnector.onStartInputView(inputView.getWindowToken());
+
+ if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
+ }
+
+ private int initializeInputAttributesAndGetMode(int inputType) {
+ final int variation = inputType & InputType.TYPE_MASK_VARIATION;
+ mAutoSpace = false;
mInputTypeNoAutoCorrect = false;
mIsSettingsSuggestionStripOn = false;
mApplicationSpecifiedCompletionOn = false;
mApplicationSpecifiedCompletions = null;
- mEnteredText = null;
final int mode;
- switch (attribute.inputType & InputType.TYPE_MASK_CLASS) {
+ switch (inputType & InputType.TYPE_MASK_CLASS) {
case InputType.TYPE_CLASS_NUMBER:
case InputType.TYPE_CLASS_DATETIME:
mode = KeyboardId.MODE_NUMBER;
@@ -525,7 +605,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mode = KeyboardId.MODE_WEB;
// If it's a browser edit field and auto correct is not ON explicitly, then
// disable auto correction, but keep suggestions on.
- if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) {
+ if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) {
mInputTypeNoAutoCorrect = true;
}
} else {
@@ -533,16 +613,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
// If NO_SUGGESTIONS is set, don't do prediction.
- if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) {
+ if ((inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) {
mIsSettingsSuggestionStripOn = false;
mInputTypeNoAutoCorrect = true;
}
// If it's not multiline and the autoCorrect flag is not set, then don't correct
- if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 &&
- (attribute.inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) {
+ if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 &&
+ (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) {
mInputTypeNoAutoCorrect = true;
}
- if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
+ if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
mIsSettingsSuggestionStripOn = false;
mApplicationSpecifiedCompletionOn = isFullscreenMode();
}
@@ -551,40 +631,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mode = KeyboardId.MODE_TEXT;
break;
}
- inputView.closing();
- mComposing.setLength(0);
- mHasValidSuggestions = false;
- mDeleteCount = 0;
- mJustAddedAutoSpace = false;
-
- loadSettings(attribute);
- if (mSubtypeSwitcher.isKeyboardMode()) {
- switcher.loadKeyboard(mode, attribute.imeOptions,
- mVoiceConnector.isVoiceButtonEnabled(),
- mVoiceConnector.isVoiceButtonOnPrimary());
- switcher.updateShiftState();
- }
-
- setCandidatesViewShownInternal(isCandidateStripVisible(),
- false /* needsInputViewShown */ );
- // Delay updating suggestions because keyboard input view may not be shown at this point.
- mHandler.postUpdateSuggestions();
-
- // If the dictionary is not big enough, don't auto correct
- mHasDictionary = mSuggest.hasMainDictionary();
-
- updateCorrectionMode();
-
- inputView.setPreviewEnabled(mPopupOn);
- inputView.setProximityCorrectionEnabled(true);
- mIsSettingsSuggestionStripOn &= (mCorrectionMode > 0 || isShowingSuggestionsStrip());
- // If we just entered a text field, maybe it has some old text that requires correction
- checkReCorrectionOnStart();
- inputView.setForeground(true);
-
- mVoiceConnector.onStartInputView(mKeyboardSwitcher.getInputView().getWindowToken());
-
- if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
+ return mode;
}
private void checkReCorrectionOnStart() {
@@ -1106,14 +1153,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void handleBackspace() {
if (mVoiceConnector.logAndRevertVoiceInput()) return;
- boolean deleteChar = false;
- InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
+ final InputConnection ic = getCurrentInputConnection();
+ if (ic == null) return;
ic.beginBatchEdit();
mVoiceConnector.handleBackspace();
+ boolean deleteChar = false;
if (mHasValidSuggestions) {
final int length = mComposing.length();
if (length > 0) {
@@ -1131,12 +1178,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
deleteChar = true;
}
mHandler.postUpdateShiftKeyState();
+
TextEntryState.backspace();
if (TextEntryState.getState() == TextEntryState.State.UNDO_COMMIT) {
revertLastWord(deleteChar);
ic.endBatchEdit();
return;
- } else if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) {
+ }
+
+ if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) {
ic.deleteSurroundingText(mEnteredText.length(), 0);
} else if (deleteChar) {
if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) {
@@ -1355,7 +1405,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
private boolean isSuggestionsRequested() {
- return mIsSettingsSuggestionStripOn;
+ return mIsSettingsSuggestionStripOn
+ && (mCorrectionMode > 0 || isShowingSuggestionsStrip());
}
private boolean isShowingPunctuationList() {
@@ -1491,7 +1542,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) {
setSuggestions(suggestedWords);
if (suggestedWords.size() > 0) {
- if (suggestedWords.hasAutoCorrectionWord()) {
+ if (Utils.shouldBlockedBySafetyNetForAutoCorrection(suggestedWords)) {
+ mBestWord = typedWord;
+ } else if (suggestedWords.hasAutoCorrectionWord()) {
mBestWord = suggestedWords.getWord(1);
} else {
mBestWord = typedWord;
@@ -1773,18 +1826,31 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final int length = mComposing.length();
if (!mHasValidSuggestions && length > 0) {
final InputConnection ic = getCurrentInputConnection();
- mHasValidSuggestions = true;
mJustReverted = true;
+ final CharSequence punctuation = ic.getTextBeforeCursor(1, 0);
if (deleteChar) ic.deleteSurroundingText(1, 0);
int toDelete = mCommittedLength;
- CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0);
- if (toTheLeft != null && toTheLeft.length() > 0
- && isWordSeparator(toTheLeft.charAt(0))) {
+ final CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0);
+ if (!TextUtils.isEmpty(toTheLeft) && isWordSeparator(toTheLeft.charAt(0))) {
toDelete--;
}
ic.deleteSurroundingText(toDelete, 0);
- ic.setComposingText(mComposing, 1);
- TextEntryState.backspace();
+ // Re-insert punctuation only when the deleted character was word separator and the
+ // composing text wasn't equal to the auto-corrected text.
+ if (deleteChar
+ && !TextUtils.isEmpty(punctuation) && isWordSeparator(punctuation.charAt(0))
+ && !TextUtils.equals(mComposing, toTheLeft)) {
+ ic.commitText(mComposing, 1);
+ TextEntryState.acceptedTyped(mComposing);
+ ic.commitText(punctuation, 1);
+ TextEntryState.typedCharacter(punctuation.charAt(0), true);
+ // Clear composing text
+ mComposing.setLength(0);
+ } else {
+ mHasValidSuggestions = true;
+ ic.setComposingText(mComposing, 1);
+ TextEntryState.backspace();
+ }
mHandler.postUpdateSuggestions();
} else {
sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
@@ -1814,21 +1880,22 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return mWord.isFirstCharCapitalized();
}
- // Notify that Language has been changed and toggleLanguage will update KeyboaredID according
- // to new Language.
- public void onKeyboardLanguageChanged() {
+ // Notify that language or mode have been changed and toggleLanguage will update KeyboaredID
+ // according to new language or mode.
+ public void onRefreshKeyboard() {
toggleLanguage(true, true);
}
// "reset" and "next" are used only for USE_SPACEBAR_LANGUAGE_SWITCHER.
private void toggleLanguage(boolean reset, boolean next) {
- if (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER) {
+ if (mSubtypeSwitcher.useSpacebarLanguageSwitcher()) {
mSubtypeSwitcher.toggleLanguage(reset, next);
}
// Reload keyboard because the current language has been changed.
KeyboardSwitcher switcher = mKeyboardSwitcher;
- final int mode = switcher.getKeyboardMode();
final EditorInfo attribute = getCurrentInputEditorInfo();
+ final int mode = initializeInputAttributesAndGetMode((attribute != null)
+ ? attribute.inputType : 0);
final int imeOptions = (attribute != null) ? attribute.imeOptions : 0;
switcher.loadKeyboard(mode, imeOptions, mVoiceConnector.isVoiceButtonEnabled(),
mVoiceConnector.isVoiceButtonOnPrimary());
@@ -2016,7 +2083,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mPopupOn = prefs.getBoolean(Settings.PREF_POPUP_ON,
mResources.getBoolean(R.bool.config_default_popup_preview));
mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true);
- mQuickFixes = prefs.getBoolean(Settings.PREF_QUICK_FIXES, true);
+ mQuickFixes = isQuickFixesEnabled(prefs);
mAutoCorrectEnabled = isAutoCorrectEnabled(prefs);
mBigramSuggestionEnabled = mAutoCorrectEnabled && isBigramSuggestionEnabled(prefs);
@@ -2065,6 +2132,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mSuggest.setAutoCorrectionThreshold(autoCorrectionThreshold);
}
+ private boolean isQuickFixesEnabled(SharedPreferences sp) {
+ final boolean showQuickFixesOption = mResources.getBoolean(
+ R.bool.config_enable_quick_fixes_option);
+ if (!showQuickFixesOption) {
+ return isAutoCorrectEnabled(sp);
+ }
+ return sp.getBoolean(Settings.PREF_QUICK_FIXES, mResources.getBoolean(
+ R.bool.config_default_quick_fixes));
+ }
+
private boolean isAutoCorrectEnabled(SharedPreferences sp) {
final String currentAutoCorrectionSetting = sp.getString(
Settings.PREF_AUTO_CORRECTION_THRESHOLD,
@@ -2075,8 +2152,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
private boolean isBigramSuggestionEnabled(SharedPreferences sp) {
- // TODO: Define default value instead of 'true'.
- return sp.getBoolean(Settings.PREF_BIGRAM_SUGGESTIONS, true);
+ final boolean showBigramSuggestionsOption = mResources.getBoolean(
+ R.bool.config_enable_bigram_suggestions_option);
+ if (!showBigramSuggestionsOption) {
+ return isAutoCorrectEnabled(sp);
+ }
+ return sp.getBoolean(Settings.PREF_BIGRAM_SUGGESTIONS, mResources.getBoolean(
+ R.bool.config_default_bigram_suggestions));
}
private void initSuggestPuncList() {
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index d3fb23baf..c78e6dd07 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
@@ -48,6 +48,7 @@ public class Settings extends PreferenceActivity
DialogInterface.OnDismissListener, OnPreferenceClickListener {
private static final String TAG = "Settings";
+ public static final String PREF_GENERAL_SETTINGS_KEY = "general_settings";
public static final String PREF_VIBRATE_ON = "vibrate_on";
public static final String PREF_SOUND_ON = "sound_on";
public static final String PREF_POPUP_ON = "popup_on";
@@ -65,6 +66,8 @@ public class Settings extends PreferenceActivity
public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold";
public static final String PREF_BIGRAM_SUGGESTIONS = "bigram_suggestion";
+ public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
+
// Dialog ids
private static final int VOICE_INPUT_CONFIRM_DIALOG = 0;
@@ -111,30 +114,64 @@ public class Settings extends PreferenceActivity
mBigramSuggestion = (CheckBoxPreference) findPreference(PREF_BIGRAM_SUGGESTIONS);
ensureConsistencyOfAutoCorrectionSettings();
+ final PreferenceGroup generalSettings =
+ (PreferenceGroup) findPreference(PREF_GENERAL_SETTINGS_KEY);
+ final PreferenceGroup textCorrectionGroup =
+ (PreferenceGroup) findPreference(PREF_PREDICTION_SETTINGS_KEY);
+
final boolean showSettingsKeyOption = getResources().getBoolean(
R.bool.config_enable_show_settings_key_option);
if (!showSettingsKeyOption) {
- getPreferenceScreen().removePreference(mSettingsKeyPreference);
+ generalSettings.removePreference(mSettingsKeyPreference);
}
final boolean showVoiceKeyOption = getResources().getBoolean(
R.bool.config_enable_show_voice_key_option);
if (!showVoiceKeyOption) {
- getPreferenceScreen().removePreference(mVoicePreference);
+ generalSettings.removePreference(mVoicePreference);
}
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
if (vibrator == null
// @@@ || !vibrator.hasVibrator()
) {
- getPreferenceScreen().removePreference(
- getPreferenceScreen().findPreference(PREF_VIBRATE_ON));
+ generalSettings.removePreference(findPreference(PREF_VIBRATE_ON));
}
final boolean showSubtypeSettings = getResources().getBoolean(
R.bool.config_enable_show_subtype_settings);
if (!showSubtypeSettings) {
- getPreferenceScreen().removePreference(findPreference(PREF_SUBTYPES));
+ generalSettings.removePreference(findPreference(PREF_SUBTYPES));
+ }
+
+ final boolean showPopupOption = getResources().getBoolean(
+ R.bool.config_enable_show_popup_on_keypress_option);
+ if (!showPopupOption) {
+ generalSettings.removePreference(findPreference(PREF_POPUP_ON));
+ }
+
+ final boolean showRecorrectionOption = getResources().getBoolean(
+ R.bool.config_enable_show_recorrection_option);
+ if (!showRecorrectionOption) {
+ generalSettings.removePreference(findPreference(PREF_RECORRECTION_ENABLED));
+ }
+
+ final boolean showQuickFixesOption = getResources().getBoolean(
+ R.bool.config_enable_quick_fixes_option);
+ if (!showQuickFixesOption) {
+ textCorrectionGroup.removePreference(findPreference(PREF_QUICK_FIXES));
+ }
+
+ final boolean showBigramSuggestionsOption = getResources().getBoolean(
+ R.bool.config_enable_bigram_suggestions_option);
+ if (!showBigramSuggestionsOption) {
+ textCorrectionGroup.removePreference(findPreference(PREF_BIGRAM_SUGGESTIONS));
+ }
+
+ final boolean showUsabilityModeStudyOption = getResources().getBoolean(
+ R.bool.config_enable_usability_study_mode_option);
+ if (!showUsabilityModeStudyOption) {
+ getPreferenceScreen().removePreference(findPreference(PREF_USABILITY_STUDY_MODE));
}
}
@@ -184,7 +221,7 @@ public class Settings extends PreferenceActivity
if (pref == mInputLanguageSelection) {
final String action;
if (android.os.Build.VERSION.SDK_INT
- >= /* android.os.Build.VERSION_CODES.HONEYCOMB */ 10) {
+ >= /* android.os.Build.VERSION_CODES.HONEYCOMB */ 11) {
action = "android.settings.INPUT_METHOD_AND_SUBTYPE_ENABLER";
} else {
action = "com.android.inputmethod.latin.INPUT_LANGUAGE_SELECTION";
diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
new file mode 100644
index 000000000..917521c40
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+import java.util.Locale;
+
+public class SubtypeLocale {
+ private static String[] sExceptionKeys;
+ private static String[] sExceptionValues;
+
+ private SubtypeLocale() {
+ // Intentional empty constructor for utility class.
+ }
+
+ public static void init(Context context) {
+ final Resources res = context.getResources();
+ sExceptionKeys = res.getStringArray(R.array.subtype_locale_exception_keys);
+ sExceptionValues = res.getStringArray(R.array.subtype_locale_exception_values);
+ }
+
+ public static String getFullDisplayName(Locale locale) {
+ String localeCode = locale.toString();
+ for (int index = 0; index < sExceptionKeys.length; index++) {
+ if (sExceptionKeys[index].equals(localeCode))
+ return sExceptionValues[index];
+ }
+ return locale.getDisplayName(locale);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index cb676fa00..6666c8e15 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -41,11 +41,6 @@ import java.util.Locale;
import java.util.Map;
public class SubtypeSwitcher {
- // TODO: This should be configurable by resource
- // This flag indicates if we support language switching by swipe on space bar.
- // We may or may not draw the current language on space bar regardless of this flag.
- // @@@
- public static final boolean USE_SPACEBAR_LANGUAGE_SWITCHER = true;
private static final boolean DBG = false;
private static final String TAG = "SubtypeSwitcher";
@@ -64,6 +59,8 @@ public class SubtypeSwitcher {
new ArrayList();
private final ArrayList mEnabledLanguagesOfCurrentInputMethod = new ArrayList();
+ private boolean mConfigUseSpacebarLanguageSwitcher;
+
/*-----------------------------------------------------------*/
// Variants which should be changed only by reload functions.
private boolean mNeedsToDisplayLanguage;
@@ -85,11 +82,9 @@ public class SubtypeSwitcher {
public static void init(LatinIME service, SharedPreferences prefs) {
sInstance.mPrefs = prefs;
sInstance.resetParams(service);
- if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
- sInstance.initLanguageSwitcher(service);
- }
-
sInstance.updateAllParameters();
+
+ SubtypeLocale.init(service);
}
private SubtypeSwitcher() {
@@ -110,6 +105,10 @@ public class SubtypeSwitcher {
mAllEnabledSubtypesOfCurrentInputMethod = null;
// TODO: Voice input should be created here
mVoiceInput = null;
+ mConfigUseSpacebarLanguageSwitcher = mResources.getBoolean(
+ R.bool.config_use_spacebar_language_switcher);
+ if (mConfigUseSpacebarLanguageSwitcher)
+ initLanguageSwitcher(service);
}
// Update all parameters stored in SubtypeSwitcher.
@@ -123,8 +122,8 @@ public class SubtypeSwitcher {
// Update parameters which are changed outside LatinIME. This parameters affect UI so they
// should be updated every time onStartInputview.
public void updateParametersOnStartInputView() {
- if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
- updateForSpaceBarLanguageSwitch();
+ if (mConfigUseSpacebarLanguageSwitcher) {
+ updateForSpacebarLanguageSwitch();
} else {
updateEnabledSubtypes();
}
@@ -135,7 +134,7 @@ public class SubtypeSwitcher {
private void updateEnabledSubtypes() {
boolean foundCurrentSubtypeBecameDisabled = true;
// @@@ mAllEnabledSubtypesOfCurrentInputMethod = mImm.getEnabledInputMethodSubtypeList(
- //null, false);
+ // null, true);
mEnabledLanguagesOfCurrentInputMethod.clear();
mEnabledKeyboardSubtypesOfCurrentInputMethod.clear();
for (InputMethodSubtype ims: mAllEnabledSubtypesOfCurrentInputMethod) {
@@ -156,6 +155,7 @@ public class SubtypeSwitcher {
&& mIsSystemLanguageSameAsInputLanguage);
if (foundCurrentSubtypeBecameDisabled) {
if (DBG) {
+ Log.w(TAG, "Current subtype: " + mInputLocaleStr + ", " + mMode);
Log.w(TAG, "Last subtype was disabled. Update to the current one.");
}
// @@@ updateSubtype(mImm.getCurrentInputMethodSubtype());
@@ -189,7 +189,7 @@ public class SubtypeSwitcher {
// fallback to the default locale and mode.
Log.w(TAG, "Couldn't get the current subtype.");
newLocale = "en_US";
- newMode =KEYBOARD_MODE;
+ newMode = KEYBOARD_MODE;
} else {
newLocale = newSubtype.getLocale();
newMode = newSubtype.getMode();
@@ -219,8 +219,8 @@ public class SubtypeSwitcher {
mVoiceInput.cancel();
}
}
- if (languageChanged) {
- mService.onKeyboardLanguageChanged();
+ if (modeChanged || languageChanged) {
+ mService.onRefreshKeyboard();
}
} else if (isVoiceMode()) {
// If needsToShowWarningDialog is true, voice input need to show warning before
@@ -312,19 +312,23 @@ public class SubtypeSwitcher {
//////////////////////////////////
public int getEnabledKeyboardLocaleCount() {
- if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+ if (mConfigUseSpacebarLanguageSwitcher) {
return mLanguageSwitcher.getLocaleCount();
} else {
return mEnabledKeyboardSubtypesOfCurrentInputMethod.size();
}
}
+ public boolean useSpacebarLanguageSwitcher() {
+ return mConfigUseSpacebarLanguageSwitcher;
+ }
+
public boolean needsToDisplayLanguage() {
return mNeedsToDisplayLanguage;
}
public Locale getInputLocale() {
- if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+ if (mConfigUseSpacebarLanguageSwitcher) {
return mLanguageSwitcher.getInputLocale();
} else {
return mInputLocale;
@@ -332,7 +336,7 @@ public class SubtypeSwitcher {
}
public String getInputLocaleStr() {
- if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+ if (mConfigUseSpacebarLanguageSwitcher) {
String inputLanguage = null;
inputLanguage = mLanguageSwitcher.getInputLanguage();
// Should return system locale if there is no Language available.
@@ -346,7 +350,7 @@ public class SubtypeSwitcher {
}
public String[] getEnabledLanguages() {
- if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+ if (mConfigUseSpacebarLanguageSwitcher) {
return mLanguageSwitcher.getEnabledLanguages();
} else {
return mEnabledLanguagesOfCurrentInputMethod.toArray(
@@ -355,7 +359,7 @@ public class SubtypeSwitcher {
}
public Locale getSystemLocale() {
- if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+ if (mConfigUseSpacebarLanguageSwitcher) {
return mLanguageSwitcher.getSystemLocale();
} else {
return mSystemLocale;
@@ -363,7 +367,7 @@ public class SubtypeSwitcher {
}
public boolean isSystemLanguageSameAsInputLanguage() {
- if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+ if (mConfigUseSpacebarLanguageSwitcher) {
return getSystemLocale().getLanguage().equalsIgnoreCase(
getInputLocaleStr().substring(0, 2));
} else {
@@ -375,7 +379,7 @@ public class SubtypeSwitcher {
final Locale systemLocale = conf.locale;
// If system configuration was changed, update all parameters.
if (!TextUtils.equals(systemLocale.toString(), mSystemLocale.toString())) {
- if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+ if (mConfigUseSpacebarLanguageSwitcher) {
// If the system locale changes and is different from the saved
// locale (mSystemLocale), then reload the input locale list from the
// latin ime settings (shared prefs) and reset the input locale
@@ -389,7 +393,7 @@ public class SubtypeSwitcher {
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+ if (mConfigUseSpacebarLanguageSwitcher) {
if (Settings.PREF_SELECTED_LANGUAGES.equals(key)) {
mLanguageSwitcher.loadLocales(sharedPreferences);
}
@@ -439,18 +443,18 @@ public class SubtypeSwitcher {
private void triggerVoiceIME() {
if (!mService.isInputViewShown()) return;
VoiceIMEConnector.getInstance().startListening(false,
- KeyboardSwitcher.getInstance().getInputView().getWindowToken(), false);
+ KeyboardSwitcher.getInstance().getInputView().getWindowToken());
}
//////////////////////////////////////
- // SpaceBar Language Switch support //
+ // Spacebar Language Switch support //
//////////////////////////////////////
private LanguageSwitcher mLanguageSwitcher;
public static String getFullDisplayName(Locale locale, boolean returnsNameInThisLocale) {
if (returnsNameInThisLocale) {
- return toTitleCase(locale.getDisplayName(locale));
+ return toTitleCase(SubtypeLocale.getFullDisplayName(locale));
} else {
return toTitleCase(locale.getDisplayName());
}
@@ -471,7 +475,7 @@ public class SubtypeSwitcher {
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
}
- private void updateForSpaceBarLanguageSwitch() {
+ private void updateForSpacebarLanguageSwitch() {
// We need to update mNeedsToDisplayLanguage in onStartInputView because
// getEnabledKeyboardLocaleCount could have been changed.
mNeedsToDisplayLanguage = !(getEnabledKeyboardLocaleCount() <= 1
@@ -484,7 +488,7 @@ public class SubtypeSwitcher {
}
public String getNextInputLanguageName() {
- if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+ if (mConfigUseSpacebarLanguageSwitcher) {
return getDisplayLanguage(mLanguageSwitcher.getNextInputLocale());
} else {
return "";
@@ -492,7 +496,7 @@ public class SubtypeSwitcher {
}
public String getPreviousInputLanguageName() {
- if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+ if (mConfigUseSpacebarLanguageSwitcher) {
return getDisplayLanguage(mLanguageSwitcher.getPrevInputLocale());
} else {
return "";
@@ -529,13 +533,13 @@ public class SubtypeSwitcher {
}
public void loadSettings() {
- if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+ if (mConfigUseSpacebarLanguageSwitcher) {
mLanguageSwitcher.loadLocales(mPrefs);
}
}
public void toggleLanguage(boolean reset, boolean next) {
- if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+ if (mConfigUseSpacebarLanguageSwitcher) {
if (reset) {
mLanguageSwitcher.reset();
} else {
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 9ea9c2f3e..24c73e8ea 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -31,7 +31,7 @@ import java.util.Arrays;
*/
public class Suggest implements Dictionary.WordCallback {
- public static final String TAG = "Suggest";
+ public static final String TAG = Suggest.class.getSimpleName();
public static final int APPROX_MAX_WORD_LENGTH = 32;
@@ -64,6 +64,8 @@ public class Suggest implements Dictionary.WordCallback {
static final int LARGE_DICTIONARY_THRESHOLD = 200 * 1000;
+ private static boolean DBG = LatinImeLogger.sDBG;
+
private BinaryDictionary mMainDict;
private Dictionary mUserDictionary;
@@ -93,7 +95,7 @@ public class Suggest implements Dictionary.WordCallback {
private ArrayList mSuggestions = new ArrayList();
ArrayList mBigramSuggestions = new ArrayList();
private ArrayList mStringPool = new ArrayList();
- private boolean mHaveCorrection;
+ private boolean mHaveAutoCorrection;
private String mLowerOriginalWord;
// TODO: Remove these member variables by passing more context to addWord() callback method
@@ -103,7 +105,7 @@ public class Suggest implements Dictionary.WordCallback {
private int mCorrectionMode = CORRECTION_BASIC;
public Suggest(Context context, int dictionaryResId) {
- mMainDict = new BinaryDictionary(context, dictionaryResId, DIC_MAIN);
+ mMainDict = BinaryDictionary.initDictionary(context, dictionaryResId, DIC_MAIN);
initPool();
}
@@ -127,7 +129,7 @@ public class Suggest implements Dictionary.WordCallback {
}
public boolean hasMainDictionary() {
- return mMainDict.getSize() > LARGE_DICTIONARY_THRESHOLD;
+ return mMainDict != null && mMainDict.getSize() > LARGE_DICTIONARY_THRESHOLD;
}
public int getApproxMaxWordLength() {
@@ -198,7 +200,7 @@ public class Suggest implements Dictionary.WordCallback {
public SuggestedWords.Builder getSuggestedWordBuilder(View view, WordComposer wordComposer,
CharSequence prevWordForBigram) {
LatinImeLogger.onStartSuggestion(prevWordForBigram);
- mHaveCorrection = false;
+ mHaveAutoCorrection = false;
mIsFirstCharCapitalized = wordComposer.isFirstCharCapitalized();
mIsAllUpperCase = wordComposer.isAllUpperCase();
collectGarbage(mSuggestions, mPrefMaxSuggestions);
@@ -273,10 +275,13 @@ public class Suggest implements Dictionary.WordCallback {
if (mSuggestions.size() > 0 && isValidWord(typedWord)
&& (mCorrectionMode == CORRECTION_FULL
|| mCorrectionMode == CORRECTION_FULL_BIGRAM)) {
- mHaveCorrection = true;
+ if (DBG) {
+ Log.d(TAG, "Auto corrected by CORRECTION_FULL.");
+ }
+ mHaveAutoCorrection = true;
}
}
- mMainDict.getWords(wordComposer, this, mNextLettersFrequencies);
+ if (mMainDict != null) mMainDict.getWords(wordComposer, this, mNextLettersFrequencies);
if ((mCorrectionMode == CORRECTION_FULL || mCorrectionMode == CORRECTION_FULL_BIGRAM)
&& mSuggestions.size() > 0 && mPriorities.length > 0) {
// TODO: when the normalized score of the first suggestion is nearly equals to
@@ -289,7 +294,10 @@ public class Suggest implements Dictionary.WordCallback {
+ "(" + mAutoCorrectionThreshold + ")");
}
if (normalizedScore >= mAutoCorrectionThreshold) {
- mHaveCorrection = true;
+ if (DBG) {
+ Log.d(TAG, "Auto corrected by S-threthhold.");
+ }
+ mHaveAutoCorrection = true;
}
}
}
@@ -331,7 +339,10 @@ public class Suggest implements Dictionary.WordCallback {
canAdd &= !TextUtils.equals(autoText, mSuggestions.get(i + 1));
}
if (canAdd) {
- mHaveCorrection = true;
+ if (DBG) {
+ Log.d(TAG, "Auto corrected by AUTOTEXT.");
+ }
+ mHaveAutoCorrection = true;
mSuggestions.add(i + 1, autoText);
i++;
}
@@ -374,7 +385,7 @@ public class Suggest implements Dictionary.WordCallback {
}
public boolean hasMinimalCorrection() {
- return mHaveCorrection;
+ return mHaveAutoCorrection;
}
private boolean compareCaseInsensitive(final String mLowerOriginalWord,
@@ -496,7 +507,7 @@ public class Suggest implements Dictionary.WordCallback {
}
public boolean isValidWord(final CharSequence word) {
- if (word == null || word.length() == 0) {
+ if (word == null || word.length() == 0 || mMainDict == null) {
return false;
}
return mMainDict.isValidWord(word)
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 5398b77b2..0fbbcdd91 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -124,7 +124,7 @@ public class SuggestedWords {
addWord(previousSuggestions.getWord(pos));
mIsCompletions = false;
mTypedWordValid = false;
- mHasMinimalSuggestion = (previousSize > 1);
+ mHasMinimalSuggestion = false;
return this;
}
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 56ad6c7aa..160948507 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -36,6 +36,8 @@ import java.text.SimpleDateFormat;
import java.util.Date;
public class Utils {
+ private static final String TAG = Utils.class.getSimpleName();
+ private static boolean DBG = LatinImeLogger.sDBG;
/**
* Cancel an {@link AsyncTask}.
@@ -96,6 +98,29 @@ public class Utils {
// || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1;
}
+
+ public static boolean shouldBlockedBySafetyNetForAutoCorrection(SuggestedWords suggestions) {
+ // Safety net for auto correction.
+ // Actually if we hit this safety net, it's actually a bug.
+ if (suggestions.size() <= 1 || suggestions.mTypedWordValid) return false;
+ CharSequence typedWord = suggestions.getWord(0);
+ CharSequence candidateWord = suggestions.getWord(1);
+ final int typedWordLength = typedWord.length();
+ final int maxEditDistanceOfNativeDictionary = typedWordLength < 5 ? 2 : typedWordLength / 2;
+ final int distance = Utils.editDistance(typedWord, candidateWord);
+ if (DBG) {
+ Log.d(TAG, "Autocorrected edit distance = " + distance
+ + ", " + maxEditDistanceOfNativeDictionary);
+ }
+ if (distance > maxEditDistanceOfNativeDictionary) {
+ Log.w(TAG, "(Error) The edit distance of this correction exceeds limit. "
+ + "Turning off auto-correction.");
+ return true;
+ } else {
+ return false;
+ }
+ }
+
/* package */ static class RingCharBuffer {
private static RingCharBuffer sRingCharBuffer = new RingCharBuffer();
private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC';
diff --git a/java/src/com/android/inputmethod/voice/RecognitionView.java b/java/src/com/android/inputmethod/voice/RecognitionView.java
index 12d0de852..98db9365f 100644
--- a/java/src/com/android/inputmethod/voice/RecognitionView.java
+++ b/java/src/com/android/inputmethod/voice/RecognitionView.java
@@ -16,9 +16,6 @@
package com.android.inputmethod.voice;
-import com.android.inputmethod.latin.R;
-
-import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -29,20 +26,21 @@ import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
-import android.util.TypedValue;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
-import android.view.ViewGroup.MarginLayoutParams;
+import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
+import com.android.inputmethod.latin.R;
+
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
-import java.util.ArrayList;
import java.util.List;
/**
@@ -58,81 +56,55 @@ public class RecognitionView {
private View mView;
private Context mContext;
- private ImageView mImage;
private TextView mText;
- private View mButton;
- private TextView mButtonText;
+ private ImageView mImage;
private View mProgress;
+ private SoundIndicator mSoundIndicator;
+ private Button mButton;
private Drawable mInitializing;
private Drawable mError;
- private List mSpeakNow;
- private float mVolume = 0.0f;
- private int mLevel = 0;
+ private static final int INIT = 0;
+ private static final int LISTENING = 1;
+ private static final int WORKING = 2;
+ private static final int READY = 3;
+
+ private int mState = INIT;
- private enum State {LISTENING, WORKING, READY}
- private State mState = State.READY;
+ private final View mPopupLayout;
- private float mMinMicrophoneLevel;
- private float mMaxMicrophoneLevel;
-
- /** Updates the microphone icon to show user their volume.*/
- private Runnable mUpdateVolumeRunnable = new Runnable() {
- @Override
- public void run() {
- if (mState != State.LISTENING) {
- return;
- }
-
- final float min = mMinMicrophoneLevel;
- final float max = mMaxMicrophoneLevel;
- final int maxLevel = mSpeakNow.size() - 1;
-
- int index = (int) ((mVolume - min) / (max - min) * maxLevel);
- final int level = Math.min(Math.max(0, index), maxLevel);
-
- if (level != mLevel) {
- mImage.setImageDrawable(mSpeakNow.get(level));
- mLevel = level;
- }
- mUiHandler.postDelayed(mUpdateVolumeRunnable, 50);
- }
- };
+ private final Drawable mListeningBorder;
+ private final Drawable mWorkingBorder;
+ private final Drawable mErrorBorder;
public RecognitionView(Context context, OnClickListener clickListener) {
mUiHandler = new Handler();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
+ Context.LAYOUT_INFLATER_SERVICE);
+
mView = inflater.inflate(R.layout.recognition_status, null);
- ContentResolver cr = context.getContentResolver();
- mMinMicrophoneLevel = SettingsUtil.getSettingsFloat(
- cr, SettingsUtil.LATIN_IME_MIN_MICROPHONE_LEVEL, 15.f);
- mMaxMicrophoneLevel = SettingsUtil.getSettingsFloat(
- cr, SettingsUtil.LATIN_IME_MAX_MICROPHONE_LEVEL, 30.f);
+
+ mPopupLayout= mView.findViewById(R.id.popup_layout);
// Pre-load volume level images
Resources r = context.getResources();
- mSpeakNow = new ArrayList();
- mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level0));
- mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level1));
- mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level2));
- mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level3));
- mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level4));
- mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level5));
- mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level6));
+ mListeningBorder = r.getDrawable(R.drawable.vs_dialog_red);
+ mWorkingBorder = r.getDrawable(R.drawable.vs_dialog_blue);
+ mErrorBorder = r.getDrawable(R.drawable.vs_dialog_yellow);
mInitializing = r.getDrawable(R.drawable.mic_slash);
mError = r.getDrawable(R.drawable.caution);
mImage = (ImageView) mView.findViewById(R.id.image);
- mButton = mView.findViewById(R.id.button);
+ mProgress = mView.findViewById(R.id.progress);
+ mSoundIndicator = (SoundIndicator) mView.findViewById(R.id.sound_indicator);
+
+ mButton = (Button) mView.findViewById(R.id.button);
mButton.setOnClickListener(clickListener);
mText = (TextView) mView.findViewById(R.id.text);
- mButtonText = (TextView) mView.findViewById(R.id.button_text);
- mProgress = mView.findViewById(R.id.progress);
mContext = context;
}
@@ -146,9 +118,9 @@ public class RecognitionView {
@Override
public void run() {
// Restart the spinner
- if (mState == State.WORKING) {
- ((ProgressBar)mProgress).setIndeterminate(false);
- ((ProgressBar)mProgress).setIndeterminate(true);
+ if (mState == WORKING) {
+ ((ProgressBar) mProgress).setIndeterminate(false);
+ ((ProgressBar) mProgress).setIndeterminate(true);
}
}
});
@@ -158,48 +130,48 @@ public class RecognitionView {
mUiHandler.post(new Runnable() {
@Override
public void run() {
- prepareDialog(false, mContext.getText(R.string.voice_initializing), mInitializing,
- mContext.getText(R.string.cancel));
+ mState = INIT;
+ prepareDialog(mContext.getText(R.string.voice_initializing), mInitializing,
+ mContext.getText(R.string.cancel));
}
});
}
public void showListening() {
+ Log.d(TAG, "#showListening");
mUiHandler.post(new Runnable() {
@Override
public void run() {
- mState = State.LISTENING;
- prepareDialog(false, mContext.getText(R.string.voice_listening), mSpeakNow.get(0),
+ mState = LISTENING;
+ prepareDialog(mContext.getText(R.string.voice_listening), null,
mContext.getText(R.string.cancel));
}
});
- mUiHandler.postDelayed(mUpdateVolumeRunnable, 50);
}
- public void updateVoiceMeter(final float rmsdB) {
- mVolume = rmsdB;
+ public void updateVoiceMeter(float rmsdB) {
+ mSoundIndicator.setRmsdB(rmsdB);
}
public void showError(final String message) {
mUiHandler.post(new Runnable() {
@Override
public void run() {
- mState = State.READY;
- prepareDialog(false, message, mError, mContext.getText(R.string.ok));
+ mState = READY;
+ prepareDialog(message, mError, mContext.getText(R.string.ok));
}
- });
+ });
}
public void showWorking(
final ByteArrayOutputStream waveBuffer,
final int speechStartPosition,
final int speechEndPosition) {
-
mUiHandler.post(new Runnable() {
@Override
public void run() {
- mState = State.WORKING;
- prepareDialog(true, mContext.getText(R.string.voice_working), null, mContext
+ mState = WORKING;
+ prepareDialog(mContext.getText(R.string.voice_working), null, mContext
.getText(R.string.cancel));
final ShortBuffer buf = ByteBuffer.wrap(waveBuffer.toByteArray()).order(
ByteOrder.nativeOrder()).asShortBuffer();
@@ -207,21 +179,71 @@ public class RecognitionView {
waveBuffer.reset();
showWave(buf, speechStartPosition / 2, speechEndPosition / 2);
}
- });
+ });
}
- private void prepareDialog(boolean spinVisible, CharSequence text, Drawable image,
+ private void prepareDialog(CharSequence text, Drawable image,
CharSequence btnTxt) {
- if (spinVisible) {
- mProgress.setVisibility(View.VISIBLE);
- mImage.setVisibility(View.GONE);
- } else {
- mProgress.setVisibility(View.GONE);
- mImage.setImageDrawable(image);
- mImage.setVisibility(View.VISIBLE);
+ switch (mState) {
+ case INIT:
+ mText.setVisibility(View.GONE);
+
+ mProgress.setVisibility(View.GONE);
+
+ mImage.setVisibility(View.VISIBLE);
+ mImage.setImageResource(R.drawable.mic_slash);
+
+ mSoundIndicator.setVisibility(View.GONE);
+ mSoundIndicator.stop();
+
+ mPopupLayout.setBackgroundDrawable(mListeningBorder);
+ break;
+ case LISTENING:
+ mText.setVisibility(View.VISIBLE);
+ mText.setText(text);
+
+ mProgress.setVisibility(View.GONE);
+
+ mImage.setVisibility(View.GONE);
+
+ mSoundIndicator.setVisibility(View.VISIBLE);
+ mSoundIndicator.start();
+
+ mPopupLayout.setBackgroundDrawable(mListeningBorder);
+ break;
+ case WORKING:
+
+ mText.setVisibility(View.VISIBLE);
+ mText.setText(text);
+
+ mProgress.setVisibility(View.VISIBLE);
+
+ mImage.setVisibility(View.VISIBLE);
+
+ mSoundIndicator.setVisibility(View.GONE);
+ mSoundIndicator.stop();
+
+ mPopupLayout.setBackgroundDrawable(mWorkingBorder);
+ break;
+ case READY:
+ mText.setVisibility(View.VISIBLE);
+ mText.setText(text);
+
+ mProgress.setVisibility(View.GONE);
+
+ mImage.setVisibility(View.VISIBLE);
+ mImage.setImageResource(R.drawable.caution);
+
+ mSoundIndicator.setVisibility(View.GONE);
+ mSoundIndicator.stop();
+
+ mPopupLayout.setBackgroundDrawable(mErrorBorder);
+ break;
+ default:
+ Log.w(TAG, "Unknown state " + mState);
}
- mText.setText(text);
- mButtonText.setText(btnTxt);
+ mPopupLayout.requestLayout();
+ mButton.setText(btnTxt);
}
/**
@@ -248,7 +270,7 @@ public class RecognitionView {
*/
private void showWave(ShortBuffer waveBuffer, int startPosition, int endPosition) {
final int w = ((View) mImage.getParent()).getWidth();
- final int h = mImage.getHeight();
+ final int h = ((View) mImage.getParent()).getHeight();
if (w <= 0 || h <= 0) {
// view is not visible this time. Skip drawing.
return;
@@ -259,7 +281,7 @@ public class RecognitionView {
paint.setColor(0xFFFFFFFF); // 0xAARRGGBB
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
- paint.setAlpha(0x90);
+ paint.setAlpha(80);
final PathEffect effect = new CornerPathEffect(3);
paint.setPathEffect(effect);
@@ -281,7 +303,7 @@ public class RecognitionView {
final int count = (endIndex - startIndex) / numSamplePerWave;
final float deltaX = 1.0f * w / count;
- int yMax = h / 2 - 8;
+ int yMax = h / 2;
Path path = new Path();
c.translate(0, yMax);
float x = 0;
@@ -295,37 +317,20 @@ public class RecognitionView {
path.lineTo(x, y);
}
if (deltaX > 4) {
- paint.setStrokeWidth(3);
+ paint.setStrokeWidth(2);
} else {
- paint.setStrokeWidth(Math.max(1, (int) (deltaX -.05)));
+ paint.setStrokeWidth(Math.max(0, (int) (deltaX -.05)));
}
c.drawPath(path, paint);
mImage.setImageBitmap(b);
- mImage.setVisibility(View.VISIBLE);
- MarginLayoutParams mProgressParams = (MarginLayoutParams)mProgress.getLayoutParams();
- mProgressParams.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,
- -h , mContext.getResources().getDisplayMetrics());
-
- // Tweak the padding manually to fill out the whole view horizontally.
- // TODO: Do this in the xml layout instead.
- ((View) mImage.getParent()).setPadding(4, ((View) mImage.getParent()).getPaddingTop(), 3,
- ((View) mImage.getParent()).getPaddingBottom());
- mProgress.setLayoutParams(mProgressParams);
}
-
public void finish() {
mUiHandler.post(new Runnable() {
@Override
public void run() {
- mState = State.READY;
- exitWorking();
+ mSoundIndicator.stop();
}
- });
- }
-
- private void exitWorking() {
- mProgress.setVisibility(View.GONE);
- mImage.setVisibility(View.VISIBLE);
+ });
}
}
diff --git a/java/src/com/android/inputmethod/voice/SoundIndicator.java b/java/src/com/android/inputmethod/voice/SoundIndicator.java
new file mode 100644
index 000000000..543290b32
--- /dev/null
+++ b/java/src/com/android/inputmethod/voice/SoundIndicator.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * 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.voice;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import com.android.inputmethod.latin.R;
+
+/**
+ * A widget which shows the volume of audio using a microphone icon
+ */
+public class SoundIndicator extends ImageView {
+ @SuppressWarnings("unused")
+ private static final String TAG = "SoundIndicator";
+
+ private static final float UP_SMOOTHING_FACTOR = 0.9f;
+ private static final float DOWN_SMOOTHING_FACTOR = 0.4f;
+
+ private static final float AUDIO_METER_MIN_DB = 7.0f;
+ private static final float AUDIO_METER_DB_RANGE = 20.0f;
+
+ private static final long FRAME_DELAY = 50;
+
+ private Bitmap mDrawingBuffer;
+ private Canvas mBufferCanvas;
+ private Bitmap mEdgeBitmap;
+ private float mLevel = 0.0f;
+ private Drawable mFrontDrawable;
+ private Paint mClearPaint;
+ private Paint mMultPaint;
+ private int mEdgeBitmapOffset;
+
+ private Handler mHandler;
+
+ private Runnable mDrawFrame = new Runnable() {
+ public void run() {
+ invalidate();
+ mHandler.postDelayed(mDrawFrame, FRAME_DELAY);
+ }
+ };
+
+ public SoundIndicator(Context context) {
+ this(context, null);
+ }
+
+ public SoundIndicator(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mFrontDrawable = getDrawable();
+ BitmapDrawable edgeDrawable =
+ (BitmapDrawable) context.getResources().getDrawable(R.drawable.vs_popup_mic_edge);
+ mEdgeBitmap = edgeDrawable.getBitmap();
+ mEdgeBitmapOffset = mEdgeBitmap.getHeight() / 2;
+
+ mDrawingBuffer =
+ Bitmap.createBitmap(mFrontDrawable.getIntrinsicWidth(),
+ mFrontDrawable.getIntrinsicHeight(), Config.ARGB_8888);
+
+ mBufferCanvas = new Canvas(mDrawingBuffer);
+
+ // Initialize Paints.
+ mClearPaint = new Paint();
+ mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+
+ mMultPaint = new Paint();
+ mMultPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
+
+ mHandler = new Handler();
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ //super.onDraw(canvas);
+
+ float w = getWidth();
+ float h = getHeight();
+
+ // Clear the buffer canvas
+ mBufferCanvas.drawRect(0, 0, w, h, mClearPaint);
+
+ // Set its clip so we don't draw the front image all the way to the top
+ Rect clip = new Rect(0,
+ (int) ((1.0 - mLevel) * (h + mEdgeBitmapOffset)) - mEdgeBitmapOffset,
+ (int) w,
+ (int) h);
+
+ mBufferCanvas.save();
+ mBufferCanvas.clipRect(clip);
+
+ // Draw the front image
+ mFrontDrawable.setBounds(new Rect(0, 0, (int) w, (int) h));
+ mFrontDrawable.draw(mBufferCanvas);
+
+ mBufferCanvas.restore();
+
+ // Draw the edge image on top of the buffer image with a multiply mode
+ mBufferCanvas.drawBitmap(mEdgeBitmap, 0, clip.top, mMultPaint);
+
+ // Draw the buffer image (on top of the background image)
+ canvas.drawBitmap(mDrawingBuffer, 0, 0, null);
+ }
+
+ /**
+ * Sets the sound level
+ *
+ * @param rmsdB The level of the sound, in dB.
+ */
+ public void setRmsdB(float rmsdB) {
+ float level = ((rmsdB - AUDIO_METER_MIN_DB) / AUDIO_METER_DB_RANGE);
+
+ level = Math.min(Math.max(0.0f, level), 1.0f);
+
+ // We smooth towards the new level
+ if (level > mLevel) {
+ mLevel = (level - mLevel) * UP_SMOOTHING_FACTOR + mLevel;
+ } else {
+ mLevel = (level - mLevel) * DOWN_SMOOTHING_FACTOR + mLevel;
+ }
+ invalidate();
+ }
+
+ public void start() {
+ mHandler.post(mDrawFrame);
+ }
+
+ public void stop() {
+ mHandler.removeCallbacks(mDrawFrame);
+ }
+}
diff --git a/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java b/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java
index 1ff918315..fe6e318c9 100644
--- a/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java
+++ b/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.voice;
+import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.latin.EditingUtils;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinIME.UIHandler;
@@ -29,6 +30,7 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.res.Configuration;
import android.net.Uri;
import android.os.IBinder;
import android.preference.PreferenceManager;
@@ -77,6 +79,9 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
// dialog is already showing a voice search button.
private static final String IME_OPTION_NO_MICROPHONE = "nm";
+ @SuppressWarnings("unused")
+ private static final String TAG = "VoiceIMEConnector";
+
private boolean mAfterVoiceInput;
private boolean mHasUsedVoiceInput;
private boolean mHasUsedVoiceInputUnsupportedLocale;
@@ -91,7 +96,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
private boolean mVoiceInputHighlighted;
private InputMethodManager mImm;
- private LatinIME mContext;
+ private LatinIME mService;
private AlertDialog mVoiceWarningDialog;
private VoiceInput mVoiceInput;
private final VoiceResults mVoiceResults = new VoiceResults();
@@ -111,21 +116,19 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
return sInstance;
}
- private void initInternal(LatinIME context, SharedPreferences prefs, UIHandler h) {
- mContext = context;
+ private void initInternal(LatinIME service, SharedPreferences prefs, UIHandler h) {
+ mService = service;
mHandler = h;
- mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+ mImm = (InputMethodManager) service.getSystemService(Context.INPUT_METHOD_SERVICE);
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
if (VOICE_INSTALLED) {
- mVoiceInput = new VoiceInput(context, this);
- mHints = new Hints(context, prefs, new Hints.Display() {
+ mVoiceInput = new VoiceInput(service, this);
+ mHints = new Hints(service, prefs, new Hints.Display() {
@Override
public void showHint(int viewResource) {
- LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(viewResource, null);
- mContext.setCandidatesView(view);
- mContext.setCandidatesViewShown(true);
+ View view = LayoutInflater.from(mService).inflate(viewResource, null);
+ mService.setCandidatesView(view);
+ mService.setCandidatesViewShown(true);
mIsShowingHint = true;
}
});
@@ -161,23 +164,22 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
mVoiceInput.flushAllTextModificationCounters();
// send this intent AFTER logging any prior aggregated edits.
mVoiceInput.logTextModifiedByChooseSuggestion(suggestion.toString(), index,
- wordSeparators, mContext.getCurrentInputConnection());
+ wordSeparators, mService.getCurrentInputConnection());
}
}
- private void showVoiceWarningDialog(final boolean swipe, IBinder token,
- final boolean configurationChanging) {
+ private void showVoiceWarningDialog(final boolean swipe, IBinder token) {
if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) {
return;
}
- AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+ AlertDialog.Builder builder = new AlertDialog.Builder(mService);
builder.setCancelable(true);
builder.setIcon(R.drawable.ic_mic_dialog);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
mVoiceInput.logKeyboardWarningDialogOk();
- reallyStartListening(swipe, configurationChanging);
+ reallyStartListening(swipe);
}
});
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@@ -199,13 +201,13 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
final CharSequence message;
if (mLocaleSupportedForVoiceInput) {
message = TextUtils.concat(
- mContext.getText(R.string.voice_warning_may_not_understand), "\n\n",
- mContext.getText(R.string.voice_warning_how_to_turn_off));
+ mService.getText(R.string.voice_warning_may_not_understand), "\n\n",
+ mService.getText(R.string.voice_warning_how_to_turn_off));
} else {
message = TextUtils.concat(
- mContext.getText(R.string.voice_warning_locale_not_supported), "\n\n",
- mContext.getText(R.string.voice_warning_may_not_understand), "\n\n",
- mContext.getText(R.string.voice_warning_how_to_turn_off));
+ mService.getText(R.string.voice_warning_locale_not_supported), "\n\n",
+ mService.getText(R.string.voice_warning_may_not_understand), "\n\n",
+ mService.getText(R.string.voice_warning_how_to_turn_off));
}
builder.setMessage(message);
@@ -296,7 +298,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
}
public void showPunctuationHintIfNecessary() {
- InputConnection ic = mContext.getCurrentInputConnection();
+ InputConnection ic = mService.getCurrentInputConnection();
if (!mImmediatelyAfterVoiceInput && mAfterVoiceInput && ic != null) {
if (mHints.showPunctuationHintIfNecessary(ic)) {
mVoiceInput.logPunctuationHintDisplayed();
@@ -364,17 +366,17 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
}
private void revertVoiceInput() {
- InputConnection ic = mContext.getCurrentInputConnection();
+ InputConnection ic = mService.getCurrentInputConnection();
if (ic != null) ic.commitText("", 1);
- mContext.updateSuggestions();
+ mService.updateSuggestions();
mVoiceInputHighlighted = false;
}
public void commitVoiceInput() {
if (VOICE_INSTALLED && mVoiceInputHighlighted) {
- InputConnection ic = mContext.getCurrentInputConnection();
+ InputConnection ic = mService.getCurrentInputConnection();
if (ic != null) ic.finishComposingText();
- mContext.updateSuggestions();
+ mService.updateSuggestions();
mVoiceInputHighlighted = false;
}
}
@@ -394,7 +396,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
if (mShowingVoiceSuggestions) {
// Retain the replaced word in the alternatives array.
String wordToBeReplaced = EditingUtils.getWordAtCursor(
- mContext.getCurrentInputConnection(), wordSeparators);
+ mService.getCurrentInputConnection(), wordSeparators);
if (!mWordToSuggestions.containsKey(wordToBeReplaced)) {
wordToBeReplaced = wordToBeReplaced.toLowerCase();
}
@@ -438,8 +440,8 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
builder.addWords(suggestions);
}
builder.setTypedWordValid(true).setHasMinimalSuggestion(true);
- mContext.setSuggestions(builder.build());
- mContext.setCandidatesViewShown(true);
+ mService.setSuggestions(builder.build());
+ mService.setCandidatesViewShown(true);
return true;
}
return false;
@@ -486,15 +488,15 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
mAfterVoiceInput = true;
mImmediatelyAfterVoiceInput = true;
- InputConnection ic = mContext.getCurrentInputConnection();
- if (!mContext.isFullscreenMode()) {
+ InputConnection ic = mService.getCurrentInputConnection();
+ if (!mService.isFullscreenMode()) {
// Start listening for updates to the text from typing, etc.
if (ic != null) {
ExtractedTextRequest req = new ExtractedTextRequest();
ic.getExtractedText(req, InputConnection.GET_EXTRACTED_TEXT_MONITOR);
}
}
- mContext.vibrate();
+ mService.vibrate();
final List nBest = new ArrayList();
for (String c : mVoiceResults.candidates) {
@@ -511,7 +513,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
mHints.registerVoiceResult(bestResult);
if (ic != null) ic.beginBatchEdit(); // To avoid extra updates on committing older text
- mContext.commitTyped(ic);
+ mService.commitTyped(ic);
EditingUtils.appendText(ic, bestResult);
if (ic != null) ic.endBatchEdit();
@@ -520,22 +522,38 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
onCancelVoice();
}
- public void switchToRecognitionStatusView(final boolean configurationChanging) {
- final boolean configChanged = configurationChanging;
+ public void switchToRecognitionStatusView(final Configuration configuration) {
mHandler.post(new Runnable() {
@Override
public void run() {
- mContext.setCandidatesViewShown(false);
+ mService.setCandidatesViewShown(false);
mRecognizing = true;
+ mVoiceInput.newView();
View v = mVoiceInput.getView();
+
ViewParent p = v.getParent();
if (p != null && p instanceof ViewGroup) {
- ((ViewGroup)p).removeView(v);
+ ((ViewGroup) p).removeView(v);
}
- mContext.setInputView(v);
- mContext.updateInputViewShown();
- if (configChanged) {
- mVoiceInput.onConfigurationChanged();
+
+ View keyboardView = KeyboardSwitcher.getInstance().getInputView();
+
+ // The full height of the keyboard is difficult to calculate
+ // as the dimension is expressed in "mm" and not in "pixel"
+ // As we add mm, we don't know how the rounding is going to work
+ // thus we may end up with few pixels extra (or less).
+ if (keyboardView != null) {
+ int h = keyboardView.getHeight();
+ if (h > 0) {
+ View popupLayout = v.findViewById(R.id.popup_layout);
+ popupLayout.getLayoutParams().height = h;
+ }
+ }
+ mService.setInputView(v);
+ mService.updateInputViewShown();
+
+ if (configuration != null) {
+ mVoiceInput.onConfigurationChanged(configuration);
}
}});
}
@@ -547,7 +565,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
*/
}
- private void reallyStartListening(boolean swipe, final boolean configurationChanging) {
+ private void reallyStartListening(boolean swipe) {
if (!VOICE_INSTALLED) {
return;
}
@@ -555,7 +573,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
// The user has started a voice input, so remember that in the
// future (so we don't show the warning dialog after the first run).
SharedPreferences.Editor editor =
- PreferenceManager.getDefaultSharedPreferences(mContext).edit();
+ PreferenceManager.getDefaultSharedPreferences(mService).edit();
editor.putBoolean(PREF_HAS_USED_VOICE_INPUT, true);
SharedPreferencesCompat.apply(editor);
mHasUsedVoiceInput = true;
@@ -565,34 +583,32 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
// The user has started a voice input from an unsupported locale, so remember that
// in the future (so we don't show the warning dialog the next time they do this).
SharedPreferences.Editor editor =
- PreferenceManager.getDefaultSharedPreferences(mContext).edit();
+ PreferenceManager.getDefaultSharedPreferences(mService).edit();
editor.putBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, true);
SharedPreferencesCompat.apply(editor);
mHasUsedVoiceInputUnsupportedLocale = true;
}
// Clear N-best suggestions
- mContext.clearSuggestions();
+ mService.clearSuggestions();
FieldContext context = makeFieldContext();
mVoiceInput.startListening(context, swipe);
- switchToRecognitionStatusView(configurationChanging);
+ switchToRecognitionStatusView(null);
}
- public void startListening(final boolean swipe, IBinder token,
- final boolean configurationChanging) {
+ public void startListening(final boolean swipe, IBinder token) {
// TODO: remove swipe which is no longer used.
if (VOICE_INSTALLED) {
if (needsToShowWarningDialog()) {
// Calls reallyStartListening if user clicks OK, does nothing if user clicks Cancel.
- showVoiceWarningDialog(swipe, token, configurationChanging);
+ showVoiceWarningDialog(swipe, token);
} else {
- reallyStartListening(swipe, configurationChanging);
+ reallyStartListening(swipe);
}
}
}
-
private boolean fieldCanDoVoice(FieldContext fieldContext) {
return !mPasswordText
&& mVoiceInput != null
@@ -603,7 +619,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
return ENABLE_VOICE_BUTTON && fieldCanDoVoice(fieldContext)
&& !(attribute != null
&& IME_OPTION_NO_MICROPHONE.equals(attribute.privateImeOptions))
- && SpeechRecognizer.isRecognitionAvailable(mContext);
+ && SpeechRecognizer.isRecognitionAvailable(mService);
}
public void loadSettings(EditorInfo attribute, SharedPreferences sp) {
@@ -616,10 +632,10 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
if (VOICE_INSTALLED) {
final String voiceMode = sp.getString(PREF_VOICE_MODE,
- mContext.getString(R.string.voice_mode_main));
- mVoiceButtonEnabled = !voiceMode.equals(mContext.getString(R.string.voice_mode_off))
+ mService.getString(R.string.voice_mode_main));
+ mVoiceButtonEnabled = !voiceMode.equals(mService.getString(R.string.voice_mode_off))
&& shouldShowVoiceButton(makeFieldContext(), attribute);
- mVoiceButtonOnPrimary = voiceMode.equals(mContext.getString(R.string.voice_mode_main));
+ mVoiceButtonOnPrimary = voiceMode.equals(mService.getString(R.string.voice_mode_main));
}
}
@@ -632,9 +648,14 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
public void onStartInputView(IBinder token) {
// If IME is in voice mode, but still needs to show the voice warning dialog,
// keep showing the warning.
- if (mSubtypeSwitcher.isVoiceMode() && needsToShowWarningDialog() && token != null) {
- showVoiceWarningDialog(false, token, false);
+ if (mSubtypeSwitcher.isVoiceMode() && token != null) {
+ // Close keyboard view if it is been shown.
+ if (KeyboardSwitcher.getInstance().isInputViewShown())
+ KeyboardSwitcher.getInstance().getInputView().purgeKeyboardAndClosing();
+ startListening(false, token);
}
+ // If we have no token, onAttachedToWindow will take care of showing dialog and start
+ // listening.
}
public void onAttachedToWindow() {
@@ -643,9 +664,9 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
mSubtypeSwitcher.setVoiceInput(mVoiceInput);
}
- public void onConfigurationChanged(boolean configurationChanging) {
+ public void onConfigurationChanged(Configuration configuration) {
if (mRecognizing) {
- switchToRecognitionStatusView(configurationChanging);
+ switchToRecognitionStatusView(configuration);
}
}
@@ -664,7 +685,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
// onCurrentInputMethodSubtypeChanged() will be called first. LatinIME will know
// that it's in keyboard mode and SubtypeSwitcher will call onCancelVoice().
mRecognizing = false;
- mContext.switchToKeyboardView();
+ mService.switchToKeyboardView();
}
}
}
@@ -682,8 +703,8 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
public FieldContext makeFieldContext() {
SubtypeSwitcher switcher = SubtypeSwitcher.getInstance();
- return new FieldContext(mContext.getCurrentInputConnection(),
- mContext.getCurrentInputEditorInfo(), switcher.getInputLocaleStr(),
+ return new FieldContext(mService.getCurrentInputConnection(),
+ mService.getCurrentInputEditorInfo(), switcher.getInputLocaleStr(),
switcher.getEnabledLanguages());
}
diff --git a/java/src/com/android/inputmethod/voice/VoiceInput.java b/java/src/com/android/inputmethod/voice/VoiceInput.java
index f77b4dd0d..ffa349fde 100644
--- a/java/src/com/android/inputmethod/voice/VoiceInput.java
+++ b/java/src/com/android/inputmethod/voice/VoiceInput.java
@@ -22,6 +22,7 @@ import com.android.inputmethod.latin.R;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -129,12 +130,17 @@ public class VoiceInput implements OnClickListener {
private final static int MSG_CLOSE_ERROR_DIALOG = 1;
+ private final static int MSG_RESET = 2;
+
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
- if (msg.what == MSG_CLOSE_ERROR_DIALOG) {
+ if (msg.what == MSG_RESET || msg.what == MSG_CLOSE_ERROR_DIALOG) {
mState = DEFAULT;
mRecognitionView.finish();
+ }
+
+ if (msg.what == MSG_CLOSE_ERROR_DIALOG) {
mUiListener.onCancelVoice();
}
}
@@ -277,8 +283,9 @@ public class VoiceInput implements OnClickListener {
* The configuration of the IME changed and may have caused the views to be layed out
* again. Restore the state of the recognition view.
*/
- public void onConfigurationChanged() {
+ public void onConfigurationChanged(Configuration configuration) {
mRecognitionView.restoreState();
+ mRecognitionView.getView().dispatchConfigurationChanged(configuration);
}
/**
@@ -509,7 +516,7 @@ public class VoiceInput implements OnClickListener {
mState = DEFAULT;
// Remove all pending tasks (e.g., timers to cancel voice input)
- mHandler.removeMessages(MSG_CLOSE_ERROR_DIALOG);
+ mHandler.removeMessages(MSG_RESET);
mSpeechRecognizer.cancel();
mUiListener.onCancelVoice();
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 6e4e97138..25580f4b1 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -89,7 +89,7 @@ static jint latinime_BinaryDictionary_open(JNIEnv *env, jobject object,
return 0;
}
dictBuf = malloc(sizeof(char) * dictSize);
- if (dictBuf == NULL) {
+ if (!dictBuf) {
LOGE("DICT: Can't allocate memory region for dictionary. errno=%d", errno);
return 0;
}
diff --git a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
new file mode 100644
index 000000000..004ddb61a
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.test.AndroidTestCase;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+public class SubtypeLocaleTests extends AndroidTestCase {
+ private static final String PACKAGE = LatinIME.class.getPackage().getName();
+
+ private Resources mRes;
+ private List mKeyboardSubtypes;
+
+ public interface Predicator {
+ public boolean evaluate(T object);
+ }
+
+ private static List filter(List source, Predicator super T> predicator) {
+ final ArrayList filtered = new ArrayList();
+ for (final T element : source) {
+ if (predicator.evaluate(element))
+ filtered.add(element);
+ }
+ return filtered;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ final Context context = getContext();
+ mRes = context.getResources();
+
+ SubtypeLocale.init(context);
+
+ final InputMethodManager imm = (InputMethodManager) context.getSystemService(
+ Context.INPUT_METHOD_SERVICE);
+ for (final InputMethodInfo imi : imm.getInputMethodList()) {
+ if (imi.getPackageName().equals(PACKAGE)) {
+ mKeyboardSubtypes = filter(imi.getSubtypes(),
+ new Predicator() {
+ @Override
+ public boolean evaluate(InputMethodSubtype ims) {
+ return ims.getMode().equals("keyboard");
+ }
+ });
+ break;
+ }
+ }
+ assertNotNull("Can not find input method " + PACKAGE, mKeyboardSubtypes);
+ assertTrue("Can not find keyboard subtype", mKeyboardSubtypes.size() > 0);
+ }
+
+ // Copied from {@link java.junit.Assert#format(String, Object, Object)}
+ private static String format(String message, Object expected, Object actual) {
+ return message + " expected:<" + expected + "> but was:<" + actual + ">";
+ }
+
+ private String getStringWithLocale(int resId, Locale locale) {
+ final Locale savedLocale = Locale.getDefault();
+ try {
+ Locale.setDefault(locale);
+ return mRes.getString(resId);
+ } finally {
+ Locale.setDefault(savedLocale);
+ }
+ }
+
+ public void testSubtypeLocale() {
+ for (final InputMethodSubtype subtype : mKeyboardSubtypes) {
+ final String localeCode = subtype.getLocale();
+ final Locale locale = new Locale(localeCode);
+ // The locale name which will be displayed on spacebar. For example 'English (US)' or
+ // 'Francais (Canada)'. (c=\u008d)
+ final String displayName = SubtypeLocale.getFullDisplayName(locale);
+ // The subtype name in its locale. For example 'English (US) Keyboard' or
+ // 'Clavier Francais (Canada)'. (c=\u008d)
+ final String subtypeName = getStringWithLocale(subtype.getNameResId(), locale);
+ assertTrue(
+ format("subtype display name of " + localeCode + ":", subtypeName, displayName),
+ subtypeName.contains(displayName));
+ }
+ }
+}