use of com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem in project platform_frameworks_base by android.
the class InputMethodManagerService method switchToNextInputMethod.
@Override
public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
if (!calledFromValidUser()) {
return false;
}
synchronized (mMethodMap) {
if (!calledWithValidToken(token)) {
final int uid = Binder.getCallingUid();
Slog.e(TAG, "Ignoring switchToNextInputMethod due to an invalid token. uid:" + uid + " token:" + token);
return false;
}
final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype, true);
if (nextSubtype == null) {
return false;
}
setInputMethodWithSubtypeIdLocked(token, nextSubtype.mImi.getId(), nextSubtype.mSubtypeId);
return true;
}
}
use of com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem in project platform_frameworks_base by android.
the class InputMethodManagerService method showInputMethodMenu.
private void showInputMethodMenu(boolean showAuxSubtypes) {
if (DEBUG)
Slog.v(TAG, "Show switching menu. showAuxSubtypes=" + showAuxSubtypes);
final Context context = mContext;
final boolean isScreenLocked = isScreenLocked();
final String lastInputMethodId = mSettings.getSelectedInputMethod();
int lastInputMethodSubtypeId = mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId);
if (DEBUG)
Slog.v(TAG, "Current IME: " + lastInputMethodId);
synchronized (mMethodMap) {
final HashMap<InputMethodInfo, List<InputMethodSubtype>> immis = mSettings.getExplicitlyOrImplicitlyEnabledInputMethodsAndSubtypeListLocked(mContext);
if (immis == null || immis.size() == 0) {
return;
}
hideInputMethodMenuLocked();
final List<ImeSubtypeListItem> imList = mSwitchingController.getSortedInputMethodAndSubtypeListLocked(showAuxSubtypes, isScreenLocked);
if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked();
if (currentSubtype != null) {
final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
lastInputMethodSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode(currentImi, currentSubtype.hashCode());
}
}
final int N = imList.size();
mIms = new InputMethodInfo[N];
mSubtypeIds = new int[N];
int checkedItem = 0;
for (int i = 0; i < N; ++i) {
final ImeSubtypeListItem item = imList.get(i);
mIms[i] = item.mImi;
mSubtypeIds[i] = item.mSubtypeId;
if (mIms[i].getId().equals(lastInputMethodId)) {
int subtypeId = mSubtypeIds[i];
if ((subtypeId == NOT_A_SUBTYPE_ID) || (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID && subtypeId == 0) || (subtypeId == lastInputMethodSubtypeId)) {
checkedItem = i;
}
}
}
final Context settingsContext = new ContextThemeWrapper(context, com.android.internal.R.style.Theme_DeviceDefault_Settings);
mDialogBuilder = new AlertDialog.Builder(settingsContext);
mDialogBuilder.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
hideInputMethodMenu();
}
});
final Context dialogContext = mDialogBuilder.getContext();
final TypedArray a = dialogContext.obtainStyledAttributes(null, com.android.internal.R.styleable.DialogPreference, com.android.internal.R.attr.alertDialogStyle, 0);
final Drawable dialogIcon = a.getDrawable(com.android.internal.R.styleable.DialogPreference_dialogIcon);
a.recycle();
mDialogBuilder.setIcon(dialogIcon);
final LayoutInflater inflater = dialogContext.getSystemService(LayoutInflater.class);
final View tv = inflater.inflate(com.android.internal.R.layout.input_method_switch_dialog_title, null);
mDialogBuilder.setCustomTitle(tv);
// Setup layout for a toggle switch of the hardware keyboard
mSwitchingDialogTitleView = tv;
mSwitchingDialogTitleView.findViewById(com.android.internal.R.id.hard_keyboard_section).setVisibility(mWindowManagerInternal.isHardKeyboardAvailable() ? View.VISIBLE : View.GONE);
final Switch hardKeySwitch = (Switch) mSwitchingDialogTitleView.findViewById(com.android.internal.R.id.hard_keyboard_switch);
hardKeySwitch.setChecked(mShowImeWithHardKeyboard);
hardKeySwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mSettings.setShowImeWithHardKeyboard(isChecked);
// Ensure that the input method dialog is dismissed when changing
// the hardware keyboard state.
hideInputMethodMenu();
}
});
final ImeSubtypeListAdapter adapter = new ImeSubtypeListAdapter(dialogContext, com.android.internal.R.layout.input_method_switch_item, imList, checkedItem);
final OnClickListener choiceListener = new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
synchronized (mMethodMap) {
if (mIms == null || mIms.length <= which || mSubtypeIds == null || mSubtypeIds.length <= which) {
return;
}
final InputMethodInfo im = mIms[which];
int subtypeId = mSubtypeIds[which];
adapter.mCheckedItem = which;
adapter.notifyDataSetChanged();
hideInputMethodMenu();
if (im != null) {
if (subtypeId < 0 || subtypeId >= im.getSubtypeCount()) {
subtypeId = NOT_A_SUBTYPE_ID;
}
setInputMethodLocked(im.getId(), subtypeId);
}
}
}
};
mDialogBuilder.setSingleChoiceItems(adapter, checkedItem, choiceListener);
mSwitchingDialog = mDialogBuilder.create();
mSwitchingDialog.setCanceledOnTouchOutside(true);
mSwitchingDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
mSwitchingDialog.getWindow().getAttributes().privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
mSwitchingDialog.getWindow().getAttributes().setTitle("Select input method");
updateSystemUi(mCurToken, mImeWindowVis, mBackDisposition);
mSwitchingDialog.show();
}
}
use of com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem in project platform_frameworks_base by android.
the class InputMethodSubtypeSwitchingControllerTest method assertRotationOrder.
private void assertRotationOrder(final ControllerImpl controller, final boolean onlyCurrentIme, final ImeSubtypeListItem... expectedRotationOrderOfImeSubtypeList) {
final int N = expectedRotationOrderOfImeSubtypeList.length;
for (int i = 0; i < N; i++) {
final int currentIndex = i;
final int prevIndex = (currentIndex + N - 1) % N;
final int nextIndex = (currentIndex + 1) % N;
final ImeSubtypeListItem currentItem = expectedRotationOrderOfImeSubtypeList[currentIndex];
final ImeSubtypeListItem nextItem = expectedRotationOrderOfImeSubtypeList[nextIndex];
final ImeSubtypeListItem prevItem = expectedRotationOrderOfImeSubtypeList[prevIndex];
assertNextInputMethod(controller, onlyCurrentIme, currentItem, nextItem, prevItem);
}
}
use of com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem in project platform_frameworks_base by android.
the class InputMethodSubtypeSwitchingControllerTest method testControllerImpl.
@SmallTest
public void testControllerImpl() throws Exception {
final List<ImeSubtypeListItem> disabledItems = createDisabledImeSubtypes();
final ImeSubtypeListItem disabledIme_en_US = disabledItems.get(0);
final ImeSubtypeListItem disabledIme_hi = disabledItems.get(1);
final ImeSubtypeListItem disabledSwitchingUnawareIme = disabledItems.get(2);
final ImeSubtypeListItem disabledSubtypeUnawareIme = disabledItems.get(3);
final List<ImeSubtypeListItem> enabledItems = createEnabledImeSubtypes();
final ImeSubtypeListItem latinIme_en_US = enabledItems.get(0);
final ImeSubtypeListItem latinIme_fr = enabledItems.get(1);
final ImeSubtypeListItem switchingUnawarelatinIme_en_UK = enabledItems.get(2);
final ImeSubtypeListItem switchingUnawarelatinIme_hi = enabledItems.get(3);
final ImeSubtypeListItem subtypeUnawareIme = enabledItems.get(4);
final ImeSubtypeListItem japaneseIme_ja_JP = enabledItems.get(5);
final ImeSubtypeListItem switchUnawareJapaneseIme_ja_JP = enabledItems.get(6);
final ControllerImpl controller = ControllerImpl.createFrom(null, /* currentInstance */
enabledItems);
// switching-aware loop
assertRotationOrder(controller, false, /* onlyCurrentIme */
latinIme_en_US, latinIme_fr, japaneseIme_ja_JP);
// switching-unaware loop
assertRotationOrder(controller, false, /* onlyCurrentIme */
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi, subtypeUnawareIme, switchUnawareJapaneseIme_ja_JP);
// test onlyCurrentIme == true
assertRotationOrder(controller, true, /* onlyCurrentIme */
latinIme_en_US, latinIme_fr);
assertRotationOrder(controller, true, /* onlyCurrentIme */
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi);
assertNextInputMethod(controller, true, /* onlyCurrentIme */
subtypeUnawareIme, null, null);
assertNextInputMethod(controller, true, /* onlyCurrentIme */
japaneseIme_ja_JP, null, null);
assertNextInputMethod(controller, true, /* onlyCurrentIme */
switchUnawareJapaneseIme_ja_JP, null, null);
// Make sure that disabled IMEs are not accepted.
assertNextInputMethod(controller, false, /* onlyCurrentIme */
disabledIme_en_US, null, null);
assertNextInputMethod(controller, false, /* onlyCurrentIme */
disabledIme_hi, null, null);
assertNextInputMethod(controller, false, /* onlyCurrentIme */
disabledSwitchingUnawareIme, null, null);
assertNextInputMethod(controller, false, /* onlyCurrentIme */
disabledSubtypeUnawareIme, null, null);
assertNextInputMethod(controller, true, /* onlyCurrentIme */
disabledIme_en_US, null, null);
assertNextInputMethod(controller, true, /* onlyCurrentIme */
disabledIme_hi, null, null);
assertNextInputMethod(controller, true, /* onlyCurrentIme */
disabledSwitchingUnawareIme, null, null);
assertNextInputMethod(controller, true, /* onlyCurrentIme */
disabledSubtypeUnawareIme, null, null);
}
use of com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem in project platform_frameworks_base by android.
the class InputMethodSubtypeSwitchingControllerTest method testControllerImplWithUserAction.
@SmallTest
public void testControllerImplWithUserAction() throws Exception {
final List<ImeSubtypeListItem> enabledItems = createEnabledImeSubtypes();
final ImeSubtypeListItem latinIme_en_US = enabledItems.get(0);
final ImeSubtypeListItem latinIme_fr = enabledItems.get(1);
final ImeSubtypeListItem switchingUnawarelatinIme_en_UK = enabledItems.get(2);
final ImeSubtypeListItem switchingUnawarelatinIme_hi = enabledItems.get(3);
final ImeSubtypeListItem subtypeUnawareIme = enabledItems.get(4);
final ImeSubtypeListItem japaneseIme_ja_JP = enabledItems.get(5);
final ImeSubtypeListItem switchUnawareJapaneseIme_ja_JP = enabledItems.get(6);
final ControllerImpl controller = ControllerImpl.createFrom(null, /* currentInstance */
enabledItems);
// === switching-aware loop ===
assertRotationOrder(controller, false, /* onlyCurrentIme */
latinIme_en_US, latinIme_fr, japaneseIme_ja_JP);
// Then notify that a user did something for latinIme_fr.
onUserAction(controller, latinIme_fr);
assertRotationOrder(controller, false, /* onlyCurrentIme */
latinIme_fr, latinIme_en_US, japaneseIme_ja_JP);
// Then notify that a user did something for latinIme_fr again.
onUserAction(controller, latinIme_fr);
assertRotationOrder(controller, false, /* onlyCurrentIme */
latinIme_fr, latinIme_en_US, japaneseIme_ja_JP);
// Then notify that a user did something for japaneseIme_ja_JP.
onUserAction(controller, latinIme_fr);
assertRotationOrder(controller, false, /* onlyCurrentIme */
japaneseIme_ja_JP, latinIme_fr, latinIme_en_US);
// Check onlyCurrentIme == true.
assertNextInputMethod(controller, true, /* onlyCurrentIme */
japaneseIme_ja_JP, null, null);
assertRotationOrder(controller, true, /* onlyCurrentIme */
latinIme_fr, latinIme_en_US);
assertRotationOrder(controller, true, /* onlyCurrentIme */
latinIme_en_US, latinIme_fr);
// === switching-unaware loop ===
assertRotationOrder(controller, false, /* onlyCurrentIme */
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi, subtypeUnawareIme, switchUnawareJapaneseIme_ja_JP);
// User action should be ignored for switching unaware IMEs.
onUserAction(controller, switchingUnawarelatinIme_hi);
assertRotationOrder(controller, false, /* onlyCurrentIme */
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi, subtypeUnawareIme, switchUnawareJapaneseIme_ja_JP);
// User action should be ignored for switching unaware IMEs.
onUserAction(controller, switchUnawareJapaneseIme_ja_JP);
assertRotationOrder(controller, false, /* onlyCurrentIme */
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi, subtypeUnawareIme, switchUnawareJapaneseIme_ja_JP);
// Check onlyCurrentIme == true.
assertRotationOrder(controller, true, /* onlyCurrentIme */
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi);
assertNextInputMethod(controller, true, /* onlyCurrentIme */
subtypeUnawareIme, null, null);
assertNextInputMethod(controller, true, /* onlyCurrentIme */
switchUnawareJapaneseIme_ja_JP, null, null);
// Rotation order should be preserved when created with the same subtype list.
final List<ImeSubtypeListItem> sameEnabledItems = createEnabledImeSubtypes();
final ControllerImpl newController = ControllerImpl.createFrom(controller, sameEnabledItems);
assertRotationOrder(newController, false, /* onlyCurrentIme */
japaneseIme_ja_JP, latinIme_fr, latinIme_en_US);
assertRotationOrder(newController, false, /* onlyCurrentIme */
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi, subtypeUnawareIme, switchUnawareJapaneseIme_ja_JP);
// Rotation order should be initialized when created with a different subtype list.
final List<ImeSubtypeListItem> differentEnabledItems = Arrays.asList(latinIme_en_US, latinIme_fr, switchingUnawarelatinIme_en_UK, switchUnawareJapaneseIme_ja_JP);
final ControllerImpl anotherController = ControllerImpl.createFrom(controller, differentEnabledItems);
assertRotationOrder(anotherController, false, /* onlyCurrentIme */
latinIme_en_US, latinIme_fr);
assertRotationOrder(anotherController, false, /* onlyCurrentIme */
switchingUnawarelatinIme_en_UK, switchUnawareJapaneseIme_ja_JP);
}
Aggregations