Search in sources :

Example 21 with InputMethodSubtype

use of android.view.inputmethod.InputMethodSubtype in project android_frameworks_base by DirtyUnicorns.

the class InputMethodManagerService method getCurrentInputMethodSubtypeLocked.

private InputMethodSubtype getCurrentInputMethodSubtypeLocked() {
    if (mCurMethodId == null) {
        return null;
    }
    final boolean subtypeIsSelected = mSettings.isSubtypeSelected();
    final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
    if (imi == null || imi.getSubtypeCount() == 0) {
        return null;
    }
    if (!subtypeIsSelected || mCurrentSubtype == null || !InputMethodUtils.isValidSubtypeId(imi, mCurrentSubtype.hashCode())) {
        int subtypeId = mSettings.getSelectedInputMethodSubtypeId(mCurMethodId);
        if (subtypeId == NOT_A_SUBTYPE_ID) {
            // If there are no selected subtypes, the framework will try to find
            // the most applicable subtype from explicitly or implicitly enabled
            // subtypes.
            List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes = mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
            // just returns it.
            if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) {
                mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0);
            } else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) {
                mCurrentSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(mRes, explicitlyOrImplicitlyEnabledSubtypes, InputMethodUtils.SUBTYPE_MODE_KEYBOARD, null, true);
                if (mCurrentSubtype == null) {
                    mCurrentSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(mRes, explicitlyOrImplicitlyEnabledSubtypes, null, null, true);
                }
            }
        } else {
            mCurrentSubtype = InputMethodUtils.getSubtypes(imi).get(subtypeId);
        }
    }
    return mCurrentSubtype;
}
Also used : InputMethodSubtype(android.view.inputmethod.InputMethodSubtype) InputMethodInfo(android.view.inputmethod.InputMethodInfo)

Example 22 with InputMethodSubtype

use of android.view.inputmethod.InputMethodSubtype in project android_frameworks_base by DirtyUnicorns.

the class InputMethodManagerService method switchToLastInputMethod.

@Override
public boolean switchToLastInputMethod(IBinder token) {
    if (!calledFromValidUser()) {
        return false;
    }
    synchronized (mMethodMap) {
        final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
        final InputMethodInfo lastImi;
        if (lastIme != null) {
            lastImi = mMethodMap.get(lastIme.first);
        } else {
            lastImi = null;
        }
        String targetLastImiId = null;
        int subtypeId = NOT_A_SUBTYPE_ID;
        if (lastIme != null && lastImi != null) {
            final boolean imiIdIsSame = lastImi.getId().equals(mCurMethodId);
            final int lastSubtypeHash = Integer.parseInt(lastIme.second);
            final int currentSubtypeHash = mCurrentSubtype == null ? NOT_A_SUBTYPE_ID : mCurrentSubtype.hashCode();
            // defined, there is no need to switch to the last IME.
            if (!imiIdIsSame || lastSubtypeHash != currentSubtypeHash) {
                targetLastImiId = lastIme.first;
                subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
            }
        }
        if (TextUtils.isEmpty(targetLastImiId) && !InputMethodUtils.canAddToLastInputMethod(mCurrentSubtype)) {
            // This is a safety net. If the currentSubtype can't be added to the history
            // and the framework couldn't find the last ime, we will make the last ime be
            // the most applicable enabled keyboard subtype of the system imes.
            final List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
            if (enabled != null) {
                final int N = enabled.size();
                final String locale = mCurrentSubtype == null ? mRes.getConfiguration().locale.toString() : mCurrentSubtype.getLocale();
                for (int i = 0; i < N; ++i) {
                    final InputMethodInfo imi = enabled.get(i);
                    if (imi.getSubtypeCount() > 0 && InputMethodUtils.isSystemIme(imi)) {
                        InputMethodSubtype keyboardSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(mRes, InputMethodUtils.getSubtypes(imi), InputMethodUtils.SUBTYPE_MODE_KEYBOARD, locale, true);
                        if (keyboardSubtype != null) {
                            targetLastImiId = imi.getId();
                            subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(imi, keyboardSubtype.hashCode());
                            if (keyboardSubtype.getLocale().equals(locale)) {
                                break;
                            }
                        }
                    }
                }
            }
        }
        if (!TextUtils.isEmpty(targetLastImiId)) {
            if (DEBUG) {
                Slog.d(TAG, "Switch to: " + lastImi.getId() + ", " + lastIme.second + ", from: " + mCurMethodId + ", " + subtypeId);
            }
            setInputMethodWithSubtypeIdLocked(token, targetLastImiId, subtypeId);
            return true;
        } else {
            return false;
        }
    }
}
Also used : InputMethodSubtype(android.view.inputmethod.InputMethodSubtype) InputMethodInfo(android.view.inputmethod.InputMethodInfo)

