Support performAccessibilityAction for CLICK and LONG_CLICK
Bug: 15727335 Change-Id: I83274c1a9d3cf2e8237d1674fe915b7b2d222a53
This commit is contained in:
parent
c9c3ea0b68
commit
1e31672295
4 changed files with 47 additions and 27 deletions
|
@ -26,7 +26,7 @@ import com.android.inputmethod.latin.R;
|
||||||
// Handling long press timer to show a more keys keyboard.
|
// Handling long press timer to show a more keys keyboard.
|
||||||
final class AccessibilityLongPressTimer extends Handler {
|
final class AccessibilityLongPressTimer extends Handler {
|
||||||
public interface LongPressTimerCallback {
|
public interface LongPressTimerCallback {
|
||||||
public void onLongPressed(Key key);
|
public void performLongClickOn(Key key);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int MSG_LONG_PRESS = 1;
|
private static final int MSG_LONG_PRESS = 1;
|
||||||
|
@ -47,7 +47,7 @@ final class AccessibilityLongPressTimer extends Handler {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case MSG_LONG_PRESS:
|
case MSG_LONG_PRESS:
|
||||||
cancelLongPress();
|
cancelLongPress();
|
||||||
mCallback.onLongPressed((Key)msg.obj);
|
mCallback.performLongClickOn((Key)msg.obj);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
super.handleMessage(msg);
|
super.handleMessage(msg);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package com.android.inputmethod.accessibility;
|
package com.android.inputmethod.accessibility;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.support.v4.view.AccessibilityDelegateCompat;
|
import android.support.v4.view.AccessibilityDelegateCompat;
|
||||||
import android.support.v4.view.ViewCompat;
|
import android.support.v4.view.ViewCompat;
|
||||||
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
|
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
|
||||||
|
@ -49,7 +50,7 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
||||||
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<KV> mAccessibilityNodeProvider;
|
||||||
private Key mLastHoverKey;
|
private Key mLastHoverKey;
|
||||||
|
|
||||||
public static final int HOVER_EVENT_POINTER_ID = 0;
|
public static final int HOVER_EVENT_POINTER_ID = 0;
|
||||||
|
@ -132,19 +133,20 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
||||||
* @return The accessibility node provider for the current keyboard.
|
* @return The accessibility node provider for the current keyboard.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public KeyboardAccessibilityNodeProvider getAccessibilityNodeProvider(final View host) {
|
public KeyboardAccessibilityNodeProvider<KV> getAccessibilityNodeProvider(final View host) {
|
||||||
return getAccessibilityNodeProvider();
|
return getAccessibilityNodeProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A lazily-instantiated node provider for this view delegate.
|
* @return A lazily-instantiated node provider for this view delegate.
|
||||||
*/
|
*/
|
||||||
protected KeyboardAccessibilityNodeProvider getAccessibilityNodeProvider() {
|
protected KeyboardAccessibilityNodeProvider<KV> getAccessibilityNodeProvider() {
|
||||||
// Instantiate the provide only when requested. Since the system
|
// Instantiate the provide only when requested. Since the system
|
||||||
// will call this method multiple times it is a good practice to
|
// will call this method multiple times it is a good practice to
|
||||||
// cache the provider instance.
|
// cache the provider instance.
|
||||||
if (mAccessibilityNodeProvider == null) {
|
if (mAccessibilityNodeProvider == null) {
|
||||||
mAccessibilityNodeProvider = new KeyboardAccessibilityNodeProvider(mKeyboardView);
|
mAccessibilityNodeProvider =
|
||||||
|
new KeyboardAccessibilityNodeProvider<>(mKeyboardView, this);
|
||||||
}
|
}
|
||||||
return mAccessibilityNodeProvider;
|
return mAccessibilityNodeProvider;
|
||||||
}
|
}
|
||||||
|
@ -241,35 +243,37 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
||||||
// 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);
|
performClickOn(key);
|
||||||
onHoverExitFrom(key);
|
onHoverExitFrom(key);
|
||||||
}
|
}
|
||||||
setLastHoverKey(null);
|
setLastHoverKey(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a key that is selected by a hover event
|
* Perform click on a key.
|
||||||
*
|
*
|
||||||
* @param key A key to be registered.
|
* @param key A key to be registered.
|
||||||
* @param event A hover exit event that triggers key registering.
|
|
||||||
*/
|
*/
|
||||||
protected void onRegisterHoverKey(final Key key, final MotionEvent event) {
|
public void performClickOn(final Key key) {
|
||||||
if (DEBUG_HOVER) {
|
if (DEBUG_HOVER) {
|
||||||
Log.d(TAG, "onRegisterHoverKey: key=" + key);
|
Log.d(TAG, "performClickOn: key=" + key);
|
||||||
}
|
}
|
||||||
simulateTouchEvent(MotionEvent.ACTION_DOWN, event);
|
simulateTouchEvent(MotionEvent.ACTION_DOWN, key);
|
||||||
simulateTouchEvent(MotionEvent.ACTION_UP, event);
|
simulateTouchEvent(MotionEvent.ACTION_UP, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulating a touch event by injecting a synthesized touch event into {@link KeyboardView}.
|
* Simulating a touch event by injecting a synthesized touch event into {@link KeyboardView}.
|
||||||
*
|
*
|
||||||
* @param touchAction The action of the synthesizing touch event.
|
* @param touchAction The action of the synthesizing touch event.
|
||||||
* @param hoverEvent The base hover event from that the touch event is synthesized.
|
* @param key The key that a synthesized touch event is on.
|
||||||
*/
|
*/
|
||||||
private void simulateTouchEvent(final int touchAction, final MotionEvent hoverEvent) {
|
private void simulateTouchEvent(final int touchAction, final Key key) {
|
||||||
final MotionEvent touchEvent = MotionEvent.obtain(hoverEvent);
|
final int x = key.getHitBox().centerX();
|
||||||
touchEvent.setAction(touchAction);
|
final int y = key.getHitBox().centerY();
|
||||||
|
final long eventTime = SystemClock.uptimeMillis();
|
||||||
|
final MotionEvent touchEvent = MotionEvent.obtain(
|
||||||
|
eventTime, eventTime, touchAction, x, y, 0 /* metaState */);
|
||||||
mKeyboardView.onTouchEvent(touchEvent);
|
mKeyboardView.onTouchEvent(touchEvent);
|
||||||
touchEvent.recycle();
|
touchEvent.recycle();
|
||||||
}
|
}
|
||||||
|
@ -285,7 +289,7 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
||||||
}
|
}
|
||||||
key.onPressed();
|
key.onPressed();
|
||||||
mKeyboardView.invalidateKey(key);
|
mKeyboardView.invalidateKey(key);
|
||||||
final KeyboardAccessibilityNodeProvider provider = getAccessibilityNodeProvider();
|
final KeyboardAccessibilityNodeProvider<KV> provider = getAccessibilityNodeProvider();
|
||||||
provider.onHoverEnterTo(key);
|
provider.onHoverEnterTo(key);
|
||||||
provider.performActionForKey(key, AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
|
provider.performActionForKey(key, AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
|
||||||
}
|
}
|
||||||
|
@ -308,7 +312,16 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
||||||
}
|
}
|
||||||
key.onReleased();
|
key.onReleased();
|
||||||
mKeyboardView.invalidateKey(key);
|
mKeyboardView.invalidateKey(key);
|
||||||
final KeyboardAccessibilityNodeProvider provider = getAccessibilityNodeProvider();
|
final KeyboardAccessibilityNodeProvider<KV> provider = getAccessibilityNodeProvider();
|
||||||
provider.onHoverExitFrom(key);
|
provider.onHoverExitFrom(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform long click on a key.
|
||||||
|
*
|
||||||
|
* @param key A key to be long pressed on.
|
||||||
|
*/
|
||||||
|
public void performLongClickOn(final Key key) {
|
||||||
|
// A extended class should override this method to implement long press.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,8 @@ import java.util.List;
|
||||||
* virtual views, thus conveying their logical structure.
|
* virtual views, thus conveying their logical structure.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
final class KeyboardAccessibilityNodeProvider extends AccessibilityNodeProviderCompat {
|
final class KeyboardAccessibilityNodeProvider<KV extends KeyboardView>
|
||||||
|
extends AccessibilityNodeProviderCompat {
|
||||||
private static final String TAG = KeyboardAccessibilityNodeProvider.class.getSimpleName();
|
private static final String TAG = KeyboardAccessibilityNodeProvider.class.getSimpleName();
|
||||||
|
|
||||||
// From {@link android.view.accessibility.AccessibilityNodeInfo#UNDEFINED_ITEM_ID}.
|
// From {@link android.view.accessibility.AccessibilityNodeInfo#UNDEFINED_ITEM_ID}.
|
||||||
|
@ -69,16 +70,20 @@ final class KeyboardAccessibilityNodeProvider extends AccessibilityNodeProviderC
|
||||||
private int mHoveringNodeId = UNDEFINED;
|
private int mHoveringNodeId = UNDEFINED;
|
||||||
|
|
||||||
/** The keyboard view to provide an accessibility node info. */
|
/** The keyboard view to provide an accessibility node info. */
|
||||||
private final KeyboardView mKeyboardView;
|
private final KV mKeyboardView;
|
||||||
|
/** The accessibility delegate. */
|
||||||
|
private final KeyboardAccessibilityDelegate<KV> mDelegate;
|
||||||
|
|
||||||
/** The current keyboard. */
|
/** The current keyboard. */
|
||||||
private Keyboard mKeyboard;
|
private Keyboard mKeyboard;
|
||||||
|
|
||||||
public KeyboardAccessibilityNodeProvider(final KeyboardView keyboardView) {
|
public KeyboardAccessibilityNodeProvider(final KV keyboardView,
|
||||||
|
final KeyboardAccessibilityDelegate<KV> delegate) {
|
||||||
super();
|
super();
|
||||||
mKeyCodeDescriptionMapper = KeyCodeDescriptionMapper.getInstance();
|
mKeyCodeDescriptionMapper = KeyCodeDescriptionMapper.getInstance();
|
||||||
mAccessibilityUtils = AccessibilityUtils.getInstance();
|
mAccessibilityUtils = AccessibilityUtils.getInstance();
|
||||||
mKeyboardView = keyboardView;
|
mKeyboardView = keyboardView;
|
||||||
|
mDelegate = delegate;
|
||||||
|
|
||||||
// Since this class is constructed lazily, we might not get a subsequent
|
// Since this class is constructed lazily, we might not get a subsequent
|
||||||
// call to setKeyboard() and therefore need to call it now.
|
// call to setKeyboard() and therefore need to call it now.
|
||||||
|
@ -287,9 +292,11 @@ final class KeyboardAccessibilityNodeProvider extends AccessibilityNodeProviderC
|
||||||
return true;
|
return true;
|
||||||
case AccessibilityNodeInfoCompat.ACTION_CLICK:
|
case AccessibilityNodeInfoCompat.ACTION_CLICK:
|
||||||
sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_VIEW_CLICKED);
|
sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_VIEW_CLICKED);
|
||||||
|
mDelegate.performClickOn(key);
|
||||||
return true;
|
return true;
|
||||||
case AccessibilityNodeInfoCompat.ACTION_LONG_CLICK:
|
case AccessibilityNodeInfoCompat.ACTION_LONG_CLICK:
|
||||||
sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
|
sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
|
||||||
|
mDelegate.performLongClickOn(key);
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -207,11 +207,11 @@ public final class MainKeyboardAccessibilityDelegate
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onRegisterHoverKey(final Key key, final MotionEvent event) {
|
public void performClickOn(final Key key) {
|
||||||
final int x = key.getHitBox().centerX();
|
final int x = key.getHitBox().centerX();
|
||||||
final int y = key.getHitBox().centerY();
|
final int y = key.getHitBox().centerY();
|
||||||
if (DEBUG_HOVER) {
|
if (DEBUG_HOVER) {
|
||||||
Log.d(TAG, "onRegisterHoverKey: key=" + key
|
Log.d(TAG, "performClickOn: key=" + key
|
||||||
+ " inIgnoreBounds=" + mBoundsToIgnoreHoverEvent.contains(x, y));
|
+ " inIgnoreBounds=" + mBoundsToIgnoreHoverEvent.contains(x, y));
|
||||||
}
|
}
|
||||||
if (mBoundsToIgnoreHoverEvent.contains(x, y)) {
|
if (mBoundsToIgnoreHoverEvent.contains(x, y)) {
|
||||||
|
@ -220,7 +220,7 @@ public final class MainKeyboardAccessibilityDelegate
|
||||||
mBoundsToIgnoreHoverEvent.setEmpty();
|
mBoundsToIgnoreHoverEvent.setEmpty();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
super.onRegisterHoverKey(key, event);
|
super.performClickOn(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -257,9 +257,9 @@ public final class MainKeyboardAccessibilityDelegate
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLongPressed(final Key key) {
|
public void performLongClickOn(final Key key) {
|
||||||
if (DEBUG_HOVER) {
|
if (DEBUG_HOVER) {
|
||||||
Log.d(TAG, "onLongPressed: key=" + key);
|
Log.d(TAG, "performLongClickOn: key=" + key);
|
||||||
}
|
}
|
||||||
final PointerTracker tracker = PointerTracker.getPointerTracker(HOVER_EVENT_POINTER_ID);
|
final PointerTracker tracker = PointerTracker.getPointerTracker(HOVER_EVENT_POINTER_ID);
|
||||||
final long eventTime = SystemClock.uptimeMillis();
|
final long eventTime = SystemClock.uptimeMillis();
|
||||||
|
|
Loading…
Reference in a new issue