Merge "Separate color into app color and dot color; specify dot color" into tm-dev
diff --git a/go/quickstep/src/com/android/launcher3/AppSharing.java b/go/quickstep/src/com/android/launcher3/AppSharing.java
index c287446..e717937 100644
--- a/go/quickstep/src/com/android/launcher3/AppSharing.java
+++ b/go/quickstep/src/com/android/launcher3/AppSharing.java
@@ -39,6 +39,7 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.popup.SystemShortcut;
+import com.android.launcher3.views.ActivityContext;
import java.io.File;
@@ -191,9 +192,14 @@
}
private void showCannotShareToast(Context context) {
+ ActivityContext activityContext = ActivityContext.lookupContext(context);
+ String blockedByMessage = activityContext.getStringCache() != null
+ ? activityContext.getStringCache().disabledByAdminMessage
+ : context.getString(R.string.blocked_by_policy);
+
CharSequence text = (mSharingEnabledForUser)
? context.getText(R.string.toast_p2p_app_not_shareable)
- : context.getText(R.string.blocked_by_policy);
+ : blockedByMessage;
int duration = Toast.LENGTH_SHORT;
Toast.makeText(context, text, duration).show();
}
diff --git a/quickstep/res/values-sw600dp-land/dimens.xml b/quickstep/res/values-sw600dp-land/dimens.xml
index 2cd48d5..0cd9b2b 100644
--- a/quickstep/res/values-sw600dp-land/dimens.xml
+++ b/quickstep/res/values-sw600dp-land/dimens.xml
@@ -15,7 +15,6 @@
*/
-->
<resources>
+ <!-- Overview actions -->
<dimen name="overview_actions_top_margin">12dp</dimen>
- <dimen name="overview_grid_side_margin">52dp</dimen>
- <dimen name="overview_page_spacing">38dp</dimen>
</resources>
diff --git a/quickstep/res/values-sw600dp/dimens.xml b/quickstep/res/values-sw600dp/dimens.xml
index 5153afa..7494683 100644
--- a/quickstep/res/values-sw600dp/dimens.xml
+++ b/quickstep/res/values-sw600dp/dimens.xml
@@ -17,11 +17,13 @@
<resources>
<dimen name="navigation_key_padding">25dp</dimen>
+ <!-- Task View -->
+ <dimen name="task_thumbnail_icon_size">48dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
<dimen name="overview_task_margin">12dp</dimen>
- <dimen name="overview_task_margin_grid">4dp</dimen>
- <dimen name="overview_actions_button_spacing">36dp</dimen>
- <dimen name="overview_grid_side_margin">60dp</dimen>
- <dimen name="overview_grid_row_spacing">36dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size_grid">44dp</dimen>
+ <dimen name="overview_task_margin_grid">12dp</dimen>
+ <dimen name="overview_grid_row_spacing">28dp</dimen>
<dimen name="overview_page_spacing">36dp</dimen>
- <dimen name="task_thumbnail_icon_drawable_size_grid">32dp</dimen>
+ <dimen name="overview_grid_side_margin">64dp</dimen>
</resources>
diff --git a/quickstep/res/values-sw720dp-land/dimens.xml b/quickstep/res/values-sw720dp-land/dimens.xml
new file mode 100644
index 0000000..02d1189
--- /dev/null
+++ b/quickstep/res/values-sw720dp-land/dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ * Copyright (c) 2022, 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.
+*/
+-->
+<resources>
+ <!-- Overview actions -->
+ <dimen name="overview_actions_top_margin">20dp</dimen>
+</resources>
diff --git a/quickstep/res/values-sw720dp/dimens.xml b/quickstep/res/values-sw720dp/dimens.xml
index e381cb0..ceaa8f8 100644
--- a/quickstep/res/values-sw720dp/dimens.xml
+++ b/quickstep/res/values-sw720dp/dimens.xml
@@ -15,11 +15,13 @@
*/
-->
<resources>
+ <!-- Task View -->
+ <dimen name="task_thumbnail_icon_size">48dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
<dimen name="overview_task_margin">16dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size_grid">44dp</dimen>
<dimen name="overview_task_margin_grid">16dp</dimen>
- <dimen name="overview_grid_side_margin">64dp</dimen>
<dimen name="overview_grid_row_spacing">36dp</dimen>
<dimen name="overview_page_spacing">44dp</dimen>
- <dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
- <dimen name="task_thumbnail_icon_drawable_size_grid">44dp</dimen>
+ <dimen name="overview_grid_side_margin">64dp</dimen>
</resources>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 4210052..3072a3e 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -15,8 +15,6 @@
-->
<resources>
- <dimen name="task_thumbnail_icon_size">48dp</dimen>
- <dimen name="task_thumbnail_icon_drawable_size">48dp</dimen>
<!-- For screens without rounded corners -->
<dimen name="task_corner_radius_small">2dp</dimen>
<!-- For Launchers that want to override the default dialog corner radius -->
@@ -32,18 +30,20 @@
<dimen name="overview_proactive_row_bottom_margin">16dp</dimen>
<dimen name="overview_minimum_next_prev_size">50dp</dimen>
+
+ <!-- Task View -->
+ <dimen name="task_thumbnail_icon_size">48dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
<dimen name="overview_task_margin">16dp</dimen>
- <dimen name="overview_task_margin_grid">0dp</dimen>
+ <dimen name="overview_page_spacing">16dp</dimen>
+
<item name="overview_max_scale" format="float" type="dimen">0.7</item>
<item name="overview_modal_max_scale" format="float" type="dimen">1.1</item>
<!-- Overrideable in overlay that provides the Overview Actions. -->
- <dimen name="overview_actions_height">48dp</dimen>
- <dimen name="overview_actions_button_spacing">32dp</dimen>
<dimen name="overview_actions_top_margin">24dp</dimen>
- <dimen name="overview_actions_horizontal_margin">16dp</dimen>
-
- <dimen name="overview_page_spacing">16dp</dimen>
+ <dimen name="overview_actions_height">48dp</dimen>
+ <dimen name="overview_actions_button_spacing">36dp</dimen>
<!-- These speeds are in dp/s -->
<dimen name="max_task_dismiss_drag_velocity">2.25dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 349dd0a..cbdbdb9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -16,6 +16,7 @@
package com.android.launcher3.taskbar;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
+import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
import static com.android.launcher3.taskbar.LauncherTaskbarUIController.SYSUI_SURFACE_PROGRESS_INDEX;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK;
@@ -51,6 +52,7 @@
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.PaintDrawable;
import android.inputmethodservice.InputMethodService;
+import android.os.Handler;
import android.util.Property;
import android.view.Gravity;
import android.view.MotionEvent;
@@ -158,6 +160,7 @@
private BaseDragLayer<TaskbarActivityContext> mSeparateWindowParent; // Initialized in init.
private final ViewTreeObserverWrapper.OnComputeInsetsListener mSeparateWindowInsetsComputer =
this::onComputeInsetsForSeparateWindow;
+ private final RecentsHitboxExtender mHitboxExtender = new RecentsHitboxExtender();
public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) {
mContext = context;
@@ -297,6 +300,8 @@
navButtonsLayoutParams.setMarginEnd(navButtonsLayoutParams.getMarginStart());
navButtonsLayoutParams.gravity = Gravity.CENTER;
mNavButtonContainer.requestLayout();
+
+ mHomeButton.setOnLongClickListener(null);
}
// Animate taskbar background when either..
@@ -388,8 +393,7 @@
|| (flags & FLAG_KEYGUARD_VISIBLE) != 0,
VIEW_TRANSLATE_X, navButtonSize * (isRtl ? -2 : 2), 0));
-
- // home and recents buttons
+ // home button
mHomeButton = addButton(R.drawable.ic_sysbar_home, BUTTON_HOME, navContainer,
navButtonController, R.id.home);
mHomeButtonAlpha = new MultiValueAlpha(mHomeButton, NUM_ALPHA_CHANNELS);
@@ -399,8 +403,21 @@
ALPHA_INDEX_KEYGUARD_OR_DISABLE),
flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 &&
(flags & FLAG_DISABLE_HOME) == 0));
+
+ // Recents button
View recentsButton = addButton(R.drawable.ic_sysbar_recent, BUTTON_RECENTS,
navContainer, navButtonController, R.id.recent_apps);
+ mHitboxExtender.init(recentsButton, mNavButtonsView, mContext.getDeviceProfile(),
+ () -> {
+ float[] recentsCoords = new float[2];
+ getDescendantCoordRelativeToAncestor(recentsButton, mNavButtonsView,
+ recentsCoords, false);
+ return recentsCoords;
+ }, new Handler());
+ recentsButton.setOnClickListener(v -> {
+ navButtonController.onButtonClick(BUTTON_RECENTS);
+ mHitboxExtender.onRecentsButtonClicked();
+ });
mPropertyHolders.add(new StatePropertyHolder(recentsButton,
flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 && (flags & FLAG_DISABLE_RECENTS) == 0
&& !mContext.isNavBarKidsModeActive()));
@@ -504,6 +521,9 @@
View button = mAllButtons.get(i);
if (button.getVisibility() == View.VISIBLE) {
parent.getDescendantRectRelativeToSelf(button, mTempRect);
+ if (mHitboxExtender.extendedHitboxEnabled()) {
+ mTempRect.bottom += mContext.mDeviceProfile.getTaskbarOffsetY();
+ }
outRegion.op(mTempRect, Op.UNION);
}
}
@@ -733,6 +753,17 @@
return str.toString();
}
+ public TouchController getTouchController() {
+ return mHitboxExtender;
+ }
+
+ /**
+ * @param alignment 0 -> Taskbar, 1 -> Workspace
+ */
+ public void updateTaskbarAlignment(float alignment) {
+ mHitboxExtender.onAnimationProgressToOverview(alignment);
+ }
+
private class RotationButtonListener implements RotationButton.RotationButtonUpdatesCallback {
@Override
public void onVisibilityChanged(boolean isVisible) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/RecentsHitboxExtender.java b/quickstep/src/com/android/launcher3/taskbar/RecentsHitboxExtender.java
new file mode 100644
index 0000000..4651570
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/RecentsHitboxExtender.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2022 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.launcher3.taskbar;
+
+import android.graphics.Rect;
+import android.os.Handler;
+import android.view.MotionEvent;
+import android.view.TouchDelegate;
+import android.view.View;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.util.TouchController;
+
+import java.util.function.Supplier;
+
+/**
+ * Extends the Recents touch area during the taskbar to overview animation
+ * to give user some error room when trying to quickly double tap recents button since it moves.
+ *
+ * Listens for icon alignment as our indication for the animation.
+ */
+public class RecentsHitboxExtender implements TouchController {
+
+ private static final int RECENTS_HITBOX_TIMEOUT_MS = 500;
+
+ private View mRecentsButton;
+ private View mRecentsParent;
+ private DeviceProfile mDeviceProfile;
+ private Supplier<float[]> mParentCoordSupplier;
+ private TouchDelegate mRecentsTouchDelegate;
+ /**
+ * Will be true while the animation from taskbar to overview is occurring.
+ * Lifecycle of this variable slightly extends past the animation by
+ * {@link #RECENTS_HITBOX_TIMEOUT_MS}, so can use this variable as a proxy for if
+ * the current hitbox is extended or not.
+ */
+ private boolean mAnimatingFromTaskbarToOverview;
+ private float mLastIconAlignment;
+ private final Rect mRecentsHitBox = new Rect();
+ private boolean mRecentsButtonClicked;
+ private Handler mHandler;
+ private final Runnable mRecentsHitboxResetRunnable = this::reset;
+
+ public void init(View recentsButton, View recentsParent, DeviceProfile deviceProfile,
+ Supplier<float[]> parentCoordSupplier, Handler handler) {
+ mRecentsButton = recentsButton;
+ mRecentsParent = recentsParent;
+ mDeviceProfile = deviceProfile;
+ mParentCoordSupplier = parentCoordSupplier;
+ mHandler = handler;
+ }
+
+ public void onRecentsButtonClicked() {
+ mRecentsButtonClicked = true;
+ }
+
+ /**
+ * @param progress 0 -> Taskbar, 1 -> Overview
+ */
+ public void onAnimationProgressToOverview(float progress) {
+ if (progress == 1 || progress == 0) {
+ // Done w/ animation
+ mLastIconAlignment = progress;
+ if (mAnimatingFromTaskbarToOverview) {
+ if (progress == 1) {
+ // Finished animation to workspace, remove the touch delegate shortly
+ mHandler.postDelayed(mRecentsHitboxResetRunnable, RECENTS_HITBOX_TIMEOUT_MS);
+ return;
+ } else {
+ // Went back to taskbar, reset immediately
+ mHandler.removeCallbacks(mRecentsHitboxResetRunnable);
+ reset();
+ }
+ }
+ }
+
+ if (mAnimatingFromTaskbarToOverview) {
+ return;
+ }
+
+ if (progress > 0 && mLastIconAlignment == 0 && mRecentsButtonClicked) {
+ // Starting animation, previously we were showing taskbar
+ mAnimatingFromTaskbarToOverview = true;
+ float[] recentsCoords = mParentCoordSupplier.get();
+ int x = (int) recentsCoords[0];
+ int y = (int) (recentsCoords[1]);
+ // Extend hitbox vertically by the offset amount from mDeviceProfile.getTaskbarOffsetY()
+ mRecentsHitBox.set(x, y,
+ x + mRecentsButton.getWidth(),
+ y + mRecentsButton.getHeight() + mDeviceProfile.getTaskbarOffsetY()
+ );
+ mRecentsTouchDelegate = new TouchDelegate(mRecentsHitBox, mRecentsButton);
+ mRecentsParent.setTouchDelegate(mRecentsTouchDelegate);
+ }
+ }
+
+ private void reset() {
+ mAnimatingFromTaskbarToOverview = false;
+ mRecentsButton.setTouchDelegate(null);
+ mRecentsHitBox.setEmpty();
+ mRecentsButtonClicked = false;
+ }
+
+ /**
+ * @return {@code true} if the bounds for recents touches are currently extended
+ */
+ public boolean extendedHitboxEnabled() {
+ return mAnimatingFromTaskbarToOverview;
+ }
+
+ @Override
+ public boolean onControllerTouchEvent(MotionEvent ev) {
+ return mRecentsTouchDelegate.onTouchEvent(ev);
+ }
+
+ @Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ return mRecentsHitBox.contains((int)ev.getX(), (int)ev.getY());
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index 3e2695c..99c59a8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -182,7 +182,8 @@
*/
public TouchController[] getTouchControllers() {
return new TouchController[]{mActivity.getDragController(),
- mControllers.taskbarForceVisibleImmersiveController};
+ mControllers.taskbarForceVisibleImmersiveController,
+ mControllers.navbarButtonsViewController.getTouchController()};
}
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 2be1179..052c695 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -428,6 +428,7 @@
// Switch taskbar and hotseat in last frame
setTaskbarViewVisible(alignment < 1);
+ mControllers.navbarButtonsViewController.updateTaskbarAlignment(alignment);
}
private float getCurrentIconAlignmentRatioBetweenAppAndHome() {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index 7b01670..3b1f119 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -58,17 +58,21 @@
@Override
public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
- ScaleAndTranslation scaleAndTranslation =
- new ScaleAndTranslation(NO_SCALE, NO_OFFSET, NO_OFFSET);
+ return new ScaleAndTranslation(0.97f, NO_OFFSET, NO_OFFSET);
+ }
+
+ @Override
+ public ScaleAndTranslation getHotseatScaleAndTranslation(Launcher launcher) {
if (launcher.getDeviceProfile().isTablet) {
- scaleAndTranslation.scale = 0.97f;
+ return getWorkspaceScaleAndTranslation(launcher);
} else {
ScaleAndTranslation overviewScaleAndTranslation = LauncherState.OVERVIEW
.getWorkspaceScaleAndTranslation(launcher);
- scaleAndTranslation.translationX = overviewScaleAndTranslation.translationX;
- scaleAndTranslation.translationY = overviewScaleAndTranslation.translationY;
+ return new ScaleAndTranslation(
+ NO_SCALE,
+ overviewScaleAndTranslation.translationX,
+ overviewScaleAndTranslation.translationY);
}
- return scaleAndTranslation;
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index b5b03a1..f2162b0 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -192,7 +192,10 @@
1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD));
config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_ACCELERATE);
} else if (fromState == NORMAL && toState == ALL_APPS) {
- config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_DECELERATE);
+ if (mActivity.getDeviceProfile().isTablet) {
+ config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_DECELERATE);
+ }
+ // TODO(b/231682175): centralize this setup in AllAppsSwipeController
}
}
}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 13389c0..f60b225 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -1177,6 +1177,11 @@
}
private void doLogGesture(GestureEndTarget endTarget, @Nullable TaskView targetTask) {
+ if (mDp == null || !mDp.isGestureMode || mDownPos == null) {
+ // We probably never received an animation controller, skip logging.
+ return;
+ }
+
StatsLogManager.EventEnum event;
switch (endTarget) {
case HOME:
@@ -1200,11 +1205,6 @@
logger.withItemInfo(targetTask.getItemInfo());
}
- DeviceProfile dp = mDp;
- if (dp == null || mDownPos == null) {
- // We probably never received an animation controller, skip logging.
- return;
- }
int pageIndex = endTarget == LAST_TASK || mRecentsView == null
? LOG_NO_OP_PAGE_INDEX
: mRecentsView.getNextPage();
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 6745246..2fcd286 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -222,32 +222,27 @@
*/
public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect) {
Resources res = context.getResources();
+ float maxScale = res.getFloat(R.dimen.overview_max_scale);
if (dp.isTablet) {
Rect gridRect = new Rect();
calculateGridSize(dp, gridRect);
- PointF taskDimension = getTaskDimension(context, dp);
- float scale = gridRect.height() / taskDimension.y;
- scale = Math.min(scale, res.getFloat(R.dimen.overview_max_scale));
- int outWidth = Math.round(scale * taskDimension.x);
- int outHeight = Math.round(scale * taskDimension.y);
-
- int gravity = Gravity.CENTER;
- Gravity.apply(gravity, outWidth, outHeight, gridRect, outRect);
+ calculateTaskSizeInternal(context, dp, gridRect, maxScale, Gravity.CENTER, outRect);
} else {
int taskMargin = dp.overviewTaskMarginPx;
calculateTaskSizeInternal(context, dp,
dp.overviewTaskThumbnailTopMarginPx,
dp.getOverviewActionsClaimedSpace(),
res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin,
+ maxScale,
Gravity.CENTER,
outRect);
}
}
private void calculateTaskSizeInternal(Context context, DeviceProfile dp, int claimedSpaceAbove,
- int claimedSpaceBelow, int minimumHorizontalPadding, int gravity, Rect outRect) {
- PointF taskDimension = getTaskDimension(context, dp);
+ int claimedSpaceBelow, int minimumHorizontalPadding, float maxScale, int gravity,
+ Rect outRect) {
Rect insets = dp.getInsets();
Rect potentialTaskRect = new Rect(0, 0, dp.widthPx, dp.heightPx);
@@ -258,9 +253,17 @@
minimumHorizontalPadding,
claimedSpaceBelow);
+ calculateTaskSizeInternal(context, dp, potentialTaskRect, maxScale, gravity, outRect);
+ }
+
+ private void calculateTaskSizeInternal(Context context, DeviceProfile dp,
+ Rect potentialTaskRect, float maxScale, int gravity, Rect outRect) {
+ PointF taskDimension = getTaskDimension(context, dp);
+
float scale = Math.min(
potentialTaskRect.width() / taskDimension.x,
potentialTaskRect.height() / taskDimension.y);
+ scale = Math.min(scale, maxScale);
int outWidth = Math.round(scale * taskDimension.x);
int outHeight = Math.round(scale * taskDimension.y);
@@ -359,6 +362,7 @@
dp.overviewTaskMarginPx,
dp.heightPx - outRect.bottom - dp.getInsets().bottom,
Math.round((dp.availableWidthPx - outRect.width() * maxScale) / 2),
+ 1f /*maxScale*/,
Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM,
outRect);
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 920ed71..4fb7e6b 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -419,6 +419,13 @@
}
/**
+ * @return whether notification panel is expanded
+ */
+ public boolean isNotificationPanelExpanded() {
+ return (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0;
+ }
+
+ /**
* @return whether the global actions dialog is showing
*/
public boolean isSystemUiDialogShowing() {
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index f53491b..3ef1332 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -46,6 +46,7 @@
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.ResourceBasedOverride;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
+import com.android.launcher3.views.ActivityContext;
import com.android.quickstep.TaskShortcutFactory.SplitSelectSystemShortcut;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.views.OverviewActionsView;
@@ -314,9 +315,14 @@
}
protected void showBlockedByPolicyMessage() {
+ ActivityContext activityContext = ActivityContext.lookupContext(
+ mThumbnailView.getContext());
+ String message = activityContext.getStringCache() != null
+ ? activityContext.getStringCache().disabledByAdminMessage
+ : mThumbnailView.getContext().getString(R.string.blocked_by_policy);
Toast.makeText(
mThumbnailView.getContext(),
- R.string.blocked_by_policy,
+ message,
Toast.LENGTH_LONG).show();
}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 0078d55..f2583fb 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -700,7 +700,10 @@
// If Bubbles is expanded, use the overlay input consumer, which will close Bubbles
// instead of going all the way home when a swipe up is detected.
- if (mDeviceState.isBubblesExpanded() || mDeviceState.isSystemUiDialogShowing()) {
+ // Notification panel can be expanded on top of expanded bubbles. Bubbles remain
+ // expanded in the back. Make sure swipe up is not passed to bubbles in this case.
+ if ((mDeviceState.isBubblesExpanded() && !mDeviceState.isNotificationPanelExpanded())
+ || mDeviceState.isSystemUiDialogShowing()) {
base = new SysUiOverlayInputConsumer(
getBaseContext(), mDeviceState, mInputMonitorCompat);
}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/RecentsHitboxExtenderTest.java b/quickstep/tests/src/com/android/launcher3/taskbar/RecentsHitboxExtenderTest.java
new file mode 100644
index 0000000..929bff3
--- /dev/null
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/RecentsHitboxExtenderTest.java
@@ -0,0 +1,125 @@
+package com.android.launcher3.taskbar;
+
+import static android.view.MotionEvent.ACTION_DOWN;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.os.Handler;
+import android.view.MotionEvent;
+import android.view.View;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.launcher3.DeviceProfile;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.function.Supplier;
+
+@RunWith(AndroidJUnit4.class)
+public class RecentsHitboxExtenderTest {
+
+ private static final int TASKBAR_OFFSET_Y = 35;
+ private static final int BUTTON_WIDTH = 10;
+ private static final int BUTTON_HEIGHT = 10;
+
+ private final RecentsHitboxExtender mHitboxExtender = new RecentsHitboxExtender();
+ @Mock
+ View mMockRecentsButton;
+ @Mock
+ View mMockRecentsParent;
+ @Mock
+ DeviceProfile mMockDeviceProfile;
+ @Mock
+ Handler mMockHandler;
+ Context mContext;
+
+ float[] mRecentsCoords = new float[]{0,0};
+ private final Supplier<float[]> mSupplier = () -> mRecentsCoords;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ mContext = instrumentation.getContext();
+ mHitboxExtender.init(mMockRecentsButton, mMockRecentsParent, mMockDeviceProfile, mSupplier,
+ mMockHandler);
+ when(mMockDeviceProfile.getTaskbarOffsetY()).thenReturn(TASKBAR_OFFSET_Y);
+ when(mMockRecentsButton.getContext()).thenReturn(mContext);
+ when(mMockRecentsButton.getWidth()).thenReturn(BUTTON_WIDTH);
+ when(mMockRecentsButton.getHeight()).thenReturn(BUTTON_HEIGHT);
+ }
+
+ @Test
+ public void noRecentsButtonClick_notActive() {
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertFalse(mHitboxExtender.extendedHitboxEnabled());
+ }
+
+ @Test
+ public void recentsButtonClick_active() {
+ mHitboxExtender.onRecentsButtonClicked();
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertTrue(mHitboxExtender.extendedHitboxEnabled());
+ }
+
+ @Test
+ public void homeToTaskbar_notActive() {
+ mHitboxExtender.onAnimationProgressToOverview(1);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertFalse(mHitboxExtender.extendedHitboxEnabled());
+ }
+
+ @Test
+ public void animationEndReset() {
+ mHitboxExtender.onRecentsButtonClicked();
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertTrue(mHitboxExtender.extendedHitboxEnabled());
+ mHitboxExtender.onAnimationProgressToOverview(1);
+ verify(mMockHandler, times(1)).postDelayed(any(), anyLong());
+ }
+
+ @Test
+ public void motionWithinHitbox() {
+ mHitboxExtender.onRecentsButtonClicked();
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertTrue(mHitboxExtender.extendedHitboxEnabled());
+ // Center width, past height but w/in offset bounds
+ MotionEvent motionEvent = getMotionEvent(ACTION_DOWN,
+ BUTTON_WIDTH / 2, BUTTON_HEIGHT + TASKBAR_OFFSET_Y / 2);
+ assertTrue(mHitboxExtender.onControllerInterceptTouchEvent(motionEvent));
+ }
+
+ @Test
+ public void motionOutsideHitbox() {
+ mHitboxExtender.onRecentsButtonClicked();
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertTrue(mHitboxExtender.extendedHitboxEnabled());
+ // Center width, past height and offset
+ MotionEvent motionEvent = getMotionEvent(ACTION_DOWN,
+ BUTTON_WIDTH / 2, BUTTON_HEIGHT + TASKBAR_OFFSET_Y * 2);
+ assertFalse(mHitboxExtender.onControllerInterceptTouchEvent(motionEvent));
+ }
+
+ private MotionEvent getMotionEvent(int action, int x, int y) {
+ return MotionEvent.obtain(0, 0, action, x, y, 0);
+ }
+}
diff --git a/res/color-night-v31/all_apps_button_color_2.xml b/res/color-night-v31/all_apps_button_color_2.xml
index 30b972f..e400543 100644
--- a/res/color-night-v31/all_apps_button_color_2.xml
+++ b/res/color-night-v31/all_apps_button_color_2.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_accent2_50"
+ android:color="@android:color/system_accent2_500"
android:lStar="98" />
</selector>
diff --git a/res/color-night-v31/folder_background_dark.xml b/res/color-night-v31/folder_background_dark.xml
index d607395..696e8ea 100644
--- a/res/color-night-v31/folder_background_dark.xml
+++ b/res/color-night-v31/folder_background_dark.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_neutral2_50"
+ android:color="@android:color/system_neutral2_500"
android:lStar="35" />
</selector>
diff --git a/res/color-night-v31/folder_preview_dark.xml b/res/color-night-v31/folder_preview_dark.xml
index a5bd636..bdd48a2 100644
--- a/res/color-night-v31/folder_preview_dark.xml
+++ b/res/color-night-v31/folder_preview_dark.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_neutral2_50"
+ android:color="@android:color/system_neutral2_500"
android:lStar="30" />
</selector>
diff --git a/res/color-v31/all_apps_button_bg_color.xml b/res/color-v31/all_apps_button_bg_color.xml
index 3ad38bc..8959020 100644
--- a/res/color-v31/all_apps_button_bg_color.xml
+++ b/res/color-v31/all_apps_button_bg_color.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_neutral1_50"
+ android:color="@android:color/system_neutral1_500"
android:lStar="98" />
</selector>
diff --git a/res/color-v31/all_apps_button_color_1.xml b/res/color-v31/all_apps_button_color_1.xml
index 2d0895e..71c7d8d 100644
--- a/res/color-v31/all_apps_button_color_1.xml
+++ b/res/color-v31/all_apps_button_color_1.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_accent1_50"
+ android:color="@android:color/system_accent1_500"
android:lStar="40" />
</selector>
diff --git a/res/color-v31/all_apps_button_color_2.xml b/res/color-v31/all_apps_button_color_2.xml
index 7674b43..608c8a9 100644
--- a/res/color-v31/all_apps_button_color_2.xml
+++ b/res/color-v31/all_apps_button_color_2.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_accent2_50"
+ android:color="@android:color/system_accent2_500"
android:lStar="48" />
</selector>
diff --git a/res/color-v31/all_apps_button_color_3.xml b/res/color-v31/all_apps_button_color_3.xml
index 17cb54f..dbb97b1 100644
--- a/res/color-v31/all_apps_button_color_3.xml
+++ b/res/color-v31/all_apps_button_color_3.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_accent1_50"
+ android:color="@android:color/system_accent1_500"
android:lStar="35" />
</selector>
diff --git a/res/color-v31/all_apps_button_color_4.xml b/res/color-v31/all_apps_button_color_4.xml
index a6150f1..d02528f6 100644
--- a/res/color-v31/all_apps_button_color_4.xml
+++ b/res/color-v31/all_apps_button_color_4.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_accent3_50"
+ android:color="@android:color/system_accent3_500"
android:lStar="48" />
</selector>
diff --git a/res/color-v31/folder_background_light.xml b/res/color-v31/folder_background_light.xml
index e3c7e7d..eb2fdd7 100644
--- a/res/color-v31/folder_background_light.xml
+++ b/res/color-v31/folder_background_light.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_neutral1_50"
+ android:color="@android:color/system_neutral1_500"
android:lStar="98" />
</selector>
diff --git a/res/color-v31/folder_preview_light.xml b/res/color-v31/folder_preview_light.xml
index fe30c87..ed1205e 100644
--- a/res/color-v31/folder_preview_light.xml
+++ b/res/color-v31/folder_preview_light.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_accent2_50"
+ android:color="@android:color/system_accent2_500"
android:lStar="80" />
</selector>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index e85969b..13f20c2 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -159,6 +159,17 @@
defaults to 2 * numHotseatIcons -->
<attr name="numExtendedHotseatIcons" format="integer" />
+ <!-- alignment of hotseat to the grid.
+ Not applicable for 3 button mode when taskbar is enabled -->
+ <!-- defaults to numColumns, if not specified -->
+ <attr name="hotseatColumnSpan" format="integer" />
+ <!-- defaults to numColumns, if not specified -->
+ <attr name="hotseatColumnSpanLandscape" format="integer" />
+ <!-- defaults to numColumns, if not specified -->
+ <attr name="hotseatColumnSpanTwoPanelLandscape" format="integer" />
+ <!-- defaults to numColumns, if not specified -->
+ <attr name="hotseatColumnSpanTwoPanelPortrait" format="integer" />
+
<attr name="dbFile" format="string" />
<attr name="defaultLayoutId" format="reference" />
<attr name="defaultSplitDisplayLayoutId" format="reference" />
@@ -306,17 +317,6 @@
if not specified -->
<attr name="allAppsBorderSpaceTwoPanelLandscapeVertical" format="float" />
- <!-- alignment of hotseat to the grid.
- Not applicable for 3 button mode when taskbar is enabled -->
- <!-- defaults to numColumns, if not specified -->
- <attr name="hotseatColumnSpan" format="integer" />
- <!-- defaults to numColumns, if not specified -->
- <attr name="hotseatColumnSpanLandscape" format="integer" />
- <!-- defaults to numColumns, if not specified -->
- <attr name="hotseatColumnSpanTwoPanelLandscape" format="integer" />
- <!-- defaults to numColumns, if not specified -->
- <attr name="hotseatColumnSpanTwoPanelPortrait" format="integer" />
-
<!-- defaults to borderSpaceDps, if not specified -->
<attr name="hotseatBorderSpace" format="float" />
<!-- defaults to hotseatBorderSpace, if not specified -->
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index a8ee721..098c694 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -100,7 +100,7 @@
<dimen name="fastscroll_end_margin">-26dp</dimen>
<!-- All Apps -->
- <dimen name="all_apps_starting_vertical_translate">320dp</dimen>
+ <dimen name="all_apps_starting_vertical_translate">300dp</dimen>
<dimen name="all_apps_search_bar_field_height">48dp</dimen>
<!-- all_apps_search_bar_field_height / 2 -->
<dimen name="all_apps_search_bar_content_overlap">24dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ee5e024..829a21d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -277,6 +277,9 @@
<!-- Summary for Notification dots setting. Tapping this will link enable/disable notification dots feature on the home screen. [CHAR LIMIT=50] -->
<string name="notification_dots_service_title">Show notification dots</string>
+ <!-- Title for Developer Options setting. [CHAR LIMIT=50] -->
+ <string name="developer_options_title">Developer Options</string>
+
<!-- Label for the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=60] -->
<string name="auto_add_shortcuts_label">Add app icons to home screen</string>
<!-- Text description of the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=NONE] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 864bb58..2109510 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -76,7 +76,7 @@
</style>
<style name="LauncherTheme.DarkMainColor" parent="@style/LauncherTheme">
- <item name="disabledIconAlpha">.254</item>
+ <item name="disabledIconAlpha">.54</item>
</style>
diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml
index 258da80..290bc8c 100644
--- a/res/xml/device_profiles.xml
+++ b/res/xml/device_profiles.xml
@@ -144,6 +144,7 @@
launcher:numFolderRows="3"
launcher:numFolderColumns="3"
launcher:numHotseatIcons="6"
+ launcher:hotseatColumnSpanLandscape="4"
launcher:numAllAppsColumns="6"
launcher:isScalable="true"
launcher:devicePaddingId="@xml/paddings_6x5"
@@ -176,7 +177,6 @@
launcher:allAppsBorderSpaceHorizontal="8"
launcher:allAppsBorderSpaceVertical="16"
launcher:allAppsBorderSpaceLandscape="16"
- launcher:hotseatColumnSpanLandscape="4"
launcher:hotseatBorderSpace="58"
launcher:hotseatBorderSpaceLandscape="50.4"
launcher:canBeDefault="true" />
diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml
index 90de498..8a0c909 100644
--- a/res/xml/launcher_preferences.xml
+++ b/res/xml/launcher_preferences.xml
@@ -53,7 +53,7 @@
<androidx.preference.PreferenceScreen
android:key="pref_developer_options"
android:persistent="false"
- android:title="Developer Options"
+ android:title="@string/developer_options_title"
android:fragment="com.android.launcher3.settings.DeveloperOptionsFragment"/>
</androidx.preference.PreferenceScreen>
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 87bbac6..76e945d 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -65,6 +65,7 @@
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.folder.PreviewBackground;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.util.CellAndSpan;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.ParcelableSparseArray;
@@ -290,7 +291,7 @@
for (int i = 0; i < mDragOutlineAnims.length; i++) {
final InterruptibleInOutAnimator anim =
- new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);
+ new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);
anim.getAnimator().setInterpolator(mEaseOutInterpolator);
final int thisIndex = i;
anim.getAnimator().addUpdateListener(new AnimatorUpdateListener() {
@@ -2440,7 +2441,7 @@
// First we determine if things have moved enough to cause a different layout
ItemConfiguration swapSolution = findReorderSolution(pixelXY[0], pixelXY[1], spanX, spanY,
- spanX, spanY, direction, dragView, true, new ItemConfiguration());
+ spanX, spanY, direction, dragView, true, new ItemConfiguration());
setUseTempCoords(true);
if (swapSolution != null && swapSolution.isSolution) {
@@ -2477,7 +2478,7 @@
// direction vector, since we want the solution to match the preview, and it's possible
// that the exact position of the item has changed to result in a new reordering outcome.
if ((mode == MODE_ON_DROP || mode == MODE_ON_DROP_EXTERNAL || mode == MODE_ACCEPT_DROP)
- && mPreviousReorderDirection[0] != INVALID_DIRECTION) {
+ && mPreviousReorderDirection[0] != INVALID_DIRECTION) {
mDirectionVector[0] = mPreviousReorderDirection[0];
mDirectionVector[1] = mPreviousReorderDirection[1];
// We reset this vector after drop
@@ -2493,7 +2494,7 @@
// Find a solution involving pushing / displacing any items in the way
ItemConfiguration swapSolution = findReorderSolution(pixelX, pixelY, minSpanX, minSpanY,
- spanX, spanY, mDirectionVector, dragView, true, new ItemConfiguration());
+ spanX, spanY, mDirectionVector, dragView, true, new ItemConfiguration());
// We attempt the approach which doesn't shuffle views at all
ItemConfiguration noShuffleSolution = findConfigurationNoShuffle(pixelX, pixelY, minSpanX,
@@ -2733,12 +2734,24 @@
}
public void markCellsAsOccupiedForView(View view) {
+ if (view instanceof LauncherAppWidgetHostView
+ && view.getTag() instanceof LauncherAppWidgetInfo) {
+ LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) view.getTag();
+ mOccupied.markCells(info.cellX, info.cellY, info.spanX, info.spanY, true);
+ return;
+ }
if (view == null || view.getParent() != mShortcutsAndWidgets) return;
LayoutParams lp = (LayoutParams) view.getLayoutParams();
mOccupied.markCells(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, true);
}
public void markCellsAsUnoccupiedForView(View view) {
+ if (view instanceof LauncherAppWidgetHostView
+ && view.getTag() instanceof LauncherAppWidgetInfo) {
+ LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) view.getTag();
+ mOccupied.markCells(info.cellX, info.cellY, info.spanX, info.spanY, false);
+ return;
+ }
if (view == null || view.getParent() != mShortcutsAndWidgets) return;
LayoutParams lp = (LayoutParams) view.getLayoutParams();
mOccupied.markCells(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, false);
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 561f9b9..be180a6 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -501,7 +501,7 @@
*/
private int calculateQsbWidth() {
if (isQsbInline) {
- int columns = getPanelCount() * inv.numColumns;
+ int columns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
return getIconToIconWidthForColumns(columns)
- iconSizePx * numShownHotseatIcons
- hotseatBorderSpace * numShownHotseatIcons;
@@ -901,10 +901,14 @@
result = new Point();
}
- result.x = calculateCellWidth(getShortcutAndWidgetContainerWidth(),
- cellLayoutBorderSpacePx.x, inv.numColumns);
- result.y = calculateCellHeight(getShortcutAndWidgetContainerHeight(),
- cellLayoutBorderSpacePx.y, inv.numRows);
+ int shortcutAndWidgetContainerWidth =
+ getCellLayoutWidth() - (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right);
+ result.x = calculateCellWidth(shortcutAndWidgetContainerWidth, cellLayoutBorderSpacePx.x,
+ inv.numColumns);
+ int shortcutAndWidgetContainerHeight =
+ getCellLayoutHeight() - (cellLayoutPaddingPx.top + cellLayoutPaddingPx.bottom);
+ result.y = calculateCellHeight(shortcutAndWidgetContainerHeight, cellLayoutBorderSpacePx.y,
+ inv.numRows);
return result;
}
@@ -966,7 +970,7 @@
scale = Math.min(scale, 1f);
// Reduce scale if next pages would not be visible after scaling the workspace
- int workspaceWidth = getWorkspaceWidth();
+ int workspaceWidth = availableWidthPx;
float scaledWorkspaceWidth = workspaceWidth * scale;
float maxAvailableWidth =
workspaceWidth - (2 * getWorkspaceSpringLoadedMinimumNextPageVisible());
@@ -977,27 +981,13 @@
}
/**
- * Gets the width of the Workspace, aka a scrollable page of the homescreen.
- */
- public int getWorkspaceWidth() {
- return availableWidthPx;
- }
-
- /**
- * Gets the height of the Workspace, aka a scrollable page of the homescreen.
- */
- public int getWorkspaceHeight() {
- return availableHeightPx;
- }
-
- /**
* Gets the width of a single Cell Layout, aka a single panel within a Workspace.
*
* <p>This is the width of a Workspace, less its horizontal padding. Note that two-panel
* layouts have two Cell Layouts per workspace.
*/
public int getCellLayoutWidth() {
- return (getWorkspaceWidth() - getTotalWorkspacePadding().x) / getPanelCount();
+ return (availableWidthPx - getTotalWorkspacePadding().x) / getPanelCount();
}
/**
@@ -1006,25 +996,7 @@
* <p>This is the height of a Workspace, less its vertical padding.
*/
public int getCellLayoutHeight() {
- return getWorkspaceHeight() - getTotalWorkspacePadding().y;
- }
-
- /**
- * Gets the width of the container holding the shortcuts and widgets.
- *
- * <p>This is the width of one Cell Layout less its horizontal padding.
- */
- public int getShortcutAndWidgetContainerWidth() {
- return getCellLayoutWidth() - (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right);
- }
-
- /**
- * Gets the height of the container holding the shortcuts and widgets.
- *
- * <p>This is the height of one Cell Layout less its vertical padding.
- */
- public int getShortcutAndWidgetContainerHeight() {
- return getCellLayoutHeight() - (cellLayoutPaddingPx.top + cellLayoutPaddingPx.bottom);
+ return availableHeightPx - getTotalWorkspacePadding().y;
}
public Point getTotalWorkspacePadding() {
@@ -1196,7 +1168,7 @@
return ((taskbarSize - overviewActionsHeight) / 2) + getTaskbarOffsetY();
}
- return 0;
+ return isTaskbarPresent ? stashedTaskbarSize : mInsets.bottom;
}
/** Gets the space that the overview actions will take, including bottom margin. */
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 0373eef..db43b44 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -127,7 +127,6 @@
public PointF[] borderSpaces;
public float folderBorderSpace;
public float[] hotseatBorderSpaces;
- public int[] hotseatColumnSpan;
public float[] horizontalMargin;
@@ -155,6 +154,8 @@
*/
public int numDatabaseHotseatIcons;
+ public int[] hotseatColumnSpan;
+
/**
* Number of columns in the all apps list.
*/
@@ -358,8 +359,8 @@
numShrunkenHotseatIcons = closestProfile.numShrunkenHotseatIcons;
numDatabaseHotseatIcons = deviceType == TYPE_MULTI_DISPLAY
? closestProfile.numDatabaseHotseatIcons : closestProfile.numHotseatIcons;
+ hotseatColumnSpan = closestProfile.hotseatColumnSpan;
hotseatBorderSpaces = displayOption.hotseatBorderSpaces;
- hotseatColumnSpan = displayOption.hotseatColumnSpan;
numAllAppsColumns = closestProfile.numAllAppsColumns;
numDatabaseAllAppsColumns = deviceType == TYPE_MULTI_DISPLAY
@@ -738,6 +739,7 @@
private final int numHotseatIcons;
private final int numShrunkenHotseatIcons;
private final int numDatabaseHotseatIcons;
+ private final int[] hotseatColumnSpan = new int[COUNT_SIZES];
private final String dbFile;
@@ -777,6 +779,16 @@
R.styleable.GridDisplayOption_numShrunkenHotseatIcons, numHotseatIcons / 2);
numDatabaseHotseatIcons = a.getInt(
R.styleable.GridDisplayOption_numExtendedHotseatIcons, 2 * numHotseatIcons);
+ hotseatColumnSpan[INDEX_DEFAULT] = a.getInt(
+ R.styleable.GridDisplayOption_hotseatColumnSpan, numColumns);
+ hotseatColumnSpan[INDEX_LANDSCAPE] = a.getInt(
+ R.styleable.GridDisplayOption_hotseatColumnSpanLandscape, numColumns);
+ hotseatColumnSpan[INDEX_TWO_PANEL_LANDSCAPE] = a.getInt(
+ R.styleable.GridDisplayOption_hotseatColumnSpanTwoPanelLandscape,
+ numColumns);
+ hotseatColumnSpan[INDEX_TWO_PANEL_PORTRAIT] = a.getInt(
+ R.styleable.GridDisplayOption_hotseatColumnSpanTwoPanelPortrait,
+ numColumns);
numFolderRows = a.getInt(
R.styleable.GridDisplayOption_numFolderRows, numRows);
@@ -826,7 +838,6 @@
private final float[] horizontalMargin = new float[COUNT_SIZES];
//TODO(http://b/228998082) remove this when 3 button spaces are fixed
private final float[] hotseatBorderSpaces = new float[COUNT_SIZES];
- private final int[] hotseatColumnSpan = new int[COUNT_SIZES];
private final float[] iconSizes = new float[COUNT_SIZES];
private final float[] textSizes = new float[COUNT_SIZES];
@@ -1052,17 +1063,6 @@
R.styleable.ProfileDisplayOption_hotseatBorderSpaceTwoPanelPortrait,
hotseatBorderSpaces[INDEX_DEFAULT]);
- hotseatColumnSpan[INDEX_DEFAULT] = a.getInt(
- R.styleable.ProfileDisplayOption_hotseatColumnSpan, grid.numColumns);
- hotseatColumnSpan[INDEX_LANDSCAPE] = a.getInt(
- R.styleable.ProfileDisplayOption_hotseatColumnSpanLandscape, grid.numColumns);
- hotseatColumnSpan[INDEX_TWO_PANEL_LANDSCAPE] = a.getInt(
- R.styleable.ProfileDisplayOption_hotseatColumnSpanTwoPanelLandscape,
- grid.numColumns);
- hotseatColumnSpan[INDEX_TWO_PANEL_PORTRAIT] = a.getInt(
- R.styleable.ProfileDisplayOption_hotseatColumnSpanTwoPanelPortrait,
- grid.numColumns);
-
a.recycle();
}
@@ -1121,7 +1121,6 @@
minCellSize[i].y += p.minCellSize[i].y;
horizontalMargin[i] += p.horizontalMargin[i];
hotseatBorderSpaces[i] += p.hotseatBorderSpaces[i];
- hotseatColumnSpan[i] = p.hotseatColumnSpan[i];
allAppsCellSize[i].x += p.allAppsCellSize[i].x;
allAppsCellSize[i].y += p.allAppsCellSize[i].y;
allAppsIconSizes[i] += p.allAppsIconSizes[i];
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index ad87451..135b88d 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1169,6 +1169,7 @@
}
AbstractFloatingView.closeAllOpenViewsExcept(this, false, TYPE_REBIND_SAFE);
+ DragView.removeAllViews(this);
TraceHelper.INSTANCE.endSection(traceToken);
}
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 4501159..597bc8d 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
+
import static com.android.launcher3.Utilities.getDevicePrefs;
import static com.android.launcher3.config.FeatureFlags.ENABLE_THEMED_ICONS;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -97,7 +99,8 @@
modelChangeReceiver.register(mContext, Intent.ACTION_LOCALE_CHANGED,
Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
- Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
+ Intent.ACTION_MANAGED_PROFILE_UNLOCKED,
+ ACTION_DEVICE_POLICY_RESOURCE_UPDATED);
if (FeatureFlags.IS_STUDIO_BUILD) {
modelChangeReceiver.register(mContext, Context.RECEIVER_EXPORTED, ACTION_FORCE_ROLOAD);
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index ee6f51e..5c5c101 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
+
import static com.android.launcher3.LauncherAppState.ACTION_FORCE_ROLOAD;
import static com.android.launcher3.config.FeatureFlags.IS_STUDIO_BUILD;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -51,6 +53,7 @@
import com.android.launcher3.model.PackageIncrementalDownloadUpdatedTask;
import com.android.launcher3.model.PackageInstallStateChangedTask;
import com.android.launcher3.model.PackageUpdatedTask;
+import com.android.launcher3.model.ReloadStringCacheTask;
import com.android.launcher3.model.ShortcutsChangedTask;
import com.android.launcher3.model.UserLockStateChangedTask;
import com.android.launcher3.model.data.AppInfo;
@@ -278,6 +281,8 @@
user, Intent.ACTION_MANAGED_PROFILE_UNLOCKED.equals(action)));
}
}
+ } else if (ACTION_DEVICE_POLICY_RESOURCE_UPDATED.equals(action)) {
+ enqueueModelUpdateTask(new ReloadStringCacheTask(mModelDelegate));
} else if (IS_STUDIO_BUILD && ACTION_FORCE_ROLOAD.equals(action)) {
for (Callbacks cb : getCallbacks()) {
if (cb instanceof Launcher) {
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index bf56ac0..a991c2f 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -36,6 +36,7 @@
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS;
import static com.android.launcher3.graphics.SysUiScrim.SYSUI_PROGRESS;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
@@ -117,8 +118,6 @@
}
int elements = state.getVisibleElements(mLauncher);
- Interpolator fadeInterpolator = config.getInterpolator(ANIM_WORKSPACE_FADE,
- pageAlphaProvider.interpolator);
Hotseat hotseat = mWorkspace.getHotseat();
Interpolator scaleInterpolator = config.getInterpolator(ANIM_WORKSPACE_SCALE, ZOOM_OUT);
LauncherState fromState = mLauncher.getStateManager().getState();
@@ -146,11 +145,15 @@
hotseatScaleInterpolator);
}
- float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0;
- propertySetter.setViewAlpha(hotseat, hotseatIconsAlpha, fadeInterpolator);
+ Interpolator workspaceFadeInterpolator = config.getInterpolator(ANIM_WORKSPACE_FADE,
+ pageAlphaProvider.interpolator);
float workspacePageIndicatorAlpha = (elements & WORKSPACE_PAGE_INDICATOR) != 0 ? 1 : 0;
propertySetter.setViewAlpha(mLauncher.getWorkspace().getPageIndicator(),
- workspacePageIndicatorAlpha, fadeInterpolator);
+ workspacePageIndicatorAlpha, workspaceFadeInterpolator);
+ Interpolator hotseatFadeInterpolator = config.getInterpolator(ANIM_HOTSEAT_FADE,
+ workspaceFadeInterpolator);
+ float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0;
+ propertySetter.setViewAlpha(hotseat, hotseatIconsAlpha, hotseatFadeInterpolator);
// Update the accessibility flags for hotseat based on launcher state.
hotseat.setImportantForAccessibility(
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 58df50c..33d2f2b 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -118,7 +118,7 @@
List<AdapterItem> items = mApps.getAdapterItems();
adapterPosition = Math.max(adapterPosition, items.size() - 1);
int extraRows = 0;
- for (int i = 0; i <= adapterPosition; i++) {
+ for (int i = 0; i <= adapterPosition && i < items.size(); i++) {
if (!isViewType(items.get(i).viewType, VIEW_TYPE_MASK_ICON)) {
extraRows++;
}
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index bdfeada..096e2c8 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -228,6 +228,8 @@
requestFocus();
mgr.logger().sendToInteractionJankMonitor(
LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN, this);
+ hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
+ getApplicationWindowToken());
break;
case SCROLL_STATE_IDLE:
mgr.logger().sendToInteractionJankMonitor(
@@ -243,8 +245,6 @@
&& mEmptySearchBackground != null && mEmptySearchBackground.getAlpha() > 0) {
mEmptySearchBackground.setHotspot(e.getX(), e.getY());
}
- hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
- getApplicationWindowToken());
return result;
}
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
index 5bbc67e..95c67dd 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -17,6 +17,7 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB;
+import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -437,8 +438,12 @@
if (showTabs == mUsingTabs && !force) {
return;
}
+
+ // replaceRVcontainer() needs to use both mUsingTabs value to remove the old view AND
+ // showTabs value to create new view. Hence the mUsingTabs new value assignment MUST happen
+ // after this call.
+ replaceRVContainer(showTabs);
mUsingTabs = showTabs;
- replaceRVContainer(mUsingTabs);
mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
@@ -454,6 +459,8 @@
mActivityContext.getStatsLogManager().logger()
.log(LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB);
}
+ hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
+ getApplicationWindowToken());
});
findViewById(R.id.tab_work)
.setOnClickListener((View view) -> {
@@ -461,6 +468,8 @@
mActivityContext.getStatsLogManager().logger()
.log(LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB);
}
+ hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
+ getApplicationWindowToken());
});
setDeviceManagementResources();
onActivePageChanged(mViewPager.getNextPage());
diff --git a/src/com/android/launcher3/anim/AnimationSuccessListener.java b/src/com/android/launcher3/anim/AnimationSuccessListener.java
index a312070..6196df2 100644
--- a/src/com/android/launcher3/anim/AnimationSuccessListener.java
+++ b/src/com/android/launcher3/anim/AnimationSuccessListener.java
@@ -19,6 +19,8 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import androidx.annotation.CallSuper;
+
/**
* Extension of {@link AnimatorListenerAdapter} for listening for non-cancelled animations
*/
@@ -27,6 +29,7 @@
protected boolean mCancelled = false;
@Override
+ @CallSuper
public void onAnimationCancel(Animator animation) {
mCancelled = true;
}
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index f8a2c79..c38cf9a 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -57,6 +57,11 @@
public static final Interpolator DECELERATED_EASE = new PathInterpolator(0, 0, .2f, 1f);
public static final Interpolator ACCELERATED_EASE = new PathInterpolator(0.4f, 0, 1f, 1f);
+ public static final Interpolator EMPHASIZED_ACCELERATE = new PathInterpolator(
+ 0.3f, 0f, 0.8f, 0.15f);
+ public static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator(
+ 0.05f, 0.7f, 0.1f, 1f);
+
public static final Interpolator EXAGGERATED_EASE;
public static final Interpolator INSTANT = t -> 1;
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 626e15c..54edb33 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -261,6 +261,10 @@
public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = new DeviceFlag(
"ENABLE_ONE_SEARCH_MOTION", true, "Enables animations in OneSearch.");
+ public static final BooleanFlag ENABLE_SHOW_KEYBOARD_IN_ALL_APPS = getDebugFlag(
+ "ENABLE_SHOW_KEYBOARD_IN_ALL_APPS", false,
+ "Enable option to show keyboard when going to all-apps");
+
public static final BooleanFlag USE_LOCAL_ICON_OVERRIDES = getDebugFlag(
"USE_LOCAL_ICON_OVERRIDES", true,
"Use inbuilt monochrome icons if app doesn't provide one");
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index a3945fd..0264ae2 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -578,4 +578,19 @@
iv.setImageDrawable(drawable);
return iv;
}
+
+ /**
+ * Removes any stray DragView from the DragLayer.
+ */
+ public static void removeAllViews(ActivityContext activity) {
+ BaseDragLayer dragLayer = activity.getDragLayer();
+ // Iterate in reverse order. DragView is added later to the dragLayer,
+ // and will be one of the last views.
+ for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) {
+ View child = dragLayer.getChildAt(i);
+ if (child instanceof DragView) {
+ dragLayer.removeView(child);
+ }
+ }
+ }
}
diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java
index 2b621bd..5021644 100644
--- a/src/com/android/launcher3/folder/FolderNameProvider.java
+++ b/src/com/android/launcher3/folder/FolderNameProvider.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.folder;
+import android.annotation.SuppressLint;
+import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.os.Process;
@@ -22,11 +24,15 @@
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.WorkerThread;
+
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.model.AllAppsList;
import com.android.launcher3.model.BaseModelUpdateTask;
import com.android.launcher3.model.BgDataModel;
+import com.android.launcher3.model.StringCache;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -94,6 +100,7 @@
/**
* Generate and rank the suggested Folder names.
*/
+ @WorkerThread
public void getSuggestedFolderName(Context context,
ArrayList<WorkspaceItemInfo> workspaceItemInfos,
FolderNameInfos nameInfos) {
@@ -107,8 +114,7 @@
Set<UserHandle> users = workspaceItemInfos.stream().map(w -> w.user)
.collect(Collectors.toSet());
if (users.size() == 1 && !users.contains(Process.myUserHandle())) {
- String workFolderName = context.getString(R.string.work_folder_name);
- setAsLastSuggestion(nameInfos, workFolderName);
+ setAsLastSuggestion(nameInfos, getWorkFolderName(context));
}
// If all the icons are from same package (e.g., main icon, shortcut, shortcut)
@@ -130,6 +136,17 @@
}
}
+ @WorkerThread
+ @SuppressLint("NewApi")
+ private String getWorkFolderName(Context context) {
+ if (!Utilities.ATLEAST_T) {
+ return context.getString(R.string.work_folder_name);
+ }
+ return context.getSystemService(DevicePolicyManager.class).getResources()
+ .getString(StringCache.WORK_FOLDER_NAME, () ->
+ context.getString(R.string.work_folder_name));
+ }
+
private Optional<AppInfo> getAppInfoByPackageName(String packageName) {
if (mAppInfos == null || mAppInfos.isEmpty()) {
return Optional.empty();
diff --git a/src/com/android/launcher3/model/ReloadStringCacheTask.java b/src/com/android/launcher3/model/ReloadStringCacheTask.java
new file mode 100644
index 0000000..f4d4298
--- /dev/null
+++ b/src/com/android/launcher3/model/ReloadStringCacheTask.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 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.launcher3.model;
+
+import com.android.launcher3.LauncherAppState;
+
+/**
+ * Handles updates due to changes in Device Policy Management resources triggered by
+ * {@link android.app.admin.DevicePolicyManager#ACTION_DEVICE_POLICY_RESOURCE_UPDATED}.
+ */
+public class ReloadStringCacheTask extends BaseModelUpdateTask {
+ private ModelDelegate mModelDelegate;
+
+ public ReloadStringCacheTask(ModelDelegate modelDelegate) {
+ mModelDelegate = modelDelegate;
+ }
+
+ @Override
+ public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList appsList) {
+ synchronized (dataModel) {
+ mModelDelegate.loadStringCache(dataModel.stringCache);
+ StringCache cloneSC = dataModel.stringCache.clone();
+ scheduleCallbackTask(c -> c.bindStringCache(cloneSC));
+ }
+ }
+}
diff --git a/src/com/android/launcher3/model/StringCache.java b/src/com/android/launcher3/model/StringCache.java
index 663a463..9859ddc 100644
--- a/src/com/android/launcher3/model/StringCache.java
+++ b/src/com/android/launcher3/model/StringCache.java
@@ -35,6 +35,11 @@
private static final String PREFIX = "Launcher.";
/**
+ * Work folder name.
+ */
+ public static final String WORK_FOLDER_NAME = PREFIX + "WORK_FOLDER_NAME";
+
+ /**
* User on-boarding title for work profile apps.
*/
private static final String WORK_PROFILE_EDU = PREFIX + "WORK_PROFILE_EDU";
@@ -91,11 +96,6 @@
PREFIX + "ALL_APPS_PERSONAL_TAB_ACCESSIBILITY";
/**
- * Work folder name.
- */
- private static final String WORK_FOLDER_NAME = PREFIX + "WORK_FOLDER_NAME";
-
- /**
* Label on widget tab to indicate work app widgets.
*/
private static final String WIDGETS_WORK_TAB = PREFIX + "WIDGETS_WORK_TAB";
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index 2aa9dde..9f50ff9 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -335,7 +335,13 @@
@Override
public void onAnimationStart(Animator animation) {
// Change the internal state only when the transition actually starts
- onStateTransitionStart(state);
+ onStateTransitionStart(mCancelled ? mCurrentStableState : state);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ super.onAnimationCancel(animation);
+ mState = mCurrentStableState;
}
@Override
diff --git a/src/com/android/launcher3/states/StateAnimationConfig.java b/src/com/android/launcher3/states/StateAnimationConfig.java
index f04e685..f99519d 100644
--- a/src/com/android/launcher3/states/StateAnimationConfig.java
+++ b/src/com/android/launcher3/states/StateAnimationConfig.java
@@ -53,6 +53,7 @@
ANIM_WORKSPACE_FADE,
ANIM_HOTSEAT_SCALE,
ANIM_HOTSEAT_TRANSLATE,
+ ANIM_HOTSEAT_FADE,
ANIM_OVERVIEW_SCALE,
ANIM_OVERVIEW_TRANSLATE_X,
ANIM_OVERVIEW_TRANSLATE_Y,
@@ -72,6 +73,7 @@
public static final int ANIM_WORKSPACE_FADE = 3;
public static final int ANIM_HOTSEAT_SCALE = 4;
public static final int ANIM_HOTSEAT_TRANSLATE = 5;
+ public static final int ANIM_HOTSEAT_FADE = 16;
public static final int ANIM_OVERVIEW_SCALE = 6;
public static final int ANIM_OVERVIEW_TRANSLATE_X = 7;
public static final int ANIM_OVERVIEW_TRANSLATE_Y = 8;
@@ -83,7 +85,7 @@
public static final int ANIM_OVERVIEW_ACTIONS_FADE = 14;
public static final int ANIM_WORKSPACE_PAGE_TRANSLATE_X = 15;
- private static final int ANIM_TYPES_COUNT = 16;
+ private static final int ANIM_TYPES_COUNT = 17;
protected final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT];
diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java
index 5aac3f3..9d7fd9a 100644
--- a/src/com/android/launcher3/touch/AllAppsSwipeController.java
+++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java
@@ -17,11 +17,19 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.anim.Interpolators.DECELERATED_EASE;
+import static com.android.launcher3.anim.Interpolators.EMPHASIZED_ACCELERATE;
+import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE;
import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_DEPTH;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
@@ -39,11 +47,41 @@
private static final float ALLAPPS_STAGGERED_FADE_THRESHOLD = 0.5f;
+ // Custom timing for NORMAL -> ALL_APPS on phones only.
+ private static final float WORKSPACE_MOTION_START = 0.1667f;
+ private static final float ALL_APPS_STATE_TRANSITION = 0.305f;
+ private static final float ALL_APPS_FADE_END = 0.4717f;
+
public static final Interpolator ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER =
Interpolators.clampToProgress(LINEAR, 0, ALLAPPS_STAGGERED_FADE_THRESHOLD);
public static final Interpolator ALLAPPS_STAGGERED_FADE_LATE_RESPONDER =
Interpolators.clampToProgress(LINEAR, ALLAPPS_STAGGERED_FADE_THRESHOLD, 1f);
+ // Custom interpolators for NORMAL -> ALL_APPS on phones only.
+ public static final Interpolator BLUR =
+ Interpolators.clampToProgress(
+ EMPHASIZED_DECELERATE, WORKSPACE_MOTION_START, ALL_APPS_STATE_TRANSITION);
+ public static final Interpolator WORKSPACE_SCALE =
+ Interpolators.clampToProgress(
+ EMPHASIZED_DECELERATE, WORKSPACE_MOTION_START, ALL_APPS_STATE_TRANSITION);
+ public static final Interpolator HOTSEAT_FADE =
+ Interpolators.clampToProgress(FINAL_FRAME, 0f, ALL_APPS_STATE_TRANSITION);
+ public static final Interpolator HOTSEAT_TRANSLATE =
+ Interpolators.clampToProgress(
+ EMPHASIZED_ACCELERATE, WORKSPACE_MOTION_START, ALL_APPS_STATE_TRANSITION);
+ public static final Interpolator SCRIM_FADE =
+ Interpolators.clampToProgress(
+ Interpolators.mapToProgress(LINEAR, 0f, 0.8f),
+ WORKSPACE_MOTION_START, ALL_APPS_STATE_TRANSITION);
+ public static final Interpolator ALL_APPS_FADE =
+ Interpolators.clampToProgress(
+ Interpolators.mapToProgress(DECELERATED_EASE, 0.2f, 1.0f),
+ ALL_APPS_STATE_TRANSITION, ALL_APPS_FADE_END);
+ public static final Interpolator ALL_APPS_VERTICAL_PROGRESS =
+ Interpolators.clampToProgress(
+ Interpolators.mapToProgress(EMPHASIZED_DECELERATE, 0.4f, 1.0f),
+ ALL_APPS_STATE_TRANSITION, 1.0f);
+
public AllAppsSwipeController(Launcher l) {
super(l, SingleAxisSwipeDetector.VERTICAL);
}
@@ -118,11 +156,17 @@
*/
public static void applyNormalToAllAppsAnimConfig(Launcher launcher,
StateAnimationConfig config) {
- boolean isTablet = launcher.getDeviceProfile().isTablet;
- config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
- config.setInterpolator(ANIM_ALL_APPS_FADE, isTablet
- ? INSTANT : ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
+ if (launcher.getDeviceProfile().isTablet) {
+ config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
+ config.setInterpolator(ANIM_ALL_APPS_FADE, INSTANT);
+ } else {
+ config.setInterpolator(ANIM_DEPTH, BLUR);
+ config.setInterpolator(ANIM_WORKSPACE_SCALE, WORKSPACE_SCALE);
+ config.setInterpolator(ANIM_HOTSEAT_FADE, HOTSEAT_FADE);
+ config.setInterpolator(ANIM_HOTSEAT_TRANSLATE, HOTSEAT_TRANSLATE);
+ config.setInterpolator(ANIM_SCRIM_FADE, SCRIM_FADE);
+ config.setInterpolator(ANIM_ALL_APPS_FADE, ALL_APPS_FADE);
+ config.setInterpolator(ANIM_VERTICAL_PROGRESS, ALL_APPS_VERTICAL_PROGRESS);
+ }
}
-
-
}
diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index a982786..7a8e9d5 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -20,6 +20,8 @@
import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE;
+import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync;
+
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
@@ -283,6 +285,9 @@
}
break;
case MotionEvent.ACTION_UP:
+ hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
+ getApplicationWindowToken());
+ break;
case MotionEvent.ACTION_CANCEL:
mRv.onFastScrollCompleted();
mTouchOffsetY = 0;
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
index 52a6759..ec921e8 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -59,15 +59,21 @@
@Override
public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
- ScaleAndTranslation scaleAndTranslation =
- new ScaleAndTranslation(NO_SCALE, NO_OFFSET, NO_OFFSET);
+ return new ScaleAndTranslation(0.97f, NO_OFFSET, NO_OFFSET);
+ }
+
+ @Override
+ public ScaleAndTranslation getHotseatScaleAndTranslation(Launcher launcher) {
if (launcher.getDeviceProfile().isTablet) {
- scaleAndTranslation.scale = 0.97f;
+ return getWorkspaceScaleAndTranslation(launcher);
} else {
- scaleAndTranslation.translationY =
- -launcher.getAllAppsController().getShiftRange() * PARALLAX_COEFFICIENT;
+ ScaleAndTranslation overviewScaleAndTranslation = LauncherState.OVERVIEW
+ .getWorkspaceScaleAndTranslation(launcher);
+ return new ScaleAndTranslation(
+ NO_SCALE,
+ overviewScaleAndTranslation.translationX,
+ overviewScaleAndTranslation.translationY);
}
- return scaleAndTranslation;
}
@Override
diff --git a/tests/src/com/android/launcher3/DeviceProfileGridDimensionsTest.kt b/tests/src/com/android/launcher3/DeviceProfileGridDimensionsTest.kt
index 63abc7d..80259a5 100644
--- a/tests/src/com/android/launcher3/DeviceProfileGridDimensionsTest.kt
+++ b/tests/src/com/android/launcher3/DeviceProfileGridDimensionsTest.kt
@@ -35,42 +35,6 @@
class DeviceProfileGridDimensionsTest : DeviceProfileBaseTest() {
@Test
- fun getWorkspaceWidth_twoPanelLandscapeScalable4By4GridTablet_workspaceWidthIsFullPage() {
- val tabletWidth = 2560
- val tabletHeight = 1600
- val availableWidth = 2560
- val availableHeight = 1500
- windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
- useTwoPanels = true
- whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
-
- val dp = newDP()
-
- val expectedWorkspaceWidth = availableWidth
- assertThat(dp.workspaceWidth).isEqualTo(expectedWorkspaceWidth)
- }
-
- @Test
- fun getWorkspaceHeight_twoPanelLandscapeScalable4By4GridTablet_workspaceHeightIsFullPage() {
- val tabletWidth = 2560
- val tabletHeight = 1600
- val availableWidth = 2560
- val availableHeight = 1500
- windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
- useTwoPanels = true
- whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
-
- val dp = newDP()
-
- val expectedWorkspaceHeight = availableHeight
- assertThat(dp.workspaceHeight).isEqualTo(expectedWorkspaceHeight)
- }
-
- @Test
fun getCellLayoutWidth_twoPanelLandscapeScalable4By4GridTablet_equalsSinglePanelWidth() {
val tabletWidth = 2560
val tabletHeight = 1600
@@ -79,8 +43,8 @@
windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
useTwoPanels = true
whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
+ whenever(info.densityDpi).thenReturn(320)
+ inv = newScalableInvariantDeviceProfile()
val dp = newDP()
@@ -100,8 +64,8 @@
windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
useTwoPanels = true
whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
+ whenever(info.densityDpi).thenReturn(320)
+ inv = newScalableInvariantDeviceProfile()
val dp = newDP()
@@ -112,52 +76,6 @@
}
@Test
- fun getShortcutAndWidgetContainerWidth_twoPanelLandscapeScalable4By4GridTablet_equalsIconsPlusBorderSpacesWidth() {
- val tabletWidth = 2560
- val tabletHeight = 1600
- val availableWidth = 2560
- val availableHeight = 1500
- windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
- useTwoPanels = true
- whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
-
- val dp = newDP()
-
- val expectedWorkspaceWidth = availableWidth
- val expectedCellLayoutWidth =
- (expectedWorkspaceWidth - (dp.workspacePadding.right + dp.workspacePadding.left)) /
- dp.panelCount
- val expectedShortcutAndWidgetContainerWidth = expectedCellLayoutWidth -
- (dp.cellLayoutPaddingPx.left + dp.cellLayoutPaddingPx.right)
- assertThat(dp.shortcutAndWidgetContainerWidth).isEqualTo(expectedShortcutAndWidgetContainerWidth)
- }
-
- @Test
- fun getShortcutAndWidgetContainerHeight_twoPanelLandscapeScalable4By4GridTablet_equalsIconsPlusBorderSpacesHeight() {
- val tabletWidth = 2560
- val tabletHeight = 1600
- val availableWidth = 2560
- val availableHeight = 1500
- windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
- useTwoPanels = true
- whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
-
- val dp = newDP()
-
- val expectedWorkspaceHeight = availableHeight
- val expectedCellLayoutHeight =
- expectedWorkspaceHeight - (dp.workspacePadding.top + dp.workspacePadding.bottom)
- val expectedShortcutAndWidgetContainerHeight = expectedCellLayoutHeight -
- (dp.cellLayoutPaddingPx.top + dp.cellLayoutPaddingPx.bottom)
- assertThat(dp.shortcutAndWidgetContainerHeight).isEqualTo(
- expectedShortcutAndWidgetContainerHeight)
- }
-
- @Test
fun getCellSize_twoPanelLandscapeScalable4By4GridTablet_equalsSinglePanelWidth() {
val tabletWidth = 2560
val tabletHeight = 1600
@@ -166,8 +84,8 @@
windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
useTwoPanels = true
whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
+ whenever(info.densityDpi).thenReturn(320)
+ inv = newScalableInvariantDeviceProfile()
val dp = newDP()
@@ -200,59 +118,11 @@
windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
useTwoPanels = true
whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
+ whenever(info.densityDpi).thenReturn(320)
+ inv = newScalableInvariantDeviceProfile()
val dp = newDP()
assertThat(dp.panelCount).isEqualTo(2)
}
-
- fun getScalable4By4InvariantDeviceProfile(): InvariantDeviceProfile {
- return InvariantDeviceProfile().apply {
- isScalable = true
- numColumns = 4
- numRows = 4
- numShownHotseatIcons = 4
- numDatabaseHotseatIcons = 6
- numShrunkenHotseatIcons = 5
- horizontalMargin = FloatArray(4) { 22f }
- borderSpaces = listOf(
- PointF(16f, 16f),
- PointF(16f, 16f),
- PointF(16f, 16f),
- PointF(16f, 16f)
- ).toTypedArray()
- allAppsBorderSpaces = listOf(
- PointF(16f, 16f),
- PointF(16f, 16f),
- PointF(16f, 16f),
- PointF(16f, 16f)
- ).toTypedArray()
- hotseatBorderSpaces = FloatArray(4) { 16f }
- hotseatColumnSpan = IntArray(4) { 4 }
- iconSize = FloatArray(4) { 56f }
- allAppsIconSize = FloatArray(4) { 56f }
- iconTextSize = FloatArray(4) { 14f }
- allAppsIconTextSize = FloatArray(4) { 14f }
- minCellSize = listOf(
- PointF(64f, 83f),
- PointF(64f, 83f),
- PointF(64f, 83f),
- PointF(64f, 83f)
- ).toTypedArray()
- allAppsCellSize = listOf(
- PointF(64f, 83f),
- PointF(64f, 83f),
- PointF(64f, 83f),
- PointF(64f, 83f)
- ).toTypedArray()
- inlineQsb = booleanArrayOf(
- false,
- false,
- false,
- false
- )
- }
- }
}
\ No newline at end of file