Example 23 with InputMethodSubtype

use of android.view.inputmethod.InputMethodSubtype in project android_frameworks_base by DirtyUnicorns.

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();
    }
}
Also used : AlertDialog(android.app.AlertDialog) DialogInterface(android.content.DialogInterface) InputMethodInfo(android.view.inputmethod.InputMethodInfo) TypedArray(android.content.res.TypedArray) ArrayList(java.util.ArrayList) List(java.util.List) LocaleList(android.os.LocaleList) OnCancelListener(android.content.DialogInterface.OnCancelListener) IInputContext(com.android.internal.view.IInputContext) Context(android.content.Context) InputMethodSubtype(android.view.inputmethod.InputMethodSubtype) OnCheckedChangeListener(android.widget.CompoundButton.OnCheckedChangeListener) Drawable(android.graphics.drawable.Drawable) View(android.view.View) TextView(android.widget.TextView) ImeSubtypeListItem(com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem) ContextThemeWrapper(android.view.ContextThemeWrapper) Switch(android.widget.Switch) LayoutInflater(android.view.LayoutInflater) OnClickListener(android.content.DialogInterface.OnClickListener) CompoundButton(android.widget.CompoundButton)

Example 24 with InputMethodSubtype

use of android.view.inputmethod.InputMethodSubtype in project android_frameworks_base by DirtyUnicorns.

the class InputMethodUtils method getImplicitlyApplicableSubtypesLockedImpl.

private static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLockedImpl(Resources res, InputMethodInfo imi) {
    final List<InputMethodSubtype> subtypes = InputMethodUtils.getSubtypes(imi);
    final LocaleList systemLocales = res.getConfiguration().getLocales();
    final String systemLocale = systemLocales.get(0).toString();
    if (TextUtils.isEmpty(systemLocale))
        return new ArrayList<>();
    final int numSubtypes = subtypes.size();
    // Handle overridesImplicitlyEnabledSubtype mechanism.
    final HashMap<String, InputMethodSubtype> applicableModeAndSubtypesMap = new HashMap<>();
    for (int i = 0; i < numSubtypes; ++i) {
        // scan overriding implicitly enabled subtypes.
        final InputMethodSubtype subtype = subtypes.get(i);
        if (subtype.overridesImplicitlyEnabledSubtype()) {
            final String mode = subtype.getMode();
            if (!applicableModeAndSubtypesMap.containsKey(mode)) {
                applicableModeAndSubtypesMap.put(mode, subtype);
            }
        }
    }
    if (applicableModeAndSubtypesMap.size() > 0) {
        return new ArrayList<>(applicableModeAndSubtypesMap.values());
    }
    final HashMap<String, ArrayList<InputMethodSubtype>> nonKeyboardSubtypesMap = new HashMap<>();
    final ArrayList<InputMethodSubtype> keyboardSubtypes = new ArrayList<>();
    for (int i = 0; i < numSubtypes; ++i) {
        final InputMethodSubtype subtype = subtypes.get(i);
        final String mode = subtype.getMode();
        if (SUBTYPE_MODE_KEYBOARD.equals(mode)) {
            keyboardSubtypes.add(subtype);
        } else {
            if (!nonKeyboardSubtypesMap.containsKey(mode)) {
                nonKeyboardSubtypesMap.put(mode, new ArrayList<>());
            }
            nonKeyboardSubtypesMap.get(mode).add(subtype);
        }
    }
    final ArrayList<InputMethodSubtype> applicableSubtypes = new ArrayList<>();
    LocaleUtils.filterByLanguage(keyboardSubtypes, sSubtypeToLocale, systemLocales, applicableSubtypes);
    if (!applicableSubtypes.isEmpty()) {
        boolean hasAsciiCapableKeyboard = false;
        final int numApplicationSubtypes = applicableSubtypes.size();
        for (int i = 0; i < numApplicationSubtypes; ++i) {
            final InputMethodSubtype subtype = applicableSubtypes.get(i);
            if (subtype.containsExtraValueKey(TAG_ASCII_CAPABLE)) {
                hasAsciiCapableKeyboard = true;
                break;
            }
        }
        if (!hasAsciiCapableKeyboard) {
            final int numKeyboardSubtypes = keyboardSubtypes.size();
            for (int i = 0; i < numKeyboardSubtypes; ++i) {
                final InputMethodSubtype subtype = keyboardSubtypes.get(i);
                final String mode = subtype.getMode();
                if (SUBTYPE_MODE_KEYBOARD.equals(mode) && subtype.containsExtraValueKey(TAG_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)) {
                    applicableSubtypes.add(subtype);
                }
            }
        }
    }
    if (applicableSubtypes.isEmpty()) {
        InputMethodSubtype lastResortKeyboardSubtype = findLastResortApplicableSubtypeLocked(res, subtypes, SUBTYPE_MODE_KEYBOARD, systemLocale, true);
        if (lastResortKeyboardSubtype != null) {
            applicableSubtypes.add(lastResortKeyboardSubtype);
        }
    }
    // For each non-keyboard mode, extract subtypes with system locales.
    for (final ArrayList<InputMethodSubtype> subtypeList : nonKeyboardSubtypesMap.values()) {
        LocaleUtils.filterByLanguage(subtypeList, sSubtypeToLocale, systemLocales, applicableSubtypes);
    }
    return applicableSubtypes;
}
Also used : InputMethodSubtype(android.view.inputmethod.InputMethodSubtype) LocaleList(android.os.LocaleList) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList)

