diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index 842abc399f..7ab09c5ce9 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -103,16 +103,40 @@
android:clearTaskOnLaunch="true"
android:exported="false"/>
+
+ android:autoRemoveFromRecents="true"
+ android:excludeFromRecents="true"
+ android:screenOrientation="portrait"
+ android:permission="android.permission.REBOOT"
+ android:exported="true">
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/quickstep/res/layout/activity_allset.xml b/quickstep/res/layout/activity_allset.xml
new file mode 100644
index 0000000000..a6a17e5ebc
--- /dev/null
+++ b/quickstep/res/layout/activity_allset.xml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/quickstep/res/layout/overview_panel.xml b/quickstep/res/layout/overview_panel.xml
index d7bcd9e932..f303f31199 100644
--- a/quickstep/res/layout/overview_panel.xml
+++ b/quickstep/res/layout/overview_panel.xml
@@ -15,12 +15,6 @@
-->
-
+
+
diff --git a/quickstep/res/values/attrs.xml b/quickstep/res/values/attrs.xml
new file mode 100644
index 0000000000..336fb572d5
--- /dev/null
+++ b/quickstep/res/values/attrs.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 9c0a083084..4f9b3ebe59 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -99,6 +99,13 @@
24dp
18dp
+
+ 40dp
+ 28dp
+ 80dp
+ 52dp
+ 24dp
+
8dp
64dp
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index a0f1638c8a..7ada496c40 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -177,6 +177,15 @@
Tutorial %1$d/%2$d
+
+ All set!
+
+ Swipe up to go home
+
+ You\u2019re ready to start using your phone
+
+ Navigation settings for accessibility
+
Share
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index 7c7d20a20a..0a8ecb8bde 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -59,7 +59,7 @@
parent="TextAppearance.GestureTutorial">
- start
- ?android:attr/textColorPrimary
- - google-sans
+ - google-sans-text
- 0.03
- 18sp
- 24sp
@@ -99,6 +99,11 @@
- @color/gesture_tutorial_primary_color
+
+
Wallpapers
- Styles & wallpapers
+ Wallpaper & style
Home settings
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index 20b4631dec..c1f3ac5e0d 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -57,6 +57,22 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
private final View[] mDragHandles = new View[HANDLE_COUNT];
private final List mSystemGestureExclusionRects = new ArrayList<>(HANDLE_COUNT);
+ private final OnAttachStateChangeListener mWidgetViewAttachStateChangeListener =
+ new OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View view) {
+ // Do nothing
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View view) {
+ // When the app widget view is detached, we should close the resize frame.
+ // An example is when the dragging starts, the widget view is detached from
+ // CellLayout and then reattached to DragLayout.
+ close(false);
+ }
+ };
+
private LauncherAppWidgetHostView mWidgetView;
private CellLayout mCellLayout;
@@ -177,7 +193,11 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
private void setupForWidget(LauncherAppWidgetHostView widgetView, CellLayout cellLayout,
DragLayer dragLayer) {
mCellLayout = cellLayout;
+ if (mWidgetView != null) {
+ mWidgetView.removeOnAttachStateChangeListener(mWidgetViewAttachStateChangeListener);
+ }
mWidgetView = widgetView;
+ mWidgetView.addOnAttachStateChangeListener(mWidgetViewAttachStateChangeListener);
LauncherAppWidgetProviderInfo info = (LauncherAppWidgetProviderInfo)
widgetView.getAppWidgetInfo();
mResizeMode = info.resizeMode;
@@ -628,6 +648,9 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
@Override
protected void handleClose(boolean animate) {
mDragLayer.removeView(this);
+ if (mWidgetView != null) {
+ mWidgetView.removeOnAttachStateChangeListener(mWidgetViewAttachStateChangeListener);
+ }
}
@Override
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 2f755e11e0..1df9df6763 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -18,6 +18,7 @@ package com.android.launcher3;
import static android.animation.ValueAnimator.areAnimatorsEnabled;
+import static com.android.launcher3.Utilities.getBoundsForViewInDragLayer;
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
import android.animation.Animator;
@@ -193,6 +194,8 @@ public class CellLayout extends ViewGroup {
private static final int INVALID_DIRECTION = -100;
private final Rect mTempRect = new Rect();
+ private final RectF mTempRectF = new RectF();
+ private final float[] mTmpFloatArray = new float[4];
private static final Paint sPaint = new Paint();
@@ -1070,11 +1073,16 @@ public class CellLayout extends ViewGroup {
// Apply local extracted color if the DragView is an AppWidgetHostViewDrawable.
View view = dragObject.dragView.getContentView();
if (view instanceof LauncherAppWidgetHostView) {
- Workspace workspace =
- Launcher.getLauncher(dragObject.dragView.getContext()).getWorkspace();
+ Launcher launcher = Launcher.getLauncher(dragObject.dragView.getContext());
+ Workspace workspace = launcher.getWorkspace();
int screenId = workspace.getIdForScreen(this);
int pageId = workspace.getPageIndexForScreenId(screenId);
cellToRect(targetCell[0], targetCell[1], spanX, spanY, mTempRect);
+
+ // Now get the rect in drag layer coordinates.
+ getBoundsForViewInDragLayer(launcher.getDragLayer(), workspace, mTempRect, false,
+ mTmpFloatArray, mTempRectF);
+ Utilities.setRect(mTempRectF, mTempRect);
((LauncherAppWidgetHostView) view).handleDrag(mTempRect, pageId);
}
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index be5463ec2c..972a6e84f5 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -33,6 +33,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Bitmap;
@@ -84,6 +85,7 @@ import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.shortcuts.ShortcutRequest;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import java.lang.reflect.Method;
@@ -104,6 +106,8 @@ public final class Utilities {
private static final Pattern sTrimPattern =
Pattern.compile("^[\\s|\\p{javaSpaceChar}]*(.*)[\\s|\\p{javaSpaceChar}]*$");
+ private static final float[] sTmpFloatArray = new float[4];
+
private static final int[] sLoc0 = new int[2];
private static final int[] sLoc1 = new int[2];
private static final Matrix sMatrix = new Matrix();
@@ -133,6 +137,15 @@ public final class Utilities {
Build.TYPE.toLowerCase(Locale.ROOT).contains("debug") ||
Build.TYPE.toLowerCase(Locale.ROOT).equals("eng");
+ /**
+ * Returns true if theme is dark.
+ */
+ public static boolean isDarkTheme(Context context) {
+ Configuration configuration = context.getResources().getConfiguration();
+ int nightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
+ return nightMode == Configuration.UI_MODE_NIGHT_YES;
+ }
+
public static boolean isDevelopersOptionsEnabled(Context context) {
return Settings.Global.getInt(context.getApplicationContext().getContentResolver(),
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
@@ -218,6 +231,33 @@ public final class Utilities {
return scale;
}
+ /**
+ * Returns bounds for a child view of DragLayer, in drag layer coordinates.
+ *
+ * see {@link com.android.launcher3.dragndrop.DragLayer}.
+ *
+ * @param viewBounds Bounds of the view wanted in drag layer coordinates, relative to the view
+ * itself. eg. (0, 0, view.getWidth, view.getHeight)
+ * @param ignoreTransform If true, view transform is ignored
+ * @param outRect The out rect where we return the bounds of {@param view} in drag layer coords.
+ */
+ public static void getBoundsForViewInDragLayer(BaseDragLayer dragLayer, View view,
+ Rect viewBounds, boolean ignoreTransform, float[] recycle, RectF outRect) {
+ float[] points = recycle == null ? new float[4] : recycle;
+ points[0] = viewBounds.left;
+ points[1] = viewBounds.top;
+ points[2] = viewBounds.right;
+ points[3] = viewBounds.bottom;
+
+ Utilities.getDescendantCoordRelativeToAncestor(view, dragLayer, points,
+ false, ignoreTransform);
+ outRect.set(
+ Math.min(points[0], points[2]),
+ Math.min(points[1], points[3]),
+ Math.max(points[0], points[2]),
+ Math.max(points[1], points[3]));
+ }
+
/**
* Inverse of {@link #getDescendantCoordRelativeToAncestor(View, View, float[], boolean)}.
*/
@@ -273,6 +313,16 @@ public final class Utilities {
return new int[] {sLoc1[0] - sLoc0[0], sLoc1[1] - sLoc0[1]};
}
+ /**
+ * Helper method to set rectOut with rectFSrc.
+ */
+ public static void setRect(RectF rectFSrc, Rect rectOut) {
+ rectOut.left = (int) rectFSrc.left;
+ rectOut.top = (int) rectFSrc.top;
+ rectOut.right = (int) rectFSrc.right;
+ rectOut.bottom = (int) rectFSrc.bottom;
+ }
+
public static void scaleRectFAboutCenter(RectF r, float scale) {
if (scale != 1.0f) {
float cx = r.centerX();
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index a5852ba828..dbdfb2b663 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -32,6 +32,7 @@ import com.android.launcher3.R;
import com.android.launcher3.Workspace;
import com.android.launcher3.dragndrop.DragController.DragListener;
import com.android.launcher3.dragndrop.DragOptions;
+import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.keyboard.KeyboardDragAndDropView;
import com.android.launcher3.model.data.AppInfo;
@@ -290,7 +291,12 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
return actions;
}
- CellLayout layout = (CellLayout) host.getParent().getParent();
+ CellLayout layout;
+ if (host.getParent() instanceof DragView) {
+ layout = (CellLayout) ((DragView) host.getParent()).getContentViewParent().getParent();
+ } else {
+ layout = (CellLayout) host.getParent().getParent();
+ }
if ((providerInfo.resizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0) {
if (layout.isRegionVacant(info.cellX + info.spanX, info.cellY, 1, info.spanY) ||
layout.isRegionVacant(info.cellX - 1, info.cellY, 1, info.spanY)) {
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 119a91ffba..b11b63ed69 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -75,7 +75,7 @@ import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePag
public class AllAppsContainerView extends SpringRelativeLayout implements DragSource,
Insettable, OnDeviceProfileChangeListener, OnActivePageChangedListener {
- private static final float FLING_VELOCITY_MULTIPLIER = 1800f;
+ private static final float FLING_VELOCITY_MULTIPLIER = 1000f;
// Starts the springs after at least 25% of the animation has passed.
private static final float FLING_ANIMATION_THRESHOLD = 0.25f;
@@ -611,7 +611,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
public void onAnimationUpdate(ValueAnimator valueAnimator) {
if (shouldSpring
&& valueAnimator.getAnimatedFraction() >= FLING_ANIMATION_THRESHOLD) {
- absorbSwipeUpVelocity(-Math.abs(
+ absorbSwipeUpVelocity(Math.abs(
Math.round(velocity * FLING_VELOCITY_MULTIPLIER)));
shouldSpring = false;
}
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index c61c0d6d53..c4c7891d58 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -15,13 +15,15 @@
*/
package com.android.launcher3.allapps;
+import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.ALL_APPS_CONTENT;
-import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
+import static com.android.launcher3.anim.Interpolators.ACCEL_2;
+import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.util.SystemUiController.UI_STATE_ALLAPPS;
@@ -154,9 +156,9 @@ public class AllAppsTransitionController
return;
}
- Interpolator interpolator = config.userControlled ? LINEAR : toState == OVERVIEW
- ? config.getInterpolator(ANIM_OVERVIEW_SCALE, FAST_OUT_SLOW_IN)
- : FAST_OUT_SLOW_IN;
+ Interpolator interpolator = toState.equals(ALL_APPS)
+ ? (config.userControlled ? ACCEL_2 : ACCEL_0_75) :
+ (config.userControlled ? DEACCEL_2 : DEACCEL);
Animator anim = createSpringAnimation(mProgress, targetProgress);
anim.setInterpolator(config.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index 13ae866efb..e45b8f7918 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -21,7 +21,6 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
-import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
@@ -34,6 +33,7 @@ import android.util.Property;
import android.util.SparseArray;
import android.view.ContextThemeWrapper;
+import com.android.launcher3.Utilities;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.icons.GraphicsUtils;
@@ -119,9 +119,7 @@ public class PreloadIconDrawable extends FastBitmapDrawable {
info,
IconPalette.getPreloadProgressColor(context, info.bitmap.color),
getPreloadColors(context),
- (context.getResources().getConfiguration().uiMode
- & Configuration.UI_MODE_NIGHT_MASK
- & Configuration.UI_MODE_NIGHT_YES) != 0) /* isDarkMode */;
+ Utilities.isDarkTheme(context));
}
public PreloadIconDrawable(
diff --git a/src/com/android/launcher3/model/data/SearchActionItemInfo.java b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
index b3057d5bd2..0eea92c691 100644
--- a/src/com/android/launcher3/model/data/SearchActionItemInfo.java
+++ b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
@@ -94,6 +94,11 @@ public class SearchActionItemInfo extends ItemInfoWithIcon {
"SearchActionItemInfo can only have either an Intent or a PendingIntent");
}
mIntent = intent;
+ // bandage fix for just one week
+ if (intent != null && "com.android.server.telecom".equals(intent.getPackage())) {
+ intent.setAction(Intent.ACTION_DIAL);
+ intent.setPackage(null);
+ }
}
public PendingIntent getPendingIntent() {
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index c19dfe9300..c63d69dfd3 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -16,7 +16,6 @@
package com.android.launcher3.popup;
-import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS;
@@ -31,6 +30,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Outline;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
@@ -41,17 +41,21 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
+import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.InsettableFrameLayout;
+import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.Workspace;
import com.android.launcher3.anim.RevealOutlineAnimation;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
import com.android.launcher3.dragndrop.DragLayer;
@@ -59,9 +63,11 @@ import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
+import com.android.launcher3.widget.LocalColorExtractor;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
/**
* A container for shortcuts to deep links and notifications associated with an app.
@@ -73,6 +79,9 @@ public abstract class ArrowPopup>
// +1 for system shortcut view
private static final int MAX_NUM_CHILDREN = MAX_SHORTCUTS + 1;
+ // Index used to get background color when using local wallpaper color extraction,
+ private static final int LIGHT_COLOR_EXTRACTION_INDEX = android.R.color.system_accent2_50;
+ private static final int DARK_COLOR_EXTRACTION_INDEX = android.R.color.system_accent2_800;
private final Rect mTempRect = new Rect();
@@ -104,8 +113,14 @@ public abstract class ArrowPopup>
private Runnable mOnCloseCallback = () -> { };
+ // The rect string of the view that the arrow is attached to, in screen reference frame.
+ private String mArrowColorRectString;
private int mArrowColor;
private final int[] mColors;
+ private final HashMap mViewForRect = new HashMap<>();
+
+ private final int mColorExtractionIndex;
+ @Nullable private LocalColorExtractor mColorExtractor;
public ArrowPopup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
@@ -113,7 +128,9 @@ public abstract class ArrowPopup>
mOutlineRadius = Themes.getDialogCornerRadius(context);
mLauncher = BaseDraggingActivity.fromContext(context);
mIsRtl = Utilities.isRtl(getResources());
-
+ mColorExtractionIndex = Utilities.isDarkTheme(context)
+ ? DARK_COLOR_EXTRACTION_INDEX
+ : LIGHT_COLOR_EXTRACTION_INDEX;
setClipToOutline(true);
setOutlineProvider(new ViewOutlineProvider() {
@Override
@@ -158,6 +175,10 @@ public abstract class ArrowPopup>
mColors[i] =
(int) argb.evaluate((i + 1) * step, primaryColor, secondaryColor);
}
+
+ if (Utilities.ATLEAST_S) {
+ setupColorExtraction();
+ }
}
}
@@ -342,6 +363,15 @@ public abstract class ArrowPopup>
// so we centered it instead. In that case we don't want to showDefaultOptions the arrow.
mArrow.setVisibility(INVISIBLE);
} else {
+ updateArrowColor();
+ }
+
+ mArrow.setPivotX(mArrowWidth / 2.0f);
+ mArrow.setPivotY(mIsAboveIcon ? mArrowHeight : 0);
+ }
+
+ private void updateArrowColor() {
+ if (!Gravity.isVertical(mGravity)) {
mArrow.setBackground(new RoundedArrowDrawable(
mArrowWidth, mArrowHeight, mArrowPointRadius,
mOutlineRadius, getMeasuredWidth(), getMeasuredHeight(),
@@ -350,9 +380,6 @@ public abstract class ArrowPopup>
mArrowColor));
mArrow.setElevation(getElevation());
}
-
- mArrow.setPivotX(mArrowWidth / 2.0f);
- mArrow.setPivotY(mIsAboveIcon ? mArrowHeight : 0);
}
/**
@@ -671,6 +698,12 @@ public abstract class ArrowPopup>
getPopupContainer().removeView(this);
getPopupContainer().removeView(mArrow);
mOnCloseCallback.run();
+ mArrowColorRectString = null;
+ mViewForRect.clear();
+ if (mColorExtractor != null) {
+ mColorExtractor.removeLocations();
+ mColorExtractor.setListener(null);
+ }
}
/**
@@ -680,6 +713,68 @@ public abstract class ArrowPopup>
mOnCloseCallback = callback;
}
+ private void setupColorExtraction() {
+ Workspace workspace = mLauncher.findViewById(R.id.workspace);
+ if (workspace == null) {
+ return;
+ }
+
+ mColorExtractor = LocalColorExtractor.newInstance(mLauncher);
+ mColorExtractor.setListener((rect, extractedColors) -> {
+ String rectString = rect.toShortString();
+ View v = mViewForRect.get(rectString);
+ if (v != null) {
+ int newColor = extractedColors.get(mColorExtractionIndex);
+ setChildColor(v, newColor);
+ if (rectString.equals(mArrowColorRectString)) {
+ mArrowColor = newColor;
+ updateArrowColor();
+ }
+ }
+ });
+
+ getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ getViewTreeObserver().removeOnPreDrawListener(this);
+
+ ArrayList locations = new ArrayList<>();
+ Rect r = new Rect();
+
+ int count = getChildCount();
+ int numVisibleChild = 0;
+ for (int i = 0; i < count; i++) {
+ View view = getChildAt(i);
+ if (view.getVisibility() == VISIBLE) {
+ RectF rf = new RectF();
+ mColorExtractor.getExtractedRectForView(Launcher.getLauncher(getContext()),
+ workspace.getCurrentPage(), view, rf);
+ if (rf.isEmpty()) {
+ numVisibleChild++;
+ continue;
+ }
+
+ locations.add(rf);
+ String rectString = rf.toShortString();
+ mViewForRect.put(rectString, view);
+
+ // Arrow color matches the first child or the last child.
+ if (!mIsAboveIcon && numVisibleChild == 0) {
+ mArrowColorRectString = rectString;
+ } else if (mIsAboveIcon) {
+ mArrowColorRectString = rectString;
+ }
+
+ numVisibleChild++;
+ }
+ }
+
+ mColorExtractor.addLocation(locations);
+ return false;
+ }
+ });
+ }
+
protected BaseDragLayer getPopupContainer() {
return mLauncher.getDragLayer();
}
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index 2fd5efc3f6..44e55e102c 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -159,6 +159,19 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
return VIEW_TRANSLATE_X;
}
+ @Override
+ public int getSplitTaskViewDismissDirection(SplitPositionOption splitPosition,
+ DeviceProfile dp) {
+ // Don't use device profile here because we know we're in fake landscape, only split option
+ // available is top/left
+ if (splitPosition.mStagePosition == STAGE_POSITION_TOP_OR_LEFT) {
+ // Top (visually left) side
+ return SPLIT_TRANSLATE_PRIMARY_NEGATIVE;
+ }
+ throw new IllegalStateException("Invalid split stage position: " +
+ splitPosition.mStagePosition);
+ }
+
@Override
public int getPrimaryScroll(View view) {
return view.getScrollY();
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index 6c2f17ee34..d8e5a485fd 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -42,6 +42,10 @@ import java.util.List;
*/
public interface PagedOrientationHandler {
+ int SPLIT_TRANSLATE_PRIMARY_POSITIVE = 0;
+ int SPLIT_TRANSLATE_PRIMARY_NEGATIVE = 1;
+ int SPLIT_TRANSLATE_SECONDARY_NEGATIVE = 2;
+
PagedOrientationHandler PORTRAIT = new PortraitPagedViewHandler();
PagedOrientationHandler LANDSCAPE = new LandscapePagedViewHandler();
PagedOrientationHandler SEASCAPE = new SeascapePagedViewHandler();
@@ -71,6 +75,13 @@ public interface PagedOrientationHandler {
int getSecondaryDimension(View view);
FloatProperty getPrimaryViewTranslate();
FloatProperty getSecondaryViewTranslate();
+
+ /**
+ * @param splitPosition The position where the view to be split will go
+ * @return {@link #SPLIT_TRANSLATE_*} constants to indicate which direction the
+ * dismissal should happen
+ */
+ int getSplitTaskViewDismissDirection(SplitPositionOption splitPosition, DeviceProfile dp);
int getPrimaryScroll(View view);
float getPrimaryScale(View view);
int getChildStart(View view);
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index f6a6448602..d3d77fd99a 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -155,6 +155,25 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
return VIEW_TRANSLATE_Y;
}
+ @Override
+ public int getSplitTaskViewDismissDirection(SplitPositionOption splitPosition,
+ DeviceProfile dp) {
+ if (splitPosition.mStagePosition == STAGE_POSITION_TOP_OR_LEFT) {
+ if (dp.isLandscape) {
+ // Left side
+ return SPLIT_TRANSLATE_PRIMARY_NEGATIVE;
+ } else {
+ // Top side
+ return SPLIT_TRANSLATE_SECONDARY_NEGATIVE;
+ }
+ } else if (splitPosition.mStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
+ // We don't have a bottom option, so should be right
+ return SPLIT_TRANSLATE_PRIMARY_POSITIVE;
+ }
+ throw new IllegalStateException("Invalid split stage position: " +
+ splitPosition.mStagePosition);
+ }
+
@Override
public int getPrimaryScroll(View view) {
return view.getScrollX();
@@ -277,7 +296,7 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
} else {
// Phone Portrait, LargeScreen Landscape/Portrait
viewGroup.setOrientation(LinearLayout.HORIZONTAL);
- lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;
+ lp.width = LinearLayout.LayoutParams.MATCH_PARENT;
}
lp.height = LinearLayout.LayoutParams.WRAP_CONTENT;
diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java
index 99942aa56d..06cac08aec 100644
--- a/src/com/android/launcher3/util/Themes.java
+++ b/src/com/android/launcher3/util/Themes.java
@@ -22,7 +22,6 @@ import static android.app.WallpaperColors.HINT_SUPPORTS_DARK_THEME;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.content.Context;
-import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.ColorMatrix;
@@ -54,16 +53,12 @@ public class Themes {
}
public static int getActivityThemeRes(Context context, int wallpaperColorHints) {
- Configuration configuration = context.getResources().getConfiguration();
- int nightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
- boolean darkTheme = nightMode == Configuration.UI_MODE_NIGHT_YES;
-
boolean supportsDarkText = Utilities.ATLEAST_S
&& (wallpaperColorHints & HINT_SUPPORTS_DARK_TEXT) != 0;
boolean isMainColorDark = Utilities.ATLEAST_S
&& (wallpaperColorHints & HINT_SUPPORTS_DARK_THEME) != 0;
- if (darkTheme) {
+ if (Utilities.isDarkTheme(context)) {
return supportsDarkText ? R.style.AppTheme_Dark_DarkText
: isMainColorDark ? R.style.AppTheme_Dark_DarkMainColor : R.style.AppTheme_Dark;
} else {
diff --git a/src/com/android/launcher3/util/UiThreadHelper.java b/src/com/android/launcher3/util/UiThreadHelper.java
index be14e01f0d..f5e1234a28 100644
--- a/src/com/android/launcher3/util/UiThreadHelper.java
+++ b/src/com/android/launcher3/util/UiThreadHelper.java
@@ -48,7 +48,13 @@ public class UiThreadHelper {
WindowInsets rootInsets = launcher.getRootView().getRootWindowInsets();
boolean isImeShown = rootInsets != null && rootInsets.isVisible(
WindowInsets.Type.ime());
- if (!isImeShown) return;
+ if (isImeShown) {
+ // this call is already asynchronous
+ launcher.getAppsView().getWindowInsetsController().hide(
+ WindowInsets.Type.ime()
+ );
+ }
+ return;
}
Message.obtain(HANDLER.get(launcher), MSG_HIDE_KEYBOARD, token).sendToTarget();
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index d49320b073..81581fa80a 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -233,15 +233,8 @@ public class FloatingIconView extends FrameLayout implements
outViewBounds.set(0, 0, v.getWidth(), v.getHeight());
}
- float[] points = new float[] {outViewBounds.left, outViewBounds.top, outViewBounds.right,
- outViewBounds.bottom};
- Utilities.getDescendantCoordRelativeToAncestor(v, launcher.getDragLayer(), points,
- false, ignoreTransform);
- outRect.set(
- Math.min(points[0], points[2]),
- Math.min(points[1], points[3]),
- Math.max(points[0], points[2]),
- Math.max(points[1], points[3]));
+ Utilities.getBoundsForViewInDragLayer(launcher.getDragLayer(), v, outViewBounds,
+ ignoreTransform, null /** recycle */, outRect);
}
/**
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index 620604a4d1..5deecd4c8a 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -16,6 +16,9 @@
package com.android.launcher3.widget;
+import static com.android.launcher3.Utilities.getBoundsForViewInDragLayer;
+import static com.android.launcher3.Utilities.setRect;
+
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.content.res.Configuration;
@@ -25,7 +28,6 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler;
import android.os.SystemClock;
-import android.util.Log;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
@@ -95,11 +97,12 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
private RectF mLastLocationRegistered = null;
@Nullable private AppWidgetHostViewDragListener mDragListener;
- // Used to store the widget size during onLayout.
+ // Used to store the widget sizes in drag layer coordinates.
private final Rect mCurrentWidgetSize = new Rect();
private final Rect mWidgetSizeAtDrag = new Rect();
+
+ private final float[] mTmpFloatArray = new float[4];
private final RectF mTempRectF = new RectF();
- private final boolean mIsRtl;
private final Rect mEnforcedRectangle = new Rect();
private final float mEnforcedCornerRadius;
private final ViewOutlineProvider mCornerRadiusEnforcementOutline = new ViewOutlineProvider() {
@@ -129,7 +132,6 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
if (Utilities.ATLEAST_Q && Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText)) {
setOnLightBackground(true);
}
- mIsRtl = Utilities.isRtl(context.getResources());
mColorExtractor = LocalColorExtractor.newInstance(getContext());
mColorExtractor.setListener(this);
@@ -319,13 +321,12 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
mIsScrollable = checkScrollableRecursively(this);
if (!mIsInDragMode && getTag() instanceof LauncherAppWidgetInfo) {
- mCurrentWidgetSize.left = left;
- mCurrentWidgetSize.top = top;
- mCurrentWidgetSize.right = right;
- mCurrentWidgetSize.bottom = bottom;
LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) getTag();
- int pageId = mWorkspace.getPageIndexForScreenId(info.screenId);
- updateColorExtraction(mCurrentWidgetSize, pageId);
+ getBoundsForViewInDragLayer(mLauncher.getDragLayer(), this, mCurrentWidgetSize, true,
+ mTmpFloatArray, mTempRectF);
+ setRect(mTempRectF, mCurrentWidgetSize);
+ updateColorExtraction(mCurrentWidgetSize,
+ mWorkspace.getPageIndexForScreenId(info.screenId));
}
enforceRoundedCorners();
@@ -338,8 +339,8 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
}
/** Handles a drag event occurred on a workspace page, {@code pageId}. */
- public void handleDrag(Rect rect, int pageId) {
- mWidgetSizeAtDrag.set(rect);
+ public void handleDrag(Rect rectInDragLayer, int pageId) {
+ mWidgetSizeAtDrag.set(rectInDragLayer);
updateColorExtraction(mWidgetSizeAtDrag, pageId);
}
@@ -351,53 +352,14 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
requestLayout();
}
- private void updateColorExtraction(Rect widgetLocation, int pageId) {
- // If the widget hasn't been measured and laid out, we cannot do this.
- if (widgetLocation.isEmpty()) {
- return;
- }
- int screenWidth = mLauncher.getDeviceProfile().widthPx;
- int screenHeight = mLauncher.getDeviceProfile().heightPx;
- int numScreens = mWorkspace.getNumPagesForWallpaperParallax();
- pageId = mIsRtl ? numScreens - pageId - 1 : pageId;
- float relativeScreenWidth = 1f / numScreens;
- float absoluteTop = widgetLocation.top;
- float absoluteBottom = widgetLocation.bottom;
- View v = this;
- while (v.getParent() instanceof View) {
- v = (View) v.getParent();
- if (v.getId() != R.id.launcher) {
- break;
- }
- absoluteBottom += v.getTop();
- absoluteTop += v.getTop();
- }
- float xOffset = 0;
- View parentView = (View) getParent();
- // The layout depends on the orientation.
- if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
- int parentViewWidth = parentView == null ? 0 : parentView.getWidth();
- xOffset = screenWidth - mWorkspace.getPaddingRight() - parentViewWidth;
- } else {
- int parentViewPaddingLeft = parentView == null ? 0 : parentView.getPaddingLeft();
- xOffset = mWorkspace.getPaddingLeft() + parentViewPaddingLeft;
- }
- // This is the position of the widget relative to the wallpaper, as expected by the
- // local color extraction of the WallpaperManager.
- // The coordinate system is such that, on the horizontal axis, each screen has a
- // distinct range on the [0,1] segment. So if there are 3 screens, they will have the
- // ranges [0, 1/3], [1/3, 2/3] and [2/3, 1]. The position on the subrange should be
- // the position of the widget relative to the screen. For the vertical axis, this is
- // simply the location of the widget relative to the screen.
- mTempRectF.left = ((widgetLocation.left + xOffset) / screenWidth + pageId)
- * relativeScreenWidth;
- mTempRectF.right = ((widgetLocation.right + xOffset) / screenWidth + pageId)
- * relativeScreenWidth;
- mTempRectF.top = absoluteTop / screenHeight;
- mTempRectF.bottom = absoluteBottom / screenHeight;
- if (mTempRectF.left < 0 || mTempRectF.right > 1 || mTempRectF.top < 0
- || mTempRectF.bottom > 1) {
- Log.e(LOG_TAG, " Error, invalid relative position");
+ /**
+ * @param rectInDragLayer Rect of widget in drag layer coordinates.
+ * @param pageId The workspace page the widget is on.
+ */
+ private void updateColorExtraction(Rect rectInDragLayer, int pageId) {
+ mColorExtractor.getExtractedRectForViewRect(mLauncher, pageId, rectInDragLayer, mTempRectF);
+
+ if (mTempRectF.isEmpty()) {
return;
}
if (!mTempRectF.equals(mLastLocationRegistered)) {
diff --git a/src/com/android/launcher3/widget/LocalColorExtractor.java b/src/com/android/launcher3/widget/LocalColorExtractor.java
index be4faea68f..8ae6b2e435 100644
--- a/src/com/android/launcher3/widget/LocalColorExtractor.java
+++ b/src/com/android/launcher3/widget/LocalColorExtractor.java
@@ -19,11 +19,14 @@ package com.android.launcher3.widget;
import android.app.WallpaperColors;
import android.appwidget.AppWidgetHostView;
import android.content.Context;
+import android.graphics.Rect;
import android.graphics.RectF;
import android.util.SparseIntArray;
+import android.view.View;
import androidx.annotation.Nullable;
+import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.util.ResourceBasedOverride;
@@ -71,4 +74,33 @@ public class LocalColorExtractor implements ResourceBasedOverride {
* Updates the base context to contain the colors override
*/
public void applyColorsOverride(Context base, WallpaperColors colors) { }
+
+ /**
+ * Takes a view and returns its rect that can be used by the wallpaper local color extractor.
+ *
+ * @param launcher Launcher class class.
+ * @param pageId The page the workspace item is on.
+ * @param v The view.
+ * @param colorExtractionRectOut The location rect, but converted to a format expected by the
+ * wallpaper local color extractor.
+ */
+ public void getExtractedRectForView(Launcher launcher, int pageId, View v,
+ RectF colorExtractionRectOut) {
+ // no-op
+ }
+
+ /**
+ * Takes a rect in drag layer coordinates and returns the rect that can be used by the wallpaper
+ * local color extractor.
+ *
+ * @param launcher Launcher class.
+ * @param pageId The page the workspace item is on.
+ * @param rectInDragLayer The relevant bounds of the view in drag layer coordinates.
+ * @param colorExtractionRectOut The location rect, but converted to a format expected by the
+ * wallpaper local color extractor.
+ */
+ public void getExtractedRectForViewRect(Launcher launcher, int pageId, Rect rectInDragLayer,
+ RectF colorExtractionRectOut) {
+ // no-op
+ }
}