Merge "Enabled to change the current subtype to voice input subtypes"

main
satok 2010-11-23 13:35:20 -08:00 committed by Android (Google) Code Review
commit da64719c6d
3 changed files with 154 additions and 26 deletions

View File

@ -35,6 +35,7 @@ import android.inputmethodservice.InputMethodService;
import android.media.AudioManager; import android.media.AudioManager;
import android.os.Debug; import android.os.Debug;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder;
import android.os.Message; import android.os.Message;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.Vibrator; import android.os.Vibrator;
@ -48,6 +49,8 @@ import android.util.Printer;
import android.view.HapticFeedbackConstants; import android.view.HapticFeedbackConstants;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CompletionInfo;
@ -458,7 +461,7 @@ public class LatinIME extends InputMethodService
@Override @Override
public void onConfigurationChanged(Configuration conf) { public void onConfigurationChanged(Configuration conf) {
mSubtypeSwitcher.onConfigurationChanged(conf); mSubtypeSwitcher.onConfigurationChanged(conf);
onLanguageChanged(); onKeyboardLanguageChanged();
updateAutoTextEnabled(); updateAutoTextEnabled();
// If orientation changed while predicting, commit the change // If orientation changed while predicting, commit the change
@ -512,6 +515,7 @@ public class LatinIME extends InputMethodService
public void onStartInputView(EditorInfo attribute, boolean restarting) { public void onStartInputView(EditorInfo attribute, boolean restarting) {
final KeyboardSwitcher switcher = mKeyboardSwitcher; final KeyboardSwitcher switcher = mKeyboardSwitcher;
LatinKeyboardView inputView = switcher.getInputView(); LatinKeyboardView inputView = switcher.getInputView();
// In landscape mode, this method gets called without the input view being created. // In landscape mode, this method gets called without the input view being created.
if (inputView == null) { if (inputView == null) {
return; return;
@ -521,7 +525,7 @@ public class LatinIME extends InputMethodService
if (mRefreshKeyboardRequired) { if (mRefreshKeyboardRequired) {
mRefreshKeyboardRequired = false; mRefreshKeyboardRequired = false;
onLanguageChanged(); onKeyboardLanguageChanged();
} }
TextEntryState.newSession(this); TextEntryState.newSession(this);
@ -629,6 +633,10 @@ public class LatinIME extends InputMethodService
checkReCorrectionOnStart(); checkReCorrectionOnStart();
checkTutorial(attribute.privateImeOptions); checkTutorial(attribute.privateImeOptions);
inputView.setForeground(true); inputView.setForeground(true);
// TODO: Not to show keyboard if IME starts in Voice One shot mode.
mVoiceConnector.onStartInputView();
if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
} }
@ -709,10 +717,8 @@ public class LatinIME extends InputMethodService
// If the current selection in the text view changes, we should // If the current selection in the text view changes, we should
// clear whatever candidate text we have. // clear whatever candidate text we have.
if ((((mComposing.length() > 0 && mPredicting) if ((((mComposing.length() > 0 && mPredicting)
|| mVoiceConnector.isVoiceInputHighlighted()) || mVoiceConnector.isVoiceInputHighlighted()) && (newSelStart != candidatesEnd
&& (newSelStart != candidatesEnd || newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart)) {
|| newSelEnd != candidatesEnd)
&& mLastSelectionStart != newSelStart)) {
mComposing.setLength(0); mComposing.setLength(0);
mPredicting = false; mPredicting = false;
mHandler.postUpdateSuggestions(); mHandler.postUpdateSuggestions();
@ -1418,8 +1424,17 @@ public class LatinIME extends InputMethodService
public void switchToKeyboardView() { public void switchToKeyboardView() {
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
public void run() { public void run() {
if (mKeyboardSwitcher.getInputView() != null) { if (DEBUG) {
setInputView(mKeyboardSwitcher.getInputView()); Log.d(TAG, "Switch to keyboard view.");
}
View v = mKeyboardSwitcher.getInputView();
if (v != null) {
// Confirms that the keyboard view doesn't have parent view.
ViewParent p = v.getParent();
if (p != null && p instanceof ViewGroup) {
((ViewGroup)p).removeView(v);
}
setInputView(v);
} }
setCandidatesViewShown(isCandidateStripVisible()); setCandidatesViewShown(isCandidateStripVisible());
updateInputViewShown(); updateInputViewShown();
@ -1844,7 +1859,7 @@ public class LatinIME extends InputMethodService
// Notify that Language has been changed and toggleLanguage will update KeyboaredID according // Notify that Language has been changed and toggleLanguage will update KeyboaredID according
// to new Language. // to new Language.
private void onLanguageChanged() { public void onKeyboardLanguageChanged() {
toggleLanguage(true, true); toggleLanguage(true, true);
} }
@ -2226,6 +2241,5 @@ public class LatinIME extends InputMethodService
@Override @Override
public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) { public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) {
SubtypeSwitcher.getInstance().updateSubtype(subtype); SubtypeSwitcher.getInstance().updateSubtype(subtype);
onLanguageChanged();
} }
} }

View File

@ -17,12 +17,12 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import com.android.inputmethod.voice.SettingsUtil; import com.android.inputmethod.voice.SettingsUtil;
import com.android.inputmethod.voice.VoiceInput;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.inputmethodservice.InputMethodService;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@ -39,7 +39,7 @@ public class SubtypeSwitcher {
// We may or may not draw the current language on space bar regardless of this flag. // We may or may not draw the current language on space bar regardless of this flag.
public static final boolean USE_SPACEBAR_LANGUAGE_SWITCHER = false; public static final boolean USE_SPACEBAR_LANGUAGE_SWITCHER = false;
private static final boolean DBG = false; private static final boolean DBG = false;
private static final String TAG = "SubtypeSwitcher"; private static final String TAG = "InputMethodSubtypeSwitcher";
private static final char LOCALE_SEPARATER = '_'; private static final char LOCALE_SEPARATER = '_';
private static final String KEYBOARD_MODE = "keyboard"; private static final String KEYBOARD_MODE = "keyboard";
@ -48,7 +48,7 @@ public class SubtypeSwitcher {
new TextUtils.SimpleStringSplitter(LOCALE_SEPARATER); new TextUtils.SimpleStringSplitter(LOCALE_SEPARATER);
private static final SubtypeSwitcher sInstance = new SubtypeSwitcher(); private static final SubtypeSwitcher sInstance = new SubtypeSwitcher();
private /* final */ InputMethodService mService; private /* final */ LatinIME mService;
private /* final */ InputMethodManager mImm; private /* final */ InputMethodManager mImm;
private /* final */ Resources mResources; private /* final */ Resources mResources;
private final ArrayList<InputMethodSubtype> mEnabledKeyboardSubtypesOfCurrentInputMethod = private final ArrayList<InputMethodSubtype> mEnabledKeyboardSubtypesOfCurrentInputMethod =
@ -62,6 +62,7 @@ public class SubtypeSwitcher {
private String mInputLocaleStr; private String mInputLocaleStr;
private String mMode; private String mMode;
private List<InputMethodSubtype> mAllEnabledSubtypesOfCurrentInputMethod; private List<InputMethodSubtype> mAllEnabledSubtypesOfCurrentInputMethod;
private VoiceInput mVoiceInput;
private boolean mNeedsToDisplayLanguage; private boolean mNeedsToDisplayLanguage;
private boolean mIsSystemLanguageSameAsInputLanguage; private boolean mIsSystemLanguageSameAsInputLanguage;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -71,10 +72,7 @@ public class SubtypeSwitcher {
} }
public static void init(LatinIME service) { public static void init(LatinIME service) {
sInstance.mService = service; sInstance.resetParams(service);
sInstance.mResources = service.getResources();
sInstance.mImm = (InputMethodManager) service.getSystemService(
Context.INPUT_METHOD_SERVICE);
if (USE_SPACEBAR_LANGUAGE_SWITCHER) { if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
sInstance.initLanguageSwitcher(service); sInstance.initLanguageSwitcher(service);
} }
@ -85,6 +83,21 @@ public class SubtypeSwitcher {
private SubtypeSwitcher() { private SubtypeSwitcher() {
} }
private void resetParams(LatinIME service) {
mService = service;
mResources = service.getResources();
mImm = (InputMethodManager) service.getSystemService(Context.INPUT_METHOD_SERVICE);
mEnabledKeyboardSubtypesOfCurrentInputMethod.clear();
mEnabledLanguagesOfCurrentInputMethod.clear();
mSystemLocale = null;
mInputLocale = null;
mInputLocaleStr = null;
mMode = null;
mAllEnabledSubtypesOfCurrentInputMethod = null;
// TODO: Voice input should be created here
mVoiceInput = null;
}
// Update all parameters stored in SubtypeSwitcher. // Update all parameters stored in SubtypeSwitcher.
// Only configuration changed event is allowed to call this because this is heavy. // Only configuration changed event is allowed to call this because this is heavy.
private void updateAllParameters() { private void updateAllParameters() {
@ -126,17 +139,65 @@ public class SubtypeSwitcher {
mNeedsToDisplayLanguage = !(getEnabledKeyboardLocaleCount() <= 1 mNeedsToDisplayLanguage = !(getEnabledKeyboardLocaleCount() <= 1
&& mIsSystemLanguageSameAsInputLanguage); && mIsSystemLanguageSameAsInputLanguage);
if (foundCurrentSubtypeBecameDisabled) { if (foundCurrentSubtypeBecameDisabled) {
if (DBG) {
Log.w(TAG, "Last subtype was disabled. Update to the current one.");
}
updateSubtype(mImm.getCurrentInputMethodSubtype()); updateSubtype(mImm.getCurrentInputMethodSubtype());
} }
} }
// Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function. // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function.
public void updateSubtype(InputMethodSubtype newSubtype) { public void updateSubtype(InputMethodSubtype newSubtype) {
if (DBG) { final String newLocale;
Log.w(TAG, "Update subtype to:" + newSubtype.getLocale() + "," + newSubtype.getMode()); final String newMode;
if (newSubtype == null) {
// Normally, newSubtype shouldn't be null. But just in case if newSubtype was null,
// fallback to the default locale and mode.
Log.e(TAG, "Couldn't get the current subtype.");
newLocale = "en_US";
newMode =KEYBOARD_MODE;
} else {
newLocale = newSubtype.getLocale();
newMode = newSubtype.getMode();
}
if (DBG) {
Log.w(TAG, "Update subtype to:" + newLocale + "," + newMode
+ ", from: " + mInputLocaleStr + ", " + mMode);
}
boolean languageChanged = false;
if (!newLocale.equals(mInputLocaleStr)) {
if (mInputLocaleStr != null) {
languageChanged = true;
}
updateInputLocale(newLocale);
}
boolean modeChanged = false;
String oldMode = mMode;
if (!newMode.equals(mMode)) {
if (mMode != null) {
modeChanged = true;
}
mMode = newMode;
}
if (isKeyboardMode()) {
if (modeChanged) {
if (VOICE_MODE.equals(oldMode) && mVoiceInput != null) {
mVoiceInput.cancel();
}
}
if (languageChanged) {
mService.onKeyboardLanguageChanged();
}
} else if (isVoiceMode()) {
if (languageChanged || modeChanged) {
if (mVoiceInput != null) {
// TODO: Call proper function to trigger VoiceIME
mService.onKey(LatinKeyboardView.KEYCODE_VOICE, null, 0, 0);
}
}
} else {
Log.w(TAG, "Unknown subtype mode: " + mMode);
} }
updateInputLocale(newSubtype.getLocale());
mMode = newSubtype.getMode();
} }
// Update the current input locale from Locale string. // Update the current input locale from Locale string.
@ -269,6 +330,37 @@ public class SubtypeSwitcher {
return oldLocale; return oldLocale;
} }
public boolean isKeyboardMode() {
return KEYBOARD_MODE.equals(mMode);
}
///////////////////////////
// Voice Input functions //
///////////////////////////
public boolean setVoiceInput(VoiceInput vi) {
if (mVoiceInput == null) {
// TODO: Remove requirements to construct KeyboardSwitcher
// when IME was enabled with Voice mode
mService.onKeyboardLanguageChanged();
mVoiceInput = vi;
if (isVoiceMode() && mVoiceInput != null) {
if (DBG) {
Log.d(TAG, "Set and call voice input.");
}
// TODO: Call proper function to enable VoiceIME
mService.onKey(LatinKeyboardView.KEYCODE_VOICE, null, 0, 0);
return true;
}
}
return false;
}
public boolean isVoiceMode() {
return VOICE_MODE.equals(mMode);
}
////////////////////////////////////// //////////////////////////////////////
// SpaceBar Language Switch support // // SpaceBar Language Switch support //
////////////////////////////////////// //////////////////////////////////////

View File

@ -41,6 +41,7 @@ import android.view.WindowManager;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -78,12 +79,14 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
private boolean mVoiceButtonOnPrimary; private boolean mVoiceButtonOnPrimary;
private boolean mVoiceInputHighlighted; private boolean mVoiceInputHighlighted;
private InputMethodManager mImm;
private LatinIME mContext; private LatinIME mContext;
private AlertDialog mVoiceWarningDialog; private AlertDialog mVoiceWarningDialog;
private VoiceInput mVoiceInput; private VoiceInput mVoiceInput;
private final VoiceResults mVoiceResults = new VoiceResults(); private final VoiceResults mVoiceResults = new VoiceResults();
private Hints mHints; private Hints mHints;
private UIHandler mHandler; private UIHandler mHandler;
private SubtypeSwitcher mSubtypeSwitcher;
// For each word, a list of potential replacements, usually from voice. // For each word, a list of potential replacements, usually from voice.
private final Map<String, List<CharSequence>> mWordToSuggestions = private final Map<String, List<CharSequence>> mWordToSuggestions =
new HashMap<String, List<CharSequence>>(); new HashMap<String, List<CharSequence>>();
@ -96,6 +99,8 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
private void initInternal(LatinIME context, UIHandler h) { private void initInternal(LatinIME context, UIHandler h) {
mContext = context; mContext = context;
mHandler = h; mHandler = h;
mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
if (VOICE_INSTALLED) { if (VOICE_INSTALLED) {
mVoiceInput = new VoiceInput(context, this); mVoiceInput = new VoiceInput(context, this);
mHints = new Hints(context, new Hints.Display() { mHints = new Hints(context, new Hints.Display() {
@ -376,7 +381,6 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
} }
} }
mContext.vibrate(); mContext.vibrate();
mContext.switchToKeyboardView();
final List<CharSequence> nBest = new ArrayList<CharSequence>(); final List<CharSequence> nBest = new ArrayList<CharSequence>();
for (String c : mVoiceResults.candidates) { for (String c : mVoiceResults.candidates) {
@ -399,6 +403,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
mVoiceInputHighlighted = true; mVoiceInputHighlighted = true;
mWordToSuggestions.putAll(mVoiceResults.alternatives); mWordToSuggestions.putAll(mVoiceResults.alternatives);
onCancelVoice();
} }
public void switchToRecognitionStatusView(final boolean configurationChanging) { public void switchToRecognitionStatusView(final boolean configurationChanging) {
@ -410,7 +415,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
View v = mVoiceInput.getView(); View v = mVoiceInput.getView();
ViewParent p = v.getParent(); ViewParent p = v.getParent();
if (p != null && p instanceof ViewGroup) { if (p != null && p instanceof ViewGroup) {
((ViewGroup)v.getParent()).removeView(v); ((ViewGroup)p).removeView(v);
} }
mContext.setInputView(v); mContext.setInputView(v);
mContext.updateInputViewShown(); mContext.updateInputViewShown();
@ -499,6 +504,10 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
} }
} }
public void onStartInputView() {
mSubtypeSwitcher.setVoiceInput(mVoiceInput);
}
public void onConfigurationChanged(boolean configurationChanging) { public void onConfigurationChanged(boolean configurationChanging) {
if (mRecognizing) { if (mRecognizing) {
switchToRecognitionStatusView(configurationChanging); switchToRecognitionStatusView(configurationChanging);
@ -507,10 +516,23 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
@Override @Override
public void onCancelVoice() { public void onCancelVoice() {
if (mRecognizing) { if (mRecognizing) {
if (mSubtypeSwitcher.isVoiceMode()) {
// If voice mode is being canceled within LatinIME (i.e. time-out or user
// cancellation etc.), onCancelVoice() will be called first. LatinIME thinks it's
// still in voice mode. LatinIME needs to call switchToLastInputMethod().
// Note that onCancelVoice() will be called again from SubtypeSwitcher.
IBinder token = mContext.getWindow().getWindow().getAttributes().token;
mImm.switchToLastInputMethod(token);
} else if (mSubtypeSwitcher.isKeyboardMode()) {
// If voice mode is being canceled out of LatinIME (i.e. by user's IME switching or
// as a result of switchToLastInputMethod() etc.),
// onCurrentInputMethodSubtypeChanged() will be called first. LatinIME will know
// that it's in keyboard mode and SubtypeSwitcher will call onCancelVoice().
mRecognizing = false; mRecognizing = false;
mContext.switchToKeyboardView(); mContext.switchToKeyboardView();
} }
} }
}
@Override @Override
public void onVoiceResults(List<String> candidates, public void onVoiceResults(List<String> candidates,