Example 25 with InputMethodSubtype

use of android.view.inputmethod.InputMethodSubtype in project android_frameworks_base by DirtyUnicorns.

the class InputMethodUtils method getImplicitlyApplicableSubtypesLocked.

@VisibleForTesting
public static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLocked(Resources res, InputMethodInfo imi) {
    final LocaleList systemLocales = res.getConfiguration().getLocales();
    synchronized (sCacheLock) {
        // it does not check if subtypes are also identical.
        if (systemLocales.equals(sCachedSystemLocales) && sCachedInputMethodInfo == imi) {
            return new ArrayList<>(sCachedResult);
        }
    }
    // Note: Only resource info in "res" is used in getImplicitlyApplicableSubtypesLockedImpl().
    // TODO: Refactor getImplicitlyApplicableSubtypesLockedImpl() so that it can receive
    // LocaleList rather than Resource.
    final ArrayList<InputMethodSubtype> result = getImplicitlyApplicableSubtypesLockedImpl(res, imi);
    synchronized (sCacheLock) {
        // Both LocaleList and InputMethodInfo are immutable. No need to copy them here.
        sCachedSystemLocales = systemLocales;
        sCachedInputMethodInfo = imi;
        sCachedResult = new ArrayList<>(result);
    }
    return result;
}
Also used : LocaleList(android.os.LocaleList) InputMethodSubtype(android.view.inputmethod.InputMethodSubtype) ArrayList(java.util.ArrayList) VisibleForTesting(com.android.internal.annotations.VisibleForTesting)

Aggregations

InputMethodSubtype (android.view.inputmethod.InputMethodSubtype)195 InputMethodInfo (android.view.inputmethod.InputMethodInfo)92 ArrayList (java.util.ArrayList)48 Locale (java.util.Locale)17 LocaleList (android.os.LocaleList)15 ImeSubtypeListItem (com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem)15 InputMethodManager (android.view.inputmethod.InputMethodManager)14 Context (android.content.Context)12 SmallTest (android.test.suitebuilder.annotation.SmallTest)10 View (android.view.View)9 TextView (android.widget.TextView)9 RichInputMethodSubtype (com.android.inputmethod.latin.RichInputMethodSubtype)8 List (java.util.List)8 Intent (android.content.Intent)7 Pair (android.util.Pair)7 AlertDialog (android.app.AlertDialog)6 PendingIntent (android.app.PendingIntent)6 DialogInterface (android.content.DialogInterface)6 OnCancelListener (android.content.DialogInterface.OnCancelListener)6 TypedArray (android.content.res.TypedArray)6