Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25b0c309 authored by Michael Wright's avatar Michael Wright
Browse files

Debounce touch navigation taps and button presses

Bug: 8990644
Change-Id: Ib4ef2e2ab699a109c12614c1d64e4b7e63b514b0
parent 7ddd1103
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -1837,6 +1837,19 @@ public class KeyEvent extends InputEvent implements Parcelable {
        }
    }

    /** Whether key will, by default, trigger a click on the focused view.
     * @hide
     */
    public static final boolean isConfirmKey(int keyCode) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_CENTER:
            case KeyEvent.KEYCODE_ENTER:
                return true;
            default:
                return false;
        }
    }

    /** {@inheritDoc} */
    @Override
    public final int getDeviceId() {
+11 −15
Original line number Diff line number Diff line
@@ -7945,9 +7945,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        boolean result = false;
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_CENTER:
            case KeyEvent.KEYCODE_ENTER: {
        if (KeyEvent.isConfirmKey(event.getKeyCode())) {
            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
                return true;
            }
@@ -7959,8 +7957,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                checkForLongClick(0);
                return true;
            }
                break;
            }
        }
        return result;
    }
+37 −6
Original line number Diff line number Diff line
@@ -228,6 +228,7 @@ public final class ViewRootImpl implements ViewParent,

    InputStage mFirstInputStage;
    InputStage mFirstPostImeInputStage;
    SyntheticInputStage mSyntheticInputStage;

    boolean mWindowAttributesChanged = false;
    int mWindowAttributesChangesFlag = 0;
@@ -589,8 +590,8 @@ public final class ViewRootImpl implements ViewParent,

                // Set up the input pipeline.
                CharSequence counterSuffix = attrs.getTitle();
                InputStage syntheticStage = new SyntheticInputStage();
                InputStage viewPostImeStage = new ViewPostImeInputStage(syntheticStage);
                mSyntheticInputStage = new SyntheticInputStage();
                InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
                InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
                        "aq:native-post-ime:" + counterSuffix);
                InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
@@ -3773,6 +3774,9 @@ public final class ViewRootImpl implements ViewParent,
        private int processKeyEvent(QueuedInputEvent q) {
            final KeyEvent event = (KeyEvent)q.mEvent;

            // The synthetic stage occasionally needs to know about keys in order to debounce taps
            mSyntheticInputStage.notifyKeyEvent(event);

            // Deliver the key to the view hierarchy.
            if (mView.dispatchKeyEvent(event)) {
                return FINISH_HANDLED;
@@ -3945,6 +3949,10 @@ public final class ViewRootImpl implements ViewParent,
            }
            super.onDeliverToNext(q);
        }

        public void notifyKeyEvent(KeyEvent e) {
            mTouchNavigation.notifyKeyEvent(e);
        }
    }

    /**
@@ -4375,6 +4383,9 @@ public final class ViewRootImpl implements ViewParent,
        // Tap timeout in milliseconds.
        private static final int TAP_TIMEOUT = 250;

        // Debounce timeout for touch nav devices with a button under their pad, in milliseconds
        private static final int DEBOUNCE_TIME = 250;

        // The maximum distance traveled for a gesture to be considered a tap in millimeters.
        private static final int TAP_SLOP_MILLIMETERS = 5;

@@ -4409,6 +4420,9 @@ public final class ViewRootImpl implements ViewParent,
        private int mConfigTapTimeout;
        private float mConfigTapSlop;

        // Amount of time to wait between button presses and tap generation for debouncing
        private int mConfigDebounceTime;

        // The scaled tick distance.  A movement of this amount should generally translate
        // into a single dpad event in a given direction.
        private float mConfigTickDistance;
@@ -4454,6 +4468,11 @@ public final class ViewRootImpl implements ViewParent,
        private boolean mFlinging;
        private float mFlingVelocity;

        // The last time a confirm key was pressed on the touch nav device
        private long mLastConfirmKeyTime = Long.MAX_VALUE;

        private boolean mHasButtonUnderPad;

        public SyntheticTouchNavigationHandler() {
            super(true);
        }
@@ -4497,6 +4516,8 @@ public final class ViewRootImpl implements ViewParent,
                                MIN_FLING_VELOCITY_TICKS_PER_SECOND * mConfigTickDistance;
                        mConfigMaxFlingVelocity =
                                MAX_FLING_VELOCITY_TICKS_PER_SECOND * mConfigTickDistance;
                        mConfigDebounceTime = DEBOUNCE_TIME;
                        mHasButtonUnderPad = device.hasButtonUnderPad();

                        if (LOCAL_DEBUG) {
                            Log.d(LOCAL_TAG, "Configured device " + mCurrentDeviceId
@@ -4567,10 +4588,13 @@ public final class ViewRootImpl implements ViewParent,
                        if (!mConsumedMovement
                                && Math.hypot(mLastX - mStartX, mLastY - mStartY) < mConfigTapSlop
                                && time <= mStartTime + mConfigTapTimeout) {
                            if (!mHasButtonUnderPad ||
                                        time >= mLastConfirmKeyTime + mConfigDebounceTime) {
                                // It's a tap!
                                finishKeys(time);
                                sendKeyDownOrRepeat(time, KeyEvent.KEYCODE_DPAD_CENTER, metaState);
                                sendKeyUp(time);
                            }
                        } else if (mConsumedMovement
                                && mPendingKeyCode != KeyEvent.KEYCODE_UNKNOWN) {
                            // It might be a fling.
@@ -4603,6 +4627,13 @@ public final class ViewRootImpl implements ViewParent,
            }
        }

        public void notifyKeyEvent(KeyEvent e) {
            final int keyCode = e.getKeyCode();
            if (KeyEvent.isConfirmKey(e.getKeyCode())) {
                mLastConfirmKeyTime  = e.getDownTime();
            }
        }

        private void finishKeys(long time) {
            cancelFling();
            sendKeyUp(time);