Move some methods out from SubtypeSwitcher
Change-Id: I89aaf87d7d0cc204b0ca0f61c2f64d15e2df848emain
parent
e1652d7570
commit
2a7da0ab87
|
@ -26,6 +26,8 @@ import com.android.inputmethod.latin.common.Constants;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public final class InputMethodSubtypeCompatUtils {
|
public final class InputMethodSubtypeCompatUtils {
|
||||||
private static final String TAG = InputMethodSubtypeCompatUtils.class.getSimpleName();
|
private static final String TAG = InputMethodSubtypeCompatUtils.class.getSimpleName();
|
||||||
// Note that InputMethodSubtype(int nameId, int iconId, String locale, String mode,
|
// Note that InputMethodSubtype(int nameId, int iconId, String locale, String mode,
|
||||||
|
@ -53,6 +55,7 @@ public final class InputMethodSubtypeCompatUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
|
@Nonnull
|
||||||
public static InputMethodSubtype newInputMethodSubtype(int nameId, int iconId, String locale,
|
public static InputMethodSubtype newInputMethodSubtype(int nameId, int iconId, String locale,
|
||||||
String mode, String extraValue, boolean isAuxiliary,
|
String mode, String extraValue, boolean isAuxiliary,
|
||||||
boolean overridesImplicitlyEnabledSubtype, int id) {
|
boolean overridesImplicitlyEnabledSubtype, int id) {
|
||||||
|
|
|
@ -38,7 +38,6 @@ import com.android.inputmethod.keyboard.internal.KeysCache;
|
||||||
import com.android.inputmethod.latin.InputAttributes;
|
import com.android.inputmethod.latin.InputAttributes;
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.RichInputMethodSubtype;
|
import com.android.inputmethod.latin.RichInputMethodSubtype;
|
||||||
import com.android.inputmethod.latin.SubtypeSwitcher;
|
|
||||||
import com.android.inputmethod.latin.define.DebugFlags;
|
import com.android.inputmethod.latin.define.DebugFlags;
|
||||||
import com.android.inputmethod.latin.utils.InputTypeUtils;
|
import com.android.inputmethod.latin.utils.InputTypeUtils;
|
||||||
import com.android.inputmethod.latin.utils.ScriptUtils;
|
import com.android.inputmethod.latin.utils.ScriptUtils;
|
||||||
|
@ -276,7 +275,7 @@ public final class KeyboardLayoutSet {
|
||||||
mParams.mEditorInfo.imeOptions)
|
mParams.mEditorInfo.imeOptions)
|
||||||
|| deprecatedForceAscii;
|
|| deprecatedForceAscii;
|
||||||
final RichInputMethodSubtype keyboardSubtype = (forceAscii && !asciiCapable)
|
final RichInputMethodSubtype keyboardSubtype = (forceAscii && !asciiCapable)
|
||||||
? SubtypeSwitcher.getInstance().getNoLanguageSubtype()
|
? RichInputMethodSubtype.getNoLanguageSubtype()
|
||||||
: subtype;
|
: subtype;
|
||||||
mParams.mSubtype = keyboardSubtype;
|
mParams.mSubtype = keyboardSubtype;
|
||||||
mParams.mKeyboardLayoutSetName = KEYBOARD_LAYOUT_SET_RESOURCE_PREFIX
|
mParams.mKeyboardLayoutSetName = KEYBOARD_LAYOUT_SET_RESOURCE_PREFIX
|
||||||
|
|
|
@ -48,7 +48,7 @@ import com.android.inputmethod.keyboard.internal.KeyVisualAttributes;
|
||||||
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
|
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
|
||||||
import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
|
import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.SubtypeSwitcher;
|
import com.android.inputmethod.latin.RichInputMethodSubtype;
|
||||||
import com.android.inputmethod.latin.common.Constants;
|
import com.android.inputmethod.latin.common.Constants;
|
||||||
import com.android.inputmethod.latin.utils.ResourceUtils;
|
import com.android.inputmethod.latin.utils.ResourceUtils;
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
|
||||||
context, null /* editorInfo */);
|
context, null /* editorInfo */);
|
||||||
final Resources res = context.getResources();
|
final Resources res = context.getResources();
|
||||||
mEmojiLayoutParams = new EmojiLayoutParams(res);
|
mEmojiLayoutParams = new EmojiLayoutParams(res);
|
||||||
builder.setSubtype(SubtypeSwitcher.getInstance().getEmojiSubtype());
|
builder.setSubtype(RichInputMethodSubtype.getEmojiSubtype());
|
||||||
builder.setKeyboardGeometry(ResourceUtils.getDefaultKeyboardWidth(res),
|
builder.setKeyboardGeometry(ResourceUtils.getDefaultKeyboardWidth(res),
|
||||||
mEmojiLayoutParams.mEmojiKeyboardHeight);
|
mEmojiLayoutParams.mEmojiKeyboardHeight);
|
||||||
final KeyboardLayoutSet layoutSet = builder.build();
|
final KeyboardLayoutSet layoutSet = builder.build();
|
||||||
|
|
|
@ -626,7 +626,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
private void refreshPersonalizationDictionarySession(
|
private void refreshPersonalizationDictionarySession(
|
||||||
final SettingsValues currentSettingsValues) {
|
final SettingsValues currentSettingsValues) {
|
||||||
mDictionaryFacilitator.setIsMonolingualUser(
|
mDictionaryFacilitator.setIsMonolingualUser(
|
||||||
mSubtypeSwitcher.isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes());
|
mRichImm.isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes());
|
||||||
mPersonalizationDictionaryUpdater.onLoadSettings(
|
mPersonalizationDictionaryUpdater.onLoadSettings(
|
||||||
currentSettingsValues.mUsePersonalizedDicts);
|
currentSettingsValues.mUsePersonalizedDicts);
|
||||||
mContextualDictionaryUpdater.onLoadSettings(currentSettingsValues.mUsePersonalizedDicts);
|
mContextualDictionaryUpdater.onLoadSettings(currentSettingsValues.mUsePersonalizedDicts);
|
||||||
|
@ -863,7 +863,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
// also wouldn't be consuming gesture data.
|
// also wouldn't be consuming gesture data.
|
||||||
mGestureConsumer = GestureConsumer.NULL_GESTURE_CONSUMER;
|
mGestureConsumer = GestureConsumer.NULL_GESTURE_CONSUMER;
|
||||||
mRichImm.clearSubtypeCaches();
|
mRichImm.clearSubtypeCaches();
|
||||||
mSubtypeSwitcher.refreshSubtypeInfo();
|
mSubtypeSwitcher.onSubtypeChanged(mRichImm.getCurrentRawSubtype());
|
||||||
final KeyboardSwitcher switcher = mKeyboardSwitcher;
|
final KeyboardSwitcher switcher = mKeyboardSwitcher;
|
||||||
switcher.updateKeyboardTheme();
|
switcher.updateKeyboardTheme();
|
||||||
final MainKeyboardView mainKeyboardView = switcher.getMainKeyboardView();
|
final MainKeyboardView mainKeyboardView = switcher.getMainKeyboardView();
|
||||||
|
|
|
@ -29,6 +29,8 @@ import android.view.inputmethod.InputMethodManager;
|
||||||
import android.view.inputmethod.InputMethodSubtype;
|
import android.view.inputmethod.InputMethodSubtype;
|
||||||
|
|
||||||
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
|
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
|
||||||
|
import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
|
||||||
|
import com.android.inputmethod.latin.common.Constants;
|
||||||
import com.android.inputmethod.latin.settings.AdditionalFeaturesSettingUtils;
|
import com.android.inputmethod.latin.settings.AdditionalFeaturesSettingUtils;
|
||||||
import com.android.inputmethod.latin.settings.Settings;
|
import com.android.inputmethod.latin.settings.Settings;
|
||||||
import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
|
import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
|
||||||
|
@ -36,7 +38,10 @@ import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
@ -432,4 +437,29 @@ public class RichInputMethodManager {
|
||||||
}
|
}
|
||||||
return mImmWrapper.shouldOfferSwitchingToNextInputMethod(binder);
|
return mImmWrapper.shouldOfferSwitchingToNextInputMethod(binder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes() {
|
||||||
|
final Locale systemLocale = mContext.getResources().getConfiguration().locale;
|
||||||
|
final Set<InputMethodSubtype> enabledSubtypesOfEnabledImes = new HashSet<>();
|
||||||
|
final InputMethodManager inputMethodManager = getInputMethodManager();
|
||||||
|
final List<InputMethodInfo> enabledInputMethodInfoList =
|
||||||
|
inputMethodManager.getEnabledInputMethodList();
|
||||||
|
for (final InputMethodInfo info : enabledInputMethodInfoList) {
|
||||||
|
final List<InputMethodSubtype> enabledSubtypes =
|
||||||
|
inputMethodManager.getEnabledInputMethodSubtypeList(
|
||||||
|
info, true /* allowsImplicitlySelectedSubtypes */);
|
||||||
|
if (enabledSubtypes.isEmpty()) {
|
||||||
|
// An IME with no subtypes is found.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
enabledSubtypesOfEnabledImes.addAll(enabledSubtypes);
|
||||||
|
}
|
||||||
|
for (final InputMethodSubtype subtype : enabledSubtypesOfEnabledImes) {
|
||||||
|
if (!subtype.isAuxiliary() && !subtype.getLocale().isEmpty()
|
||||||
|
&& !systemLocale.equals(SubtypeLocaleUtils.getSubtypeLocale(subtype))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,33 +16,45 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
|
import static com.android.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
import android.view.inputmethod.InputMethodSubtype;
|
import android.view.inputmethod.InputMethodSubtype;
|
||||||
|
|
||||||
|
import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
|
||||||
|
import com.android.inputmethod.latin.common.Constants;
|
||||||
import com.android.inputmethod.latin.utils.LocaleUtils;
|
import com.android.inputmethod.latin.utils.LocaleUtils;
|
||||||
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enrichment class for InputMethodSubtype to enable concurrent multi-lingual input.
|
* Enrichment class for InputMethodSubtype to enable concurrent multi-lingual input.
|
||||||
*
|
*
|
||||||
* Right now, this returns the extra value of its primary subtype.
|
* Right now, this returns the extra value of its primary subtype.
|
||||||
*/
|
*/
|
||||||
public final class RichInputMethodSubtype {
|
public final class RichInputMethodSubtype {
|
||||||
|
private static final String TAG = RichInputMethodSubtype.class.getSimpleName();
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
private final InputMethodSubtype mSubtype;
|
private final InputMethodSubtype mSubtype;
|
||||||
|
@Nonnull
|
||||||
private final Locale[] mLocales;
|
private final Locale[] mLocales;
|
||||||
|
|
||||||
public RichInputMethodSubtype(final InputMethodSubtype subtype, final Locale... locales) {
|
public RichInputMethodSubtype(@Nonnull final InputMethodSubtype subtype,
|
||||||
|
@Nonnull final Locale... locales) {
|
||||||
mSubtype = subtype;
|
mSubtype = subtype;
|
||||||
mLocales = new Locale[locales.length+1];
|
mLocales = new Locale[locales.length + 1];
|
||||||
mLocales[0] = LocaleUtils.constructLocaleFromString(mSubtype.getLocale());
|
mLocales[0] = LocaleUtils.constructLocaleFromString(mSubtype.getLocale());
|
||||||
System.arraycopy(locales, 0, mLocales, 1, locales.length);
|
System.arraycopy(locales, 0, mLocales, 1, locales.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extra values are determined by the primary subtype. This is probably right, but
|
// Extra values are determined by the primary subtype. This is probably right, but
|
||||||
// we may have to revisit this later.
|
// we may have to revisit this later.
|
||||||
public String getExtraValueOf(final String key) {
|
public String getExtraValueOf(@Nonnull final String key) {
|
||||||
return mSubtype.getExtraValueOf(key);
|
return mSubtype.getExtraValueOf(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +92,7 @@ public final class RichInputMethodSubtype {
|
||||||
// en_US azerty T English English (US)
|
// en_US azerty T English English (US)
|
||||||
// zz azerty T AZERTY AZERTY
|
// zz azerty T AZERTY AZERTY
|
||||||
// Get the RichInputMethodSubtype's full display name in its locale.
|
// Get the RichInputMethodSubtype's full display name in its locale.
|
||||||
|
@Nonnull
|
||||||
public String getFullDisplayName() {
|
public String getFullDisplayName() {
|
||||||
if (isNoLanguage()) {
|
if (isNoLanguage()) {
|
||||||
return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(mSubtype);
|
return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(mSubtype);
|
||||||
|
@ -88,6 +101,7 @@ public final class RichInputMethodSubtype {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the RichInputMethodSubtype's middle display name in its locale.
|
// Get the RichInputMethodSubtype's middle display name in its locale.
|
||||||
|
@Nonnull
|
||||||
public String getMiddleDisplayName() {
|
public String getMiddleDisplayName() {
|
||||||
if (isNoLanguage()) {
|
if (isNoLanguage()) {
|
||||||
return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(mSubtype);
|
return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(mSubtype);
|
||||||
|
@ -96,7 +110,7 @@ public final class RichInputMethodSubtype {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(final Object o) {
|
||||||
if (!(o instanceof RichInputMethodSubtype)) {
|
if (!(o instanceof RichInputMethodSubtype)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -114,6 +128,7 @@ public final class RichInputMethodSubtype {
|
||||||
return "Multi-lingual subtype: " + mSubtype.toString() + ", " + Arrays.toString(mLocales);
|
return "Multi-lingual subtype: " + mSubtype.toString() + ", " + Arrays.toString(mLocales);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public Locale[] getLocales() {
|
public Locale[] getLocales() {
|
||||||
return mLocales;
|
return mLocales;
|
||||||
}
|
}
|
||||||
|
@ -124,5 +139,80 @@ public final class RichInputMethodSubtype {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove this method
|
// TODO: remove this method
|
||||||
|
@Nonnull
|
||||||
public InputMethodSubtype getRawSubtype() { return mSubtype; }
|
public InputMethodSubtype getRawSubtype() { return mSubtype; }
|
||||||
|
|
||||||
|
// Dummy no language QWERTY subtype. See {@link R.xml.method}.
|
||||||
|
private static final int SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE = 0xdde0bfd3;
|
||||||
|
private static final String EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE =
|
||||||
|
"KeyboardLayoutSet=" + SubtypeLocaleUtils.QWERTY
|
||||||
|
+ "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE
|
||||||
|
+ "," + Constants.Subtype.ExtraValue.ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE
|
||||||
|
+ "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
|
||||||
|
@Nonnull
|
||||||
|
private static final RichInputMethodSubtype DUMMY_NO_LANGUAGE_SUBTYPE =
|
||||||
|
new RichInputMethodSubtype(InputMethodSubtypeCompatUtils.newInputMethodSubtype(
|
||||||
|
R.string.subtype_no_language_qwerty, R.drawable.ic_ime_switcher_dark,
|
||||||
|
SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
|
||||||
|
EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE,
|
||||||
|
false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
|
||||||
|
SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE));
|
||||||
|
// Caveat: We probably should remove this when we add an Emoji subtype in {@link R.xml.method}.
|
||||||
|
// Dummy Emoji subtype. See {@link R.xml.method}.
|
||||||
|
private static final int SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE = 0xd78b2ed0;
|
||||||
|
private static final String EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE =
|
||||||
|
"KeyboardLayoutSet=" + SubtypeLocaleUtils.EMOJI
|
||||||
|
+ "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
|
||||||
|
@Nonnull
|
||||||
|
private static final RichInputMethodSubtype DUMMY_EMOJI_SUBTYPE = new RichInputMethodSubtype(
|
||||||
|
InputMethodSubtypeCompatUtils.newInputMethodSubtype(
|
||||||
|
R.string.subtype_emoji, R.drawable.ic_ime_switcher_dark,
|
||||||
|
SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
|
||||||
|
EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE,
|
||||||
|
false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
|
||||||
|
SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE));
|
||||||
|
private static RichInputMethodSubtype sNoLanguageSubtype;
|
||||||
|
private static RichInputMethodSubtype sEmojiSubtype;
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public static RichInputMethodSubtype getNoLanguageSubtype() {
|
||||||
|
RichInputMethodSubtype noLanguageSubtype = sNoLanguageSubtype;
|
||||||
|
if (noLanguageSubtype == null) {
|
||||||
|
final InputMethodSubtype rawNoLanguageSubtype = RichInputMethodManager.getInstance()
|
||||||
|
.findSubtypeByLocaleAndKeyboardLayoutSet(
|
||||||
|
SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.QWERTY);
|
||||||
|
if (rawNoLanguageSubtype != null) {
|
||||||
|
noLanguageSubtype = new RichInputMethodSubtype(rawNoLanguageSubtype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (noLanguageSubtype != null) {
|
||||||
|
sNoLanguageSubtype = noLanguageSubtype;
|
||||||
|
return noLanguageSubtype;
|
||||||
|
}
|
||||||
|
Log.w(TAG, "Can't find any language with QWERTY subtype");
|
||||||
|
Log.w(TAG, "No input method subtype found; returning dummy subtype: "
|
||||||
|
+ DUMMY_NO_LANGUAGE_SUBTYPE);
|
||||||
|
return DUMMY_NO_LANGUAGE_SUBTYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public static RichInputMethodSubtype getEmojiSubtype() {
|
||||||
|
RichInputMethodSubtype emojiSubtype = sEmojiSubtype;
|
||||||
|
if (emojiSubtype == null) {
|
||||||
|
final InputMethodSubtype rawEmojiSubtype = RichInputMethodManager.getInstance()
|
||||||
|
.findSubtypeByLocaleAndKeyboardLayoutSet(
|
||||||
|
SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.EMOJI);
|
||||||
|
if (rawEmojiSubtype != null) {
|
||||||
|
emojiSubtype = new RichInputMethodSubtype(rawEmojiSubtype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (emojiSubtype != null) {
|
||||||
|
sEmojiSubtype = emojiSubtype;
|
||||||
|
return emojiSubtype;
|
||||||
|
}
|
||||||
|
Log.w(TAG, "Can't find emoji subtype");
|
||||||
|
Log.w(TAG, "No input method subtype found; returning dummy subtype: "
|
||||||
|
+ DUMMY_EMOJI_SUBTYPE);
|
||||||
|
return DUMMY_EMOJI_SUBTYPE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.REQ_NETWORK_CONNECTIVITY;
|
import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.REQ_NETWORK_CONNECTIVITY;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
@ -31,18 +32,14 @@ import android.view.inputmethod.InputMethodManager;
|
||||||
import android.view.inputmethod.InputMethodSubtype;
|
import android.view.inputmethod.InputMethodSubtype;
|
||||||
|
|
||||||
import com.android.inputmethod.annotations.UsedForTesting;
|
import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
|
|
||||||
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
||||||
import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper;
|
import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper;
|
||||||
import com.android.inputmethod.latin.common.Constants;
|
|
||||||
import com.android.inputmethod.latin.define.DebugFlags;
|
import com.android.inputmethod.latin.define.DebugFlags;
|
||||||
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
@ -60,39 +57,8 @@ public final class SubtypeSwitcher {
|
||||||
private InputMethodInfo mShortcutInputMethodInfo;
|
private InputMethodInfo mShortcutInputMethodInfo;
|
||||||
private InputMethodSubtype mShortcutSubtype;
|
private InputMethodSubtype mShortcutSubtype;
|
||||||
private RichInputMethodSubtype mCurrentRichInputMethodSubtype;
|
private RichInputMethodSubtype mCurrentRichInputMethodSubtype;
|
||||||
private RichInputMethodSubtype mNoLanguageSubtype;
|
|
||||||
private RichInputMethodSubtype mEmojiSubtype;
|
|
||||||
private boolean mIsNetworkConnected;
|
private boolean mIsNetworkConnected;
|
||||||
|
|
||||||
private static final String KEYBOARD_MODE = "keyboard";
|
|
||||||
// Dummy no language QWERTY subtype. See {@link R.xml.method}.
|
|
||||||
private static final int SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE = 0xdde0bfd3;
|
|
||||||
private static final String EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE =
|
|
||||||
"KeyboardLayoutSet=" + SubtypeLocaleUtils.QWERTY
|
|
||||||
+ "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE
|
|
||||||
+ "," + Constants.Subtype.ExtraValue.ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE
|
|
||||||
+ "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
|
|
||||||
private static final RichInputMethodSubtype DUMMY_NO_LANGUAGE_SUBTYPE =
|
|
||||||
new RichInputMethodSubtype(InputMethodSubtypeCompatUtils.newInputMethodSubtype(
|
|
||||||
R.string.subtype_no_language_qwerty, R.drawable.ic_ime_switcher_dark,
|
|
||||||
SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
|
|
||||||
EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE,
|
|
||||||
false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
|
|
||||||
SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE));
|
|
||||||
// Caveat: We probably should remove this when we add an Emoji subtype in {@link R.xml.method}.
|
|
||||||
// Dummy Emoji subtype. See {@link R.xml.method}.
|
|
||||||
private static final int SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE = 0xd78b2ed0;
|
|
||||||
private static final String EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE =
|
|
||||||
"KeyboardLayoutSet=" + SubtypeLocaleUtils.EMOJI
|
|
||||||
+ "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
|
|
||||||
private static final RichInputMethodSubtype DUMMY_EMOJI_SUBTYPE = new RichInputMethodSubtype(
|
|
||||||
InputMethodSubtypeCompatUtils.newInputMethodSubtype(
|
|
||||||
R.string.subtype_emoji, R.drawable.ic_ime_switcher_dark,
|
|
||||||
SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
|
|
||||||
EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE,
|
|
||||||
false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
|
|
||||||
SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE));
|
|
||||||
|
|
||||||
public static SubtypeSwitcher getInstance() {
|
public static SubtypeSwitcher getInstance() {
|
||||||
return sInstance;
|
return sInstance;
|
||||||
}
|
}
|
||||||
|
@ -119,12 +85,8 @@ public final class SubtypeSwitcher {
|
||||||
final NetworkInfo info = connectivityManager.getActiveNetworkInfo();
|
final NetworkInfo info = connectivityManager.getActiveNetworkInfo();
|
||||||
mIsNetworkConnected = (info != null && info.isConnected());
|
mIsNetworkConnected = (info != null && info.isConnected());
|
||||||
|
|
||||||
refreshSubtypeInfo();
|
|
||||||
updateParametersOnStartInputView();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void refreshSubtypeInfo() {
|
|
||||||
onSubtypeChanged(mRichImm.getCurrentRawSubtype());
|
onSubtypeChanged(mRichImm.getCurrentRawSubtype());
|
||||||
|
updateParametersOnStartInputView();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -267,31 +229,6 @@ public final class SubtypeSwitcher {
|
||||||
return mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(subtype);
|
return mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(subtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes() {
|
|
||||||
final Locale systemLocale = mResources.getConfiguration().locale;
|
|
||||||
final Set<InputMethodSubtype> enabledSubtypesOfEnabledImes = new HashSet<>();
|
|
||||||
final InputMethodManager inputMethodManager = mRichImm.getInputMethodManager();
|
|
||||||
final List<InputMethodInfo> enabledInputMethodInfoList =
|
|
||||||
inputMethodManager.getEnabledInputMethodList();
|
|
||||||
for (final InputMethodInfo info : enabledInputMethodInfoList) {
|
|
||||||
final List<InputMethodSubtype> enabledSubtypes =
|
|
||||||
inputMethodManager.getEnabledInputMethodSubtypeList(
|
|
||||||
info, true /* allowsImplicitlySelectedSubtypes */);
|
|
||||||
if (enabledSubtypes.isEmpty()) {
|
|
||||||
// An IME with no subtypes is found.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
enabledSubtypesOfEnabledImes.addAll(enabledSubtypes);
|
|
||||||
}
|
|
||||||
for (final InputMethodSubtype subtype : enabledSubtypesOfEnabledImes) {
|
|
||||||
if (!subtype.isAuxiliary() && !subtype.getLocale().isEmpty()
|
|
||||||
&& !systemLocale.equals(SubtypeLocaleUtils.getSubtypeLocale(subtype))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static RichInputMethodSubtype sForcedSubtypeForTesting = null;
|
private static RichInputMethodSubtype sForcedSubtypeForTesting = null;
|
||||||
|
|
||||||
@UsedForTesting
|
@UsedForTesting
|
||||||
|
@ -313,39 +250,6 @@ public final class SubtypeSwitcher {
|
||||||
return mCurrentRichInputMethodSubtype;
|
return mCurrentRichInputMethodSubtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RichInputMethodSubtype getNoLanguageSubtype() {
|
|
||||||
if (mNoLanguageSubtype == null) {
|
|
||||||
mNoLanguageSubtype = new RichInputMethodSubtype(
|
|
||||||
mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
|
|
||||||
SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.QWERTY));
|
|
||||||
}
|
|
||||||
if (mNoLanguageSubtype != null) {
|
|
||||||
return mNoLanguageSubtype;
|
|
||||||
}
|
|
||||||
Log.w(TAG, "Can't find any language with QWERTY subtype");
|
|
||||||
Log.w(TAG, "No input method subtype found; returning dummy subtype: "
|
|
||||||
+ DUMMY_NO_LANGUAGE_SUBTYPE);
|
|
||||||
return DUMMY_NO_LANGUAGE_SUBTYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RichInputMethodSubtype getEmojiSubtype() {
|
|
||||||
if (mEmojiSubtype == null) {
|
|
||||||
final InputMethodSubtype rawEmojiSubtype =
|
|
||||||
mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
|
|
||||||
SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.EMOJI);
|
|
||||||
if (null != rawEmojiSubtype) {
|
|
||||||
mEmojiSubtype = new RichInputMethodSubtype(rawEmojiSubtype);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mEmojiSubtype != null) {
|
|
||||||
return mEmojiSubtype;
|
|
||||||
}
|
|
||||||
Log.w(TAG, "Can't find emoji subtype");
|
|
||||||
Log.w(TAG, "No input method subtype found; returning dummy subtype: "
|
|
||||||
+ DUMMY_EMOJI_SUBTYPE);
|
|
||||||
return DUMMY_EMOJI_SUBTYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCombiningRulesExtraValueOfCurrentSubtype() {
|
public String getCombiningRulesExtraValueOfCurrentSubtype() {
|
||||||
return SubtypeLocaleUtils.getCombiningRulesExtraValue(getCurrentSubtype().getRawSubtype());
|
return SubtypeLocaleUtils.getCombiningRulesExtraValue(getCurrentSubtype().getRawSubtype());
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ import android.text.TextUtils;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to help with handling Locales in string form.
|
* A class to help with handling Locales in string form.
|
||||||
*
|
*
|
||||||
|
@ -164,8 +166,10 @@ public final class LocaleUtils {
|
||||||
/**
|
/**
|
||||||
* Creates a locale from a string specification.
|
* Creates a locale from a string specification.
|
||||||
*/
|
*/
|
||||||
public static Locale constructLocaleFromString(final String localeStr) {
|
@Nullable
|
||||||
|
public static Locale constructLocaleFromString(@Nullable final String localeStr) {
|
||||||
if (localeStr == null) {
|
if (localeStr == null) {
|
||||||
|
// TODO: Should this be Locale.ROOT?
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
synchronized (sLocaleCache) {
|
synchronized (sLocaleCache) {
|
||||||
|
@ -173,7 +177,7 @@ public final class LocaleUtils {
|
||||||
if (retval != null) {
|
if (retval != null) {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
String[] localeParams = localeStr.split("_", 3);
|
final String[] localeParams = localeStr.split("_", 3);
|
||||||
if (localeParams.length == 1) {
|
if (localeParams.length == 1) {
|
||||||
retval = new Locale(localeParams[0]);
|
retval = new Locale(localeParams[0]);
|
||||||
} else if (localeParams.length == 2) {
|
} else if (localeParams.length == 2) {
|
||||||
|
@ -184,6 +188,7 @@ public final class LocaleUtils {
|
||||||
if (retval != null) {
|
if (retval != null) {
|
||||||
sLocaleCache.put(localeStr, retval);
|
sLocaleCache.put(localeStr, retval);
|
||||||
}
|
}
|
||||||
|
// TODO: Should return Locale.ROOT instead of null?
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper class to deal with subtype locales.
|
* A helper class to deal with subtype locales.
|
||||||
*/
|
*/
|
||||||
|
@ -173,7 +175,8 @@ public final class SubtypeLocaleUtils {
|
||||||
return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId;
|
return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Locale getDisplayLocaleOfSubtypeLocale(final String localeString) {
|
@Nonnull
|
||||||
|
public static Locale getDisplayLocaleOfSubtypeLocale(@Nonnull final String localeString) {
|
||||||
if (NO_LANGUAGE.equals(localeString)) {
|
if (NO_LANGUAGE.equals(localeString)) {
|
||||||
return sResources.getConfiguration().locale;
|
return sResources.getConfiguration().locale;
|
||||||
}
|
}
|
||||||
|
@ -183,17 +186,20 @@ public final class SubtypeLocaleUtils {
|
||||||
return LocaleUtils.constructLocaleFromString(localeString);
|
return LocaleUtils.constructLocaleFromString(localeString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getSubtypeLocaleDisplayNameInSystemLocale(final String localeString) {
|
public static String getSubtypeLocaleDisplayNameInSystemLocale(
|
||||||
|
@Nonnull final String localeString) {
|
||||||
final Locale displayLocale = sResources.getConfiguration().locale;
|
final Locale displayLocale = sResources.getConfiguration().locale;
|
||||||
return getSubtypeLocaleDisplayNameInternal(localeString, displayLocale);
|
return getSubtypeLocaleDisplayNameInternal(localeString, displayLocale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getSubtypeLocaleDisplayName(final String localeString) {
|
@Nonnull
|
||||||
|
public static String getSubtypeLocaleDisplayName(@Nonnull final String localeString) {
|
||||||
final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString);
|
final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString);
|
||||||
return getSubtypeLocaleDisplayNameInternal(localeString, displayLocale);
|
return getSubtypeLocaleDisplayNameInternal(localeString, displayLocale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getSubtypeLanguageDisplayName(final String localeString) {
|
@Nonnull
|
||||||
|
public static String getSubtypeLanguageDisplayName(@Nonnull final String localeString) {
|
||||||
final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString);
|
final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString);
|
||||||
final String languageString;
|
final String languageString;
|
||||||
if (sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) {
|
if (sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) {
|
||||||
|
@ -205,8 +211,9 @@ public final class SubtypeLocaleUtils {
|
||||||
return getSubtypeLocaleDisplayNameInternal(languageString, displayLocale);
|
return getSubtypeLocaleDisplayNameInternal(languageString, displayLocale);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getSubtypeLocaleDisplayNameInternal(final String localeString,
|
@Nonnull
|
||||||
final Locale displayLocale) {
|
private static String getSubtypeLocaleDisplayNameInternal(@Nonnull final String localeString,
|
||||||
|
@Nonnull final Locale displayLocale) {
|
||||||
if (NO_LANGUAGE.equals(localeString)) {
|
if (NO_LANGUAGE.equals(localeString)) {
|
||||||
// No language subtype should be displayed in system locale.
|
// No language subtype should be displayed in system locale.
|
||||||
return sResources.getString(R.string.subtype_no_language);
|
return sResources.getString(R.string.subtype_no_language);
|
||||||
|
@ -255,8 +262,9 @@ public final class SubtypeLocaleUtils {
|
||||||
// en_US azerty T English (US) (AZERTY) exception
|
// en_US azerty T English (US) (AZERTY) exception
|
||||||
// zz azerty T Alphabet (AZERTY) in system locale
|
// zz azerty T Alphabet (AZERTY) in system locale
|
||||||
|
|
||||||
private static String getReplacementString(final InputMethodSubtype subtype,
|
@Nonnull
|
||||||
final Locale displayLocale) {
|
private static String getReplacementString(@Nonnull final InputMethodSubtype subtype,
|
||||||
|
@Nonnull final Locale displayLocale) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
|
||||||
&& subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) {
|
&& subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) {
|
||||||
return subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME);
|
return subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME);
|
||||||
|
@ -264,20 +272,24 @@ public final class SubtypeLocaleUtils {
|
||||||
return getSubtypeLocaleDisplayNameInternal(subtype.getLocale(), displayLocale);
|
return getSubtypeLocaleDisplayNameInternal(subtype.getLocale(), displayLocale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getSubtypeDisplayNameInSystemLocale(final InputMethodSubtype subtype) {
|
@Nonnull
|
||||||
|
public static String getSubtypeDisplayNameInSystemLocale(
|
||||||
|
@Nonnull final InputMethodSubtype subtype) {
|
||||||
final Locale displayLocale = sResources.getConfiguration().locale;
|
final Locale displayLocale = sResources.getConfiguration().locale;
|
||||||
return getSubtypeDisplayNameInternal(subtype, displayLocale);
|
return getSubtypeDisplayNameInternal(subtype, displayLocale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getSubtypeNameForLogging(final InputMethodSubtype subtype) {
|
@Nonnull
|
||||||
|
public static String getSubtypeNameForLogging(@Nonnull final InputMethodSubtype subtype) {
|
||||||
if (subtype == null) {
|
if (subtype == null) {
|
||||||
return "<null subtype>";
|
return "<null subtype>";
|
||||||
}
|
}
|
||||||
return getSubtypeLocale(subtype) + "/" + getKeyboardLayoutSetName(subtype);
|
return getSubtypeLocale(subtype) + "/" + getKeyboardLayoutSetName(subtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getSubtypeDisplayNameInternal(final InputMethodSubtype subtype,
|
@Nonnull
|
||||||
final Locale displayLocale) {
|
private static String getSubtypeDisplayNameInternal(@Nonnull final InputMethodSubtype subtype,
|
||||||
|
@Nonnull final Locale displayLocale) {
|
||||||
final String replacementString = getReplacementString(subtype, displayLocale);
|
final String replacementString = getReplacementString(subtype, displayLocale);
|
||||||
// TODO: rework this for multi-lingual subtypes
|
// TODO: rework this for multi-lingual subtypes
|
||||||
final int nameResId = subtype.getNameResId();
|
final int nameResId = subtype.getNameResId();
|
||||||
|
@ -302,21 +314,26 @@ public final class SubtypeLocaleUtils {
|
||||||
getSubtypeName.runInLocale(sResources, displayLocale), displayLocale);
|
getSubtypeName.runInLocale(sResources, displayLocale), displayLocale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Locale getSubtypeLocale(final InputMethodSubtype subtype) {
|
@Nonnull
|
||||||
|
public static Locale getSubtypeLocale(@Nonnull final InputMethodSubtype subtype) {
|
||||||
final String localeString = subtype.getLocale();
|
final String localeString = subtype.getLocale();
|
||||||
return LocaleUtils.constructLocaleFromString(localeString);
|
return LocaleUtils.constructLocaleFromString(localeString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getKeyboardLayoutSetDisplayName(final InputMethodSubtype subtype) {
|
@Nonnull
|
||||||
|
public static String getKeyboardLayoutSetDisplayName(
|
||||||
|
@Nonnull final InputMethodSubtype subtype) {
|
||||||
final String layoutName = getKeyboardLayoutSetName(subtype);
|
final String layoutName = getKeyboardLayoutSetName(subtype);
|
||||||
return getKeyboardLayoutSetDisplayName(layoutName);
|
return getKeyboardLayoutSetDisplayName(layoutName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getKeyboardLayoutSetDisplayName(final String layoutName) {
|
@Nonnull
|
||||||
|
public static String getKeyboardLayoutSetDisplayName(@Nonnull final String layoutName) {
|
||||||
return sKeyboardLayoutToDisplayNameMap.get(layoutName);
|
return sKeyboardLayoutToDisplayNameMap.get(layoutName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getKeyboardLayoutSetName(final RichInputMethodSubtype subtype) {
|
@Nonnull
|
||||||
|
public static String getKeyboardLayoutSetName(@Nonnull final RichInputMethodSubtype subtype) {
|
||||||
return getKeyboardLayoutSetName(subtype.getRawSubtype());
|
return getKeyboardLayoutSetName(subtype.getRawSubtype());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue