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

Commit 817d014b authored by Mark Renouf's avatar Mark Renouf Committed by Android (Google) Code Review
Browse files

Merge "Support frame-synchronized clipping on SurfaceView"

parents 47350ebf e574ad09
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
@@ -101,6 +102,8 @@ public class ActivityView extends ViewGroup {

    private Insets mForwardedInsets;

    private float mCornerRadius;

    public ActivityView(Context context) {
        this(context, null /* attrs */);
    }
@@ -203,6 +206,45 @@ public class ActivityView extends ViewGroup {
        mSurfaceView.setCornerRadius(cornerRadius);
    }

    /**
     * @hide
     */
    public float getCornerRadius() {
        return mSurfaceView.getCornerRadius();
    }

    /**
     * Control whether the surface is clipped to the same bounds as the View. If true, then
     * the bounds set by {@link #setSurfaceClipBounds(Rect)} are applied to the surface as
     * window-crop.
     *
     * @param clippingEnabled whether to enable surface clipping
     * @hide
     */
    public void setSurfaceClippingEnabled(boolean clippingEnabled) {
        mSurfaceView.setEnableSurfaceClipping(clippingEnabled);
    }

    /**
     * Sets an area on the contained surface to which it will be clipped
     * when it is drawn. Setting the value to null will remove the clip bounds
     * and the surface will draw normally, using its full bounds.
     *
     * @param clipBounds The rectangular area, in the local coordinates of
     * this view, to which future drawing operations will be clipped.
     * @hide
     */
    public void setSurfaceClipBounds(Rect clipBounds) {
        mSurfaceView.setClipBounds(clipBounds);
    }

    /**
     * @hide
     */
    public boolean getSurfaceClipBounds(Rect outRect) {
        return mSurfaceView.getClipBounds(outRect);
    }

    /**
     * Launch a new activity into this container.
     * <p>Activity resolved by the provided {@link Intent} must have
+59 −1
Original line number Diff line number Diff line
@@ -167,6 +167,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall

    boolean mUseAlpha = false;
    float mSurfaceAlpha = 1f;
    boolean mClipSurfaceToBounds;

    @UnsupportedAppUsage
    boolean mHaveFrame = false;
@@ -555,9 +556,52 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
        super.dispatchDraw(canvas);
    }

    /**
     * Control whether the surface is clipped to the same bounds as the View. If true, then
     * the bounds set by {@link #setClipBounds(Rect)} are applied to the surface as window-crop.
     *
     * @param enabled whether to enable surface clipping
     * @hide
     */
    public void setEnableSurfaceClipping(boolean enabled) {
        mClipSurfaceToBounds = enabled;
        invalidate();
    }

    @Override
    public void setClipBounds(Rect clipBounds) {
        super.setClipBounds(clipBounds);

        if (!mClipSurfaceToBounds) {
            return;
        }

        // When cornerRadius is non-zero, a draw() is required to update
        // the viewport (rounding the corners of the clipBounds).
        if (mCornerRadius > 0f && !isAboveParent()) {
            invalidate();
        }

        if (mSurfaceControl != null) {
            if (mClipBounds != null) {
                mTmpRect.set(mClipBounds);
            } else {
                mTmpRect.set(0, 0, mSurfaceWidth, mSurfaceHeight);
            }
            SyncRtSurfaceTransactionApplier applier = new SyncRtSurfaceTransactionApplier(this);
            applier.scheduleApply(
                    new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(mSurfaceControl)
                            .withWindowCrop(mTmpRect)
                            .build());
        }
    }

    private void clearSurfaceViewPort(Canvas canvas) {
        if (mCornerRadius > 0f) {
            canvas.getClipBounds(mTmpRect);
            if (mClipSurfaceToBounds && mClipBounds != null) {
                mTmpRect.intersect(mClipBounds);
            }
            canvas.drawRoundRect(mTmpRect.left, mTmpRect.top, mTmpRect.right, mTmpRect.bottom,
                    mCornerRadius, mCornerRadius, mRoundedViewportPaint);
        } else {
@@ -582,6 +626,16 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
        invalidate();
    }

    /**
     * Returns the corner radius for the SurfaceView.

     * @return the radius of the corners in pixels
     * @hide
     */
    public float getCornerRadius() {
        return mCornerRadius;
    }

    /**
     * Control whether the surface view's surface is placed on top of another
     * regular surface view in the window (but still behind the window itself).
@@ -840,8 +894,12 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                            // crop the buffer to the surface size since the buffer producer may
                            // use SCALING_MODE_SCALE and submit a larger size than the surface
                            // size.
                            if (mClipSurfaceToBounds && mClipBounds != null) {
                                mSurfaceControl.setWindowCrop(mClipBounds);
                            } else {
                                mSurfaceControl.setWindowCrop(mSurfaceWidth, mSurfaceHeight);
                            }
                        }
                        mSurfaceControl.setCornerRadius(mCornerRadius);
                        if (sizeChanged && !creating) {
                            mSurfaceControl.setBufferSize(mSurfaceWidth, mSurfaceHeight);