mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-04-24 08:36:26 +00:00
convert compat utils to kotlin and cleanup
This commit is contained in:
parent
fa36013750
commit
bb88c6ec00
115 changed files with 977 additions and 2235 deletions
|
@ -13,7 +13,6 @@ import android.view.accessibility.AccessibilityEvent
|
|||
import android.view.accessibility.AccessibilityManager
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.core.view.accessibility.AccessibilityEventCompat
|
||||
import org.dslul.openboard.inputmethod.compat.SettingsSecureCompatUtils
|
||||
import org.dslul.openboard.inputmethod.latin.R
|
||||
import org.dslul.openboard.inputmethod.latin.SuggestedWords
|
||||
import org.dslul.openboard.inputmethod.latin.utils.InputTypeUtils
|
||||
|
@ -61,9 +60,9 @@ class AccessibilityUtils private constructor() {
|
|||
fun shouldObscureInput(editorInfo: EditorInfo?): Boolean {
|
||||
if (editorInfo == null) return false
|
||||
// The user can optionally force speaking passwords.
|
||||
if (SettingsSecureCompatUtils.ACCESSIBILITY_SPEAK_PASSWORD != null) {
|
||||
if (Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD != null) {
|
||||
val speakPassword = Settings.Secure.getInt(mContext!!.contentResolver,
|
||||
SettingsSecureCompatUtils.ACCESSIBILITY_SPEAK_PASSWORD, 0) != 0
|
||||
Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0) != 0
|
||||
if (speakPassword) return false
|
||||
}
|
||||
// Always speak if the user is listening through headphones.
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ActivityManagerCompatUtils {
|
||||
private static final Object LOCK = new Object();
|
||||
private static volatile Boolean sBoolean = null;
|
||||
private static final Method METHOD_isLowRamDevice = CompatUtils.getMethod(
|
||||
ActivityManager.class, "isLowRamDevice");
|
||||
|
||||
private ActivityManagerCompatUtils() {
|
||||
// Do not instantiate this class.
|
||||
}
|
||||
|
||||
public static boolean isLowRamDevice(Context context) {
|
||||
if (sBoolean == null) {
|
||||
synchronized(LOCK) {
|
||||
if (sBoolean == null) {
|
||||
final ActivityManager am =
|
||||
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
sBoolean = (Boolean)CompatUtils.invoke(am, false, METHOD_isLowRamDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sBoolean;
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.content.pm.PackageInfo;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class AppWorkaroundsHelper {
|
||||
private AppWorkaroundsHelper() {
|
||||
// This helper class is not publicly instantiable.
|
||||
}
|
||||
|
||||
public static boolean evaluateIsBrokenByRecorrection(final PackageInfo info) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
|
||||
/**
|
||||
* A class to encapsulate work-arounds specific to particular apps.
|
||||
*/
|
||||
public class AppWorkaroundsUtils {
|
||||
private final PackageInfo mPackageInfo; // May be null
|
||||
private final boolean mIsBrokenByRecorrection;
|
||||
|
||||
public AppWorkaroundsUtils(final PackageInfo packageInfo) {
|
||||
mPackageInfo = packageInfo;
|
||||
mIsBrokenByRecorrection = AppWorkaroundsHelper.evaluateIsBrokenByRecorrection(
|
||||
packageInfo);
|
||||
}
|
||||
|
||||
public boolean isBrokenByRecorrection() {
|
||||
return mIsBrokenByRecorrection;
|
||||
}
|
||||
|
||||
public boolean isBeforeJellyBean() {
|
||||
if (null == mPackageInfo || null == mPackageInfo.applicationInfo) {
|
||||
return false;
|
||||
}
|
||||
return mPackageInfo.applicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (null == mPackageInfo || null == mPackageInfo.applicationInfo) {
|
||||
return "";
|
||||
}
|
||||
final StringBuilder s = new StringBuilder();
|
||||
s.append("Target application : ")
|
||||
.append(mPackageInfo.applicationInfo.name)
|
||||
.append("\nPackage : ")
|
||||
.append(mPackageInfo.applicationInfo.packageName)
|
||||
.append("\nTarget app sdk version : ")
|
||||
.append(mPackageInfo.applicationInfo.targetSdkVersion);
|
||||
return s.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package org.dslul.openboard.inputmethod.compat
|
||||
|
||||
import android.content.pm.PackageInfo
|
||||
|
||||
/**
|
||||
* A class to encapsulate work-arounds specific to particular apps.
|
||||
*/
|
||||
class AppWorkaroundsUtils(private val mPackageInfo: PackageInfo?) {
|
||||
override fun toString(): String {
|
||||
if (mPackageInfo?.applicationInfo == null) {
|
||||
return ""
|
||||
}
|
||||
val s = StringBuilder()
|
||||
s.append("Target application : ")
|
||||
.append(mPackageInfo.applicationInfo.name)
|
||||
.append("\nPackage : ")
|
||||
.append(mPackageInfo.applicationInfo.packageName)
|
||||
.append("\nTarget app sdk version : ")
|
||||
.append(mPackageInfo.applicationInfo.targetSdkVersion)
|
||||
return s.toString()
|
||||
}
|
||||
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
public final class BuildCompatUtils {
|
||||
private BuildCompatUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
private static final boolean IS_RELEASE_BUILD = Build.VERSION.CODENAME.equals("REL");
|
||||
|
||||
/**
|
||||
* The "effective" API version.
|
||||
* {@link android.os.Build.VERSION#SDK_INT} if the platform is a release build.
|
||||
* {@link android.os.Build.VERSION#SDK_INT} plus 1 if the platform is a development build.
|
||||
*/
|
||||
public static final int EFFECTIVE_SDK_INT = IS_RELEASE_BUILD
|
||||
? Build.VERSION.SDK_INT
|
||||
: Build.VERSION.SDK_INT + 1;
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public final class CharacterCompat {
|
||||
// Note that Character.isAlphabetic(int), has been introduced in API level 19
|
||||
// (Build.VERSION_CODE.KITKAT).
|
||||
private static final Method METHOD_isAlphabetic = CompatUtils.getMethod(
|
||||
Character.class, "isAlphabetic", int.class);
|
||||
|
||||
private CharacterCompat() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
public static boolean isAlphabetic(final int code) {
|
||||
if (METHOD_isAlphabetic != null) {
|
||||
return (Boolean)CompatUtils.invoke(null, false, METHOD_isAlphabetic, code);
|
||||
}
|
||||
switch (Character.getType(code)) {
|
||||
case Character.UPPERCASE_LETTER:
|
||||
case Character.LOWERCASE_LETTER:
|
||||
case Character.TITLECASE_LETTER:
|
||||
case Character.MODIFIER_LETTER:
|
||||
case Character.OTHER_LETTER:
|
||||
case Character.LETTER_NUMBER:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,218 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public final class CompatUtils {
|
||||
private static final String TAG = CompatUtils.class.getSimpleName();
|
||||
|
||||
private CompatUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
public static Class<?> getClass(final String className) {
|
||||
try {
|
||||
return Class.forName(className);
|
||||
} catch (final ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Method getMethod(final Class<?> targetClass, final String name,
|
||||
final Class<?>... parameterTypes) {
|
||||
if (targetClass == null || TextUtils.isEmpty(name)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return targetClass.getMethod(name, parameterTypes);
|
||||
} catch (final SecurityException | NoSuchMethodException e) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Field getField(final Class<?> targetClass, final String name) {
|
||||
if (targetClass == null || TextUtils.isEmpty(name)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return targetClass.getField(name);
|
||||
} catch (final SecurityException | NoSuchFieldException e) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Constructor<?> getConstructor(final Class<?> targetClass,
|
||||
final Class<?> ... types) {
|
||||
if (targetClass == null || types == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return targetClass.getConstructor(types);
|
||||
} catch (final SecurityException | NoSuchMethodException e) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object newInstance(final Constructor<?> constructor, final Object ... args) {
|
||||
if (constructor == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return constructor.newInstance(args);
|
||||
} catch (final InstantiationException | IllegalAccessException | IllegalArgumentException
|
||||
| InvocationTargetException e) {
|
||||
Log.e(TAG, "Exception in newInstance", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object invoke(final Object receiver, final Object defaultValue,
|
||||
final Method method, final Object... args) {
|
||||
if (method == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return method.invoke(receiver, args);
|
||||
} catch (final IllegalAccessException | IllegalArgumentException
|
||||
| InvocationTargetException e) {
|
||||
Log.e(TAG, "Exception in invoke", e);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static Object getFieldValue(final Object receiver, final Object defaultValue,
|
||||
final Field field) {
|
||||
if (field == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return field.get(receiver);
|
||||
} catch (final IllegalAccessException | IllegalArgumentException e) {
|
||||
Log.e(TAG, "Exception in getFieldValue", e);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static void setFieldValue(final Object receiver, final Field field, final Object value) {
|
||||
if (field == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
field.set(receiver, value);
|
||||
} catch (final IllegalAccessException | IllegalArgumentException e) {
|
||||
Log.e(TAG, "Exception in setFieldValue", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static ClassWrapper getClassWrapper(final String className) {
|
||||
return new ClassWrapper(getClass(className));
|
||||
}
|
||||
|
||||
public static final class ClassWrapper {
|
||||
private final Class<?> mClass;
|
||||
public ClassWrapper(final Class<?> targetClass) {
|
||||
mClass = targetClass;
|
||||
}
|
||||
|
||||
public boolean exists() {
|
||||
return mClass != null;
|
||||
}
|
||||
|
||||
public <T> ToObjectMethodWrapper<T> getMethod(final String name,
|
||||
final T defaultValue, final Class<?>... parameterTypes) {
|
||||
return new ToObjectMethodWrapper<>(CompatUtils.getMethod(mClass, name, parameterTypes),
|
||||
defaultValue);
|
||||
}
|
||||
|
||||
public ToIntMethodWrapper getPrimitiveMethod(final String name, final int defaultValue,
|
||||
final Class<?>... parameterTypes) {
|
||||
return new ToIntMethodWrapper(CompatUtils.getMethod(mClass, name, parameterTypes),
|
||||
defaultValue);
|
||||
}
|
||||
|
||||
public ToFloatMethodWrapper getPrimitiveMethod(final String name, final float defaultValue,
|
||||
final Class<?>... parameterTypes) {
|
||||
return new ToFloatMethodWrapper(CompatUtils.getMethod(mClass, name, parameterTypes),
|
||||
defaultValue);
|
||||
}
|
||||
|
||||
public ToBooleanMethodWrapper getPrimitiveMethod(final String name,
|
||||
final boolean defaultValue, final Class<?>... parameterTypes) {
|
||||
return new ToBooleanMethodWrapper(CompatUtils.getMethod(mClass, name, parameterTypes),
|
||||
defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ToObjectMethodWrapper<T> {
|
||||
private final Method mMethod;
|
||||
private final T mDefaultValue;
|
||||
public ToObjectMethodWrapper(final Method method, final T defaultValue) {
|
||||
mMethod = method;
|
||||
mDefaultValue = defaultValue;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public T invoke(final Object receiver, final Object... args) {
|
||||
return (T) CompatUtils.invoke(receiver, mDefaultValue, mMethod, args);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ToIntMethodWrapper {
|
||||
private final Method mMethod;
|
||||
private final int mDefaultValue;
|
||||
public ToIntMethodWrapper(final Method method, final int defaultValue) {
|
||||
mMethod = method;
|
||||
mDefaultValue = defaultValue;
|
||||
}
|
||||
public int invoke(final Object receiver, final Object... args) {
|
||||
return (int) CompatUtils.invoke(receiver, mDefaultValue, mMethod, args);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ToFloatMethodWrapper {
|
||||
private final Method mMethod;
|
||||
private final float mDefaultValue;
|
||||
public ToFloatMethodWrapper(final Method method, final float defaultValue) {
|
||||
mMethod = method;
|
||||
mDefaultValue = defaultValue;
|
||||
}
|
||||
public float invoke(final Object receiver, final Object... args) {
|
||||
return (float) CompatUtils.invoke(receiver, mDefaultValue, mMethod, args);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ToBooleanMethodWrapper {
|
||||
private final Method mMethod;
|
||||
private final boolean mDefaultValue;
|
||||
public ToBooleanMethodWrapper(final Method method, final boolean defaultValue) {
|
||||
mMethod = method;
|
||||
mDefaultValue = defaultValue;
|
||||
}
|
||||
public boolean invoke(final Object receiver, final Object... args) {
|
||||
return (boolean) CompatUtils.invoke(receiver, mDefaultValue, mMethod, args);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
package org.dslul.openboard.inputmethod.compat
|
||||
|
||||
import android.text.TextUtils
|
||||
import android.util.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 (e: SecurityException) { // ignore
|
||||
} catch (e: NoSuchMethodException) {
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getField(targetClass: Class<*>?, name: String?): Field? {
|
||||
if (targetClass == null || TextUtils.isEmpty(name)) {
|
||||
return null
|
||||
}
|
||||
try {
|
||||
return targetClass.getField(name!!)
|
||||
} catch (e: SecurityException) { // ignore
|
||||
} catch (e: NoSuchFieldException) {
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getConstructor(targetClass: Class<*>?,
|
||||
vararg types: Class<*>?): Constructor<*>? {
|
||||
if (targetClass == null || types == null) {
|
||||
return null
|
||||
}
|
||||
try {
|
||||
return targetClass.getConstructor(*types)
|
||||
} catch (e: SecurityException) { // ignore
|
||||
} catch (e: 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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,185 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.view.inputmethod.CursorAnchorInfo;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A wrapper for {@link CursorAnchorInfo}, which has been introduced in API Level 21. You can use
|
||||
* this wrapper to avoid direct dependency on newly introduced types.
|
||||
*/
|
||||
public class CursorAnchorInfoCompatWrapper {
|
||||
|
||||
/**
|
||||
* The insertion marker or character bounds have at least one visible region.
|
||||
*/
|
||||
public static final int FLAG_HAS_VISIBLE_REGION = 0x01;
|
||||
|
||||
/**
|
||||
* The insertion marker or character bounds have at least one invisible (clipped) region.
|
||||
*/
|
||||
public static final int FLAG_HAS_INVISIBLE_REGION = 0x02;
|
||||
|
||||
/**
|
||||
* The insertion marker or character bounds is placed at right-to-left (RTL) character.
|
||||
*/
|
||||
public static final int FLAG_IS_RTL = 0x04;
|
||||
|
||||
CursorAnchorInfoCompatWrapper() {
|
||||
// This class is not publicly instantiable.
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@Nullable
|
||||
public static CursorAnchorInfoCompatWrapper wrap(@Nullable final CursorAnchorInfo instance) {
|
||||
if (BuildCompatUtils.EFFECTIVE_SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return null;
|
||||
}
|
||||
if (instance == null) {
|
||||
return null;
|
||||
}
|
||||
return new RealWrapper(instance);
|
||||
}
|
||||
|
||||
public int getSelectionStart() {
|
||||
throw new UnsupportedOperationException("not supported.");
|
||||
}
|
||||
|
||||
public int getSelectionEnd() {
|
||||
throw new UnsupportedOperationException("not supported.");
|
||||
}
|
||||
|
||||
public CharSequence getComposingText() {
|
||||
throw new UnsupportedOperationException("not supported.");
|
||||
}
|
||||
|
||||
public int getComposingTextStart() {
|
||||
throw new UnsupportedOperationException("not supported.");
|
||||
}
|
||||
|
||||
public Matrix getMatrix() {
|
||||
throw new UnsupportedOperationException("not supported.");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public RectF getCharacterBounds(final int index) {
|
||||
throw new UnsupportedOperationException("not supported.");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public int getCharacterBoundsFlags(final int index) {
|
||||
throw new UnsupportedOperationException("not supported.");
|
||||
}
|
||||
|
||||
public float getInsertionMarkerBaseline() {
|
||||
throw new UnsupportedOperationException("not supported.");
|
||||
}
|
||||
|
||||
public float getInsertionMarkerBottom() {
|
||||
throw new UnsupportedOperationException("not supported.");
|
||||
}
|
||||
|
||||
public float getInsertionMarkerHorizontal() {
|
||||
throw new UnsupportedOperationException("not supported.");
|
||||
}
|
||||
|
||||
public float getInsertionMarkerTop() {
|
||||
throw new UnsupportedOperationException("not supported.");
|
||||
}
|
||||
|
||||
public int getInsertionMarkerFlags() {
|
||||
throw new UnsupportedOperationException("not supported.");
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private static final class RealWrapper extends CursorAnchorInfoCompatWrapper {
|
||||
|
||||
@Nonnull
|
||||
private final CursorAnchorInfo mInstance;
|
||||
|
||||
public RealWrapper(@Nonnull final CursorAnchorInfo info) {
|
||||
mInstance = info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSelectionStart() {
|
||||
return mInstance.getSelectionStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSelectionEnd() {
|
||||
return mInstance.getSelectionEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getComposingText() {
|
||||
return mInstance.getComposingText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getComposingTextStart() {
|
||||
return mInstance.getComposingTextStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Matrix getMatrix() {
|
||||
return mInstance.getMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RectF getCharacterBounds(final int index) {
|
||||
return mInstance.getCharacterBounds(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharacterBoundsFlags(final int index) {
|
||||
return mInstance.getCharacterBoundsFlags(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getInsertionMarkerBaseline() {
|
||||
return mInstance.getInsertionMarkerBaseline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getInsertionMarkerBottom() {
|
||||
return mInstance.getInsertionMarkerBottom();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getInsertionMarkerHorizontal() {
|
||||
return mInstance.getInsertionMarkerHorizontal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getInsertionMarkerTop() {
|
||||
return mInstance.getInsertionMarkerTop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInsertionMarkerFlags() {
|
||||
return mInstance.getInsertionMarkerFlags();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
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
|
||||
|
||||
@kotlin.jvm.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) }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class EditorInfoCompatUtils {
|
||||
// Note that EditorInfo.IME_FLAG_FORCE_ASCII has been introduced
|
||||
// in API level 16 (Build.VERSION_CODES.JELLY_BEAN).
|
||||
private static final Field FIELD_IME_FLAG_FORCE_ASCII = CompatUtils.getField(
|
||||
EditorInfo.class, "IME_FLAG_FORCE_ASCII");
|
||||
private static final Integer OBJ_IME_FLAG_FORCE_ASCII = (Integer) CompatUtils.getFieldValue(
|
||||
null /* receiver */, null /* defaultValue */, FIELD_IME_FLAG_FORCE_ASCII);
|
||||
private static final Field FIELD_HINT_LOCALES = CompatUtils.getField(
|
||||
EditorInfo.class, "hintLocales");
|
||||
|
||||
private EditorInfoCompatUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
public static boolean hasFlagForceAscii(final int imeOptions) {
|
||||
if (OBJ_IME_FLAG_FORCE_ASCII == null) return false;
|
||||
return (imeOptions & OBJ_IME_FLAG_FORCE_ASCII) != 0;
|
||||
}
|
||||
|
||||
public static String imeActionName(final int imeOptions) {
|
||||
final int actionId = imeOptions & EditorInfo.IME_MASK_ACTION;
|
||||
switch (actionId) {
|
||||
case EditorInfo.IME_ACTION_UNSPECIFIED:
|
||||
return "actionUnspecified";
|
||||
case EditorInfo.IME_ACTION_NONE:
|
||||
return "actionNone";
|
||||
case EditorInfo.IME_ACTION_GO:
|
||||
return "actionGo";
|
||||
case EditorInfo.IME_ACTION_SEARCH:
|
||||
return "actionSearch";
|
||||
case EditorInfo.IME_ACTION_SEND:
|
||||
return "actionSend";
|
||||
case EditorInfo.IME_ACTION_NEXT:
|
||||
return "actionNext";
|
||||
case EditorInfo.IME_ACTION_DONE:
|
||||
return "actionDone";
|
||||
case EditorInfo.IME_ACTION_PREVIOUS:
|
||||
return "actionPrevious";
|
||||
default:
|
||||
return "actionUnknown(" + actionId + ")";
|
||||
}
|
||||
}
|
||||
|
||||
public static String imeOptionsName(final int imeOptions) {
|
||||
final String action = imeActionName(imeOptions);
|
||||
final StringBuilder flags = new StringBuilder();
|
||||
if ((imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
|
||||
flags.append("flagNoEnterAction|");
|
||||
}
|
||||
if ((imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0) {
|
||||
flags.append("flagNavigateNext|");
|
||||
}
|
||||
if ((imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0) {
|
||||
flags.append("flagNavigatePrevious|");
|
||||
}
|
||||
if (hasFlagForceAscii(imeOptions)) {
|
||||
flags.append("flagForceAscii|");
|
||||
}
|
||||
return (action != null) ? flags + action : flags.toString();
|
||||
}
|
||||
|
||||
public static Locale getPrimaryHintLocale(final EditorInfo editorInfo) {
|
||||
if (editorInfo == null) {
|
||||
return null;
|
||||
}
|
||||
final Object localeList = CompatUtils.getFieldValue(editorInfo, null, FIELD_HINT_LOCALES);
|
||||
if (localeList == null) {
|
||||
return null;
|
||||
}
|
||||
if (LocaleListCompatUtils.isEmpty(localeList)) {
|
||||
return null;
|
||||
}
|
||||
return LocaleListCompatUtils.get(localeList, 0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package org.dslul.openboard.inputmethod.compat
|
||||
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import java.util.*
|
||||
|
||||
object EditorInfoCompatUtils {
|
||||
// Note that EditorInfo.IME_FLAG_FORCE_ASCII has been introduced
|
||||
// in API level 16 (Build.VERSION_CODES.JELLY_BEAN).
|
||||
private val FIELD_IME_FLAG_FORCE_ASCII = CompatUtils.getField(
|
||||
EditorInfo::class.java, "IME_FLAG_FORCE_ASCII")
|
||||
private val OBJ_IME_FLAG_FORCE_ASCII: Int? = CompatUtils.getFieldValue(
|
||||
null /* receiver */, null /* defaultValue */, FIELD_IME_FLAG_FORCE_ASCII) as Int
|
||||
private val FIELD_HINT_LOCALES = CompatUtils.getField(
|
||||
EditorInfo::class.java, "hintLocales")
|
||||
|
||||
@kotlin.jvm.JvmStatic
|
||||
fun hasFlagForceAscii(imeOptions: Int): Boolean {
|
||||
return if (OBJ_IME_FLAG_FORCE_ASCII == null) false else imeOptions and OBJ_IME_FLAG_FORCE_ASCII != 0
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmStatic
|
||||
fun imeActionName(imeOptions: Int): String {
|
||||
val actionId = imeOptions and EditorInfo.IME_MASK_ACTION
|
||||
return when (actionId) {
|
||||
EditorInfo.IME_ACTION_UNSPECIFIED -> "actionUnspecified"
|
||||
EditorInfo.IME_ACTION_NONE -> "actionNone"
|
||||
EditorInfo.IME_ACTION_GO -> "actionGo"
|
||||
EditorInfo.IME_ACTION_SEARCH -> "actionSearch"
|
||||
EditorInfo.IME_ACTION_SEND -> "actionSend"
|
||||
EditorInfo.IME_ACTION_NEXT -> "actionNext"
|
||||
EditorInfo.IME_ACTION_DONE -> "actionDone"
|
||||
EditorInfo.IME_ACTION_PREVIOUS -> "actionPrevious"
|
||||
else -> "actionUnknown($actionId)"
|
||||
}
|
||||
}
|
||||
|
||||
fun imeOptionsName(imeOptions: Int): String {
|
||||
val action = imeActionName(imeOptions)
|
||||
val flags = StringBuilder()
|
||||
if (imeOptions and EditorInfo.IME_FLAG_NO_ENTER_ACTION != 0) {
|
||||
flags.append("flagNoEnterAction|")
|
||||
}
|
||||
if (imeOptions and EditorInfo.IME_FLAG_NAVIGATE_NEXT != 0) {
|
||||
flags.append("flagNavigateNext|")
|
||||
}
|
||||
if (imeOptions and EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS != 0) {
|
||||
flags.append("flagNavigatePrevious|")
|
||||
}
|
||||
if (hasFlagForceAscii(imeOptions)) {
|
||||
flags.append("flagForceAscii|")
|
||||
}
|
||||
return if (action != null) flags.toString() + action else flags.toString()
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmStatic
|
||||
fun getPrimaryHintLocale(editorInfo: EditorInfo?): Locale? {
|
||||
if (editorInfo == null) {
|
||||
return null
|
||||
}
|
||||
val localeList = CompatUtils.getFieldValue(editorInfo, null, FIELD_HINT_LOCALES)
|
||||
?: return null
|
||||
return if (LocaleListCompatUtils.isEmpty(localeList)) {
|
||||
null
|
||||
} else LocaleListCompatUtils.get(localeList, 0)
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
public final class InputConnectionCompatUtils {
|
||||
private static final CompatUtils.ClassWrapper sInputConnectionType;
|
||||
private static final CompatUtils.ToBooleanMethodWrapper sRequestCursorUpdatesMethod;
|
||||
static {
|
||||
sInputConnectionType = new CompatUtils.ClassWrapper(InputConnection.class);
|
||||
sRequestCursorUpdatesMethod = sInputConnectionType.getPrimitiveMethod(
|
||||
"requestCursorUpdates", false, int.class);
|
||||
}
|
||||
|
||||
public static boolean isRequestCursorUpdatesAvailable() {
|
||||
return sRequestCursorUpdatesMethod != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Local copies of some constants in InputConnection until the SDK becomes publicly available.
|
||||
*/
|
||||
private static int CURSOR_UPDATE_IMMEDIATE = 1 << 0;
|
||||
private static int CURSOR_UPDATE_MONITOR = 1 << 1;
|
||||
|
||||
private static boolean requestCursorUpdatesImpl(final InputConnection inputConnection,
|
||||
final int cursorUpdateMode) {
|
||||
if (!isRequestCursorUpdatesAvailable()) {
|
||||
return false;
|
||||
}
|
||||
return sRequestCursorUpdatesMethod.invoke(inputConnection, cursorUpdateMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the editor to call back {@link InputMethodManager#updateCursorAnchorInfo}.
|
||||
* @param inputConnection the input connection to which the request is to be sent.
|
||||
* @param enableMonitor {@code true} to request the editor to call back the method whenever the
|
||||
* cursor/anchor position is changed.
|
||||
* @param requestImmediateCallback {@code true} to request the editor to call back the method
|
||||
* as soon as possible to notify the current cursor/anchor position to the input method.
|
||||
* @return {@code false} if the request is not handled. Otherwise returns {@code true}.
|
||||
*/
|
||||
public static boolean requestCursorUpdates(final InputConnection inputConnection,
|
||||
final boolean enableMonitor, final boolean requestImmediateCallback) {
|
||||
final int cursorUpdateMode = (enableMonitor ? CURSOR_UPDATE_MONITOR : 0)
|
||||
| (requestImmediateCallback ? CURSOR_UPDATE_IMMEDIATE : 0);
|
||||
return requestCursorUpdatesImpl(inputConnection, cursorUpdateMode);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package org.dslul.openboard.inputmethod.compat
|
||||
|
||||
import android.view.inputmethod.InputConnection
|
||||
import org.dslul.openboard.inputmethod.compat.CompatUtils.ClassWrapper
|
||||
import org.dslul.openboard.inputmethod.compat.CompatUtils.ToBooleanMethodWrapper
|
||||
|
||||
object InputConnectionCompatUtils {
|
||||
private var sInputConnectionType: ClassWrapper? = null
|
||||
private var sRequestCursorUpdatesMethod: ToBooleanMethodWrapper? = null
|
||||
val isRequestCursorUpdatesAvailable: Boolean
|
||||
get() = sRequestCursorUpdatesMethod != null
|
||||
|
||||
/**
|
||||
* Local copies of some constants in InputConnection until the SDK becomes publicly available.
|
||||
*/
|
||||
private const val CURSOR_UPDATE_IMMEDIATE = 1 shl 0
|
||||
private const val CURSOR_UPDATE_MONITOR = 1 shl 1
|
||||
private fun requestCursorUpdatesImpl(inputConnection: InputConnection,
|
||||
cursorUpdateMode: Int): Boolean {
|
||||
return if (!isRequestCursorUpdatesAvailable) {
|
||||
false
|
||||
} else sRequestCursorUpdatesMethod!!.invoke(inputConnection, cursorUpdateMode)
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the editor to call back [InputMethodManager.updateCursorAnchorInfo].
|
||||
* @param inputConnection the input connection to which the request is to be sent.
|
||||
* @param enableMonitor `true` to request the editor to call back the method whenever the
|
||||
* cursor/anchor position is changed.
|
||||
* @param requestImmediateCallback `true` to request the editor to call back the method
|
||||
* as soon as possible to notify the current cursor/anchor position to the input method.
|
||||
* @return `false` if the request is not handled. Otherwise returns `true`.
|
||||
*/
|
||||
@kotlin.jvm.JvmStatic
|
||||
fun requestCursorUpdates(inputConnection: InputConnection,
|
||||
enableMonitor: Boolean, requestImmediateCallback: Boolean): Boolean {
|
||||
val cursorUpdateMode = ((if (enableMonitor) CURSOR_UPDATE_MONITOR else 0)
|
||||
or if (requestImmediateCallback) CURSOR_UPDATE_IMMEDIATE else 0)
|
||||
return requestCursorUpdatesImpl(inputConnection, cursorUpdateMode)
|
||||
}
|
||||
|
||||
init {
|
||||
sInputConnectionType = ClassWrapper(InputConnection::class.java)
|
||||
sRequestCursorUpdatesMethod = sInputConnectionType!!.getPrimitiveMethod(
|
||||
"requestCursorUpdates", false, Int::class.javaPrimitiveType)
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.IBinder;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public final class InputMethodManagerCompatWrapper {
|
||||
// Note that InputMethodManager.switchToNextInputMethod() has been introduced
|
||||
// in API level 16 (Build.VERSION_CODES.JELLY_BEAN).
|
||||
private static final Method METHOD_switchToNextInputMethod = CompatUtils.getMethod(
|
||||
InputMethodManager.class, "switchToNextInputMethod", IBinder.class, boolean.class);
|
||||
|
||||
// Note that InputMethodManager.shouldOfferSwitchingToNextInputMethod() has been introduced
|
||||
// in API level 19 (Build.VERSION_CODES.KITKAT).
|
||||
private static final Method METHOD_shouldOfferSwitchingToNextInputMethod =
|
||||
CompatUtils.getMethod(InputMethodManager.class,
|
||||
"shouldOfferSwitchingToNextInputMethod", IBinder.class);
|
||||
|
||||
public final InputMethodManager mImm;
|
||||
|
||||
public InputMethodManagerCompatWrapper(final Context context) {
|
||||
mImm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
}
|
||||
|
||||
public boolean switchToNextInputMethod(final IBinder token, final boolean onlyCurrentIme) {
|
||||
return (Boolean)CompatUtils.invoke(mImm, false /* defaultValue */,
|
||||
METHOD_switchToNextInputMethod, token, onlyCurrentIme);
|
||||
}
|
||||
|
||||
public boolean shouldOfferSwitchingToNextInputMethod(final IBinder token) {
|
||||
return (Boolean)CompatUtils.invoke(mImm, false /* defaultValue */,
|
||||
METHOD_shouldOfferSwitchingToNextInputMethod, token);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package org.dslul.openboard.inputmethod.compat
|
||||
|
||||
import android.content.Context
|
||||
import android.os.IBinder
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
|
||||
class InputMethodManagerCompatWrapper(context: Context) {
|
||||
@kotlin.jvm.JvmField
|
||||
val mImm: InputMethodManager
|
||||
fun switchToNextInputMethod(token: IBinder?, onlyCurrentIme: Boolean): Boolean {
|
||||
return CompatUtils.invoke(mImm, false /* defaultValue */,
|
||||
METHOD_switchToNextInputMethod, token, onlyCurrentIme) as Boolean
|
||||
}
|
||||
|
||||
fun shouldOfferSwitchingToNextInputMethod(token: IBinder?): Boolean {
|
||||
return CompatUtils.invoke(mImm, false /* defaultValue */,
|
||||
METHOD_shouldOfferSwitchingToNextInputMethod, token) as Boolean
|
||||
}
|
||||
|
||||
companion object {
|
||||
// Note that InputMethodManager.switchToNextInputMethod() has been introduced
|
||||
// in API level 16 (Build.VERSION_CODES.JELLY_BEAN).
|
||||
private val METHOD_switchToNextInputMethod = CompatUtils.getMethod(
|
||||
InputMethodManager::class.java, "switchToNextInputMethod", IBinder::class.java, Boolean::class.javaPrimitiveType)
|
||||
// Note that InputMethodManager.shouldOfferSwitchingToNextInputMethod() has been introduced
|
||||
// in API level 19 (Build.VERSION_CODES.KITKAT).
|
||||
private val METHOD_shouldOfferSwitchingToNextInputMethod = CompatUtils.getMethod(InputMethodManager::class.java,
|
||||
"shouldOfferSwitchingToNextInputMethod", IBinder::class.java)
|
||||
}
|
||||
|
||||
init {
|
||||
mImm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public final class InputMethodServiceCompatUtils {
|
||||
// Note that {@link InputMethodService#enableHardwareAcceleration} has been introduced
|
||||
// in API level 17 (Build.VERSION_CODES.JELLY_BEAN_MR1).
|
||||
private static final Method METHOD_enableHardwareAcceleration =
|
||||
CompatUtils.getMethod(InputMethodService.class, "enableHardwareAcceleration");
|
||||
|
||||
private InputMethodServiceCompatUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
public static boolean enableHardwareAcceleration(final InputMethodService ims) {
|
||||
return (Boolean)CompatUtils.invoke(ims, false /* defaultValue */,
|
||||
METHOD_enableHardwareAcceleration);
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
||||
import org.dslul.openboard.inputmethod.latin.RichInputMethodSubtype;
|
||||
import org.dslul.openboard.inputmethod.latin.common.Constants;
|
||||
import org.dslul.openboard.inputmethod.latin.common.LocaleUtils;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public final class InputMethodSubtypeCompatUtils {
|
||||
private static final String TAG = InputMethodSubtypeCompatUtils.class.getSimpleName();
|
||||
// Note that InputMethodSubtype(int nameId, int iconId, String locale, String mode,
|
||||
// String extraValue, boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, int id)
|
||||
// has been introduced in API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1).
|
||||
private static final Constructor<?> CONSTRUCTOR_INPUT_METHOD_SUBTYPE =
|
||||
CompatUtils.getConstructor(InputMethodSubtype.class,
|
||||
int.class, int.class, String.class, String.class, String.class, boolean.class,
|
||||
boolean.class, int.class);
|
||||
static {
|
||||
if (CONSTRUCTOR_INPUT_METHOD_SUBTYPE == null) {
|
||||
android.util.Log.w(TAG, "Warning!!! Constructor is not defined.");
|
||||
}
|
||||
}
|
||||
|
||||
// Note that {@link InputMethodSubtype#isAsciiCapable()} has been introduced in API level 19
|
||||
// (Build.VERSION_CODE.KITKAT).
|
||||
private static final Method METHOD_isAsciiCapable = CompatUtils.getMethod(
|
||||
InputMethodSubtype.class, "isAsciiCapable");
|
||||
|
||||
private InputMethodSubtypeCompatUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Nonnull
|
||||
public static InputMethodSubtype newInputMethodSubtype(int nameId, int iconId, String locale,
|
||||
String mode, String extraValue, boolean isAuxiliary,
|
||||
boolean overridesImplicitlyEnabledSubtype, int id) {
|
||||
if (CONSTRUCTOR_INPUT_METHOD_SUBTYPE == null) {
|
||||
return new InputMethodSubtype(nameId, iconId, locale, mode, extraValue, isAuxiliary,
|
||||
overridesImplicitlyEnabledSubtype);
|
||||
}
|
||||
return (InputMethodSubtype) CompatUtils.newInstance(CONSTRUCTOR_INPUT_METHOD_SUBTYPE,
|
||||
nameId, iconId, locale, mode, extraValue, isAuxiliary,
|
||||
overridesImplicitlyEnabledSubtype, id);
|
||||
}
|
||||
|
||||
public static boolean isAsciiCapable(final RichInputMethodSubtype subtype) {
|
||||
return isAsciiCapable(subtype.getRawSubtype());
|
||||
}
|
||||
|
||||
public static boolean isAsciiCapable(final InputMethodSubtype subtype) {
|
||||
return isAsciiCapableWithAPI(subtype)
|
||||
|| subtype.containsExtraValueKey(Constants.Subtype.ExtraValue.ASCII_CAPABLE);
|
||||
}
|
||||
|
||||
// Note that InputMethodSubtype.getLanguageTag() is expected to be available in Android N+.
|
||||
private static final Method GET_LANGUAGE_TAG =
|
||||
CompatUtils.getMethod(InputMethodSubtype.class, "getLanguageTag");
|
||||
|
||||
public static Locale getLocaleObject(final InputMethodSubtype subtype) {
|
||||
// Locale.forLanguageTag() is available only in Android L and later.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
final String languageTag = (String) CompatUtils.invoke(subtype, null, GET_LANGUAGE_TAG);
|
||||
if (!TextUtils.isEmpty(languageTag)) {
|
||||
return Locale.forLanguageTag(languageTag);
|
||||
}
|
||||
}
|
||||
return LocaleUtils.constructLocaleFromString(subtype.getLocale());
|
||||
}
|
||||
|
||||
@UsedForTesting
|
||||
public static boolean isAsciiCapableWithAPI(final InputMethodSubtype subtype) {
|
||||
return (Boolean)CompatUtils.invoke(subtype, false, METHOD_isAsciiCapable);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package org.dslul.openboard.inputmethod.compat
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Build.VERSION_CODES
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import android.view.inputmethod.InputMethodSubtype
|
||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting
|
||||
import org.dslul.openboard.inputmethod.latin.RichInputMethodSubtype
|
||||
import org.dslul.openboard.inputmethod.latin.common.Constants
|
||||
import org.dslul.openboard.inputmethod.latin.common.LocaleUtils
|
||||
import java.util.*
|
||||
|
||||
object InputMethodSubtypeCompatUtils {
|
||||
private val TAG = InputMethodSubtypeCompatUtils::class.java.simpleName
|
||||
// Note that InputMethodSubtype(int nameId, int iconId, String locale, String mode,
|
||||
// String extraValue, boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, int id)
|
||||
// has been introduced in API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1).
|
||||
private val CONSTRUCTOR_INPUT_METHOD_SUBTYPE = CompatUtils.getConstructor(InputMethodSubtype::class.java,
|
||||
Int::class.javaPrimitiveType, Int::class.javaPrimitiveType, String::class.java, String::class.java, String::class.java, Boolean::class.javaPrimitiveType,
|
||||
Boolean::class.javaPrimitiveType, Int::class.javaPrimitiveType)
|
||||
|
||||
@kotlin.jvm.JvmStatic
|
||||
fun newInputMethodSubtype(nameId: Int, iconId: Int, locale: String?,
|
||||
mode: String?, extraValue: String?, isAuxiliary: Boolean,
|
||||
overridesImplicitlyEnabledSubtype: Boolean, id: Int): InputMethodSubtype? {
|
||||
return if (CONSTRUCTOR_INPUT_METHOD_SUBTYPE == null) {
|
||||
InputMethodSubtype(nameId, iconId, locale, mode, extraValue, isAuxiliary,
|
||||
overridesImplicitlyEnabledSubtype)
|
||||
} else CompatUtils.newInstance(CONSTRUCTOR_INPUT_METHOD_SUBTYPE,
|
||||
nameId, iconId, locale, mode, extraValue, isAuxiliary,
|
||||
overridesImplicitlyEnabledSubtype, id) as InputMethodSubtype
|
||||
}
|
||||
|
||||
// Note that InputMethodSubtype.getLanguageTag() is expected to be available in Android N+.
|
||||
private val GET_LANGUAGE_TAG = CompatUtils.getMethod(InputMethodSubtype::class.java, "getLanguageTag")
|
||||
|
||||
@kotlin.jvm.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 (!TextUtils.isEmpty(languageTag)) {
|
||||
return Locale.forLanguageTag(languageTag)
|
||||
}
|
||||
}
|
||||
return LocaleUtils.constructLocaleFromString(subtype.locale)
|
||||
}
|
||||
|
||||
init {
|
||||
if (CONSTRUCTOR_INPUT_METHOD_SUBTYPE == null) {
|
||||
Log.w(TAG, "Warning!!! Constructor is not defined.")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
public final class IntentCompatUtils {
|
||||
// Note that Intent.ACTION_USER_INITIALIZE have been introduced in API level 17
|
||||
// (Build.VERSION_CODE.JELLY_BEAN_MR1).
|
||||
private static final String ACTION_USER_INITIALIZE =
|
||||
(String)CompatUtils.getFieldValue(null /* receiver */, null /* defaultValue */,
|
||||
CompatUtils.getField(Intent.class, "ACTION_USER_INITIALIZE"));
|
||||
|
||||
private IntentCompatUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
public static boolean is_ACTION_USER_INITIALIZE(final String action) {
|
||||
return ACTION_USER_INITIALIZE != null && ACTION_USER_INITIALIZE.equals(action);
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class LocaleListCompatUtils {
|
||||
private static final Class CLASS_LocaleList = CompatUtils.getClass("android.os.LocaleList");
|
||||
private static final Method METHOD_get =
|
||||
CompatUtils.getMethod(CLASS_LocaleList, "get", int.class);
|
||||
private static final Method METHOD_isEmpty =
|
||||
CompatUtils.getMethod(CLASS_LocaleList, "isEmpty");
|
||||
|
||||
private LocaleListCompatUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
public static boolean isEmpty(final Object localeList) {
|
||||
return (Boolean) CompatUtils.invoke(localeList, Boolean.FALSE, METHOD_isEmpty);
|
||||
}
|
||||
|
||||
public static Locale get(final Object localeList, final int index) {
|
||||
return (Locale) CompatUtils.invoke(localeList, null, METHOD_get, index);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.dslul.openboard.inputmethod.compat
|
||||
|
||||
import java.util.*
|
||||
|
||||
object LocaleListCompatUtils {
|
||||
private val CLASS_LocaleList = CompatUtils.getClass("android.os.LocaleList")
|
||||
private val METHOD_get = CompatUtils.getMethod(CLASS_LocaleList, "get", Int::class.javaPrimitiveType)
|
||||
private val METHOD_isEmpty = CompatUtils.getMethod(CLASS_LocaleList, "isEmpty")
|
||||
fun isEmpty(localeList: Any?): Boolean {
|
||||
return CompatUtils.invoke(localeList, java.lang.Boolean.FALSE, METHOD_isEmpty) as Boolean
|
||||
}
|
||||
|
||||
operator fun get(localeList: Any?, index: Int): Locale? {
|
||||
return CompatUtils.invoke(localeList, null, METHOD_get, index) as Locale
|
||||
}
|
||||
}
|
|
@ -1,218 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.text.Spannable;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.LocaleSpan;
|
||||
import android.util.Log;
|
||||
|
||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
@UsedForTesting
|
||||
public final class LocaleSpanCompatUtils {
|
||||
private static final String TAG = LocaleSpanCompatUtils.class.getSimpleName();
|
||||
|
||||
// Note that LocaleSpan(Locale locale) has been introduced in API level 17
|
||||
// (Build.VERSION_CODE.JELLY_BEAN_MR1).
|
||||
private static Class<?> getLocaleSpanClass() {
|
||||
try {
|
||||
return Class.forName("android.text.style.LocaleSpan");
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private static final Class<?> LOCALE_SPAN_TYPE;
|
||||
private static final Constructor<?> LOCALE_SPAN_CONSTRUCTOR;
|
||||
private static final Method LOCALE_SPAN_GET_LOCALE;
|
||||
static {
|
||||
LOCALE_SPAN_TYPE = getLocaleSpanClass();
|
||||
LOCALE_SPAN_CONSTRUCTOR = CompatUtils.getConstructor(LOCALE_SPAN_TYPE, Locale.class);
|
||||
LOCALE_SPAN_GET_LOCALE = CompatUtils.getMethod(LOCALE_SPAN_TYPE, "getLocale");
|
||||
}
|
||||
|
||||
@UsedForTesting
|
||||
public static boolean isLocaleSpanAvailable() {
|
||||
return (LOCALE_SPAN_CONSTRUCTOR != null && LOCALE_SPAN_GET_LOCALE != null);
|
||||
}
|
||||
|
||||
@UsedForTesting
|
||||
public static Object newLocaleSpan(final Locale locale) {
|
||||
return CompatUtils.newInstance(LOCALE_SPAN_CONSTRUCTOR, locale);
|
||||
}
|
||||
|
||||
@UsedForTesting
|
||||
public static Locale getLocaleFromLocaleSpan(final Object localeSpan) {
|
||||
return (Locale) CompatUtils.invoke(localeSpan, null, LOCALE_SPAN_GET_LOCALE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the specified range is covered with only one {@link LocaleSpan} with the given
|
||||
* locale. If the region is already covered by one or more {@link LocaleSpan}, their ranges are
|
||||
* updated so that each character has only one locale.
|
||||
* @param spannable the spannable object to be updated.
|
||||
* @param start the start index from which {@link LocaleSpan} is attached (inclusive).
|
||||
* @param end the end index to which {@link LocaleSpan} is attached (exclusive).
|
||||
* @param locale the locale to be attached to the specified range.
|
||||
*/
|
||||
@UsedForTesting
|
||||
public static void updateLocaleSpan(final Spannable spannable, final int start,
|
||||
final int end, final Locale locale) {
|
||||
if (end < start) {
|
||||
Log.e(TAG, "Invalid range: start=" + start + " end=" + end);
|
||||
return;
|
||||
}
|
||||
if (!isLocaleSpanAvailable()) {
|
||||
return;
|
||||
}
|
||||
// A brief summary of our strategy;
|
||||
// 1. Enumerate all LocaleSpans between [start - 1, end + 1].
|
||||
// 2. For each LocaleSpan S:
|
||||
// - Update the range of S so as not to cover [start, end] if S doesn't have the
|
||||
// expected locale.
|
||||
// - Mark S as "to be merged" if S has the expected locale.
|
||||
// 3. Merge all the LocaleSpans that are marked as "to be merged" into one LocaleSpan.
|
||||
// If no appropriate span is found, create a new one with newLocaleSpan method.
|
||||
final int searchStart = Math.max(start - 1, 0);
|
||||
final int searchEnd = Math.min(end + 1, spannable.length());
|
||||
// LocaleSpans found in the target range. See the step 1 in the above comment.
|
||||
final Object[] existingLocaleSpans = spannable.getSpans(searchStart, searchEnd,
|
||||
LOCALE_SPAN_TYPE);
|
||||
// LocaleSpans that are marked as "to be merged". See the step 2 in the above comment.
|
||||
final ArrayList<Object> existingLocaleSpansToBeMerged = new ArrayList<>();
|
||||
boolean isStartExclusive = true;
|
||||
boolean isEndExclusive = true;
|
||||
int newStart = start;
|
||||
int newEnd = end;
|
||||
for (final Object existingLocaleSpan : existingLocaleSpans) {
|
||||
final Locale attachedLocale = getLocaleFromLocaleSpan(existingLocaleSpan);
|
||||
if (!locale.equals(attachedLocale)) {
|
||||
// This LocaleSpan does not have the expected locale. Update its range if it has
|
||||
// an intersection with the range [start, end] (the first case of the step 2 in the
|
||||
// above comment).
|
||||
removeLocaleSpanFromRange(existingLocaleSpan, spannable, start, end);
|
||||
continue;
|
||||
}
|
||||
final int spanStart = spannable.getSpanStart(existingLocaleSpan);
|
||||
final int spanEnd = spannable.getSpanEnd(existingLocaleSpan);
|
||||
if (spanEnd < spanStart) {
|
||||
Log.e(TAG, "Invalid span: spanStart=" + spanStart + " spanEnd=" + spanEnd);
|
||||
continue;
|
||||
}
|
||||
if (spanEnd < start || end < spanStart) {
|
||||
// No intersection found.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Here existingLocaleSpan has the expected locale and an intersection with the
|
||||
// range [start, end] (the second case of the the step 2 in the above comment).
|
||||
final int spanFlag = spannable.getSpanFlags(existingLocaleSpan);
|
||||
if (spanStart < newStart) {
|
||||
newStart = spanStart;
|
||||
isStartExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
if (newEnd < spanEnd) {
|
||||
newEnd = spanEnd;
|
||||
isEndExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
existingLocaleSpansToBeMerged.add(existingLocaleSpan);
|
||||
}
|
||||
|
||||
int originalLocaleSpanFlag = 0;
|
||||
Object localeSpan = null;
|
||||
if (existingLocaleSpansToBeMerged.isEmpty()) {
|
||||
// If there is no LocaleSpan that is marked as to be merged, create a new one.
|
||||
localeSpan = newLocaleSpan(locale);
|
||||
} else {
|
||||
// Reuse the first LocaleSpan to avoid unnecessary object instantiation.
|
||||
localeSpan = existingLocaleSpansToBeMerged.get(0);
|
||||
originalLocaleSpanFlag = spannable.getSpanFlags(localeSpan);
|
||||
// No need to keep other instances.
|
||||
for (int i = 1; i < existingLocaleSpansToBeMerged.size(); ++i) {
|
||||
spannable.removeSpan(existingLocaleSpansToBeMerged.get(i));
|
||||
}
|
||||
}
|
||||
final int localeSpanFlag = getSpanFlag(originalLocaleSpanFlag, isStartExclusive,
|
||||
isEndExclusive);
|
||||
spannable.setSpan(localeSpan, newStart, newEnd, localeSpanFlag);
|
||||
}
|
||||
|
||||
private static void removeLocaleSpanFromRange(final Object localeSpan,
|
||||
final Spannable spannable, final int removeStart, final int removeEnd) {
|
||||
if (!isLocaleSpanAvailable()) {
|
||||
return;
|
||||
}
|
||||
final int spanStart = spannable.getSpanStart(localeSpan);
|
||||
final int spanEnd = spannable.getSpanEnd(localeSpan);
|
||||
if (spanStart > spanEnd) {
|
||||
Log.e(TAG, "Invalid span: spanStart=" + spanStart + " spanEnd=" + spanEnd);
|
||||
return;
|
||||
}
|
||||
if (spanEnd < removeStart) {
|
||||
// spanStart < spanEnd < removeStart < removeEnd
|
||||
return;
|
||||
}
|
||||
if (removeEnd < spanStart) {
|
||||
// spanStart < removeEnd < spanStart < spanEnd
|
||||
return;
|
||||
}
|
||||
final int spanFlags = spannable.getSpanFlags(localeSpan);
|
||||
if (spanStart < removeStart) {
|
||||
if (removeEnd < spanEnd) {
|
||||
// spanStart < removeStart < removeEnd < spanEnd
|
||||
final Locale locale = getLocaleFromLocaleSpan(localeSpan);
|
||||
spannable.setSpan(localeSpan, spanStart, removeStart, spanFlags);
|
||||
final Object attionalLocaleSpan = newLocaleSpan(locale);
|
||||
spannable.setSpan(attionalLocaleSpan, removeEnd, spanEnd, spanFlags);
|
||||
return;
|
||||
}
|
||||
// spanStart < removeStart < spanEnd <= removeEnd
|
||||
spannable.setSpan(localeSpan, spanStart, removeStart, spanFlags);
|
||||
return;
|
||||
}
|
||||
if (removeEnd < spanEnd) {
|
||||
// removeStart <= spanStart < removeEnd < spanEnd
|
||||
spannable.setSpan(localeSpan, removeEnd, spanEnd, spanFlags);
|
||||
return;
|
||||
}
|
||||
// removeStart <= spanStart < spanEnd < removeEnd
|
||||
spannable.removeSpan(localeSpan);
|
||||
}
|
||||
|
||||
private static int getSpanFlag(final int originalFlag,
|
||||
final boolean isStartExclusive, final boolean isEndExclusive) {
|
||||
return (originalFlag & ~Spanned.SPAN_POINT_MARK_MASK) |
|
||||
getSpanPointMarkFlag(isStartExclusive, isEndExclusive);
|
||||
}
|
||||
|
||||
private static int getSpanPointMarkFlag(final boolean isStartExclusive,
|
||||
final boolean isEndExclusive) {
|
||||
if (isStartExclusive) {
|
||||
return isEndExclusive ? Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
: Spanned.SPAN_EXCLUSIVE_INCLUSIVE;
|
||||
}
|
||||
return isEndExclusive ? Spanned.SPAN_INCLUSIVE_EXCLUSIVE
|
||||
: Spanned.SPAN_INCLUSIVE_INCLUSIVE;
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.os.Looper;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Helper to call Looper#quitSafely, which was introduced in API
|
||||
* level 18 (Build.VERSION_CODES.JELLY_BEAN_MR2).
|
||||
*
|
||||
* In unit tests, we create lots of instances of LatinIME, which means we need to clean up
|
||||
* some Loopers lest we leak file descriptors. In normal use on a device though, this is never
|
||||
* necessary (although it does not hurt).
|
||||
*/
|
||||
public final class LooperCompatUtils {
|
||||
private static final Method METHOD_quitSafely = CompatUtils.getMethod(
|
||||
Looper.class, "quitSafely");
|
||||
|
||||
public static void quitSafely(final Looper looper) {
|
||||
if (null != METHOD_quitSafely) {
|
||||
CompatUtils.invoke(looper, null /* default return value */, METHOD_quitSafely);
|
||||
} else {
|
||||
looper.quit();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.os.Build;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class NotificationCompatUtils {
|
||||
// Note that TextInfo.getCharSequence() is supposed to be available in API level 21 and later.
|
||||
private static final Method METHOD_setColor =
|
||||
CompatUtils.getMethod(Notification.Builder.class, "setColor", int.class);
|
||||
private static final Method METHOD_setVisibility =
|
||||
CompatUtils.getMethod(Notification.Builder.class, "setVisibility", int.class);
|
||||
private static final Method METHOD_setCategory =
|
||||
CompatUtils.getMethod(Notification.Builder.class, "setCategory", String.class);
|
||||
private static final Method METHOD_setPriority =
|
||||
CompatUtils.getMethod(Notification.Builder.class, "setPriority", int.class);
|
||||
private static final Method METHOD_build =
|
||||
CompatUtils.getMethod(Notification.Builder.class, "build");
|
||||
private static final Field FIELD_VISIBILITY_SECRET =
|
||||
CompatUtils.getField(Notification.class, "VISIBILITY_SECRET");
|
||||
private static final int VISIBILITY_SECRET = null == FIELD_VISIBILITY_SECRET ? 0
|
||||
: (Integer) CompatUtils.getFieldValue(null /* receiver */, null /* defaultValue */,
|
||||
FIELD_VISIBILITY_SECRET);
|
||||
private static final Field FIELD_CATEGORY_RECOMMENDATION =
|
||||
CompatUtils.getField(Notification.class, "CATEGORY_RECOMMENDATION");
|
||||
private static final String CATEGORY_RECOMMENDATION = null == FIELD_CATEGORY_RECOMMENDATION ? ""
|
||||
: (String) CompatUtils.getFieldValue(null /* receiver */, null /* defaultValue */,
|
||||
FIELD_CATEGORY_RECOMMENDATION);
|
||||
private static final Field FIELD_PRIORITY_LOW =
|
||||
CompatUtils.getField(Notification.class, "PRIORITY_LOW");
|
||||
private static final int PRIORITY_LOW = null == FIELD_PRIORITY_LOW ? 0
|
||||
: (Integer) CompatUtils.getFieldValue(null /* receiver */, null /* defaultValue */,
|
||||
FIELD_PRIORITY_LOW);
|
||||
|
||||
private NotificationCompatUtils() {
|
||||
// This class is non-instantiable.
|
||||
}
|
||||
|
||||
// Sets the accent color
|
||||
public static void setColor(final Notification.Builder builder, final int color) {
|
||||
CompatUtils.invoke(builder, null, METHOD_setColor, color);
|
||||
}
|
||||
|
||||
public static void setVisibilityToSecret(final Notification.Builder builder) {
|
||||
CompatUtils.invoke(builder, null, METHOD_setVisibility, VISIBILITY_SECRET);
|
||||
}
|
||||
|
||||
public static void setCategoryToRecommendation(final Notification.Builder builder) {
|
||||
CompatUtils.invoke(builder, null, METHOD_setCategory, CATEGORY_RECOMMENDATION);
|
||||
}
|
||||
|
||||
public static void setPriorityToLow(final Notification.Builder builder) {
|
||||
CompatUtils.invoke(builder, null, METHOD_setPriority, PRIORITY_LOW);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static Notification build(final Notification.Builder builder) {
|
||||
// #build was added in API level 16, JELLY_BEAN
|
||||
return (Notification) CompatUtils.invoke(builder, null, METHOD_build);
|
||||
// #getNotification was deprecated in API level 16, JELLY_BEAN
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public final class SettingsSecureCompatUtils {
|
||||
// Note that Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD has been introduced
|
||||
// in API level 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1).
|
||||
private static final Field FIELD_ACCESSIBILITY_SPEAK_PASSWORD = CompatUtils.getField(
|
||||
android.provider.Settings.Secure.class, "ACCESSIBILITY_SPEAK_PASSWORD");
|
||||
|
||||
private SettingsSecureCompatUtils() {
|
||||
// This class is non-instantiable.
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to speak passwords while in accessibility mode.
|
||||
*/
|
||||
public static final String ACCESSIBILITY_SPEAK_PASSWORD = (String) CompatUtils.getFieldValue(
|
||||
null /* receiver */, null /* defaultValue */, FIELD_ACCESSIBILITY_SPEAK_PASSWORD);
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.SuggestionSpan;
|
||||
|
||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
||||
import org.dslul.openboard.inputmethod.latin.SuggestedWords;
|
||||
import org.dslul.openboard.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||
import org.dslul.openboard.inputmethod.latin.common.LocaleUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.define.DebugFlags;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class SuggestionSpanUtils {
|
||||
// Note that SuggestionSpan.FLAG_AUTO_CORRECTION has been introduced
|
||||
// in API level 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1).
|
||||
private static final Field FIELD_FLAG_AUTO_CORRECTION = CompatUtils.getField(
|
||||
SuggestionSpan.class, "FLAG_AUTO_CORRECTION");
|
||||
private static final Integer OBJ_FLAG_AUTO_CORRECTION = (Integer) CompatUtils.getFieldValue(
|
||||
null /* receiver */, null /* defaultValue */, FIELD_FLAG_AUTO_CORRECTION);
|
||||
|
||||
static {
|
||||
if (DebugFlags.DEBUG_ENABLED) {
|
||||
if (OBJ_FLAG_AUTO_CORRECTION == null) {
|
||||
throw new RuntimeException("Field is accidentially null.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SuggestionSpanUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
@UsedForTesting
|
||||
public static CharSequence getTextWithAutoCorrectionIndicatorUnderline(
|
||||
final Context context, final String text, @Nonnull final Locale locale) {
|
||||
if (TextUtils.isEmpty(text) || OBJ_FLAG_AUTO_CORRECTION == null) {
|
||||
return text;
|
||||
}
|
||||
final Spannable spannable = new SpannableString(text);
|
||||
final SuggestionSpan suggestionSpan = new SuggestionSpan(context, locale,
|
||||
new String[] {} /* suggestions */, OBJ_FLAG_AUTO_CORRECTION, null);
|
||||
spannable.setSpan(suggestionSpan, 0, text.length(),
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING);
|
||||
return spannable;
|
||||
}
|
||||
|
||||
@UsedForTesting
|
||||
public static CharSequence getTextWithSuggestionSpan(final Context context,
|
||||
final String pickedWord, final SuggestedWords suggestedWords, final Locale locale) {
|
||||
if (TextUtils.isEmpty(pickedWord) || suggestedWords.isEmpty()
|
||||
|| suggestedWords.isPrediction() || suggestedWords.isPunctuationSuggestions()) {
|
||||
return pickedWord;
|
||||
}
|
||||
|
||||
final ArrayList<String> suggestionsList = new ArrayList<>();
|
||||
for (int i = 0; i < suggestedWords.size(); ++i) {
|
||||
if (suggestionsList.size() >= SuggestionSpan.SUGGESTIONS_MAX_SIZE) {
|
||||
break;
|
||||
}
|
||||
final SuggestedWordInfo info = suggestedWords.getInfo(i);
|
||||
if (info.isKindOf(SuggestedWordInfo.KIND_PREDICTION)) {
|
||||
continue;
|
||||
}
|
||||
final String word = suggestedWords.getWord(i);
|
||||
if (!TextUtils.equals(pickedWord, word)) {
|
||||
suggestionsList.add(word.toString());
|
||||
}
|
||||
}
|
||||
final SuggestionSpan suggestionSpan = new SuggestionSpan(context, locale,
|
||||
suggestionsList.toArray(new String[suggestionsList.size()]), 0 /* flags */, null);
|
||||
final Spannable spannable = new SpannableString(pickedWord);
|
||||
spannable.setSpan(suggestionSpan, 0, pickedWord.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return spannable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns first {@link Locale} found in the given array of {@link SuggestionSpan}.
|
||||
* @param suggestionSpans the array of {@link SuggestionSpan} to be examined.
|
||||
* @return the first {@link Locale} found in {@code suggestionSpans}. {@code null} when not
|
||||
* found.
|
||||
*/
|
||||
@UsedForTesting
|
||||
@Nullable
|
||||
public static Locale findFirstLocaleFromSuggestionSpans(
|
||||
final SuggestionSpan[] suggestionSpans) {
|
||||
for (final SuggestionSpan suggestionSpan : suggestionSpans) {
|
||||
final String localeString = suggestionSpan.getLocale();
|
||||
if (TextUtils.isEmpty(localeString)) {
|
||||
continue;
|
||||
}
|
||||
return LocaleUtils.constructLocaleFromString(localeString);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package org.dslul.openboard.inputmethod.compat
|
||||
|
||||
import android.content.Context
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.text.Spanned
|
||||
import android.text.TextUtils
|
||||
import android.text.style.SuggestionSpan
|
||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting
|
||||
import org.dslul.openboard.inputmethod.latin.SuggestedWords
|
||||
import org.dslul.openboard.inputmethod.latin.SuggestedWords.SuggestedWordInfo
|
||||
import org.dslul.openboard.inputmethod.latin.common.LocaleUtils
|
||||
import org.dslul.openboard.inputmethod.latin.define.DebugFlags
|
||||
import java.util.*
|
||||
|
||||
object SuggestionSpanUtils {
|
||||
// Note that SuggestionSpan.FLAG_AUTO_CORRECTION has been introduced
|
||||
// in API level 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1).
|
||||
private val FIELD_FLAG_AUTO_CORRECTION = CompatUtils.getField(
|
||||
SuggestionSpan::class.java, "FLAG_AUTO_CORRECTION")
|
||||
private val OBJ_FLAG_AUTO_CORRECTION: Int? = CompatUtils.getFieldValue(
|
||||
null /* receiver */, null /* defaultValue */, FIELD_FLAG_AUTO_CORRECTION) as Int
|
||||
|
||||
@kotlin.jvm.JvmStatic
|
||||
@UsedForTesting
|
||||
fun getTextWithAutoCorrectionIndicatorUnderline(
|
||||
context: Context?, text: String,locale: Locale?): CharSequence {
|
||||
if (TextUtils.isEmpty(text) || OBJ_FLAG_AUTO_CORRECTION == null) {
|
||||
return text
|
||||
}
|
||||
val spannable: Spannable = SpannableString(text)
|
||||
val suggestionSpan = SuggestionSpan(context, locale, arrayOf(), OBJ_FLAG_AUTO_CORRECTION, null)
|
||||
spannable.setSpan(suggestionSpan, 0, text.length,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE or Spanned.SPAN_COMPOSING)
|
||||
return spannable
|
||||
}
|
||||
|
||||
@UsedForTesting
|
||||
fun getTextWithSuggestionSpan(context: Context?,
|
||||
pickedWord: String, suggestedWords: SuggestedWords, locale: Locale?): CharSequence {
|
||||
if (TextUtils.isEmpty(pickedWord) || suggestedWords.isEmpty
|
||||
|| suggestedWords.isPrediction || suggestedWords.isPunctuationSuggestions) {
|
||||
return pickedWord
|
||||
}
|
||||
val suggestionsList = ArrayList<String>()
|
||||
for (i in 0 until suggestedWords.size()) {
|
||||
if (suggestionsList.size >= SuggestionSpan.SUGGESTIONS_MAX_SIZE) {
|
||||
break
|
||||
}
|
||||
val info = suggestedWords.getInfo(i)
|
||||
if (info.isKindOf(SuggestedWordInfo.KIND_PREDICTION)) {
|
||||
continue
|
||||
}
|
||||
val word = suggestedWords.getWord(i)
|
||||
if (!TextUtils.equals(pickedWord, word)) {
|
||||
suggestionsList.add(word.toString())
|
||||
}
|
||||
}
|
||||
val suggestionSpan = SuggestionSpan(context, locale,
|
||||
suggestionsList.toTypedArray(), 0 /* flags */, null)
|
||||
val spannable: Spannable = SpannableString(pickedWord)
|
||||
spannable.setSpan(suggestionSpan, 0, pickedWord.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return spannable
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns first [Locale] found in the given array of [SuggestionSpan].
|
||||
* @param suggestionSpans the array of [SuggestionSpan] to be examined.
|
||||
* @return the first [Locale] found in `suggestionSpans`. `null` when not
|
||||
* found.
|
||||
*/
|
||||
@UsedForTesting
|
||||
fun findFirstLocaleFromSuggestionSpans(
|
||||
suggestionSpans: Array<SuggestionSpan>): Locale? {
|
||||
for (suggestionSpan in suggestionSpans) {
|
||||
val localeString = suggestionSpan.locale
|
||||
if (TextUtils.isEmpty(localeString)) {
|
||||
continue
|
||||
}
|
||||
return LocaleUtils.constructLocaleFromString(localeString)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
init {
|
||||
if (DebugFlags.DEBUG_ENABLED) {
|
||||
if (OBJ_FLAG_AUTO_CORRECTION == null) {
|
||||
throw RuntimeException("Field is accidentially null.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.view.textservice.SuggestionsInfo;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public final class SuggestionsInfoCompatUtils {
|
||||
// Note that SuggestionsInfo.RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS has been introduced
|
||||
// in API level 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1).
|
||||
private static final Field FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS =
|
||||
CompatUtils.getField(SuggestionsInfo.class, "RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS");
|
||||
private static final Integer OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS =
|
||||
(Integer) CompatUtils.getFieldValue(null /* receiver */, null /* defaultValue */,
|
||||
FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS);
|
||||
private static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS =
|
||||
OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS != null
|
||||
? OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS : 0;
|
||||
|
||||
private SuggestionsInfoCompatUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the flag value of the attributes of the suggestions that can be obtained by
|
||||
* {@link SuggestionsInfo#getSuggestionsAttributes()}: this tells that the text service thinks
|
||||
* the result suggestions include highly recommended ones.
|
||||
*/
|
||||
public static int getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS() {
|
||||
return RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS;
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.view.textservice.TextInfo;
|
||||
|
||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@UsedForTesting
|
||||
public final class TextInfoCompatUtils {
|
||||
// Note that TextInfo.getCharSequence() is supposed to be available in API level 21 and later.
|
||||
private static final Method TEXT_INFO_GET_CHAR_SEQUENCE =
|
||||
CompatUtils.getMethod(TextInfo.class, "getCharSequence");
|
||||
private static final Constructor<?> TEXT_INFO_CONSTRUCTOR_FOR_CHAR_SEQUENCE =
|
||||
CompatUtils.getConstructor(TextInfo.class, CharSequence.class, int.class, int.class,
|
||||
int.class, int.class);
|
||||
|
||||
@UsedForTesting
|
||||
public static boolean isCharSequenceSupported() {
|
||||
return TEXT_INFO_GET_CHAR_SEQUENCE != null &&
|
||||
TEXT_INFO_CONSTRUCTOR_FOR_CHAR_SEQUENCE != null;
|
||||
}
|
||||
|
||||
@UsedForTesting
|
||||
public static TextInfo newInstance(CharSequence charSequence, int start, int end, int cookie,
|
||||
int sequenceNumber) {
|
||||
if (TEXT_INFO_CONSTRUCTOR_FOR_CHAR_SEQUENCE != null) {
|
||||
return (TextInfo) CompatUtils.newInstance(TEXT_INFO_CONSTRUCTOR_FOR_CHAR_SEQUENCE,
|
||||
charSequence, start, end, cookie, sequenceNumber);
|
||||
}
|
||||
return new TextInfo(charSequence.subSequence(start, end).toString(), cookie,
|
||||
sequenceNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of {@link TextInfo#getCharSequence()} when available. Otherwise returns
|
||||
* the result of {@link TextInfo#getText()} as fall back.
|
||||
* @param textInfo the instance for which {@link TextInfo#getCharSequence()} or
|
||||
* {@link TextInfo#getText()} is called.
|
||||
* @return the result of {@link TextInfo#getCharSequence()} when available. Otherwise returns
|
||||
* the result of {@link TextInfo#getText()} as fall back. If {@code textInfo} is {@code null},
|
||||
* returns {@code null}.
|
||||
*/
|
||||
@UsedForTesting
|
||||
public static CharSequence getCharSequenceOrString(final TextInfo textInfo) {
|
||||
final CharSequence defaultValue = (textInfo == null ? null : textInfo.getText());
|
||||
return (CharSequence) CompatUtils.invoke(textInfo, defaultValue,
|
||||
TEXT_INFO_GET_CHAR_SEQUENCE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package org.dslul.openboard.inputmethod.compat
|
||||
|
||||
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")
|
||||
private val TEXT_INFO_CONSTRUCTOR_FOR_CHAR_SEQUENCE = CompatUtils.getConstructor(TextInfo::class.java, CharSequence::class.java, Int::class.javaPrimitiveType, Int::class.javaPrimitiveType,
|
||||
Int::class.javaPrimitiveType, Int::class.javaPrimitiveType)
|
||||
|
||||
@get:UsedForTesting
|
||||
val isCharSequenceSupported: Boolean
|
||||
get() = TEXT_INFO_GET_CHAR_SEQUENCE != null &&
|
||||
TEXT_INFO_CONSTRUCTOR_FOR_CHAR_SEQUENCE != null
|
||||
|
||||
@kotlin.jvm.JvmStatic
|
||||
@UsedForTesting
|
||||
fun newInstance(charSequence: CharSequence, start: Int, end: Int, cookie: Int,
|
||||
sequenceNumber: Int): TextInfo? {
|
||||
return if (TEXT_INFO_CONSTRUCTOR_FOR_CHAR_SEQUENCE != null) {
|
||||
CompatUtils.newInstance(TEXT_INFO_CONSTRUCTOR_FOR_CHAR_SEQUENCE,
|
||||
charSequence, start, end, cookie, sequenceNumber) as TextInfo
|
||||
} else 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`.
|
||||
*/
|
||||
@kotlin.jvm.JvmStatic
|
||||
@UsedForTesting
|
||||
fun getCharSequenceOrString(textInfo: TextInfo?): CharSequence? {
|
||||
val defaultValue: CharSequence? = textInfo?.text
|
||||
return CompatUtils.invoke(textInfo, defaultValue!!,
|
||||
TEXT_INFO_GET_CHAR_SEQUENCE) as CharSequence
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public final class TextViewCompatUtils {
|
||||
// Note that TextView.setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable,Drawable,
|
||||
// Drawable,Drawable) has been introduced in API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1).
|
||||
private static final Method METHOD_setCompoundDrawablesRelativeWithIntrinsicBounds =
|
||||
CompatUtils.getMethod(TextView.class, "setCompoundDrawablesRelativeWithIntrinsicBounds",
|
||||
Drawable.class, Drawable.class, Drawable.class, Drawable.class);
|
||||
|
||||
private TextViewCompatUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
public static void setCompoundDrawablesRelativeWithIntrinsicBounds(final TextView textView,
|
||||
final Drawable start, final Drawable top, final Drawable end, final Drawable bottom) {
|
||||
if (METHOD_setCompoundDrawablesRelativeWithIntrinsicBounds == null) {
|
||||
textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
|
||||
return;
|
||||
}
|
||||
CompatUtils.invoke(textView, null, METHOD_setCompoundDrawablesRelativeWithIntrinsicBounds,
|
||||
start, top, end, bottom);
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.provider.UserDictionary;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public final class UserDictionaryCompatUtils {
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void addWord(final Context context, final String word,
|
||||
final int freq, final String shortcut, final Locale locale) {
|
||||
if (BuildCompatUtils.EFFECTIVE_SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
addWordWithShortcut(context, word, freq, shortcut, locale);
|
||||
return;
|
||||
}
|
||||
// Fall back to the pre-JellyBean method.
|
||||
final Locale currentLocale = context.getResources().getConfiguration().locale;
|
||||
final int localeType = currentLocale.equals(locale)
|
||||
? UserDictionary.Words.LOCALE_TYPE_CURRENT : UserDictionary.Words.LOCALE_TYPE_ALL;
|
||||
UserDictionary.Words.addWord(context, word, freq, localeType);
|
||||
}
|
||||
|
||||
// {@link UserDictionary.Words#addWord(Context,String,int,String,Locale)} was introduced
|
||||
// in API level 16 (Build.VERSION_CODES.JELLY_BEAN).
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
private static void addWordWithShortcut(final Context context, final String word,
|
||||
final int freq, final String shortcut, final Locale locale) {
|
||||
UserDictionary.Words.addWord(context, word, freq, shortcut, locale);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.UserManager;
|
||||
import androidx.annotation.IntDef;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* A temporary solution until {@code UserManagerCompat.isUserUnlocked()} in the support-v4 library
|
||||
* becomes publicly available.
|
||||
*/
|
||||
public final class UserManagerCompatUtils {
|
||||
private static final Method METHOD_isUserUnlocked;
|
||||
|
||||
static {
|
||||
// We do not try to search the method in Android M and prior.
|
||||
if (BuildCompatUtils.EFFECTIVE_SDK_INT <= Build.VERSION_CODES.M) {
|
||||
METHOD_isUserUnlocked = null;
|
||||
} else {
|
||||
METHOD_isUserUnlocked = CompatUtils.getMethod(UserManager.class, "isUserUnlocked");
|
||||
}
|
||||
}
|
||||
|
||||
private UserManagerCompatUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
public static final int LOCK_STATE_UNKNOWN = 0;
|
||||
public static final int LOCK_STATE_UNLOCKED = 1;
|
||||
public static final int LOCK_STATE_LOCKED = 2;
|
||||
|
||||
@Retention(SOURCE)
|
||||
@IntDef({LOCK_STATE_UNKNOWN, LOCK_STATE_UNLOCKED, LOCK_STATE_LOCKED})
|
||||
public @interface LockState {}
|
||||
|
||||
/**
|
||||
* Check if the calling user is running in an "unlocked" state. A user is unlocked only after
|
||||
* they've entered their credentials (such as a lock pattern or PIN), and credential-encrypted
|
||||
* private app data storage is available.
|
||||
* @param context context from which {@link UserManager} should be obtained.
|
||||
* @return One of {@link LockState}.
|
||||
*/
|
||||
@LockState
|
||||
public static int getUserLockState(final Context context) {
|
||||
if (METHOD_isUserUnlocked == null) {
|
||||
return LOCK_STATE_UNKNOWN;
|
||||
}
|
||||
final UserManager userManager = context.getSystemService(UserManager.class);
|
||||
if (userManager == null) {
|
||||
return LOCK_STATE_UNKNOWN;
|
||||
}
|
||||
final Boolean result =
|
||||
(Boolean) CompatUtils.invoke(userManager, null, METHOD_isUserUnlocked);
|
||||
if (result == null) {
|
||||
return LOCK_STATE_UNKNOWN;
|
||||
}
|
||||
return result ? LOCK_STATE_UNLOCKED : LOCK_STATE_LOCKED;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package org.dslul.openboard.inputmethod.compat
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.Build.VERSION_CODES
|
||||
import android.os.UserManager
|
||||
import androidx.annotation.IntDef
|
||||
import androidx.annotation.RequiresApi
|
||||
import java.lang.reflect.Method
|
||||
|
||||
/**
|
||||
* A temporary solution until `UserManagerCompat.isUserUnlocked()` in the support-v4 library
|
||||
* becomes publicly available.
|
||||
*/
|
||||
object UserManagerCompatUtils {
|
||||
private var METHOD_isUserUnlocked: Method? = null
|
||||
const val LOCK_STATE_UNKNOWN = 0
|
||||
const val LOCK_STATE_UNLOCKED = 1
|
||||
const val LOCK_STATE_LOCKED = 2
|
||||
/**
|
||||
* Check if the calling user is running in an "unlocked" state. A user is unlocked only after
|
||||
* they've entered their credentials (such as a lock pattern or PIN), and credential-encrypted
|
||||
* private app data storage is available.
|
||||
* @param context context from which [UserManager] should be obtained.
|
||||
* @return One of [LockState].
|
||||
*/
|
||||
@RequiresApi(VERSION_CODES.M)
|
||||
@kotlin.jvm.JvmStatic
|
||||
@LockState
|
||||
fun getUserLockState(context: Context): Int {
|
||||
if (METHOD_isUserUnlocked == null) {
|
||||
return LOCK_STATE_UNKNOWN
|
||||
}
|
||||
val userManager = context.getSystemService(UserManager::class.java)
|
||||
?: return LOCK_STATE_UNKNOWN
|
||||
val result = CompatUtils.invoke(userManager, null, METHOD_isUserUnlocked) as Boolean
|
||||
?: return LOCK_STATE_UNKNOWN
|
||||
return if (result) LOCK_STATE_UNLOCKED else LOCK_STATE_LOCKED
|
||||
}
|
||||
|
||||
@kotlin.annotation.Retention(AnnotationRetention.SOURCE)
|
||||
@IntDef(LOCK_STATE_UNKNOWN, LOCK_STATE_UNLOCKED, LOCK_STATE_LOCKED)
|
||||
annotation class LockState
|
||||
|
||||
init { // We do not try to search the method in Android M and prior.
|
||||
METHOD_isUserUnlocked = if (Build.VERSION.SDK_INT <= VERSION_CODES.M) {
|
||||
null
|
||||
} else {
|
||||
CompatUtils.getMethod(UserManager::class.java, "isUserUnlocked")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
// TODO: Use {@link androidx.core.view.ViewCompat} instead of this utility class.
|
||||
// Currently {@link #getPaddingEnd(View)} and {@link #setPaddingRelative(View,int,int,int,int)}
|
||||
// are missing from android-support-v4 static library in KitKat SDK.
|
||||
public final class ViewCompatUtils {
|
||||
// Note that View.getPaddingEnd(), View.setPaddingRelative(int,int,int,int) have been
|
||||
// introduced in API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1).
|
||||
private static final Method METHOD_getPaddingEnd = CompatUtils.getMethod(
|
||||
View.class, "getPaddingEnd");
|
||||
private static final Method METHOD_setPaddingRelative = CompatUtils.getMethod(
|
||||
View.class, "setPaddingRelative",
|
||||
int.class, int.class, int.class, int.class);
|
||||
// Note that View.setTextAlignment(int) has been introduced in API level 17.
|
||||
private static final Method METHOD_setTextAlignment = CompatUtils.getMethod(
|
||||
View.class, "setTextAlignment", int.class);
|
||||
|
||||
private ViewCompatUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
public static int getPaddingEnd(final View view) {
|
||||
if (METHOD_getPaddingEnd == null) {
|
||||
return view.getPaddingRight();
|
||||
}
|
||||
return (Integer)CompatUtils.invoke(view, 0, METHOD_getPaddingEnd);
|
||||
}
|
||||
|
||||
public static void setPaddingRelative(final View view, final int start, final int top,
|
||||
final int end, final int bottom) {
|
||||
if (METHOD_setPaddingRelative == null) {
|
||||
view.setPadding(start, top, end, bottom);
|
||||
return;
|
||||
}
|
||||
CompatUtils.invoke(view, null, METHOD_setPaddingRelative, start, top, end, bottom);
|
||||
}
|
||||
|
||||
// These TEXT_ALIGNMENT_* constants have been introduced in API 17.
|
||||
public static final int TEXT_ALIGNMENT_INHERIT = 0;
|
||||
public static final int TEXT_ALIGNMENT_GRAVITY = 1;
|
||||
public static final int TEXT_ALIGNMENT_TEXT_START = 2;
|
||||
public static final int TEXT_ALIGNMENT_TEXT_END = 3;
|
||||
public static final int TEXT_ALIGNMENT_CENTER = 4;
|
||||
public static final int TEXT_ALIGNMENT_VIEW_START = 5;
|
||||
public static final int TEXT_ALIGNMENT_VIEW_END = 6;
|
||||
|
||||
public static void setTextAlignment(final View view, final int textAlignment) {
|
||||
CompatUtils.invoke(view, null, METHOD_setTextAlignment, textAlignment);
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
|
||||
public class ViewOutlineProviderCompatUtils {
|
||||
private ViewOutlineProviderCompatUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
public interface InsetsUpdater {
|
||||
public void setInsets(final InputMethodService.Insets insets);
|
||||
}
|
||||
|
||||
private static final InsetsUpdater EMPTY_INSETS_UPDATER = new InsetsUpdater() {
|
||||
@Override
|
||||
public void setInsets(final InputMethodService.Insets insets) {}
|
||||
};
|
||||
|
||||
public static InsetsUpdater setInsetsOutlineProvider(final View view) {
|
||||
if (BuildCompatUtils.EFFECTIVE_SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return EMPTY_INSETS_UPDATER;
|
||||
}
|
||||
return ViewOutlineProviderCompatUtilsLXX.setInsetsOutlineProvider(view);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package org.dslul.openboard.inputmethod.compat
|
||||
|
||||
import android.inputmethodservice.InputMethodService
|
||||
import android.os.Build
|
||||
import android.os.Build.VERSION_CODES
|
||||
import android.view.View
|
||||
|
||||
object ViewOutlineProviderCompatUtils {
|
||||
private val EMPTY_INSETS_UPDATER: InsetsUpdater = object : InsetsUpdater {
|
||||
override fun setInsets(insets: InputMethodService.Insets) {}
|
||||
}
|
||||
|
||||
@kotlin.jvm.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)
|
||||
}
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.graphics.Outline;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
import android.view.ViewOutlineProvider;
|
||||
|
||||
import org.dslul.openboard.inputmethod.compat.ViewOutlineProviderCompatUtils.InsetsUpdater;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
class ViewOutlineProviderCompatUtilsLXX {
|
||||
private ViewOutlineProviderCompatUtilsLXX() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
static InsetsUpdater setInsetsOutlineProvider(final View view) {
|
||||
final InsetsOutlineProvider provider = new InsetsOutlineProvider(view);
|
||||
view.setOutlineProvider(provider);
|
||||
return provider;
|
||||
}
|
||||
|
||||
private static class InsetsOutlineProvider extends ViewOutlineProvider
|
||||
implements InsetsUpdater {
|
||||
private final View mView;
|
||||
private static final int NO_DATA = -1;
|
||||
private int mLastVisibleTopInsets = NO_DATA;
|
||||
|
||||
public InsetsOutlineProvider(final View view) {
|
||||
mView = view;
|
||||
view.setOutlineProvider(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInsets(final InputMethodService.Insets insets) {
|
||||
final int visibleTopInsets = insets.visibleTopInsets;
|
||||
if (mLastVisibleTopInsets != visibleTopInsets) {
|
||||
mLastVisibleTopInsets = visibleTopInsets;
|
||||
mView.invalidateOutline();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getOutline(final View view, final Outline outline) {
|
||||
if (mLastVisibleTopInsets == NO_DATA) {
|
||||
// Call default implementation.
|
||||
ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
|
||||
return;
|
||||
}
|
||||
// TODO: Revisit this when floating/resize keyboard is supported.
|
||||
outline.setRect(
|
||||
view.getLeft(), mLastVisibleTopInsets, view.getRight(), view.getBottom());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package org.dslul.openboard.inputmethod.compat
|
||||
|
||||
import android.graphics.Outline
|
||||
import android.inputmethodservice.InputMethodService
|
||||
import android.view.View
|
||||
import android.view.ViewOutlineProvider
|
||||
import org.dslul.openboard.inputmethod.compat.ViewOutlineProviderCompatUtils.InsetsUpdater
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,12 +16,6 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.keyboard;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_OUTPUT_TEXT;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_SHIFT;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_SWITCH_ALPHA_SYMBOL;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_UNSPECIFIED;
|
||||
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Typeface;
|
||||
|
@ -46,6 +40,12 @@ import java.util.Locale;
|
|||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_OUTPUT_TEXT;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_SHIFT;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_SWITCH_ALPHA_SYMBOL;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_UNSPECIFIED;
|
||||
|
||||
/**
|
||||
* Class for describing the position and characteristics of a single key in the keyboard.
|
||||
*/
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.keyboard;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
|
||||
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
|
@ -29,6 +27,8 @@ import org.dslul.openboard.inputmethod.latin.utils.InputTypeUtils;
|
|||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
|
||||
|
||||
/**
|
||||
* Unique identifier for each keyboard type.
|
||||
*/
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.keyboard;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.FORCE_ASCII;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.NO_SETTINGS_KEY;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
|
@ -39,12 +36,10 @@ import org.dslul.openboard.inputmethod.keyboard.internal.UniqueKeysCache;
|
|||
import org.dslul.openboard.inputmethod.latin.InputAttributes;
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
import org.dslul.openboard.inputmethod.latin.RichInputMethodSubtype;
|
||||
import org.dslul.openboard.inputmethod.latin.define.DebugFlags;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.InputTypeUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.ScriptUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.SubtypeLocaleUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.XmlParseUtils;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
|
@ -55,6 +50,9 @@ import java.util.HashMap;
|
|||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.FORCE_ASCII;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.NO_SETTINGS_KEY;
|
||||
|
||||
/**
|
||||
* This class represents a set of keyboard layouts. Each of them represents a different keyboard
|
||||
* specific to a keyboard state, such as alphabet, symbols, and so on. Layouts in the same
|
||||
|
@ -295,7 +293,7 @@ public final class KeyboardLayoutSet {
|
|||
}
|
||||
|
||||
public Builder setSubtype(@Nonnull final RichInputMethodSubtype subtype) {
|
||||
final boolean asciiCapable = InputMethodSubtypeCompatUtils.isAsciiCapable(subtype);
|
||||
final boolean asciiCapable = subtype.getmSubtype().isAsciiCapable();
|
||||
// TODO: Consolidate with {@link InputAttributes}.
|
||||
@SuppressWarnings("deprecation")
|
||||
final boolean deprecatedForceAscii = InputAttributes.inPrivateImeOptions(
|
||||
|
|
|
@ -24,7 +24,6 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
|
||||
import org.dslul.openboard.inputmethod.compat.InputMethodServiceCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.event.Event;
|
||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardLayoutSet.KeyboardLayoutSetException;
|
||||
import org.dslul.openboard.inputmethod.keyboard.emoji.EmojiPalettesView;
|
||||
|
@ -84,8 +83,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
|
|||
mLatinIME = latinIme;
|
||||
mRichImm = RichInputMethodManager.getInstance();
|
||||
mState = new KeyboardState(this);
|
||||
mIsHardwareAcceleratedDrawingEnabled =
|
||||
InputMethodServiceCompatUtils.enableHardwareAcceleration(mLatinIME);
|
||||
mIsHardwareAcceleratedDrawingEnabled = mLatinIME.enableHardwareAcceleration();
|
||||
}
|
||||
|
||||
public void updateKeyboardTheme() {
|
||||
|
|
|
@ -23,7 +23,6 @@ import android.os.Build.VERSION_CODES;
|
|||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import org.dslul.openboard.inputmethod.compat.BuildCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -156,7 +155,7 @@ public final class KeyboardTheme implements Comparable<KeyboardTheme> {
|
|||
}
|
||||
|
||||
public static void saveKeyboardThemeId(final int themeId, final SharedPreferences prefs) {
|
||||
saveKeyboardThemeId(themeId, prefs, BuildCompatUtils.EFFECTIVE_SDK_INT);
|
||||
saveKeyboardThemeId(themeId, prefs, Build.VERSION.SDK_INT);
|
||||
}
|
||||
|
||||
/* package private for testing */
|
||||
|
@ -177,7 +176,7 @@ public final class KeyboardTheme implements Comparable<KeyboardTheme> {
|
|||
public static KeyboardTheme getKeyboardTheme(final Context context) {
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final KeyboardTheme[] availableThemeArray = getAvailableThemeArray(context);
|
||||
return getKeyboardTheme(prefs, BuildCompatUtils.EFFECTIVE_SDK_INT, availableThemeArray);
|
||||
return getKeyboardTheme(prefs, Build.VERSION.SDK_INT, availableThemeArray);
|
||||
}
|
||||
|
||||
/* package private for testing */
|
||||
|
|
|
@ -28,7 +28,6 @@ import android.graphics.Paint;
|
|||
import android.graphics.Paint.Align;
|
||||
import android.graphics.Typeface;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -60,7 +59,6 @@ import org.dslul.openboard.inputmethod.latin.settings.DebugSettings;
|
|||
import org.dslul.openboard.inputmethod.latin.utils.LanguageOnSpacebarUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.TypefaceUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
|
|
@ -25,7 +25,6 @@ import android.os.Build;
|
|||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.dslul.openboard.inputmethod.compat.BuildCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.keyboard.Key;
|
||||
import org.dslul.openboard.inputmethod.keyboard.Keyboard;
|
||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardId;
|
||||
|
@ -174,7 +173,7 @@ final class EmojiCategory {
|
|||
|
||||
int defaultCategoryId = EmojiCategory.ID_SYMBOLS;
|
||||
addShownCategoryId(EmojiCategory.ID_RECENTS);
|
||||
if (BuildCompatUtils.EFFECTIVE_SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
if (canShowUnicodeEightEmoji()) {
|
||||
defaultCategoryId = EmojiCategory.ID_EIGHT_SMILEY_PEOPLE;
|
||||
addShownCategoryId(EmojiCategory.ID_EIGHT_SMILEY_PEOPLE);
|
||||
|
|
|
@ -17,13 +17,14 @@
|
|||
package org.dslul.openboard.inputmethod.keyboard.emoji;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
|
||||
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
final class EmojiLayoutParams {
|
||||
private static final int DEFAULT_KEYBOARD_ROWS = 4;
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.keyboard.emoji;
|
||||
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -28,6 +27,8 @@ import org.dslul.openboard.inputmethod.keyboard.Keyboard;
|
|||
import org.dslul.openboard.inputmethod.keyboard.KeyboardView;
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
|
||||
final class EmojiPalettesAdapter extends PagerAdapter {
|
||||
private static final String TAG = EmojiPalettesAdapter.class.getSimpleName();
|
||||
private static final boolean DEBUG_PAGER = false;
|
||||
|
|
|
@ -16,14 +16,11 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.keyboard.emoji;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.NOT_A_COORDINATE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.preference.PreferenceManager;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Pair;
|
||||
import android.util.TypedValue;
|
||||
|
@ -51,6 +48,10 @@ import org.dslul.openboard.inputmethod.latin.RichInputMethodSubtype;
|
|||
import org.dslul.openboard.inputmethod.latin.common.Constants;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
|
||||
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.NOT_A_COORDINATE;
|
||||
|
||||
/**
|
||||
* View class to implement Emoji palettes.
|
||||
* The Emoji keyboard consists of group of views layout/emoji_palettes_view.
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.keyboard.internal;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.common.Constants;
|
||||
import org.dslul.openboard.inputmethod.latin.common.StringUtils;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
/**
|
||||
* The string parser of codesArray specification for <GridRows />. The attribute codesArray is an
|
||||
* array of string.
|
||||
|
|
|
@ -16,15 +16,15 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.keyboard.internal;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_OUTPUT_TEXT;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_UNSPECIFIED;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.common.Constants;
|
||||
import org.dslul.openboard.inputmethod.latin.common.StringUtils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_OUTPUT_TEXT;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_UNSPECIFIED;
|
||||
|
||||
/**
|
||||
* The string parser of the key specification.
|
||||
*
|
||||
|
|
|
@ -22,7 +22,6 @@ import android.util.SparseArray;
|
|||
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.XmlParseUtils;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@ import org.dslul.openboard.inputmethod.latin.common.StringUtils;
|
|||
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.XmlParseUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.XmlParseUtils.ParseException;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ import org.dslul.openboard.inputmethod.keyboard.Key;
|
|||
import org.dslul.openboard.inputmethod.keyboard.Keyboard;
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.keyboard.internal;
|
||||
|
||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,7 +19,6 @@ package org.dslul.openboard.inputmethod.keyboard.internal;
|
|||
import android.text.TextUtils;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import org.dslul.openboard.inputmethod.compat.CharacterCompat;
|
||||
import org.dslul.openboard.inputmethod.keyboard.Key;
|
||||
import org.dslul.openboard.inputmethod.latin.common.CollectionUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.common.Constants;
|
||||
|
@ -129,7 +128,7 @@ public final class MoreKeySpec {
|
|||
|
||||
public void addLetter(@Nonnull final Key key) {
|
||||
final int code = key.getCode();
|
||||
if (CharacterCompat.isAlphabetic(code)) {
|
||||
if (Character.isAlphabetic(code)) {
|
||||
mCodes.put(code, 0);
|
||||
} else if (code == Constants.CODE_OUTPUT_TEXT) {
|
||||
mTexts.add(key.getOutputText());
|
||||
|
@ -138,7 +137,7 @@ public final class MoreKeySpec {
|
|||
|
||||
public boolean contains(@Nonnull final MoreKeySpec moreKey) {
|
||||
final int code = moreKey.mCode;
|
||||
if (CharacterCompat.isAlphabetic(code) && mCodes.indexOfKey(code) >= 0) {
|
||||
if (Character.isAlphabetic(code) && mCodes.indexOfKey(code) >= 0) {
|
||||
return true;
|
||||
} else if (code == Constants.CODE_OUTPUT_TEXT && mTexts.contains(moreKey.mOutputText)) {
|
||||
return true;
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.keyboard.internal;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.MatrixUtils.MatrixOperationFailedException;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,21 +28,15 @@ import android.text.TextUtils;
|
|||
import android.util.Log;
|
||||
|
||||
import org.dslul.openboard.inputmethod.dictionarypack.DictionaryPackConstants;
|
||||
import org.dslul.openboard.inputmethod.dictionarypack.MD5Calculator;
|
||||
import org.dslul.openboard.inputmethod.latin.common.FileUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.define.DecoderSpecificConstants;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.DictionaryInfoUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.DictionaryInfoUtils.DictionaryInfo;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.FileTransforms;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.MetadataFileUriGetter;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
|
|
|
@ -25,7 +25,6 @@ import android.text.TextUtils;
|
|||
import android.util.Log;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.common.Constants;
|
||||
import org.dslul.openboard.inputmethod.latin.common.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
|
|
@ -22,9 +22,9 @@ import org.dslul.openboard.inputmethod.latin.common.ComposedData;
|
|||
import org.dslul.openboard.inputmethod.latin.settings.SettingsValuesForSuggestion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Abstract base class for a dictionary that can do a fuzzy search for words based on a set of key
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Cache for dictionary facilitators of multiple locales.
|
||||
* This class automatically creates and releases up to 3 facilitator instances using LRU policy.
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin;
|
||||
|
||||
import org.dslul.openboard.inputmethod.dictionarypack.DictionaryPackConstants;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.TargetPackageInfoGetterTask;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -28,6 +25,9 @@ import android.content.pm.ProviderInfo;
|
|||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import org.dslul.openboard.inputmethod.dictionarypack.DictionaryPackConstants;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.TargetPackageInfoGetterTask;
|
||||
|
||||
/**
|
||||
* Receives broadcasts pertaining to dictionary management and takes the appropriate action.
|
||||
*
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.dslul.openboard.inputmethod.latin.settings.Settings;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.NO_FLOATING_GESTURE_PREVIEW;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT;
|
||||
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
|
@ -30,6 +26,10 @@ import org.dslul.openboard.inputmethod.latin.utils.InputTypeUtils;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.NO_FLOATING_GESTURE_PREVIEW;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT;
|
||||
|
||||
/**
|
||||
* Class to hold attributes of the input field.
|
||||
*/
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.FORCE_ASCII;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT;
|
||||
|
||||
import android.Manifest.permission;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.AlertDialog;
|
||||
|
@ -40,7 +36,6 @@ import android.os.IBinder;
|
|||
import android.os.Message;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.PrintWriterPrinter;
|
||||
import android.util.Printer;
|
||||
|
@ -57,10 +52,7 @@ 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.BuildCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.compat.EditorInfoCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.compat.InputMethodServiceCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.compat.InputMethodSubtypeCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.compat.ViewOutlineProviderCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.compat.ViewOutlineProviderCompatUtils.InsetsUpdater;
|
||||
import org.dslul.openboard.inputmethod.dictionarypack.DictionaryPackConstants;
|
||||
|
@ -109,6 +101,10 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.FORCE_ASCII;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT;
|
||||
|
||||
/**
|
||||
* Input method implementation for Qwerty'ish keyboard.
|
||||
*/
|
||||
|
@ -583,8 +579,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
mSettings = Settings.getInstance();
|
||||
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
|
||||
mStatsUtilsManager = StatsUtilsManager.getInstance();
|
||||
mIsHardwareAcceleratedDrawingEnabled =
|
||||
InputMethodServiceCompatUtils.enableHardwareAcceleration(this);
|
||||
mIsHardwareAcceleratedDrawingEnabled = this.enableHardwareAcceleration();
|
||||
Log.i(TAG, "Hardware accelerated drawing: " + mIsHardwareAcceleratedDrawingEnabled);
|
||||
}
|
||||
|
||||
|
@ -1992,7 +1987,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
}
|
||||
|
||||
private void setNavigationBarVisibility(final boolean visible) {
|
||||
if (BuildCompatUtils.EFFECTIVE_SDK_INT > Build.VERSION_CODES.M) {
|
||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
|
||||
// For N and later, IMEs can specify Color.TRANSPARENT to make the navigation bar
|
||||
// transparent. For other colors the system uses the default color.
|
||||
getWindow().getWindow().setNavigationBarColor(
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package org.dslul.openboard.inputmethod.latin;
|
||||
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.text.SpannableStringBuilder;
|
||||
|
@ -34,8 +33,8 @@ import android.view.inputmethod.InputMethodManager;
|
|||
|
||||
import org.dslul.openboard.inputmethod.compat.InputConnectionCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.common.Constants;
|
||||
import org.dslul.openboard.inputmethod.latin.common.UnicodeSurrogate;
|
||||
import org.dslul.openboard.inputmethod.latin.common.StringUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.common.UnicodeSurrogate;
|
||||
import org.dslul.openboard.inputmethod.latin.inputlogic.PrivateCommandPerformer;
|
||||
import org.dslul.openboard.inputmethod.latin.settings.SpacingAndPunctuations;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.CapsModeUtils;
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
|
@ -49,6 +47,8 @@ import java.util.Set;
|
|||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
|
||||
|
||||
/**
|
||||
* Enrichment class for InputMethodManager to simplify interaction and add functionality.
|
||||
*/
|
||||
|
|
|
@ -16,13 +16,10 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
|
||||
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import org.dslul.openboard.inputmethod.compat.BuildCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.compat.InputMethodSubtypeCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.common.Constants;
|
||||
import org.dslul.openboard.inputmethod.latin.common.LocaleUtils;
|
||||
|
@ -34,6 +31,8 @@ import java.util.Locale;
|
|||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
|
||||
|
||||
/**
|
||||
* Enrichment class for InputMethodSubtype to enable concurrent multi-lingual input.
|
||||
*
|
||||
|
@ -46,7 +45,7 @@ public class RichInputMethodSubtype {
|
|||
private static final HashMap<Locale, Locale> sLocaleMap = initializeLocaleMap();
|
||||
private static final HashMap<Locale, Locale> initializeLocaleMap() {
|
||||
final HashMap<Locale, Locale> map = new HashMap<>();
|
||||
if (BuildCompatUtils.EFFECTIVE_SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// Locale#forLanguageTag is available on API Level 21+.
|
||||
// TODO: Remove this workaround once when we become able to deal with "sr-Latn".
|
||||
map.put(Locale.forLanguageTag("sr-Latn"), new Locale("sr_ZZ"));
|
||||
|
@ -54,6 +53,11 @@ public class RichInputMethodSubtype {
|
|||
return map;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InputMethodSubtype getmSubtype() {
|
||||
return mSubtype;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private final InputMethodSubtype mSubtype;
|
||||
@Nonnull
|
||||
|
|
|
@ -18,9 +18,6 @@ package org.dslul.openboard.inputmethod.latin;
|
|||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.define.DecoderSpecificConstants.SHOULD_AUTO_CORRECT_USING_NON_WHITE_LISTED_SUGGESTION;
|
||||
import static org.dslul.openboard.inputmethod.latin.define.DecoderSpecificConstants.SHOULD_REMOVE_PREVIOUSLY_REJECTED_SUGGESTION;
|
||||
|
||||
import org.dslul.openboard.inputmethod.keyboard.Keyboard;
|
||||
import org.dslul.openboard.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||
import org.dslul.openboard.inputmethod.latin.common.Constants;
|
||||
|
@ -37,6 +34,9 @@ import java.util.Locale;
|
|||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.define.DecoderSpecificConstants.SHOULD_AUTO_CORRECT_USING_NON_WHITE_LISTED_SUGGESTION;
|
||||
import static org.dslul.openboard.inputmethod.latin.define.DecoderSpecificConstants.SHOULD_REMOVE_PREVIOUSLY_REJECTED_SUGGESTION;
|
||||
|
||||
/**
|
||||
* This class loads a dictionary and provides a list of suggestions for a given sequence of
|
||||
* characters. This includes corrections and completions.
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin;
|
||||
|
||||
import android.app.DownloadManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
|
@ -24,14 +23,12 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.os.Process;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import org.dslul.openboard.inputmethod.dictionarypack.DictionaryPackConstants;
|
||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardLayoutSet;
|
||||
import org.dslul.openboard.inputmethod.latin.settings.Settings;
|
||||
import org.dslul.openboard.inputmethod.latin.setup.SetupActivity;
|
||||
|
|
|
@ -22,7 +22,6 @@ import android.database.ContentObserver;
|
|||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.provider.UserDictionary.Words;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
|
|
@ -1109,8 +1109,7 @@ public final class InputLogic {
|
|||
StatsUtils.onBackspaceSelectedText(numCharsDeleted);
|
||||
} else {
|
||||
// There is no selection, just delete one character.
|
||||
if (inputTransaction.getMSettingsValues().isBeforeJellyBean()
|
||||
|| inputTransaction.getMSettingsValues().mInputAttributes.isTypeNull()
|
||||
if (inputTransaction.getMSettingsValues().mInputAttributes.isTypeNull()
|
||||
|| Constants.NOT_A_CURSOR_POSITION
|
||||
== mConnection.getExpectedSelectionEnd()) {
|
||||
// There are three possible reasons to send a key event: either the field has
|
||||
|
@ -1518,10 +1517,7 @@ public final class InputLogic {
|
|||
// HACK: We may want to special-case some apps that exhibit bad behavior in case of
|
||||
// recorrection. This is a temporary, stopgap measure that will be removed later.
|
||||
// TODO: remove this.
|
||||
if (settingsValues.isBrokenByRecorrection()
|
||||
// Recorrection is not supported in languages without spaces because we don't know
|
||||
// how to segment them yet.
|
||||
|| !settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces
|
||||
if (!settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces
|
||||
// If no suggestions are requested, don't try restarting suggestions.
|
||||
|| !settingsValues.needsToLookupSuggestions()
|
||||
// If we are currently in a batch input, we must not resume suggestions, or the result
|
||||
|
@ -1997,16 +1993,7 @@ public final class InputLogic {
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: we should do this also when the editor has TYPE_NULL
|
||||
if (Constants.CODE_ENTER == codePoint && settingsValues.isBeforeJellyBean()) {
|
||||
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate
|
||||
// a hardware keyboard event on pressing enter or delete. This is bad for many
|
||||
// reasons (there are race conditions with commits) but some applications are
|
||||
// relying on this behavior so we continue to support it for older apps.
|
||||
sendDownUpKeyEvent(KeyEvent.KEYCODE_ENTER);
|
||||
} else {
|
||||
mConnection.commitText(StringUtils.newSingleCodePointString(codePoint), 1);
|
||||
}
|
||||
mConnection.commitText(StringUtils.newSingleCodePointString(codePoint), 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,10 +20,9 @@ import android.os.Handler;
|
|||
import android.os.HandlerThread;
|
||||
import android.os.Message;
|
||||
|
||||
import org.dslul.openboard.inputmethod.compat.LooperCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.LatinIME;
|
||||
import org.dslul.openboard.inputmethod.latin.SuggestedWords;
|
||||
import org.dslul.openboard.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
|
||||
import org.dslul.openboard.inputmethod.latin.SuggestedWords;
|
||||
import org.dslul.openboard.inputmethod.latin.common.InputPointers;
|
||||
|
||||
/**
|
||||
|
@ -83,7 +82,7 @@ class InputLogicHandler implements Handler.Callback {
|
|||
// In unit tests, we create several instances of LatinIME, which results in several instances
|
||||
// of InputLogicHandler. To avoid these handlers lingering, we call this.
|
||||
public void destroy() {
|
||||
LooperCompatUtils.quitSafely(mNonUIThreadHandler.getLooper());
|
||||
mNonUIThreadHandler.getLooper().quitSafely();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.app.Activity;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
|
||||
|
|
|
@ -20,13 +20,14 @@ import android.app.Activity;
|
|||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
/**
|
||||
* Utility class for permissions.
|
||||
*/
|
||||
|
|
|
@ -24,8 +24,6 @@ import org.dslul.openboard.inputmethod.latin.BinaryDictionary;
|
|||
import org.dslul.openboard.inputmethod.latin.Dictionary;
|
||||
import org.dslul.openboard.inputmethod.latin.ExpandableBinaryDictionary;
|
||||
import org.dslul.openboard.inputmethod.latin.NgramContext;
|
||||
import org.dslul.openboard.inputmethod.latin.define.DecoderSpecificConstants;
|
||||
import org.dslul.openboard.inputmethod.latin.define.ProductionFlags;
|
||||
import org.dslul.openboard.inputmethod.latin.makedict.DictionaryHeader;
|
||||
|
||||
import java.io.File;
|
||||
|
|
|
@ -21,8 +21,8 @@ import android.content.SharedPreferences;
|
|||
import android.preference.PreferenceFragment;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.RichInputMethodSubtype;
|
||||
import org.dslul.openboard.inputmethod.latin.RichInputMethodManager;
|
||||
import org.dslul.openboard.inputmethod.latin.RichInputMethodSubtype;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
|
|
|
@ -22,12 +22,10 @@ import android.content.res.Resources;
|
|||
import android.media.AudioManager;
|
||||
import android.os.Bundle;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.AudioAndHapticFeedbackManager;
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
import org.dslul.openboard.inputmethod.latin.SystemBroadcastReceiver;
|
||||
import org.dslul.openboard.inputmethod.latin.define.ProductionFlags;
|
||||
|
||||
/**
|
||||
* "Advanced" settings sub screen.
|
||||
|
|
|
@ -23,7 +23,6 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.SwitchPreference;
|
||||
|
|
|
@ -32,8 +32,6 @@ import android.widget.ArrayAdapter;
|
|||
import android.widget.Spinner;
|
||||
import android.widget.SpinnerAdapter;
|
||||
|
||||
import org.dslul.openboard.inputmethod.compat.InputMethodSubtypeCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.compat.ViewCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
import org.dslul.openboard.inputmethod.latin.RichInputMethodManager;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.AdditionalSubtypeUtils;
|
||||
|
@ -125,8 +123,7 @@ final class CustomInputStylePreference extends DialogPreference
|
|||
// the view would align them to the left even if the system locale is RTL, but that
|
||||
// would look strange. To fix this, we align them to the view's start, which will be
|
||||
// natural for any direction.
|
||||
ViewCompatUtils.setTextAlignment(
|
||||
mKeyboardLayoutSetSpinner, ViewCompatUtils.TEXT_ALIGNMENT_VIEW_START);
|
||||
mKeyboardLayoutSetSpinner.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -295,7 +292,7 @@ final class CustomInputStylePreference extends DialogPreference
|
|||
subtype.getLocale(), subtype.hashCode(), subtype.hashCode(),
|
||||
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype)));
|
||||
}
|
||||
if (InputMethodSubtypeCompatUtils.isAsciiCapable(subtype)) {
|
||||
if (subtype.isAsciiCapable()) {
|
||||
items.add(new SubtypeLocaleItem(subtype));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ import android.os.Bundle;
|
|||
import android.preference.Preference;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceGroup;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -47,6 +46,8 @@ import org.dslul.openboard.inputmethod.latin.utils.SubtypeLocaleUtils;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
public final class CustomInputStyleSettingsFragment extends PreferenceFragment
|
||||
implements CustomInputStylePreference.Listener {
|
||||
private static final String TAG = CustomInputStyleSettingsFragment.class.getSimpleName();
|
||||
|
|
|
@ -19,7 +19,6 @@ package org.dslul.openboard.inputmethod.latin.settings;
|
|||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ import android.os.Build;
|
|||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import org.dslul.openboard.inputmethod.compat.BuildCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.AudioAndHapticFeedbackManager;
|
||||
import org.dslul.openboard.inputmethod.latin.InputAttributes;
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
|
@ -73,9 +72,9 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
|||
public static final String PREF_BLOCK_POTENTIALLY_OFFENSIVE =
|
||||
"pref_key_block_potentially_offensive";
|
||||
public static final boolean ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS =
|
||||
BuildCompatUtils.EFFECTIVE_SDK_INT <= Build.VERSION_CODES.KITKAT;
|
||||
Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT;
|
||||
public static final boolean SHOULD_SHOW_LXX_SUGGESTION_UI =
|
||||
BuildCompatUtils.EFFECTIVE_SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
||||
public static final String PREF_SHOW_LANGUAGE_SWITCH_KEY =
|
||||
"pref_show_language_switch_key";
|
||||
public static final String PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST =
|
||||
|
|
|
@ -16,17 +16,15 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin.settings;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.permissions.PermissionsManager;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.FragmentUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.StatsUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.StatsUtilsManager;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.permissions.PermissionsManager;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.FragmentUtils;
|
||||
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import android.view.MenuItem;
|
||||
|
||||
public final class SettingsActivity extends PreferenceActivity
|
||||
implements ActivityCompat.OnRequestPermissionsResultCallback {
|
||||
|
|
|
@ -28,7 +28,6 @@ import android.view.MenuInflater;
|
|||
import android.view.MenuItem;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
import org.dslul.openboard.inputmethod.latin.define.ProductionFlags;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.ApplicationUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.FeedbackUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.JniUtils;
|
||||
|
|
|
@ -21,7 +21,6 @@ import android.content.SharedPreferences;
|
|||
import android.content.pm.PackageInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
|
||||
|
@ -292,18 +291,6 @@ public class SettingsValues {
|
|||
return mDisplayOrientation == configuration.orientation;
|
||||
}
|
||||
|
||||
public boolean isBeforeJellyBean() {
|
||||
final AppWorkaroundsUtils appWorkaroundUtils
|
||||
= mAppWorkarounds.get(null, TIMEOUT_TO_GET_TARGET_PACKAGE);
|
||||
return null == appWorkaroundUtils ? false : appWorkaroundUtils.isBeforeJellyBean();
|
||||
}
|
||||
|
||||
public boolean isBrokenByRecorrection() {
|
||||
final AppWorkaroundsUtils appWorkaroundUtils
|
||||
= mAppWorkarounds.get(null, TIMEOUT_TO_GET_TARGET_PACKAGE);
|
||||
return null == appWorkaroundUtils ? false : appWorkaroundUtils.isBrokenByRecorrection();
|
||||
}
|
||||
|
||||
private static final String SUGGESTIONS_VISIBILITY_HIDE_VALUE_OBSOLETE = "2";
|
||||
|
||||
private static boolean readSuggestionsEnabled(final SharedPreferences prefs) {
|
||||
|
|
|
@ -21,7 +21,6 @@ import android.content.res.ColorStateList;
|
|||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
@ -30,6 +29,8 @@ import android.widget.TextView;
|
|||
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
public final class SetupStartIndicatorView extends LinearLayout {
|
||||
public SetupStartIndicatorView(final Context context, final AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
|
|
@ -20,12 +20,13 @@ import android.content.Context;
|
|||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
public final class SetupStepIndicatorView extends View {
|
||||
private final Path mIndicatorPath = new Path();
|
||||
private final Paint mIndicatorPaint = new Paint();
|
||||
|
|
|
@ -33,8 +33,6 @@ import android.widget.ImageView;
|
|||
import android.widget.TextView;
|
||||
import android.widget.VideoView;
|
||||
|
||||
import org.dslul.openboard.inputmethod.compat.TextViewCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.compat.ViewCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
import org.dslul.openboard.inputmethod.latin.settings.SettingsActivity;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.LeakGuardHandlerWrapper;
|
||||
|
@ -222,8 +220,8 @@ public final class SetupWizardActivity extends Activity implements View.OnClickL
|
|||
mActionNext = findViewById(R.id.setup_next);
|
||||
mActionNext.setOnClickListener(this);
|
||||
mActionFinish = (TextView)findViewById(R.id.setup_finish);
|
||||
TextViewCompatUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(mActionFinish,
|
||||
getResources().getDrawable(R.drawable.ic_setup_finish), null, null, null);
|
||||
mActionFinish.setCompoundDrawablesRelativeWithIntrinsicBounds(getResources().getDrawable(R.drawable.ic_setup_finish),
|
||||
null, null, null);
|
||||
mActionFinish.setOnClickListener(this);
|
||||
}
|
||||
|
||||
|
@ -460,11 +458,11 @@ public final class SetupWizardActivity extends Activity implements View.OnClickL
|
|||
mActionLabel = (TextView)mStepView.findViewById(R.id.setup_step_action_label);
|
||||
mActionLabel.setText(res.getString(actionLabel));
|
||||
if (actionIcon == 0) {
|
||||
final int paddingEnd = ViewCompatUtils.getPaddingEnd(mActionLabel);
|
||||
ViewCompatUtils.setPaddingRelative(mActionLabel, paddingEnd, 0, paddingEnd, 0);
|
||||
final int paddingEnd = mActionLabel.getPaddingEnd();
|
||||
mActionLabel.setPaddingRelative(paddingEnd, 0, paddingEnd, 0);
|
||||
} else {
|
||||
TextViewCompatUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
mActionLabel, res.getDrawable(actionIcon), null, null, null);
|
||||
mActionLabel.setCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
res.getDrawable(actionIcon), null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ import android.util.LruCache;
|
|||
import android.view.textservice.SuggestionsInfo;
|
||||
import android.view.textservice.TextInfo;
|
||||
|
||||
import org.dslul.openboard.inputmethod.compat.SuggestionsInfoCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.keyboard.Keyboard;
|
||||
import org.dslul.openboard.inputmethod.latin.NgramContext;
|
||||
import org.dslul.openboard.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||
|
@ -312,8 +311,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
|
|||
final int flags =
|
||||
SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO
|
||||
| (result.mHasRecommendedSuggestions
|
||||
? SuggestionsInfoCompatUtils
|
||||
.getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS()
|
||||
? SuggestionsInfo.RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS
|
||||
: 0);
|
||||
final SuggestionsInfo retval = new SuggestionsInfo(flags, result.mSuggestions);
|
||||
mSuggestionsCache.putSuggestionsToCache(text, result.mSuggestions, flags);
|
||||
|
|
|
@ -16,14 +16,15 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin.spellcheck;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.permissions.PermissionsManager;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.FragmentUtils;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.permissions.PermissionsManager;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.FragmentUtils;
|
||||
|
||||
import androidx.core.app.ActivityCompat;
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,7 +21,6 @@ import android.content.res.Resources;
|
|||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
|
@ -55,6 +54,8 @@ import org.dslul.openboard.inputmethod.latin.utils.ImportantNoticeUtils;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
public final class SuggestionStripView extends RelativeLayout implements OnClickListener,
|
||||
OnLongClickListener {
|
||||
public interface Listener {
|
||||
|
|
|
@ -26,7 +26,6 @@ import android.text.TextUtils;
|
|||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
|
||||
import org.dslul.openboard.inputmethod.compat.UserDictionaryCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
import org.dslul.openboard.inputmethod.latin.common.LocaleUtils;
|
||||
|
||||
|
@ -184,7 +183,7 @@ public class UserDictionaryAddWordContents {
|
|||
|
||||
// In this class we use the empty string to represent 'all locales' and mLocale cannot
|
||||
// be null. However the addWord method takes null to mean 'all locales'.
|
||||
UserDictionaryCompatUtils.addWord(context, newWord.toString(),
|
||||
UserDictionary.Words.addWord(context, newWord.toString(),
|
||||
FREQUENCY_FOR_USER_DICTIONARY_ADDS, newShortcut, TextUtils.isEmpty(mLocale) ?
|
||||
null : LocaleUtils.constructLocaleFromString(mLocale));
|
||||
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin.userdictionary;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
import org.dslul.openboard.inputmethod.latin.userdictionary.UserDictionaryAddWordContents.LocaleRenderer;
|
||||
import org.dslul.openboard.inputmethod.latin.userdictionary.UserDictionaryLocalePicker.LocationChangedListener;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
|
@ -33,6 +29,10 @@ import android.widget.AdapterView;
|
|||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
import org.dslul.openboard.inputmethod.latin.userdictionary.UserDictionaryAddWordContents.LocaleRenderer;
|
||||
import org.dslul.openboard.inputmethod.latin.userdictionary.UserDictionaryLocalePicker.LocationChangedListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
|
|
|
@ -16,14 +16,11 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin.userdictionary;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
|
||||
import android.app.ListFragment;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.UserDictionary;
|
||||
import android.text.TextUtils;
|
||||
|
@ -40,6 +37,8 @@ import android.widget.SectionIndexer;
|
|||
import android.widget.SimpleCursorAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
// Caveat: This class is basically taken from
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin.userdictionary;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
import org.dslul.openboard.inputmethod.latin.common.LocaleUtils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
import org.dslul.openboard.inputmethod.latin.common.LocaleUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,13 +16,6 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin.utils;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.ExtraValue.ASCII_CAPABLE;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME;
|
||||
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
@ -36,6 +29,13 @@ import org.dslul.openboard.inputmethod.latin.common.StringUtils;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.ExtraValue.ASCII_CAPABLE;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME;
|
||||
import static org.dslul.openboard.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
|
||||
|
||||
public final class AdditionalSubtypeUtils {
|
||||
private static final String TAG = AdditionalSubtypeUtils.class.getSimpleName();
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ import android.view.ViewParent;
|
|||
import android.view.inputmethod.CursorAnchorInfo;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.dslul.openboard.inputmethod.compat.BuildCompatUtils;
|
||||
import org.dslul.openboard.inputmethod.compat.CursorAnchorInfoCompatWrapper;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
@ -96,7 +95,7 @@ public final class CursorAnchorInfoUtils {
|
|||
@Nullable
|
||||
public static CursorAnchorInfoCompatWrapper extractFromTextView(
|
||||
@Nonnull final TextView textView) {
|
||||
if (BuildCompatUtils.EFFECTIVE_SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return null;
|
||||
}
|
||||
return CursorAnchorInfoCompatWrapper.wrap(extractFromTextViewInternal(textView));
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue