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

Commit 187f1a95 authored by Adam Cohen's avatar Adam Cohen Committed by Android (Google) Code Review
Browse files

Merge "Cleaned up the way StackView draws outside of its bounds"

parents b82213d5 d51bbb5b
Loading
Loading
Loading
Loading
+37 −38
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.TableMaskFilter;
import android.util.AttributeSet;
import android.util.Log;
@@ -113,10 +114,9 @@ public class StackView extends AdapterViewAnimator {
    private ImageView mHighlight;
    private StackSlider mStackSlider;
    private boolean mFirstLayoutHappened = false;
    private ViewGroup mAncestorContainingAllChildren = null;
    private int mAncestorHeight = 0;
    private int mStackMode;
    private int mFramePadding;
    private final Rect invalidateRect = new Rect();

    public StackView(Context context) {
        super(context);
@@ -269,24 +269,18 @@ public class StackView extends AdapterViewAnimator {

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        canvas.getClipBounds(invalidateRect);
        final int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
            invalidateRect.union(lp.getInvalidateRect());
            lp.resetInvalidateRect();
        }

    // TODO: right now, this code walks up the hierarchy as far as needed and disables clipping
    // so that the stack's children can draw outside of the stack's bounds. This is fine within
    // the context of widgets in the launcher, but is destructive in general, as the clipping
    // values are not being reset. For this to be a full framework level widget, we will need
    // framework level support for drawing outside of a parent's bounds.
    private void disableParentalClipping() {
        if (mAncestorContainingAllChildren != null) {
            ViewGroup vg = this;
            while (vg.getParent() != null && vg.getParent() instanceof ViewGroup) {
                if (vg == mAncestorContainingAllChildren) break;
                vg = (ViewGroup) vg.getParent();
                vg.setClipChildren(false);
                vg.setClipToPadding(false);
            }
        }
        canvas.save(Canvas.CLIP_SAVE_FLAG);
        canvas.clipRect(invalidateRect, Region.Op.UNION);
        super.dispatchDraw(canvas);
        canvas.restore();
    }

    private void onLayout() {
@@ -343,6 +337,8 @@ public class StackView extends AdapterViewAnimator {
            cancelLongPress();
            requestDisallowInterceptTouchEvent(true);

            if (mAdapter == null) return;

            int activeIndex;
            if (mStackMode == ITEMS_SLIDE_UP) {
                activeIndex = (swipeGestureType == GESTURE_SLIDE_DOWN) ?
@@ -352,8 +348,6 @@ public class StackView extends AdapterViewAnimator {
                        mNumActiveViews - 2 : mNumActiveViews - 1;
            }

            if (mAdapter == null) return;

            if (mLoopViews) {
                mStackSlider.setMode(StackSlider.NORMAL_MODE);
            } else if (mCurrentWindowStartUnbounded + activeIndex == 0) {
@@ -845,6 +839,11 @@ public class StackView extends AdapterViewAnimator {
        int horizontalOffset;
        int verticalOffset;
        View mView;
        int left, top, right, bottom;
        private final Rect parentRect = new Rect();
        private final Rect invalidateRect = new Rect();
        private final RectF invalidateRectf = new RectF();
        private final Rect globalInvalidateRect = new Rect();

        LayoutParams(View view) {
            super(0, 0);
@@ -863,8 +862,9 @@ public class StackView extends AdapterViewAnimator {
            height = 0;
        }

        private Rect parentRect = new Rect();
        void invalidateGlobalRegion(View v, Rect r) {
            // We need to make a new rect here, so as not to modify the one passed
            globalInvalidateRect.set(r);
            View p = v;
            if (!(v.getParent() != null && v.getParent() instanceof View)) return;

@@ -872,9 +872,10 @@ public class StackView extends AdapterViewAnimator {
            parentRect.set(0, 0, 0, 0);
            int depth = 0;
            while (p.getParent() != null && p.getParent() instanceof View
                    && !parentRect.contains(r)) {
                    && !parentRect.contains(globalInvalidateRect)) {
                if (!firstPass) {
                    r.offset(p.getLeft() - p.getScrollX(), p.getTop() - p.getScrollY());
                    globalInvalidateRect.offset(p.getLeft() - p.getScrollX(), p.getTop()
                            - p.getScrollY());
                    depth++;
                }
                firstPass = false;
@@ -882,22 +883,20 @@ public class StackView extends AdapterViewAnimator {
                parentRect.set(p.getScrollX(), p.getScrollY(),
                               p.getWidth() + p.getScrollX(), p.getHeight() + p.getScrollY());

                // TODO: we need to stop early here if we've hit the edge of the screen
                // so as to prevent us from walking too high in the hierarchy. A lot of this
                // code might become a lot more straightforward.
            }

            if (depth > mAncestorHeight) {
                mAncestorContainingAllChildren = (ViewGroup) p;
                mAncestorHeight = depth;
                disableParentalClipping();
            p.invalidate(globalInvalidateRect.left, globalInvalidateRect.top,
                    globalInvalidateRect.right, globalInvalidateRect.bottom);
        }

        Rect getInvalidateRect() {
            return invalidateRect;
        }

            p.invalidate(r.left, r.top, r.right, r.bottom);
        void resetInvalidateRect() {
           invalidateRect.set(0, 0, 0, 0);
        }

        private Rect invalidateRect = new Rect();
        private RectF invalidateRectf = new RectF();
        // This is public so that ObjectAnimator can access it
        public void setVerticalOffset(int newVerticalOffset) {
            int offsetDelta = newVerticalOffset - verticalOffset;
@@ -915,7 +914,7 @@ public class StackView extends AdapterViewAnimator {
                invalidateRectf.offset(xoffset, yoffset);
                mView.getMatrix().mapRect(invalidateRectf);
                invalidateRectf.offset(-xoffset, -yoffset);
                invalidateRect.set((int) Math.floor(invalidateRectf.left),
                invalidateRect.union((int) Math.floor(invalidateRectf.left),
                        (int) Math.floor(invalidateRectf.top),
                        (int) Math.ceil(invalidateRectf.right),
                        (int) Math.ceil(invalidateRectf.bottom));
@@ -940,7 +939,7 @@ public class StackView extends AdapterViewAnimator {
                mView.getMatrix().mapRect(invalidateRectf);
                invalidateRectf.offset(-xoffset, -yoffset);

                invalidateRect.set((int) Math.floor(invalidateRectf.left),
                invalidateRect.union((int) Math.floor(invalidateRectf.left),
                        (int) Math.floor(invalidateRectf.top),
                        (int) Math.ceil(invalidateRectf.right),
                        (int) Math.ceil(invalidateRectf.bottom));