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

Commit 4b8eea7d authored by Filip Gruszczynski's avatar Filip Gruszczynski
Browse files

Crop application windows to their stack bounds.

We don't want applications to put their content outside of the area
designated by their stacks. However, we don't want to affect their
frames or task bounds. Instead, we crop their surfaces to the bounds
so they don't extend outside of the stack.

Change-Id: I7231c4baa437eefaa6bd7ba89dbc3d5038496c46
parent ca9f413b
Loading
Loading
Loading
Loading
+35 −2
Original line number Diff line number Diff line
@@ -115,6 +115,7 @@ class WindowStateAnimator {
    Rect mClipRect = new Rect();
    Rect mTmpClipRect = new Rect();
    Rect mLastClipRect = new Rect();
    Rect mTmpStackBounds = new Rect();

    // Used to save animation distances between the time they are calculated and when they are
    // used.
@@ -168,6 +169,11 @@ class WindowStateAnimator {
    /** Set when the window has been shown in the screen the first time. */
    static final int HAS_DRAWN = 4;

    // Surface flinger doesn't support crop rectangles where width or height is non-positive.
    // However, we need to somehow handle the situation where the cropping would completely hide
    // the window. We achieve this by explicitly hiding the surface and not letting it be shown.
    private boolean mHiddenForCrop;

    String drawStateToString() {
        switch (mDrawState) {
            case NO_SURFACE: return "NO_SURFACE";
@@ -1331,12 +1337,20 @@ class WindowStateAnimator {
        // so we need to translate to match the actual surface coordinates.
        clipRect.offset(attrs.surfaceInsets.left, attrs.surfaceInsets.top);

        adjustCropToStackBounds(w, clipRect);

        if (!clipRect.equals(mLastClipRect)) {
            mLastClipRect.set(clipRect);
            try {
                if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
                        "CROP " + clipRect.toShortString(), null);
                if (clipRect.width() > 0 && clipRect.height() > 0) {
                    mSurfaceControl.setWindowCrop(clipRect);
                    mHiddenForCrop = false;
                } else {
                    hide();
                    mHiddenForCrop = true;
                }
            } catch (RuntimeException e) {
                Slog.w(TAG, "Error setting crop surface of " + w
                        + " crop=" + clipRect.toShortString(), e);
@@ -1347,6 +1361,25 @@ class WindowStateAnimator {
        }
    }

    private void adjustCropToStackBounds(WindowState w, Rect clipRect) {
        if (w.getAttrs().type == LayoutParams.TYPE_BASE_APPLICATION) {
            TaskStack stack = w.getTask().mStack;
            stack.getBounds(mTmpStackBounds);
            final int surfaceX = (int) mSurfaceX;
            final int surfaceY = (int) mSurfaceY;
            // We need to do some acrobatics with surface position, because their clip region is
            // relative to the inside of the surface, but the stack bounds aren't.
            clipRect.left = Math.max(0,
                    Math.max(mTmpStackBounds.left, surfaceX + clipRect.left) - surfaceX);
            clipRect.top = Math.max(0,
                    Math.max(mTmpStackBounds.top, surfaceY + clipRect.top) - surfaceY);
            clipRect.right = Math.max(0,
                    Math.min(mTmpStackBounds.right, surfaceX + clipRect.right) - surfaceX);
            clipRect.bottom = Math.max(0,
                    Math.min(mTmpStackBounds.bottom, surfaceY + clipRect.bottom) - surfaceY);
        }
    }

    void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
        final WindowState w = mWin;

@@ -1517,7 +1550,7 @@ class WindowStateAnimator {
                            mDsDx * w.mHScale, mDtDx * w.mVScale,
                            mDsDy * w.mHScale, mDtDy * w.mVScale);

                    if (mLastHidden && mDrawState == HAS_DRAWN) {
                    if (mLastHidden && mDrawState == HAS_DRAWN && !mHiddenForCrop) {
                        if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
                                "SHOW (performLayout)", null);
                        if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w