Fix erroneous keyswipes (#919)

This commit is contained in:
Devy Ballard 2024-07-05 14:42:09 -06:00 committed by GitHub
parent 2bce73ad7d
commit 21124a5a45
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -131,7 +131,6 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
// the popup keys panel currently being shown. equals null if no panel is active. // the popup keys panel currently being shown. equals null if no panel is active.
private PopupKeysPanel mPopupKeysPanel; private PopupKeysPanel mPopupKeysPanel;
private static final int MULTIPLIER_FOR_LONG_PRESS_TIMEOUT_IN_SLIDING_INPUT = 3;
// true if this pointer is in the dragging finger mode. // true if this pointer is in the dragging finger mode.
boolean mIsInDraggingFinger; boolean mIsInDraggingFinger;
// true if this pointer is sliding from a modifier key and in the sliding key input mode, // true if this pointer is sliding from a modifier key and in the sliding key input mode,
@ -142,6 +141,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
// true if dragging finger is allowed. // true if dragging finger is allowed.
private boolean mIsAllowedDraggingFinger; private boolean mIsAllowedDraggingFinger;
// true if a keyswipe gesture is enabled and warranted.
private boolean mKeySwipeAllowed = false;
private static boolean sInKeySwipe = false;
private final BatchInputArbiter mBatchInputArbiter; private final BatchInputArbiter mBatchInputArbiter;
private final GestureStrokeDrawingPoints mGestureStrokeDrawingPoints; private final GestureStrokeDrawingPoints mGestureStrokeDrawingPoints;
@ -637,7 +639,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
// A gesture should start only from a non-modifier key. Note that the gesture detection is // A gesture should start only from a non-modifier key. Note that the gesture detection is
// disabled when the key is repeating. // disabled when the key is repeating.
mIsDetectingGesture = (mKeyboard != null) && mKeyboard.mId.isAlphabetKeyboard() mIsDetectingGesture = (mKeyboard != null) && mKeyboard.mId.isAlphabetKeyboard()
&& key != null && !key.isModifier(); && key != null && !key.isModifier() && !mKeySwipeAllowed && !sInKeySwipe;
if (mIsDetectingGesture) { if (mIsDetectingGesture) {
mBatchInputArbiter.addDownEventPoint(x, y, eventTime, mBatchInputArbiter.addDownEventPoint(x, y, eventTime,
sTypingTimeRecorder.getLastLetterTypingTime(), getActivePointerTrackerCount()); sTypingTimeRecorder.getLastLetterTypingTime(), getActivePointerTrackerCount());
@ -666,6 +668,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
mIsAllowedDraggingFinger = sParams.mKeySelectionByDraggingFinger mIsAllowedDraggingFinger = sParams.mKeySelectionByDraggingFinger
|| (key != null && key.isModifier()) || (key != null && key.isModifier())
|| mKeyDetector.alwaysAllowsKeySelectionByDraggingFinger(); || mKeyDetector.alwaysAllowsKeySelectionByDraggingFinger();
if (key != null && isSwiper(key.getCode()) && !sInGesture) {
mKeySwipeAllowed = true;
sInKeySwipe = true;
}
mKeyboardLayoutHasBeenChanged = false; mKeyboardLayoutHasBeenChanged = false;
mIsTrackingForActionDisabled = false; mIsTrackingForActionDisabled = false;
resetKeySelectionByDraggingFinger(); resetKeySelectionByDraggingFinger();
@ -704,9 +710,19 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
sDrawingProxy.showSlidingKeyInputPreview(null); sDrawingProxy.showSlidingKeyInputPreview(null);
} }
private boolean isSwiper(final int code) {
final SettingsValues sv = Settings.getInstance().getCurrent();
return switch (code) {
case Constants.CODE_SPACE -> sv.mSpaceSwipeHorizontal != KeyboardActionListener.SWIPE_NO_ACTION
|| sv.mSpaceSwipeVertical != KeyboardActionListener.SWIPE_NO_ACTION;
case KeyCode.DELETE -> sv.mDeleteSwipeEnabled;
default -> false;
};
}
private void onGestureMoveEvent(final int x, final int y, final long eventTime, private void onGestureMoveEvent(final int x, final int y, final long eventTime,
final boolean isMajorEvent, final Key key) { final boolean isMajorEvent, final Key key) {
if (!mIsDetectingGesture) { if (!mIsDetectingGesture || sInKeySwipe) {
return; return;
} }
final boolean onValidArea = mBatchInputArbiter.addMoveEventPoint( final boolean onValidArea = mBatchInputArbiter.addMoveEventPoint(
@ -863,23 +879,24 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
} }
} }
private void onMoveEventInternal(final int x, final int y, final long eventTime) { private void onKeySwipe(final int code, final int x, final int y, final long eventTime) {
final Key oldKey = mCurrentKey;
final SettingsValues sv = Settings.getInstance().getCurrent(); final SettingsValues sv = Settings.getInstance().getCurrent();
final int fastTypingTimeout = 2 * sv.mKeyLongpressTimeout / 3;
// todo (later): move key swipe stuff to a separate function (and finally extend it) // we don't want keyswipes to start immediately if the user is fast-typing,
if (!mIsInSlidingKeyInput && oldKey != null && oldKey.getCode() == Constants.CODE_SPACE) { // see https://github.com/openboard-team/openboard/issues/411
// reason for timeout: https://github.com/openboard-team/openboard/issues/411 if (System.currentTimeMillis() < mStartTime + fastTypingTimeout && sTypingTimeRecorder.isInFastTyping(eventTime))
final int longpressTimeout = 2 * sv.mKeyLongpressTimeout / MULTIPLIER_FOR_LONG_PRESS_TIMEOUT_IN_SLIDING_INPUT;
if (mStartTime + longpressTimeout > System.currentTimeMillis())
return; return;
if (code == Constants.CODE_SPACE) {
int dX = x - mStartX; int dX = x - mStartX;
int dY = y - mStartY; int dY = y - mStartY;
// vertical movement // Vertical movement
int stepsY = dY / sPointerStep; int stepsY = dY / sPointerStep;
if (stepsY != 0 && abs(dX) < abs(dY) && !mInHorizontalSwipe) { if (stepsY != 0 && abs(dX) < abs(dY) && !mInHorizontalSwipe) {
if (!mInVerticalSwipe) {
sTimerProxy.cancelKeyTimersOf(this);
mInVerticalSwipe = true; mInVerticalSwipe = true;
}
if (sListener.onVerticalSpaceSwipe(stepsY)) { if (sListener.onVerticalSpaceSwipe(stepsY)) {
mStartY += stepsY * sPointerStep; mStartY += stepsY * sPointerStep;
} }
@ -889,23 +906,34 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
// Horizontal movement // Horizontal movement
int stepsX = dX / sPointerStep; int stepsX = dX / sPointerStep;
if (stepsX != 0 && !mInVerticalSwipe) { if (stepsX != 0 && !mInVerticalSwipe) {
if (!mInHorizontalSwipe) {
sTimerProxy.cancelKeyTimersOf(this);
mInHorizontalSwipe = true; mInHorizontalSwipe = true;
}
if (sListener.onHorizontalSpaceSwipe(stepsX)) { if (sListener.onHorizontalSpaceSwipe(stepsX)) {
mStartX += stepsX * sPointerStep; mStartX += stepsX * sPointerStep;
} }
} }
return; } else if (code == KeyCode.DELETE) {
}
if (!mIsInSlidingKeyInput && oldKey != null && oldKey.getCode() == KeyCode.DELETE && sv.mDeleteSwipeEnabled) {
// Delete slider // Delete slider
int steps = (x - mStartX) / sPointerStep; int steps = (x - mStartX) / sPointerStep;
if (abs(steps) > 2 || (mInHorizontalSwipe && steps != 0)) { if (steps != 0) {
if (!mInHorizontalSwipe) {
sTimerProxy.cancelKeyTimersOf(this); sTimerProxy.cancelKeyTimersOf(this);
mInHorizontalSwipe = true; mInHorizontalSwipe = true;
}
mStartX += steps * sPointerStep; mStartX += steps * sPointerStep;
sListener.onMoveDeletePointer(steps); sListener.onMoveDeletePointer(steps);
} }
}
}
private void onMoveEventInternal(final int x, final int y, final long eventTime) {
final Key oldKey = mCurrentKey;
// todo (later): move key swipe stuff to KeyboardActionListener (and finally extend it)
if (mKeySwipeAllowed) {
onKeySwipe(oldKey.getCode(), x, y, eventTime);
return; return;
} }
@ -1001,11 +1029,15 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
return; return;
} }
if (mKeySwipeAllowed) {
mKeySwipeAllowed = false;
sInKeySwipe = false;
if (mInHorizontalSwipe || mInVerticalSwipe) { if (mInHorizontalSwipe || mInVerticalSwipe) {
mInHorizontalSwipe = false; mInHorizontalSwipe = false;
mInVerticalSwipe = false; mInVerticalSwipe = false;
return; return;
} }
}
if (sInGesture) { if (sInGesture) {
if (currentKey != null) { if (currentKey != null) {
@ -1049,9 +1081,6 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
if (isShowingPopupKeysPanel()) { if (isShowingPopupKeysPanel()) {
return; return;
} }
if(mInHorizontalSwipe || mInVerticalSwipe) {
return;
}
final Key key = getKey(); final Key key = getKey();
if (key == null) { if (key == null) {
return; return;
@ -1093,6 +1122,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
final int translatedY = popupKeysPanel.translateY(mLastY); final int translatedY = popupKeysPanel.translateY(mLastY);
popupKeysPanel.onDownEvent(translatedX, translatedY, mPointerId, SystemClock.uptimeMillis()); popupKeysPanel.onDownEvent(translatedX, translatedY, mPointerId, SystemClock.uptimeMillis());
mPopupKeysPanel = popupKeysPanel; mPopupKeysPanel = popupKeysPanel;
if (mKeySwipeAllowed) {
mKeySwipeAllowed = false;
sInKeySwipe = false;
}
} }
private void cancelKeyTracking() { private void cancelKeyTracking() {
@ -1179,7 +1212,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
return longpressTimeout * 3 / 2; return longpressTimeout * 3 / 2;
} else if (mIsInSlidingKeyInput) { } else if (mIsInSlidingKeyInput) {
// We use longer timeout for sliding finger input started from a modifier key. // We use longer timeout for sliding finger input started from a modifier key.
return longpressTimeout * MULTIPLIER_FOR_LONG_PRESS_TIMEOUT_IN_SLIDING_INPUT; return longpressTimeout * 3;
} }
return longpressTimeout; return longpressTimeout;
} }
@ -1218,6 +1251,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
return; return;
} }
mCurrentRepeatingKeyCode = code; mCurrentRepeatingKeyCode = code;
if (mKeySwipeAllowed) {
mKeySwipeAllowed = false;
sInKeySwipe = false;
}
mIsDetectingGesture = false; mIsDetectingGesture = false;
final int nextRepeatCount = repeatCount + 1; final int nextRepeatCount = repeatCount + 1;
startKeyRepeatTimer(nextRepeatCount); startKeyRepeatTimer(nextRepeatCount);