mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Support long-click for morekeys with Talkback
This commit is contained in:
parent
db758a975d
commit
2c632bd4bd
@ -29,10 +29,8 @@ import android.view.inputmethod.EditorInfo;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.view.AccessibilityDelegateCompat;
|
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
|
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
|
||||||
import androidx.core.view.accessibility.AccessibilityNodeProviderCompat;
|
|
||||||
import androidx.customview.widget.ExploreByTouchHelper;
|
import androidx.customview.widget.ExploreByTouchHelper;
|
||||||
|
|
||||||
import org.futo.inputmethod.keyboard.Key;
|
import org.futo.inputmethod.keyboard.Key;
|
||||||
@ -121,7 +119,7 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
|||||||
*/
|
*/
|
||||||
protected void sendWindowStateChanged(final String text) {
|
protected void sendWindowStateChanged(final String text) {
|
||||||
final AccessibilityEvent stateChange = AccessibilityEvent.obtain(
|
final AccessibilityEvent stateChange = AccessibilityEvent.obtain(
|
||||||
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
AccessibilityEvent.TYPE_ANNOUNCEMENT);
|
||||||
mKeyboardView.onInitializeAccessibilityEvent(stateChange);
|
mKeyboardView.onInitializeAccessibilityEvent(stateChange);
|
||||||
stateChange.getText().add(text);
|
stateChange.getText().add(text);
|
||||||
stateChange.setContentDescription(null);
|
stateChange.setContentDescription(null);
|
||||||
@ -183,10 +181,14 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
|||||||
node.setFocusable(true);
|
node.setFocusable(true);
|
||||||
node.setScreenReaderFocusable(true);
|
node.setScreenReaderFocusable(true);
|
||||||
|
|
||||||
if(k.isActionKey() || k.getCode() == Constants.CODE_SWITCH_ALPHA_SYMBOL || k.getCode() == Constants.CODE_EMOJI || k.getCode() == Constants.CODE_SYMBOL_SHIFT) {
|
if(k.isActionKey() || k.getCode() == Constants.CODE_SWITCH_ALPHA_SYMBOL || k.getCode() == Constants.CODE_EMOJI || k.getCode() == Constants.CODE_SYMBOL_SHIFT || (k.getCode() >= Constants.CODE_ACTION_0 && k.getCode() <= Constants.CODE_ACTION_MAX)) {
|
||||||
node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
|
node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
|
||||||
|
node.addAction(AccessibilityNodeInfoCompat.ACTION_LONG_CLICK);
|
||||||
node.setClickable(true);
|
node.setClickable(true);
|
||||||
} else {
|
} else {
|
||||||
|
if(k.isLongPressEnabled()) {
|
||||||
|
node.addAction(AccessibilityNodeInfoCompat.ACTION_LONG_CLICK);
|
||||||
|
}
|
||||||
node.setTextEntryKey(true);
|
node.setTextEntryKey(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,6 +202,10 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
|
|||||||
// Handle the click action for the virtual button
|
// Handle the click action for the virtual button
|
||||||
performClickOn(k);
|
performClickOn(k);
|
||||||
return true;
|
return true;
|
||||||
|
} else if(action == AccessibilityNodeInfoCompat.ACTION_LONG_CLICK) {
|
||||||
|
// Show morekeys
|
||||||
|
performLongClickOn(k);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -227,38 +227,6 @@ public final class MainKeyboardAccessibilityDelegate
|
|||||||
Log.d(TAG, "performLongClickOn: 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();
|
mKeyboardView.showMoreKeysKeyboard(key, tracker);
|
||||||
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);
|
|
||||||
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.
|
|
||||||
mBoundsToIgnoreHoverEvent.setEmpty();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// This long press has handled at {@link MainKeyboardView#onLongPress(PointerTracker)}.
|
|
||||||
// We should ignore further hover events on this key.
|
|
||||||
mBoundsToIgnoreHoverEvent.set(key.getHitBox());
|
|
||||||
if (key.getHasNoPanelAutoMoreKey()) {
|
|
||||||
// This long press has registered a code point without showing a more keys keyboard.
|
|
||||||
// We should talk back the code point if possible.
|
|
||||||
final int codePointOfNoPanelAutoMoreKey = key.getMoreKeys().get(0).mCode;
|
|
||||||
final String text = KeyCodeDescriptionMapper.getInstance().getDescriptionForCodePoint(
|
|
||||||
mKeyboardView.getContext(), codePointOfNoPanelAutoMoreKey);
|
|
||||||
if (text != null) {
|
|
||||||
sendWindowStateChanged(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
package org.futo.inputmethod.accessibility;
|
package org.futo.inputmethod.accessibility;
|
||||||
|
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.util.Log;
|
import android.view.HapticFeedbackConstants;
|
||||||
import android.view.MotionEvent;
|
import android.view.SoundEffectConstants;
|
||||||
import android.view.accessibility.AccessibilityEvent;
|
import android.view.accessibility.AccessibilityEvent;
|
||||||
|
|
||||||
import androidx.core.view.accessibility.AccessibilityEventCompat;
|
import androidx.core.view.accessibility.AccessibilityEventCompat;
|
||||||
@ -27,7 +27,6 @@ import androidx.core.view.accessibility.AccessibilityRecordCompat;
|
|||||||
import org.futo.inputmethod.keyboard.Key;
|
import org.futo.inputmethod.keyboard.Key;
|
||||||
import org.futo.inputmethod.keyboard.KeyDetector;
|
import org.futo.inputmethod.keyboard.KeyDetector;
|
||||||
import org.futo.inputmethod.keyboard.MoreKeysKeyboardView;
|
import org.futo.inputmethod.keyboard.MoreKeysKeyboardView;
|
||||||
import org.futo.inputmethod.keyboard.PointerTracker;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents a delegate that can be registered in {@link MoreKeysKeyboardView} to
|
* This class represents a delegate that can be registered in {@link MoreKeysKeyboardView} to
|
||||||
@ -57,6 +56,9 @@ public class MoreKeysKeyboardAccessibilityDelegate
|
|||||||
|
|
||||||
public void onShowMoreKeysKeyboard() {
|
public void onShowMoreKeysKeyboard() {
|
||||||
sendWindowStateChanged(mOpenAnnounceResId);
|
sendWindowStateChanged(mOpenAnnounceResId);
|
||||||
|
|
||||||
|
mKeyboardView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||||
|
mKeyboardView.playSoundEffect(SoundEffectConstants.CLICK);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onDismissMoreKeysKeyboard() {
|
public void onDismissMoreKeysKeyboard() {
|
||||||
|
@ -300,22 +300,6 @@ data class Key(
|
|||||||
((actionFlags and KeyConsts.ACTION_FLAGS_ENABLE_LONG_PRESS) != 0
|
((actionFlags and KeyConsts.ACTION_FLAGS_ENABLE_LONG_PRESS) != 0
|
||||||
&& (labelFlags and KeyConsts.LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) == 0)
|
&& (labelFlags and KeyConsts.LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) == 0)
|
||||||
|
|
||||||
fun markAsLeftEdge(params: KeyboardParams) {
|
|
||||||
hitBox.left = params.mLeftPadding
|
|
||||||
}
|
|
||||||
|
|
||||||
fun markAsRightEdge(params: KeyboardParams) {
|
|
||||||
hitBox.right = params.mOccupiedWidth - params.mRightPadding
|
|
||||||
}
|
|
||||||
|
|
||||||
fun markAsTopEdge(params: KeyboardParams) {
|
|
||||||
hitBox.top = params.mTopPadding
|
|
||||||
}
|
|
||||||
|
|
||||||
fun markAsBottomEdge(params: KeyboardParams) {
|
|
||||||
hitBox.bottom = params.mOccupiedHeight + params.mBottomPadding
|
|
||||||
}
|
|
||||||
|
|
||||||
fun selectTypeface(params: KeyDrawParams): Typeface {
|
fun selectTypeface(params: KeyDrawParams): Typeface {
|
||||||
return when (labelFlags and KeyConsts.LABEL_FLAGS_FONT_MASK) {
|
return when (labelFlags and KeyConsts.LABEL_FLAGS_FONT_MASK) {
|
||||||
KeyConsts.LABEL_FLAGS_FONT_NORMAL -> Typeface.DEFAULT
|
KeyConsts.LABEL_FLAGS_FONT_NORMAL -> Typeface.DEFAULT
|
||||||
|
@ -248,10 +248,10 @@ public final class MoreKeysKeyboard extends Keyboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void markAsEdgeKey(final Key key, final int row) {
|
public void markAsEdgeKey(final Key key, final int row) {
|
||||||
if (row == 0)
|
//if (row == 0)
|
||||||
key.markAsTopEdge(this);
|
// key.markAsTopEdge(this);
|
||||||
if (isTopRow(row))
|
//if (isTopRow(row))
|
||||||
key.markAsBottomEdge(this);
|
// key.markAsBottomEdge(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTopRow(final int rowCount) {
|
private boolean isTopRow(final int rowCount) {
|
||||||
|
@ -25,9 +25,12 @@ import android.graphics.drawable.Drawable;
|
|||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.TouchDelegate;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.futo.inputmethod.accessibility.AccessibilityUtils;
|
import org.futo.inputmethod.accessibility.AccessibilityUtils;
|
||||||
import org.futo.inputmethod.accessibility.MoreKeysKeyboardAccessibilityDelegate;
|
import org.futo.inputmethod.accessibility.MoreKeysKeyboardAccessibilityDelegate;
|
||||||
import org.futo.inputmethod.keyboard.internal.KeyDrawParams;
|
import org.futo.inputmethod.keyboard.internal.KeyDrawParams;
|
||||||
@ -43,7 +46,7 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
|
|||||||
private final int[] mCoordinates = CoordinateUtils.newInstance();
|
private final int[] mCoordinates = CoordinateUtils.newInstance();
|
||||||
|
|
||||||
private final Drawable mDivider;
|
private final Drawable mDivider;
|
||||||
protected final KeyDetector mKeyDetector;
|
protected final MoreKeysDetector mKeyDetector;
|
||||||
private Controller mController = EMPTY_CONTROLLER;
|
private Controller mController = EMPTY_CONTROLLER;
|
||||||
protected KeyboardActionListener mListener;
|
protected KeyboardActionListener mListener;
|
||||||
private int mOriginX;
|
private int mOriginX;
|
||||||
@ -104,8 +107,6 @@ 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(), -getPaddingTop() + getVerticalCorrection());
|
|
||||||
if (AccessibilityUtils.getInstance().isAccessibilityEnabled()) {
|
if (AccessibilityUtils.getInstance().isAccessibilityEnabled()) {
|
||||||
if (mAccessibilityDelegate == null) {
|
if (mAccessibilityDelegate == null) {
|
||||||
mAccessibilityDelegate = new MoreKeysKeyboardAccessibilityDelegate(
|
mAccessibilityDelegate = new MoreKeysKeyboardAccessibilityDelegate(
|
||||||
@ -114,8 +115,15 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
|
|||||||
mAccessibilityDelegate.setCloseAnnounce(R.string.spoken_close_more_keys_keyboard);
|
mAccessibilityDelegate.setCloseAnnounce(R.string.spoken_close_more_keys_keyboard);
|
||||||
}
|
}
|
||||||
mAccessibilityDelegate.setKeyboard(keyboard);
|
mAccessibilityDelegate.setKeyboard(keyboard);
|
||||||
|
|
||||||
|
// No vertical correction
|
||||||
|
mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(), -getPaddingTop());
|
||||||
} else {
|
} else {
|
||||||
mAccessibilityDelegate = null;
|
mAccessibilityDelegate = null;
|
||||||
|
|
||||||
|
// With vertical correction
|
||||||
|
mKeyDetector.setKeyboard(
|
||||||
|
keyboard, -getPaddingLeft(), -getPaddingTop() + getVerticalCorrection());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,8 +147,13 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
|
|||||||
container.setX(panelX);
|
container.setX(panelX);
|
||||||
container.setY(panelY);
|
container.setY(panelY);
|
||||||
|
|
||||||
mOriginX = CoordinateUtils.x(touchOrigin) - getDefaultCoordX();
|
if(AccessibilityUtils.getInstance().isAccessibilityEnabled()) {
|
||||||
mOriginY = CoordinateUtils.y(touchOrigin) - container.getMeasuredHeight();
|
mOriginX = (int)container.getX() - CoordinateUtils.x(mCoordinates);
|
||||||
|
mOriginY = (int)container.getY() - CoordinateUtils.y(mCoordinates);
|
||||||
|
} else {
|
||||||
|
mOriginX = CoordinateUtils.x(touchOrigin) - getDefaultCoordX();
|
||||||
|
mOriginY = CoordinateUtils.y(touchOrigin) - container.getMeasuredHeight();
|
||||||
|
}
|
||||||
controller.onShowMoreKeysPanel(this);
|
controller.onShowMoreKeysPanel(this);
|
||||||
final MoreKeysKeyboardAccessibilityDelegate accessibilityDelegate = mAccessibilityDelegate;
|
final MoreKeysKeyboardAccessibilityDelegate accessibilityDelegate = mAccessibilityDelegate;
|
||||||
if (accessibilityDelegate != null
|
if (accessibilityDelegate != null
|
||||||
@ -194,6 +207,8 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
|
|||||||
* Performs the specific action for this panel when the user presses a key on the panel.
|
* Performs the specific action for this panel when the user presses a key on the panel.
|
||||||
*/
|
*/
|
||||||
protected void onKeyInput(final Key key, final int x, final int y) {
|
protected void onKeyInput(final Key key, final int x, final int y) {
|
||||||
|
dismissMoreKeysPanel();
|
||||||
|
|
||||||
final int code = key.getCode();
|
final int code = key.getCode();
|
||||||
if (code == Constants.CODE_OUTPUT_TEXT) {
|
if (code == Constants.CODE_OUTPUT_TEXT) {
|
||||||
mListener.onTextInput(mCurrentKey.getOutputText());
|
mListener.onTextInput(mCurrentKey.getOutputText());
|
||||||
@ -315,6 +330,36 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
|
|||||||
public void showInParent(final ViewGroup parentView) {
|
public void showInParent(final ViewGroup parentView) {
|
||||||
removeFromParent();
|
removeFromParent();
|
||||||
parentView.addView(getContainerView());
|
parentView.addView(getContainerView());
|
||||||
|
|
||||||
|
if(mAccessibilityDelegate != null && AccessibilityUtils.getInstance().isTouchExplorationEnabled()) {
|
||||||
|
parentView.setTouchDelegate(new MyTouchDelegate(parentView, getContainerView()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyTouchDelegate extends TouchDelegate {
|
||||||
|
public MyTouchDelegate(View parentView, View delegateView) {
|
||||||
|
super(new Rect(Integer.MIN_VALUE / 2, Integer.MIN_VALUE / 2, Integer.MAX_VALUE / 2 - 1, Integer.MAX_VALUE / 2 - 1), delegateView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchExplorationHoverEvent(@NonNull MotionEvent event) {
|
||||||
|
MotionEvent copy = MotionEvent.obtain(event);
|
||||||
|
copy.offsetLocation(-getContainerView().getX(), -getContainerView().getY());
|
||||||
|
|
||||||
|
// Dismiss the panel if we exit outside of the range
|
||||||
|
if(copy.getAction() == MotionEvent.ACTION_HOVER_EXIT) {
|
||||||
|
if (mKeyDetector.detectHitKey(
|
||||||
|
(int)copy.getX(),
|
||||||
|
(int)copy.getY()
|
||||||
|
) == null) {
|
||||||
|
dismissMoreKeysPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return MoreKeysKeyboardView.this.dispatchHoverEvent(copy);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -323,6 +368,7 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
|
|||||||
final ViewGroup currentParent = (ViewGroup)containerView.getParent();
|
final ViewGroup currentParent = (ViewGroup)containerView.getParent();
|
||||||
if (currentParent != null) {
|
if (currentParent != null) {
|
||||||
currentParent.removeView(containerView);
|
currentParent.removeView(containerView);
|
||||||
|
currentParent.setTouchDelegate(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user