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

Commit 88f00ab1 authored by Winson's avatar Winson
Browse files

Cleaning up stack layout.

- Refactoring the layout to remove unused (and confusing) variables, 
  reducing the number of calculations when updating min/max bounds, and
  allow more accurate tracking of stack positions (for attached views).
- Tweaking the transform for single-task stacks so that they behave 
  better.
- Removing old, unused dismiss-all ui.

Change-Id: I8ec3bf062b0451543bd8a297aa810405f68c84cb
parent f32a1089
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -254,8 +254,6 @@ public class Recents extends SystemUI
                    null, mHandler);
        }

        // Initialize some static datastructures
        TaskStackViewLayoutAlgorithm.initializeCurve();
        // Initialize the static configuration resources
        mConfig = RecentsConfiguration.initialize(mContext, mSystemServicesProxy);
        mStatusBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
@@ -524,15 +522,16 @@ public class Recents extends SystemUI
                        mStatusBarHeight, mSearchBarBounds);
            }
        }
        mConfig.getAvailableTaskStackBounds(windowRect,
                mStatusBarHeight, (mConfig.hasTransposedNavBar ? mNavBarWidth : 0),
        Rect systemInsets = new Rect(0, mStatusBarHeight,
                (mConfig.hasTransposedNavBar ? mNavBarWidth : 0),
                (mConfig.hasTransposedNavBar ? 0 : mNavBarHeight));
        mConfig.getTaskStackBounds(windowRect, systemInsets.top, systemInsets.right,
                mSearchBarBounds, mTaskStackBounds);
        int systemBarBottomInset = mConfig.hasTransposedNavBar ? 0 : mNavBarHeight;

        // Rebind the header bar and draw it for the transition
        TaskStackViewLayoutAlgorithm algo = mDummyStackView.getStackAlgorithm();
        Rect taskStackBounds = new Rect(mTaskStackBounds);
        taskStackBounds.bottom -= systemBarBottomInset;
        algo.setSystemInsets(systemInsets);
        algo.computeRects(windowRect.width(), windowRect.height(), taskStackBounds);
        Rect taskViewBounds = algo.getUntransformedTaskViewBounds();
        if (!taskViewBounds.equals(mLastTaskViewBounds)) {
@@ -665,8 +664,11 @@ public class Recents extends SystemUI
            TaskStack stack, TaskStackView stackView, boolean isTopTaskHome) {
        preloadIcon(topTask);

        // Update the header bar if necessary
        reloadHeaderBarLayout(false /* tryAndBindSearchWidget */);

        // Update the destination rect
        mDummyStackView.updateMinMaxScrollForStack(stack, mTriggeredFromAltTab, isTopTaskHome);
        mDummyStackView.updateMinMaxScrollForStack(stack);
        final Task toTask = new Task();
        final TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView,
                topTask.id, toTask);
@@ -759,14 +761,13 @@ public class Recents extends SystemUI
        TaskStack stack = sInstanceLoadPlan.getTaskStack();

        // Prepare the dummy stack for the transition
        mDummyStackView.updateMinMaxScrollForStack(stack, mTriggeredFromAltTab, isTopTaskHome);
        mDummyStackView.updateMinMaxScrollForStack(stack);
        TaskStackViewLayoutAlgorithm.VisibilityReport stackVr =
                mDummyStackView.computeStackVisibilityReport();
        boolean hasRecentTasks = stack.getTaskCount() > 0;
        boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks;

        if (useThumbnailTransition) {

            // Try starting with a thumbnail transition
            ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, stack,
                    mDummyStackView);
+1 −1
Original line number Diff line number Diff line
@@ -154,7 +154,7 @@ public class RecentsConfiguration {
     * Returns the task stack bounds in the current orientation. These bounds do not account for
     * the system insets.
     */
    public void getAvailableTaskStackBounds(Rect windowBounds, int topInset,
    public void getTaskStackBounds(Rect windowBounds, int topInset,
            int rightInset, Rect searchBarBounds, Rect taskStackBounds) {
        if (hasTransposedNavBar) {
            // In landscape phones, the search bar appears on the left, but we overlay it on top
+263 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.recents.misc;

import android.graphics.Rect;
import android.os.SystemClock;
import android.util.Log;

/**
 * Represents a 2d curve that is parameterized along the arc length of the curve (p), and allows the
 * conversions of x->p and p->x.
 */
public class ParametricCurve {

    private static final boolean DEBUG = false;
    private static final String TAG = "ParametricCurve";

    private static final int PrecisionSteps = 250;

    /**
     * A 2d function, representing the curve.
     */
    public interface CurveFunction {
        float f(float x);
        float invF(float y);
    }

    /**
     * A function that returns a value given a parametric value.
     */
    public interface ParametricCurveFunction {
        float f(float p);
    }

    float[] xp;
    float[] px;

    CurveFunction mFn;
    ParametricCurveFunction mScaleFn;

    public ParametricCurve(CurveFunction fn, ParametricCurveFunction scaleFn) {
        long t1;
        if (DEBUG) {
            t1 = SystemClock.currentThreadTimeMicro();
            Log.d(TAG, "initializeCurve");
        }
        mFn = fn;
        mScaleFn = scaleFn;
        xp = new float[PrecisionSteps + 1];
        px = new float[PrecisionSteps + 1];

        // Approximate f(x)
        float[] fx = new float[PrecisionSteps + 1];
        float step = 1f / PrecisionSteps;
        float x = 0;
        for (int xStep = 0; xStep <= PrecisionSteps; xStep++) {
            fx[xStep] = fn.f(x);
            x += step;
        }
        // Calculate the arc length for x:1->0
        float pLength = 0;
        float[] dx = new float[PrecisionSteps + 1];
        dx[0] = 0;
        for (int xStep = 1; xStep < PrecisionSteps; xStep++) {
            dx[xStep] = (float) Math.hypot(fx[xStep] - fx[xStep - 1], step);
            pLength += dx[xStep];
        }
        // Approximate p(x), a function of cumulative progress with x, normalized to 0..1
        float p = 0;
        px[0] = 0f;
        px[PrecisionSteps] = 1f;
        if (DEBUG) {
            Log.d(TAG, "p[0]=0");
            Log.d(TAG, "p[" + PrecisionSteps + "]=1");
        }
        for (int xStep = 1; xStep < PrecisionSteps; xStep++) {
            p += Math.abs(dx[xStep] / pLength);
            px[xStep] = p;
            if (DEBUG) {
                Log.d(TAG, "p[" + xStep + "]=" + p);
            }
        }
        // Given p(x), calculate the inverse function x(p). This assumes that x(p) is also a valid
        // function.
        int xStep = 0;
        p = 0;
        xp[0] = 0f;
        xp[PrecisionSteps] = 1f;
        if (DEBUG) {
            Log.d(TAG, "x[0]=0");
            Log.d(TAG, "x[" + PrecisionSteps + "]=1");
        }
        for (int pStep = 0; pStep < PrecisionSteps; pStep++) {
            // Walk forward in px and find the x where px <= p && p < px+1
            while (xStep < PrecisionSteps) {
                if (px[xStep] > p) break;
                xStep++;
            }
            // Now, px[xStep-1] <= p < px[xStep]
            if (xStep == 0) {
                xp[pStep] = 0;
            } else {
                // Find x such that proportionally, x is correct
                float fraction = (p - px[xStep - 1]) / (px[xStep] - px[xStep - 1]);
                x = (xStep - 1 + fraction) * step;
                xp[pStep] = x;
            }
            if (DEBUG) {
                Log.d(TAG, "x[" + pStep + "]=" + xp[pStep]);
            }
            p += step;
        }
        if (DEBUG) {
            Log.d(TAG, "\t1t: " + (SystemClock.currentThreadTimeMicro() - t1) + "microsecs");
        }
    }

    /**
     * Converts from the progress along the arc-length of the curve to a coordinate within the
     * bounds.  Note, p=0 represents the top of the bounds, and p=1 represents the bottom.
     */
    public int pToX(float p, Rect bounds) {
        int top = bounds.top;
        int height = bounds.height();

        if (p <= 0f) return top;
        if (p >= 1f) return top + (int) (p * height);

        float pIndex = p * PrecisionSteps;
        int pFloorIndex = (int) Math.floor(pIndex);
        int pCeilIndex = (int) Math.ceil(pIndex);
        float x = xp[pFloorIndex];
        if (pFloorIndex < PrecisionSteps && (pCeilIndex != pFloorIndex)) {
            // Interpolate between the two precalculated positions
            x += (xp[pCeilIndex] - xp[pFloorIndex]) * (pIndex - pFloorIndex);
        }
        return top + (int) (x * height);
    }

    /**
     * Converts from the progress along the arc-length of the curve to a scale.
     */
    public float pToScale(float p) {
        return mScaleFn.f(p);
    }

    /**
     * Converts from a bounds coordinate to the progress along the arc-length of the curve.
     * Note, p=0 represents the top of the bounds, and p=1 represents the bottom.
     */
    public float xToP(int x, Rect bounds) {
        int top = bounds.top;

        float xf = (float) (x - top) / bounds.height();
        if (xf <= 0f) return 0f;
        if (xf >= 1f) return xf;

        float xIndex = xf * PrecisionSteps;
        int xFloorIndex = (int) Math.floor(xIndex);
        int xCeilIndex = (int) Math.ceil(xIndex);
        float p = px[xFloorIndex];
        if (xFloorIndex < PrecisionSteps && (xCeilIndex != xFloorIndex)) {
            // Interpolate between the two precalculated positions
            p += (px[xCeilIndex] - px[xFloorIndex]) * (xIndex - xFloorIndex);
        }
        return p;
    }

    /**
     * Computes the progress offset from the bottom of the curve (p=1) such that the given height
     * is visible when scaled at the that progress.
     */
    public float computePOffsetForScaledHeight(int height, Rect bounds) {
        int top = bounds.top;
        int bottom = bounds.bottom;

        if (bounds.height() == 0) {
            return 0;
        }

        // Find the next p(x) such that (bottom-x) == scale(p(x))*height
        int minX = top;
        int maxX = bottom;
        long t1;
        if (DEBUG) {
            t1 = SystemClock.currentThreadTimeMicro();
            Log.d(TAG, "computePOffsetForScaledHeight: " + height);
        }
        while (minX <= maxX) {
            int midX = minX + ((maxX - minX) / 2);
            float pMidX = xToP(midX, bounds);
            float scaleMidX = mScaleFn.f(pMidX);
            int scaledHeight = (int) (scaleMidX * height);
            if ((bottom - midX) < scaledHeight) {
                maxX = midX - 1;
            } else if ((bottom - midX) > scaledHeight) {
                minX = midX + 1;
            } else {
                if (DEBUG) {
                    Log.d(TAG, "\t1t: " + (SystemClock.currentThreadTimeMicro() - t1) + "microsecs");
                }
                return 1f - pMidX;
            }
        }
        if (DEBUG) {
            Log.d(TAG, "\t2t: " + (SystemClock.currentThreadTimeMicro() - t1) + "microsecs");
        }
        return 1f - xToP(maxX, bounds);
    }

    /**
     * Computes the progress offset from the bottom of the curve (p=1) that allows the given height,
     * unscaled at the progress, will be visible.
     */
    public float computePOffsetForHeight(int height, Rect bounds) {
        int top = bounds.top;
        int bottom = bounds.bottom;

        if (bounds.height() == 0) {
            return 0;
        }

        // Find the next p(x) such that (bottom-x) == height
        int minX = top;
        int maxX = bottom;
        long t1;
        if (DEBUG) {
            t1 = SystemClock.currentThreadTimeMicro();
            Log.d(TAG, "computePOffsetForHeight: " + height);
        }
        while (minX <= maxX) {
            int midX = minX + ((maxX - minX) / 2);
            if ((bottom - midX) < height) {
                maxX = midX - 1;
            } else if ((bottom - midX) > height) {
                minX = midX + 1;
            } else {
                if (DEBUG) {
                    Log.d(TAG, "\t1t: " + (SystemClock.currentThreadTimeMicro() - t1) + "microsecs");
                }
                return 1f - xToP(midX, bounds);
            }
        }
        if (DEBUG) {
            Log.d(TAG, "\t2t: " + (SystemClock.currentThreadTimeMicro() - t1) + "microsecs");
        }
        return 1f - xToP(maxX, bounds);
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -317,10 +317,10 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
        }

        Rect taskStackBounds = new Rect();
        mConfig.getAvailableTaskStackBounds(new Rect(0, 0, width, height), mSystemInsets.top,
        mConfig.getTaskStackBounds(new Rect(0, 0, width, height), mSystemInsets.top,
                mSystemInsets.right, searchBarSpaceBounds, taskStackBounds);
        if (mTaskStackView != null && mTaskStackView.getVisibility() != GONE) {
            mTaskStackView.setTaskStackBounds(taskStackBounds);
            mTaskStackView.setTaskStackBounds(taskStackBounds, mSystemInsets);
            mTaskStackView.measure(widthMeasureSpec, heightMeasureSpec);
        }

+22 −151

File changed.

Preview size limit exceeded, changes collapsed.

Loading