Merge "Play window close animation to home for most app to launcher scenarios" into sc-v2-dev
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index fcbea77..c80818a 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -24,6 +24,7 @@
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
@@ -35,6 +36,7 @@
import android.content.Intent;
import android.content.IntentSender;
import android.content.ServiceConnection;
+import android.graphics.Insets;
import android.hardware.SensorManager;
import android.hardware.devicestate.DeviceStateManager;
import android.os.Bundle;
@@ -43,6 +45,7 @@
import android.os.IBinder;
import android.util.Log;
import android.view.View;
+import android.view.WindowInsets;
import android.window.SplashScreen;
import androidx.annotation.Nullable;
@@ -639,4 +642,17 @@
mDepthController.dump(prefix, writer);
}
}
+
+ @Override
+ public void updateWindowInsets(WindowInsets.Builder updatedInsetsBuilder,
+ WindowInsets oldInsets) {
+ // Override the tappable insets to be 0 on the bottom for gesture nav (otherwise taskbar
+ // would count towards it). This is used for the bottom protection in All Apps for example.
+ if (SysUINavigationMode.getMode(this) == NO_BUTTON) {
+ Insets oldTappableInsets = oldInsets.getInsets(WindowInsets.Type.tappableElement());
+ Insets newTappableInsets = Insets.of(oldTappableInsets.left, oldTappableInsets.top,
+ oldTappableInsets.right, 0);
+ updatedInsetsBuilder.setInsets(WindowInsets.Type.tappableElement(), newTappableInsets);
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 978fb57..e3e7b33 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -51,6 +51,7 @@
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskThumbnailView;
import com.android.quickstep.views.TaskView;
+import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -63,11 +64,16 @@
public class TaskOverlayFactory implements ResourceBasedOverride {
public static List<SystemShortcut> getEnabledShortcuts(TaskView taskView,
- DeviceProfile deviceProfile) {
+ DeviceProfile deviceProfile, TaskIdAttributeContainer taskContainer) {
final ArrayList<SystemShortcut> shortcuts = new ArrayList<>();
final BaseDraggingActivity activity = BaseActivity.fromContext(taskView.getContext());
+ boolean hasMultipleTasks = taskView.getTaskIds()[1] != -1;
for (TaskShortcutFactory menuOption : MENU_OPTIONS) {
- SystemShortcut shortcut = menuOption.getShortcut(activity, taskView);
+ if (hasMultipleTasks && !menuOption.showForSplitscreen()) {
+ continue;
+ }
+
+ SystemShortcut shortcut = menuOption.getShortcut(activity, taskContainer);
if (shortcut == null) {
continue;
}
@@ -87,7 +93,7 @@
if (!canLauncherRotate && isInLandscape) {
// Add screenshot action to task menu.
SystemShortcut screenshotShortcut = TaskShortcutFactory.SCREENSHOT
- .getShortcut(activity, taskView);
+ .getShortcut(activity, taskContainer);
if (screenshotShortcut != null) {
shortcuts.add(screenshotShortcut);
}
@@ -95,7 +101,7 @@
// Add modal action only if display orientation is the same as the device orientation.
if (orientedState.getDisplayRotation() == ROTATION_0) {
SystemShortcut modalShortcut = TaskShortcutFactory.MODAL
- .getShortcut(activity, taskView);
+ .getShortcut(activity, taskContainer);
if (modalShortcut != null) {
shortcuts.add(modalShortcut);
}
@@ -105,7 +111,7 @@
}
- public static void addSplitOptions(List<SystemShortcut> outShortcuts,
+ private static void addSplitOptions(List<SystemShortcut> outShortcuts,
BaseDraggingActivity activity, TaskView taskView, DeviceProfile deviceProfile) {
int[] taskViewTaskIds = taskView.getTaskIds();
boolean alreadyHasMultipleTasks = taskViewTaskIds[0] != -1 &&
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index 559125e..dbb5f10 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -45,6 +45,7 @@
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskThumbnailView;
import com.android.quickstep.views.TaskView;
+import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
@@ -61,9 +62,25 @@
* Represents a system shortcut that can be shown for a recent task.
*/
public interface TaskShortcutFactory {
- SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView view);
+ SystemShortcut getShortcut(BaseDraggingActivity activity,
+ TaskIdAttributeContainer taskContainer);
- TaskShortcutFactory APP_INFO = (activity, view) -> new AppInfo(activity, view.getItemInfo());
+ default boolean showForSplitscreen() {
+ return false;
+ }
+
+ TaskShortcutFactory APP_INFO = new TaskShortcutFactory() {
+ @Override
+ public SystemShortcut getShortcut(BaseDraggingActivity activity,
+ TaskIdAttributeContainer taskContainer) {
+ return new AppInfo(activity, taskContainer.getItemInfo());
+ }
+
+ @Override
+ public boolean showForSplitscreen() {
+ return true;
+ }
+ };
abstract class MultiWindowFactory implements TaskShortcutFactory {
@@ -82,15 +99,16 @@
protected abstract boolean onActivityStarted(BaseDraggingActivity activity);
@Override
- public SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView taskView) {
- final Task task = taskView.getTask();
+ public SystemShortcut getShortcut(BaseDraggingActivity activity,
+ TaskIdAttributeContainer taskContainer) {
+ final Task task = taskContainer.getTask();
if (!task.isDockable) {
return null;
}
if (!isAvailable(activity, task.key.displayId)) {
return null;
}
- return new MultiWindowSystemShortcut(mIconRes, mTextRes, activity, taskView, this,
+ return new MultiWindowSystemShortcut(mIconRes, mTextRes, activity, taskContainer, this,
mLauncherEvent);
}
}
@@ -123,13 +141,14 @@
private final LauncherEvent mLauncherEvent;
public MultiWindowSystemShortcut(int iconRes, int textRes, BaseDraggingActivity activity,
- TaskView taskView, MultiWindowFactory factory, LauncherEvent launcherEvent) {
- super(iconRes, textRes, activity, taskView.getItemInfo());
+ TaskIdAttributeContainer taskContainer, MultiWindowFactory factory,
+ LauncherEvent launcherEvent) {
+ super(iconRes, textRes, activity, taskContainer.getItemInfo());
mLauncherEvent = launcherEvent;
mHandler = new Handler(Looper.getMainLooper());
- mTaskView = taskView;
+ mTaskView = taskContainer.getTaskView();
mRecentsView = activity.getOverviewPanel();
- mThumbnailView = taskView.getThumbnail();
+ mThumbnailView = taskContainer.getThumbnailView();
mFactory = factory;
}
@@ -233,11 +252,13 @@
}
@Override
- public SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView taskView) {
- SystemShortcut shortcut = super.getShortcut(activity, taskView);
+ public SystemShortcut getShortcut(BaseDraggingActivity activity,
+ TaskIdAttributeContainer taskContainer) {
+ SystemShortcut shortcut = super.getShortcut(activity, taskContainer);
if (shortcut != null && FeatureFlags.ENABLE_SPLIT_SELECT.get()) {
// Disable if there's only one recent app for split screen
- shortcut.setEnabled(taskView.getRecentsView().getTaskViewCount() > 1);
+ shortcut.setEnabled(taskContainer.getTaskView().
+ getRecentsView().getTaskViewCount() > 1);
}
return shortcut;
}
@@ -284,7 +305,7 @@
}
};
- TaskShortcutFactory PIN = (activity, tv) -> {
+ TaskShortcutFactory PIN = (activity, taskContainer) -> {
if (!SystemUiProxy.INSTANCE.get(activity).isActive()) {
return null;
}
@@ -295,7 +316,7 @@
// We shouldn't be able to pin while an app is locked.
return null;
}
- return new PinSystemShortcut(activity, tv);
+ return new PinSystemShortcut(activity, taskContainer);
};
class PinSystemShortcut extends SystemShortcut {
@@ -304,9 +325,11 @@
private final TaskView mTaskView;
- public PinSystemShortcut(BaseDraggingActivity target, TaskView tv) {
- super(R.drawable.ic_pin, R.string.recent_task_option_pin, target, tv.getItemInfo());
- mTaskView = tv;
+ public PinSystemShortcut(BaseDraggingActivity target,
+ TaskIdAttributeContainer taskContainer) {
+ super(R.drawable.ic_pin, R.string.recent_task_option_pin, target,
+ taskContainer.getItemInfo());
+ mTaskView = taskContainer.getTaskView();
}
@Override
@@ -320,20 +343,22 @@
}
}
- TaskShortcutFactory INSTALL = (activity, view) ->
+ TaskShortcutFactory INSTALL = (activity, taskContainer) ->
InstantAppResolver.newInstance(activity).isInstantApp(activity,
- view.getTask().getTopComponent().getPackageName())
- ? new SystemShortcut.Install(activity, view.getItemInfo()) : null;
+ taskContainer.getTask().getTopComponent().getPackageName())
+ ? new SystemShortcut.Install(activity, taskContainer.getItemInfo()) : null;
- TaskShortcutFactory WELLBEING = (activity, view) ->
- WellbeingModel.SHORTCUT_FACTORY.getShortcut(activity, view.getItemInfo());
+ TaskShortcutFactory WELLBEING = (activity, taskContainer) ->
+ WellbeingModel.SHORTCUT_FACTORY.getShortcut(activity, taskContainer.getItemInfo());
- TaskShortcutFactory SCREENSHOT = (activity, tv) -> tv.getThumbnail().getTaskOverlay()
- .getScreenshotShortcut(activity, tv.getItemInfo());
+ TaskShortcutFactory SCREENSHOT = (activity, taskContainer) ->
+ taskContainer.getThumbnailView().getTaskOverlay()
+ .getScreenshotShortcut(activity, taskContainer.getItemInfo());
- TaskShortcutFactory MODAL = (activity, tv) -> {
+ TaskShortcutFactory MODAL = (activity, taskContainer) -> {
if (ENABLE_OVERVIEW_SELECTIONS.get()) {
- return tv.getThumbnail().getTaskOverlay().getModalStateSystemShortcut(tv.getItemInfo());
+ return taskContainer.getThumbnailView()
+ .getTaskOverlay().getModalStateSystemShortcut(taskContainer.getItemInfo());
}
return null;
};
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index b1b4b54..72d3731 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -1,5 +1,8 @@
package com.android.quickstep.views;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
+
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
@@ -11,7 +14,6 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.util.RunnableList;
-import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
import com.android.launcher3.util.TransformingTouchDelegate;
import com.android.quickstep.RecentsModel;
@@ -72,7 +74,9 @@
super.bind(primary, orientedState);
mSecondaryTask = secondary;
mTaskIdContainer[1] = secondary.key.id;
- mTaskIdAttributeContainer[1] = new TaskIdAttributeContainer(secondary, mSnapshotView2);
+ mTaskIdAttributeContainer[1] = new TaskIdAttributeContainer(secondary, mSnapshotView2,
+ STAGE_POSITION_BOTTOM_OR_RIGHT);
+ mTaskIdAttributeContainer[0].setStagePosition(STAGE_POSITION_TOP_OR_LEFT);
mSnapshotView2.bind(secondary);
mSplitBoundsConfig = splitBoundsConfig;
}
@@ -112,6 +116,10 @@
}
}
+ protected boolean showTaskMenuWithContainer(IconView iconView) {
+ return TaskMenuView.showForTask(mTaskIdAttributeContainer[iconView == mIconView ? 0 : 1]);
+ }
+
public void updateSplitBoundsConfig(StagedSplitBounds stagedSplitBounds) {
mSplitBoundsConfig = stagedSplitBounds;
invalidate();
@@ -143,14 +151,14 @@
@Override
public RunnableList launchTaskAnimated() {
getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask,
- SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT, null /*callback*/);
+ STAGE_POSITION_TOP_OR_LEFT, null /*callback*/);
return null;
}
@Override
public void launchTask(@NonNull Consumer<Boolean> callback, boolean freezeTaskList) {
getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask,
- SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT, callback);
+ STAGE_POSITION_TOP_OR_LEFT, callback);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index bfc7eea..5ddbf87 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -16,6 +16,8 @@
package com.android.quickstep.views;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
import android.animation.Animator;
@@ -39,6 +41,7 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.Interpolators;
@@ -49,6 +52,7 @@
import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.TaskCornerRadius;
+import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
/**
* Contains options for a recent task when long-pressing its icon.
@@ -65,6 +69,7 @@
private TextView mTaskName;
private AnimatorSet mOpenCloseAnimator;
private TaskView mTaskView;
+ private TaskIdAttributeContainer mTaskContainer;
private LinearLayout mOptionLayout;
public TaskMenuView(Context context, AttributeSet attrs) {
@@ -129,7 +134,8 @@
// Inset due to margin
PointF additionalInset = pagedOrientationHandler
.getAdditionalInsetForTaskMenu(mTaskInsetMargin);
- int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
+ DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+ int taskTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
float adjustedY = y + taskTopMargin - additionalInset.y;
float adjustedX = x - additionalInset.x;
@@ -137,7 +143,7 @@
// NOTE: Changing the pivots means the rotated view gets rotated about the new pivots set,
// which would render the X and Y position set here incorrect
setPivotX(0);
- if (mActivity.getDeviceProfile().overviewShowAsGrid) {
+ if (deviceProfile.overviewShowAsGrid) {
// In tablet, set pivotY to original position without mThumbnailTopMargin adjustment.
setPivotY(-taskTopMargin);
} else {
@@ -145,9 +151,26 @@
}
setRotation(pagedOrientationHandler.getDegreesRotated());
setX(pagedOrientationHandler.getTaskMenuX(adjustedX,
- mTaskView.getThumbnail(), overscrollShift));
+ mTaskContainer.getThumbnailView(), overscrollShift));
setY(pagedOrientationHandler.getTaskMenuY(
- adjustedY, mTaskView.getThumbnail(), overscrollShift));
+ adjustedY, mTaskContainer.getThumbnailView(), overscrollShift));
+
+ // TODO(b/193432925) temporary menu placement for split screen task menus
+ TaskIdAttributeContainer[] taskIdAttributeContainers =
+ mTaskView.getTaskIdAttributeContainers();
+ if (taskIdAttributeContainers[0].getStagePosition() != STAGE_POSITION_UNDEFINED) {
+ if (mTaskContainer.getStagePosition() != STAGE_POSITION_BOTTOM_OR_RIGHT) {
+ return;
+ }
+ Rect r = new Rect();
+ mTaskContainer.getThumbnailView().getBoundsOnScreen(r);
+ if (deviceProfile.isLandscape) {
+ setX(r.left);
+ } else {
+ setY(r.top);
+
+ }
+ }
}
public void onRotationChanged() {
@@ -162,19 +185,21 @@
}
}
- public static boolean showForTask(TaskView taskView) {
- BaseDraggingActivity activity = BaseDraggingActivity.fromContext(taskView.getContext());
+ public static boolean showForTask(TaskIdAttributeContainer taskContainer) {
+ BaseDraggingActivity activity = BaseDraggingActivity.fromContext(
+ taskContainer.getTaskView().getContext());
final TaskMenuView taskMenuView = (TaskMenuView) activity.getLayoutInflater().inflate(
R.layout.task_menu, activity.getDragLayer(), false);
- return taskMenuView.populateAndShowForTask(taskView);
+ return taskMenuView.populateAndShowForTask(taskContainer);
}
- private boolean populateAndShowForTask(TaskView taskView) {
+ private boolean populateAndShowForTask(TaskIdAttributeContainer taskContainer) {
if (isAttachedToWindow()) {
return false;
}
mActivity.getDragLayer().addView(this);
- mTaskView = taskView;
+ mTaskView = taskContainer.getTaskView();
+ mTaskContainer = taskContainer;
if (!populateAndLayoutMenu()) {
return false;
}
@@ -192,20 +217,21 @@
/** @return true if successfully able to populate task view menu, false otherwise */
private boolean populateAndLayoutMenu() {
- if (mTaskView.getTask().icon == null) {
+ if (mTaskContainer.getTask().icon == null) {
// Icon may not be loaded
return false;
}
- addMenuOptions(mTaskView);
- orientAroundTaskView(mTaskView);
+ addMenuOptions(mTaskContainer);
+ orientAroundTaskView(mTaskContainer);
return true;
}
- private void addMenuOptions(TaskView taskView) {
- mTaskName.setText(TaskUtils.getTitle(getContext(), taskView.getTask()));
+ private void addMenuOptions(TaskIdAttributeContainer taskContainer) {
+ mTaskName.setText(TaskUtils.getTitle(getContext(), taskContainer.getTask()));
mTaskName.setOnClickListener(v -> close(true));
- TaskOverlayFactory.getEnabledShortcuts(taskView, mActivity.getDeviceProfile())
+ TaskOverlayFactory.getEnabledShortcuts(mTaskView, mActivity.getDeviceProfile(),
+ taskContainer)
.forEach(this::addMenuOption);
}
@@ -223,23 +249,25 @@
mOptionLayout.addView(menuOptionView);
}
- private void orientAroundTaskView(TaskView taskView) {
- PagedOrientationHandler orientationHandler = taskView.getPagedOrientationHandler();
+ private void orientAroundTaskView(TaskIdAttributeContainer taskContainer) {
+ RecentsView recentsView = mActivity.getOverviewPanel();
+ PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
orientationHandler.setTaskMenuAroundTaskView(this, mTaskInsetMargin);
// Get Position
- mActivity.getDragLayer().getDescendantRectRelativeToSelf(taskView, sTempRect);
+ mActivity.getDragLayer().getDescendantRectRelativeToSelf(mTaskView, sTempRect);
Rect insets = mActivity.getDragLayer().getInsets();
BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) getLayoutParams();
int padding = getResources()
.getDimensionPixelSize(R.dimen.task_menu_vertical_padding);
- params.width = orientationHandler.getTaskMenuWidth(taskView.getThumbnail()) - (2 * padding);
+ params.width = orientationHandler
+ .getTaskMenuWidth(taskContainer.getThumbnailView()) - (2 * padding);
// Gravity set to Left instead of Start as sTempRect.left measures Left distance not Start
params.gravity = Gravity.LEFT;
setLayoutParams(params);
- setScaleX(taskView.getScaleX());
- setScaleY(taskView.getScaleY());
+ setScaleX(mTaskView.getScaleX());
+ setScaleY(mTaskView.getScaleY());
// Set divider spacing
ShapeDrawable divider = new ShapeDrawable(new RectShape());
@@ -272,7 +300,7 @@
revealAnimator.setInterpolator(Interpolators.DEACCEL);
mOpenCloseAnimator.playTogether(revealAnimator,
ObjectAnimator.ofFloat(
- mTaskView.getThumbnail(), DIM_ALPHA,
+ mTaskContainer.getThumbnailView(), DIM_ALPHA,
closing ? 0 : TaskView.MAX_PAGE_SCRIM_ALPHA),
ObjectAnimator.ofFloat(this, ALPHA, closing ? 0 : 1));
mOpenCloseAnimator.addListener(new AnimationSuccessListener() {
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 461a89b..053d07c 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -18,13 +18,6 @@
import static android.view.Gravity.BOTTOM;
import static android.view.Gravity.CENTER_HORIZONTAL;
-import static android.view.Gravity.CENTER_VERTICAL;
-import static android.view.Gravity.END;
-import static android.view.Gravity.START;
-import static android.view.Gravity.TOP;
-import static android.view.Surface.ROTATION_180;
-import static android.view.Surface.ROTATION_270;
-import static android.view.Surface.ROTATION_90;
import static android.widget.Toast.LENGTH_SHORT;
import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
@@ -39,6 +32,7 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -58,7 +52,6 @@
import android.util.FloatProperty;
import android.util.Log;
import android.view.MotionEvent;
-import android.view.Surface;
import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewGroup;
@@ -86,6 +79,7 @@
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.RunnableList;
+import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.util.TransformingTouchDelegate;
import com.android.launcher3.util.ViewPool.Reusable;
@@ -466,7 +460,10 @@
* Builds proto for logging
*/
public WorkspaceItemInfo getItemInfo() {
- final Task task = getTask();
+ return getItemInfo(mTask);
+ }
+
+ protected WorkspaceItemInfo getItemInfo(Task task) {
ComponentKey componentKey = TaskUtils.getLaunchComponentKeyForTask(task.key);
WorkspaceItemInfo stubInfo = new WorkspaceItemInfo();
stubInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_TASK;
@@ -569,7 +566,8 @@
cancelPendingLoadTasks();
mTask = task;
mTaskIdContainer[0] = mTask.key.id;
- mTaskIdAttributeContainer[0] = new TaskIdAttributeContainer(task, mSnapshotView);
+ mTaskIdAttributeContainer[0] = new TaskIdAttributeContainer(task, mSnapshotView,
+ STAGE_POSITION_UNDEFINED);
mSnapshotView.bind(task);
setOrientationState(orientedState);
}
@@ -825,7 +823,7 @@
}
}
- private boolean showTaskMenu() {
+ private boolean showTaskMenu(IconView iconView) {
if (getRecentsView().mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
// Don't show menu when selecting second split screen app
return true;
@@ -837,10 +835,14 @@
} else {
mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo())
.log(LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS);
- return TaskMenuView.showForTask(this);
+ return showTaskMenuWithContainer(iconView);
}
}
+ protected boolean showTaskMenuWithContainer(IconView iconView) {
+ return TaskMenuView.showForTask(mTaskIdAttributeContainer[0]);
+ }
+
protected void setIcon(IconView iconView, Drawable icon) {
if (icon != null) {
iconView.setDrawable(icon);
@@ -850,14 +852,14 @@
recentsView.switchToScreenshot(
() -> recentsView.finishRecentsAnimation(true /* toRecents */,
false /* shouldPip */,
- this::showTaskMenu));
+ () -> showTaskMenu(iconView)));
} else {
- showTaskMenu();
+ showTaskMenu(iconView);
}
});
iconView.setOnLongClickListener(v -> {
requestDisallowInterceptTouchEvent(true);
- return showTaskMenu();
+ return showTaskMenu(iconView);
});
} else {
iconView.setDrawable(null);
@@ -1328,8 +1330,9 @@
getContext().getText(R.string.accessibility_close)));
final Context context = getContext();
+ // TODO(b/200609838) Determine which task to run A11y action on when in split screen
for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this,
- mActivity.getDeviceProfile())) {
+ mActivity.getDeviceProfile(), mTaskIdAttributeContainer[0])) {
info.addAction(s.createAccessibilityAction(context));
}
@@ -1361,8 +1364,9 @@
return true;
}
+ // TODO(b/200609838) Determine which task to run A11y action on when in split screen
for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this,
- mActivity.getDeviceProfile())) {
+ mActivity.getDeviceProfile(), mTaskIdAttributeContainer[0])) {
if (s.hasHandlerForAction(action)) {
s.onClick(this);
return true;
@@ -1581,20 +1585,40 @@
}
public class TaskIdAttributeContainer {
- private final TaskThumbnailView thumbnailView;
- private final Task task;
+ private final TaskThumbnailView mThumbnailView;
+ private final Task mTask;
+ /** Defaults to STAGE_POSITION_UNDEFINED if in not a split screen task view */
+ private @SplitConfigurationOptions.StagePosition int mStagePosition;
- public TaskIdAttributeContainer(Task task, TaskThumbnailView thumbnailView) {
- this.task = task;
- this.thumbnailView = thumbnailView;
+ public TaskIdAttributeContainer(Task task, TaskThumbnailView thumbnailView,
+ int stagePosition) {
+ this.mTask = task;
+ this.mThumbnailView = thumbnailView;
+ this.mStagePosition = stagePosition;
}
public TaskThumbnailView getThumbnailView() {
- return thumbnailView;
+ return mThumbnailView;
}
public Task getTask() {
- return task;
+ return mTask;
+ }
+
+ public WorkspaceItemInfo getItemInfo() {
+ return TaskView.this.getItemInfo(mTask);
+ }
+
+ public TaskView getTaskView() {
+ return TaskView.this;
+ }
+
+ public int getStagePosition() {
+ return mStagePosition;
+ }
+
+ void setStagePosition(@SplitConfigurationOptions.StagePosition int stagePosition) {
+ this.mStagePosition = stagePosition;
}
}
}
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index f26cfe8..28afc57 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -4,15 +4,20 @@
import android.annotation.TargetApi;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Canvas;
+import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.view.ViewDebug;
import android.view.WindowInsets;
+import androidx.annotation.RequiresApi;
+
import com.android.launcher3.graphics.SysUiScrim;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.uioverrides.ApiWrapper;
import java.util.Collections;
import java.util.List;
@@ -61,12 +66,75 @@
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mTempRect.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
- insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
+ if (Utilities.ATLEAST_R) {
+ insets = updateInsetsDueToTaskbar(insets);
+ Insets systemWindowInsets = insets.getInsetsIgnoringVisibility(
+ WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
+ mTempRect.set(systemWindowInsets.left, systemWindowInsets.top, systemWindowInsets.right,
+ systemWindowInsets.bottom);
+ } else {
+ mTempRect.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
+ insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
+ }
handleSystemWindowInsets(mTempRect);
return insets;
}
+ /**
+ * Taskbar provides nav bar and tappable insets. However, taskbar is not attached immediately,
+ * and can be destroyed and recreated. Thus, instead of relying on taskbar being present to
+ * get its insets, we calculate them ourselves so they are stable regardless of whether taskbar
+ * is currently attached.
+ *
+ * TODO(b/198798034): Currently we always calculate nav insets as taskbarSize, but then we
+ * subtract nonOverlappingTaskbarInset in handleSystemWindowInsets(). Instead, we should just
+ * calculate the normal nav bar height here, and remove nonOverlappingTaskbarInset altogether.
+ *
+ * @param oldInsets The system-provided insets, which we are modifying.
+ * @return The updated insets.
+ */
+ @RequiresApi(api = Build.VERSION_CODES.R)
+ private WindowInsets updateInsetsDueToTaskbar(WindowInsets oldInsets) {
+ if (!ApiWrapper.TASKBAR_DRAWN_IN_PROCESS) {
+ // 3P launchers based on Launcher3 should still be inset like normal.
+ return oldInsets;
+ }
+
+ WindowInsets.Builder updatedInsetsBuilder = new WindowInsets.Builder(oldInsets);
+
+ DeviceProfile dp = mActivity.getDeviceProfile();
+ Resources resources = getResources();
+
+ Insets oldNavInsets = oldInsets.getInsets(WindowInsets.Type.navigationBars());
+ Rect newNavInsets = new Rect(oldNavInsets.left, oldNavInsets.top, oldNavInsets.right,
+ oldNavInsets.bottom);
+ if (dp.isTaskbarPresent) {
+ // TODO (see javadoc): Remove this block and fall into the next one instead.
+ newNavInsets.bottom = dp.taskbarSize;
+ } else if (dp.isLandscape) {
+ if (dp.isTablet) {
+ newNavInsets.bottom = ResourceUtils.getNavbarSize(
+ "navigation_bar_height_landscape", resources);
+ } else {
+ int navWidth = ResourceUtils.getNavbarSize("navigation_bar_width", resources);
+ if (dp.isSeascape()) {
+ newNavInsets.left = navWidth;
+ } else {
+ newNavInsets.right = navWidth;
+ }
+ }
+ } else {
+ newNavInsets.bottom = ResourceUtils.getNavbarSize("navigation_bar_height", resources);
+ }
+ updatedInsetsBuilder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(newNavInsets));
+ updatedInsetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.navigationBars(),
+ Insets.of(newNavInsets));
+
+ mActivity.updateWindowInsets(updatedInsetsBuilder, oldInsets);
+
+ return updatedInsetsBuilder.build();
+ }
+
@Override
public void setInsets(Rect insets) {
// If the insets haven't changed, this is a no-op. Avoid unnecessary layout caused by
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 63fd9a0..a701548 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -426,8 +426,7 @@
@Override
public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
if (Utilities.ATLEAST_Q) {
- mNavBarScrimHeight = insets.getTappableElementInsets().bottom
- - mLauncher.getDeviceProfile().nonOverlappingTaskbarInset;
+ mNavBarScrimHeight = insets.getTappableElementInsets().bottom;
} else {
mNavBarScrimHeight = insets.getStableInsetBottom();
}
diff --git a/src/com/android/launcher3/statemanager/StatefulActivity.java b/src/com/android/launcher3/statemanager/StatefulActivity.java
index 8a35cb3..7a23caa 100644
--- a/src/com/android/launcher3/statemanager/StatefulActivity.java
+++ b/src/com/android/launcher3/statemanager/StatefulActivity.java
@@ -17,11 +17,15 @@
import static com.android.launcher3.LauncherState.FLAG_NON_INTERACTIVE;
+import android.graphics.Insets;
+import android.os.Build;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.WindowInsets;
import androidx.annotation.CallSuper;
+import androidx.annotation.RequiresApi;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.LauncherRootView;
@@ -173,4 +177,12 @@
mHandler.removeCallbacks(mHandleDeferredResume);
Utilities.postAsyncCallback(mHandler, mHandleDeferredResume);
}
+
+ /**
+ * Gives subclasses a chance to override some window insets (via
+ * {@link android.view.WindowInsets.Builder#setInsets(int, Insets)}).
+ */
+ @RequiresApi(api = Build.VERSION_CODES.R)
+ public void updateWindowInsets(WindowInsets.Builder updatedInsetsBuilder,
+ WindowInsets oldInsets) { }
}
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index bb4638a..68532ca 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -36,7 +36,6 @@
import android.widget.TableRow;
import android.widget.TextView;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.model.WidgetItem;
@@ -70,7 +69,6 @@
private static final long EDUCATION_TIP_DELAY_MS = 300;
private ItemInfo mOriginalItemInfo;
- private final int mMaxTableHeight;
private int mMaxHorizontalSpan = DEFAULT_MAX_HORIZONTAL_SPANS;
private final int mWidgetCellHorizontalPadding;
@@ -110,10 +108,6 @@
public WidgetsBottomSheet(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setWillNotDraw(false);
- DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
- // Set the max table height to 2 / 3 of the grid height so that the bottom picker won't
- // take over the entire view vertically.
- mMaxTableHeight = deviceProfile.inv.numRows * 2 / 3 * deviceProfile.cellHeightPx;
if (!hasSeenEducationTip()) {
addOnLayoutChangeListener(mLayoutChangeListenerToShowTips);
}
@@ -162,13 +156,9 @@
setTranslationShift(mTranslationShift);
- // Ensure the scroll view height is not larger than mMaxTableHeight, which is a value
- // smaller than the entire screen height.
ScrollView widgetsTableScrollView = findViewById(R.id.widgets_table_scroll_view);
- if (widgetsTableScrollView.getMeasuredHeight() > mMaxTableHeight) {
- ViewGroup.LayoutParams layoutParams = widgetsTableScrollView.getLayoutParams();
- layoutParams.height = mMaxTableHeight;
- widgetsTableScrollView.setLayoutParams(layoutParams);
+ TableLayout widgetsTable = findViewById(R.id.widgets_table);
+ if (widgetsTable.getMeasuredHeight() > widgetsTableScrollView.getMeasuredHeight()) {
findViewById(R.id.collapse_handle).setVisibility(VISIBLE);
}
}