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

Commit 556ac61c authored by Vladislav Kaznacheev's avatar Vladislav Kaznacheev
Browse files

Filter out position jitter in hover tooltip handling

Allow for some jitter when detecting stationary hover in the tooltip
handling code. This makes it possible to invoke a tooltip with stylus.

Bug: 70173905
Test: android.view.cts.TooltipTest
Change-Id: I016e378df5b48fdc45bcc3a4dbe46e3644ecb74a
parent d8171027
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -47010,6 +47010,7 @@ package android.view {
    method public int getScaledEdgeSlop();
    method public int getScaledFadingEdgeLength();
    method public float getScaledHorizontalScrollFactor();
    method public int getScaledHoverSlop();
    method public int getScaledMaximumDrawingCacheSize();
    method public int getScaledMaximumFlingVelocity();
    method public int getScaledMinimumFlingVelocity();
+37 −3
Original line number Diff line number Diff line
@@ -4296,6 +4296,38 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
         */
        Runnable mShowTooltipRunnable;
        Runnable mHideTooltipRunnable;
        /**
         * Hover move is ignored if it is within this distance in pixels from the previous one.
         */
        int mHoverSlop;
        /**
         * Update the anchor position if it significantly (that is by at least mHoverSlop)
         * different from the previously stored position. Ignoring insignificant changes
         * filters out the jitter which is typical for such input sources as stylus.
         *
         * @return True if the position has been updated.
         */
        private boolean updateAnchorPos(MotionEvent event) {
            final int newAnchorX = (int) event.getX();
            final int newAnchorY = (int) event.getY();
            if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop
                    && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) {
                return false;
            }
            mAnchorX = newAnchorX;
            mAnchorY = newAnchorY;
            return true;
        }
        /**
         *  Clear the anchor position to ensure that the next change is considered significant.
         */
        private void clearAnchorPos() {
            mAnchorX = Integer.MAX_VALUE;
            mAnchorY = Integer.MAX_VALUE;
        }
    }
    TooltipInfo mTooltipInfo;
@@ -26813,6 +26845,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                mTooltipInfo = new TooltipInfo();
                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
                mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop();
                mTooltipInfo.clearAnchorPos();
            }
            mTooltipInfo.mTooltipText = tooltipText;
        }
@@ -26879,6 +26913,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        mTooltipInfo.mTooltipPopup.hide();
        mTooltipInfo.mTooltipPopup = null;
        mTooltipInfo.mTooltipFromLongClick = false;
        mTooltipInfo.clearAnchorPos();
        if (mAttachInfo != null) {
            mAttachInfo.mTooltipHost = null;
        }
@@ -26903,11 +26938,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
                    break;
                }
                if (!mTooltipInfo.mTooltipFromLongClick) {
                if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) {
                    if (mTooltipInfo.mTooltipPopup == null) {
                        // Schedule showing the tooltip after a timeout.
                        mTooltipInfo.mAnchorX = (int) event.getX();
                        mTooltipInfo.mAnchorY = (int) event.getY();
                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
                                ViewConfiguration.getHoverTooltipShowTimeout());
@@ -26929,6 +26962,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                return true;
            case MotionEvent.ACTION_HOVER_EXIT:
                mTooltipInfo.clearAnchorPos();
                if (!mTooltipInfo.mTooltipFromLongClick) {
                    hideTooltip();
                }
+12 −0
Original line number Diff line number Diff line
@@ -290,6 +290,7 @@ public class ViewConfiguration {
    private final int mMaximumFlingVelocity;
    private final int mScrollbarSize;
    private final int mTouchSlop;
    private final int mHoverSlop;
    private final int mMinScrollbarTouchTarget;
    private final int mDoubleTapTouchSlop;
    private final int mPagingTouchSlop;
@@ -320,6 +321,7 @@ public class ViewConfiguration {
        mMaximumFlingVelocity = MAXIMUM_FLING_VELOCITY;
        mScrollbarSize = SCROLL_BAR_SIZE;
        mTouchSlop = TOUCH_SLOP;
        mHoverSlop = TOUCH_SLOP / 2;
        mMinScrollbarTouchTarget = MIN_SCROLLBAR_TOUCH_TARGET;
        mDoubleTapTouchSlop = DOUBLE_TAP_TOUCH_SLOP;
        mPagingTouchSlop = PAGING_TOUCH_SLOP;
@@ -407,6 +409,8 @@ public class ViewConfiguration {
                com.android.internal.R.bool.config_ui_enableFadingMarquee);
        mTouchSlop = res.getDimensionPixelSize(
                com.android.internal.R.dimen.config_viewConfigurationTouchSlop);
        mHoverSlop = res.getDimensionPixelSize(
                com.android.internal.R.dimen.config_viewConfigurationHoverSlop);
        mMinScrollbarTouchTarget = res.getDimensionPixelSize(
                com.android.internal.R.dimen.config_minScrollbarTouchTarget);
        mPagingTouchSlop = mTouchSlop * 2;
@@ -639,6 +643,14 @@ public class ViewConfiguration {
        return mTouchSlop;
    }

    /**
     * @return Distance in pixels a hover can wander while it is still considered "stationary".
     *
     */
    public int getScaledHoverSlop() {
        return mHoverSlop;
    }

    /**
     * @return Distance in pixels the first touch can wander before we do not consider this a
     * potential double tap event
+4 −0
Original line number Diff line number Diff line
@@ -2061,6 +2061,10 @@
         movement threshold where scrolling should begin. -->
    <dimen name="config_viewConfigurationTouchSlop">8dp</dimen>

    <!-- Base "hover slop" value used by ViewConfiguration as a
         movement threshold under which hover is considered "stationary". -->
    <dimen name="config_viewConfigurationHoverSlop">4dp</dimen>

    <!-- Minimum velocity to initiate a fling, as measured in dips per second. -->
    <dimen name="config_viewMinFlingVelocity">50dp</dimen>

+1 −0
Original line number Diff line number Diff line
@@ -470,6 +470,7 @@
  <java-symbol type="dimen" name="config_minScrollbarTouchTarget" />
  <java-symbol type="dimen" name="config_prefDialogWidth" />
  <java-symbol type="dimen" name="config_viewConfigurationTouchSlop" />
  <java-symbol type="dimen" name="config_viewConfigurationHoverSlop" />
  <java-symbol type="dimen" name="config_viewMinFlingVelocity" />
  <java-symbol type="dimen" name="config_viewMaxFlingVelocity" />
  <java-symbol type="dimen" name="config_scrollbarSize" />