Added support for speaking keys through accessibility service.
Issue: 3366636 Change-Id: I70a2ebb4420782ba4d7d874ffc2259bb1b80446fmain
parent
ededda059c
commit
dcade18113
|
@ -28,4 +28,24 @@
|
|||
<integer name="key_delete">-5</integer>
|
||||
<integer name="key_settings">-100</integer>
|
||||
<integer name="key_voice">-102</integer>
|
||||
|
||||
<!-- Array used for mapping key codes to description strings. -->
|
||||
<array name="key_descriptions">
|
||||
<item>@integer/key_tab</item>
|
||||
<item>@string/description_tab_key</item>
|
||||
<item>@integer/key_return</item>
|
||||
<item>@string/description_return_key</item>
|
||||
<item>@integer/key_space</item>
|
||||
<item>@string/description_space_key</item>
|
||||
<item>@integer/key_shift</item>
|
||||
<item>@string/description_shift_key</item>
|
||||
<item>@integer/key_switch_alpha_symbol</item>
|
||||
<item>@string/description_switch_alpha_symbol_key</item>
|
||||
<item>@integer/key_delete</item>
|
||||
<item>@string/description_delete_key</item>
|
||||
<item>@integer/key_settings</item>
|
||||
<item>@string/description_settings_key</item>
|
||||
<item>@integer/key_voice</item>
|
||||
<item>@string/description_voice_key</item>
|
||||
</array>
|
||||
</resources>
|
||||
|
|
|
@ -102,6 +102,31 @@
|
|||
<!-- Label for "Wait" key of phone number keyboard. Must be short to fit on key! [CHAR LIMIT=5]-->
|
||||
<string name="label_wait_key">Wait</string>
|
||||
|
||||
<!-- Spoken text description for delete key. -->
|
||||
<string name="description_delete_key">Delete</string>
|
||||
<!-- Spoken text description for return key. -->
|
||||
<string name="description_return_key">Return</string>
|
||||
<!-- Spoken text description for settings key. -->
|
||||
<string name="description_settings_key">Settings</string>
|
||||
<!-- Spoken text description for shift key. -->
|
||||
<string name="description_shift_key">Shift</string>
|
||||
<!-- Spoken text description for space key. -->
|
||||
<string name="description_space_key">Space</string>
|
||||
<!-- Spoken text description for symbols key. -->
|
||||
<string name="description_switch_alpha_symbol_key">Symbols</string>
|
||||
<!-- Spoken text description for tab key. -->
|
||||
<string name="description_tab_key">Tab</string>
|
||||
<!-- Spoken text description for voice input key. -->
|
||||
<string name="description_voice_key">Voice Input</string>
|
||||
<!-- Spoken text description for symbols mode on. -->
|
||||
<string name="description_symbols_on">Symbols on</string>
|
||||
<!-- Spoken text description for symbols mode off. -->
|
||||
<string name="description_symbols_off">Symbols off</string>
|
||||
<!-- Spoken text description for shift mode on. -->
|
||||
<string name="description_shift_on">Shift on</string>
|
||||
<!-- Spoken text description for shift mode off. -->
|
||||
<string name="description_shift_off">Shift off</string>
|
||||
|
||||
<!-- Voice related labels -->
|
||||
|
||||
<!-- Title of the warning dialog that shows when a user initiates voice input for
|
||||
|
|
|
@ -336,7 +336,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
|||
// state when shift key is pressed to go to normal mode.
|
||||
// On the other hand, on distinct multi touch panel device, turning off the shift locked
|
||||
// state with shift key pressing is handled by onReleaseShift().
|
||||
if (!hasDistinctMultitouch() && !shifted && latinKeyboard.isShiftLocked()) {
|
||||
if ((!hasDistinctMultitouch() || isAccessibilityEnabled())
|
||||
&& !shifted && latinKeyboard.isShiftLocked()) {
|
||||
latinKeyboard.setShiftLocked(false);
|
||||
}
|
||||
if (latinKeyboard.setShifted(shifted)) {
|
||||
|
@ -434,6 +435,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
|||
public void onPressShift() {
|
||||
if (!isKeyboardAvailable())
|
||||
return;
|
||||
// If accessibility is enabled, disable momentary shift lock.
|
||||
if (isAccessibilityEnabled())
|
||||
return;
|
||||
ShiftKeyState shiftKeyState = mShiftKeyState;
|
||||
if (DEBUG_STATE)
|
||||
Log.d(TAG, "onPressShift:"
|
||||
|
@ -469,6 +473,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
|||
public void onReleaseShift() {
|
||||
if (!isKeyboardAvailable())
|
||||
return;
|
||||
// If accessibility is enabled, disable momentary shift lock.
|
||||
if (isAccessibilityEnabled())
|
||||
return;
|
||||
ShiftKeyState shiftKeyState = mShiftKeyState;
|
||||
if (DEBUG_STATE)
|
||||
Log.d(TAG, "onReleaseShift:"
|
||||
|
@ -494,6 +501,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
|||
}
|
||||
|
||||
public void onPressSymbol() {
|
||||
// If accessibility is enabled, disable momentary symbol lock.
|
||||
if (isAccessibilityEnabled())
|
||||
return;
|
||||
if (DEBUG_STATE)
|
||||
Log.d(TAG, "onPressSymbol:"
|
||||
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
|
||||
|
@ -504,6 +514,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
|||
}
|
||||
|
||||
public void onReleaseSymbol() {
|
||||
// If accessibility is enabled, disable momentary symbol lock.
|
||||
if (isAccessibilityEnabled())
|
||||
return;
|
||||
if (DEBUG_STATE)
|
||||
Log.d(TAG, "onReleaseSymbol:"
|
||||
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
|
||||
|
@ -516,6 +529,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
|||
}
|
||||
|
||||
public void onOtherKeyPressed() {
|
||||
// If accessibility is enabled, disable momentary mode locking.
|
||||
if (isAccessibilityEnabled())
|
||||
return;
|
||||
if (DEBUG_STATE)
|
||||
Log.d(TAG, "onOtherKeyPressed:"
|
||||
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
|
||||
|
@ -574,6 +590,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isAccessibilityEnabled() {
|
||||
return mInputView != null && mInputView.isAccessibilityEnabled();
|
||||
}
|
||||
|
||||
public boolean hasDistinctMultitouch() {
|
||||
return mInputView != null && mInputView.hasDistinctMultitouch();
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import android.graphics.drawable.Drawable;
|
|||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
|
@ -146,6 +147,9 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
|||
private final boolean mHasDistinctMultitouch;
|
||||
private int mOldPointerCount = 1;
|
||||
|
||||
// Accessibility
|
||||
private boolean mIsAccessibilityEnabled;
|
||||
|
||||
protected KeyDetector mKeyDetector = new ProximityKeyDetector();
|
||||
|
||||
// Swipe gesture detector
|
||||
|
@ -523,7 +527,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return whether the device has distinct multi-touch panel.
|
||||
* Returns whether the device has distinct multi-touch panel.
|
||||
* @return true if the device has distinct multi-touch panel.
|
||||
*/
|
||||
@Override
|
||||
|
@ -531,6 +535,28 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
|||
return mHasDistinctMultitouch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables accessibility.
|
||||
* @param accessibilityEnabled whether or not to enable accessibility
|
||||
*/
|
||||
public void setAccessibilityEnabled(boolean accessibilityEnabled) {
|
||||
mIsAccessibilityEnabled = accessibilityEnabled;
|
||||
|
||||
// Propagate this change to all existing pointer trackers.
|
||||
for (PointerTracker tracker : mPointerTrackers) {
|
||||
tracker.setAccessibilityEnabled(accessibilityEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the device has accessibility enabled.
|
||||
* @return true if the device has accessibility enabled.
|
||||
*/
|
||||
@Override
|
||||
public boolean isAccessibilityEnabled() {
|
||||
return mIsAccessibilityEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the key feedback popup. This is a popup that shows a magnified
|
||||
* version of the depressed key. By default the preview is enabled.
|
||||
|
@ -1210,15 +1236,18 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
|||
// TODO: cleanup this code into a multi-touch to single-touch event converter class?
|
||||
// If the device does not have distinct multi-touch support panel, ignore all multi-touch
|
||||
// events except a transition from/to single-touch.
|
||||
if (!mHasDistinctMultitouch && pointerCount > 1 && oldPointerCount > 1) {
|
||||
if ((!mHasDistinctMultitouch || mIsAccessibilityEnabled)
|
||||
&& pointerCount > 1 && oldPointerCount > 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Track the last few movements to look for spurious swipes.
|
||||
mSwipeTracker.addMovement(me);
|
||||
|
||||
// Gesture detector must be enabled only when mini-keyboard is not on the screen.
|
||||
if (mMiniKeyboardView == null
|
||||
// Gesture detector must be enabled only when mini-keyboard is not on the screen and
|
||||
// accessibility is not enabled.
|
||||
// TODO: Reconcile gesture detection and accessibility features.
|
||||
if (mMiniKeyboardView == null && !mIsAccessibilityEnabled
|
||||
&& mGestureDetector != null && mGestureDetector.onTouchEvent(me)) {
|
||||
dismissKeyPreview();
|
||||
mHandler.cancelKeyTimers();
|
||||
|
@ -1263,7 +1292,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
|||
// TODO: cleanup this code into a multi-touch to single-touch event converter class?
|
||||
// Translate mutli-touch event to single-touch events on the device that has no distinct
|
||||
// multi-touch panel.
|
||||
if (!mHasDistinctMultitouch) {
|
||||
if (!mHasDistinctMultitouch || mIsAccessibilityEnabled) {
|
||||
// Use only main (id=0) pointer tracker.
|
||||
PointerTracker tracker = getPointerTracker(0);
|
||||
if (pointerCount == 1 && oldPointerCount == 2) {
|
||||
|
|
|
@ -145,6 +145,10 @@ public class LatinKeyboardView extends KeyboardView {
|
|||
// If device has distinct multi touch panel, there is no need to check sudden jump.
|
||||
if (hasDistinctMultitouch())
|
||||
return false;
|
||||
// If accessibiliy is enabled, stop looking for sudden jumps because it interferes
|
||||
// with touch exploration of the keyboard.
|
||||
if (isAccessibilityEnabled())
|
||||
return false;
|
||||
final int action = me.getAction();
|
||||
final int x = (int) me.getX();
|
||||
final int y = (int) me.getY();
|
||||
|
|
|
@ -38,6 +38,7 @@ public class PointerTracker {
|
|||
public void invalidateKey(Key key);
|
||||
public void showPreview(int keyIndex, PointerTracker tracker);
|
||||
public boolean hasDistinctMultitouch();
|
||||
public boolean isAccessibilityEnabled();
|
||||
}
|
||||
|
||||
public final int mPointerId;
|
||||
|
@ -68,6 +69,9 @@ public class PointerTracker {
|
|||
|
||||
private final PointerTrackerKeyState mKeyState;
|
||||
|
||||
// true if accessibility is enabled in the parent keyboard
|
||||
private boolean mIsAccessibilityEnabled;
|
||||
|
||||
// true if keyboard layout has been changed.
|
||||
private boolean mKeyboardLayoutHasBeenChanged;
|
||||
|
||||
|
@ -112,6 +116,7 @@ public class PointerTracker {
|
|||
mKeyDetector = keyDetector;
|
||||
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
|
||||
mKeyState = new PointerTrackerKeyState(keyDetector);
|
||||
mIsAccessibilityEnabled = proxy.isAccessibilityEnabled();
|
||||
mHasDistinctMultitouch = proxy.hasDistinctMultitouch();
|
||||
mConfigSlidingKeyInputEnabled = res.getBoolean(R.bool.config_sliding_key_input_enabled);
|
||||
mDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start);
|
||||
|
@ -128,6 +133,10 @@ public class PointerTracker {
|
|||
mListener = listener;
|
||||
}
|
||||
|
||||
public void setAccessibilityEnabled(boolean accessibilityEnabled) {
|
||||
mIsAccessibilityEnabled = accessibilityEnabled;
|
||||
}
|
||||
|
||||
// Returns true if keyboard has been changed by this callback.
|
||||
private boolean callListenerOnPressAndCheckKeyboardLayoutChange(Key key) {
|
||||
if (DEBUG_LISTENER)
|
||||
|
@ -312,9 +321,10 @@ public class PointerTracker {
|
|||
private void onDownEventInternal(int x, int y, long eventTime) {
|
||||
int keyIndex = mKeyState.onDownKey(x, y, eventTime);
|
||||
// Sliding key is allowed when 1) enabled by configuration, 2) this pointer starts sliding
|
||||
// from modifier key, or 3) this pointer is on mini-keyboard.
|
||||
// from modifier key, 3) this pointer is on mini-keyboard, or 4) accessibility is enabled.
|
||||
mIsAllowedSlidingKeyInput = mConfigSlidingKeyInputEnabled || isModifierInternal(keyIndex)
|
||||
|| mKeyDetector instanceof MiniKeyboardKeyDetector;
|
||||
|| mKeyDetector instanceof MiniKeyboardKeyDetector
|
||||
|| mIsAccessibilityEnabled;
|
||||
mKeyboardLayoutHasBeenChanged = false;
|
||||
mKeyAlreadyProcessed = false;
|
||||
mIsRepeatableKey = false;
|
||||
|
@ -327,7 +337,9 @@ public class PointerTracker {
|
|||
keyIndex = mKeyState.onDownKey(x, y, eventTime);
|
||||
}
|
||||
if (isValidKeyIndex(keyIndex)) {
|
||||
if (mKeys[keyIndex].mRepeatable) {
|
||||
// Accessibility disables key repeat because users may need to pause on a key to hear
|
||||
// its spoken description.
|
||||
if (mKeys[keyIndex].mRepeatable && !mIsAccessibilityEnabled) {
|
||||
repeatKey(keyIndex);
|
||||
mHandler.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this);
|
||||
mIsRepeatableKey = true;
|
||||
|
@ -517,8 +529,9 @@ public class PointerTracker {
|
|||
updateKeyGraphics(keyIndex);
|
||||
// The modifier key, such as shift key, should not be shown as preview when multi-touch is
|
||||
// supported. On the other hand, if multi-touch is not supported, the modifier key should
|
||||
// be shown as preview.
|
||||
if (mHasDistinctMultitouch && isModifier()) {
|
||||
// be shown as preview. If accessibility is turned on, the modifier key should be shown as
|
||||
// preview.
|
||||
if (mHasDistinctMultitouch && isModifier() && !mIsAccessibilityEnabled) {
|
||||
mProxy.showPreview(NOT_A_KEY, this);
|
||||
} else {
|
||||
mProxy.showPreview(keyIndex, this);
|
||||
|
@ -526,6 +539,11 @@ public class PointerTracker {
|
|||
}
|
||||
|
||||
private void startLongPressTimer(int keyIndex) {
|
||||
// Accessibility disables long press because users are likely to need to pause on a key
|
||||
// for an unspecified duration in order to hear the key's spoken description.
|
||||
if (mIsAccessibilityEnabled) {
|
||||
return;
|
||||
}
|
||||
Key key = getKey(keyIndex);
|
||||
if (key.mCode == Keyboard.CODE_SHIFT) {
|
||||
mHandler.startLongPressShiftTimer(mLongPressShiftKeyTimeout, keyIndex, this);
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.TypedArray;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
import com.android.inputmethod.keyboard.Keyboard;
|
||||
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Utility functions for accessibility support.
|
||||
*/
|
||||
public class AccessibilityUtils {
|
||||
/** Shared singleton instance. */
|
||||
private static final AccessibilityUtils sInstance = new AccessibilityUtils();
|
||||
private /* final */ LatinIME mService;
|
||||
private /* final */ AccessibilityManager mAccessibilityManager;
|
||||
private /* final */ Map<Integer, CharSequence> mDescriptions;
|
||||
|
||||
/**
|
||||
* Returns a shared instance of AccessibilityUtils.
|
||||
*
|
||||
* @return A shared instance of AccessibilityUtils.
|
||||
*/
|
||||
public static AccessibilityUtils getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes (or re-initializes) the shared instance of AccessibilityUtils
|
||||
* with the specified parent service and preferences.
|
||||
*
|
||||
* @param service The parent input method service.
|
||||
* @param prefs The parent preferences.
|
||||
*/
|
||||
public static void init(LatinIME service, SharedPreferences prefs) {
|
||||
sInstance.initialize(service, prefs);
|
||||
}
|
||||
|
||||
private AccessibilityUtils() {
|
||||
// This class is not publicly instantiable.
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes (or re-initializes) with the specified parent service and
|
||||
* preferences.
|
||||
*
|
||||
* @param service The parent input method service.
|
||||
* @param prefs The parent preferences.
|
||||
*/
|
||||
private void initialize(LatinIME service, SharedPreferences prefs) {
|
||||
mService = service;
|
||||
mAccessibilityManager = (AccessibilityManager) service.getSystemService(
|
||||
Context.ACCESSIBILITY_SERVICE);
|
||||
mDescriptions = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if accessibility is enabled.
|
||||
*
|
||||
* @return {@code true} if accessibility is enabled.
|
||||
*/
|
||||
public boolean isAccessibilityEnabled() {
|
||||
return mAccessibilityManager.isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Speaks a key's action after it has been released. Does not speak letter
|
||||
* keys since typed keys are already spoken aloud by TalkBack.
|
||||
* <p>
|
||||
* No-op if accessibility is not enabled.
|
||||
* </p>
|
||||
*
|
||||
* @param primaryCode The primary code of the released key.
|
||||
* @param switcher The input method's {@link KeyboardSwitcher}.
|
||||
*/
|
||||
public void onRelease(int primaryCode, KeyboardSwitcher switcher) {
|
||||
if (!isAccessibilityEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int resId = -1;
|
||||
|
||||
switch (primaryCode) {
|
||||
case Keyboard.CODE_SHIFT: {
|
||||
if (switcher.isShiftedOrShiftLocked()) {
|
||||
resId = R.string.description_shift_on;
|
||||
} else {
|
||||
resId = R.string.description_shift_off;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: {
|
||||
if (switcher.isAlphabetMode()) {
|
||||
resId = R.string.description_symbols_off;
|
||||
} else {
|
||||
resId = R.string.description_symbols_on;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (resId >= 0) {
|
||||
speakDescription(mService.getResources().getText(resId));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Speaks a key's description for accessibility. If a key has an explicit
|
||||
* description defined in keycodes.xml, that will be used. Otherwise, if the
|
||||
* key is a Unicode character, then its character will be used.
|
||||
* <p>
|
||||
* No-op if accessibility is not enabled.
|
||||
* </p>
|
||||
*
|
||||
* @param primaryCode The primary code of the pressed key.
|
||||
* @param switcher The input method's {@link KeyboardSwitcher}.
|
||||
*/
|
||||
public void onPress(int primaryCode, KeyboardSwitcher switcher) {
|
||||
if (!isAccessibilityEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO Use the current keyboard state to read "Switch to symbols"
|
||||
// instead of just "Symbols" (and similar for shift key).
|
||||
CharSequence description = describeKey(primaryCode);
|
||||
if (description == null && Character.isDefined((char) primaryCode)) {
|
||||
description = Character.toString((char) primaryCode);
|
||||
}
|
||||
|
||||
if (description != null) {
|
||||
speakDescription(description);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a text description for a given key code. If the key does not have
|
||||
* an explicit description, returns <code>null</code>.
|
||||
*
|
||||
* @param keyCode An integer key code.
|
||||
* @return A {@link CharSequence} describing the key or <code>null</code> if
|
||||
* no description is available.
|
||||
*/
|
||||
private CharSequence describeKey(int keyCode) {
|
||||
// If not loaded yet, load key descriptions from XML file.
|
||||
if (mDescriptions == null) {
|
||||
mDescriptions = loadDescriptions();
|
||||
}
|
||||
|
||||
return mDescriptions.get(keyCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads key descriptions from resources.
|
||||
*/
|
||||
private Map<Integer, CharSequence> loadDescriptions() {
|
||||
final Map<Integer, CharSequence> descriptions = new HashMap<Integer, CharSequence>();
|
||||
final TypedArray array = mService.getResources().obtainTypedArray(R.array.key_descriptions);
|
||||
|
||||
// Key descriptions are stored as a key code followed by a string.
|
||||
for (int i = 0; i < array.length() - 1; i += 2) {
|
||||
int code = array.getInteger(i, 0);
|
||||
CharSequence desc = array.getText(i + 1);
|
||||
|
||||
descriptions.put(code, desc);
|
||||
}
|
||||
|
||||
array.recycle();
|
||||
|
||||
return descriptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a character sequence to be read aloud.
|
||||
*
|
||||
* @param description The {@link CharSequence} to be read aloud.
|
||||
*/
|
||||
private void speakDescription(CharSequence description) {
|
||||
// TODO We need to add an AccessibilityEvent type for IMEs.
|
||||
final AccessibilityEvent event = AccessibilityEvent.obtain(
|
||||
AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
|
||||
event.setPackageName(mService.getPackageName());
|
||||
event.setClassName(getClass().getName());
|
||||
event.setAddedCount(description.length());
|
||||
event.getText().add(description);
|
||||
|
||||
mAccessibilityManager.sendAccessibilityEvent(event);
|
||||
}
|
||||
}
|
|
@ -152,6 +152,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
private boolean mIsSettingsSuggestionStripOn;
|
||||
private boolean mApplicationSpecifiedCompletionOn;
|
||||
|
||||
private AccessibilityUtils mAccessibilityUtils;
|
||||
|
||||
private final StringBuilder mComposing = new StringBuilder();
|
||||
private WordComposer mWord = new WordComposer();
|
||||
private CharSequence mBestWord;
|
||||
|
@ -357,6 +359,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
LatinImeLogger.init(this, prefs);
|
||||
SubtypeSwitcher.init(this, prefs);
|
||||
KeyboardSwitcher.init(this, prefs);
|
||||
AccessibilityUtils.init(this, prefs);
|
||||
|
||||
super.onCreate();
|
||||
|
||||
|
@ -364,6 +367,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
mInputMethodId = Utils.getInputMethodId(mImm, getPackageName());
|
||||
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
|
||||
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
|
||||
mAccessibilityUtils = AccessibilityUtils.getInstance();
|
||||
|
||||
final Resources res = getResources();
|
||||
mResources = res;
|
||||
|
@ -546,8 +550,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
|
||||
updateCorrectionMode();
|
||||
|
||||
final boolean accessibilityEnabled = mAccessibilityUtils.isAccessibilityEnabled();
|
||||
|
||||
inputView.setPreviewEnabled(mPopupOn);
|
||||
inputView.setProximityCorrectionEnabled(true);
|
||||
inputView.setAccessibilityEnabled(accessibilityEnabled);
|
||||
// If we just entered a text field, maybe it has some old text that requires correction
|
||||
checkReCorrectionOnStart();
|
||||
inputView.setForeground(true);
|
||||
|
@ -1073,6 +1080,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
}
|
||||
mLastKeyTime = when;
|
||||
KeyboardSwitcher switcher = mKeyboardSwitcher;
|
||||
final boolean accessibilityEnabled = switcher.isAccessibilityEnabled();
|
||||
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
|
||||
switch (primaryCode) {
|
||||
case Keyboard.CODE_DELETE:
|
||||
|
@ -1082,12 +1090,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
break;
|
||||
case Keyboard.CODE_SHIFT:
|
||||
// Shift key is handled in onPress() when device has distinct multi-touch panel.
|
||||
if (!distinctMultiTouch)
|
||||
if (!distinctMultiTouch || accessibilityEnabled)
|
||||
switcher.toggleShift();
|
||||
break;
|
||||
case Keyboard.CODE_SWITCH_ALPHA_SYMBOL:
|
||||
// Symbol key is handled in onPress() when device has distinct multi-touch panel.
|
||||
if (!distinctMultiTouch)
|
||||
if (!distinctMultiTouch || accessibilityEnabled)
|
||||
switcher.changeKeyboardMode();
|
||||
break;
|
||||
case Keyboard.CODE_CANCEL:
|
||||
|
@ -1913,6 +1921,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
} else {
|
||||
switcher.onOtherKeyPressed();
|
||||
}
|
||||
mAccessibilityUtils.onPress(primaryCode, switcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1926,6 +1935,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
} else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
|
||||
switcher.onReleaseSymbol();
|
||||
}
|
||||
mAccessibilityUtils.onRelease(primaryCode, switcher);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue