pull updates accidentally committed to hangul_update branch

This commit is contained in:
Helium314 2023-09-16 22:49:05 +02:00
commit 7b9ba8d60e
67 changed files with 330 additions and 1020 deletions

View file

@ -111,13 +111,11 @@ public class ProximityInfo {
return count;
}
private long createNativeProximityInfo(
@NonNull final TouchPositionCorrection touchPositionCorrection) {
final List<Key>[] gridNeighborKeys = mGridNeighbors;
private long createNativeProximityInfo(@NonNull final TouchPositionCorrection touchPositionCorrection) {
final int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE];
Arrays.fill(proximityCharsArray, Constants.NOT_A_CODE);
for (int i = 0; i < mGridSize; ++i) {
final List<Key> neighborKeys = gridNeighborKeys[i];
final List<Key> neighborKeys = mGridNeighbors[i];
final int proximityCharsLength = neighborKeys.size();
int infoIndex = i * MAX_PROXIMITY_CHARS_SIZE;
for (int j = 0; j < proximityCharsLength; ++j) {
@ -243,10 +241,9 @@ public class ProximityInfo {
}
private void computeNearestNeighbors() {
final int defaultWidth = mMostCommonKeyWidth;
final int keyCount = mSortedKeys.size();
final int gridSize = mGridNeighbors.length;
final int threshold = (int) (defaultWidth * SEARCH_DISTANCE);
final int threshold = (int) (mMostCommonKeyWidth * SEARCH_DISTANCE);
final int thresholdSquared = threshold * threshold;
// Round-up so we don't have any pixels outside the grid
final int lastPixelXCoordinate = mGridWidth * mCellWidth - 1;

View file

@ -18,9 +18,9 @@ import org.dslul.openboard.inputmethod.latin.SuggestedWords
import org.dslul.openboard.inputmethod.latin.utils.InputTypeUtils
class AccessibilityUtils private constructor() {
private var mContext: Context? = null
private var mAccessibilityManager: AccessibilityManager? = null
private var mAudioManager: AudioManager? = null
private lateinit var mContext: Context
private lateinit var mAccessibilityManager: AccessibilityManager
private lateinit var mAudioManager: AudioManager
/** The most recent auto-correction. */
private var mAutoCorrectionWord: String? = null
/** The most recent typed word for auto-correction. */
@ -39,7 +39,7 @@ class AccessibilityUtils private constructor() {
* @return `true` if accessibility is enabled.
*/
val isAccessibilityEnabled: Boolean
get() = ENABLE_ACCESSIBILITY && mAccessibilityManager!!.isEnabled
get() = ENABLE_ACCESSIBILITY && mAccessibilityManager.isEnabled
/**
* Returns `true` if touch exploration is enabled. Currently, this
@ -49,7 +49,7 @@ class AccessibilityUtils private constructor() {
* @return `true` if touch exploration is enabled.
*/
val isTouchExplorationEnabled: Boolean
get() = isAccessibilityEnabled && mAccessibilityManager!!.isTouchExplorationEnabled
get() = isAccessibilityEnabled && mAccessibilityManager.isTouchExplorationEnabled
/**
* Returns whether the device should obscure typed password characters.
@ -61,12 +61,12 @@ class AccessibilityUtils private constructor() {
if (editorInfo == null) return false
// The user can optionally force speaking passwords.
if (Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD != null) {
val speakPassword = Settings.Secure.getInt(mContext!!.contentResolver,
val speakPassword = Settings.Secure.getInt(mContext.contentResolver,
Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0) != 0
if (speakPassword) return false
}
// Always speak if the user is listening through headphones.
return if (mAudioManager!!.isWiredHeadsetOn || mAudioManager!!.isBluetoothA2dpOn) {
return if (mAudioManager.isWiredHeadsetOn || mAudioManager.isBluetoothA2dpOn) {
false
} else InputTypeUtils.isPasswordInputType(editorInfo.inputType)
// Don't speak if the IME is connected to a password field.
@ -105,9 +105,9 @@ class AccessibilityUtils private constructor() {
if (!TextUtils.isEmpty(mAutoCorrectionWord)) {
if (!TextUtils.equals(mAutoCorrectionWord, mTypedWord)) {
return if (shouldObscure) { // This should never happen, but just in case...
mContext!!.getString(R.string.spoken_auto_correct_obscured,
mContext.getString(R.string.spoken_auto_correct_obscured,
keyCodeDescription)
} else mContext!!.getString(R.string.spoken_auto_correct, keyCodeDescription,
} else mContext.getString(R.string.spoken_auto_correct, keyCodeDescription,
mTypedWord, mAutoCorrectionWord)
}
}
@ -122,7 +122,7 @@ class AccessibilityUtils private constructor() {
* @param text The text to speak.
*/
fun announceForAccessibility(view: View, text: CharSequence?) {
if (!mAccessibilityManager!!.isEnabled) {
if (!mAccessibilityManager.isEnabled) {
Log.e(TAG, "Attempted to speak when accessibility was disabled!")
return
}
@ -154,10 +154,9 @@ class AccessibilityUtils private constructor() {
* @param editorInfo The input connection's editor info attribute.
* @param restarting Whether the connection is being restarted.
*/
fun onStartInputViewInternal(view: View, editorInfo: EditorInfo?,
restarting: Boolean) {
fun onStartInputViewInternal(view: View, editorInfo: EditorInfo?, restarting: Boolean) {
if (shouldObscureInput(editorInfo)) {
val text = mContext!!.getText(R.string.spoken_use_headphones)
val text = mContext.getText(R.string.spoken_use_headphones)
announceForAccessibility(view, text)
}
}
@ -169,8 +168,8 @@ class AccessibilityUtils private constructor() {
* @param event The event to send.
*/
fun requestSendAccessibilityEvent(event: AccessibilityEvent?) {
if (mAccessibilityManager!!.isEnabled) {
mAccessibilityManager!!.sendAccessibilityEvent(event)
if (mAccessibilityManager.isEnabled) {
mAccessibilityManager.sendAccessibilityEvent(event)
}
}
@ -180,10 +179,10 @@ class AccessibilityUtils private constructor() {
private val PACKAGE = AccessibilityUtils::class.java.getPackage()!!.name
val instance = AccessibilityUtils()
/*
* Setting this constant to {@code false} will disable all keyboard
* accessibility code, regardless of whether Accessibility is turned on in
* the system settings. It should ONLY be used in the event of an emergency.
*/
* Setting this constant to {@code false} will disable all keyboard
* accessibility code, regardless of whether Accessibility is turned on in
* the system settings. It should ONLY be used in the event of an emergency.
*/
private const val ENABLE_ACCESSIBILITY = true
@JvmStatic

View file

@ -15,7 +15,30 @@ import java.util.*
internal class KeyCodeDescriptionMapper private constructor() {
// Sparse array of spoken description resource IDs indexed by key codes
private val mKeyCodeMap = SparseIntArray()
private val mKeyCodeMap = SparseIntArray().apply {
// Special non-character codes defined in Keyboard
put(Constants.CODE_SPACE, R.string.spoken_description_space)
put(Constants.CODE_DELETE, R.string.spoken_description_delete)
put(Constants.CODE_ENTER, R.string.spoken_description_return)
put(Constants.CODE_SETTINGS, R.string.spoken_description_settings)
put(Constants.CODE_SHIFT, R.string.spoken_description_shift)
put(Constants.CODE_SHORTCUT, R.string.spoken_description_mic)
put(Constants.CODE_SWITCH_ALPHA_SYMBOL, R.string.spoken_description_to_symbol)
put(Constants.CODE_TAB, R.string.spoken_description_tab)
put(Constants.CODE_LANGUAGE_SWITCH, R.string.spoken_description_language_switch)
put(Constants.CODE_ACTION_NEXT, R.string.spoken_description_action_next)
put(Constants.CODE_ACTION_PREVIOUS, R.string.spoken_description_action_previous)
put(Constants.CODE_EMOJI, R.string.spoken_description_emoji)
// Because the upper-case and lower-case mappings of the following letters is depending on
// the locale, the upper case descriptions should be defined here. The lower case
// descriptions are handled in {@link #getSpokenLetterDescriptionId(Context,int)}.
// U+0049: "I" LATIN CAPITAL LETTER I
// U+0069: "i" LATIN SMALL LETTER I
// U+0130: "İ" LATIN CAPITAL LETTER I WITH DOT ABOVE
// U+0131: "ı" LATIN SMALL LETTER DOTLESS I
put(0x0049, R.string.spoken_letter_0049)
put(0x0130, R.string.spoken_letter_0130)
}
/**
* Returns the localized description of the action performed by a specified
@ -27,8 +50,7 @@ internal class KeyCodeDescriptionMapper private constructor() {
* @param shouldObscure {@true} if text (e.g. non-control) characters should be obscured.
* @return a character sequence describing the action performed by pressing the key
*/
fun getDescriptionForKey(context: Context, keyboard: Keyboard?,
key: Key, shouldObscure: Boolean): String? {
fun getDescriptionForKey(context: Context, keyboard: Keyboard?, key: Key, shouldObscure: Boolean): String? {
val code = key.code
if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) {
val description = getDescriptionForSwitchAlphaSymbol(context, keyboard)
@ -39,17 +61,19 @@ internal class KeyCodeDescriptionMapper private constructor() {
if (code == Constants.CODE_SHIFT) {
return getDescriptionForShiftKey(context, keyboard)
}
if (code == Constants.CODE_ENTER) { // The following function returns the correct description in all action and
// regular enter cases, taking care of all modes.
if (code == Constants.CODE_ENTER) {
// The following function returns the correct description in all action and
// regular enter cases, taking care of all modes.
return getDescriptionForActionKey(context, keyboard, key)
}
if (code == Constants.CODE_OUTPUT_TEXT) {
val outputText = key.outputText
val outputText = key.outputText ?: return context.getString(R.string.spoken_description_unknown)
val description = getSpokenEmoticonDescription(context, outputText)
return if (TextUtils.isEmpty(description)) outputText else description
}
// Just attempt to speak the description.
if (code != Constants.CODE_UNSPECIFIED) { // If the key description should be obscured, now is the time to do it.
if (code != Constants.CODE_UNSPECIFIED) {
// If the key description should be obscured, now is the time to do it.
val isDefinedNonCtrl = (Character.isDefined(code)
&& !Character.isISOControl(code))
if (shouldObscure && isDefinedNonCtrl) {
@ -74,7 +98,8 @@ internal class KeyCodeDescriptionMapper private constructor() {
* @param codePoint The code point from which to obtain a description.
* @return a character sequence describing the code point.
*/
fun getDescriptionForCodePoint(context: Context, codePoint: Int): String? { // If the key description should be obscured, now is the time to do it.
fun getDescriptionForCodePoint(context: Context, codePoint: Int): String? {
// If the key description should be obscured, now is the time to do it.
val index = mKeyCodeMap.indexOfKey(codePoint)
if (index >= 0) {
return context.getString(mKeyCodeMap.valueAt(index))
@ -141,8 +166,7 @@ internal class KeyCodeDescriptionMapper private constructor() {
val resourceName = String.format(Locale.ROOT, resourceNameFormat, code)
val resources = context.resources
// Note that the resource package name may differ from the context package name.
val resourcePackageName = resources.getResourcePackageName(
R.string.spoken_description_unknown)
val resourcePackageName = resources.getResourcePackageName(R.string.spoken_description_unknown)
val resId = resources.getIdentifier(resourceName, "string", resourcePackageName)
if (resId != 0) {
mKeyCodeMap.append(code, resId)
@ -170,12 +194,8 @@ internal class KeyCodeDescriptionMapper private constructor() {
* @param keyboard The keyboard on which the key resides.
* @return a character sequence describing the action performed by pressing the key
*/
private fun getDescriptionForSwitchAlphaSymbol(context: Context,
keyboard: Keyboard?): String? {
val keyboardId = keyboard!!.mId
val elementId = keyboardId.mElementId
val resId: Int
resId = when (elementId) {
private fun getDescriptionForSwitchAlphaSymbol(context: Context, keyboard: Keyboard?): String? {
val resId = when (val elementId = keyboard?.mId?.mElementId) {
KeyboardId.ELEMENT_ALPHABET, KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED, KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED, KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED, KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED -> R.string.spoken_description_to_symbol
KeyboardId.ELEMENT_SYMBOLS, KeyboardId.ELEMENT_SYMBOLS_SHIFTED -> R.string.spoken_description_to_alpha
KeyboardId.ELEMENT_PHONE -> R.string.spoken_description_to_symbol
@ -195,12 +215,8 @@ internal class KeyCodeDescriptionMapper private constructor() {
* @param keyboard The keyboard on which the key resides.
* @return A context-sensitive description of the "Shift" key.
*/
private fun getDescriptionForShiftKey(context: Context,
keyboard: Keyboard?): String {
val keyboardId = keyboard!!.mId
val elementId = keyboardId.mElementId
val resId: Int
resId = when (elementId) {
private fun getDescriptionForShiftKey(context: Context, keyboard: Keyboard?): String {
val resId: Int = when (keyboard?.mId?.mElementId) {
KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED, KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED -> R.string.spoken_description_caps_lock
KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED, KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED -> R.string.spoken_description_shift_shifted
KeyboardId.ELEMENT_SYMBOLS -> R.string.spoken_description_symbols_shift
@ -218,16 +234,12 @@ internal class KeyCodeDescriptionMapper private constructor() {
* @param key The key to describe.
* @return Returns a context-sensitive description of the "Enter" action key.
*/
private fun getDescriptionForActionKey(context: Context, keyboard: Keyboard?,
key: Key): String {
val keyboardId = keyboard!!.mId
val actionId = keyboardId.imeAction()
val resId: Int
private fun getDescriptionForActionKey(context: Context, keyboard: Keyboard?, key: Key): String {
// Always use the label, if available.
if (!TextUtils.isEmpty(key.label)) {
return key.label!!.trim { it <= ' ' }
}
resId = when (actionId) {
val resId = when (keyboard?.mId?.imeAction()) {
EditorInfo.IME_ACTION_SEARCH -> R.string.label_search_key
EditorInfo.IME_ACTION_GO -> R.string.label_go_key
EditorInfo.IME_ACTION_SEND -> R.string.label_send_key
@ -240,10 +252,9 @@ internal class KeyCodeDescriptionMapper private constructor() {
}
// TODO: Remove this method once TTS supports emoticon verbalization.
private fun getSpokenEmoticonDescription(context: Context,
outputText: String?): String? {
private fun getSpokenEmoticonDescription(context: Context, outputText: String): String? {
val sb = StringBuilder(SPOKEN_EMOTICON_RESOURCE_NAME_PREFIX)
val textLength = outputText!!.length
val textLength = outputText.length
var index = 0
while (index < textLength) {
val codePoint = outputText.codePointAt(index)
@ -253,36 +264,10 @@ internal class KeyCodeDescriptionMapper private constructor() {
val resourceName = sb.toString()
val resources = context.resources
// Note that the resource package name may differ from the context package name.
val resourcePackageName = resources.getResourcePackageName(
R.string.spoken_description_unknown)
val resourcePackageName = resources.getResourcePackageName(R.string.spoken_description_unknown)
val resId = resources.getIdentifier(resourceName, "string", resourcePackageName)
return if (resId == 0) null else resources.getString(resId)
}
}
init { // Special non-character codes defined in Keyboard
mKeyCodeMap.put(Constants.CODE_SPACE, R.string.spoken_description_space)
mKeyCodeMap.put(Constants.CODE_DELETE, R.string.spoken_description_delete)
mKeyCodeMap.put(Constants.CODE_ENTER, R.string.spoken_description_return)
mKeyCodeMap.put(Constants.CODE_SETTINGS, R.string.spoken_description_settings)
mKeyCodeMap.put(Constants.CODE_SHIFT, R.string.spoken_description_shift)
mKeyCodeMap.put(Constants.CODE_SHORTCUT, R.string.spoken_description_mic)
mKeyCodeMap.put(Constants.CODE_SWITCH_ALPHA_SYMBOL, R.string.spoken_description_to_symbol)
mKeyCodeMap.put(Constants.CODE_TAB, R.string.spoken_description_tab)
mKeyCodeMap.put(Constants.CODE_LANGUAGE_SWITCH,
R.string.spoken_description_language_switch)
mKeyCodeMap.put(Constants.CODE_ACTION_NEXT, R.string.spoken_description_action_next)
mKeyCodeMap.put(Constants.CODE_ACTION_PREVIOUS,
R.string.spoken_description_action_previous)
mKeyCodeMap.put(Constants.CODE_EMOJI, R.string.spoken_description_emoji)
// Because the upper-case and lower-case mappings of the following letters is depending on
// the locale, the upper case descriptions should be defined here. The lower case
// descriptions are handled in {@link #getSpokenLetterDescriptionId(Context,int)}.
// U+0049: "I" LATIN CAPITAL LETTER I
// U+0069: "i" LATIN SMALL LETTER I
// U+0130: "İ" LATIN CAPITAL LETTER I WITH DOT ABOVE
// U+0131: "ı" LATIN SMALL LETTER DOTLESS I
mKeyCodeMap.put(0x0049, R.string.spoken_letter_0049)
mKeyCodeMap.put(0x0130, R.string.spoken_letter_0130)
}
}
}

View file

@ -25,12 +25,14 @@ import org.dslul.openboard.inputmethod.keyboard.KeyboardView
*
* @param <KV> The keyboard view class type.
</KV> */
open class KeyboardAccessibilityDelegate<KV : KeyboardView?>(protected val mKeyboardView: KV, protected val mKeyDetector: KeyDetector) : AccessibilityDelegateCompat() {
open class KeyboardAccessibilityDelegate<KV : KeyboardView>(
protected val mKeyboardView: KV,
protected val mKeyDetector: KeyDetector
) : AccessibilityDelegateCompat() {
private var mKeyboard: Keyboard? = null
private var mAccessibilityNodeProvider: KeyboardAccessibilityNodeProvider<KV>? = null
private var mLastHoverKey: Key? = null
protected open var lastHoverKey: Key?
get() = mLastHoverKey
set(key) {
@ -45,14 +47,14 @@ open class KeyboardAccessibilityDelegate<KV : KeyboardView?>(protected val mKeyb
* @param keyboard The keyboard that is being set to the wrapping view.
*/
open var keyboard: Keyboard?
get() = mKeyboard
set(keyboard) {
if (keyboard == null) {
return
get() = mKeyboard
set(keyboard) {
if (keyboard == null) {
return
}
mAccessibilityNodeProvider?.setKeyboard(keyboard)
mKeyboard = keyboard
}
mAccessibilityNodeProvider?.setKeyboard(keyboard)
mKeyboard = keyboard
}
/**
* Sends a window state change event with the specified string resource id.
@ -63,7 +65,7 @@ open class KeyboardAccessibilityDelegate<KV : KeyboardView?>(protected val mKeyb
if (resId == 0) {
return
}
val context = mKeyboardView!!.context
val context = mKeyboardView.context
sendWindowStateChanged(context.getString(resId))
}
@ -74,7 +76,7 @@ open class KeyboardAccessibilityDelegate<KV : KeyboardView?>(protected val mKeyb
*/
protected fun sendWindowStateChanged(text: String?) {
val stateChange = AccessibilityUtils.obtainEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
mKeyboardView!!.onInitializeAccessibilityEvent(stateChange)
mKeyboardView.onInitializeAccessibilityEvent(stateChange)
stateChange.text.add(text)
stateChange.contentDescription = null
val parent = mKeyboardView.parent
@ -91,19 +93,21 @@ open class KeyboardAccessibilityDelegate<KV : KeyboardView?>(protected val mKeyb
*/
override fun getAccessibilityNodeProvider(host: View): KeyboardAccessibilityNodeProvider<KV> {
return accessibilityNodeProvider
}// Instantiate the provide only when requested. Since the system
// will call this method multiple times it is a good practice to
// cache the provider instance.
}
// Instantiate the provide only when requested. Since the system
// will call this method multiple times it is a good practice to
// cache the provider instance.
/**
* @return A lazily-instantiated node provider for this view delegate.
*/
protected val accessibilityNodeProvider: KeyboardAccessibilityNodeProvider<KV>
get() { // Instantiate the provide only when requested. Since the system
// will call this method multiple times it is a good practice to
// cache the provider instance.
return mAccessibilityNodeProvider ?: KeyboardAccessibilityNodeProvider(mKeyboardView, this)
}
get() {
// Instantiate the provide only when requested. Since the system
// will call this method multiple times it is a good practice to
// cache the provider instance.
return mAccessibilityNodeProvider ?: KeyboardAccessibilityNodeProvider(mKeyboardView, this)
}
/**
* Get a key that a hover event is on.
@ -177,7 +181,7 @@ open class KeyboardAccessibilityDelegate<KV : KeyboardView?>(protected val mKeyb
lastKey?.let { onHoverExitFrom(it) }
val key = getHoverKeyOf(event)
// Make sure we're not getting an EXIT event because the user slid
// off the keyboard area, then force a key press.
// off the keyboard area, then force a key press.
key?.let { performClickOn(it)
onHoverExitFrom(it) }
mLastHoverKey = null
@ -208,7 +212,7 @@ open class KeyboardAccessibilityDelegate<KV : KeyboardView?>(protected val mKeyb
val eventTime = SystemClock.uptimeMillis()
val touchEvent = MotionEvent.obtain(
eventTime, eventTime, touchAction, x.toFloat(), y.toFloat(), 0 /* metaState */)
mKeyboardView!!.onTouchEvent(touchEvent)
mKeyboardView.onTouchEvent(touchEvent)
touchEvent.recycle()
}
@ -222,7 +226,7 @@ open class KeyboardAccessibilityDelegate<KV : KeyboardView?>(protected val mKeyb
Log.d(TAG, "onHoverEnterTo: key=$key")
}
key.onPressed()
mKeyboardView!!.invalidateKey(key)
mKeyboardView.invalidateKey(key)
val provider = accessibilityNodeProvider
provider.onHoverEnterTo(key)
provider.performActionForKey(key, AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS)
@ -245,7 +249,7 @@ open class KeyboardAccessibilityDelegate<KV : KeyboardView?>(protected val mKeyb
Log.d(TAG, "onHoverExitFrom: key=$key")
}
key.onReleased()
mKeyboardView!!.invalidateKey(key)
mKeyboardView.invalidateKey(key)
val provider = accessibilityNodeProvider
provider.onHoverExitFrom(key)
}
@ -255,17 +259,18 @@ open class KeyboardAccessibilityDelegate<KV : KeyboardView?>(protected val mKeyb
*
* @param key A key to be long pressed on.
*/
open fun performLongClickOn(key: Key) { // A extended class should override this method to implement long press.
open fun performLongClickOn(key: Key) {
// A extended class should override this method to implement long press.
}
companion object {
private val TAG = KeyboardAccessibilityDelegate::class.java.simpleName
const val DEBUG_HOVER = false
const val HOVER_EVENT_POINTER_ID = 0
private val TAG = KeyboardAccessibilityDelegate::class.java.simpleName
const val DEBUG_HOVER = false
const val HOVER_EVENT_POINTER_ID = 0
}
init {
// Ensure that the view has an accessibility delegate.
ViewCompat.setAccessibilityDelegate(mKeyboardView!!, this)
ViewCompat.setAccessibilityDelegate(mKeyboardView, this) // todo: see the warning, this may be bad
}
}

View file

@ -1,7 +1,6 @@
package org.dslul.openboard.inputmethod.accessibility
import android.graphics.Rect
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.View
@ -28,10 +27,14 @@ import org.dslul.openboard.inputmethod.latin.settings.Settings
* virtual views, thus conveying their logical structure.
*
*/
class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
delegate: KeyboardAccessibilityDelegate<KV>) : AccessibilityNodeProviderCompat() {
private val mKeyCodeDescriptionMapper: KeyCodeDescriptionMapper
private val mAccessibilityUtils: AccessibilityUtils
class KeyboardAccessibilityNodeProvider<KV : KeyboardView>(
/** The keyboard view to provide an accessibility node info. */
private val mKeyboardView: KV,
/** The accessibility delegate. */
private val mDelegate: KeyboardAccessibilityDelegate<KV>
) : AccessibilityNodeProviderCompat() {
private val mKeyCodeDescriptionMapper: KeyCodeDescriptionMapper = KeyCodeDescriptionMapper.instance
private val mAccessibilityUtils: AccessibilityUtils = AccessibilityUtils.instance
/** Temporary rect used to calculate in-screen bounds. */
private val mTempBoundsInScreen = Rect()
/** The parent view's cached on-screen location. */
@ -40,12 +43,8 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
private var mAccessibilityFocusedView = UNDEFINED
/** The virtual view identifier for the hovering node. */
private var mHoveringNodeId = UNDEFINED
/** The keyboard view to provide an accessibility node info. */
private val mKeyboardView: KV
/** The accessibility delegate. */
private val mDelegate: KeyboardAccessibilityDelegate<KV>
/** The current keyboard. */
private var mKeyboard: Keyboard? = null
private var mKeyboard: Keyboard? = mKeyboardView.keyboard
/**
* Sets the keyboard represented by this node provider.
@ -57,10 +56,8 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
}
private fun getKeyOf(virtualViewId: Int): Key? {
if (mKeyboard == null) {
return null
}
val sortedKeys = mKeyboard!!.sortedKeys
val keyboard = mKeyboard ?: return null
val sortedKeys = keyboard.sortedKeys
// Use a virtual view id as an index of the sorted keys list.
return if (virtualViewId >= 0 && virtualViewId < sortedKeys.size) {
sortedKeys[virtualViewId]
@ -68,10 +65,8 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
}
private fun getVirtualViewIdOf(key: Key): Int {
if (mKeyboard == null) {
return View.NO_ID
}
val sortedKeys = mKeyboard!!.sortedKeys
val keyboard = mKeyboard ?: return View.NO_ID
val sortedKeys = keyboard.sortedKeys
val size = sortedKeys.size
for (index in 0 until size) {
if (sortedKeys[index] === key) { // Use an index of the sorted keys list as a virtual view id.
@ -94,7 +89,7 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
val virtualViewId = getVirtualViewIdOf(key)
val keyDescription = getKeyDescription(key)
val event = AccessibilityUtils.obtainEvent(eventType)
event.packageName = mKeyboardView!!.context.packageName
event.packageName = mKeyboardView.context.packageName
event.className = key.javaClass.name
event.contentDescription = keyDescription
event.isEnabled = true
@ -109,8 +104,8 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
return
}
// Start hovering on the key. Because our accessibility model is lift-to-type, we should
// report the node info without click and long click actions to avoid unnecessary
// announcements.
// report the node info without click and long click actions to avoid unnecessary
// announcements.
mHoveringNodeId = id
// Invalidate the node info of the key.
sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)
@ -120,7 +115,7 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
fun onHoverExitFrom(key: Key) {
mHoveringNodeId = UNDEFINED
// Invalidate the node info of the key to be able to revert the change we have done
// in {@link #onHoverEnterTo(Key)}.
// in {@link #onHoverEnterTo(Key)}.
sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)
sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_VIEW_HOVER_EXIT)
}
@ -152,13 +147,15 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
if (virtualViewId == UNDEFINED) {
return null
}
if (virtualViewId == View.NO_ID) { // We are requested to create an AccessibilityNodeInfo describing
// this View, i.e. the root of the virtual sub-tree.
val keyboard = mKeyboard ?: return null
if (virtualViewId == View.NO_ID) {
// We are requested to create an AccessibilityNodeInfo describing
// this View, i.e. the root of the virtual sub-tree.
val rootInfo = AccessibilityNodeInfoCompat.obtain(mKeyboardView)
ViewCompat.onInitializeAccessibilityNodeInfo(mKeyboardView!!, rootInfo)
ViewCompat.onInitializeAccessibilityNodeInfo(mKeyboardView, rootInfo)
updateParentLocation()
// Add the virtual children of the root View.
val sortedKeys = mKeyboard!!.sortedKeys
val sortedKeys = keyboard.sortedKeys
val size = sortedKeys.size
for (index in 0 until size) {
val key = sortedKeys[index]
@ -180,12 +177,11 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
val boundsInParent = key.hitBox
// Calculate the key's in-screen bounds.
mTempBoundsInScreen.set(boundsInParent)
mTempBoundsInScreen.offset(
CoordinateUtils.x(mParentLocation), CoordinateUtils.y(mParentLocation))
mTempBoundsInScreen.offset(CoordinateUtils.x(mParentLocation), CoordinateUtils.y(mParentLocation))
val boundsInScreen = mTempBoundsInScreen
// Obtain and initialize an AccessibilityNodeInfo with information about the virtual view.
val info = AccessibilityNodeInfoCompat.obtain()
info.packageName = mKeyboardView!!.context.packageName
info.packageName = mKeyboardView.context.packageName
info.className = key.javaClass.name
info.contentDescription = keyDescription
info.setBoundsInParent(boundsInParent)
@ -195,7 +191,7 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
info.isEnabled = key.isEnabled
info.isVisibleToUser = true
// Don't add ACTION_CLICK and ACTION_LONG_CLOCK actions while hovering on the key.
// See {@link #onHoverEnterTo(Key)} and {@link #onHoverExitFrom(Key)}.
// See {@link #onHoverEnterTo(Key)} and {@link #onHoverExitFrom(Key)}.
if (virtualViewId != mHoveringNodeId) {
info.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK)
if (key.isLongPressEnabled) {
@ -227,14 +223,12 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
return when (action) {
AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS -> {
mAccessibilityFocusedView = getVirtualViewIdOf(key)
sendAccessibilityEventForKey(
key, AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUSED)
sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUSED)
true
}
AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS -> {
mAccessibilityFocusedView = UNDEFINED
sendAccessibilityEventForKey(
key, AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED)
sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED)
true
}
AccessibilityNodeInfoCompat.ACTION_CLICK -> {
@ -269,14 +263,13 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
* @return The context-specific description of the key.
*/
private fun getKeyDescription(key: Key): String? {
val editorInfo = mKeyboard!!.mId.mEditorInfo
val editorInfo = mKeyboard?.mId?.mEditorInfo
val shouldObscure = mAccessibilityUtils.shouldObscureInput(editorInfo)
val currentSettings = Settings.getInstance().current
val keyCodeDescription = mKeyCodeDescriptionMapper.getDescriptionForKey(
mKeyboardView!!.context, mKeyboard, key, shouldObscure)
mKeyboardView.context, mKeyboard, key, shouldObscure)
return if (currentSettings.isWordSeparator(key.code)) {
mAccessibilityUtils.getAutoCorrectionDescription(
keyCodeDescription, shouldObscure)
mAccessibilityUtils.getAutoCorrectionDescription(keyCodeDescription, shouldObscure)
} else keyCodeDescription
}
@ -284,7 +277,7 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
* Updates the parent's on-screen location.
*/
private fun updateParentLocation() {
mKeyboardView!!.getLocationOnScreen(mParentLocation)
mKeyboardView.getLocationOnScreen(mParentLocation)
}
companion object {
@ -293,13 +286,4 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
private const val UNDEFINED = Int.MAX_VALUE
}
init {
mKeyCodeDescriptionMapper = KeyCodeDescriptionMapper.instance
mAccessibilityUtils = AccessibilityUtils.instance
mKeyboardView = keyboardView
mDelegate = delegate
// Since this class is constructed lazily, we might not get a subsequent
// call to setKeyboard() and therefore need to call it now.
setKeyboard(keyboardView!!.keyboard)
}
}

View file

@ -14,33 +14,18 @@ import org.dslul.openboard.inputmethod.latin.utils.SubtypeLocaleUtils
* This class represents a delegate that can be registered in [MainKeyboardView] to enhance
* accessibility support via composition rather via inheritance.
*/
class MainKeyboardAccessibilityDelegate(mainKeyboardView: MainKeyboardView,
keyDetector: KeyDetector) : KeyboardAccessibilityDelegate<MainKeyboardView?>(mainKeyboardView, keyDetector), LongPressTimerCallback {
companion object {
private val TAG = MainKeyboardAccessibilityDelegate::class.java.simpleName
/** Map of keyboard modes to resource IDs. */
private val KEYBOARD_MODE_RES_IDS = SparseIntArray()
private const val KEYBOARD_IS_HIDDEN = -1
init {
KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_DATE, R.string.keyboard_mode_date)
KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_DATETIME, R.string.keyboard_mode_date_time)
KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_EMAIL, R.string.keyboard_mode_email)
KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_IM, R.string.keyboard_mode_im)
KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_NUMBER, R.string.keyboard_mode_number)
KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_PHONE, R.string.keyboard_mode_phone)
KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_TEXT, R.string.keyboard_mode_text)
KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_TIME, R.string.keyboard_mode_time)
KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_URL, R.string.keyboard_mode_url)
}
}
class MainKeyboardAccessibilityDelegate(
mainKeyboardView: MainKeyboardView,
keyDetector: KeyDetector
) : KeyboardAccessibilityDelegate<MainKeyboardView>(mainKeyboardView, keyDetector), LongPressTimerCallback {
/** The most recently set keyboard mode. */
private var mLastKeyboardMode = KEYBOARD_IS_HIDDEN
// The rectangle region to ignore hover events.
private val mBoundsToIgnoreHoverEvent = Rect()
private val mAccessibilityLongPressTimer: AccessibilityLongPressTimer// Since this method is called even when accessibility is off, make sure
// to check the state before announcing anything.
private val mAccessibilityLongPressTimer = AccessibilityLongPressTimer(this /* callback */, mainKeyboardView.context)
// Since this method is called even when accessibility is off, make sure
// to check the state before announcing anything.
// Announce the language name only when the language is changed.
// Announce the mode only when the mode is changed.
// Announce the keyboard type only when the type is changed.
@ -58,7 +43,7 @@ class MainKeyboardAccessibilityDelegate(mainKeyboardView: MainKeyboardView,
val lastKeyboardMode = mLastKeyboardMode
mLastKeyboardMode = keyboard.mId.mMode
// Since this method is called even when accessibility is off, make sure
// to check the state before announcing anything.
// to check the state before announcing anything.
if (!AccessibilityUtils.instance.isAccessibilityEnabled) {
return
}
@ -107,7 +92,7 @@ class MainKeyboardAccessibilityDelegate(mainKeyboardView: MainKeyboardView,
* @param keyboard The new keyboard.
*/
private fun announceKeyboardMode(keyboard: Keyboard) {
val context = mKeyboardView!!.context
val context = mKeyboardView.context
val modeTextResId = KEYBOARD_MODE_RES_IDS[keyboard.mId.mMode]
if (modeTextResId == 0) {
return
@ -129,22 +114,25 @@ class MainKeyboardAccessibilityDelegate(mainKeyboardView: MainKeyboardView,
resId = when (keyboard.mId.mElementId) {
KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED, KeyboardId.ELEMENT_ALPHABET -> {
if (lastElementId == KeyboardId.ELEMENT_ALPHABET
|| lastElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) { // Transition between alphabet mode and automatic shifted mode should be silently
// ignored because it can be determined by each key's talk back announce.
|| lastElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) {
// Transition between alphabet mode and automatic shifted mode should be silently
// ignored because it can be determined by each key's talk back announce.
return
}
R.string.spoken_description_mode_alpha
}
KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED -> {
if (lastElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) { // Resetting automatic shifted mode by pressing the shift key causes the transition
// from automatic shifted to manual shifted that should be silently ignored.
if (lastElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) {
// Resetting automatic shifted mode by pressing the shift key causes the transition
// from automatic shifted to manual shifted that should be silently ignored.
return
}
R.string.spoken_description_shiftmode_on
}
KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED -> {
if (lastElementId == KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED) { // Resetting caps locked mode by pressing the shift key causes the transition
// from shift locked to shift lock shifted that should be silently ignored.
if (lastElementId == KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED) {
// Resetting caps locked mode by pressing the shift key causes the transition
// from shift locked to shift lock shifted that should be silently ignored.
return
}
R.string.spoken_description_shiftmode_locked
@ -169,12 +157,13 @@ class MainKeyboardAccessibilityDelegate(mainKeyboardView: MainKeyboardView,
override fun performClickOn(key: Key) {
val x = key.hitBox.centerX()
val y = key.hitBox.centerY()
if (KeyboardAccessibilityDelegate.DEBUG_HOVER) {
if (DEBUG_HOVER) {
Log.d(TAG, "performClickOn: key=" + key
+ " inIgnoreBounds=" + mBoundsToIgnoreHoverEvent.contains(x, y))
}
if (mBoundsToIgnoreHoverEvent.contains(x, y)) { // This hover exit event points to the key that should be ignored.
// Clear the ignoring region to handle further hover events.
if (mBoundsToIgnoreHoverEvent.contains(x, y)) {
// This hover exit event points to the key that should be ignored.
// Clear the ignoring region to handle further hover events.
mBoundsToIgnoreHoverEvent.setEmpty()
return
}
@ -184,7 +173,7 @@ class MainKeyboardAccessibilityDelegate(mainKeyboardView: MainKeyboardView,
override fun onHoverEnterTo(key: Key) {
val x = key.hitBox.centerX()
val y = key.hitBox.centerY()
if (KeyboardAccessibilityDelegate.DEBUG_HOVER) {
if (DEBUG_HOVER) {
Log.d(TAG, "onHoverEnterTo: key=" + key
+ " inIgnoreBounds=" + mBoundsToIgnoreHoverEvent.contains(x, y))
}
@ -193,7 +182,7 @@ class MainKeyboardAccessibilityDelegate(mainKeyboardView: MainKeyboardView,
return
}
// This hover enter event points to the key that isn't in the ignoring region.
// Further hover events should be handled.
// Further hover events should be handled.
mBoundsToIgnoreHoverEvent.setEmpty()
super.onHoverEnterTo(key)
if (key.isLongPressEnabled) {
@ -204,7 +193,7 @@ class MainKeyboardAccessibilityDelegate(mainKeyboardView: MainKeyboardView,
override fun onHoverExitFrom(key: Key) {
val x = key.hitBox.centerX()
val y = key.hitBox.centerY()
if (KeyboardAccessibilityDelegate.DEBUG_HOVER) {
if (DEBUG_HOVER) {
Log.d(TAG, "onHoverExitFrom: key=" + key
+ " inIgnoreBounds=" + mBoundsToIgnoreHoverEvent.contains(x, y))
}
@ -213,43 +202,56 @@ class MainKeyboardAccessibilityDelegate(mainKeyboardView: MainKeyboardView,
}
override fun performLongClickOn(key: Key) {
if (KeyboardAccessibilityDelegate.Companion.DEBUG_HOVER) {
if (DEBUG_HOVER) {
Log.d(TAG, "performLongClickOn: key=$key")
}
val tracker = PointerTracker.getPointerTracker(KeyboardAccessibilityDelegate.Companion.HOVER_EVENT_POINTER_ID)
val tracker = PointerTracker.getPointerTracker(HOVER_EVENT_POINTER_ID)
val eventTime = SystemClock.uptimeMillis()
val x = key.hitBox.centerX()
val y = key.hitBox.centerY()
val downEvent = MotionEvent.obtain(
eventTime, eventTime, MotionEvent.ACTION_DOWN, x.toFloat(), y.toFloat(), 0 /* metaState */)
val downEvent = MotionEvent.obtain(eventTime, eventTime, MotionEvent.ACTION_DOWN, x.toFloat(), y.toFloat(), 0)
// Inject a fake down event to {@link PointerTracker} to handle a long press correctly.
tracker.processMotionEvent(downEvent, mKeyDetector)
downEvent.recycle()
// Invoke {@link PointerTracker#onLongPressed()} as if a long press timeout has passed.
tracker.onLongPressed()
// If {@link Key#hasNoPanelAutoMoreKeys()} is true (such as "0 +" key on the phone layout)
// or a key invokes IME switcher dialog, we should just ignore the next
// {@link #onRegisterHoverKey(Key,MotionEvent)}. It can be determined by whether
// {@link PointerTracker} is in operation or not.
if (tracker.isInOperation) { // This long press shows a more keys keyboard and further hover events should be
// handled.
// or a key invokes IME switcher dialog, we should just ignore the next
// {@link #onRegisterHoverKey(Key,MotionEvent)}. It can be determined by whether
// {@link PointerTracker} is in operation or not.
if (tracker.isInOperation) {
// This long press shows a more keys keyboard and further hover events should be
// handled.
mBoundsToIgnoreHoverEvent.setEmpty()
return
}
// This long press has handled at {@link MainKeyboardView#onLongPress(PointerTracker)}.
// We should ignore further hover events on this key.
// We should ignore further hover events on this key.
mBoundsToIgnoreHoverEvent.set(key.hitBox)
if (key.hasNoPanelAutoMoreKey()) { // This long press has registered a code point without showing a more keys keyboard.
// We should talk back the code point if possible.
val codePointOfNoPanelAutoMoreKey = key.moreKeys!![0].mCode
if (key.hasNoPanelAutoMoreKey()) {
// This long press has registered a code point without showing a more keys keyboard.
// We should talk back the code point if possible.
val codePointOfNoPanelAutoMoreKey = key.moreKeys?.get(0)?.mCode ?: return
val text: String = KeyCodeDescriptionMapper.instance.getDescriptionForCodePoint(
mKeyboardView!!.context, codePointOfNoPanelAutoMoreKey)!!
text.let { sendWindowStateChanged(it) }
mKeyboardView.context, codePointOfNoPanelAutoMoreKey) ?: return
sendWindowStateChanged(text)
}
}
init {
mAccessibilityLongPressTimer = AccessibilityLongPressTimer(
this /* callback */, mainKeyboardView.context)
companion object {
private val TAG = MainKeyboardAccessibilityDelegate::class.java.simpleName
/** Map of keyboard modes to resource IDs. */
private val KEYBOARD_MODE_RES_IDS = SparseIntArray().apply {
put(KeyboardId.MODE_DATE, R.string.keyboard_mode_date)
put(KeyboardId.MODE_DATETIME, R.string.keyboard_mode_date_time)
put(KeyboardId.MODE_EMAIL, R.string.keyboard_mode_email)
put(KeyboardId.MODE_IM, R.string.keyboard_mode_im)
put(KeyboardId.MODE_NUMBER, R.string.keyboard_mode_number)
put(KeyboardId.MODE_PHONE, R.string.keyboard_mode_phone)
put(KeyboardId.MODE_TEXT, R.string.keyboard_mode_text)
put(KeyboardId.MODE_TIME, R.string.keyboard_mode_time)
put(KeyboardId.MODE_URL, R.string.keyboard_mode_url)
}
private const val KEYBOARD_IS_HIDDEN = -1
}
}

View file

@ -11,8 +11,10 @@ import org.dslul.openboard.inputmethod.keyboard.PointerTracker
* This class represents a delegate that can be registered in [MoreKeysKeyboardView] to
* enhance accessibility support via composition rather via inheritance.
*/
class MoreKeysKeyboardAccessibilityDelegate(moreKeysKeyboardView: MoreKeysKeyboardView,
keyDetector: KeyDetector) : KeyboardAccessibilityDelegate<MoreKeysKeyboardView?>(moreKeysKeyboardView, keyDetector) {
class MoreKeysKeyboardAccessibilityDelegate(
moreKeysKeyboardView: MoreKeysKeyboardView,
keyDetector: KeyDetector
) : KeyboardAccessibilityDelegate<MoreKeysKeyboardView>(moreKeysKeyboardView, keyDetector) {
private val mMoreKeysKeyboardValidBounds = Rect()
private var mOpenAnnounceResId = 0
private var mCloseAnnounceResId = 0
@ -42,7 +44,7 @@ class MoreKeysKeyboardAccessibilityDelegate(moreKeysKeyboardView: MoreKeysKeyboa
val y = event.getY(actionIndex).toInt()
val pointerId = event.getPointerId(actionIndex)
val eventTime = event.eventTime
mKeyboardView!!.onDownEvent(x, y, pointerId, eventTime)
mKeyboardView.onDownEvent(x, y, pointerId, eventTime)
}
override fun onHoverMove(event: MotionEvent) {
@ -52,7 +54,7 @@ class MoreKeysKeyboardAccessibilityDelegate(moreKeysKeyboardView: MoreKeysKeyboa
val y = event.getY(actionIndex).toInt()
val pointerId = event.getPointerId(actionIndex)
val eventTime = event.eventTime
mKeyboardView!!.onMoveEvent(x, y, pointerId, eventTime)
mKeyboardView.onMoveEvent(x, y, pointerId, eventTime)
}
override fun onHoverExit(event: MotionEvent) {
@ -70,20 +72,21 @@ class MoreKeysKeyboardAccessibilityDelegate(moreKeysKeyboardView: MoreKeysKeyboa
val pointerId = event.getPointerId(actionIndex)
val eventTime = event.eventTime
// A hover exit event at one pixel width or height area on the edges of more keys keyboard
// are treated as closing.
mMoreKeysKeyboardValidBounds[0, 0, mKeyboardView!!.width] = mKeyboardView.height
// are treated as closing.
mMoreKeysKeyboardValidBounds[0, 0, mKeyboardView.width] = mKeyboardView.height
mMoreKeysKeyboardValidBounds.inset(CLOSING_INSET_IN_PIXEL, CLOSING_INSET_IN_PIXEL)
if (mMoreKeysKeyboardValidBounds.contains(x, y)) { // Invoke {@link MoreKeysKeyboardView#onUpEvent(int,int,int,long)} as if this hover
// exit event selects a key.
if (mMoreKeysKeyboardValidBounds.contains(x, y)) {
// Invoke {@link MoreKeysKeyboardView#onUpEvent(int,int,int,long)} as if this hover
// exit event selects a key.
mKeyboardView.onUpEvent(x, y, pointerId, eventTime)
// TODO: Should fix this reference. This is a hack to clear the state of
// {@link PointerTracker}.
// {@link PointerTracker}.
PointerTracker.dismissAllMoreKeysPanels()
return
}
// Close the more keys keyboard.
// TODO: Should fix this reference. This is a hack to clear the state of
// {@link PointerTracker}.
// TODO: Should fix this reference. This is a hack to clear the state of
// {@link PointerTracker}.
PointerTracker.dismissAllMoreKeysPanels()
}
@ -91,4 +94,4 @@ class MoreKeysKeyboardAccessibilityDelegate(moreKeysKeyboardView: MoreKeysKeyboa
private val TAG = MoreKeysKeyboardAccessibilityDelegate::class.java.simpleName
private const val CLOSING_INSET_IN_PIXEL = 1
}
}
}

View file

@ -147,7 +147,7 @@ open class CursorAnchorInfoCompatWrapper internal constructor() {
*/
const val FLAG_IS_RTL = 0x04
@kotlin.jvm.JvmStatic
@JvmStatic
@TargetApi(VERSION_CODES.LOLLIPOP)
fun wrap(instance: CursorAnchorInfo?): CursorAnchorInfoCompatWrapper? {
return if (Build.VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {

View file

@ -6,12 +6,9 @@ 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")
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, null, FIELD_IME_FLAG_FORCE_ASCII) as? Int
private val FIELD_HINT_LOCALES = CompatUtils.getField(EditorInfo::class.java, "hintLocales")
@JvmStatic
fun hasFlagForceAscii(imeOptions: Int): Boolean {
@ -20,8 +17,7 @@ object EditorInfoCompatUtils {
@JvmStatic
fun imeActionName(imeOptions: Int): String {
val actionId = imeOptions and EditorInfo.IME_MASK_ACTION
return when (actionId) {
return when (val actionId = imeOptions and EditorInfo.IME_MASK_ACTION) {
EditorInfo.IME_ACTION_UNSPECIFIED -> "actionUnspecified"
EditorInfo.IME_ACTION_NONE -> "actionNone"
EditorInfo.IME_ACTION_GO -> "actionGo"
@ -57,8 +53,7 @@ object EditorInfoCompatUtils {
if (editorInfo == null) {
return null
}
val localeList = CompatUtils.getFieldValue(editorInfo, null, FIELD_HINT_LOCALES)
?: return null
val localeList = CompatUtils.getFieldValue(editorInfo, null, FIELD_HINT_LOCALES) ?: return null
return if (LocaleListCompatUtils.isEmpty(localeList)) {
null
} else LocaleListCompatUtils[localeList, 0]

View file

@ -8,8 +8,7 @@ import java.security.NoSuchAlgorithmException
object MD5Calculator {
@Throws(IOException::class)
fun checksum(`in`: InputStream): String? { // This code from the Android documentation for MessageDigest. Nearly verbatim.
val digester: MessageDigest
digester = try {
val digester: MessageDigest = try {
MessageDigest.getInstance("MD5")
} catch (e: NoSuchAlgorithmException) {
return null // Platform does not support MD5 : can't check, so return null
@ -26,4 +25,4 @@ object MD5Calculator {
}
return s.toString()
}
}
}

View file

@ -88,10 +88,10 @@ class InputTransaction(// Initial conditions
companion object {
// UPDATE_LATER is stronger than UPDATE_NOW. The reason for this is, if we have to update later,
// it's because something will change that we can't evaluate now, which means that even if we
// re-evaluate now we'll have to do it again later. The only case where that wouldn't apply
// would be if we needed to update now to find out the new state right away, but then we
// can't do it with this deferred mechanism anyway.
// it's because something will change that we can't evaluate now, which means that even if we
// re-evaluate now we'll have to do it again later. The only case where that wouldn't apply
// would be if we needed to update now to find out the new state right away, but then we
// can't do it with this deferred mechanism anyway.
const val SHIFT_NO_UPDATE = 0
const val SHIFT_UPDATE_NOW = 1
const val SHIFT_UPDATE_LATER = 2

View file

@ -173,14 +173,6 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
keyboardView.setKeyboard(newKeyboard);
mCurrentInputView.setKeyboardTopPadding(newKeyboard.mTopPadding);
keyboardView.setKeyPreviewPopupEnabled(currentSettingsValues.mKeyPreviewPopupOn);
keyboardView.setKeyPreviewAnimationParams(
currentSettingsValues.mHasCustomKeyPreviewAnimationParams,
currentSettingsValues.mKeyPreviewShowUpStartXScale,
currentSettingsValues.mKeyPreviewShowUpStartYScale,
currentSettingsValues.mKeyPreviewShowUpDuration,
currentSettingsValues.mKeyPreviewDismissEndXScale,
currentSettingsValues.mKeyPreviewDismissEndYScale,
currentSettingsValues.mKeyPreviewDismissDuration);
keyboardView.updateShortcutKey(mRichImm.isShortcutImeReady());
final boolean subtypeChanged = (oldKeyboard == null)
|| !newKeyboard.mId.mSubtype.equals(oldKeyboard.mId.mSubtype);

View file

@ -304,7 +304,7 @@ public class KeyboardView extends View {
mShowsHints = Settings.getInstance().getCurrent().mShowsHints;
final float scale = Settings.getInstance().getCurrent().mKeyboardHeightScale;
mIconScaleFactor = scale < 0.8f ? scale + 0.2f : scale;
mIconScaleFactor = scale < 0.8f ? scale + 0.2f : 1f;
final Paint paint = mPaint;
final Drawable background = getBackground();
// Calculate clip region and set.

View file

@ -92,9 +92,6 @@ import java.util.WeakHashMap;
* @attr ref R.styleable#MainKeyboardView_keyPreviewLayout
* @attr ref R.styleable#MainKeyboardView_keyPreviewOffset
* @attr ref R.styleable#MainKeyboardView_keyPreviewHeight
* @attr ref R.styleable#MainKeyboardView_keyPreviewLingerTimeout
* @attr ref R.styleable#MainKeyboardView_keyPreviewShowUpAnimator
* @attr ref R.styleable#MainKeyboardView_keyPreviewDismissAnimator
* @attr ref R.styleable#MainKeyboardView_moreKeysKeyboardLayout
* @attr ref R.styleable#MainKeyboardView_moreKeysKeyboardForActionLayout
* @attr ref R.styleable#MainKeyboardView_backgroundDimAlpha
@ -422,27 +419,6 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
mKeyPreviewDrawParams.setPopupEnabled(previewEnabled);
}
/**
* Enables or disables the key preview popup animations and set animations' parameters.
*
* @param hasCustomAnimationParams false to use the default key preview popup animations
* specified by keyPreviewShowUpAnimator and keyPreviewDismissAnimator attributes.
* true to override the default animations with the specified parameters.
* @param showUpStartXScale from this x-scale the show up animation will start.
* @param showUpStartYScale from this y-scale the show up animation will start.
* @param showUpDuration the duration of the show up animation in milliseconds.
* @param dismissEndXScale to this x-scale the dismiss animation will end.
* @param dismissEndYScale to this y-scale the dismiss animation will end.
* @param dismissDuration the duration of the dismiss animation in milliseconds.
*/
public void setKeyPreviewAnimationParams(final boolean hasCustomAnimationParams,
final float showUpStartXScale, final float showUpStartYScale, final int showUpDuration,
final float dismissEndXScale, final float dismissEndYScale, final int dismissDuration) {
mKeyPreviewDrawParams.setAnimationParams(hasCustomAnimationParams,
showUpStartXScale, showUpStartYScale, showUpDuration,
dismissEndXScale, dismissEndYScale, dismissDuration);
}
private void locatePreviewPlacerView() {
getLocationInWindow(mOriginCoords);
mDrawingPreviewPlacerView.setKeyboardViewGeometry(mOriginCoords, getWidth(), getHeight());

View file

@ -95,6 +95,7 @@ class ClipboardHistoryView @JvmOverloads constructor(
setOnTouchListener(this@ClipboardHistoryView)
setOnClickListener(this@ClipboardHistoryView)
colorFilter = colors.keyTextFilter
colors.setBackgroundColor(background, BackgroundType.SUGGESTION)
}
}

View file

@ -18,6 +18,8 @@ package org.dslul.openboard.inputmethod.keyboard.internal;
import android.util.Log;
import androidx.annotation.NonNull;
public final class AlphabetShiftState {
private static final String TAG = AlphabetShiftState.class.getSimpleName();
private static final boolean DEBUG = false;
@ -112,6 +114,7 @@ public final class AlphabetShiftState {
return mState == MANUAL_SHIFTED_FROM_AUTO;
}
@NonNull
@Override
public String toString() {
return toString(mState);

View file

@ -46,7 +46,7 @@ public final class DrawingPreviewPlacerView extends RelativeLayout {
}
public void addPreview(final AbstractDrawingPreview preview) {
if (mPreviews.indexOf(preview) < 0) {
if (!mPreviews.contains(preview)) {
mPreviews.add(preview);
}
}

View file

@ -126,7 +126,7 @@ public class GestureFloatingTextDrawingPreview extends AbstractDrawingPreview {
}
@Override
public void setPreviewPosition(final PointerTracker tracker) {
public void setPreviewPosition(@NonNull final PointerTracker tracker) {
if (!isPreviewEnabled()) {
return;
}
@ -139,7 +139,7 @@ public class GestureFloatingTextDrawingPreview extends AbstractDrawingPreview {
* @param canvas The canvas where preview text is drawn.
*/
@Override
public void drawPreview(final Canvas canvas) {
public void drawPreview(@NonNull final Canvas canvas) {
if (!isPreviewEnabled() || mSuggestedWords.isEmpty()
|| TextUtils.isEmpty(mSuggestedWords.getWord(0))) {
return;
@ -161,8 +161,6 @@ public class GestureFloatingTextDrawingPreview extends AbstractDrawingPreview {
}
final String text = mSuggestedWords.getWord(0);
final RectF rectangle = mGesturePreviewRectangle;
final int textHeight = mParams.mGesturePreviewTextHeight;
final float textWidth = mParams.getTextPaint().measureText(text);
final float hPad = mParams.mGesturePreviewHorizontalPadding;
@ -175,7 +173,7 @@ public class GestureFloatingTextDrawingPreview extends AbstractDrawingPreview {
mParams.mDisplayWidth - rectWidth);
final float rectY = CoordinateUtils.y(mLastPointerCoords)
- mParams.mGesturePreviewTextOffset - rectHeight;
rectangle.set(rectX, rectY, rectX + rectWidth, rectY + rectHeight);
mGesturePreviewRectangle.set(rectX, rectY, rectX + rectWidth, rectY + rectHeight);
mPreviewTextX = (int)(rectX + hPad + textWidth / 2.0f);
mPreviewTextY = (int)(rectY + vPad) + textHeight;

View file

@ -146,7 +146,7 @@ public final class GestureStrokeRecognitionPoints {
}
// TODO: Make this package private
public final boolean isStartOfAGesture() {
public boolean isStartOfAGesture() {
if (!hasDetectedFastMove()) {
return false;
}
@ -225,7 +225,7 @@ public final class GestureStrokeRecognitionPoints {
mLastMajorEventY = y;
}
private final boolean hasDetectedFastMove() {
private boolean hasDetectedFastMove() {
return mDetectFastMoveTime > 0;
}
@ -303,18 +303,18 @@ public final class GestureStrokeRecognitionPoints {
}
// TODO: Make this package private
public final boolean hasRecognitionTimePast(
public boolean hasRecognitionTimePast(
final long currentTime, final long lastRecognitionTime) {
return currentTime > lastRecognitionTime + mRecognitionParams.mRecognitionMinimumTime;
}
// TODO: Make this package private
public final void appendAllBatchPoints(final InputPointers out) {
public void appendAllBatchPoints(final InputPointers out) {
appendBatchPoints(out, getLength());
}
// TODO: Make this package private
public final void appendIncrementalBatchPoints(final InputPointers out) {
public void appendIncrementalBatchPoints(final InputPointers out) {
appendBatchPoints(out, mIncrementalRecognitionSize);
}

View file

@ -19,7 +19,6 @@ package org.dslul.openboard.inputmethod.keyboard.internal;
import android.content.res.TypedArray;
import org.dslul.openboard.inputmethod.latin.R;
import org.dslul.openboard.inputmethod.latin.common.Colors;
import org.dslul.openboard.inputmethod.latin.settings.Settings;
/**

View file

@ -102,9 +102,8 @@ final class GestureTrailDrawingPoints {
eventTimes[i] -= elapsedTime;
}
final int[] xCoords = mXCoordinates.getPrimitiveArray();
final int downIndex = trailSize;
xCoords[downIndex] = markAsDownEvent(xCoords[downIndex]);
mCurrentTimeBase = downTime - eventTimes[downIndex];
xCoords[trailSize] = markAsDownEvent(xCoords[trailSize]);
mCurrentTimeBase = downTime - eventTimes[trailSize];
mCurrentStrokeId = strokeId;
}
}

View file

@ -27,6 +27,8 @@ import android.graphics.Rect;
import android.os.Handler;
import android.util.SparseArray;
import androidx.annotation.NonNull;
import org.dslul.openboard.inputmethod.keyboard.PointerTracker;
/**
@ -56,7 +58,7 @@ public final class GestureTrailsDrawingPreview extends AbstractDrawingPreview im
}
@Override
public void setKeyboardViewGeometry(final int[] originCoords, final int width,
public void setKeyboardViewGeometry(@NonNull final int[] originCoords, final int width,
final int height) {
super.setKeyboardViewGeometry(originCoords, width, height);
mOffscreenOffsetY = (int)(height
@ -127,7 +129,7 @@ public final class GestureTrailsDrawingPreview extends AbstractDrawingPreview im
* @param canvas The canvas where the preview is drawn.
*/
@Override
public void drawPreview(final Canvas canvas) {
public void drawPreview(@NonNull final Canvas canvas) {
if (!isPreviewEnabled()) {
return;
}
@ -154,7 +156,7 @@ public final class GestureTrailsDrawingPreview extends AbstractDrawingPreview im
* @param tracker The new location of the preview is based on the points in PointerTracker.
*/
@Override
public void setPreviewPosition(final PointerTracker tracker) {
public void setPreviewPosition(@NonNull final PointerTracker tracker) {
if (!isPreviewEnabled()) {
return;
}

View file

@ -16,14 +16,8 @@
package org.dslul.openboard.inputmethod.keyboard.internal;
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.res.TypedArray;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import org.dslul.openboard.inputmethod.latin.R;
@ -105,10 +99,4 @@ public final class KeyPreviewDrawParams {
return mShowPopup;
}
public void setAnimationParams(final boolean hasCustomAnimationParams,
final float showUpStartXScale, final float showUpStartYScale, final int showUpDuration,
final float dismissEndXScale, final float dismissEndYScale, final int dismissDuration) {
//TODO: remove
}
}

View file

@ -105,7 +105,7 @@ public final class KeyboardIconsSet {
NAME_SWITCH_ONEHANDED_KEY, R.styleable.Keyboard_iconSwitchOneHandedMode,
};
private static int NUM_ICONS = NAMES_AND_ATTR_IDS.length / 2;
private static final int NUM_ICONS = NAMES_AND_ATTR_IDS.length / 2;
private static final String[] ICON_NAMES = new String[NUM_ICONS];
private final Drawable[] mIcons = new Drawable[NUM_ICONS];
private final int[] mIconResourceIds = new int[NUM_ICONS];

View file

@ -91,15 +91,12 @@ public class KeyboardParams {
new TouchPositionCorrection();
// Comparator to sort {@link Key}s from top-left to bottom-right order.
private static final Comparator<Key> ROW_COLUMN_COMPARATOR = new Comparator<Key>() {
@Override
public int compare(final Key lhs, final Key rhs) {
if (lhs.getY() < rhs.getY()) return -1;
if (lhs.getY() > rhs.getY()) return 1;
if (lhs.getX() < rhs.getX()) return -1;
if (lhs.getX() > rhs.getX()) return 1;
return 0;
}
private static final Comparator<Key> ROW_COLUMN_COMPARATOR = (lhs, rhs) -> {
if (lhs.getY() < rhs.getY()) return -1;
if (lhs.getY() > rhs.getY()) return 1;
if (lhs.getX() < rhs.getX()) return -1;
if (lhs.getX() > rhs.getX()) return 1;
return 0;
};
public KeyboardParams() {

View file

@ -19,6 +19,8 @@ package org.dslul.openboard.inputmethod.keyboard.internal;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import org.dslul.openboard.inputmethod.event.Event;
import org.dslul.openboard.inputmethod.latin.common.Constants;
import org.dslul.openboard.inputmethod.latin.settings.Settings;
@ -73,8 +75,9 @@ public final class KeyboardState {
private final SwitchActions mSwitchActions;
private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift");
private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol");
private final ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift");
private final ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol");
private final AlphabetShiftState mAlphabetShiftState = new AlphabetShiftState();
// TODO: Merge {@link #mSwitchState}, {@link #mIsAlphabetMode}, {@link #mAlphabetShiftState},
// {@link #mIsSymbolShifted}, {@link #mPrevMainKeyboardWasShiftLocked}, and
@ -93,7 +96,6 @@ public final class KeyboardState {
private static final int MODE_CLIPBOARD = 3;
private static final int MODE_NUMPAD = 4;
private int mMode = MODE_ALPHABET;
private AlphabetShiftState mAlphabetShiftState = new AlphabetShiftState();
private boolean mIsSymbolShifted;
private boolean mPrevMainKeyboardWasShiftLocked;
private boolean mPrevSymbolsKeyboardWasShifted;
@ -111,6 +113,7 @@ public final class KeyboardState {
public int mMode;
public int mShiftMode;
@NonNull
@Override
public String toString() {
if (!mIsValid) {

View file

@ -28,6 +28,7 @@ import org.dslul.openboard.inputmethod.latin.utils.RunInLocale;
import org.dslul.openboard.inputmethod.latin.utils.SubtypeLocaleUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Locale;

View file

@ -59,7 +59,7 @@ public final class KeyboardTextsTable {
return text;
}
// Validity check.
if (index >= 0 && index < TEXTS_DEFAULT.length) {
if (index < TEXTS_DEFAULT.length) {
return TEXTS_DEFAULT[index];
}
// Throw exception for debugging purpose.

View file

@ -21,6 +21,7 @@ import android.util.Log;
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
import java.util.Arrays;
import java.util.Locale;
/**
* Utilities for matrix operations. Don't instantiate objects inside this class to prevent
@ -154,10 +155,10 @@ public class MatrixUtils {
Log.d(TAG, "Dump matrix: " + title);
Log.d(TAG, "/*---------------------");
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < row; ++i) {
for (float[] floats : a) {
sb.setLength(0);
for (int j = 0; j < column; ++j) {
sb.append(String.format("%4f", a[i][j])).append(' ');
sb.append(String.format(Locale.ROOT, "%4f", floats[j])).append(' ');
}
Log.d(TAG, sb.toString());
}

View file

@ -18,6 +18,8 @@ package org.dslul.openboard.inputmethod.keyboard.internal;
import android.util.Log;
import androidx.annotation.NonNull;
/* package */ class ModifierKeyState {
protected static final String TAG = ModifierKeyState.class.getSimpleName();
protected static final boolean DEBUG = false;
@ -67,6 +69,7 @@ import android.util.Log;
return mState == CHORDING;
}
@NonNull
@Override
public String toString() {
return toString(mState);

View file

@ -30,7 +30,7 @@ public final class NonDistinctMultitouchHelper {
private static final int MAIN_POINTER_TRACKER_ID = 0;
private int mOldPointerCount = 1;
private Key mOldKey;
private int[] mLastCoords = CoordinateUtils.newInstance();
private final int[] mLastCoords = CoordinateUtils.newInstance();
public void processMotionEvent(final MotionEvent me, final KeyDetector keyDetector) {
final int pointerCount = me.getPointerCount();

View file

@ -18,6 +18,8 @@ package org.dslul.openboard.inputmethod.keyboard.internal;
import android.util.Log;
import androidx.annotation.NonNull;
import java.util.ArrayList;
public final class PointerTrackerQueue {
@ -176,10 +178,9 @@ public final class PointerTrackerQueue {
public boolean hasModifierKeyOlderThan(final Element pointer) {
synchronized (mExpandableArrayOfActivePointers) {
final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
final int arraySize = mArraySize;
for (int index = 0; index < arraySize; index++) {
final Element element = expandableArray.get(index);
final Element element = mExpandableArrayOfActivePointers.get(index);
if (element == pointer) {
return false; // Stop searching modifier key.
}
@ -193,10 +194,9 @@ public final class PointerTrackerQueue {
public boolean isAnyInDraggingFinger() {
synchronized (mExpandableArrayOfActivePointers) {
final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
final int arraySize = mArraySize;
for (int index = 0; index < arraySize; index++) {
final Element element = expandableArray.get(index);
final Element element = mExpandableArrayOfActivePointers.get(index);
if (element.isInDraggingFinger()) {
return true;
}
@ -210,29 +210,28 @@ public final class PointerTrackerQueue {
if (DEBUG) {
Log.d(TAG, "cancelAllPointerTracker: " + this);
}
final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
final int arraySize = mArraySize;
for (int index = 0; index < arraySize; index++) {
final Element element = expandableArray.get(index);
final Element element = mExpandableArrayOfActivePointers.get(index);
element.cancelTrackingForAction();
}
}
}
@NonNull
@Override
public String toString() {
synchronized (mExpandableArrayOfActivePointers) {
final StringBuilder sb = new StringBuilder();
final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
final int arraySize = mArraySize;
for (int index = 0; index < arraySize; index++) {
final Element element = expandableArray.get(index);
final Element element = mExpandableArrayOfActivePointers.get(index);
if (sb.length() > 0) {
sb.append(" ");
}
sb.append(element.toString());
}
return "[" + sb.toString() + "]";
return "[" + sb + "]";
}
}
}

View file

@ -18,6 +18,8 @@ package org.dslul.openboard.inputmethod.keyboard.internal;
import android.util.Log;
import androidx.annotation.NonNull;
/* package */ final class ShiftKeyState extends ModifierKeyState {
private static final int PRESSING_ON_SHIFTED = 3; // both temporary shifted & shift locked
private static final int IGNORING = 4;
@ -53,6 +55,7 @@ import android.util.Log;
return mState == IGNORING;
}
@NonNull
@Override
public String toString() {
return toString(mState);

View file

@ -21,6 +21,8 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import androidx.annotation.NonNull;
import org.dslul.openboard.inputmethod.keyboard.PointerTracker;
import org.dslul.openboard.inputmethod.latin.R;
import org.dslul.openboard.inputmethod.latin.common.CoordinateUtils;
@ -79,7 +81,7 @@ public final class SlidingKeyInputDrawingPreview extends AbstractDrawingPreview
* @param canvas The canvas where the preview is drawn.
*/
@Override
public void drawPreview(final Canvas canvas) {
public void drawPreview(@NonNull final Canvas canvas) {
if (!isPreviewEnabled() || !mShowsSlidingKeyInputPreview) {
return;
}

View file

@ -61,8 +61,8 @@ public class SmoothingUtils {
Arrays.fill(m0[i], 0);
for (int j = 0; j < COEFF_COUNT; ++j) {
final int pow = i + j;
for (int k = 0; k < N; ++k) {
m0[i][j] += (float) Math.pow(xs[k], pow);
for (float x : xs) {
m0[i][j] += (float) Math.pow(x, pow);
}
}
}

View file

@ -35,8 +35,9 @@ public abstract class UniqueKeysCache {
@Override
public void clear() {}
@NonNull
@Override
public Key getUniqueKey(Key key) { return key; }
public Key getUniqueKey(@NonNull Key key) { return key; }
};
@NonNull
@ -63,8 +64,9 @@ public abstract class UniqueKeysCache {
mCache.clear();
}
@NonNull
@Override
public Key getUniqueKey(final Key key) {
public Key getUniqueKey(@NonNull final Key key) {
if (!mEnabled) {
return key;
}

View file

@ -113,7 +113,7 @@ class KeyboardWrapperView @JvmOverloads constructor(
val scale = Settings.getInstance().current.mKeyboardHeightScale
// scale one-handed mode button height if keyboard height scale is < 80%
// more relevant: also change the distance, so the buttons are actually visible
val heightScale = scale + 0.2f
val heightScale = if (scale < 0.8f) scale + 0.2f else 1f
val buttonsLeft = if (isLeftGravity) keyboardView.measuredWidth else 0
stopOneHandedModeBtn.layout(
buttonsLeft + (spareWidth - stopOneHandedModeBtn.measuredWidth) / 2,

View file

@ -36,7 +36,10 @@ class Colors (
val keyHintText: Int
) {
val navBar: Int
/** brightened or darkened variant of [background], to be used if exact background color would be
* bad contrast, e.g. more keys popup or no border space bar */
val adjustedBackground: Int
/** brightened or darkened variant of [keyText] */
val adjustedKeyText: Int
val spaceBarText: Int
@ -49,7 +52,9 @@ class Colors (
val spaceBarFilter: ColorFilter
val keyTextFilter: ColorFilter
val accentColorFilter: ColorFilter
/** color filter for the white action key icons in material theme, switches to gray if necessary for contrast */
val actionKeyIconColorFilter: ColorFilter?
/** color filter for the clipboard pin, used only in holo theme */
val clipboardPinFilter: ColorFilter?
private val backgroundStateList: ColorStateList
@ -58,8 +63,10 @@ class Colors (
private val actionKeyStateList: ColorStateList
private val spaceBarStateList: ColorStateList
private val adjustedBackgroundStateList: ColorStateList
private val suggestionBackgroundList: ColorStateList
val keyboardBackground: Drawable?
/** custom drawable used for keyboard background */
private val keyboardBackground: Drawable?
init {
accentColorFilter = colorFilter(accent)
@ -86,14 +93,20 @@ class Colors (
backgroundFilter = colorFilter(background)
adjustedKeyText = brightenOrDarken(keyText, true)
// color to be used if exact background color would be bad contrast, e.g. more keys popup or no border space bar
val doubleAdjustedBackground: Int
if (isDarkColor(background)) {
adjustedBackground = brighten(background)
adjustedBackgroundStateList = stateList(brighten(adjustedBackground), adjustedBackground)
doubleAdjustedBackground = brighten(adjustedBackground)
} else {
adjustedBackground = darken(background)
adjustedBackgroundStateList = stateList(darken(adjustedBackground), adjustedBackground)
doubleAdjustedBackground = darken(adjustedBackground)
}
adjustedBackgroundStateList = stateList(doubleAdjustedBackground, adjustedBackground)
suggestionBackgroundList = if (!hasKeyBorders && themeStyle == THEME_STYLE_MATERIAL)
stateList(doubleAdjustedBackground, Color.TRANSPARENT)
else
stateList(adjustedBackground, Color.TRANSPARENT)
adjustedBackgroundFilter = colorFilter(adjustedBackground)
if (hasKeyBorders) {
keyBackgroundFilter = colorFilter(keyBackground)
@ -148,7 +161,7 @@ class Colors (
DrawableCompat.setTintList(background, colorStateList)
}
// using !! for the color filter because null is only returned for unsupported modes, which are not used
// using !! for the color filter because null is only returned for unsupported blend modes, which are not used
private fun colorFilter(color: Int, mode: BlendModeCompat = BlendModeCompat.MODULATE): ColorFilter =
BlendModeColorFilterCompat.createBlendModeColorFilterCompat(color, mode)!!
@ -189,5 +202,20 @@ class Colors (
}
enum class BackgroundType {
BACKGROUND, KEY, FUNCTIONAL, ACTION, ACTION_MORE_KEYS, SPACE, ADJUSTED_BACKGROUND, SUGGESTION
/** generic background */
BACKGROUND,
/** key background */
KEY,
/** functional key background */
FUNCTIONAL,
/** action key background */
ACTION,
/** action key more keys background */
ACTION_MORE_KEYS,
/** space bar background */
SPACE,
/** background with some contrast to [BACKGROUND], based on adjustedBackground color */
ADJUSTED_BACKGROUND,
/** background for suggestions and similar, transparent when not pressed */
SUGGESTION
}

View file

@ -27,20 +27,6 @@ package org.dslul.openboard.inputmethod.latin.settings;
public final class DebugSettings {
public static final String PREF_DEBUG_MODE = "debug_mode";
public static final String PREF_FORCE_NON_DISTINCT_MULTITOUCH = "force_non_distinct_multitouch";
public static final String PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS =
"pref_has_custom_key_preview_animation_params";
public static final String PREF_KEY_PREVIEW_DISMISS_DURATION =
"pref_key_preview_dismiss_duration";
public static final String PREF_KEY_PREVIEW_DISMISS_END_X_SCALE =
"pref_key_preview_dismiss_end_x_scale";
public static final String PREF_KEY_PREVIEW_DISMISS_END_Y_SCALE =
"pref_key_preview_dismiss_end_y_scale";
public static final String PREF_KEY_PREVIEW_SHOW_UP_DURATION =
"pref_key_preview_show_up_duration";
public static final String PREF_KEY_PREVIEW_SHOW_UP_START_X_SCALE =
"pref_key_preview_show_up_start_x_scale";
public static final String PREF_KEY_PREVIEW_SHOW_UP_START_Y_SCALE =
"pref_key_preview_show_up_start_y_scale";
public static final String PREF_SHOULD_SHOW_LXX_SUGGESTION_UI =
"pref_should_show_lxx_suggestion_ui";
public static final String PREF_SLIDING_KEY_INPUT_PREVIEW = "pref_sliding_key_input_preview";

View file

@ -19,9 +19,7 @@ package org.dslul.openboard.inputmethod.latin.settings;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Process;
import androidx.annotation.NonNull;
import androidx.preference.Preference;
@ -32,9 +30,6 @@ import org.dslul.openboard.inputmethod.latin.DictionaryDumpBroadcastReceiver;
import org.dslul.openboard.inputmethod.latin.DictionaryFacilitatorImpl;
import org.dslul.openboard.inputmethod.latin.R;
import org.dslul.openboard.inputmethod.latin.utils.ApplicationUtils;
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
import java.util.Locale;
/**
* "Debug mode" settings sub screen.
@ -64,23 +59,6 @@ public final class DebugSettingsFragment extends SubScreenFragment
pref.setOnPreferenceClickListener(this);
dictDumpPreferenceGroup.addPreference(pref);
}
final Resources res = getResources();
setupKeyPreviewAnimationDuration(DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_DURATION,
res.getInteger(R.integer.config_key_preview_show_up_duration));
setupKeyPreviewAnimationDuration(DebugSettings.PREF_KEY_PREVIEW_DISMISS_DURATION,
res.getInteger(R.integer.config_key_preview_dismiss_duration));
final float defaultKeyPreviewShowUpStartScale = ResourceUtils.getFloatFromFraction(
res, R.fraction.config_key_preview_show_up_start_scale);
final float defaultKeyPreviewDismissEndScale = ResourceUtils.getFloatFromFraction(
res, R.fraction.config_key_preview_dismiss_end_scale);
setupKeyPreviewAnimationScale(DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_START_X_SCALE,
defaultKeyPreviewShowUpStartScale);
setupKeyPreviewAnimationScale(DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_START_Y_SCALE,
defaultKeyPreviewShowUpStartScale);
setupKeyPreviewAnimationScale(DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_X_SCALE,
defaultKeyPreviewDismissEndScale);
setupKeyPreviewAnimationScale(DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_Y_SCALE,
defaultKeyPreviewDismissEndScale);
mServiceNeedsRestart = false;
mDebugMode = findPreference(DebugSettings.PREF_DEBUG_MODE);
@ -144,94 +122,4 @@ public final class DebugSettingsFragment extends SubScreenFragment
}
}
private void setupKeyPreviewAnimationScale(final String prefKey, final float defaultValue) {
final SharedPreferences prefs = getSharedPreferences();
final Resources res = getResources();
final SeekBarDialogPreference pref = findPreference(prefKey);
if (pref == null) {
return;
}
pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
private static final float PERCENTAGE_FLOAT = 100.0f;
private float getValueFromPercentage(final int percentage) {
return percentage / PERCENTAGE_FLOAT;
}
private int getPercentageFromValue(final float floatValue) {
return (int)(floatValue * PERCENTAGE_FLOAT);
}
@Override
public void writeValue(final int value, final String key) {
prefs.edit().putFloat(key, getValueFromPercentage(value)).apply();
}
@Override
public void writeDefaultValue(final String key) {
prefs.edit().remove(key).apply();
}
@Override
public int readValue(final String key) {
return getPercentageFromValue(
Settings.readKeyPreviewAnimationScale(prefs, key, defaultValue));
}
@Override
public int readDefaultValue(final String key) {
return getPercentageFromValue(defaultValue);
}
@Override
public String getValueText(final int value) {
if (value < 0) {
return res.getString(R.string.settings_system_default);
}
return String.format(Locale.ROOT, "%d%%", value);
}
@Override
public void feedbackValue(final int value) {}
});
}
private void setupKeyPreviewAnimationDuration(final String prefKey, final int defaultValue) {
final SharedPreferences prefs = getSharedPreferences();
final Resources res = getResources();
final SeekBarDialogPreference pref = findPreference(prefKey);
if (pref == null) {
return;
}
pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
@Override
public void writeValue(final int value, final String key) {
prefs.edit().putInt(key, value).apply();
}
@Override
public void writeDefaultValue(final String key) {
prefs.edit().remove(key).apply();
}
@Override
public int readValue(final String key) {
return Settings.readKeyPreviewAnimationDuration(prefs, key, defaultValue);
}
@Override
public int readDefaultValue(final String key) {
return defaultValue;
}
@Override
public String getValueText(final int value) {
return res.getString(R.string.abbreviation_unit_milliseconds, Integer.toString(value));
}
@Override
public void feedbackValue(final int value) {}
});
}
}

View file

@ -48,10 +48,10 @@ public final class GestureSettingsFragment extends SubScreenFragment {
final SharedPreferences prefs = getSharedPreferences();
final Resources res = getResources();
setPreferenceVisible(Settings.PREF_GESTURE_PREVIEW_TRAIL,
Settings.readGestureInputEnabled(prefs, res));
Settings.readGestureInputEnabled(prefs));
setPreferenceVisible(Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT,
Settings.readGestureInputEnabled(prefs, res));
Settings.readGestureInputEnabled(prefs));
setPreferenceVisible(Settings.PREF_GESTURE_SPACE_AWARE,
Settings.readGestureInputEnabled(prefs, res));
Settings.readGestureInputEnabled(prefs));
}
}

View file

@ -46,13 +46,6 @@ public class LocalSettingsConstants {
// correctly set for it to work on a new device.
DebugSettings.PREF_DEBUG_MODE,
DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH,
DebugSettings.PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS,
DebugSettings.PREF_KEY_PREVIEW_DISMISS_DURATION,
DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_X_SCALE,
DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_Y_SCALE,
DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_DURATION,
DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_START_X_SCALE,
DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_START_Y_SCALE,
DebugSettings.PREF_SHOULD_SHOW_LXX_SUGGESTION_UI,
DebugSettings.PREF_SLIDING_KEY_INPUT_PREVIEW
};

View file

@ -262,17 +262,8 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
res.getBoolean(R.bool.config_block_potentially_offensive));
}
public static boolean readFromBuildConfigIfGestureInputEnabled(final Resources res) {
if (!JniUtils.sHaveGestureLib) {
return false;
}
return res.getBoolean(R.bool.config_gesture_input_enabled_by_build_config);
}
public static boolean readGestureInputEnabled(final SharedPreferences prefs,
final Resources res) {
return readFromBuildConfigIfGestureInputEnabled(res)
&& prefs.getBoolean(PREF_GESTURE_INPUT, true);
public static boolean readGestureInputEnabled(final SharedPreferences prefs) {
return JniUtils.sHaveGestureLib && prefs.getBoolean(PREF_GESTURE_INPUT, true);
}
public static boolean readFromBuildConfigIfToShowKeyPreviewPopupOption(final Resources res) {

View file

@ -35,7 +35,6 @@ import org.dslul.openboard.inputmethod.latin.RichInputMethodManager;
import org.dslul.openboard.inputmethod.latin.common.Colors;
import org.dslul.openboard.inputmethod.latin.spellcheck.AndroidSpellCheckerService;
import org.dslul.openboard.inputmethod.latin.utils.AsyncResultHolder;
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
import org.dslul.openboard.inputmethod.latin.utils.ScriptUtils;
import org.dslul.openboard.inputmethod.latin.utils.TargetPackageInfoGetterTask;
@ -132,15 +131,6 @@ public class SettingsValues {
// User-defined colors
public final Colors mColors;
// Debug settings
public final boolean mHasCustomKeyPreviewAnimationParams;
public final int mKeyPreviewShowUpDuration;
public final int mKeyPreviewDismissDuration;
public final float mKeyPreviewShowUpStartXScale;
public final float mKeyPreviewShowUpStartYScale;
public final float mKeyPreviewDismissEndXScale;
public final float mKeyPreviewDismissEndYScale;
@Nullable
public final String mAccount;
@ -198,7 +188,7 @@ public class SettingsValues {
Settings.PREF_ENABLE_EMOJI_ALT_PHYSICAL_KEY, true);
mShowAppIcon = Settings.readShowSetupWizardIcon(prefs, context);
mIsShowAppIconSettingInPreferences = prefs.contains(Settings.PREF_SHOW_SETUP_WIZARD_ICON);
mGestureInputEnabled = Settings.readGestureInputEnabled(prefs, res);
mGestureInputEnabled = Settings.readGestureInputEnabled(prefs);
mGestureTrailEnabled = prefs.getBoolean(Settings.PREF_GESTURE_PREVIEW_TRAIL, true);
mCloudSyncEnabled = prefs.getBoolean(LocalSettingsConstants.PREF_ENABLE_CLOUD_SYNC, false);
mAccount = prefs.getString(LocalSettingsConstants.PREF_ACCOUNT_NAME,
@ -211,30 +201,7 @@ public class SettingsValues {
readSuggestionsEnabled(prefs);
mIncognitoModeEnabled = Settings.readAlwaysIncognitoMode(prefs) || mInputAttributes.mNoLearning
|| mInputAttributes.mIsPasswordField;
mHasCustomKeyPreviewAnimationParams = prefs.getBoolean(DebugSettings.PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS, false);
mKeyboardHeightScale = Settings.readKeyboardHeight(prefs, DEFAULT_SIZE_SCALE);
mKeyPreviewShowUpDuration = Settings.readKeyPreviewAnimationDuration(
prefs, DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_DURATION,
res.getInteger(R.integer.config_key_preview_show_up_duration));
mKeyPreviewDismissDuration = Settings.readKeyPreviewAnimationDuration(
prefs, DebugSettings.PREF_KEY_PREVIEW_DISMISS_DURATION,
res.getInteger(R.integer.config_key_preview_dismiss_duration));
final float defaultKeyPreviewShowUpStartScale = ResourceUtils.getFloatFromFraction(
res, R.fraction.config_key_preview_show_up_start_scale);
final float defaultKeyPreviewDismissEndScale = ResourceUtils.getFloatFromFraction(
res, R.fraction.config_key_preview_dismiss_end_scale);
mKeyPreviewShowUpStartXScale = Settings.readKeyPreviewAnimationScale(
prefs, DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_START_X_SCALE,
defaultKeyPreviewShowUpStartScale);
mKeyPreviewShowUpStartYScale = Settings.readKeyPreviewAnimationScale(
prefs, DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_START_Y_SCALE,
defaultKeyPreviewShowUpStartScale);
mKeyPreviewDismissEndXScale = Settings.readKeyPreviewAnimationScale(
prefs, DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_X_SCALE,
defaultKeyPreviewDismissEndScale);
mKeyPreviewDismissEndYScale = Settings.readKeyPreviewAnimationScale(
prefs, DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_Y_SCALE,
defaultKeyPreviewDismissEndScale);
mDisplayOrientation = res.getConfiguration().orientation;
mAppWorkarounds = new AsyncResultHolder<>("AppWorkarounds");
final PackageInfo packageInfo = TargetPackageInfoGetterTask.getCachedPackageInfo(
@ -438,18 +405,6 @@ public class SettingsValues {
sb.append("\n mAppWorkarounds = ");
final AppWorkaroundsUtils awu = mAppWorkarounds.get(null, 0);
sb.append("" + (null == awu ? "null" : awu.toString()));
sb.append("\n mKeyPreviewShowUpDuration = ");
sb.append("" + mKeyPreviewShowUpDuration);
sb.append("\n mKeyPreviewDismissDuration = ");
sb.append("" + mKeyPreviewDismissDuration);
sb.append("\n mKeyPreviewShowUpStartScaleX = ");
sb.append("" + mKeyPreviewShowUpStartXScale);
sb.append("\n mKeyPreviewShowUpStartScaleY = ");
sb.append("" + mKeyPreviewShowUpStartYScale);
sb.append("\n mKeyPreviewDismissEndScaleX = ");
sb.append("" + mKeyPreviewDismissEndXScale);
sb.append("\n mKeyPreviewDismissEndScaleY = ");
sb.append("" + mKeyPreviewDismissEndYScale);
return sb.toString();
}
}

View file

@ -16,6 +16,7 @@
package org.dslul.openboard.inputmethod.latin.suggestions;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
@ -125,8 +126,6 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
/**
* Construct a {@link SuggestionStripView} for showing suggestions to be picked by the user.
* @param context
* @param attrs
*/
public SuggestionStripView(final Context context, final AttributeSet attrs) {
this(context, attrs, R.attr.suggestionStripViewStyle);
@ -151,7 +150,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
word.setContentDescription(getResources().getString(R.string.spoken_empty_suggestion));
word.setOnClickListener(this);
word.setOnLongClickListener(this);
colors.setBackgroundColor(word.getBackground(), BackgroundType.SUGGESTION); // only necessary in some Android versions
colors.setBackgroundColor(word.getBackground(), BackgroundType.SUGGESTION);
mWordViews.add(word);
final View divider = inflater.inflate(R.layout.suggestion_divider, null);
mDividerViews.add(divider);
@ -172,8 +171,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
final Resources res = context.getResources();
mMoreSuggestionsModalTolerance = res.getDimensionPixelOffset(
R.dimen.config_more_suggestions_modal_tolerance);
mMoreSuggestionsSlidingDetector = new GestureDetector(
context, mMoreSuggestionsSlidingListener);
mMoreSuggestionsSlidingDetector = new GestureDetector(context, mMoreSuggestionsSlidingListener);
final TypedArray keyboardAttr = context.obtainStyledAttributes(attrs,
R.styleable.Keyboard, defStyle, R.style.SuggestionStripView);
@ -194,7 +192,6 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
mVoiceKey.setColorFilter(colors.getKeyText());
mOtherKey.setColorFilter(colors.getKeyText());
// only necessary in some Android versions
colors.setBackgroundColor(mClipboardKey.getBackground(), BackgroundType.SUGGESTION);
colors.setBackgroundColor(mVoiceKey.getBackground(), BackgroundType.SUGGESTION);
colors.setBackgroundColor(mOtherKey.getBackground(), BackgroundType.SUGGESTION);
@ -202,7 +199,6 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
/**
* A connection back to the input method.
* @param listener
*/
public void setListener(final Listener listener, final View inputView) {
mListener = listener;
@ -231,11 +227,15 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
mLayoutHelper.setMoreSuggestionsHeight(remainingHeight);
}
@SuppressLint("ClickableViewAccessibility") // why would "null" need to call View#performClick?
public void clear() {
mSuggestionsStrip.removeAllViews();
removeAllDebugInfoViews();
mStripVisibilityGroup.showSuggestionsStrip();
dismissMoreSuggestionsPanel();
for (final TextView word : mWordViews) {
word.setOnTouchListener(null);
}
}
private void removeAllDebugInfoViews() {
@ -288,6 +288,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
}
@Override
@SuppressLint("ClickableViewAccessibility") // no need for View#performClick, we return false mostly anyway
public boolean onLongClick(final View view) {
if (view == mClipboardKey) {
ClipboardManager clipboardManager = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
@ -487,6 +488,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
}
@Override
@SuppressLint("ClickableViewAccessibility") // ok, perform click again, but why?
public boolean onTouchEvent(final MotionEvent me) {
if (!mMoreSuggestionsView.isShowingInParent()) {
// Ignore any touch event while more suggestions panel hasn't been shown.

View file

@ -1,39 +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.latin.utils;
import android.content.Context;
import org.dslul.openboard.inputmethod.latin.R;
/**
* Helper class to get the metadata URI and the additional ID.
*/
@SuppressWarnings("unused")
public class MetadataFileUriGetter {
private MetadataFileUriGetter() {
// This helper class is not instantiable.
}
public static String getMetadataUri(final Context context) {
return context.getString(R.string.dictionary_pack_metadata_uri);
}
public static String getMetadataAdditionalId(final Context context) {
return "";
}
}

View file

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="altCodeKeyWhileTypingAnimAlpha"
android:valueType="intType"
android:duration="1000"
android:valueFrom="128"
android:valueTo="255" />

View file

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="altCodeKeyWhileTypingAnimAlpha"
android:valueType="intType"
android:duration="3000"
android:valueFrom="255"
android:valueTo="128" />

View file

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="scaleX"
android:duration="53"
android:valueFrom="1.00"
android:valueTo="0.94" />
<objectAnimator
android:propertyName="scaleY"
android:duration="53"
android:valueFrom="1.00"
android:valueTo="0.94" />
</set>

View file

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="scaleX"
android:duration="53"
android:valueFrom="1.00"
android:valueTo="1.00" />
<objectAnimator
android:propertyName="scaleY"
android:duration="53"
android:valueFrom="1.00"
android:valueTo="0.94" />
</set>

View file

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="scaleX"
android:duration="17"
android:valueFrom="0.98"
android:valueTo="1.00" />
<objectAnimator
android:propertyName="scaleY"
android:duration="17"
android:valueFrom="0.98"
android:valueTo="1.00" />
</set>

View file

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="scaleX"
android:duration="17"
android:valueFrom="1.00"
android:valueTo="1.00" />
<objectAnimator
android:propertyName="scaleY"
android:duration="17"
android:valueFrom="0.98"
android:valueTo="1.00" />
</set>

View file

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Until KitKat (API 19), {@link android.widget.Spinner} of dialog mode in a Dialog can't
handle orientation change correctly. Using dropdown mode avoids the issue.
This file overrides values/spinner-style.xml on KitKat and up. -->
<style name="additionalSubtypeSpinnerStyle">
<item name="android:spinnerMode">dialog</item>
</style>
</resources>

View file

@ -119,13 +119,6 @@
<attr name="keyPreviewOffset" format="dimension" />
<!-- Height of the key press feedback popup. -->
<attr name="keyPreviewHeight" format="dimension" />
<!-- TODO: consolidate key preview linger timeout with the key preview animation parameters. -->
<!-- Delay after key releasing and key press feedback dismissing in millisecond -->
<attr name="keyPreviewLingerTimeout" format="integer" />
<!-- Key preview show up animator -->
<attr name="keyPreviewShowUpAnimator" format="reference" />
<!-- Key preview dismiss animator -->
<attr name="keyPreviewDismissAnimator" format="reference" />
<!-- Layout resource for more keys keyboard -->
<attr name="moreKeysKeyboardLayout" format="reference" />
<!-- Layout resource for more keys keyboard of action key -->

View file

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<resources>
<!-- Whether phrase gestures are enabled by default -->
<bool name="config_default_phrase_gesture_enabled">false</bool>
</resources>

View file

@ -35,12 +35,6 @@
<integer name="config_ignore_alt_code_key_timeout">350</integer>
<integer name="config_key_preview_show_up_duration">0</integer>
<integer name="config_key_preview_dismiss_duration">0</integer>
<fraction name="config_key_preview_show_up_start_scale">100%</fraction>
<fraction name="config_key_preview_dismiss_end_scale">100%</fraction>
<!-- TODO: consolidate key preview linger timeout with the above animation parameters. -->
<integer name="config_key_preview_linger_timeout">0</integer>
<!-- Suppress showing key preview duration after batch input in millisecond -->
<integer name="config_suppress_key_preview_after_batch_input_duration">100</integer>
@ -53,8 +47,6 @@
<integer name="config_longpress_timeout_step">10</integer>
<integer name="config_accessibility_long_press_key_timeout">3000</integer>
<integer name="config_max_more_keys_column">5</integer>
<integer name="config_more_keys_keyboard_fadein_anim_time">0</integer>
<integer name="config_more_keys_keyboard_fadeout_anim_time">100</integer>
<!-- Long pressing shift will invoke caps-lock if > 0, never invoke caps-lock if == 0 -->
<integer name="config_longpress_shift_lock_timeout">1200</integer>
@ -69,7 +61,7 @@
<dimen name="config_key_hysteresis_distance_for_sliding_modifier">8.0dp</dimen>
<integer name="config_language_on_spacebar_final_alpha">128</integer>
<dimen name="config_language_on_spacebar_horizontal_margin">1dp</dimen>
<dimen name="config_language_on_spacebar_horizontal_margin">3dp</dimen>
<integer name="config_gesture_floating_preview_text_linger_timeout">200</integer>
<integer name="config_gesture_trail_fadeout_start_delay">100</integer>
@ -146,8 +138,4 @@
<dimen name="config_accessibility_edge_slop">8dp</dimen>
<integer name="config_user_dictionary_max_word_length">48</integer>
<!-- Personalization configuration -->
<!-- -1 means periocical wipe of the personalization dict is disabled. -->
<integer name="config_personalization_dict_wipe_interval_in_days">-1</integer>
</resources>

View file

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<!-- Configuration values for Dictionary pack. -->
<resources>
<!-- Settings for the dictionary pack -->
<bool name="allow_over_metered">false</bool>
<bool name="allow_over_roaming">false</bool>
<bool name="dict_downloads_visible_in_download_UI">false</bool>
<bool name="metadata_downloads_visible_in_download_UI">false</bool>
<bool name="display_notification_for_auto_update">true</bool>
<bool name="display_notification_for_user_requested_update">true</bool>
</resources>

View file

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="dictionary_pack_client_id" translatable="false">org.dslul.openboard.inputmethod.latin</string>
<string name="dictionary_pack_metadata_uri" translatable="false"></string>
<string name="local_metadata_filename" translatable="false">metadata.json</string>
</resources>

View file

@ -27,20 +27,6 @@
<string name="sliding_key_input_preview" translatable="false">Show slide indicator</string>
<!-- Option summary to enable sliding key input indicator. The user can see a rubber band-like effect during sliding key input. [CHAR LIMIT=66]-->
<string name="sliding_key_input_preview_summary" translatable="false">Display visual cue while sliding from Shift or Symbol keys</string>
<!-- Title of the settings for customize key popup animation parameters [CHAR LIMIT=35] -->
<string name="prefs_customize_key_preview_animation" translatable="false">Customize key preview animation</string>
<!-- Title of the settings for key popup show up animation duration (in milliseconds) [CHAR LIMIT=35] -->
<string name="prefs_key_popup_show_up_duration_settings" translatable="false">Key popup show up duration</string>
<!-- Title of the settings for key popup dismiss animation duration (in milliseconds) [CHAR LIMIT=35] -->
<string name="prefs_key_popup_dismiss_duration_settings" translatable="false">Key popup dismiss duration</string>
<!-- Title of the settings for key popup show up animation start X-scale (in percentile) [CHAR LIMIT=35] -->
<string name="prefs_key_popup_show_up_start_x_scale_settings" translatable="false">Key popup show up start X scale</string>
<!-- Title of the settings for key popup show up animation start Y-scale (in percentile) [CHAR LIMIT=35] -->
<string name="prefs_key_popup_show_up_start_y_scale_settings" translatable="false">Key popup show up start Y scale</string>
<!-- Title of the settings for key popup dismiss animation end X-scale (in percentile) [CHAR LIMIT=35] -->
<string name="prefs_key_popup_dismiss_end_x_scale_settings" translatable="false">Key popup dismiss end X scale</string>
<!-- Title of the settings for key popup dismiss animation end Y-scale (in percentile) [CHAR LIMIT=35] -->
<string name="prefs_key_popup_dismiss_end_y_scale_settings" translatable="false">Key popup dismiss end Y scale</string>
<!-- Title of the settings group for dumpping dictionary files that have been created on the device [CHAR LIMIT=35] -->
<!-- Title of the settings group for dumping dictionary files that have been created on the device [CHAR LIMIT=35] -->
<string name="prefs_dump_dynamic_dicts" translatable="false">Dump dictionary</string>
</resources>

View file

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<resources>
<bool name="config_gesture_input_enabled_by_build_config">true</bool>
</resources>

View file

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2015 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
-->
<resources>
<!-- The text shown on the suggestion bar to request the contacts permission info. -->
</resources>

View file

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Until KitKat (API 19), {@link android.widget.Spinner} of dialog mode in a Dialog can't
handle orientation change correctly. Using dropdown mode avoids the issue.
This file is overridden by values-v19/spinner-style.xml on KitKat and up. -->
<style name="additionalSubtypeSpinnerStyle">
<item name="android:spinnerMode">dropdown</item>
</style>
</resources>

View file

@ -78,13 +78,11 @@
<item name="keyRepeatInterval">@integer/config_key_repeat_interval</item>
<item name="longPressShiftLockTimeout">@integer/config_longpress_shift_lock_timeout</item>
<item name="ignoreAltCodeKeyTimeout">@integer/config_ignore_alt_code_key_timeout</item>
<!-- TODO: consolidate key preview linger timeout with the key preview animation parameters. -->
<item name="keyPreviewLingerTimeout">@integer/config_key_preview_linger_timeout</item>
<item name="moreKeysKeyboardLayout">@layout/more_keys_keyboard</item>
<item name="showMoreKeysKeyboardAtTouchedPoint">@bool/config_show_more_keys_keyboard_at_touched_point</item>
<item name="languageOnSpacebarTextRatio">@fraction/config_language_on_spacebar_text_ratio</item>
<item name="languageOnSpacebarFinalAlpha">@integer/config_language_on_spacebar_final_alpha</item>
<item name="languageOnSpacebarFadeoutAnimator">@anim/language_on_spacebar_fadeout</item>
<item name="languageOnSpacebarFadeoutAnimator">@animator/language_on_spacebar_fadeout</item>
<!-- Remove animations for now because it could drain a non-negligible amount of battery while typing.
<item name="altCodeKeyWhileTypingFadeoutAnimator">@anim/alt_code_key_while_typing_fadeout</item>
<item name="altCodeKeyWhileTypingFadeinAnimator">@anim/alt_code_key_while_typing_fadein</item>

View file

@ -64,8 +64,6 @@
<item name="keyPreviewBackground">@drawable/keyboard_key_feedback_holo_white</item>
<item name="keyPreviewHeight">@dimen/config_key_preview_height_holo</item>
<item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
<item name="keyPreviewShowUpAnimator">@anim/key_preview_show_up_holo</item>
<item name="keyPreviewDismissAnimator">@anim/key_preview_dismiss_holo</item>
<item name="gestureFloatingPreviewTextColor">@color/highlight_color_holo_white</item>
<item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_holo</item>
<item name="gestureTrailColor">@color/highlight_color_holo_white</item>

View file

@ -46,8 +46,6 @@
<item name="keyPreviewBackground">@drawable/keyboard_key_feedback_lxx_light</item>
<item name="keyPreviewHeight">@dimen/config_key_preview_height_lxx</item>
<item name="keyPreviewOffset">@dimen/config_key_preview_offset_lxx</item>
<item name="keyPreviewShowUpAnimator">@anim/key_preview_show_up_lxx</item>
<item name="keyPreviewDismissAnimator">@anim/key_preview_dismiss_lxx</item>
<item name="gestureFloatingPreviewTextColor">@color/auto_correct_color_lxx_light</item>
<item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_lxx_light</item>
<item name="gestureTrailColor">@color/gesture_trail_color_lxx_light</item>

View file

@ -41,41 +41,6 @@
android:summary="@string/sliding_key_input_preview_summary"
android:defaultValue="true"
android:persistent="true" />
<SwitchPreferenceCompat
android:key="pref_has_custom_key_preview_animation_params"
android:title="@string/prefs_customize_key_preview_animation"
android:defaultValue="false"
android:persistent="true" />
<org.dslul.openboard.inputmethod.latin.settings.SeekBarDialogPreference
android:dependency="pref_has_custom_key_preview_animation_params"
android:key="pref_key_preview_show_up_start_x_scale"
android:title="@string/prefs_key_popup_show_up_start_x_scale_settings"
latin:maxValue="100" /> <!-- percent -->
<org.dslul.openboard.inputmethod.latin.settings.SeekBarDialogPreference
android:dependency="pref_has_custom_key_preview_animation_params"
android:key="pref_key_preview_show_up_start_y_scale"
android:title="@string/prefs_key_popup_show_up_start_y_scale_settings"
latin:maxValue="100" /> <!-- percent -->
<org.dslul.openboard.inputmethod.latin.settings.SeekBarDialogPreference
android:dependency="pref_has_custom_key_preview_animation_params"
android:key="pref_key_preview_dismiss_end_x_scale"
android:title="@string/prefs_key_popup_dismiss_end_x_scale_settings"
latin:maxValue="100" /> <!-- percent -->
<org.dslul.openboard.inputmethod.latin.settings.SeekBarDialogPreference
android:dependency="pref_has_custom_key_preview_animation_params"
android:key="pref_key_preview_dismiss_end_y_scale"
android:title="@string/prefs_key_popup_dismiss_end_y_scale_settings"
latin:maxValue="100" /> <!-- percent -->
<org.dslul.openboard.inputmethod.latin.settings.SeekBarDialogPreference
android:dependency="pref_has_custom_key_preview_animation_params"
android:key="pref_key_preview_show_up_duration"
android:title="@string/prefs_key_popup_show_up_duration_settings"
latin:maxValue="100" /> <!-- milliseconds -->
<org.dslul.openboard.inputmethod.latin.settings.SeekBarDialogPreference
android:dependency="pref_has_custom_key_preview_animation_params"
android:key="pref_key_preview_dismiss_duration"
android:title="@string/prefs_key_popup_dismiss_duration_settings"
latin:maxValue="100" /> <!-- milliseconds -->
<PreferenceCategory
android:key="pref_key_dump_dictionaries"
android:title="@string/prefs_dump_dynamic_dicts">