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

Commit 2d675e8a authored by Sihua Ma's avatar Sihua Ma Committed by Android (Google) Code Review
Browse files

Merge "Resize preview for correct clipping" into tm-qpr-dev

parents cf03d044 e04aa207
Loading
Loading
Loading
Loading
+65 −6
Original line number Diff line number Diff line
@@ -38,11 +38,13 @@ import android.util.SparseArray;
import android.view.Surface;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.launcher3.CellLayout.ContainerType;
import com.android.launcher3.DevicePaddings.DevicePadding;
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.IconNormalizer;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.uioverrides.ApiWrapper;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
@@ -57,6 +59,9 @@ public class DeviceProfile {
    private static final int DEFAULT_DOT_SIZE = 100;
    private static final float ALL_APPS_TABLET_MAX_ROWS = 5.5f;

    public static final PointF DEFAULT_SCALE = new PointF(1.0f, 1.0f);
    public static final ViewScaleProvider DEFAULT_PROVIDER = itemInfo -> DEFAULT_SCALE;

    // Ratio of empty space, qsb should take up to appear visually centered.
    private final float mQsbCenterFactor;

@@ -204,7 +209,7 @@ public class DeviceProfile {
    public int overviewGridSideMargin;

    // Widgets
    public final PointF appWidgetScale = new PointF(1.0f, 1.0f);
    private final ViewScaleProvider mViewScaleProvider;

    // Drop Target
    public int dropTargetBarSizePx;
@@ -240,7 +245,8 @@ public class DeviceProfile {
    /** TODO: Once we fully migrate to staged split, remove "isMultiWindowMode" */
    DeviceProfile(Context context, InvariantDeviceProfile inv, Info info, WindowBounds windowBounds,
            SparseArray<DotRenderer> dotRendererCache, boolean isMultiWindowMode,
            boolean transposeLayoutWithOrientation, boolean useTwoPanels, boolean isGestureMode) {
            boolean transposeLayoutWithOrientation, boolean useTwoPanels, boolean isGestureMode,
            @NonNull final ViewScaleProvider viewScaleProvider) {

        this.inv = inv;
        this.isLandscape = windowBounds.isLandscape();
@@ -473,6 +479,8 @@ public class DeviceProfile {
        flingToDeleteThresholdVelocity = res.getDimensionPixelSize(
                R.dimen.drag_flingToDeleteMinVelocity);

        mViewScaleProvider = viewScaleProvider;

        // This is done last, after iconSizePx is calculated above.
        mDotRendererWorkSpace = createDotRenderer(iconSizePx, dotRendererCache);
        mDotRendererAllApps = createDotRenderer(allAppsIconSizePx, dotRendererCache);
@@ -669,13 +677,18 @@ public class DeviceProfile {
                .setMultiWindowMode(true)
                .build();

        profile.hideWorkspaceLabelsIfNotEnoughSpace();

        // We use these scales to measure and layout the widgets using their full invariant profile
        // sizes and then draw them scaled and centered to fit in their multi-window mode cellspans.
        float appWidgetScaleX = (float) profile.getCellSize().x / getCellSize().x;
        float appWidgetScaleY = (float) profile.getCellSize().y / getCellSize().y;
        profile.appWidgetScale.set(appWidgetScaleX, appWidgetScaleY);
        if (appWidgetScaleX != 1 || appWidgetScaleY != 1) {
            final PointF p = new PointF(appWidgetScaleX, appWidgetScaleY);
            profile = profile.toBuilder(context)
                    .setViewScaleProvider(i -> p)
                    .build();
        }

        profile.hideWorkspaceLabelsIfNotEnoughSpace();

        return profile;
    }
@@ -1242,6 +1255,19 @@ public class DeviceProfile {
                + getOverviewActionsClaimedSpaceBelow();
    }

    /**
     * Takes the View and return the scales of width and height depending on the DeviceProfile
     * specifications
     *
     * @param itemInfo The tag of the widget view
     * @return A PointF instance with the x set to be the scale of width, and y being the scale of
     * height
     */
    @NonNull
    public PointF getAppWidgetScale(@Nullable final ItemInfo itemInfo) {
        return mViewScaleProvider.getScaleFromItemInfo(itemInfo);
    }

    /**
     * @return the bounds for which the open folders should be contained within
     */
@@ -1551,6 +1577,22 @@ public class DeviceProfile {
        }
    }

    /**
     * Handler that deals with ItemInfo of the views for the DeviceProfile
     */
    @FunctionalInterface
    public interface ViewScaleProvider {
        /**
         * Get the scales from the view
         *
         * @param itemInfo The tag of the widget view
         * @return PointF instance containing the scale information, or null if using the default
         * app widget scale of this device profile.
         */
        @NonNull
        PointF getScaleFromItemInfo(@Nullable ItemInfo itemInfo);
    }

    public static class Builder {
        private Context mContext;
        private InvariantDeviceProfile mInv;
@@ -1562,6 +1604,7 @@ public class DeviceProfile {
        private boolean mIsMultiWindowMode = false;
        private Boolean mTransposeLayoutWithOrientation;
        private Boolean mIsGestureMode;
        private ViewScaleProvider mViewScaleProvider = null;

        private SparseArray<DotRenderer> mDotRendererCache;

@@ -1601,6 +1644,19 @@ public class DeviceProfile {
            return this;
        }

        /**
         * Set the viewScaleProvider for the builder
         *
         * @param viewScaleProvider The viewScaleProvider to be set for the
         *                                DeviceProfile
         * @return This builder
         */
        @NonNull
        public Builder setViewScaleProvider(@Nullable ViewScaleProvider viewScaleProvider) {
            mViewScaleProvider = viewScaleProvider;
            return this;
        }

        public DeviceProfile build() {
            if (mWindowBounds == null) {
                throw new IllegalArgumentException("Window bounds not set");
@@ -1614,9 +1670,12 @@ public class DeviceProfile {
            if (mDotRendererCache == null) {
                mDotRendererCache = new SparseArray<>();
            }
            if (mViewScaleProvider == null) {
                mViewScaleProvider = DEFAULT_PROVIDER;
            }
            return new DeviceProfile(mContext, mInv, mInfo, mWindowBounds, mDotRendererCache,
                    mIsMultiWindowMode, mTransposeLayoutWithOrientation, mUseTwoPanels,
                    mIsGestureMode);
                    mIsGestureMode, mViewScaleProvider);
        }
    }

+9 −4
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static com.android.launcher3.CellLayout.WORKSPACE;
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.View;
@@ -32,6 +33,7 @@ import android.view.ViewGroup;

import com.android.launcher3.CellLayout.ContainerType;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.widget.NavigableAppWidgetHostView;

@@ -109,8 +111,9 @@ public class ShortcutAndWidgetContainer extends ViewGroup implements FolderIcon.
        if (child instanceof NavigableAppWidgetHostView) {
            DeviceProfile profile = mActivity.getDeviceProfile();
            ((NavigableAppWidgetHostView) child).getWidgetInset(profile, mTempRect);
            final PointF appWidgetScale = profile.getAppWidgetScale((ItemInfo) child.getTag());
            lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
                    profile.appWidgetScale.x, profile.appWidgetScale.y, mBorderSpace, mTempRect);
                    appWidgetScale.x, appWidgetScale.y, mBorderSpace, mTempRect);
        } else {
            lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
                    mBorderSpace, null);
@@ -133,8 +136,9 @@ public class ShortcutAndWidgetContainer extends ViewGroup implements FolderIcon.

        if (child instanceof NavigableAppWidgetHostView) {
            ((NavigableAppWidgetHostView) child).getWidgetInset(dp, mTempRect);
            final PointF appWidgetScale = dp.getAppWidgetScale((ItemInfo) child.getTag());
            lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
                    dp.appWidgetScale.x, dp.appWidgetScale.y, mBorderSpace, mTempRect);
                    appWidgetScale.x, appWidgetScale.y, mBorderSpace, mTempRect);
        } else {
            lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
                    mBorderSpace, null);
@@ -187,8 +191,9 @@ public class ShortcutAndWidgetContainer extends ViewGroup implements FolderIcon.

            // Scale and center the widget to fit within its cells.
            DeviceProfile profile = mActivity.getDeviceProfile();
            float scaleX = profile.appWidgetScale.x;
            float scaleY = profile.appWidgetScale.y;
            final PointF appWidgetScale = profile.getAppWidgetScale((ItemInfo) child.getTag());
            float scaleX = appWidgetScale.x;
            float scaleY = appWidgetScale.y;

            nahv.setScaleToFit(Math.min(scaleX, scaleY));
            nahv.setTranslationForCentering(-(lp.width - (lp.width * scaleX)) / 2.0f,
+5 −2
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
@@ -369,7 +370,8 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
            float scale = 1;
            if (isWidget) {
                DeviceProfile profile = mLauncher.getDeviceProfile();
                scale = Utilities.shrinkRect(r, profile.appWidgetScale.x, profile.appWidgetScale.y);
                final PointF appWidgetScale = profile.getAppWidgetScale(null);
                scale = Utilities.shrinkRect(r, appWidgetScale.x, appWidgetScale.y);
            }
            size[0] = r.width();
            size[1] = r.height();
@@ -2884,7 +2886,8 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
                r.top -= widgetPadding.top;
                r.bottom += widgetPadding.bottom;
            }
            Utilities.shrinkRect(r, profile.appWidgetScale.x, profile.appWidgetScale.y);
            PointF appWidgetScale = profile.getAppWidgetScale(null);
            Utilities.shrinkRect(r, appWidgetScale.x, appWidgetScale.y);
        }

        mTempFXY[0] = r.left;
+50 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.makeMeasureSpec;
import static android.view.View.VISIBLE;

import static com.android.launcher3.DeviceProfile.DEFAULT_SCALE;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
import static com.android.launcher3.model.ModelUtils.getMissingHotseatRanks;
@@ -36,6 +37,7 @@ import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.ColorDrawable;
@@ -55,6 +57,7 @@ import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.TextClock;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.launcher3.BubbleTextView;
@@ -100,6 +103,7 @@ import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.LocalColorExtractor;
import com.android.launcher3.widget.NavigableAppWidgetHostView;
import com.android.launcher3.widget.custom.CustomWidgetManager;
import com.android.launcher3.widget.util.WidgetSizes;

import java.util.ArrayList;
import java.util.Collections;
@@ -173,6 +177,7 @@ public class LauncherPreviewRenderer extends ContextWrapper
    private final Context mContext;
    private final InvariantDeviceProfile mIdp;
    private final DeviceProfile mDp;
    private final DeviceProfile mDpOrig;
    private final Rect mInsets;
    private final WorkspaceItemInfo mWorkspaceItemInfo;
    private final LayoutInflater mHomeElementInflater;
@@ -192,7 +197,16 @@ public class LauncherPreviewRenderer extends ContextWrapper
        mUiHandler = new Handler(Looper.getMainLooper());
        mContext = context;
        mIdp = idp;
        mDp = idp.getDeviceProfile(context).copy(context);
        mDp = idp.getDeviceProfile(context).toBuilder(context).setViewScaleProvider(
                this::getAppWidgetScale).build();
        if (context instanceof PreviewContext) {
            Context tempContext = ((PreviewContext) context).getBaseContext();
            mDpOrig = new InvariantDeviceProfile(tempContext, InvariantDeviceProfile
                    .getCurrentGridName(tempContext)).getDeviceProfile(tempContext)
                    .copy(tempContext);
        } else {
            mDpOrig = mDp;
        }

        WindowInsets currentWindowInsets = context.getSystemService(WindowManager.class)
                .getCurrentWindowMetrics().getWindowInsets();
@@ -390,6 +404,41 @@ public class LauncherPreviewRenderer extends ContextWrapper
        addInScreenFromBind(view, info);
    }

    @NonNull
    private PointF getAppWidgetScale(@Nullable ItemInfo itemInfo) {
        if (!(itemInfo instanceof LauncherAppWidgetInfo)) {
            return DEFAULT_SCALE;
        }
        LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) itemInfo;
        final Size launcherWidgetSize = mLauncherWidgetSpanInfo.get(info.appWidgetId);
        if (launcherWidgetSize == null) {
            return DEFAULT_SCALE;
        }
        final Size origSize = WidgetSizes.getWidgetSizePx(mDpOrig,
                launcherWidgetSize.getWidth(), launcherWidgetSize.getHeight());
        final Size newSize = WidgetSizes.getWidgetSizePx(mDp, info.spanX, info.spanY);
        final Rect previewInset = new Rect();
        final Rect origInset = new Rect();
        // When the setup() is called for the LayoutParams, insets are added to the width
        // and height of the view. This is not accounted for in WidgetSizes and is handled
        // here.
        if (mDp.shouldInsetWidgets()) {
            previewInset.set(mDp.inv.defaultWidgetPadding);
        } else {
            previewInset.setEmpty();
        }
        if (mDpOrig.shouldInsetWidgets()) {
            origInset.set(mDpOrig.inv.defaultWidgetPadding);
        } else {
            origInset.setEmpty();
        }

        return new PointF((float) newSize.getWidth() / (origSize.getWidth()
                + origInset.left + origInset.right),
                (float) newSize.getHeight() / (origSize.getHeight()
                + origInset.top + origInset.bottom));
    }

    private void inflateAndAddPredictedIcon(WorkspaceItemInfo info) {
        CellLayout screen = mWorkspaceScreens.get(info.screenId);
        View view = PredictedAppIconInflater.inflate(mHomeElementInflater, screen, info);
+3 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.graphics.PointF
import android.graphics.Rect
import android.util.SparseArray
import androidx.test.core.app.ApplicationProvider
import com.android.launcher3.DeviceProfile.DEFAULT_PROVIDER;
import com.android.launcher3.util.DisplayController.Info
import com.android.launcher3.util.WindowBounds
import org.junit.Before
@@ -61,7 +62,8 @@ abstract class DeviceProfileBaseTest {
        isMultiWindowMode,
        transposeLayoutWithOrientation,
        useTwoPanels,
        isGestureMode
        isGestureMode,
        DEFAULT_PROVIDER
    )

    protected fun initializeVarsForPhone(isGestureMode: Boolean = true,