Merge "Support more keys accessibility mode"
This commit is contained in:
commit
86e1e1f97c
9 changed files with 367 additions and 22 deletions
|
@ -48,6 +48,7 @@
|
||||||
<integer name="config_max_longpress_timeout">700</integer>
|
<integer name="config_max_longpress_timeout">700</integer>
|
||||||
<integer name="config_min_longpress_timeout">100</integer>
|
<integer name="config_min_longpress_timeout">100</integer>
|
||||||
<integer name="config_longpress_timeout_step">10</integer>
|
<integer name="config_longpress_timeout_step">10</integer>
|
||||||
|
<integer name="config_accessibility_long_press_key_timeout">1500</integer>
|
||||||
<integer name="config_max_more_keys_column">5</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_fadein_anim_time">0</integer>
|
||||||
<integer name="config_more_keys_keyboard_fadeout_anim_time">100</integer>
|
<integer name="config_more_keys_keyboard_fadeout_anim_time">100</integer>
|
||||||
|
|
|
@ -139,4 +139,9 @@
|
||||||
<string name="spoken_symbol_unknown">Unknown symbol</string>
|
<string name="spoken_symbol_unknown">Unknown symbol</string>
|
||||||
<!-- Spoken description for unknown emoji code point. -->
|
<!-- Spoken description for unknown emoji code point. -->
|
||||||
<string name="spoken_emoji_unknown">Unknown emoji</string>
|
<string name="spoken_emoji_unknown">Unknown emoji</string>
|
||||||
|
|
||||||
|
<!-- Spoken descriptions when opening a more keys keyboard that has alternative characters. -->
|
||||||
|
<string name="spoken_open_more_keys_keyboard">Alternative characters are available</string>
|
||||||
|
<!-- Spoken descriptions when closing a more keys keyboard that has alternative characters. -->
|
||||||
|
<string name="spoken_close_more_keys_keyboard">Alternative characters are dismissed</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2014 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.inputmethod.accessibility;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Message;
|
||||||
|
|
||||||
|
import com.android.inputmethod.keyboard.Key;
|
||||||
|
import com.android.inputmethod.latin.R;
|
||||||
|
|
||||||
|
// Handling long press timer to show a more keys keyboard.
|
||||||
|
final class AccessibilityLongPressTimer extends Handler {
|
||||||
|
public interface LongPressTimerCallback {
|
||||||
|
public void onLongPressed(Key key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int MSG_LONG_PRESS = 1;
|
||||||
|
|
||||||
|
private final LongPressTimerCallback mCallback;
|
||||||
|
private final long mConfigAccessibilityLongPressTimeout;
|
||||||
|
|
||||||
|
public AccessibilityLongPressTimer(final LongPressTimerCallback callback,
|
||||||
|
final Context context) {
|
||||||
|
super();
|
||||||
|
mCallback = callback;
|
||||||
|
mConfigAccessibilityLongPressTimeout = context.getResources().getInteger(
|
||||||
|
R.integer.config_accessibility_long_press_key_timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(final Message msg) {
|
||||||
|
switch (msg.what) {
|
||||||
|
case MSG_LONG_PRESS:
|
||||||
|
cancelLongPress();
|
||||||
|
mCallback.onLongPressed((Key)msg.obj);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
super.handleMessage(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startLongPress(final Key key) {
|
||||||
|
cancelLongPress();
|
||||||
|
final Message longPressMessage = obtainMessage(MSG_LONG_PRESS, key);
|
||||||
|
sendMessageDelayed(longPressMessage, mConfigAccessibilityLongPressTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelLongPress() {
|
||||||
|
removeMessages(MSG_LONG_PRESS);
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,14 +33,29 @@ import com.android.inputmethod.keyboard.Keyboard;
|
||||||
import com.android.inputmethod.keyboard.KeyboardView;
|
import com.android.inputmethod.keyboard.KeyboardView;
|
||||||
import com.android.inputmethod.keyboard.PointerTracker;
|
import com.android.inputmethod.keyboard.PointerTracker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a delegate that can be registered in a class that extends
|
||||||
|
* {@link KeyboardView} to enhance accessibility support via composition rather via inheritance.
|
||||||
|
*
|
||||||
|
* To implement accessibility mode, the target keyboard view has to:<p>
|
||||||
|
* - Call {@link #setKeyboard(Keyboard)} when a new keyboard is set to the keyboard view.
|
||||||
|
* - Dispatch a hover event by calling {@link #onHoverEnter(MotionEvent)}.
|
||||||
|
*
|
||||||
|
* @param <KV> The keyboard view class type.
|
||||||
|
*/
|
||||||
public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
||||||
extends AccessibilityDelegateCompat {
|
extends AccessibilityDelegateCompat {
|
||||||
|
private static final String TAG = KeyboardAccessibilityDelegate.class.getSimpleName();
|
||||||
|
protected static final boolean DEBUG_HOVER = false;
|
||||||
|
|
||||||
protected final KV mKeyboardView;
|
protected final KV mKeyboardView;
|
||||||
protected final KeyDetector mKeyDetector;
|
protected final KeyDetector mKeyDetector;
|
||||||
private Keyboard mKeyboard;
|
private Keyboard mKeyboard;
|
||||||
private KeyboardAccessibilityNodeProvider mAccessibilityNodeProvider;
|
private KeyboardAccessibilityNodeProvider mAccessibilityNodeProvider;
|
||||||
private Key mLastHoverKey;
|
private Key mLastHoverKey;
|
||||||
|
|
||||||
|
public static final int HOVER_EVENT_POINTER_ID = 0;
|
||||||
|
|
||||||
public KeyboardAccessibilityDelegate(final KV keyboardView, final KeyDetector keyDetector) {
|
public KeyboardAccessibilityDelegate(final KV keyboardView, final KeyDetector keyDetector) {
|
||||||
super();
|
super();
|
||||||
mKeyboardView = keyboardView;
|
mKeyboardView = keyboardView;
|
||||||
|
@ -180,8 +195,11 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
||||||
*/
|
*/
|
||||||
protected void onHoverEnter(final MotionEvent event) {
|
protected void onHoverEnter(final MotionEvent event) {
|
||||||
final Key key = getHoverKeyOf(event);
|
final Key key = getHoverKeyOf(event);
|
||||||
|
if (DEBUG_HOVER) {
|
||||||
|
Log.d(TAG, "onHoverEnter: key=" + key);
|
||||||
|
}
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
onHoverEnterKey(key);
|
onHoverEnterTo(key);
|
||||||
}
|
}
|
||||||
setLastHoverKey(key);
|
setLastHoverKey(key);
|
||||||
}
|
}
|
||||||
|
@ -196,14 +214,14 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
||||||
final Key key = getHoverKeyOf(event);
|
final Key key = getHoverKeyOf(event);
|
||||||
if (key != lastKey) {
|
if (key != lastKey) {
|
||||||
if (lastKey != null) {
|
if (lastKey != null) {
|
||||||
onHoverExitKey(lastKey);
|
onHoverExitFrom(lastKey);
|
||||||
}
|
}
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
onHoverEnterKey(key);
|
onHoverEnterTo(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
onHoverMoveKey(key);
|
onHoverMoveWithin(key);
|
||||||
}
|
}
|
||||||
setLastHoverKey(key);
|
setLastHoverKey(key);
|
||||||
}
|
}
|
||||||
|
@ -215,15 +233,18 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
||||||
*/
|
*/
|
||||||
protected void onHoverExit(final MotionEvent event) {
|
protected void onHoverExit(final MotionEvent event) {
|
||||||
final Key lastKey = getLastHoverKey();
|
final Key lastKey = getLastHoverKey();
|
||||||
|
if (DEBUG_HOVER) {
|
||||||
|
Log.d(TAG, "onHoverExit: key=" + getHoverKeyOf(event) + " last=" + lastKey);
|
||||||
|
}
|
||||||
if (lastKey != null) {
|
if (lastKey != null) {
|
||||||
onHoverExitKey(lastKey);
|
onHoverExitFrom(lastKey);
|
||||||
}
|
}
|
||||||
final Key key = getHoverKeyOf(event);
|
final Key key = getHoverKeyOf(event);
|
||||||
// Make sure we're not getting an EXIT event because the user slid
|
// 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.
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
onRegisterHoverKey(key, event);
|
onRegisterHoverKey(key, event);
|
||||||
onHoverExitKey(key);
|
onHoverExitFrom(key);
|
||||||
}
|
}
|
||||||
setLastHoverKey(null);
|
setLastHoverKey(null);
|
||||||
}
|
}
|
||||||
|
@ -235,6 +256,9 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
||||||
* @param event A hover exit event that triggers key registering.
|
* @param event A hover exit event that triggers key registering.
|
||||||
*/
|
*/
|
||||||
protected void onRegisterHoverKey(final Key key, final MotionEvent event) {
|
protected void onRegisterHoverKey(final Key key, final MotionEvent event) {
|
||||||
|
if (DEBUG_HOVER) {
|
||||||
|
Log.d(TAG, "onRegisterHoverKey: key=" + key);
|
||||||
|
}
|
||||||
simulateTouchEvent(MotionEvent.ACTION_DOWN, event);
|
simulateTouchEvent(MotionEvent.ACTION_DOWN, event);
|
||||||
simulateTouchEvent(MotionEvent.ACTION_UP, event);
|
simulateTouchEvent(MotionEvent.ACTION_UP, event);
|
||||||
}
|
}
|
||||||
|
@ -274,7 +298,10 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
||||||
*
|
*
|
||||||
* @param key The currently hovered key.
|
* @param key The currently hovered key.
|
||||||
*/
|
*/
|
||||||
protected void onHoverEnterKey(final Key key) {
|
protected void onHoverEnterTo(final Key key) {
|
||||||
|
if (DEBUG_HOVER) {
|
||||||
|
Log.d(TAG, "onHoverEnterTo: key=" + key);
|
||||||
|
}
|
||||||
key.onPressed();
|
key.onPressed();
|
||||||
mKeyboardView.invalidateKey(key);
|
mKeyboardView.invalidateKey(key);
|
||||||
final KeyboardAccessibilityNodeProvider provider = getAccessibilityNodeProvider();
|
final KeyboardAccessibilityNodeProvider provider = getAccessibilityNodeProvider();
|
||||||
|
@ -287,14 +314,17 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
||||||
*
|
*
|
||||||
* @param key The currently hovered key.
|
* @param key The currently hovered key.
|
||||||
*/
|
*/
|
||||||
protected void onHoverMoveKey(final Key key) { }
|
protected void onHoverMoveWithin(final Key key) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a hover exit event on a key.
|
* Handles a hover exit event on a key.
|
||||||
*
|
*
|
||||||
* @param key The currently hovered key.
|
* @param key The currently hovered key.
|
||||||
*/
|
*/
|
||||||
protected void onHoverExitKey(final Key key) {
|
protected void onHoverExitFrom(final Key key) {
|
||||||
|
if (DEBUG_HOVER) {
|
||||||
|
Log.d(TAG, "onHoverExitFrom: key=" + key);
|
||||||
|
}
|
||||||
key.onReleased();
|
key.onReleased();
|
||||||
mKeyboardView.invalidateKey(key);
|
mKeyboardView.invalidateKey(key);
|
||||||
final KeyboardAccessibilityNodeProvider provider = getAccessibilityNodeProvider();
|
final KeyboardAccessibilityNodeProvider provider = getAccessibilityNodeProvider();
|
||||||
|
|
|
@ -17,17 +17,29 @@
|
||||||
package com.android.inputmethod.accessibility;
|
package com.android.inputmethod.accessibility;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.util.Log;
|
||||||
import android.util.SparseIntArray;
|
import android.util.SparseIntArray;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
|
import com.android.inputmethod.keyboard.Key;
|
||||||
import com.android.inputmethod.keyboard.KeyDetector;
|
import com.android.inputmethod.keyboard.KeyDetector;
|
||||||
import com.android.inputmethod.keyboard.Keyboard;
|
import com.android.inputmethod.keyboard.Keyboard;
|
||||||
import com.android.inputmethod.keyboard.KeyboardId;
|
import com.android.inputmethod.keyboard.KeyboardId;
|
||||||
import com.android.inputmethod.keyboard.MainKeyboardView;
|
import com.android.inputmethod.keyboard.MainKeyboardView;
|
||||||
|
import com.android.inputmethod.keyboard.PointerTracker;
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a delegate that can be registered in {@link MainKeyboardView} to enhance
|
||||||
|
* accessibility support via composition rather via inheritance.
|
||||||
|
*/
|
||||||
public final class MainKeyboardAccessibilityDelegate
|
public final class MainKeyboardAccessibilityDelegate
|
||||||
extends KeyboardAccessibilityDelegate<MainKeyboardView> {
|
extends KeyboardAccessibilityDelegate<MainKeyboardView>
|
||||||
|
implements AccessibilityLongPressTimer.LongPressTimerCallback {
|
||||||
|
private static final String TAG = MainKeyboardAccessibilityDelegate.class.getSimpleName();
|
||||||
|
|
||||||
/** Map of keyboard modes to resource IDs. */
|
/** Map of keyboard modes to resource IDs. */
|
||||||
private static final SparseIntArray KEYBOARD_MODE_RES_IDS = new SparseIntArray();
|
private static final SparseIntArray KEYBOARD_MODE_RES_IDS = new SparseIntArray();
|
||||||
|
|
||||||
|
@ -46,10 +58,15 @@ public final class MainKeyboardAccessibilityDelegate
|
||||||
/** The most recently set keyboard mode. */
|
/** The most recently set keyboard mode. */
|
||||||
private int mLastKeyboardMode = KEYBOARD_IS_HIDDEN;
|
private int mLastKeyboardMode = KEYBOARD_IS_HIDDEN;
|
||||||
private static final int KEYBOARD_IS_HIDDEN = -1;
|
private static final int KEYBOARD_IS_HIDDEN = -1;
|
||||||
|
private boolean mShouldIgnoreOnRegisterHoverKey;
|
||||||
|
|
||||||
|
private final AccessibilityLongPressTimer mAccessibilityLongPressTimer;
|
||||||
|
|
||||||
public MainKeyboardAccessibilityDelegate(final MainKeyboardView mainKeyboardView,
|
public MainKeyboardAccessibilityDelegate(final MainKeyboardView mainKeyboardView,
|
||||||
final KeyDetector keyDetector) {
|
final KeyDetector keyDetector) {
|
||||||
super(mainKeyboardView, keyDetector);
|
super(mainKeyboardView, keyDetector);
|
||||||
|
mAccessibilityLongPressTimer = new AccessibilityLongPressTimer(
|
||||||
|
this /* callback */, mainKeyboardView.getContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -172,4 +189,63 @@ public final class MainKeyboardAccessibilityDelegate
|
||||||
private void announceKeyboardHidden() {
|
private void announceKeyboardHidden() {
|
||||||
sendWindowStateChanged(R.string.announce_keyboard_hidden);
|
sendWindowStateChanged(R.string.announce_keyboard_hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onRegisterHoverKey(final Key key, final MotionEvent event) {
|
||||||
|
if (DEBUG_HOVER) {
|
||||||
|
Log.d(TAG, "onRegisterHoverKey: key=" + key + " ignore="
|
||||||
|
+ mShouldIgnoreOnRegisterHoverKey);
|
||||||
|
}
|
||||||
|
if (!mShouldIgnoreOnRegisterHoverKey) {
|
||||||
|
super.onRegisterHoverKey(key, event);
|
||||||
|
}
|
||||||
|
mShouldIgnoreOnRegisterHoverKey = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onHoverEnterTo(final Key key) {
|
||||||
|
if (DEBUG_HOVER) {
|
||||||
|
Log.d(TAG, "onHoverEnterTo: key=" + key);
|
||||||
|
}
|
||||||
|
mAccessibilityLongPressTimer.cancelLongPress();
|
||||||
|
super.onHoverEnterTo(key);
|
||||||
|
if (key.isLongPressEnabled()) {
|
||||||
|
mAccessibilityLongPressTimer.startLongPress(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onHoverExitFrom(final Key key) {
|
||||||
|
if (DEBUG_HOVER) {
|
||||||
|
Log.d(TAG, "onHoverExitFrom: key=" + key);
|
||||||
|
}
|
||||||
|
mAccessibilityLongPressTimer.cancelLongPress();
|
||||||
|
super.onHoverExitFrom(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLongPressed(final Key key) {
|
||||||
|
if (DEBUG_HOVER) {
|
||||||
|
Log.d(TAG, "onLongPressed: key=" + key);
|
||||||
|
}
|
||||||
|
final PointerTracker tracker = PointerTracker.getPointerTracker(HOVER_EVENT_POINTER_ID);
|
||||||
|
final long eventTime = SystemClock.uptimeMillis();
|
||||||
|
final int x = key.getHitBox().centerX();
|
||||||
|
final int y = key.getHitBox().centerY();
|
||||||
|
final MotionEvent downEvent = MotionEvent.obtain(
|
||||||
|
eventTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0 /* metaState */);
|
||||||
|
// Inject a fake down event to {@link PointerTracker} to handle a long press correctly.
|
||||||
|
tracker.processMotionEvent(downEvent, mKeyDetector);
|
||||||
|
// The above fake down event triggers an unnecessary long press timer that should be
|
||||||
|
// canceled.
|
||||||
|
tracker.cancelLongPressTimer();
|
||||||
|
downEvent.recycle();
|
||||||
|
// Invoke {@link MainKeyboardView#onLongPress(PointerTracker)} as if a long press timeout
|
||||||
|
// has passed.
|
||||||
|
mKeyboardView.onLongPress(tracker);
|
||||||
|
// 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.
|
||||||
|
mShouldIgnoreOnRegisterHoverKey = !tracker.isInOperation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2014 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.inputmethod.accessibility;
|
||||||
|
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
|
import com.android.inputmethod.keyboard.Key;
|
||||||
|
import com.android.inputmethod.keyboard.KeyDetector;
|
||||||
|
import com.android.inputmethod.keyboard.MoreKeysKeyboardView;
|
||||||
|
import com.android.inputmethod.latin.Constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a delegate that can be registered in {@link MoreKeysKeyboardView} to
|
||||||
|
* enhance accessibility support via composition rather via inheritance.
|
||||||
|
*/
|
||||||
|
public class MoreKeysKeyboardAccessibilityDelegate
|
||||||
|
extends KeyboardAccessibilityDelegate<MoreKeysKeyboardView> {
|
||||||
|
private static final String TAG = MoreKeysKeyboardAccessibilityDelegate.class.getSimpleName();
|
||||||
|
|
||||||
|
private final Rect mMoreKeysKeyboardValidBounds = new Rect();
|
||||||
|
private static final int CLOSING_INSET_IN_PIXEL = 1;
|
||||||
|
private int mOpenAnnounceResId;
|
||||||
|
private int mCloseAnnounceResId;
|
||||||
|
|
||||||
|
public MoreKeysKeyboardAccessibilityDelegate(final MoreKeysKeyboardView moreKeysKeyboardView,
|
||||||
|
final KeyDetector keyDetector) {
|
||||||
|
super(moreKeysKeyboardView, keyDetector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOpenAnnounce(final int resId) {
|
||||||
|
mOpenAnnounceResId = resId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCloseAnnounce(final int resId) {
|
||||||
|
mCloseAnnounceResId = resId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onShowMoreKeysKeyboard() {
|
||||||
|
sendWindowStateChanged(mOpenAnnounceResId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onHoverEnter(final MotionEvent event) {
|
||||||
|
if (DEBUG_HOVER) {
|
||||||
|
Log.d(TAG, "onHoverEnter: key=" + getHoverKeyOf(event));
|
||||||
|
}
|
||||||
|
super.onHoverEnter(event);
|
||||||
|
final int actionIndex = event.getActionIndex();
|
||||||
|
final int x = (int)event.getX(actionIndex);
|
||||||
|
final int y = (int)event.getY(actionIndex);
|
||||||
|
final int pointerId = event.getPointerId(actionIndex);
|
||||||
|
final long eventTime = event.getEventTime();
|
||||||
|
mKeyboardView.onDownEvent(x, y, pointerId, eventTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onHoverMove(final MotionEvent event) {
|
||||||
|
super.onHoverMove(event);
|
||||||
|
final int actionIndex = event.getActionIndex();
|
||||||
|
final int x = (int)event.getX(actionIndex);
|
||||||
|
final int y = (int)event.getY(actionIndex);
|
||||||
|
final int pointerId = event.getPointerId(actionIndex);
|
||||||
|
final long eventTime = event.getEventTime();
|
||||||
|
mKeyboardView.onMoveEvent(x, y, pointerId, eventTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onHoverExit(final MotionEvent event) {
|
||||||
|
final Key lastKey = getLastHoverKey();
|
||||||
|
if (DEBUG_HOVER) {
|
||||||
|
Log.d(TAG, "onHoverExit: key=" + getHoverKeyOf(event) + " last=" + lastKey);
|
||||||
|
}
|
||||||
|
if (lastKey != null) {
|
||||||
|
super.onHoverExitFrom(lastKey);
|
||||||
|
}
|
||||||
|
setLastHoverKey(null);
|
||||||
|
final int actionIndex = event.getActionIndex();
|
||||||
|
final int x = (int)event.getX(actionIndex);
|
||||||
|
final int y = (int)event.getY(actionIndex);
|
||||||
|
final int pointerId = event.getPointerId(actionIndex);
|
||||||
|
final long eventTime = event.getEventTime();
|
||||||
|
// A hover exit event at one pixel width or height area on the edges of more keys keyboard
|
||||||
|
// are treated as closing.
|
||||||
|
mMoreKeysKeyboardValidBounds.set(0, 0, mKeyboardView.getWidth(), mKeyboardView.getHeight());
|
||||||
|
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.
|
||||||
|
mKeyboardView.onUpEvent(x, y, pointerId, eventTime);
|
||||||
|
mKeyboardView.dismissMoreKeysPanel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Close the more keys keyboard.
|
||||||
|
mKeyboardView.onMoveEvent(
|
||||||
|
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, pointerId, eventTime);
|
||||||
|
sendWindowStateChanged(mCloseAnnounceResId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,12 +17,13 @@
|
||||||
package com.android.inputmethod.keyboard;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.android.inputmethod.accessibility.AccessibilityUtils;
|
||||||
|
import com.android.inputmethod.accessibility.MoreKeysKeyboardAccessibilityDelegate;
|
||||||
import com.android.inputmethod.latin.Constants;
|
import com.android.inputmethod.latin.Constants;
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.utils.CoordinateUtils;
|
import com.android.inputmethod.latin.utils.CoordinateUtils;
|
||||||
|
@ -34,7 +35,7 @@ import com.android.inputmethod.latin.utils.CoordinateUtils;
|
||||||
public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel {
|
public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel {
|
||||||
private final int[] mCoordinates = CoordinateUtils.newInstance();
|
private final int[] mCoordinates = CoordinateUtils.newInstance();
|
||||||
|
|
||||||
protected final KeyDetector mKeyDetector;
|
protected KeyDetector mKeyDetector;
|
||||||
private Controller mController = EMPTY_CONTROLLER;
|
private Controller mController = EMPTY_CONTROLLER;
|
||||||
protected KeyboardActionListener mListener;
|
protected KeyboardActionListener mListener;
|
||||||
private int mOriginX;
|
private int mOriginX;
|
||||||
|
@ -43,6 +44,8 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
|
||||||
|
|
||||||
private int mActivePointerId;
|
private int mActivePointerId;
|
||||||
|
|
||||||
|
private MoreKeysKeyboardAccessibilityDelegate mAccessibilityDelegate;
|
||||||
|
|
||||||
public MoreKeysKeyboardView(final Context context, final AttributeSet attrs) {
|
public MoreKeysKeyboardView(final Context context, final AttributeSet attrs) {
|
||||||
this(context, attrs, R.attr.moreKeysKeyboardViewStyle);
|
this(context, attrs, R.attr.moreKeysKeyboardViewStyle);
|
||||||
}
|
}
|
||||||
|
@ -50,10 +53,8 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
|
||||||
public MoreKeysKeyboardView(final Context context, final AttributeSet attrs,
|
public MoreKeysKeyboardView(final Context context, final AttributeSet attrs,
|
||||||
final int defStyle) {
|
final int defStyle) {
|
||||||
super(context, attrs, defStyle);
|
super(context, attrs, defStyle);
|
||||||
|
mKeyDetector = new MoreKeysDetector(getResources().getDimension(
|
||||||
final Resources res = context.getResources();
|
R.dimen.config_more_keys_keyboard_slide_allowance));
|
||||||
mKeyDetector = new MoreKeysDetector(
|
|
||||||
res.getDimension(R.dimen.config_more_keys_keyboard_slide_allowance));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -71,8 +72,23 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
|
||||||
@Override
|
@Override
|
||||||
public void setKeyboard(final Keyboard keyboard) {
|
public void setKeyboard(final Keyboard keyboard) {
|
||||||
super.setKeyboard(keyboard);
|
super.setKeyboard(keyboard);
|
||||||
mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
|
if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) {
|
||||||
-getPaddingTop() + getVerticalCorrection());
|
// With accessibility mode on, any hover event outside {@link MoreKeysKeyboardView} is
|
||||||
|
// discarded at {@link InputView#dispatchHoverEvent(MotionEvent)}. Because only a hover
|
||||||
|
// event that is on this view is dispatched by the platform, we should use a
|
||||||
|
// {@link KeyDetector} that has no sliding allowance and no hysteresis.
|
||||||
|
mKeyDetector = new KeyDetector();
|
||||||
|
mAccessibilityDelegate = new MoreKeysKeyboardAccessibilityDelegate(this, mKeyDetector);
|
||||||
|
mAccessibilityDelegate.setOpenAnnounce(R.string.spoken_open_more_keys_keyboard);
|
||||||
|
mAccessibilityDelegate.setCloseAnnounce(R.string.spoken_close_more_keys_keyboard);
|
||||||
|
mAccessibilityDelegate.setKeyboard(keyboard);
|
||||||
|
} else {
|
||||||
|
mKeyDetector = new MoreKeysDetector(getResources().getDimension(
|
||||||
|
R.dimen.config_more_keys_keyboard_slide_allowance));
|
||||||
|
mAccessibilityDelegate = null;
|
||||||
|
}
|
||||||
|
mKeyDetector.setKeyboard(
|
||||||
|
keyboard, -getPaddingLeft(), -getPaddingTop() + getVerticalCorrection());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -98,6 +114,10 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
|
||||||
mOriginX = x + container.getPaddingLeft();
|
mOriginX = x + container.getPaddingLeft();
|
||||||
mOriginY = y + container.getPaddingTop();
|
mOriginY = y + container.getPaddingTop();
|
||||||
controller.onShowMoreKeysPanel(this);
|
controller.onShowMoreKeysPanel(this);
|
||||||
|
final MoreKeysKeyboardAccessibilityDelegate accessibilityDelegate = mAccessibilityDelegate;
|
||||||
|
if (accessibilityDelegate != null) {
|
||||||
|
accessibilityDelegate.onShowMoreKeysKeyboard();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -228,6 +248,18 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onHoverEvent(final MotionEvent event) {
|
||||||
|
final MoreKeysKeyboardAccessibilityDelegate accessibilityDelegate = mAccessibilityDelegate;
|
||||||
|
if (accessibilityDelegate != null) {
|
||||||
|
return accessibilityDelegate.onHoverEvent(event);
|
||||||
|
}
|
||||||
|
return super.onHoverEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
private View getContainerView() {
|
private View getContainerView() {
|
||||||
return (View)getParent();
|
return (View)getParent();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1078,6 +1078,14 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
|
||||||
mIsTrackingForActionDisabled = true;
|
mIsTrackingForActionDisabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isInOperation() {
|
||||||
|
return !mIsTrackingForActionDisabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelLongPressTimer() {
|
||||||
|
sTimerProxy.cancelLongPressTimerOf(this);
|
||||||
|
}
|
||||||
|
|
||||||
public void onLongPressed() {
|
public void onLongPressed() {
|
||||||
resetKeySelectionByDraggingFinger();
|
resetKeySelectionByDraggingFinger();
|
||||||
cancelTrackingForAction();
|
cancelTrackingForAction();
|
||||||
|
|
|
@ -23,12 +23,14 @@ import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import com.android.inputmethod.accessibility.AccessibilityUtils;
|
||||||
import com.android.inputmethod.keyboard.MainKeyboardView;
|
import com.android.inputmethod.keyboard.MainKeyboardView;
|
||||||
import com.android.inputmethod.latin.suggestions.MoreSuggestionsView;
|
import com.android.inputmethod.latin.suggestions.MoreSuggestionsView;
|
||||||
import com.android.inputmethod.latin.suggestions.SuggestionStripView;
|
import com.android.inputmethod.latin.suggestions.SuggestionStripView;
|
||||||
|
|
||||||
public final class InputView extends LinearLayout {
|
public final class InputView extends LinearLayout {
|
||||||
private final Rect mInputViewRect = new Rect();
|
private final Rect mInputViewRect = new Rect();
|
||||||
|
private MainKeyboardView mMainKeyboardView;
|
||||||
private KeyboardTopPaddingForwarder mKeyboardTopPaddingForwarder;
|
private KeyboardTopPaddingForwarder mKeyboardTopPaddingForwarder;
|
||||||
private MoreSuggestionsViewCanceler mMoreSuggestionsViewCanceler;
|
private MoreSuggestionsViewCanceler mMoreSuggestionsViewCanceler;
|
||||||
private MotionEventForwarder<?, ?> mActiveForwarder;
|
private MotionEventForwarder<?, ?> mActiveForwarder;
|
||||||
|
@ -41,18 +43,28 @@ public final class InputView extends LinearLayout {
|
||||||
protected void onFinishInflate() {
|
protected void onFinishInflate() {
|
||||||
final SuggestionStripView suggestionStripView =
|
final SuggestionStripView suggestionStripView =
|
||||||
(SuggestionStripView)findViewById(R.id.suggestion_strip_view);
|
(SuggestionStripView)findViewById(R.id.suggestion_strip_view);
|
||||||
final MainKeyboardView mainKeyboardView =
|
mMainKeyboardView = (MainKeyboardView)findViewById(R.id.keyboard_view);
|
||||||
(MainKeyboardView)findViewById(R.id.keyboard_view);
|
|
||||||
mKeyboardTopPaddingForwarder = new KeyboardTopPaddingForwarder(
|
mKeyboardTopPaddingForwarder = new KeyboardTopPaddingForwarder(
|
||||||
mainKeyboardView, suggestionStripView);
|
mMainKeyboardView, suggestionStripView);
|
||||||
mMoreSuggestionsViewCanceler = new MoreSuggestionsViewCanceler(
|
mMoreSuggestionsViewCanceler = new MoreSuggestionsViewCanceler(
|
||||||
mainKeyboardView, suggestionStripView);
|
mMainKeyboardView, suggestionStripView);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKeyboardTopPadding(final int keyboardTopPadding) {
|
public void setKeyboardTopPadding(final int keyboardTopPadding) {
|
||||||
mKeyboardTopPaddingForwarder.setKeyboardTopPadding(keyboardTopPadding);
|
mKeyboardTopPaddingForwarder.setKeyboardTopPadding(keyboardTopPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean dispatchHoverEvent(final MotionEvent event) {
|
||||||
|
if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()
|
||||||
|
&& mMainKeyboardView.isShowingMoreKeysPanel()) {
|
||||||
|
// With accessibility mode on, discard hover events while a more keys keyboard is shown.
|
||||||
|
// The {@link MoreKeysKeyboard} receives hover events directly from the platform.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.dispatchHoverEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onInterceptTouchEvent(final MotionEvent me) {
|
public boolean onInterceptTouchEvent(final MotionEvent me) {
|
||||||
final Rect rect = mInputViewRect;
|
final Rect rect = mInputViewRect;
|
||||||
|
|
Loading…
Reference in a new issue