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

Commit 64901d4e authored by Gilles Debunne's avatar Gilles Debunne
Browse files

Better handles' visibility test

Checking if the hotspot position is visible instead
of checking if it is part of the clipped visible rectangle.

Bug 5638710

Patch set 2: synchronize static variables you will.
Patch set 3: renaming and refactored the while loop.
Patch set 4: synchronize you will (again)
Patch set 5: parent

Change-Id: I330510f491c85f910fc61598936113ad07d304e4
parent 88f10c6c
Loading
Loading
Loading
Loading
+48 −30
Original line number Diff line number Diff line
@@ -9370,42 +9370,59 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            mPositionY = mTempCoords[1];
        }

        public boolean isVisible(int positionX, int positionY) {
            final TextView textView = TextView.this;
        public void onScrollChanged() {
            mScrollHasChanged = true;
        }
    }

            if (mTempRect == null) mTempRect = new Rect();
            final Rect clip = mTempRect;
            clip.left = getCompoundPaddingLeft();
            clip.top = getExtendedPaddingTop();
            clip.right = textView.getWidth() - getCompoundPaddingRight();
            clip.bottom = textView.getHeight() - getExtendedPaddingBottom();

            final ViewParent parent = textView.getParent();
            if (parent == null || !parent.getChildVisibleRect(textView, clip, null)) {
    public boolean isPositionVisible(int positionX, int positionY) {
        synchronized (sTmpPosition) {
            final float[] position = sTmpPosition;
            position[0] = positionX;
            position[1] = positionY;
            View view = this;

            while (view != null) {
                if (view != this) {
                    // Local scroll is already taken into account in positionX/Y
                    position[0] -= view.getScrollX();
                    position[1] -= view.getScrollY();
                }

                if (position[0] < 0 || position[1] < 0 ||
                        position[0] > view.getWidth() || position[1] > view.getHeight()) {
                    return false;
                }

            int posX = mPositionX + positionX;
            int posY = mPositionY + positionY;
                if (!view.getMatrix().isIdentity()) {
                    view.getMatrix().mapPoints(position);
                }

            // Offset by 1 to take into account 0.5 and int rounding around getPrimaryHorizontal.
            return posX >= clip.left - 1 && posX <= clip.right + 1 &&
                    posY >= clip.top && posY <= clip.bottom;
                position[0] += view.getLeft();
                position[1] += view.getTop();

                final ViewParent parent = view.getParent();
                if (parent instanceof View) {
                    view = (View) parent;
                } else {
                    // We've reached the ViewRoot, stop iterating
                    view = null;
                }
            }
        }

        // We've been able to walk up the view hierarchy and the position was never clipped
        return true;
    }

    public boolean isOffsetVisible(int offset) {
        final int line = mLayout.getLineForOffset(offset);
        final int lineBottom = mLayout.getLineBottom(line);
        final int primaryHorizontal = (int) mLayout.getPrimaryHorizontal(offset);
            return isVisible(primaryHorizontal + viewportToContentHorizontalOffset(),
        return isPositionVisible(primaryHorizontal + viewportToContentHorizontalOffset(),
                lineBottom + viewportToContentVerticalOffset());
    }

        public void onScrollChanged() {
            mScrollHasChanged = true;
        }
    }

    @Override
    protected void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) {
        super.onScrollChanged(horiz, vert, oldHoriz, oldVert);
@@ -9504,7 +9521,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        public void updatePosition(int parentPositionX, int parentPositionY,
                boolean parentPositionChanged, boolean parentScrolled) {
            // Either parentPositionChanged or parentScrolled is true, check if still visible
            if (isShowing() && getPositionListener().isOffsetVisible(getTextOffset())) {
            if (isShowing() && isOffsetVisible(getTextOffset())) {
                if (parentScrolled) computeLocalPosition();
                updatePosition(parentPositionX, parentPositionY);
            } else {
@@ -10528,7 +10545,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                return false;
            }

            return getPositionListener().isVisible(mPositionX + mHotspotX, mPositionY);
            return TextView.this.isPositionVisible(mPositionX + mHotspotX, mPositionY);
        }

        public abstract int getCurrentCursorOffset();
@@ -11510,6 +11527,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    private Path                    mHighlightPath;
    private boolean                 mHighlightPathBogus = true;
    private static final RectF      sTempRect = new RectF();
    private static final float[]    sTmpPosition = new float[2];

    // XXX should be much larger
    private static final int        VERY_WIDE = 1024*1024;