Merge "Various multi-window fixes" into ub-launcher3-rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
2d60935e1c
+1
-18
@@ -23,7 +23,6 @@ import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
|
||||
/**
|
||||
* State indicating that the Launcher is behind an app
|
||||
@@ -66,23 +65,7 @@ public class BackgroundAppState extends OverviewState {
|
||||
}
|
||||
|
||||
private float getOverviewScale(Launcher launcher) {
|
||||
// Initialize the recents view scale to what it would be when starting swipe up
|
||||
RecentsView recentsView = launcher.getOverviewPanel();
|
||||
int taskCount = recentsView.getTaskViewCount();
|
||||
if (taskCount == 0) return 1;
|
||||
|
||||
TaskView dummyTask;
|
||||
if (recentsView.getCurrentPage() >= recentsView.getTaskViewStartIndex()) {
|
||||
if (recentsView.getCurrentPage() <= taskCount - 1) {
|
||||
dummyTask = recentsView.getCurrentPageTaskView();
|
||||
} else {
|
||||
dummyTask = recentsView.getTaskViewAt(taskCount - 1);
|
||||
}
|
||||
} else {
|
||||
dummyTask = recentsView.getTaskViewAt(0);
|
||||
}
|
||||
return recentsView.getTempAppWindowAnimationHelper()
|
||||
.updateForFullscreenOverview(dummyTask).getSrcToTargetScale();
|
||||
return ((RecentsView) launcher.getOverviewPanel()).getMaxScaleForFullScreen();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,7 +26,6 @@ import android.animation.Animator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
@@ -265,8 +264,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||
if (targets.minimizedHomeBounds != null && runningTaskTarget != null) {
|
||||
overviewStackBounds = mActivityInterface
|
||||
.getOverviewWindowBounds(targets.minimizedHomeBounds, runningTaskTarget);
|
||||
dp = dp.getMultiWindowProfile(mContext, new Point(
|
||||
overviewStackBounds.width(), overviewStackBounds.height()));
|
||||
dp = dp.getMultiWindowProfile(mContext, overviewStackBounds);
|
||||
} else {
|
||||
// If we are not in multi-window mode, home insets should be same as system insets.
|
||||
dp = dp.copy(mContext);
|
||||
|
||||
+2
-2
@@ -18,6 +18,7 @@ package com.android.quickstep;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
||||
import static com.android.quickstep.fallback.FallbackRecentsView.ZOOM_PROGRESS;
|
||||
import static com.android.quickstep.util.WindowSizeStrategy.FALLBACK_RECENTS_SIZE_STRATEGY;
|
||||
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
|
||||
|
||||
import android.animation.Animator;
|
||||
@@ -36,7 +37,6 @@ import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
|
||||
@@ -60,7 +60,7 @@ public final class FallbackActivityInterface implements
|
||||
|
||||
@Override
|
||||
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
|
||||
LayoutUtils.calculateFallbackTaskSize(context, dp, outRect);
|
||||
FALLBACK_RECENTS_SIZE_STRATEGY.calculateTaskSize(context, dp, outRect);
|
||||
if (dp.isVerticalBarLayout()
|
||||
&& SysUINavigationMode.INSTANCE.get(context).getMode() != NO_BUTTON) {
|
||||
Rect targetInsets = dp.getInsets();
|
||||
|
||||
+2
-1
@@ -26,6 +26,7 @@ import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
||||
import static com.android.launcher3.anim.Interpolators.INSTANT;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.quickstep.LauncherSwipeHandler.RECENTS_ATTACH_DURATION;
|
||||
import static com.android.quickstep.util.WindowSizeStrategy.LAUNCHER_ACTIVITY_SIZE_STRATEGY;
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
|
||||
|
||||
import android.animation.Animator;
|
||||
@@ -82,7 +83,7 @@ public final class LauncherActivityInterface implements BaseActivityInterface<La
|
||||
|
||||
@Override
|
||||
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
|
||||
LayoutUtils.calculateLauncherTaskSize(context, dp, outRect);
|
||||
LAUNCHER_ACTIVITY_SIZE_STRATEGY.calculateTaskSize(context, dp, outRect);
|
||||
if (dp.isVerticalBarLayout() && SysUINavigationMode.getMode(context) != Mode.NO_BUTTON) {
|
||||
Rect targetInsets = dp.getInsets();
|
||||
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
|
||||
|
||||
@@ -37,6 +37,7 @@ import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
|
||||
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
|
||||
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK;
|
||||
import static com.android.quickstep.util.WindowSizeStrategy.LAUNCHER_ACTIVITY_SIZE_STRATEGY;
|
||||
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||
|
||||
import android.animation.Animator;
|
||||
@@ -80,7 +81,6 @@ import com.android.quickstep.GestureState.GestureEndTarget;
|
||||
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
|
||||
import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper.TargetAlphaProvider;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.util.ShelfPeekAnim;
|
||||
import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
|
||||
@@ -208,8 +208,7 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
||||
mTaskAnimationManager = taskAnimationManager;
|
||||
mTouchTimeMs = touchTimeMs;
|
||||
mContinuingLastGesture = continuingLastGesture;
|
||||
mTaskViewSimulator = new TaskViewSimulator(
|
||||
context, LayoutUtils::calculateLauncherTaskSize, true);
|
||||
mTaskViewSimulator = new TaskViewSimulator(context, LAUNCHER_ACTIVITY_SIZE_STRATEGY);
|
||||
|
||||
initAfterSubclassConstructor();
|
||||
initStateCallbacks();
|
||||
|
||||
@@ -121,7 +121,7 @@ public final class RecentsActivity extends BaseRecentsActivity {
|
||||
protected DeviceProfile createDeviceProfile() {
|
||||
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);
|
||||
return (mRecentsRootView != null) && isInMultiWindowMode()
|
||||
? dp.getMultiWindowProfile(this, mRecentsRootView.getLastKnownSize())
|
||||
? dp.getMultiWindowProfile(this, getMultiWindowDisplaySize())
|
||||
: super.createDeviceProfile();
|
||||
}
|
||||
|
||||
|
||||
+3
-20
@@ -16,22 +16,19 @@
|
||||
package com.android.quickstep.fallback;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.quickstep.util.WindowSizeStrategy.FALLBACK_RECENTS_SIZE_STRATEGY;
|
||||
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.FloatProperty;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.quickstep.RecentsActivity;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.views.OverviewActionsView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.Task.TaskKey;
|
||||
|
||||
@@ -65,7 +62,7 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
|
||||
}
|
||||
|
||||
public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr, false);
|
||||
super(context, attrs, defStyleAttr, FALLBACK_RECENTS_SIZE_STRATEGY);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -104,11 +101,6 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
|
||||
resetViewUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getTaskSize(DeviceProfile dp, Rect outRect) {
|
||||
LayoutUtils.calculateFallbackTaskSize(getContext(), dp, outRect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldUseMultiWindowTaskSizeStrategy() {
|
||||
// Just use the activity task size for multi-window as well.
|
||||
@@ -140,16 +132,7 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
|
||||
if (getTaskViewCount() == 0) {
|
||||
mZoomScale = 1f;
|
||||
} else {
|
||||
TaskView dummyTask = getTaskViewAt(0);
|
||||
mZoomScale = getTempAppWindowAnimationHelper()
|
||||
.updateForFullscreenOverview(dummyTask)
|
||||
.getSrcToTargetScale();
|
||||
}
|
||||
|
||||
mZoomScale = getMaxScaleForFullScreen();
|
||||
setZoomProgress(mZoomInProgress);
|
||||
}
|
||||
|
||||
|
||||
+11
-22
@@ -61,7 +61,7 @@ public class TaskViewSimulator {
|
||||
|
||||
private final RecentsOrientedState mOrientationState;
|
||||
private final Context mContext;
|
||||
private final TaskSizeProvider mSizeProvider;
|
||||
private final WindowSizeStrategy mSizeStrategy;
|
||||
|
||||
private final Rect mTaskRect = new Rect();
|
||||
private final PointF mPivot = new PointF();
|
||||
@@ -95,14 +95,12 @@ public class TaskViewSimulator {
|
||||
private boolean mLayoutValid = false;
|
||||
private boolean mScrollValid = false;
|
||||
|
||||
public TaskViewSimulator(Context context, TaskSizeProvider sizeProvider,
|
||||
boolean rotationSupportedByActivity) {
|
||||
public TaskViewSimulator(Context context, WindowSizeStrategy sizeStrategy) {
|
||||
mContext = context;
|
||||
mSizeProvider = sizeProvider;
|
||||
mSizeStrategy = sizeStrategy;
|
||||
mPositionHelper = new PreviewPositionHelper(context);
|
||||
|
||||
mOrientationState = new RecentsOrientedState(context, rotationSupportedByActivity,
|
||||
i -> { });
|
||||
mOrientationState = new RecentsOrientedState(context, sizeStrategy, i -> { });
|
||||
// We do not need to attach listeners as the simulator is created just for the gesture
|
||||
// duration, and any settings are unlikely to change during this
|
||||
mOrientationState.initWithoutListeners();
|
||||
@@ -116,6 +114,7 @@ public class TaskViewSimulator {
|
||||
*/
|
||||
public void setDp(DeviceProfile dp, boolean isOpening) {
|
||||
mDp = dp;
|
||||
mOrientationState.setMultiWindowMode(mDp.isMultiWindowMode);
|
||||
mBoostModeTargetLayers = isOpening ? MODE_OPENING : MODE_CLOSING;
|
||||
mLayoutValid = false;
|
||||
}
|
||||
@@ -143,7 +142,7 @@ public class TaskViewSimulator {
|
||||
if (mDp == null) {
|
||||
return 1;
|
||||
}
|
||||
mSizeProvider.calculateTaskSize(mContext, mDp, mTaskRect);
|
||||
mSizeStrategy.calculateTaskSize(mContext, mDp, mTaskRect);
|
||||
return mOrientationState.getFullScreenScaleAndPivot(mTaskRect, mDp, mPivot);
|
||||
}
|
||||
|
||||
@@ -161,8 +160,7 @@ public class TaskViewSimulator {
|
||||
|
||||
mThumbnailPosition.set(runningTarget.screenSpaceBounds);
|
||||
// TODO: Should sourceContainerBounds already have this offset?
|
||||
mThumbnailPosition.offsetTo(mRunningTarget.position.x, mRunningTarget.position.y);
|
||||
|
||||
mThumbnailPosition.offset(-mRunningTarget.position.x, -mRunningTarget.position.y);
|
||||
mLayoutValid = false;
|
||||
}
|
||||
|
||||
@@ -198,7 +196,7 @@ public class TaskViewSimulator {
|
||||
? mOrientationState.getDisplayRotation() : mPositionHelper.getCurrentRotation();
|
||||
|
||||
mPositionHelper.updateThumbnailMatrix(mThumbnailPosition, mThumbnailData,
|
||||
mDp.isMultiWindowMode, mTaskRect.width(), mTaskRect.height());
|
||||
mTaskRect.width(), mTaskRect.height(), mDp);
|
||||
|
||||
mPositionHelper.getMatrix().invert(mInversePositionMatrix);
|
||||
|
||||
@@ -209,6 +207,7 @@ public class TaskViewSimulator {
|
||||
mScrollValid = false;
|
||||
}
|
||||
|
||||
|
||||
if (!mScrollValid) {
|
||||
mScrollValid = true;
|
||||
int start = mOrientationState.getOrientationHandler()
|
||||
@@ -243,6 +242,8 @@ public class TaskViewSimulator {
|
||||
postDisplayRotation(deltaRotation(
|
||||
mOrientationState.getLauncherRotation(), mOrientationState.getDisplayRotation()),
|
||||
mDp.widthPx, mDp.heightPx, mMatrix);
|
||||
mMatrix.postTranslate(mDp.windowX - mRunningTarget.position.x,
|
||||
mDp.windowY - mRunningTarget.position.y);
|
||||
|
||||
// Crop rect is the inverse of thumbnail matrix
|
||||
mTempRectF.set(-insets.left, -insets.top,
|
||||
@@ -298,16 +299,4 @@ public class TaskViewSimulator {
|
||||
// Ideally we should use square-root. This is an optimization as one of the dimension is 0.
|
||||
return Math.max(Math.abs(mTempPoint[0]), Math.abs(mTempPoint[1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for calculating taskSize
|
||||
*/
|
||||
public interface TaskSizeProvider {
|
||||
|
||||
/**
|
||||
* Sets the outRect to the expected taskSize
|
||||
*/
|
||||
void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-8
@@ -25,6 +25,7 @@ import static com.android.launcher3.LauncherState.SPRING_LOADED;
|
||||
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN;
|
||||
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.quickstep.util.WindowSizeStrategy.LAUNCHER_ACTIVITY_SIZE_STRATEGY;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
@@ -39,7 +40,6 @@ import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Hotseat;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager.StateListener;
|
||||
@@ -53,7 +53,6 @@ import com.android.launcher3.views.ScrimView;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper.TransformParams;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.systemui.plugins.PluginListener;
|
||||
import com.android.systemui.plugins.RecentsExtraCard;
|
||||
|
||||
@@ -96,7 +95,7 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
|
||||
}
|
||||
|
||||
public LauncherRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr, true);
|
||||
super(context, attrs, defStyleAttr, LAUNCHER_ACTIVITY_SIZE_STRATEGY);
|
||||
mActivity.getStateManager().addStateListener(this);
|
||||
}
|
||||
|
||||
@@ -178,11 +177,6 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
|
||||
return anim;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getTaskSize(DeviceProfile dp, Rect outRect) {
|
||||
LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTaskLaunchAnimationUpdate(float progress, TaskView tv) {
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
|
||||
@@ -122,6 +122,7 @@ import com.android.quickstep.TaskUtils;
|
||||
import com.android.quickstep.ViewUtils;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.quickstep.util.WindowSizeStrategy;
|
||||
import com.android.systemui.plugins.ResourceProvider;
|
||||
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
@@ -202,6 +203,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
};
|
||||
|
||||
protected final RecentsOrientedState mOrientationState;
|
||||
protected final WindowSizeStrategy mSizeStrategy;
|
||||
protected RecentsAnimationController mRecentsAnimationController;
|
||||
protected RecentsAnimationTargets mRecentsAnimationTargets;
|
||||
protected AppWindowAnimationHelper mAppWindowAnimationHelper;
|
||||
@@ -225,7 +227,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
private final ClearAllButton mClearAllButton;
|
||||
private final Rect mClearAllButtonDeadZoneRect = new Rect();
|
||||
private final Rect mTaskViewDeadZoneRect = new Rect();
|
||||
protected final AppWindowAnimationHelper mTempAppWindowAnimationHelper;
|
||||
|
||||
private final ScrollState mScrollState = new ScrollState();
|
||||
// Keeps track of the previously known visible tasks for purposes of loading/unloading task data
|
||||
@@ -373,20 +374,19 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
};
|
||||
|
||||
public RecentsView(Context context, AttributeSet attrs, int defStyleAttr,
|
||||
boolean rotationSupportedByActivity) {
|
||||
WindowSizeStrategy sizeStrategy) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
setPageSpacing(getResources().getDimensionPixelSize(R.dimen.recents_page_spacing));
|
||||
setEnableFreeScroll(true);
|
||||
mSizeStrategy = sizeStrategy;
|
||||
mOrientationState = new RecentsOrientedState(
|
||||
context, rotationSupportedByActivity, this::animateRecentsRotationInPlace);
|
||||
context, mSizeStrategy, this::animateRecentsRotationInPlace);
|
||||
|
||||
mFastFlingVelocity = getResources()
|
||||
.getDimensionPixelSize(R.dimen.recents_fast_fling_velocity);
|
||||
mActivity = BaseActivity.fromContext(context);
|
||||
mModel = RecentsModel.INSTANCE.get(context);
|
||||
mIdp = InvariantDeviceProfile.INSTANCE.get(context);
|
||||
mTempAppWindowAnimationHelper =
|
||||
new AppWindowAnimationHelper(getPagedViewOrientedState(), context);
|
||||
|
||||
mClearAllButton = (ClearAllButton) LayoutInflater.from(context)
|
||||
.inflate(R.layout.overview_clear_all_button, this, false);
|
||||
@@ -712,7 +712,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
final int pageIndex = requiredTaskCount - i - 1 + mTaskViewStartIndex;
|
||||
final Task task = tasks.get(i);
|
||||
final TaskView taskView = (TaskView) getChildAt(pageIndex);
|
||||
taskView.bind(task, mOrientationState, mActivity.getDeviceProfile().isMultiWindowMode);
|
||||
taskView.bind(task, mOrientationState);
|
||||
}
|
||||
|
||||
if (mNextPage == INVALID_PAGE) {
|
||||
@@ -802,7 +802,8 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
public void setInsets(Rect insets) {
|
||||
mInsets.set(insets);
|
||||
DeviceProfile dp = mActivity.getDeviceProfile();
|
||||
getTaskSize(dp, mTempRect);
|
||||
mOrientationState.setMultiWindowMode(dp.isMultiWindowMode);
|
||||
getTaskSize(mTempRect);
|
||||
mTaskWidth = mTempRect.width();
|
||||
mTaskHeight = mTempRect.height();
|
||||
|
||||
@@ -812,10 +813,8 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
dp.heightPx - mInsets.bottom - mTempRect.bottom);
|
||||
}
|
||||
|
||||
protected abstract void getTaskSize(DeviceProfile dp, Rect outRect);
|
||||
|
||||
public void getTaskSize(Rect outRect) {
|
||||
getTaskSize(mActivity.getDeviceProfile(), outRect);
|
||||
mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), outRect);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1068,8 +1067,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
new ComponentName(getContext(), getClass()), 0, 0), null, null, "", "", 0, 0,
|
||||
false, true, false, false, new ActivityManager.TaskDescription(), 0,
|
||||
new ComponentName("", ""), false);
|
||||
taskView.bind(mTmpRunningTask, mOrientationState,
|
||||
mActivity.getDeviceProfile().isMultiWindowMode);
|
||||
taskView.bind(mTmpRunningTask, mOrientationState);
|
||||
}
|
||||
|
||||
boolean runningTaskTileHidden = mRunningTaskTileHidden;
|
||||
@@ -1764,7 +1762,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
int centerTaskIndex = getCurrentPage();
|
||||
boolean launchingCenterTask = taskIndex == centerTaskIndex;
|
||||
|
||||
float toScale = appWindowAnimationHelper.getSrcToTargetScale();
|
||||
float toScale = getMaxScaleForFullScreen();
|
||||
if (launchingCenterTask) {
|
||||
RecentsView recentsView = tv.getRecentsView();
|
||||
anim.play(ObjectAnimator.ofFloat(recentsView, SCALE_PROPERTY, toScale));
|
||||
@@ -1786,6 +1784,15 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
return anim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scale up required on the view, so that it coves the screen completely
|
||||
*/
|
||||
public float getMaxScaleForFullScreen() {
|
||||
getTaskSize(mTempRect);
|
||||
return getPagedViewOrientedState().getFullScreenScaleAndPivot(
|
||||
mTempRect, mActivity.getDeviceProfile(), mTempPointF);
|
||||
}
|
||||
|
||||
public PendingAnimation createTaskLaunchAnimation(
|
||||
TaskView tv, long duration, Interpolator interpolator) {
|
||||
if (FeatureFlags.IS_STUDIO_BUILD && mPendingAnimation != null) {
|
||||
@@ -2079,10 +2086,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
return mAppWindowAnimationHelper;
|
||||
}
|
||||
|
||||
public AppWindowAnimationHelper getTempAppWindowAnimationHelper() {
|
||||
return mTempAppWindowAnimationHelper;
|
||||
}
|
||||
|
||||
public AppWindowAnimationHelper.TransformParams getLiveTileParams(
|
||||
boolean mightNeedToRefill) {
|
||||
return null;
|
||||
|
||||
+27
-15
@@ -36,12 +36,12 @@ import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.FloatProperty;
|
||||
import android.util.Log;
|
||||
import android.util.Property;
|
||||
import android.view.Surface;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
@@ -104,7 +104,6 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
||||
|
||||
private boolean mOverlayEnabled;
|
||||
private OverviewScreenshotActions mOverviewScreenshotActionsPlugin;
|
||||
private boolean mIsMultiWindowMode;
|
||||
|
||||
public TaskThumbnailView(Context context) {
|
||||
this(context, null);
|
||||
@@ -126,8 +125,11 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
||||
mPreviewPositionHelper = new PreviewPositionHelper(context);
|
||||
}
|
||||
|
||||
public void bind(Task task, boolean isMultiWindowMode) {
|
||||
mIsMultiWindowMode = isMultiWindowMode;
|
||||
/**
|
||||
* Updates the thumbnail to draw the provided task
|
||||
* @param task
|
||||
*/
|
||||
public void bind(Task task) {
|
||||
mOverlay.reset();
|
||||
mTask = task;
|
||||
int color = task == null ? Color.BLACK : task.colorBackground | 0xFF000000;
|
||||
@@ -353,7 +355,7 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
||||
mPreviewRect.set(0, 0, mThumbnailData.thumbnail.getWidth(),
|
||||
mThumbnailData.thumbnail.getHeight());
|
||||
mPreviewPositionHelper.updateThumbnailMatrix(mPreviewRect, mThumbnailData,
|
||||
mIsMultiWindowMode, getMeasuredWidth(), getMeasuredHeight());
|
||||
getMeasuredWidth(), getMeasuredHeight(), mActivity.getDeviceProfile());
|
||||
|
||||
mBitmapShader.setLocalMatrix(mPreviewPositionHelper.mMatrix);
|
||||
mPaint.setShader(mBitmapShader);
|
||||
@@ -439,13 +441,14 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
||||
* Updates the matrix based on the provided parameters
|
||||
*/
|
||||
public void updateThumbnailMatrix(Rect thumbnailPosition, ThumbnailData thumbnailData,
|
||||
boolean isInMultiWindowMode, int canvasWidth, int canvasHeight) {
|
||||
int canvasWidth, int canvasHeight, DeviceProfile dp) {
|
||||
boolean isRotated = false;
|
||||
boolean isOrientationDifferent;
|
||||
mClipBottom = -1;
|
||||
|
||||
float scale = thumbnailData.scale;
|
||||
Rect thumbnailInsets = thumbnailData.insets;
|
||||
|
||||
final float thumbnailWidth = thumbnailPosition.width()
|
||||
- (thumbnailInsets.left + thumbnailInsets.right) * scale;
|
||||
final float thumbnailHeight = thumbnailPosition.height()
|
||||
@@ -456,8 +459,9 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
||||
int currentRotation = getCurrentRotation();
|
||||
int deltaRotate = getRotationDelta(currentRotation, thumbnailRotation);
|
||||
|
||||
Rect deviceInsets = dp.getInsets();
|
||||
// Landscape vs portrait change
|
||||
boolean windowingModeSupportsRotation = !isInMultiWindowMode
|
||||
boolean windowingModeSupportsRotation = !dp.isMultiWindowMode
|
||||
&& thumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN;
|
||||
isOrientationDifferent = isOrientationChange(deltaRotate)
|
||||
&& windowingModeSupportsRotation;
|
||||
@@ -476,9 +480,10 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
||||
|
||||
if (!isRotated) {
|
||||
// No Rotation
|
||||
mClippedInsets.offsetTo(thumbnailInsets.left * scale,
|
||||
thumbnailInsets.top * scale);
|
||||
mMatrix.setTranslate(-mClippedInsets.left, -mClippedInsets.top);
|
||||
mClippedInsets.offsetTo(deviceInsets.left * scale, deviceInsets.top * scale);
|
||||
mMatrix.setTranslate(
|
||||
-thumbnailInsets.left * scale,
|
||||
-thumbnailInsets.top * scale);
|
||||
} else {
|
||||
setThumbnailRotation(deltaRotate, thumbnailInsets, scale, thumbnailPosition);
|
||||
}
|
||||
@@ -495,8 +500,16 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
||||
}
|
||||
mClippedInsets.left *= thumbnailScale;
|
||||
mClippedInsets.top *= thumbnailScale;
|
||||
mClippedInsets.right = widthWithInsets - mClippedInsets.left - canvasWidth;
|
||||
mClippedInsets.bottom = heightWithInsets - mClippedInsets.top - canvasHeight;
|
||||
|
||||
if (dp.isMultiWindowMode) {
|
||||
mClippedInsets.right = deviceInsets.right * scale * thumbnailScale;
|
||||
mClippedInsets.bottom = deviceInsets.bottom * scale * thumbnailScale;
|
||||
} else {
|
||||
mClippedInsets.right = Math.max(0,
|
||||
widthWithInsets - mClippedInsets.left - canvasWidth);
|
||||
mClippedInsets.bottom = Math.max(0,
|
||||
heightWithInsets - mClippedInsets.top - canvasHeight);
|
||||
}
|
||||
|
||||
mMatrix.postScale(thumbnailScale, thumbnailScale);
|
||||
|
||||
@@ -557,9 +570,8 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
||||
/**
|
||||
* Insets to used for clipping the thumbnail (in case it is drawing outside its own space)
|
||||
*/
|
||||
public RectF getInsetsToDrawInFullscreen(boolean isMultiWindowMode) {
|
||||
// Don't show insets in multi window mode.
|
||||
return isMultiWindowMode ? EMPTY_RECT_F : mClippedInsets;
|
||||
public RectF getInsetsToDrawInFullscreen() {
|
||||
return mClippedInsets;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,10 +274,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
* TODO(b/142282126) Re-evaluate if we need to pass in isMultiWindowMode after
|
||||
* that issue is fixed
|
||||
*/
|
||||
public void bind(Task task, RecentsOrientedState orientedState, boolean isMultiWindowMode) {
|
||||
public void bind(Task task, RecentsOrientedState orientedState) {
|
||||
cancelPendingLoadTasks();
|
||||
mTask = task;
|
||||
mSnapshotView.bind(task, isMultiWindowMode);
|
||||
mSnapshotView.bind(task);
|
||||
setOrientationState(orientedState);
|
||||
}
|
||||
|
||||
@@ -1017,14 +1017,13 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
*/
|
||||
public void setProgress(float fullscreenProgress, float parentScale, int previewWidth,
|
||||
DeviceProfile dp, PreviewPositionHelper pph) {
|
||||
boolean isMultiWindowMode = dp.isMultiWindowMode;
|
||||
RectF insets = pph.getInsetsToDrawInFullscreen(isMultiWindowMode);
|
||||
RectF insets = pph.getInsetsToDrawInFullscreen();
|
||||
|
||||
float currentInsetsLeft = insets.left * fullscreenProgress;
|
||||
float currentInsetsRight = insets.right * fullscreenProgress;
|
||||
mCurrentDrawnInsets.set(currentInsetsLeft, insets.top * fullscreenProgress,
|
||||
currentInsetsRight, insets.bottom * fullscreenProgress);
|
||||
float fullscreenCornerRadius = isMultiWindowMode ? 0 : mWindowCornerRadius;
|
||||
float fullscreenCornerRadius = dp.isMultiWindowMode ? 0 : mWindowCornerRadius;
|
||||
|
||||
mCurrentDrawnCornerRadius =
|
||||
Utilities.mapRange(fullscreenProgress, mCornerRadius, fullscreenCornerRadius)
|
||||
|
||||
@@ -17,31 +17,17 @@ package com.android.quickstep.util;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
|
||||
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
import static com.android.quickstep.util.WindowSizeStrategy.LAUNCHER_ACTIVITY_SIZE_STRATEGY;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
|
||||
import androidx.annotation.AnyThread;
|
||||
import androidx.annotation.IntDef;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
public class LayoutUtils {
|
||||
|
||||
private static final int MULTI_WINDOW_STRATEGY_HALF_SCREEN = 1;
|
||||
private static final int MULTI_WINDOW_STRATEGY_DEVICE_PROFILE = 2;
|
||||
|
||||
@Retention(SOURCE)
|
||||
@IntDef({MULTI_WINDOW_STRATEGY_HALF_SCREEN, MULTI_WINDOW_STRATEGY_DEVICE_PROFILE})
|
||||
private @interface MultiWindowStrategy {}
|
||||
|
||||
/**
|
||||
* The height for the swipe up motion
|
||||
*/
|
||||
@@ -53,112 +39,11 @@ public class LayoutUtils {
|
||||
return swipeHeight;
|
||||
}
|
||||
|
||||
public static void calculateLauncherTaskSize(Context context, DeviceProfile dp, Rect outRect) {
|
||||
float extraSpace;
|
||||
if (dp.isVerticalBarLayout()) {
|
||||
extraSpace = 0;
|
||||
} else {
|
||||
Resources res = context.getResources();
|
||||
|
||||
if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context)) {
|
||||
//TODO: this needs to account for the swipe gesture height and accessibility
|
||||
// UI when shown.
|
||||
extraSpace = res.getDimensionPixelSize(R.dimen.overview_actions_height);
|
||||
} else {
|
||||
extraSpace = getDefaultSwipeHeight(context, dp) + dp.workspacePageIndicatorHeight
|
||||
+ res.getDimensionPixelSize(
|
||||
R.dimen.dynamic_grid_hotseat_extra_vertical_size)
|
||||
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
|
||||
}
|
||||
}
|
||||
calculateTaskSize(context, dp, extraSpace, MULTI_WINDOW_STRATEGY_HALF_SCREEN, outRect);
|
||||
}
|
||||
|
||||
public static void calculateFallbackTaskSize(Context context, DeviceProfile dp, Rect outRect) {
|
||||
float extraSpace;
|
||||
if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context)) {
|
||||
extraSpace = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.overview_actions_height);
|
||||
} else {
|
||||
extraSpace = 0;
|
||||
}
|
||||
calculateTaskSize(context, dp, extraSpace, MULTI_WINDOW_STRATEGY_DEVICE_PROFILE, outRect);
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
public static void calculateTaskSize(Context context, DeviceProfile dp,
|
||||
float extraVerticalSpace, @MultiWindowStrategy int multiWindowStrategy, Rect outRect) {
|
||||
float taskWidth, taskHeight, paddingHorz;
|
||||
Resources res = context.getResources();
|
||||
Rect insets = dp.getInsets();
|
||||
final boolean overviewActionsEnabled = ENABLE_OVERVIEW_ACTIONS.get();
|
||||
|
||||
if (dp.isMultiWindowMode) {
|
||||
if (multiWindowStrategy == MULTI_WINDOW_STRATEGY_HALF_SCREEN) {
|
||||
DeviceProfile fullDp = dp.getFullScreenProfile();
|
||||
// Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to
|
||||
// account for system insets
|
||||
taskWidth = fullDp.availableWidthPx;
|
||||
taskHeight = fullDp.availableHeightPx;
|
||||
float halfDividerSize = res.getDimension(R.dimen.multi_window_task_divider_size)
|
||||
/ 2;
|
||||
|
||||
if (fullDp.isLandscape) {
|
||||
taskWidth = taskWidth / 2 - halfDividerSize;
|
||||
} else {
|
||||
taskHeight = taskHeight / 2 - halfDividerSize;
|
||||
}
|
||||
} else {
|
||||
// multiWindowStrategy == MULTI_WINDOW_STRATEGY_DEVICE_PROFILE
|
||||
taskWidth = dp.widthPx;
|
||||
taskHeight = dp.heightPx;
|
||||
}
|
||||
paddingHorz = res.getDimension(R.dimen.multi_window_task_card_horz_space);
|
||||
} else {
|
||||
taskWidth = dp.availableWidthPx;
|
||||
taskHeight = dp.availableHeightPx;
|
||||
|
||||
final int paddingResId;
|
||||
if (dp.isVerticalBarLayout()) {
|
||||
paddingResId = R.dimen.landscape_task_card_horz_space;
|
||||
} else if (overviewActionsEnabled && removeShelfFromOverview(context)) {
|
||||
paddingResId = R.dimen.portrait_task_card_horz_space_big_overview;
|
||||
} else {
|
||||
paddingResId = R.dimen.portrait_task_card_horz_space;
|
||||
}
|
||||
paddingHorz = res.getDimension(paddingResId);
|
||||
}
|
||||
|
||||
float topIconMargin = res.getDimension(R.dimen.task_thumbnail_top_margin);
|
||||
float paddingVert = overviewActionsEnabled && removeShelfFromOverview(context)
|
||||
? 0 : res.getDimension(R.dimen.task_card_vert_space);
|
||||
|
||||
// Note this should be same as dp.availableWidthPx and dp.availableHeightPx unless
|
||||
// we override the insets ourselves.
|
||||
int launcherVisibleWidth = dp.widthPx - insets.left - insets.right;
|
||||
int launcherVisibleHeight = dp.heightPx - insets.top - insets.bottom;
|
||||
|
||||
float availableHeight = launcherVisibleHeight
|
||||
- topIconMargin - extraVerticalSpace - paddingVert;
|
||||
float availableWidth = launcherVisibleWidth - paddingHorz;
|
||||
|
||||
float scale = Math.min(availableWidth / taskWidth, availableHeight / taskHeight);
|
||||
float outWidth = scale * taskWidth;
|
||||
float outHeight = scale * taskHeight;
|
||||
|
||||
// Center in the visible space
|
||||
float x = insets.left + (launcherVisibleWidth - outWidth) / 2;
|
||||
float y = insets.top + Math.max(topIconMargin,
|
||||
(launcherVisibleHeight - extraVerticalSpace - outHeight) / 2);
|
||||
outRect.set(Math.round(x), Math.round(y),
|
||||
Math.round(x) + Math.round(outWidth), Math.round(y) + Math.round(outHeight));
|
||||
}
|
||||
|
||||
public static int getShelfTrackingDistance(Context context, DeviceProfile dp) {
|
||||
// Track the bottom of the window.
|
||||
if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context)) {
|
||||
Rect taskSize = new Rect();
|
||||
calculateLauncherTaskSize(context, dp, taskSize);
|
||||
LAUNCHER_ACTIVITY_SIZE_STRATEGY.calculateTaskSize(context, dp, taskSize);
|
||||
return (dp.heightPx - taskSize.height()) / 2;
|
||||
}
|
||||
int shelfHeight = dp.hotseatBarSizePx + dp.getInsets().bottom;
|
||||
@@ -169,6 +54,7 @@ public class LayoutUtils {
|
||||
|
||||
/**
|
||||
* Gets the scale that should be applied to the TaskView so that it matches the target
|
||||
* TODO: Remove this method
|
||||
*/
|
||||
public static float getTaskScale(RecentsOrientedState orientedState,
|
||||
float srcWidth, float srcHeight, float targetWidth, float targetHeight) {
|
||||
|
||||
@@ -95,28 +95,29 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
||||
private static final int FLAG_HOME_ROTATION_ALLOWED_IN_PREFS = 1 << 3;
|
||||
// If the user has enabled system rotation
|
||||
private static final int FLAG_SYSTEM_ROTATION_ALLOWED = 1 << 4;
|
||||
// Multiple orientation is not supported in multiwindow mode
|
||||
private static final int FLAG_MULTIWINDOW_ROTATION_ALLOWED = 1 << 5;
|
||||
// Whether to rotation sensor is supported on the device
|
||||
private static final int FLAG_ROTATION_WATCHER_SUPPORTED = 1 << 5;
|
||||
private static final int FLAG_ROTATION_WATCHER_SUPPORTED = 1 << 6;
|
||||
// Whether to enable rotation watcher when multi-rotation is supported
|
||||
private static final int FLAG_ROTATION_WATCHER_ENABLED = 1 << 6;
|
||||
private static final int FLAG_ROTATION_WATCHER_ENABLED = 1 << 7;
|
||||
|
||||
private static final int MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE =
|
||||
FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY
|
||||
| FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_DENSITY
|
||||
| FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_FLAG;
|
||||
|
||||
private static final int MASK_ACTIVITY_ROTATING =
|
||||
FLAG_HOME_ROTATION_ALLOWED_IN_PREFS | FLAG_SYSTEM_ROTATION_ALLOWED;
|
||||
|
||||
// State for which rotation watcher will be enabled.
|
||||
// We skip it when home rotation is enabled as in that case, activity itself rotates
|
||||
// State for which rotation watcher will be enabled. We skip it when home rotation or
|
||||
// multi-window is enabled as in that case, activity itself rotates.
|
||||
private static final int VALUE_ROTATION_WATCHER_ENABLED =
|
||||
MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE | FLAG_SYSTEM_ROTATION_ALLOWED
|
||||
| FLAG_ROTATION_WATCHER_SUPPORTED | FLAG_ROTATION_WATCHER_ENABLED;
|
||||
|
||||
private final Context mContext;
|
||||
private final ContentResolver mContentResolver;
|
||||
private final SharedPreferences mSharedPrefs;
|
||||
private final OrientationEventListener mOrientationListener;
|
||||
private final WindowSizeStrategy mSizeStrategy;
|
||||
|
||||
private final Matrix mTmpMatrix = new Matrix();
|
||||
private final Matrix mTmpInverseMatrix = new Matrix();
|
||||
@@ -129,10 +130,12 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
||||
* is enabled
|
||||
* @see #setRotationWatcherEnabled(boolean)
|
||||
*/
|
||||
public RecentsOrientedState(Context context, boolean rotationSupportedByActivity,
|
||||
public RecentsOrientedState(Context context, WindowSizeStrategy sizeStrategy,
|
||||
IntConsumer rotationChangeListener) {
|
||||
mContext = context;
|
||||
mContentResolver = context.getContentResolver();
|
||||
mSharedPrefs = Utilities.getPrefs(context);
|
||||
mSizeStrategy = sizeStrategy;
|
||||
mOrientationListener = new OrientationEventListener(context) {
|
||||
@Override
|
||||
public void onOrientationChanged(int degrees) {
|
||||
@@ -144,7 +147,8 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
||||
}
|
||||
};
|
||||
|
||||
mFlags = rotationSupportedByActivity ? FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY : 0;
|
||||
mFlags = sizeStrategy.rotationSupportedByActivity
|
||||
? FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY : 0;
|
||||
|
||||
Resources res = context.getResources();
|
||||
int originalSmallestWidth = res.getConfiguration().smallestScreenWidthDp
|
||||
@@ -160,6 +164,13 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the host is in multi-window mode
|
||||
*/
|
||||
public void setMultiWindowMode(boolean isMultiWindow) {
|
||||
setFlag(FLAG_MULTIWINDOW_ROTATION_ALLOWED, isMultiWindow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the appropriate {@link PagedOrientationHandler} for {@link #mOrientationHandler}
|
||||
* @param touchRotation The rotation the nav bar region that is touched is in
|
||||
@@ -297,11 +308,12 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
||||
}
|
||||
|
||||
public boolean isHomeRotationAllowed() {
|
||||
return (mFlags & FLAG_HOME_ROTATION_ALLOWED_IN_PREFS) != 0;
|
||||
return (mFlags & (FLAG_HOME_ROTATION_ALLOWED_IN_PREFS | FLAG_MULTIWINDOW_ROTATION_ALLOWED))
|
||||
!= 0;
|
||||
}
|
||||
|
||||
public boolean canLauncherRotate() {
|
||||
return (mFlags & MASK_ACTIVITY_ROTATING) == MASK_ACTIVITY_ROTATING;
|
||||
return (mFlags & FLAG_SYSTEM_ROTATION_ALLOWED) != 0 && isHomeRotationAllowed();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -332,11 +344,22 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
||||
Rect insets = dp.getInsets();
|
||||
float fullWidth = dp.widthPx - insets.left - insets.right;
|
||||
float fullHeight = dp.heightPx - insets.top - insets.bottom;
|
||||
final float scale = LayoutUtils.getTaskScale(this,
|
||||
fullWidth, fullHeight, taskView.width(), taskView.height());
|
||||
|
||||
if (dp.isMultiWindowMode) {
|
||||
mSizeStrategy.getMultiWindowSize(mContext, dp, outPivot);
|
||||
} else {
|
||||
outPivot.set(fullWidth, fullHeight);
|
||||
}
|
||||
final float scale = Math.min(outPivot.x / taskView.width(), outPivot.y / taskView.height());
|
||||
|
||||
if (scale == 1) {
|
||||
outPivot.set(fullWidth / 2, fullHeight / 2);
|
||||
} else if (dp.isMultiWindowMode) {
|
||||
float denominator = 1 / (scale - 1);
|
||||
// Ensure that the task aligns to right bottom for the root view
|
||||
float y = (scale * taskView.bottom - fullHeight) * denominator;
|
||||
float x = (scale * taskView.right - fullWidth) * denominator;
|
||||
outPivot.set(x, y);
|
||||
} else {
|
||||
float factor = scale / (scale - 1);
|
||||
outPivot.set(taskView.left * factor, taskView.top * factor);
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.quickstep.util;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
|
||||
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
|
||||
import static com.android.quickstep.util.LayoutUtils.getDefaultSwipeHeight;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
|
||||
/**
|
||||
* Utility class to wrap different layout behavior for Launcher and RecentsView
|
||||
* TODO: Merge is with {@link com.android.quickstep.BaseActivityInterface} once we remove the
|
||||
* state dependent members from {@link com.android.quickstep.LauncherActivityInterface}
|
||||
*/
|
||||
public abstract class WindowSizeStrategy {
|
||||
|
||||
private final PointF mTempPoint = new PointF();
|
||||
public final boolean rotationSupportedByActivity;
|
||||
|
||||
private WindowSizeStrategy(boolean rotationSupportedByActivity) {
|
||||
this.rotationSupportedByActivity = rotationSupportedByActivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the expected window size in multi-window mode
|
||||
*/
|
||||
public abstract void getMultiWindowSize(Context context, DeviceProfile dp, PointF out);
|
||||
|
||||
/**
|
||||
* Calculates the taskView size for the provided device configuration
|
||||
*/
|
||||
public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect) {
|
||||
calculateTaskSize(context, dp, getExtraSpace(context, dp), outRect);
|
||||
}
|
||||
|
||||
abstract float getExtraSpace(Context context, DeviceProfile dp);
|
||||
|
||||
private void calculateTaskSize(
|
||||
Context context, DeviceProfile dp, float extraVerticalSpace, Rect outRect) {
|
||||
float taskWidth, taskHeight, paddingHorz;
|
||||
Resources res = context.getResources();
|
||||
Rect insets = dp.getInsets();
|
||||
final boolean showLargeTaskSize = showOverviewActions(context);
|
||||
|
||||
if (dp.isMultiWindowMode) {
|
||||
getMultiWindowSize(context, dp, mTempPoint);
|
||||
taskWidth = mTempPoint.x;
|
||||
taskHeight = mTempPoint.y;
|
||||
paddingHorz = res.getDimension(R.dimen.multi_window_task_card_horz_space);
|
||||
} else {
|
||||
taskWidth = dp.availableWidthPx;
|
||||
taskHeight = dp.availableHeightPx;
|
||||
|
||||
final int paddingResId;
|
||||
if (dp.isVerticalBarLayout()) {
|
||||
paddingResId = R.dimen.landscape_task_card_horz_space;
|
||||
} else if (showLargeTaskSize) {
|
||||
paddingResId = R.dimen.portrait_task_card_horz_space_big_overview;
|
||||
} else {
|
||||
paddingResId = R.dimen.portrait_task_card_horz_space;
|
||||
}
|
||||
paddingHorz = res.getDimension(paddingResId);
|
||||
}
|
||||
|
||||
float topIconMargin = res.getDimension(R.dimen.task_thumbnail_top_margin);
|
||||
float paddingVert = showLargeTaskSize
|
||||
? 0 : res.getDimension(R.dimen.task_card_vert_space);
|
||||
|
||||
// Note this should be same as dp.availableWidthPx and dp.availableHeightPx unless
|
||||
// we override the insets ourselves.
|
||||
int launcherVisibleWidth = dp.widthPx - insets.left - insets.right;
|
||||
int launcherVisibleHeight = dp.heightPx - insets.top - insets.bottom;
|
||||
|
||||
float availableHeight = launcherVisibleHeight
|
||||
- topIconMargin - extraVerticalSpace - paddingVert;
|
||||
float availableWidth = launcherVisibleWidth - paddingHorz;
|
||||
|
||||
float scale = Math.min(availableWidth / taskWidth, availableHeight / taskHeight);
|
||||
float outWidth = scale * taskWidth;
|
||||
float outHeight = scale * taskHeight;
|
||||
|
||||
// Center in the visible space
|
||||
float x = insets.left + (launcherVisibleWidth - outWidth) / 2;
|
||||
float y = insets.top + Math.max(topIconMargin,
|
||||
(launcherVisibleHeight - extraVerticalSpace - outHeight) / 2);
|
||||
outRect.set(Math.round(x), Math.round(y),
|
||||
Math.round(x) + Math.round(outWidth), Math.round(y) + Math.round(outHeight));
|
||||
}
|
||||
|
||||
|
||||
public static final WindowSizeStrategy LAUNCHER_ACTIVITY_SIZE_STRATEGY =
|
||||
new WindowSizeStrategy(true) {
|
||||
|
||||
@Override
|
||||
public void getMultiWindowSize(Context context, DeviceProfile dp, PointF out) {
|
||||
DeviceProfile fullDp = dp.getFullScreenProfile();
|
||||
// Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to
|
||||
// account for system insets
|
||||
out.set(fullDp.availableWidthPx, fullDp.availableHeightPx);
|
||||
float halfDividerSize = context.getResources()
|
||||
.getDimension(R.dimen.multi_window_task_divider_size) / 2;
|
||||
|
||||
if (fullDp.isLandscape) {
|
||||
out.x = out.x / 2 - halfDividerSize;
|
||||
} else {
|
||||
out.y = out.y / 2 - halfDividerSize;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
float getExtraSpace(Context context, DeviceProfile dp) {
|
||||
if (dp.isVerticalBarLayout()) {
|
||||
return 0;
|
||||
} else {
|
||||
Resources res = context.getResources();
|
||||
if (showOverviewActions(context)) {
|
||||
//TODO: this needs to account for the swipe gesture height and accessibility
|
||||
// UI when shown.
|
||||
return res.getDimensionPixelSize(R.dimen.overview_actions_height);
|
||||
} else {
|
||||
return getDefaultSwipeHeight(context, dp) + dp.workspacePageIndicatorHeight
|
||||
+ res.getDimensionPixelSize(
|
||||
R.dimen.dynamic_grid_hotseat_extra_vertical_size)
|
||||
+ res.getDimensionPixelSize(
|
||||
R.dimen.dynamic_grid_hotseat_bottom_padding);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static final WindowSizeStrategy FALLBACK_RECENTS_SIZE_STRATEGY =
|
||||
new WindowSizeStrategy(false) {
|
||||
@Override
|
||||
public void getMultiWindowSize(Context context, DeviceProfile dp, PointF out) {
|
||||
out.set(dp.widthPx, dp.heightPx);
|
||||
}
|
||||
|
||||
@Override
|
||||
float getExtraSpace(Context context, DeviceProfile dp) {
|
||||
return showOverviewActions(context)
|
||||
? context.getResources().getDimensionPixelSize(R.dimen.overview_actions_height)
|
||||
: 0;
|
||||
}
|
||||
};
|
||||
|
||||
static boolean showOverviewActions(Context context) {
|
||||
return ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context);
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Process;
|
||||
@@ -31,6 +32,7 @@ import android.os.StrictMode;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
import android.view.ActionMode;
|
||||
import android.view.Display;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Toast;
|
||||
@@ -270,4 +272,16 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
||||
}
|
||||
|
||||
protected abstract void reapplyUi();
|
||||
|
||||
protected Rect getMultiWindowDisplaySize() {
|
||||
if (Utilities.ATLEAST_R) {
|
||||
return new Rect(getWindowManager().getCurrentWindowMetrics().getBounds());
|
||||
}
|
||||
// Note: Calls to getSize() can't rely on our cached DefaultDisplay since it can return
|
||||
// the app window size
|
||||
Display display = getWindowManager().getDefaultDisplay();
|
||||
Point mwSize = new Point();
|
||||
display.getSize(mwSize);
|
||||
return new Rect(0, 0, mwSize.x, mwSize.y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ public class DeviceProfile {
|
||||
public final boolean isLandscape;
|
||||
public final boolean isMultiWindowMode;
|
||||
|
||||
public final int windowX;
|
||||
public final int windowY;
|
||||
public final int widthPx;
|
||||
public final int heightPx;
|
||||
public final int availableWidthPx;
|
||||
@@ -133,13 +135,16 @@ public class DeviceProfile {
|
||||
public DotRenderer mDotRendererWorkSpace;
|
||||
public DotRenderer mDotRendererAllApps;
|
||||
|
||||
public DeviceProfile(Context context, InvariantDeviceProfile inv, DefaultDisplay.Info info,
|
||||
DeviceProfile(Context context, InvariantDeviceProfile inv, DefaultDisplay.Info info,
|
||||
Point minSize, Point maxSize, int width, int height, boolean isLandscape,
|
||||
boolean isMultiWindowMode, boolean transposeLayoutWithOrientation) {
|
||||
boolean isMultiWindowMode, boolean transposeLayoutWithOrientation,
|
||||
Point windowPosition) {
|
||||
|
||||
this.inv = inv;
|
||||
this.isLandscape = isLandscape;
|
||||
this.isMultiWindowMode = isMultiWindowMode;
|
||||
windowX = windowPosition.x;
|
||||
windowY = windowPosition.y;
|
||||
|
||||
// Determine sizes.
|
||||
widthPx = width;
|
||||
@@ -244,6 +249,7 @@ public class DeviceProfile {
|
||||
return new Builder(context, inv, mInfo)
|
||||
.setSizeRange(size, size)
|
||||
.setSize(widthPx, heightPx)
|
||||
.setWindowPosition(windowX, windowY)
|
||||
.setMultiWindowMode(isMultiWindowMode);
|
||||
}
|
||||
|
||||
@@ -254,10 +260,11 @@ public class DeviceProfile {
|
||||
/**
|
||||
* TODO: Move this to the builder as part of setMultiWindowMode
|
||||
*/
|
||||
public DeviceProfile getMultiWindowProfile(Context context, Point mwSize) {
|
||||
public DeviceProfile getMultiWindowProfile(Context context, Rect windowPosition) {
|
||||
// We take the minimum sizes of this profile and it's multi-window variant to ensure that
|
||||
// the system decor is always excluded.
|
||||
mwSize.set(Math.min(availableWidthPx, mwSize.x), Math.min(availableHeightPx, mwSize.y));
|
||||
Point mwSize = new Point(Math.min(availableWidthPx, windowPosition.width()),
|
||||
Math.min(availableHeightPx, windowPosition.height()));
|
||||
|
||||
// In multi-window mode, we can have widthPx = availableWidthPx
|
||||
// and heightPx = availableHeightPx because Launcher uses the InvariantDeviceProfiles'
|
||||
@@ -265,6 +272,7 @@ public class DeviceProfile {
|
||||
DeviceProfile profile = toBuilder(context)
|
||||
.setSizeRange(mwSize, mwSize)
|
||||
.setSize(mwSize.x, mwSize.y)
|
||||
.setWindowPosition(windowPosition.left, windowPosition.top)
|
||||
.setMultiWindowMode(true)
|
||||
.build();
|
||||
|
||||
@@ -286,7 +294,7 @@ public class DeviceProfile {
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse of {@link #getMultiWindowProfile(Context, Point)}
|
||||
* Inverse of {@link #getMultiWindowProfile(Context, Rect)}
|
||||
* @return device profile corresponding to the current orientation in non multi-window mode.
|
||||
*/
|
||||
public DeviceProfile getFullScreenProfile() {
|
||||
@@ -649,6 +657,7 @@ public class DeviceProfile {
|
||||
private InvariantDeviceProfile mInv;
|
||||
private DefaultDisplay.Info mInfo;
|
||||
|
||||
private final Point mWindowPosition = new Point();
|
||||
private Point mMinSize, mMaxSize;
|
||||
private int mWidth, mHeight;
|
||||
|
||||
@@ -682,6 +691,14 @@ public class DeviceProfile {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the window position if not full-screen
|
||||
*/
|
||||
public Builder setWindowPosition(int x, int y) {
|
||||
mWindowPosition.set(x, y);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTransposeLayoutWithOrientation(boolean transposeLayoutWithOrientation) {
|
||||
mTransposeLayoutWithOrientation = transposeLayoutWithOrientation;
|
||||
return this;
|
||||
@@ -690,7 +707,7 @@ public class DeviceProfile {
|
||||
public DeviceProfile build() {
|
||||
return new DeviceProfile(mContext, mInv, mInfo, mMinSize, mMaxSize,
|
||||
mWidth, mHeight, mIsLandscape, mIsMultiWindowMode,
|
||||
mTransposeLayoutWithOrientation);
|
||||
mTransposeLayoutWithOrientation, mWindowPosition);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,6 @@ import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.Point;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
@@ -69,7 +68,6 @@ import android.text.TextUtils;
|
||||
import android.text.method.TextKeyListener;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.Display;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.KeyboardShortcutGroup;
|
||||
import android.view.KeyboardShortcutInfo;
|
||||
@@ -560,12 +558,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
// Load configuration-specific DeviceProfile
|
||||
mDeviceProfile = idp.getDeviceProfile(this);
|
||||
if (isInMultiWindowMode()) {
|
||||
// Note: Calls to getSize() can't rely on our cached DefaultDisplay since it can return
|
||||
// the app window size
|
||||
Display display = getWindowManager().getDefaultDisplay();
|
||||
Point mwSize = new Point();
|
||||
display.getSize(mwSize);
|
||||
mDeviceProfile = mDeviceProfile.getMultiWindowProfile(this, mwSize);
|
||||
mDeviceProfile = mDeviceProfile.getMultiWindowProfile(
|
||||
this, getMultiWindowDisplaySize());
|
||||
}
|
||||
|
||||
onDeviceProfileInitiated();
|
||||
|
||||
@@ -64,15 +64,8 @@ public class LauncherRootView extends InsettableFrameLayout {
|
||||
private void handleSystemWindowInsets(Rect insets) {
|
||||
mConsumedInsets.setEmpty();
|
||||
boolean drawInsetBar = false;
|
||||
if (mLauncher.isInMultiWindowMode()
|
||||
&& (insets.left > 0 || insets.right > 0 || insets.bottom > 0)) {
|
||||
mConsumedInsets.left = insets.left;
|
||||
mConsumedInsets.right = insets.right;
|
||||
mConsumedInsets.bottom = insets.bottom;
|
||||
insets.set(0, insets.top, 0, 0);
|
||||
drawInsetBar = true;
|
||||
} else if ((insets.right > 0 || insets.left > 0) &&
|
||||
getContext().getSystemService(ActivityManager.class).isLowRamDevice()) {
|
||||
if ((insets.right > 0 || insets.left > 0)
|
||||
&& getContext().getSystemService(ActivityManager.class).isLowRamDevice()) {
|
||||
mConsumedInsets.left = insets.left;
|
||||
mConsumedInsets.right = insets.right;
|
||||
insets.set(0, insets.top, 0, insets.bottom);
|
||||
|
||||
@@ -63,6 +63,8 @@ import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.core.os.BuildCompat;
|
||||
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
|
||||
import com.android.launcher3.graphics.GridOptionsProvider;
|
||||
@@ -104,6 +106,8 @@ public final class Utilities {
|
||||
public static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
public static final Person[] EMPTY_PERSON_ARRAY = new Person[0];
|
||||
|
||||
public static final boolean ATLEAST_R = BuildCompat.isAtLeastR();
|
||||
|
||||
public static final boolean ATLEAST_Q = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
|
||||
|
||||
public static final boolean ATLEAST_P =
|
||||
|
||||
Reference in New Issue
Block a user