Merge "Resize preview for correct clipping" into tm-qpr-dev
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 418df37..20352a3 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -38,11 +38,13 @@
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 @@
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 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 @@
/** 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 @@
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 @@
.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;
}
@@ -1243,6 +1256,19 @@
}
/**
+ * 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
*/
public Rect getAbsoluteOpenFolderBounds() {
@@ -1551,6 +1577,22 @@
}
}
+ /**
+ * 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 @@
private boolean mIsMultiWindowMode = false;
private Boolean mTransposeLayoutWithOrientation;
private Boolean mIsGestureMode;
+ private ViewScaleProvider mViewScaleProvider = null;
private SparseArray<DotRenderer> mDotRendererCache;
@@ -1601,6 +1644,19 @@
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 @@
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);
}
}
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index 5583eae..486a68f 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -25,6 +25,7 @@
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 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 @@
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 @@
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 @@
// 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,
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 4c9542d..b716912 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -44,6 +44,7 @@
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 @@
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 @@
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;
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index a8546e8..c1bab54 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -20,6 +20,7 @@
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.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.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.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 @@
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 @@
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 @@
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);
diff --git a/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
index cf6be7f..77ade80 100644
--- a/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
+++ b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
@@ -20,6 +20,7 @@
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 @@
isMultiWindowMode,
transposeLayoutWithOrientation,
useTwoPanels,
- isGestureMode
+ isGestureMode,
+ DEFAULT_PROVIDER
)
protected fun initializeVarsForPhone(isGestureMode: Boolean = true,