Merge "Support select input method dialog on pre-HC platform"
This commit is contained in:
commit
1dc80048d7
10 changed files with 209 additions and 55 deletions
|
@ -301,6 +301,9 @@
|
|||
<!-- Title of the dialog for selecting input methods. [CHAR LIMIT=20] -->
|
||||
<string name="selectInputMethod">Select input method</string>
|
||||
|
||||
<!-- Title for configuring input method settings [CHAR LIMIT=35] -->
|
||||
<string name="configure_input_method">Configure input methods</string>
|
||||
|
||||
<!-- Title for input language selection screen -->
|
||||
<string name="language_selection_title">Input languages</string>
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package com.android.inputmethod.compat;
|
||||
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
|
||||
|
@ -56,4 +57,21 @@ public class InputMethodInfoCompatWrapper {
|
|||
return new InputMethodSubtypeCompatWrapper(CompatUtils.invoke(mImi, null,
|
||||
METHOD_getSubtypeAt, index));
|
||||
}
|
||||
|
||||
public CharSequence loadLabel(PackageManager pm) {
|
||||
return mImi.loadLabel(pm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof InputMethodInfoCompatWrapper) {
|
||||
return mImi.equals(((InputMethodInfoCompatWrapper)o).mImi);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mImi.hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,21 +16,28 @@
|
|||
|
||||
package com.android.inputmethod.compat;
|
||||
|
||||
import com.android.inputmethod.deprecated.LanguageSwitcherProxy;
|
||||
import com.android.inputmethod.latin.LatinIME;
|
||||
import com.android.inputmethod.latin.SubtypeSwitcher;
|
||||
import com.android.inputmethod.latin.Utils;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.IBinder;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import com.android.inputmethod.deprecated.LanguageSwitcherProxy;
|
||||
import com.android.inputmethod.latin.R;
|
||||
import com.android.inputmethod.latin.SubtypeSwitcher;
|
||||
import com.android.inputmethod.latin.Utils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -72,27 +79,27 @@ public class InputMethodManagerCompatWrapper {
|
|||
private static final String VOICE_MODE = "voice";
|
||||
private static final String KEYBOARD_MODE = "keyboard";
|
||||
|
||||
private InputMethodServiceCompatWrapper mService;
|
||||
private InputMethodManager mImm;
|
||||
private PackageManager mPackageManager;
|
||||
private ApplicationInfo mApplicationInfo;
|
||||
private LanguageSwitcherProxy mLanguageSwitcherProxy;
|
||||
private String mLatinImePackageName;
|
||||
|
||||
private InputMethodManagerCompatWrapper() {
|
||||
}
|
||||
|
||||
public static InputMethodManagerCompatWrapper getInstance(Context context) {
|
||||
if (sInstance.mImm == null) {
|
||||
sInstance.init(context);
|
||||
}
|
||||
public static InputMethodManagerCompatWrapper getInstance() {
|
||||
if (sInstance.mImm == null)
|
||||
Log.w(TAG, "getInstance() is called before initialization");
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private synchronized void init(Context context) {
|
||||
mImm = (InputMethodManager) context.getSystemService(
|
||||
public static void init(InputMethodServiceCompatWrapper service) {
|
||||
sInstance.mService = service;
|
||||
sInstance.mImm = (InputMethodManager) service.getSystemService(
|
||||
Context.INPUT_METHOD_SERVICE);
|
||||
if (context instanceof LatinIME) {
|
||||
mLatinImePackageName = context.getPackageName();
|
||||
}
|
||||
mLanguageSwitcherProxy = LanguageSwitcherProxy.getInstance();
|
||||
sInstance.mLatinImePackageName = service.getPackageName();
|
||||
sInstance.mPackageManager = service.getPackageManager();
|
||||
sInstance.mApplicationInfo = service.getApplicationInfo();
|
||||
sInstance.mLanguageSwitcherProxy = LanguageSwitcherProxy.getInstance();
|
||||
}
|
||||
|
||||
public InputMethodSubtypeCompatWrapper getCurrentInputMethodSubtype() {
|
||||
|
@ -196,11 +203,15 @@ public class InputMethodManagerCompatWrapper {
|
|||
return shortcutMap;
|
||||
}
|
||||
|
||||
// We don't call this method when we switch between subtypes within this IME.
|
||||
public void setInputMethodAndSubtype(
|
||||
IBinder token, String id, InputMethodSubtypeCompatWrapper subtype) {
|
||||
// TODO: Support subtype change on non-subtype-supported platform.
|
||||
if (subtype != null && subtype.hasOriginalObject()) {
|
||||
CompatUtils.invoke(mImm, null, METHOD_setInputMethodAndSubtype,
|
||||
token, id, subtype.getOriginalObject());
|
||||
} else {
|
||||
mImm.setInputMethod(token, id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,6 +233,87 @@ public class InputMethodManagerCompatWrapper {
|
|||
|
||||
public void showInputMethodPicker() {
|
||||
if (mImm == null) return;
|
||||
mImm.showInputMethodPicker();
|
||||
if (SUBTYPE_SUPPORTED) {
|
||||
mImm.showInputMethodPicker();
|
||||
return;
|
||||
}
|
||||
|
||||
// The code below are based on {@link InputMethodManager#showInputMethodMenuInternal}.
|
||||
|
||||
final InputMethodInfoCompatWrapper myImi = Utils.getInputMethodInfo(
|
||||
this, mLatinImePackageName);
|
||||
final List<InputMethodSubtypeCompatWrapper> myImsList = getEnabledInputMethodSubtypeList(
|
||||
myImi, true);
|
||||
final InputMethodSubtypeCompatWrapper currentIms = getCurrentInputMethodSubtype();
|
||||
final List<InputMethodInfoCompatWrapper> imiList = getEnabledInputMethodList();
|
||||
imiList.remove(myImi);
|
||||
Collections.sort(imiList, new Comparator<InputMethodInfoCompatWrapper>() {
|
||||
@Override
|
||||
public int compare(InputMethodInfoCompatWrapper imi1,
|
||||
InputMethodInfoCompatWrapper imi2) {
|
||||
final CharSequence imiId1 = imi1.loadLabel(mPackageManager) + "/" + imi1.getId();
|
||||
final CharSequence imiId2 = imi2.loadLabel(mPackageManager) + "/" + imi2.getId();
|
||||
return imiId1.toString().compareTo(imiId2.toString());
|
||||
}
|
||||
});
|
||||
|
||||
final int myImsCount = myImsList.size();
|
||||
final int imiCount = imiList.size();
|
||||
final CharSequence[] items = new CharSequence[myImsCount + imiCount];
|
||||
|
||||
int checkedItem = 0;
|
||||
int index = 0;
|
||||
final CharSequence myImiLabel = myImi.loadLabel(mPackageManager);
|
||||
for (int i = 0; i < myImsCount; i++) {
|
||||
InputMethodSubtypeCompatWrapper ims = myImsList.get(i);
|
||||
if (currentIms.equals(ims))
|
||||
checkedItem = index;
|
||||
final CharSequence title = TextUtils.concat(
|
||||
ims.getDisplayName(mService, mLatinImePackageName, mApplicationInfo),
|
||||
" (" + myImiLabel, ")");
|
||||
items[index] = title;
|
||||
index++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < imiCount; i++) {
|
||||
final InputMethodInfoCompatWrapper imi = imiList.get(i);
|
||||
final CharSequence title = imi.loadLabel(mPackageManager);
|
||||
items[index] = title;
|
||||
index++;
|
||||
}
|
||||
|
||||
final OnClickListener buttonListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface di, int whichButton) {
|
||||
final Intent intent = new Intent("android.settings.INPUT_METHOD_SETTINGS");
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
mService.startActivity(intent);
|
||||
}
|
||||
};
|
||||
final InputMethodServiceCompatWrapper service = mService;
|
||||
final IBinder token = service.getWindow().getWindow().getAttributes().token;
|
||||
final OnClickListener selectionListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface di, int which) {
|
||||
di.dismiss();
|
||||
if (which < myImsCount) {
|
||||
final int imsIndex = which;
|
||||
final InputMethodSubtypeCompatWrapper ims = myImsList.get(imsIndex);
|
||||
service.notifyOnCurrentInputMethodSubtypeChanged(ims);
|
||||
} else {
|
||||
final int imiIndex = which - myImsCount;
|
||||
final InputMethodInfoCompatWrapper imi = imiList.get(imiIndex);
|
||||
setInputMethodAndSubtype(token, imi.getId(), null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(mService)
|
||||
.setTitle(mService.getString(R.string.selectInputMethod))
|
||||
.setNeutralButton(R.string.configure_input_method, buttonListener)
|
||||
.setSingleChoiceItems(items, checkedItem, selectionListener);
|
||||
mService.showOptionDialogInternal(builder.create());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,15 @@
|
|||
|
||||
package com.android.inputmethod.compat;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.os.IBinder;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import com.android.inputmethod.deprecated.LanguageSwitcherProxy;
|
||||
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
||||
import com.android.inputmethod.latin.SubtypeSwitcher;
|
||||
|
||||
public class InputMethodServiceCompatWrapper extends InputMethodService {
|
||||
|
@ -32,10 +37,33 @@ public class InputMethodServiceCompatWrapper extends InputMethodService {
|
|||
|
||||
private InputMethodManagerCompatWrapper mImm;
|
||||
|
||||
// For compatibility of {@link InputMethodManager#showInputMethodPicker}.
|
||||
// TODO: Move this variable back to LatinIME when this compatibility wrapper is removed.
|
||||
protected AlertDialog mOptionsDialog;
|
||||
|
||||
public void showOptionDialogInternal(AlertDialog dialog) {
|
||||
final IBinder windowToken = KeyboardSwitcher.getInstance().getKeyboardView()
|
||||
.getWindowToken();
|
||||
if (windowToken == null) return;
|
||||
|
||||
dialog.setCancelable(true);
|
||||
dialog.setCanceledOnTouchOutside(true);
|
||||
|
||||
final Window window = dialog.getWindow();
|
||||
final WindowManager.LayoutParams lp = window.getAttributes();
|
||||
lp.token = windowToken;
|
||||
lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
|
||||
window.setAttributes(lp);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
|
||||
|
||||
mOptionsDialog = dialog;
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mImm = InputMethodManagerCompatWrapper.getInstance(this);
|
||||
mImm = InputMethodManagerCompatWrapper.getInstance();
|
||||
}
|
||||
|
||||
// When the API level is 10 or previous, notifyOnCurrentInputMethodSubtypeChanged should
|
||||
|
|
|
@ -16,13 +16,16 @@
|
|||
|
||||
package com.android.inputmethod.compat;
|
||||
|
||||
import com.android.inputmethod.latin.LatinImeLogger;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.inputmethod.latin.LatinImeLogger;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
// TODO: Override this class with the concrete implementation if we need to take care of the
|
||||
// performance.
|
||||
|
@ -50,6 +53,9 @@ public final class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper
|
|||
CompatUtils.getMethod(CLASS_InputMethodSubtype, "getExtraValueOf", String.class);
|
||||
private static final Method METHOD_isAuxiliary =
|
||||
CompatUtils.getMethod(CLASS_InputMethodSubtype, "isAuxiliary");
|
||||
private static final Method METHOD_getDisplayName =
|
||||
CompatUtils.getMethod(CLASS_InputMethodSubtype, "getDisplayName", Context.class,
|
||||
String.class, ApplicationInfo.class);
|
||||
|
||||
private final int mDummyNameResId;
|
||||
private final int mDummyIconResId;
|
||||
|
@ -122,6 +128,28 @@ public final class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper
|
|||
return (Boolean)CompatUtils.invoke(mObj, false, METHOD_isAuxiliary);
|
||||
}
|
||||
|
||||
public CharSequence getDisplayName(Context context, String packageName,
|
||||
ApplicationInfo appInfo) {
|
||||
if (mObj != null) {
|
||||
return (CharSequence)CompatUtils.invoke(
|
||||
mObj, "", METHOD_getDisplayName, context, packageName, appInfo);
|
||||
}
|
||||
|
||||
// The code below are based on {@link InputMethodSubtype#getDisplayName}.
|
||||
|
||||
final Locale locale = new Locale(getLocale());
|
||||
final String localeStr = locale.getDisplayName();
|
||||
if (getNameResId() == 0) {
|
||||
return localeStr;
|
||||
}
|
||||
final CharSequence subtypeName = context.getText(getNameResId());
|
||||
if (!TextUtils.isEmpty(localeStr)) {
|
||||
return String.format(subtypeName.toString(), localeStr);
|
||||
} else {
|
||||
return localeStr;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDummy() {
|
||||
return !hasOriginalObject();
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ public class VoiceProxy implements VoiceInput.UiListener {
|
|||
mHandler = h;
|
||||
mMinimumVoiceRecognitionViewHeightPixel = Utils.dipToPixel(
|
||||
Utils.getDipScale(service), RECOGNITIONVIEW_MINIMUM_HEIGHT_DIP);
|
||||
mImm = InputMethodManagerCompatWrapper.getInstance(service);
|
||||
mImm = InputMethodManagerCompatWrapper.getInstance();
|
||||
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
|
||||
if (VOICE_INSTALLED) {
|
||||
mVoiceInput = new VoiceInput(service, this);
|
||||
|
|
|
@ -821,7 +821,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
|||
if (settingsKeyMode.equals(res.getString(SETTINGS_KEY_MODE_ALWAYS_SHOW))
|
||||
|| (settingsKeyMode.equals(res.getString(SETTINGS_KEY_MODE_AUTO))
|
||||
&& Utils.hasMultipleEnabledIMEsOrSubtypes(
|
||||
(InputMethodManagerCompatWrapper.getInstance(context))))) {
|
||||
(InputMethodManagerCompatWrapper.getInstance())))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -29,7 +29,6 @@ import android.inputmethodservice.InputMethodService;
|
|||
import android.media.AudioManager;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Debug;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.preference.PreferenceActivity;
|
||||
|
@ -45,8 +44,6 @@ import android.view.KeyEvent;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.CompletionInfo;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.ExtractedText;
|
||||
|
@ -142,8 +139,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
|||
private Suggest mSuggest;
|
||||
private CompletionInfo[] mApplicationSpecifiedCompletions;
|
||||
|
||||
private AlertDialog mOptionsDialog;
|
||||
|
||||
private InputMethodManagerCompatWrapper mImm;
|
||||
private Resources mResources;
|
||||
private SharedPreferences mPrefs;
|
||||
|
@ -361,6 +356,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
|||
mPrefs = prefs;
|
||||
LatinImeLogger.init(this, prefs);
|
||||
LanguageSwitcherProxy.init(this, prefs);
|
||||
InputMethodManagerCompatWrapper.init(this);
|
||||
SubtypeSwitcher.init(this, prefs);
|
||||
KeyboardSwitcher.init(this, prefs);
|
||||
Recorrection.init(this, prefs);
|
||||
|
@ -368,7 +364,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
|||
|
||||
super.onCreate();
|
||||
|
||||
mImm = InputMethodManagerCompatWrapper.getInstance(this);
|
||||
mImm = InputMethodManagerCompatWrapper.getInstance();
|
||||
mInputMethodId = Utils.getInputMethodId(mImm, getPackageName());
|
||||
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
|
||||
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
|
||||
|
@ -2097,7 +2093,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
|||
}
|
||||
}
|
||||
};
|
||||
showOptionsMenuInternal(title, items, listener);
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this)
|
||||
.setIcon(R.drawable.ic_dialog_keyboard)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setItems(items, listener)
|
||||
.setTitle(title);
|
||||
showOptionDialogInternal(builder.create());
|
||||
}
|
||||
|
||||
private void showOptionsMenu() {
|
||||
|
@ -2120,28 +2121,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
|||
}
|
||||
}
|
||||
};
|
||||
showOptionsMenuInternal(title, items, listener);
|
||||
}
|
||||
|
||||
private void showOptionsMenuInternal(CharSequence title, CharSequence[] items,
|
||||
DialogInterface.OnClickListener listener) {
|
||||
final IBinder windowToken = mKeyboardSwitcher.getKeyboardView().getWindowToken();
|
||||
if (windowToken == null) return;
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setCancelable(true);
|
||||
builder.setIcon(R.drawable.ic_dialog_keyboard);
|
||||
builder.setNegativeButton(android.R.string.cancel, null);
|
||||
builder.setItems(items, listener);
|
||||
builder.setTitle(title);
|
||||
mOptionsDialog = builder.create();
|
||||
mOptionsDialog.setCanceledOnTouchOutside(true);
|
||||
Window window = mOptionsDialog.getWindow();
|
||||
WindowManager.LayoutParams lp = window.getAttributes();
|
||||
lp.token = windowToken;
|
||||
lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
|
||||
window.setAttributes(lp);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
|
||||
mOptionsDialog.show();
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this)
|
||||
.setIcon(R.drawable.ic_dialog_keyboard)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setItems(items, listener)
|
||||
.setTitle(title);
|
||||
showOptionDialogInternal(builder.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -498,7 +498,7 @@ public class Settings extends InputMethodSettingsActivity
|
|||
if (pref == mInputLanguageSelection) {
|
||||
startActivity(CompatUtils.getInputLanguageSelectionIntent(
|
||||
Utils.getInputMethodId(
|
||||
InputMethodManagerCompatWrapper.getInstance(getActivityInternal()),
|
||||
InputMethodManagerCompatWrapper.getInstance(),
|
||||
getActivityInternal().getApplicationInfo().packageName), 0));
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ public class SubtypeSwitcher {
|
|||
private void initialize(LatinIME service, SharedPreferences prefs) {
|
||||
mService = service;
|
||||
mResources = service.getResources();
|
||||
mImm = InputMethodManagerCompatWrapper.getInstance(service);
|
||||
mImm = InputMethodManagerCompatWrapper.getInstance();
|
||||
mConnectivityManager = (ConnectivityManager) service.getSystemService(
|
||||
Context.CONNECTIVITY_SERVICE);
|
||||
mEnabledKeyboardSubtypesOfCurrentInputMethod.clear();
|
||||
|
|
Loading…
Reference in a new issue