some cleanup after increasing required api level

This commit is contained in:
Helium314 2024-01-18 16:27:22 +01:00
parent ffea3271f9
commit 96ad9482fb
42 changed files with 87 additions and 658 deletions

View file

@ -2,14 +2,12 @@
package org.dslul.openboard.inputmethod.compat;
import android.annotation.TargetApi;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.os.Build;
public class ClipboardManagerCompat {
@TargetApi(Build.VERSION_CODES.P)
public static void clearPrimaryClip(ClipboardManager cm) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
try {
@ -23,7 +21,6 @@ public class ClipboardManagerCompat {
}
}
@TargetApi(Build.VERSION_CODES.O)
public static Long getClipTimestamp(ClipData cd) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return cd.getDescription().getTimestamp();

View file

@ -1,190 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
* modified
* SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
*/
package org.dslul.openboard.inputmethod.compat
import android.text.TextUtils
import org.dslul.openboard.inputmethod.latin.utils.Log
import java.lang.reflect.Constructor
import java.lang.reflect.Field
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
object CompatUtils {
private val TAG = CompatUtils::class.java.simpleName
fun getClass(className: String?): Class<*>? {
return try {
Class.forName(className!!)
} catch (e: ClassNotFoundException) {
null
}
}
fun getMethod(targetClass: Class<*>?, name: String?,
vararg parameterTypes: Class<*>?): Method? {
if (targetClass == null || TextUtils.isEmpty(name)) {
return null
}
try {
return targetClass.getMethod(name!!, *parameterTypes)
} catch (_: SecurityException) { // ignore
} catch (_: NoSuchMethodException) {
}
return null
}
fun getField(targetClass: Class<*>?, name: String?): Field? {
if (targetClass == null || TextUtils.isEmpty(name)) {
return null
}
try {
return targetClass.getField(name!!)
} catch (_: SecurityException) { // ignore
} catch (_: NoSuchFieldException) {
}
return null
}
fun getConstructor(targetClass: Class<*>?,
vararg types: Class<*>?): Constructor<*>? {
if (targetClass == null || types == null) {
return null
}
try {
return targetClass.getConstructor(*types)
} catch (_: SecurityException) { // ignore
} catch (_: NoSuchMethodException) {
}
return null
}
fun newInstance(constructor: Constructor<*>?, vararg args: Any?): Any? {
if (constructor == null) {
return null
}
try {
return constructor.newInstance(*args)
} catch (e: InstantiationException) {
Log.e(TAG, "Exception in newInstance", e)
} catch (e: IllegalAccessException) {
Log.e(TAG, "Exception in newInstance", e)
} catch (e: IllegalArgumentException) {
Log.e(TAG, "Exception in newInstance", e)
} catch (e: InvocationTargetException) {
Log.e(TAG, "Exception in newInstance", e)
}
return null
}
operator fun invoke(receiver: Any?, defaultValue: Any?,
method: Method?, vararg args: Any?): Any? {
if (method == null) {
return defaultValue
}
try {
return method.invoke(receiver, *args)
} catch (e: IllegalAccessException) {
Log.e(TAG, "Exception in invoke", e)
} catch (e: IllegalArgumentException) {
Log.e(TAG, "Exception in invoke", e)
} catch (e: InvocationTargetException) {
Log.e(TAG, "Exception in invoke", e)
}
return defaultValue
}
fun getFieldValue(receiver: Any?, defaultValue: Any?,
field: Field?): Any? {
if (field == null) {
return defaultValue
}
try {
return field[receiver]
} catch (e: IllegalAccessException) {
Log.e(TAG, "Exception in getFieldValue", e)
} catch (e: IllegalArgumentException) {
Log.e(TAG, "Exception in getFieldValue", e)
}
return defaultValue
}
fun setFieldValue(receiver: Any?, field: Field?, value: Any?) {
if (field == null) {
return
}
try {
field[receiver] = value
} catch (e: IllegalAccessException) {
Log.e(TAG, "Exception in setFieldValue", e)
} catch (e: IllegalArgumentException) {
Log.e(TAG, "Exception in setFieldValue", e)
}
}
fun getClassWrapper(className: String?): ClassWrapper {
return ClassWrapper(getClass(className))
}
class ClassWrapper(private val mClass: Class<*>?) {
fun exists(): Boolean {
return mClass != null
}
fun <T> getMethod(name: String?,
defaultValue: T, vararg parameterTypes: Class<*>?): ToObjectMethodWrapper<T> {
return ToObjectMethodWrapper(getMethod(mClass, name, *parameterTypes),
defaultValue)
}
fun getPrimitiveMethod(name: String?, defaultValue: Int,
vararg parameterTypes: Class<*>?): ToIntMethodWrapper {
return ToIntMethodWrapper(getMethod(mClass, name, *parameterTypes),
defaultValue)
}
fun getPrimitiveMethod(name: String?, defaultValue: Float,
vararg parameterTypes: Class<*>?): ToFloatMethodWrapper {
return ToFloatMethodWrapper(getMethod(mClass, name, *parameterTypes),
defaultValue)
}
fun getPrimitiveMethod(name: String?,
defaultValue: Boolean, vararg parameterTypes: Class<*>?): ToBooleanMethodWrapper {
return ToBooleanMethodWrapper(getMethod(mClass, name, *parameterTypes),
defaultValue)
}
}
@Suppress("unchecked_cast")
class ToObjectMethodWrapper<T>(private val mMethod: Method?, private val mDefaultValue: T) {
operator fun invoke(receiver: Any?, vararg args: Any?): T {
return CompatUtils.invoke(receiver, mDefaultValue, mMethod, *args) as T
}
}
class ToIntMethodWrapper(private val mMethod: Method?, private val mDefaultValue: Int) {
operator fun invoke(receiver: Any?, vararg args: Any?): Int {
return CompatUtils.invoke(receiver, mDefaultValue, mMethod, *args) as Int
}
}
class ToFloatMethodWrapper(private val mMethod: Method?, private val mDefaultValue: Float) {
operator fun invoke(receiver: Any?, vararg args: Any?): Float {
return CompatUtils.invoke(receiver, mDefaultValue, mMethod, *args) as Float
}
}
class ToBooleanMethodWrapper(private val mMethod: Method?, private val mDefaultValue: Boolean) {
operator fun invoke(receiver: Any?, vararg args: Any?): Boolean {
return CompatUtils.invoke(receiver, mDefaultValue, mMethod, *args) as Boolean
}
}
}

View file

@ -1,164 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
* modified
* SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
*/
package org.dslul.openboard.inputmethod.compat
import android.annotation.TargetApi
import android.graphics.Matrix
import android.graphics.RectF
import android.os.Build
import android.os.Build.VERSION_CODES
import android.view.inputmethod.CursorAnchorInfo
/**
* A wrapper for [CursorAnchorInfo], which has been introduced in API Level 21. You can use
* this wrapper to avoid direct dependency on newly introduced types.
*/
open class CursorAnchorInfoCompatWrapper internal constructor() {
open val selectionStart: Int
get() {
throw UnsupportedOperationException("not supported.")
}
open val selectionEnd: Int
get() {
throw UnsupportedOperationException("not supported.")
}
open val composingText: CharSequence?
get() {
throw UnsupportedOperationException("not supported.")
}
open val composingTextStart: Int
get() {
throw UnsupportedOperationException("not supported.")
}
open val matrix: Matrix?
get() {
throw UnsupportedOperationException("not supported.")
}
open fun getCharacterBounds(index: Int): RectF? {
throw UnsupportedOperationException("not supported.")
}
open fun getCharacterBoundsFlags(index: Int): Int {
throw UnsupportedOperationException("not supported.")
}
open val insertionMarkerBaseline: Float
get() {
throw UnsupportedOperationException("not supported.")
}
open val insertionMarkerBottom: Float
get() {
throw UnsupportedOperationException("not supported.")
}
open val insertionMarkerHorizontal: Float
get() {
throw UnsupportedOperationException("not supported.")
}
open val insertionMarkerTop: Float
get() {
throw UnsupportedOperationException("not supported.")
}
open val insertionMarkerFlags: Int
get() {
throw UnsupportedOperationException("not supported.")
}
@TargetApi(VERSION_CODES.LOLLIPOP)
private class RealWrapper(private val mInstance: CursorAnchorInfo) : CursorAnchorInfoCompatWrapper() {
override val selectionStart: Int
get() {
return mInstance.selectionStart
}
override val selectionEnd: Int
get() {
return mInstance.selectionEnd
}
override val composingText: CharSequence?
get() {
return mInstance.composingText
}
override val composingTextStart: Int
get() {
return mInstance.composingTextStart
}
override val matrix: Matrix?
get() {
return mInstance.matrix
}
override fun getCharacterBounds(index: Int): RectF? {
return mInstance.getCharacterBounds(index)
}
override fun getCharacterBoundsFlags(index: Int): Int {
return mInstance.getCharacterBoundsFlags(index)
}
override val insertionMarkerBaseline: Float
get() {
return mInstance.insertionMarkerBaseline
}
override val insertionMarkerBottom: Float
get() {
return mInstance.insertionMarkerBottom
}
override val insertionMarkerHorizontal: Float
get() {
return mInstance.insertionMarkerHorizontal
}
override val insertionMarkerTop: Float
get() {
return mInstance.insertionMarkerTop
}
override val insertionMarkerFlags: Int
get() {
return mInstance.insertionMarkerFlags
}
}
companion object {
/**
* The insertion marker or character bounds have at least one visible region.
*/
const val FLAG_HAS_VISIBLE_REGION = 0x01
/**
* The insertion marker or character bounds have at least one invisible (clipped) region.
*/
const val FLAG_HAS_INVISIBLE_REGION = 0x02
/**
* The insertion marker or character bounds is placed at right-to-left (RTL) character.
*/
const val FLAG_IS_RTL = 0x04
@JvmStatic
@TargetApi(VERSION_CODES.LOLLIPOP)
fun wrap(instance: CursorAnchorInfo?): CursorAnchorInfoCompatWrapper? {
return if (Build.VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
null
} else instance?.let { RealWrapper(it) }
}
}
}

View file

@ -14,18 +14,13 @@ import org.dslul.openboard.inputmethod.latin.utils.locale
import java.util.*
object InputMethodSubtypeCompatUtils {
// Note that InputMethodSubtype.getLanguageTag() is expected to be available in Android N+.
private val GET_LANGUAGE_TAG = CompatUtils.getMethod(InputMethodSubtype::class.java, "getLanguageTag")
@JvmStatic
fun getLocaleObject(subtype: InputMethodSubtype): Locale { // Locale.forLanguageTag() is available only in Android L and later.
if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
val languageTag = CompatUtils.invoke(subtype, null, GET_LANGUAGE_TAG) as String?
if (!languageTag.isNullOrEmpty()) {
if (Build.VERSION.SDK_INT >= VERSION_CODES.N) {
val languageTag = subtype.languageTag
if (languageTag.isNotEmpty())
return Locale.forLanguageTag(languageTag)
}
}
return LocaleUtils.constructLocaleFromString(subtype.locale())
}
}

View file

@ -14,6 +14,7 @@ import android.text.style.SuggestionSpan
import org.dslul.openboard.inputmethod.annotations.UsedForTesting
import java.util.*
// todo: this is not compat any more
object SuggestionSpanUtils {
@JvmStatic
@UsedForTesting

View file

@ -1,47 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
* modified
* SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
*/
package org.dslul.openboard.inputmethod.compat
import android.os.Build
import android.view.textservice.TextInfo
import org.dslul.openboard.inputmethod.annotations.UsedForTesting
object TextInfoCompatUtils {
// Note that TextInfo.getCharSequence() is supposed to be available in API level 21 and later.
private val TEXT_INFO_GET_CHAR_SEQUENCE = CompatUtils.getMethod(TextInfo::class.java, "getCharSequence")
@get:UsedForTesting
val isCharSequenceSupported: Boolean
get() = TEXT_INFO_GET_CHAR_SEQUENCE != null
@JvmStatic
@UsedForTesting
fun newInstance(charSequence: CharSequence, start: Int, end: Int, cookie: Int,
sequenceNumber: Int): TextInfo {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
return TextInfo(charSequence, start, end, cookie, sequenceNumber)
return TextInfo(charSequence.subSequence(start, end).toString(), cookie, sequenceNumber)
}
/**
* Returns the result of [TextInfo.getCharSequence] when available. Otherwise returns
* the result of [TextInfo.getText] as fall back.
* @param textInfo the instance for which [TextInfo.getCharSequence] or
* [TextInfo.getText] is called.
* @return the result of [TextInfo.getCharSequence] when available. Otherwise returns
* the result of [TextInfo.getText] as fall back. If `textInfo` is `null`,
* returns `null`.
*/
@JvmStatic
@UsedForTesting
fun getCharSequenceOrString(textInfo: TextInfo): CharSequence {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
return textInfo.charSequence
val defaultValue = textInfo.text
return CompatUtils.invoke(textInfo, defaultValue, TEXT_INFO_GET_CHAR_SEQUENCE) as CharSequence
}
}

View file

@ -6,24 +6,44 @@
package org.dslul.openboard.inputmethod.compat
import android.graphics.Outline
import android.inputmethodservice.InputMethodService
import android.os.Build
import android.os.Build.VERSION_CODES
import android.view.View
import android.view.ViewOutlineProvider
// todo: this is not compat any more
object ViewOutlineProviderCompatUtils {
private val EMPTY_INSETS_UPDATER: InsetsUpdater = object : InsetsUpdater {
override fun setInsets(insets: InputMethodService.Insets) {}
}
@JvmStatic
fun setInsetsOutlineProvider(view: View): InsetsUpdater {
return if (Build.VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
EMPTY_INSETS_UPDATER
} else ViewOutlineProviderCompatUtilsLXX.setInsetsOutlineProvider(view)
}
interface InsetsUpdater {
fun setInsets(insets: InputMethodService.Insets)
fun setInsetsOutlineProvider(view: View): InsetsOutlineProvider {
val provider = InsetsOutlineProvider(view)
view.outlineProvider = provider
return provider
}
}
class InsetsOutlineProvider(private val mView: View) : ViewOutlineProvider() {
private var mLastVisibleTopInsets = NO_DATA
init {
mView.outlineProvider = this
}
fun setInsets(insets: InputMethodService.Insets) {
val visibleTopInsets = insets.visibleTopInsets
if (mLastVisibleTopInsets != visibleTopInsets) {
mLastVisibleTopInsets = visibleTopInsets
mView.invalidateOutline()
}
}
override fun getOutline(view: View, outline: Outline) {
if (mLastVisibleTopInsets == NO_DATA) { // Call default implementation.
BACKGROUND.getOutline(view, outline)
return
}
// TODO: Revisit this when floating/resize keyboard is supported.
outline.setRect(view.left, mLastVisibleTopInsets, view.right, view.bottom)
}
companion object {
private const val NO_DATA = -1
}
}

View file

@ -1,52 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
* modified
* SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
*/
package org.dslul.openboard.inputmethod.compat
import android.graphics.Outline
import android.inputmethodservice.InputMethodService
import android.os.Build
import android.view.View
import android.view.ViewOutlineProvider
import androidx.annotation.RequiresApi
import org.dslul.openboard.inputmethod.compat.ViewOutlineProviderCompatUtils.InsetsUpdater
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
internal object ViewOutlineProviderCompatUtilsLXX {
fun setInsetsOutlineProvider(view: View): InsetsUpdater {
val provider = InsetsOutlineProvider(view)
view.outlineProvider = provider
return provider
}
private class InsetsOutlineProvider(private val mView: View) : ViewOutlineProvider(), InsetsUpdater {
private var mLastVisibleTopInsets = NO_DATA
override fun setInsets(insets: InputMethodService.Insets) {
val visibleTopInsets = insets.visibleTopInsets
if (mLastVisibleTopInsets != visibleTopInsets) {
mLastVisibleTopInsets = visibleTopInsets
mView.invalidateOutline()
}
}
override fun getOutline(view: View, outline: Outline) {
if (mLastVisibleTopInsets == NO_DATA) { // Call default implementation.
BACKGROUND.getOutline(view, outline)
return
}
// TODO: Revisit this when floating/resize keyboard is supported.
outline.setRect(view.left, mLastVisibleTopInsets, view.right, view.bottom)
}
companion object {
private const val NO_DATA = -1
}
init {
mView.outlineProvider = this
}
}
}

View file

@ -23,7 +23,7 @@ import org.dslul.openboard.inputmethod.latin.utils.DeviceProtectedUtils;
import java.util.Arrays;
public final class KeyboardTheme implements Comparable<KeyboardTheme> {
public final class KeyboardTheme {
// old themes
public static final String STYLE_MATERIAL = "Material";
@ -59,43 +59,23 @@ public final class KeyboardTheme implements Comparable<KeyboardTheme> {
/* package private for testing */
static final KeyboardTheme[] KEYBOARD_THEMES = {
new KeyboardTheme(THEME_ID_HOLO_BASE, "HoloBase", R.style.KeyboardTheme_HoloBase,
VERSION_CODES.BASE),
new KeyboardTheme(THEME_ID_LXX_BASE, "LXXBase", R.style.KeyboardTheme_LXX_Base,
VERSION_CODES.LOLLIPOP),
new KeyboardTheme(THEME_ID_LXX_BASE_BORDER, "LXXBaseBorder", R.style.KeyboardTheme_LXX_Base_Border,
VERSION_CODES.LOLLIPOP),
new KeyboardTheme(THEME_ID_ROUNDED_BASE, "RoundedBase", R.style.KeyboardTheme_Rounded_Base,
VERSION_CODES.LOLLIPOP),
new KeyboardTheme(THEME_ID_ROUNDED_BASE_BORDER, "RoundedBaseBorder", R.style.KeyboardTheme_Rounded_Base_Border,
VERSION_CODES.LOLLIPOP)
new KeyboardTheme(THEME_ID_HOLO_BASE, "HoloBase", R.style.KeyboardTheme_HoloBase),
new KeyboardTheme(THEME_ID_LXX_BASE, "LXXBase", R.style.KeyboardTheme_LXX_Base),
new KeyboardTheme(THEME_ID_LXX_BASE_BORDER, "LXXBaseBorder", R.style.KeyboardTheme_LXX_Base_Border),
new KeyboardTheme(THEME_ID_ROUNDED_BASE, "RoundedBase", R.style.KeyboardTheme_Rounded_Base),
new KeyboardTheme(THEME_ID_ROUNDED_BASE_BORDER, "RoundedBaseBorder", R.style.KeyboardTheme_Rounded_Base_Border)
};
static {
// Sort {@link #KEYBOARD_THEME} by descending order of {@link #mMinApiVersion}.
Arrays.sort(KEYBOARD_THEMES);
}
public final int mThemeId;
public final int mStyleId;
public final String mThemeName;
public final int mMinApiVersion;
// Note: The themeId should be aligned with "themeId" attribute of Keyboard style
// in values/themes-<style>.xml.
private KeyboardTheme(final int themeId, final String themeName, final int styleId,
final int minApiVersion) {
private KeyboardTheme(final int themeId, final String themeName, final int styleId) {
mThemeId = themeId;
mThemeName = themeName;
mStyleId = styleId;
mMinApiVersion = minApiVersion;
}
@Override
public int compareTo(final KeyboardTheme rhs) {
if (mMinApiVersion > rhs.mMinApiVersion) return -1;
if (mMinApiVersion < rhs.mMinApiVersion) return 1;
return 0;
}
@Override

View file

@ -672,10 +672,9 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
}
// crappy workaround...
val locale = when (params.mId.locale.toString().lowercase()) {
// todo: improve this when switching (rich input) subtype to use language tag
"hi_zz" -> Locale("en", "IN")
"sr_zz" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
Locale.forLanguageTag("sr-Latn")
else params.mId.locale // todo: copy strings to sr-rZZ when definitely not increasing min SDK to 21
"sr_zz" -> Locale.forLanguageTag("sr-Latn")
else -> params.mId.locale
}
return ril.runInLocale(context.resources, locale)

View file

@ -42,8 +42,8 @@ import android.view.inputmethod.InputMethodSubtype;
import org.dslul.openboard.inputmethod.accessibility.AccessibilityUtils;
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
import org.dslul.openboard.inputmethod.compat.EditorInfoCompatUtils;
import org.dslul.openboard.inputmethod.compat.InsetsOutlineProvider;
import org.dslul.openboard.inputmethod.compat.ViewOutlineProviderCompatUtils;
import org.dslul.openboard.inputmethod.compat.ViewOutlineProviderCompatUtils.InsetsUpdater;
import org.dslul.openboard.inputmethod.dictionarypack.DictionaryPackConstants;
import org.dslul.openboard.inputmethod.event.Event;
import org.dslul.openboard.inputmethod.event.HangulEventDecoder;
@ -142,7 +142,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// TODO: Move these {@link View}s to {@link KeyboardSwitcher}.
private View mInputView;
private InsetsUpdater mInsetsUpdater;
private InsetsOutlineProvider mInsetsUpdater;
private SuggestionStripView mSuggestionStripView;
private RichInputMethodManager mRichImm;
@ -2006,9 +2006,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
// slightly modified from Simple Keyboard: https://github.com/rkkr/simple-keyboard/blob/master/app/src/main/java/rkr/simplekeyboard/inputmethod/latin/LatinIME.java
@SuppressWarnings("deprecation")
private void setNavigationBarColor() {
final SettingsValues settingsValues = mSettings.getCurrent();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || !settingsValues.mCustomNavBarColor)
if (!settingsValues.mCustomNavBarColor)
return;
final int color = settingsValues.mColors.get(ColorType.NAVIGATION_BAR);
final Window window = getWindow().getWindow();
@ -2031,7 +2032,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@SuppressWarnings("deprecation")
private void clearNavigationBarColor() {
final SettingsValues settingsValues = mSettings.getCurrent();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || !settingsValues.mCustomNavBarColor)
if (!settingsValues.mCustomNavBarColor)
return;
final Window window = getWindow().getWindow();
if (window == null) {

View file

@ -1176,14 +1176,11 @@ public final class RichInputConnection implements PrivateCommandPerformer {
* prevents the application from fulfilling the request. (TODO: Improve the API when it turns
* out that we actually need more detailed error codes)
*/
public boolean requestCursorUpdates(final boolean enableMonitor,
final boolean requestImmediateCallback) {
public boolean requestCursorUpdates(final boolean enableMonitor, final boolean requestImmediateCallback) {
mIC = mParent.getCurrentInputConnection();
if (!isConnected()) {
return false;
}
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP)
return false;
final int cursorUpdateMode = (enableMonitor ? InputConnection.CURSOR_UPDATE_MONITOR : 0)
| (requestImmediateCallback ? InputConnection.CURSOR_UPDATE_IMMEDIATE : 0);
return mIC.requestCursorUpdates(cursorUpdateMode);

View file

@ -33,6 +33,7 @@ import androidx.annotation.Nullable;
public class RichInputMethodSubtype {
private static final String TAG = RichInputMethodSubtype.class.getSimpleName();
// todo: remove this map when switching (rich input) subtype to use language tag
private static final HashMap<Locale, Locale> sLocaleMap = initializeLocaleMap();
private static HashMap<Locale, Locale> initializeLocaleMap() {
final HashMap<Locale, Locale> map = new HashMap<>();

View file

@ -90,11 +90,10 @@ public class SuggestedWords {
/**
* Get suggested word to show as suggestions to UI.
*
* @param shouldShowLxxSuggestionUi true if showing suggestion UI introduced in LXX and later.
* @return the count of suggested word to show as suggestions to UI.
*/
public int getWordCountToShow(final boolean shouldShowLxxSuggestionUi) {
if (isPrediction() || !shouldShowLxxSuggestionUi) {
public int getWordCountToShow() {
if (isPrediction()) {
return size();
}
return size() - /* typed word */ 1;

View file

@ -155,11 +155,8 @@ public final class InputLogic {
} else {
mInputLogicHandler.reset();
}
if (settingsValues.mShouldShowLxxSuggestionUi) {
mConnection.requestCursorUpdates(true, true);
}
}
/**
* Call this when the subtype changes.

View file

@ -7,8 +7,6 @@ package org.dslul.openboard.inputmethod.latin.settings
import android.app.Activity
import android.content.Intent
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.text.method.LinkMovementMethod
import android.view.View
@ -16,7 +14,6 @@ import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.core.graphics.drawable.DrawableCompat
import androidx.preference.Preference
import org.dslul.openboard.inputmethod.latin.BuildConfig
import org.dslul.openboard.inputmethod.latin.R
@ -31,15 +28,6 @@ class AboutFragment : SubScreenFragment() {
super.onCreate(icicle)
addPreferencesFromResource(R.xml.prefs_screen_about)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
// need to set icon tint because old android versions don't use the vector drawables
for (i in 0 until preferenceScreen.preferenceCount) {
val p = preferenceScreen.getPreference(0)
val icon = p.icon
if (icon != null) DrawableCompat.setTint(icon, Color.WHITE)
}
}
setupHiddenFeatures()
setupVersionPref()
findPreference<Preference>("log_reader")?.setOnPreferenceClickListener {

View file

@ -120,11 +120,7 @@ class AdvancedSettingsFragment : SubScreenFragment() {
private fun onClickLoadLibrary(): Boolean {
// get architecture for telling user which file to use
val abi = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Build.SUPPORTED_ABIS[0]
} else {
@Suppress("Deprecation") Build.CPU_ABI
}
val abi = Build.SUPPORTED_ABIS[0]
// show delete / add dialog
val builder = AlertDialog.Builder(requireContext())
.setTitle(R.string.load_gesture_library)
@ -161,11 +157,7 @@ class AdvancedSettingsFragment : SubScreenFragment() {
if (checksum == JniUtils.expectedDefaultChecksum()) {
renameToLibfileAndRestart(tmpfile, checksum)
} else {
val abi = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Build.SUPPORTED_ABIS[0]
} else {
@Suppress("Deprecation") Build.CPU_ABI
}
val abi = Build.SUPPORTED_ABIS[0]
AlertDialog.Builder(requireContext())
.setMessage(getString(R.string.checksum_mismatch_message, abi))
.setPositiveButton(android.R.string.ok) { _, _ -> renameToLibfileAndRestart(tmpfile, checksum) }

View file

@ -12,7 +12,6 @@ import androidx.preference.TwoStatePreference
import org.dslul.openboard.inputmethod.keyboard.KeyboardSwitcher
import org.dslul.openboard.inputmethod.keyboard.KeyboardTheme
import org.dslul.openboard.inputmethod.latin.R
import org.dslul.openboard.inputmethod.latin.define.ProductionFlags
import java.lang.Float.max
import java.lang.Float.min
import java.util.*
@ -79,10 +78,6 @@ class AppearanceSettingsFragment : SubScreenFragment() {
removePreference("theme_select_colors_night")
}
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
// todo: consider removing the preference, and always set the navbar color
removePreference(Settings.PREF_NAVBAR_COLOR)
}
val metrics = requireContext().resources.displayMetrics
val widthDp = metrics.widthPixels / metrics.density
val heightDp = metrics.heightPixels / metrics.density

View file

@ -12,7 +12,6 @@ package org.dslul.openboard.inputmethod.latin.settings;
public final class DebugSettings {
public static final String PREF_DEBUG_MODE = "debug_mode";
public static final String PREF_FORCE_NON_DISTINCT_MULTITOUCH = "force_non_distinct_multitouch";
public static final String PREF_SHOULD_SHOW_LXX_SUGGESTION_UI = "pref_should_show_lxx_suggestion_ui";
public static final String PREF_SLIDING_KEY_INPUT_PREVIEW = "pref_sliding_key_input_preview";
public static final String PREF_SHOW_DEBUG_SETTINGS = "pref_show_debug_settings";

View file

@ -40,10 +40,6 @@ public final class DebugSettingsFragment extends SubScreenFragment
super.onCreate(icicle);
addPreferencesFromResource(R.xml.prefs_screen_debug);
if (!Settings.SHOULD_SHOW_LXX_SUGGESTION_UI) {
removePreference(DebugSettings.PREF_SHOULD_SHOW_LXX_SUGGESTION_UI);
}
final PreferenceGroup dictDumpPreferenceGroup = findPreference(PREF_KEY_DUMP_DICTS);
for (final String dictName : DictionaryFacilitatorImpl.DICT_TYPE_TO_CLASS.keySet()) {
final Preference pref = new DictDumpPreference(getActivity(), dictName);

View file

@ -13,8 +13,8 @@ import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.Switch
import android.widget.TextView
import androidx.appcompat.widget.SwitchCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.widget.doAfterTextChanged
@ -114,7 +114,7 @@ private class LanguageAdapter(list: List<MutableList<SubtypeInfo>> = listOf(), c
else isVisible = true
}
view.findViewById<SwitchCompat>(R.id.language_switch).apply {
view.findViewById<Switch>(R.id.language_switch).apply {
isEnabled = !onlySystemLocales
// take care: isChecked changes if the language is scrolled out of view and comes back!
// disable the change listener when setting the checked status on scroll

View file

@ -11,9 +11,9 @@ import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.ScrollView
import android.widget.Switch
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.SwitchCompat
import androidx.core.view.get
import androidx.core.view.isGone
import androidx.core.view.isVisible
@ -170,7 +170,7 @@ class LanguageSettingsDialog(
} else {
row.findViewById<View>(R.id.language_details).isGone = true
}
row.findViewById<SwitchCompat>(R.id.language_switch).apply {
row.findViewById<Switch>(R.id.language_switch).apply {
isChecked = subtype.isEnabled
isEnabled = !onlySystemLocales
setOnCheckedChangeListener { _, b ->
@ -186,7 +186,7 @@ class LanguageSettingsDialog(
}
}
if (isAdditionalSubtype(subtype.subtype)) {
row.findViewById<SwitchCompat>(R.id.language_switch).isEnabled = true
row.findViewById<Switch>(R.id.language_switch).isEnabled = true
row.findViewById<ImageView>(R.id.delete_button).apply {
isVisible = true
setOnClickListener {

View file

@ -12,9 +12,9 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodSubtype
import android.widget.Switch
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SwitchCompat
import androidx.core.content.edit
import androidx.fragment.app.Fragment
import org.dslul.openboard.inputmethod.latin.R
@ -37,7 +37,7 @@ class LanguageSettingsFragment : Fragment(R.layout.language_settings) {
private val systemLocales = mutableListOf<Locale>()
private lateinit var languageFilterList: LanguageFilterList
private lateinit var sharedPreferences: SharedPreferences
private lateinit var systemOnlySwitch: SwitchCompat
private lateinit var systemOnlySwitch: Switch
private val dictionaryLocales by lazy { getDictionaryLocales(requireContext()).mapTo(HashSet()) { it.languageConsideringZZ() } }
private val dictionaryFilePicker = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {

View file

@ -9,14 +9,10 @@ package org.dslul.openboard.inputmethod.latin.settings;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.view.inputmethod.InputMethodSubtype;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.preference.Preference;
import org.dslul.openboard.inputmethod.keyboard.KeyboardLayoutSet;
@ -39,16 +35,6 @@ public final class PreferencesSettingsFragment extends SubScreenFragment {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.prefs_screen_preferences);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
// need to set icon tint because old android versions don't use the vector drawables
for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
final Preference p = getPreferenceScreen().getPreference(0);
final Drawable icon = p.getIcon();
if (icon != null)
DrawableCompat.setTint(icon, Color.WHITE);
}
}
final Resources res = getResources();
final Context context = getActivity();

View file

@ -87,7 +87,6 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_KEY_USE_PERSONALIZED_DICTS = "pref_key_use_personalized_dicts";
public static final String PREF_KEY_USE_DOUBLE_SPACE_PERIOD = "pref_key_use_double_space_period";
public static final String PREF_BLOCK_POTENTIALLY_OFFENSIVE = "pref_key_block_potentially_offensive";
public static final boolean SHOULD_SHOW_LXX_SUGGESTION_UI = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
public static final String PREF_LANGUAGE_SWITCH_KEY = "pref_language_switch_key";
public static final String PREF_SHOW_EMOJI_KEY = "pref_show_emoji_key";
public static final String PREF_ADDITIONAL_SUBTYPES = "pref_additional_subtypes";

View file

@ -96,8 +96,6 @@ public class SettingsValues {
public final int mKeyLongpressTimeout;
public final boolean mEnableEmojiAltPhysicalKey;
public final boolean mIsShowAppIconSettingInPreferences;
public final boolean mShouldShowLxxSuggestionUi;
// Use split layout for keyboard.
public final boolean mIsSplitKeyboardEnabled;
public final float mSplitKeyboardSpacerRelativeWidth;
public final int mScreenMetrics;
@ -177,8 +175,6 @@ public class SettingsValues {
: 0f;
mScreenMetrics = Settings.readScreenMetrics(res);
mShouldShowLxxSuggestionUi = Settings.SHOULD_SHOW_LXX_SUGGESTION_UI
&& prefs.getBoolean(DebugSettings.PREF_SHOULD_SHOW_LXX_SUGGESTION_UI, true);
// Compute other readable settings
mKeyLongpressTimeout = Settings.readKeyLongpressTimeout(prefs, res);
mKeypressVibrationDuration = Settings.readKeypressVibrationDuration(prefs, res);

View file

@ -14,7 +14,6 @@ import android.view.textservice.SentenceSuggestionsInfo;
import android.view.textservice.SuggestionsInfo;
import android.view.textservice.TextInfo;
import org.dslul.openboard.inputmethod.compat.TextInfoCompatUtils;
import org.dslul.openboard.inputmethod.latin.NgramContext;
import org.dslul.openboard.inputmethod.latin.utils.SpannableStringUtils;
@ -34,7 +33,7 @@ public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheck
private SentenceSuggestionsInfo fixWronglyInvalidatedWordWithSingleQuote(TextInfo ti,
SentenceSuggestionsInfo ssi) {
final CharSequence typedText = TextInfoCompatUtils.getCharSequenceOrString(ti);
final CharSequence typedText = ti.getCharSequence();
if (!typedText.toString().contains(AndroidSpellCheckerService.SINGLE_QUOTE)) {
return null;
}
@ -184,8 +183,7 @@ public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheck
final CharSequence prevWord;
if (sequentialWords && i > 0) {
final TextInfo prevTextInfo = textInfos[i - 1];
final CharSequence prevWordCandidate =
TextInfoCompatUtils.getCharSequenceOrString(prevTextInfo);
final CharSequence prevWordCandidate = prevTextInfo.getCharSequence();
// Note that an empty string would be used to indicate the initial word
// in the future.
prevWord = TextUtils.isEmpty(prevWordCandidate) ? null : prevWordCandidate;

View file

@ -11,7 +11,6 @@ import android.view.textservice.SentenceSuggestionsInfo;
import android.view.textservice.SuggestionsInfo;
import android.view.textservice.TextInfo;
import org.dslul.openboard.inputmethod.compat.TextInfoCompatUtils;
import org.dslul.openboard.inputmethod.latin.common.Constants;
import org.dslul.openboard.inputmethod.latin.settings.SpacingAndPunctuations;
import org.dslul.openboard.inputmethod.latin.utils.RunInLocale;
@ -124,8 +123,7 @@ public class SentenceLevelAdapter {
public SentenceTextInfoParams getSplitWords(TextInfo originalTextInfo) {
final WordIterator wordIterator = mWordIterator;
final CharSequence originalText =
TextInfoCompatUtils.getCharSequenceOrString(originalTextInfo);
final CharSequence originalText = originalTextInfo.getCharSequence();
final int cookie = originalTextInfo.getCookie();
final int start = -1;
final int end = originalText.length();
@ -134,7 +132,7 @@ public class SentenceLevelAdapter {
int wordEnd = wordIterator.getEndOfWord(originalText, wordStart);
while (wordStart <= end && wordEnd != -1 && wordStart != -1) {
if (wordEnd >= start && wordEnd > wordStart) {
final TextInfo ti = TextInfoCompatUtils.newInstance(originalText, wordStart,
final TextInfo ti = new TextInfo(originalText, wordStart,
wordEnd, cookie, originalText.subSequence(wordStart, wordEnd).hashCode());
wordItems.add(new SentenceWordItem(ti, wordStart, wordEnd));
}

View file

@ -225,11 +225,9 @@ final class SuggestionStripLayoutHelper {
final SuggestedWords suggestedWords) {
final SettingsValues settingsValues = Settings.getInstance().getCurrent();
final boolean shouldOmitTypedWord = shouldOmitTypedWord(suggestedWords.mInputStyle,
settingsValues.mGestureFloatingPreviewTextEnabled,
settingsValues.mShouldShowLxxSuggestionUi);
settingsValues.mGestureFloatingPreviewTextEnabled, true);
return getPositionInSuggestionStrip(indexInSuggestedWords, suggestedWords.mWillAutoCorrect,
settingsValues.mShouldShowLxxSuggestionUi && shouldOmitTypedWord,
mCenterPositionInStrip, mTypedWordPositionWhenAutocorrect);
shouldOmitTypedWord, mCenterPositionInStrip, mTypedWordPositionWhenAutocorrect);
}
@UsedForTesting
@ -337,8 +335,7 @@ final class SuggestionStripLayoutHelper {
(PunctuationSuggestions)suggestedWords, stripView);
}
final int wordCountToShow = suggestedWords.getWordCountToShow(
Settings.getInstance().getCurrent().mShouldShowLxxSuggestionUi);
final int wordCountToShow = suggestedWords.getWordCountToShow();
final int startIndexOfMoreSuggestions = setupWordViewsAndReturnStartIndexOfMoreSuggestions(
suggestedWords, mSuggestionsCountInStrip);
final TextView centerWordView = mWordViews.get(mCenterPositionInStrip);

View file

@ -6,12 +6,10 @@
package org.dslul.openboard.inputmethod.latin.utils;
import android.annotation.TargetApi;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.inputmethodservice.ExtractEditText;
import android.inputmethodservice.InputMethodService;
import android.os.Build;
import android.text.Layout;
import android.text.Spannable;
import android.text.Spanned;
@ -23,8 +21,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.dslul.openboard.inputmethod.compat.CursorAnchorInfoCompatWrapper;
// todo: remove this? or is there anything it could be useful for?
/**
* This class allows input methods to extract {@link CursorAnchorInfo} directly from the given
* {@link TextView}. This is useful and even necessary to support full-screen mode where the default
@ -74,30 +71,12 @@ public final class CursorAnchorInfoUtils {
return true;
}
/**
* Extracts {@link CursorAnchorInfoCompatWrapper} from the given {@link TextView}.
* @param textView the target text view from which {@link CursorAnchorInfoCompatWrapper} is to
* be extracted.
* @return the {@link CursorAnchorInfoCompatWrapper} object based on the current layout.
* {@code null} if {@code Build.VERSION.SDK_INT} is 20 or prior or {@link TextView} is not
* ready to provide layout information.
*/
@Nullable
public static CursorAnchorInfoCompatWrapper extractFromTextView(
@NonNull final TextView textView) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return null;
}
return CursorAnchorInfoCompatWrapper.wrap(extractFromTextViewInternal(textView));
}
/**
* Returns {@link CursorAnchorInfo} from the given {@link TextView}.
* @param textView the target text view from which {@link CursorAnchorInfo} is to be extracted.
* @return the {@link CursorAnchorInfo} object based on the current layout. {@code null} if it
* is not feasible.
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Nullable
private static CursorAnchorInfo extractFromTextViewInternal(@NonNull final TextView textView) {
final Layout layout = textView.getLayout();

View file

@ -26,7 +26,7 @@ public final class JniUtils {
private static final String CHECKSUM_X86 = "bd946d126c957b5a6dea3bafa07fa36a27950b30e2b684dffc60746d0a1c7ad8";
public static String expectedDefaultChecksum() {
final String abi = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? Build.SUPPORTED_ABIS[0] : Build.CPU_ABI;
final String abi = Build.SUPPORTED_ABIS[0];
return switch (abi) {
case "arm64-v8a" -> CHECKSUM_ARM64;
case "armeabi-v7a" -> CHECKSUM_ARM32;

View file

@ -5,9 +5,9 @@ import android.content.Context
import android.content.SharedPreferences
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.Switch
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.SwitchCompat
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper
@ -135,7 +135,7 @@ fun reorderMoreKeysDialog(context: Context, key: String, defaultSetting: String,
val displayTextId = context.resources.getIdentifier(text.lowercase(), "string", context.packageName)
val displayText = if (displayTextId == 0) text else context.getString(displayTextId)
p0.itemView.findViewById<TextView>(R.id.morekeys_type)?.text = displayText
val switch = p0.itemView.findViewById<SwitchCompat>(R.id.morekeys_switch)
val switch = p0.itemView.findViewById<Switch>(R.id.morekeys_switch)
switch?.isChecked = wasChecked
switch?.isEnabled = !(key.contains(Settings.PREF_MORE_KEYS_ORDER) && text == MORE_KEYS_LAYOUT) // layout can't be disabled
switch?.setOnCheckedChangeListener { _, isChecked ->

View file

@ -34,7 +34,7 @@
android:paddingHorizontal="10dp"
style="@style/PreferenceSubtitleText" />
</LinearLayout>
<androidx.appcompat.widget.SwitchCompat
<Switch
android:id="@+id/color_switch"
android:layout_gravity="center_vertical"
android:layout_width="0dp"

View file

@ -40,7 +40,7 @@
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<androidx.appcompat.widget.SwitchCompat
<Switch
android:id="@+id/language_switch"
android:padding="6dp"
android:layout_gravity="center_vertical"

View file

@ -7,7 +7,7 @@
android:paddingTop="6dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.SwitchCompat
<Switch
android:id="@+id/language_switch"
android:text="@string/use_system_language_to_select_input_method_subtypes"
style="@style/PreferenceTitleText"

View file

@ -17,7 +17,7 @@
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<androidx.appcompat.widget.SwitchCompat
<Switch
android:id="@+id/morekeys_switch"
android:padding="6dp"
android:layout_gravity="center_vertical"

View file

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 The Android Open Source Project
modified
SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="platformActivityTheme" parent="Theme.AppCompat.DayNight">
<item name="android:colorAccent">@color/accent</item>
<item name="colorAccent">@color/accent</item>
</style>
</resources>

View file

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 The Android Open Source Project
SPDX-License-Identifier: Apache-2.0
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style
name="InputView.LXX"
parent="InputView"
>
<item name="android:elevation">8dp</item>
</style>
</resources>

View file

@ -12,7 +12,6 @@
<string name="prefs_debug_mode" translatable="false">Debug Mode</string>
<string name="prefs_show_suggestion_infos" translatable="false">Show suggestion infos</string>
<string name="prefs_force_non_distinct_multitouch" translatable="false">Force non-distinct multitouch</string>
<string name="prefs_should_show_lxx_suggestion_ui" translatable="false">Show LXX suggestion UI</string>
<!-- Option to enable sliding key input indicator. The user can see a rubber band-like effect during sliding key input. [CHAR LIMIT=30]-->
<string name="sliding_key_input_preview" translatable="false">Show slide indicator</string>
<!-- Option summary to enable sliding key input indicator. The user can see a rubber band-like effect during sliding key input. [CHAR LIMIT=66]-->

View file

@ -6,5 +6,8 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="platformActivityTheme" parent="Theme.AppCompat.DayNight" />
<style name="platformActivityTheme" parent="Theme.AppCompat.DayNight">
<item name="android:colorAccent">@color/accent</item>
<item name="colorAccent">@color/accent</item>
</style>
</resources>

View file

@ -8,7 +8,9 @@
<style
name="InputView.LXX"
parent="InputView"
/>
>
<item name="android:elevation">8dp</item>
</style>
<!-- LXX KeyboardView theme -->
<style
name="KeyboardView.LXX"

View file

@ -28,11 +28,6 @@
android:title="@string/prefs_force_non_distinct_multitouch"
android:defaultValue="false"
android:persistent="true" />
<SwitchPreferenceCompat
android:key="pref_should_show_lxx_suggestion_ui"
android:title="@string/prefs_should_show_lxx_suggestion_ui"
android:defaultValue="true"
android:persistent="true" />
<SwitchPreferenceCompat
android:key="pref_sliding_key_input_preview"
android:title="@string/sliding_key_input_preview"