summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java42
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java18
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java17
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java94
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskDragResizer.java29
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java39
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java27
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt138
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt71
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java66
14 files changed, 452 insertions, 133 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 71bf487249fb..0ef047f44909 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -235,7 +235,8 @@ public abstract class WMShellModule {
mainChoreographer,
taskOrganizer,
displayController,
- syncQueue);
+ syncQueue,
+ transitions);
}
//
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index cf1692018518..cebc4006656a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -54,6 +54,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
private final Choreographer mMainChoreographer;
private final DisplayController mDisplayController;
private final SyncTransactionQueue mSyncQueue;
+ private final Transitions mTransitions;
private TaskOperations mTaskOperations;
private final SparseArray<CaptionWindowDecoration> mWindowDecorByTaskId = new SparseArray<>();
@@ -64,13 +65,15 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
Choreographer mainChoreographer,
ShellTaskOrganizer taskOrganizer,
DisplayController displayController,
- SyncTransactionQueue syncQueue) {
+ SyncTransactionQueue syncQueue,
+ Transitions transitions) {
mContext = context;
mMainHandler = mainHandler;
mMainChoreographer = mainChoreographer;
mTaskOrganizer = taskOrganizer;
mDisplayController = displayController;
mSyncQueue = syncQueue;
+ mTransitions = transitions;
if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
mTaskOperations = new TaskOperations(null, mContext, mSyncQueue);
}
@@ -133,7 +136,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
if (decoration == null) {
createWindowDecoration(taskInfo, taskSurface, startT, finishT);
} else {
- decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
+ decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */,
+ false /* setTaskCropAndPosition */);
}
}
@@ -145,7 +149,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
if (decoration == null) return;
- decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
+ decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */,
+ false /* setTaskCropAndPosition */);
}
@Override
@@ -191,16 +196,17 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
mSyncQueue);
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
- final DragPositioningCallback dragPositioningCallback =
- new FluidResizeTaskPositioner(mTaskOrganizer, windowDecoration, mDisplayController,
- 0 /* disallowedAreaForEndBoundsHeight */);
+ final FluidResizeTaskPositioner taskPositioner =
+ new FluidResizeTaskPositioner(mTaskOrganizer, mTransitions, windowDecoration,
+ mDisplayController, 0 /* disallowedAreaForEndBoundsHeight */);
final CaptionTouchEventListener touchEventListener =
- new CaptionTouchEventListener(taskInfo, dragPositioningCallback);
+ new CaptionTouchEventListener(taskInfo, taskPositioner);
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
- windowDecoration.setDragPositioningCallback(dragPositioningCallback);
+ windowDecoration.setDragPositioningCallback(taskPositioner);
windowDecoration.setDragDetector(touchEventListener.mDragDetector);
+ windowDecoration.setTaskDragResizer(taskPositioner);
windowDecoration.relayout(taskInfo, startT, finishT,
- false /* applyStartTransactionOnDraw */);
+ false /* applyStartTransactionOnDraw */, false /* setTaskCropAndPosition */);
setupCaptionColor(taskInfo, windowDecoration);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index 6e7d11d9082b..1debb02e86af 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -157,15 +157,21 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
@Override
void relayout(RunningTaskInfo taskInfo) {
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ // The crop and position of the task should only be set when a task is fluid resizing. In
+ // all other cases, it is expected that the transition handler positions and crops the task
+ // in order to allow the handler time to animate before the task before the final
+ // position and crop are set.
+ final boolean shouldSetTaskPositionAndCrop = mTaskDragResizer.isResizingOrAnimating();
// Use |applyStartTransactionOnDraw| so that the transaction (that applies task crop) is
// synced with the buffer transaction (that draws the View). Both will be shown on screen
// at the same, whereas applying them independently causes flickering. See b/270202228.
- relayout(taskInfo, t, t, true /* applyStartTransactionOnDraw */);
+ relayout(taskInfo, t, t, true /* applyStartTransactionOnDraw */,
+ shouldSetTaskPositionAndCrop);
}
void relayout(RunningTaskInfo taskInfo,
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
- boolean applyStartTransactionOnDraw) {
+ boolean applyStartTransactionOnDraw, boolean setTaskCropAndPosition) {
final int shadowRadiusID = taskInfo.isFocused
? R.dimen.freeform_decor_shadow_focused_thickness
: R.dimen.freeform_decor_shadow_unfocused_thickness;
@@ -183,6 +189,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
mRelayoutParams.mCaptionHeightId = getCaptionHeightId(taskInfo.getWindowingMode());
mRelayoutParams.mShadowRadiusId = shadowRadiusID;
mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
+ mRelayoutParams.mSetTaskPositionAndCrop = setTaskCropAndPosition;
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
// After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index ab29df1f780c..4fd362591151 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -335,7 +335,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
if (decoration == null) {
createWindowDecoration(taskInfo, taskSurface, startT, finishT);
} else {
- decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
+ decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */,
+ false /* shouldSetTaskPositionAndCrop */);
}
}
@@ -347,7 +348,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
if (decoration == null) return;
- decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
+ decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */,
+ false /* shouldSetTaskPositionAndCrop */);
}
@Override
@@ -1010,8 +1012,23 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
windowDecoration.createResizeVeil();
- final DragPositioningCallback dragPositioningCallback = createDragPositioningCallback(
- windowDecoration);
+ final DragPositioningCallback dragPositioningCallback;
+ final int transitionAreaHeight = mContext.getResources().getDimensionPixelSize(
+ R.dimen.desktop_mode_transition_area_height);
+ if (!DesktopModeStatus.isVeiledResizeEnabled()) {
+ dragPositioningCallback = new FluidResizeTaskPositioner(
+ mTaskOrganizer, mTransitions, windowDecoration, mDisplayController,
+ mDragStartListener, mTransactionFactory, transitionAreaHeight);
+ windowDecoration.setTaskDragResizer(
+ (FluidResizeTaskPositioner) dragPositioningCallback);
+ } else {
+ dragPositioningCallback = new VeiledResizeTaskPositioner(
+ mTaskOrganizer, windowDecoration, mDisplayController,
+ mDragStartListener, mTransitions, transitionAreaHeight);
+ windowDecoration.setTaskDragResizer(
+ (VeiledResizeTaskPositioner) dragPositioningCallback);
+ }
+
final DesktopModeTouchEventListener touchEventListener =
new DesktopModeTouchEventListener(taskInfo, dragPositioningCallback);
@@ -1021,23 +1038,9 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
windowDecoration.setDragPositioningCallback(dragPositioningCallback);
windowDecoration.setDragDetector(touchEventListener.mDragDetector);
windowDecoration.relayout(taskInfo, startT, finishT,
- false /* applyStartTransactionOnDraw */);
+ false /* applyStartTransactionOnDraw */, false /* shouldSetTaskPositionAndCrop */);
incrementEventReceiverTasks(taskInfo.displayId);
}
- private DragPositioningCallback createDragPositioningCallback(
- @NonNull DesktopModeWindowDecoration windowDecoration) {
- final int transitionAreaHeight = mContext.getResources().getDimensionPixelSize(
- R.dimen.desktop_mode_transition_area_height);
- if (!DesktopModeStatus.isVeiledResizeEnabled()) {
- return new FluidResizeTaskPositioner(mTaskOrganizer, windowDecoration,
- mDisplayController, mDragStartListener, mTransactionFactory,
- transitionAreaHeight);
- } else {
- return new VeiledResizeTaskPositioner(mTaskOrganizer, windowDecoration,
- mDisplayController, mDragStartListener, mTransitions,
- transitionAreaHeight);
- }
- }
private RunningTaskInfo getOtherSplitTask(int taskId) {
@SplitPosition int remainingTaskPosition = mSplitScreenController
@@ -1138,7 +1141,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
}
}
}
-
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 2f51278e3c80..0c8e93b48d02 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -187,20 +187,28 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
}
final SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
+ // The crop and position of the task should only be set when a task is fluid resizing. In
+ // all other cases, it is expected that the transition handler positions and crops the task
+ // in order to allow the handler time to animate before the task before the final
+ // position and crop are set.
+ final boolean shouldSetTaskPositionAndCrop = !DesktopModeStatus.isVeiledResizeEnabled()
+ && mTaskDragResizer.isResizingOrAnimating();
// Use |applyStartTransactionOnDraw| so that the transaction (that applies task crop) is
// synced with the buffer transaction (that draws the View). Both will be shown on screen
// at the same, whereas applying them independently causes flickering. See b/270202228.
- relayout(taskInfo, t, t, true /* applyStartTransactionOnDraw */);
+ relayout(taskInfo, t, t, true /* applyStartTransactionOnDraw */,
+ shouldSetTaskPositionAndCrop);
}
void relayout(ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
- boolean applyStartTransactionOnDraw) {
+ boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop) {
if (isHandleMenuActive()) {
mHandleMenu.relayout(startT);
}
- updateRelayoutParams(mRelayoutParams, mContext, taskInfo, applyStartTransactionOnDraw);
+ updateRelayoutParams(mRelayoutParams, mContext, taskInfo, applyStartTransactionOnDraw,
+ shouldSetTaskPositionAndCrop);
final WindowDecorLinearLayout oldRootView = mResult.mRootView;
final SurfaceControl oldDecorationSurface = mDecorationContainerSurface;
@@ -302,7 +310,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
RelayoutParams relayoutParams,
Context context,
ActivityManager.RunningTaskInfo taskInfo,
- boolean applyStartTransactionOnDraw) {
+ boolean applyStartTransactionOnDraw,
+ boolean shouldSetTaskPositionAndCrop) {
relayoutParams.reset();
relayoutParams.mRunningTaskInfo = taskInfo;
relayoutParams.mLayoutResId =
@@ -314,6 +323,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
: R.dimen.freeform_decor_shadow_unfocused_thickness;
}
relayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
+ relayoutParams.mSetTaskPositionAndCrop = shouldSetTaskPositionAndCrop;
// The configuration used to lay out the window decoration. The system context's config is
// used when the task density has been overridden to a custom density so that the resources
// and views of the decoration aren't affected and match the rest of the System UI, if not
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java
index 677c7f1fb5a8..5afbd54088d1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java
@@ -26,9 +26,7 @@ import android.graphics.PointF;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.SurfaceControl;
-import android.window.WindowContainerTransaction;
-import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
/**
@@ -130,8 +128,7 @@ public class DragPositioningCallbackUtility {
Rect taskBoundsAtDragStart, PointF repositionStartPoint, SurfaceControl.Transaction t,
float x, float y) {
updateTaskBounds(repositionTaskBounds, taskBoundsAtDragStart, repositionStartPoint, x, y);
- t.setPosition(decoration.mTaskSurface, repositionTaskBounds.left,
- repositionTaskBounds.top);
+ t.setPosition(decoration.mTaskSurface, repositionTaskBounds.left, repositionTaskBounds.top);
}
private static void updateTaskBounds(Rect repositionTaskBounds, Rect taskBoundsAtDragStart,
@@ -188,18 +185,6 @@ public class DragPositioningCallbackUtility {
}
}
- /**
- * Apply a bounds change to a task.
- * @param windowDecoration decor of task we are changing bounds for
- * @param taskBounds new bounds of this task
- * @param taskOrganizer applies the provided WindowContainerTransaction
- */
- static void applyTaskBoundsChange(WindowContainerTransaction wct,
- WindowDecoration windowDecoration, Rect taskBounds, ShellTaskOrganizer taskOrganizer) {
- wct.setBounds(windowDecoration.mTaskInfo.token, taskBounds);
- taskOrganizer.applyTransaction(wct);
- }
-
private static float getMinWidth(DisplayController displayController,
WindowDecoration windowDecoration) {
return windowDecoration.mTaskInfo.minWidth < 0 ? getDefaultMinSize(displayController,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java
index 5d006fb4d9e2..6bfc7cdcb33e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java
@@ -16,23 +16,42 @@
package com.android.wm.shell.windowdecor;
+import static android.view.WindowManager.TRANSIT_CHANGE;
+
import android.graphics.PointF;
import android.graphics.Rect;
+import android.os.IBinder;
import android.view.Surface;
import android.view.SurfaceControl;
+import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
import android.window.WindowContainerTransaction;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.transition.Transitions;
import java.util.function.Supplier;
/**
* A task positioner that resizes/relocates task contents as it is dragged.
* Utilizes {@link DragPositioningCallbackUtility} to determine new task bounds.
+ *
+ * This positioner applies the final bounds after a resize or drag using a shell transition in order
+ * to utilize the startAnimation callback to set the final task position and crop. In most cases,
+ * the transition will be aborted since the final bounds are usually the same bounds set in the
+ * final {@link #onDragPositioningMove} call. In this case, the cropping and positioning would be
+ * set by {@link WindowDecoration#relayout} due to the final bounds change; however, it is important
+ * that we send the final shell transition since we still utilize the {@link #onTransitionConsumed}
+ * callback.
*/
-class FluidResizeTaskPositioner implements DragPositioningCallback {
+class FluidResizeTaskPositioner implements DragPositioningCallback,
+ TaskDragResizer, Transitions.TransitionHandler {
private final ShellTaskOrganizer mTaskOrganizer;
+ private final Transitions mTransitions;
private final WindowDecoration mWindowDecoration;
private final Supplier<SurfaceControl.Transaction> mTransactionSupplier;
private DisplayController mDisplayController;
@@ -45,21 +64,28 @@ class FluidResizeTaskPositioner implements DragPositioningCallback {
// finalize the bounds there using WCT#setBounds
private final int mDisallowedAreaForEndBoundsHeight;
private boolean mHasDragResized;
+ private boolean mIsResizingOrAnimatingResize;
private int mCtrlType;
+ private IBinder mDragResizeEndTransition;
@Surface.Rotation private int mRotation;
- FluidResizeTaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration,
- DisplayController displayController, int disallowedAreaForEndBoundsHeight) {
- this(taskOrganizer, windowDecoration, displayController, dragStartListener -> {},
- SurfaceControl.Transaction::new, disallowedAreaForEndBoundsHeight);
+ FluidResizeTaskPositioner(ShellTaskOrganizer taskOrganizer, Transitions transitions,
+ WindowDecoration windowDecoration, DisplayController displayController,
+ int disallowedAreaForEndBoundsHeight) {
+ this(taskOrganizer, transitions, windowDecoration, displayController,
+ dragStartListener -> {}, SurfaceControl.Transaction::new,
+ disallowedAreaForEndBoundsHeight);
}
- FluidResizeTaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration,
+ FluidResizeTaskPositioner(ShellTaskOrganizer taskOrganizer,
+ Transitions transitions,
+ WindowDecoration windowDecoration,
DisplayController displayController,
DragPositioningCallbackUtility.DragStartListener dragStartListener,
Supplier<SurfaceControl.Transaction> supplier,
int disallowedAreaForEndBoundsHeight) {
mTaskOrganizer = taskOrganizer;
+ mTransitions = transitions;
mWindowDecoration = windowDecoration;
mDisplayController = displayController;
mDragStartListener = dragStartListener;
@@ -103,9 +129,10 @@ class FluidResizeTaskPositioner implements DragPositioningCallback {
// This is the first bounds change since drag resize operation started.
wct.setDragResizing(mWindowDecoration.mTaskInfo.token, true /* dragResizing */);
}
- DragPositioningCallbackUtility.applyTaskBoundsChange(wct, mWindowDecoration,
- mRepositionTaskBounds, mTaskOrganizer);
+ wct.setBounds(mWindowDecoration.mTaskInfo.token, mRepositionTaskBounds);
+ mTaskOrganizer.applyTransaction(wct);
mHasDragResized = true;
+ mIsResizingOrAnimatingResize = true;
} else if (mCtrlType == CTRL_TYPE_UNDEFINED) {
final SurfaceControl.Transaction t = mTransactionSupplier.get();
DragPositioningCallbackUtility.setPositionOnDrag(mWindowDecoration,
@@ -129,7 +156,7 @@ class FluidResizeTaskPositioner implements DragPositioningCallback {
mWindowDecoration)) {
wct.setBounds(mWindowDecoration.mTaskInfo.token, mRepositionTaskBounds);
}
- mTaskOrganizer.applyTransaction(wct);
+ mDragResizeEndTransition = mTransitions.startTransition(TRANSIT_CHANGE, wct, this);
} else if (mCtrlType == CTRL_TYPE_UNDEFINED
&& DragPositioningCallbackUtility.isBelowDisallowedArea(
mDisallowedAreaForEndBoundsHeight, mTaskBoundsAtDragStart, mRepositionStartPoint,
@@ -139,7 +166,7 @@ class FluidResizeTaskPositioner implements DragPositioningCallback {
mTaskBoundsAtDragStart, mRepositionStartPoint, x, y,
mWindowDecoration.calculateValidDragArea());
wct.setBounds(mWindowDecoration.mTaskInfo.token, mRepositionTaskBounds);
- mTaskOrganizer.applyTransaction(wct);
+ mTransitions.startTransition(TRANSIT_CHANGE, wct, this);
}
mTaskBoundsAtDragStart.setEmpty();
@@ -154,4 +181,51 @@ class FluidResizeTaskPositioner implements DragPositioningCallback {
|| (mCtrlType & CTRL_TYPE_LEFT) != 0 || (mCtrlType & CTRL_TYPE_RIGHT) != 0;
}
+ @Override
+ public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction startTransaction,
+ @NonNull SurfaceControl.Transaction finishTransaction,
+ @NonNull Transitions.TransitionFinishCallback finishCallback) {
+ for (TransitionInfo.Change change: info.getChanges()) {
+ final SurfaceControl sc = change.getLeash();
+ final Rect endBounds = change.getEndAbsBounds();
+ startTransaction.setWindowCrop(sc, endBounds.width(), endBounds.height())
+ .setPosition(sc, endBounds.left, endBounds.top);
+ finishTransaction.setWindowCrop(sc, endBounds.width(), endBounds.height())
+ .setPosition(sc, endBounds.left, endBounds.top);
+ }
+
+ startTransaction.apply();
+ if (transition.equals(mDragResizeEndTransition)) {
+ mIsResizingOrAnimatingResize = false;
+ mDragResizeEndTransition = null;
+ }
+ finishCallback.onTransitionFinished(null);
+ return true;
+ }
+
+ /**
+ * We should never reach this as this handler's transitions are only started from shell
+ * explicitly.
+ */
+ @Nullable
+ @Override
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @NonNull TransitionRequestInfo request) {
+ return null;
+ }
+
+ @Override
+ public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+ @Nullable SurfaceControl.Transaction finishTransaction) {
+ if (transition.equals(mDragResizeEndTransition)) {
+ mIsResizingOrAnimatingResize = false;
+ mDragResizeEndTransition = null;
+ }
+ }
+
+ @Override
+ public boolean isResizingOrAnimating() {
+ return mIsResizingOrAnimatingResize;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskDragResizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskDragResizer.java
new file mode 100644
index 000000000000..40421b599889
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskDragResizer.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 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.wm.shell.windowdecor;
+
+/**
+ * Holds the state of a drag resize.
+ */
+interface TaskDragResizer {
+
+ /**
+ * Returns true if task is currently being resized or animating the final transition after
+ * a resize is complete.
+ */
+ boolean isResizingOrAnimating();
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
index 4363558ca00b..c1b18f959641 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
@@ -43,7 +43,7 @@ import java.util.function.Supplier;
* If the drag is repositioning, we update in the typical manner.
*/
public class VeiledResizeTaskPositioner implements DragPositioningCallback,
- Transitions.TransitionHandler {
+ TaskDragResizer, Transitions.TransitionHandler {
private DesktopModeWindowDecoration mDesktopWindowDecoration;
private ShellTaskOrganizer mTaskOrganizer;
@@ -59,10 +59,12 @@ public class VeiledResizeTaskPositioner implements DragPositioningCallback,
private final int mDisallowedAreaForEndBoundsHeight;
private final Supplier<SurfaceControl.Transaction> mTransactionSupplier;
private int mCtrlType;
+ private boolean mIsResizingOrAnimatingResize;
@Surface.Rotation private int mRotation;
public VeiledResizeTaskPositioner(ShellTaskOrganizer taskOrganizer,
- DesktopModeWindowDecoration windowDecoration, DisplayController displayController,
+ DesktopModeWindowDecoration windowDecoration,
+ DisplayController displayController,
DragPositioningCallbackUtility.DragStartListener dragStartListener,
Transitions transitions,
int disallowedAreaForEndBoundsHeight) {
@@ -71,12 +73,13 @@ public class VeiledResizeTaskPositioner implements DragPositioningCallback,
}
public VeiledResizeTaskPositioner(ShellTaskOrganizer taskOrganizer,
- DesktopModeWindowDecoration windowDecoration, DisplayController displayController,
+ DesktopModeWindowDecoration windowDecoration,
+ DisplayController displayController,
DragPositioningCallbackUtility.DragStartListener dragStartListener,
Supplier<SurfaceControl.Transaction> supplier, Transitions transitions,
int disallowedAreaForEndBoundsHeight) {
- mTaskOrganizer = taskOrganizer;
mDesktopWindowDecoration = windowDecoration;
+ mTaskOrganizer = taskOrganizer;
mDisplayController = displayController;
mDragStartListener = dragStartListener;
mTransactionSupplier = supplier;
@@ -117,6 +120,7 @@ public class VeiledResizeTaskPositioner implements DragPositioningCallback,
mRepositionTaskBounds, mTaskBoundsAtDragStart, mStableBounds, delta,
mDisplayController, mDesktopWindowDecoration)) {
mDesktopWindowDecoration.updateResizeVeil(mRepositionTaskBounds);
+ mIsResizingOrAnimatingResize = true;
} else if (mCtrlType == CTRL_TYPE_UNDEFINED) {
final SurfaceControl.Transaction t = mTransactionSupplier.get();
DragPositioningCallbackUtility.setPositionOnDrag(mDesktopWindowDecoration,
@@ -138,24 +142,22 @@ public class VeiledResizeTaskPositioner implements DragPositioningCallback,
mDesktopWindowDecoration.updateResizeVeil(mRepositionTaskBounds);
final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setBounds(mDesktopWindowDecoration.mTaskInfo.token, mRepositionTaskBounds);
- if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- mTransitions.startTransition(TRANSIT_CHANGE, wct, this);
- } else {
- mTaskOrganizer.applyTransaction(wct);
- }
+ mTransitions.startTransition(TRANSIT_CHANGE, wct, this);
} else {
// If bounds haven't changed, perform necessary veil reset here as startAnimation
// won't be called.
mDesktopWindowDecoration.hideResizeVeil();
+ mIsResizingOrAnimatingResize = false;
}
} else if (DragPositioningCallbackUtility.isBelowDisallowedArea(
mDisallowedAreaForEndBoundsHeight, mTaskBoundsAtDragStart, mRepositionStartPoint,
y)) {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
DragPositioningCallbackUtility.onDragEnd(mRepositionTaskBounds,
mTaskBoundsAtDragStart, mRepositionStartPoint, x, y,
mDesktopWindowDecoration.calculateValidDragArea());
- DragPositioningCallbackUtility.applyTaskBoundsChange(new WindowContainerTransaction(),
- mDesktopWindowDecoration, mRepositionTaskBounds, mTaskOrganizer);
+ wct.setBounds(mDesktopWindowDecoration.mTaskInfo.token, mRepositionTaskBounds);
+ mTransitions.startTransition(TRANSIT_CHANGE, wct, this);
}
mCtrlType = CTRL_TYPE_UNDEFINED;
@@ -174,10 +176,20 @@ public class VeiledResizeTaskPositioner implements DragPositioningCallback,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
+ for (TransitionInfo.Change change: info.getChanges()) {
+ final SurfaceControl sc = change.getLeash();
+ final Rect endBounds = change.getEndAbsBounds();
+ startTransaction.setWindowCrop(sc, endBounds.width(), endBounds.height())
+ .setPosition(sc, endBounds.left, endBounds.top);
+ finishTransaction.setWindowCrop(sc, endBounds.width(), endBounds.height())
+ .setPosition(sc, endBounds.left, endBounds.top);
+ }
+
startTransaction.apply();
mDesktopWindowDecoration.hideResizeVeil();
mCtrlType = CTRL_TYPE_UNDEFINED;
finishCallback.onTransitionFinished(null);
+ mIsResizingOrAnimatingResize = false;
return true;
}
@@ -191,4 +203,9 @@ public class VeiledResizeTaskPositioner implements DragPositioningCallback,
@NonNull TransitionRequestInfo request) {
return null;
}
+
+ @Override
+ public boolean isResizingOrAnimating() {
+ return mIsResizingOrAnimatingResize;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index ee0e31ec3aef..b5373c67c602 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -124,6 +124,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
private WindowlessWindowManager mCaptionWindowManager;
private SurfaceControlViewHost mViewHost;
private Configuration mWindowDecorConfig;
+ TaskDragResizer mTaskDragResizer;
private boolean mIsCaptionVisible;
private final Binder mOwner = new Binder();
@@ -311,25 +312,21 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
float shadowRadius;
final Point taskPosition = mTaskInfo.positionInParent;
if (isFullscreen) {
- // Setting the task crop to the width/height stops input events from being sent to
- // some regions of the app window. See b/300324920
- // TODO(b/296921174): investigate whether crop/position needs to be set by window
- // decorations at all when transition handlers are already taking ownership of the task
- // surface placement/crop, especially when in fullscreen where tasks cannot be
- // drag-resized by the window decoration.
- startT.setWindowCrop(mTaskSurface, null);
- finishT.setWindowCrop(mTaskSurface, null);
// Shadow is not needed for fullscreen tasks
shadowRadius = 0;
} else {
- startT.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight);
- finishT.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight);
shadowRadius = loadDimension(resources, params.mShadowRadiusId);
}
+
+ if (params.mSetTaskPositionAndCrop) {
+ startT.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight);
+ finishT.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight)
+ .setPosition(mTaskSurface, taskPosition.x, taskPosition.y);
+ }
+
startT.setShadowRadius(mTaskSurface, shadowRadius)
.show(mTaskSurface);
- finishT.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
- .setShadowRadius(mTaskSurface, shadowRadius);
+ finishT.setShadowRadius(mTaskSurface, shadowRadius);
if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
if (!DesktopModeStatus.isVeiledResizeEnabled()) {
// When fluid resize is enabled, add a background to freeform tasks
@@ -394,6 +391,10 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
}
}
+ void setTaskDragResizer(TaskDragResizer taskDragResizer) {
+ mTaskDragResizer = taskDragResizer;
+ }
+
private void setCaptionVisibility(View rootView, boolean visible) {
if (rootView == null) {
return;
@@ -559,6 +560,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
Configuration mWindowDecorConfig;
boolean mApplyStartTransactionOnDraw;
+ boolean mSetTaskPositionAndCrop;
void reset() {
mLayoutResId = Resources.ID_NULL;
@@ -572,6 +574,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
mCaptionY = 0;
mApplyStartTransactionOnDraw = false;
+ mSetTaskPositionAndCrop = false;
mWindowDecorConfig = null;
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index 77667ca579f2..193f16da3e39 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -144,7 +144,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
RelayoutParams relayoutParams = new RelayoutParams();
DesktopModeWindowDecoration.updateRelayoutParams(
- relayoutParams, mContext, taskInfo, /* applyStartTransactionOnDraw= */ true);
+ relayoutParams, mContext, taskInfo, /* applyStartTransactionOnDraw= */ true,
+ /* shouldSetTaskPositionAndCrop */ false);
assertThat(relayoutParams.mShadowRadiusId).isNotEqualTo(Resources.ID_NULL);
}
@@ -159,7 +160,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
relayoutParams,
mTestableContext,
taskInfo,
- /* applyStartTransactionOnDraw= */ true);
+ /* applyStartTransactionOnDraw= */ true,
+ /* shouldSetTaskPositionAndCrop */ false);
assertThat(relayoutParams.mCornerRadius).isGreaterThan(0);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
index 2ce49cf62614..de6903d9a06a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
@@ -10,6 +10,7 @@ import android.view.Surface
import android.view.Surface.ROTATION_270
import android.view.Surface.ROTATION_90
import android.view.SurfaceControl
+import android.view.WindowManager
import android.window.WindowContainerToken
import android.window.WindowContainerTransaction
import android.window.WindowContainerTransaction.Change.CHANGE_DRAG_RESIZING
@@ -18,13 +19,17 @@ import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayLayout
+import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_BOTTOM
import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT
import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP
import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_UNDEFINED
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito
@@ -34,6 +39,7 @@ import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.doReturn
import java.util.function.Supplier
import org.mockito.Mockito.`when` as whenever
@@ -50,6 +56,8 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
@Mock
private lateinit var mockShellTaskOrganizer: ShellTaskOrganizer
@Mock
+ private lateinit var mockTransitions: Transitions
+ @Mock
private lateinit var mockWindowDecoration: WindowDecoration<*>
@Mock
private lateinit var mockDragStartListener: DragPositioningCallbackUtility.DragStartListener
@@ -69,6 +77,8 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
private lateinit var mockTransactionFactory: Supplier<SurfaceControl.Transaction>
@Mock
private lateinit var mockTransaction: SurfaceControl.Transaction
+ @Mock
+ private lateinit var mockTransitionBinder: IBinder
private lateinit var taskPositioner: FluidResizeTaskPositioner
@@ -106,9 +116,12 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
`when`(mockWindowDecoration.calculateValidDragArea()).thenReturn(VALID_DRAG_AREA)
mockWindowDecoration.mDisplay = mockDisplay
whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
+ whenever(mockTransitions.startTransition(anyInt(), any(), any()))
+ .doReturn(mockTransitionBinder)
taskPositioner = FluidResizeTaskPositioner(
mockShellTaskOrganizer,
+ mockTransitions,
mockWindowDecoration,
mockDisplayController,
mockDragStartListener,
@@ -118,7 +131,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
}
@Test
- fun testDragResize_notMove_skipsTransactionOnEnd() {
+ fun testDragResize_notMove_skipsTransitionOnEnd() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_TOP or CTRL_TYPE_RIGHT,
STARTING_BOUNDS.left.toFloat(),
@@ -130,16 +143,16 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
STARTING_BOUNDS.top.toFloat() + 10
)
- verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+ verify(mockTransitions, never()).startTransition(
+ eq(WindowManager.TRANSIT_CHANGE), argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
token == taskBinder &&
((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)
- }
- })
+ }}, eq(taskPositioner))
}
@Test
- fun testDragResize_noEffectiveMove_skipsTransactionOnMoveAndEnd() {
+ fun testDragResize_noEffectiveMove_skipsTransitionOnMoveAndEnd() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_TOP or CTRL_TYPE_RIGHT,
STARTING_BOUNDS.left.toFloat(),
@@ -151,21 +164,28 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
STARTING_BOUNDS.top.toFloat()
)
+ verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)
+ }
+ })
+
taskPositioner.onDragPositioningEnd(
STARTING_BOUNDS.left.toFloat() + 10,
STARTING_BOUNDS.top.toFloat() + 10
)
- verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+ verify(mockTransitions, never()).startTransition(
+ eq(WindowManager.TRANSIT_CHANGE), argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
token == taskBinder &&
((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)
- }
- })
+ }}, eq(taskPositioner))
}
@Test
- fun testDragResize_hasEffectiveMove_issuesTransactionOnMoveAndEnd() {
+ fun testDragResize_hasEffectiveMove_issuesTransitionOnMoveAndEnd() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_TOP or CTRL_TYPE_RIGHT,
STARTING_BOUNDS.left.toFloat(),
@@ -192,13 +212,13 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
)
val rectAfterEnd = Rect(rectAfterMove)
rectAfterEnd.top += 10
- verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
- return@argThat wct.changes.any { (token, change) ->
- token == taskBinder &&
- (change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0 &&
- change.configuration.windowConfiguration.bounds == rectAfterEnd
- }
- })
+ verify(mockTransitions).startTransition(
+ eq(WindowManager.TRANSIT_CHANGE), argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ (change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0 &&
+ change.configuration.windowConfiguration.bounds == rectAfterEnd
+ }}, eq(taskPositioner))
}
@Test
@@ -226,6 +246,13 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
change.dragResizing
}
})
+ verify(mockTransitions, never()).startTransition(
+ eq(WindowManager.TRANSIT_CHANGE), argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.changeMask and CHANGE_DRAG_RESIZING) != 0) &&
+ change.dragResizing
+ }}, eq(taskPositioner))
}
@Test
@@ -253,13 +280,13 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
change.dragResizing
}
})
- verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ verify(mockTransitions).startTransition(
+ eq(WindowManager.TRANSIT_CHANGE), argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
token == taskBinder &&
((change.changeMask and CHANGE_DRAG_RESIZING) != 0) &&
!change.dragResizing
- }
- })
+ }}, eq(taskPositioner))
}
@Test
@@ -270,7 +297,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
STARTING_BOUNDS.top.toFloat()
)
- // Resize to width of 95px and height of 5px with min width of 10px
+ // Resize to width of 95px and height of 5px with min height of 10px
val newX = STARTING_BOUNDS.right.toFloat() - 5
val newY = STARTING_BOUNDS.top.toFloat() + 95
taskPositioner.onDragPositioningMove(
@@ -566,12 +593,12 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
taskPositioner.onDragPositioningEnd(newX, newY)
- verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+ verify(mockTransitions, never()).startTransition(
+ eq(WindowManager.TRANSIT_CHANGE), argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
token == taskBinder &&
((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)
- }
- })
+ }}, eq(taskPositioner))
}
private fun WindowContainerTransaction.Change.ofBounds(bounds: Rect): Boolean {
@@ -650,14 +677,14 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
)
// Verify task's top bound is set to stable bounds top since dragged outside stable bounds
// but not in disallowed end bounds area.
- verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ verify(mockTransitions).startTransition(
+ eq(WindowManager.TRANSIT_CHANGE), argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
token == taskBinder &&
(change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0 &&
change.configuration.windowConfiguration.bounds.top ==
STABLE_BOUNDS_LANDSCAPE.top
- }
- })
+ }}, eq(taskPositioner))
}
@Test
@@ -680,7 +707,8 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
newX,
newY
)
- verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ verify(mockTransitions).startTransition(
+ eq(WindowManager.TRANSIT_CHANGE), argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
token == taskBinder &&
(change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0 &&
@@ -688,8 +716,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
VALID_DRAG_AREA.bottom &&
change.configuration.windowConfiguration.bounds.left ==
VALID_DRAG_AREA.left
- }
- })
+ }}, eq(taskPositioner))
}
@Test
@@ -741,6 +768,59 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
verify(mockDisplayLayout, Mockito.times(2)).getStableBounds(any())
}
+ @Test
+ fun testIsResizingOrAnimatingResizeSet() {
+ assertFalse(taskPositioner.isResizingOrAnimating)
+
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_TOP or CTRL_TYPE_RIGHT,
+ STARTING_BOUNDS.left.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ taskPositioner.onDragPositioningMove(
+ STARTING_BOUNDS.left.toFloat() - 20,
+ STARTING_BOUNDS.top.toFloat() - 20
+ )
+
+ // isResizingOrAnimating should be set to true after move during a resize
+ assertTrue(taskPositioner.isResizingOrAnimating)
+
+ taskPositioner.onDragPositioningEnd(
+ STARTING_BOUNDS.left.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // isResizingOrAnimating should be not be set till false until after transition animation
+ assertTrue(taskPositioner.isResizingOrAnimating)
+ }
+
+ @Test
+ fun testIsResizingOrAnimatingResizeResetAfterAbortedTransition() {
+ performDrag(STARTING_BOUNDS.left.toFloat(),
+ STARTING_BOUNDS.top.toFloat(), STARTING_BOUNDS.left.toFloat() - 20,
+ STARTING_BOUNDS.top.toFloat() - 20, CTRL_TYPE_TOP or CTRL_TYPE_RIGHT)
+
+ taskPositioner.onTransitionConsumed(mockTransitionBinder, true /* aborted */,
+ mockTransaction)
+
+ // isResizingOrAnimating should be set to false until after transition successfully consumed
+ assertFalse(taskPositioner.isResizingOrAnimating)
+ }
+
+ @Test
+ fun testIsResizingOrAnimatingResizeResetAfterNonAbortedTransition() {
+ performDrag(STARTING_BOUNDS.left.toFloat(),
+ STARTING_BOUNDS.top.toFloat(), STARTING_BOUNDS.left.toFloat() - 20,
+ STARTING_BOUNDS.top.toFloat() - 20, CTRL_TYPE_TOP or CTRL_TYPE_RIGHT)
+
+ taskPositioner.onTransitionConsumed(mockTransitionBinder, false /* aborted */,
+ mockTransaction)
+
+ // isResizingOrAnimating should be set to false until after transition successfully consumed
+ assertFalse(taskPositioner.isResizingOrAnimating)
+ }
+
private fun performDrag(
startX: Float,
startY: Float,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
index a759b53f4238..08412101c30c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
@@ -26,6 +26,7 @@ import android.view.Surface.ROTATION_270
import android.view.Surface.ROTATION_90
import android.view.SurfaceControl
import android.view.WindowManager.TRANSIT_CHANGE
+import android.window.TransitionInfo
import android.window.WindowContainerToken
import androidx.test.filters.SmallTest
import com.android.wm.shell.ShellTaskOrganizer
@@ -33,10 +34,12 @@ import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayLayout
import com.android.wm.shell.transition.Transitions
+import com.android.wm.shell.transition.Transitions.TransitionFinishCallback
import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_BOTTOM
import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT
import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP
import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_UNDEFINED
+import junit.framework.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -85,6 +88,12 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
@Mock
private lateinit var mockTransaction: SurfaceControl.Transaction
@Mock
+ private lateinit var mockTransitionBinder: IBinder
+ @Mock
+ private lateinit var mockTransitionInfo: TransitionInfo
+ @Mock
+ private lateinit var mockFinishCallback: TransitionFinishCallback
+ @Mock
private lateinit var mockTransitions: Transitions
private lateinit var taskPositioner: VeiledResizeTaskPositioner
@@ -188,13 +197,12 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
verify(mockDesktopWindowDecoration, never()).createResizeVeil()
verify(mockDesktopWindowDecoration, never()).hideResizeVeil()
- verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ verify(mockTransitions).startTransition(eq(TRANSIT_CHANGE), argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
token == taskBinder &&
(change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0 &&
- change.configuration.windowConfiguration.bounds == rectAfterEnd
- }
- })
+ change.configuration.windowConfiguration.bounds == rectAfterEnd }},
+ eq(taskPositioner))
}
@Test
@@ -369,14 +377,13 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
)
// Verify task's top bound is set to stable bounds top since dragged outside stable bounds
// but not in disallowed end bounds area.
- verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ verify(mockTransitions).startTransition(eq(TRANSIT_CHANGE), argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
token == taskBinder &&
(change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0 &&
change.configuration.windowConfiguration.bounds.top ==
- STABLE_BOUNDS_LANDSCAPE.top
- }
- })
+ STABLE_BOUNDS_LANDSCAPE.top }},
+ eq(taskPositioner))
}
@Test
@@ -399,16 +406,15 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
newX,
newY
)
- verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ verify(mockTransitions).startTransition(eq(TRANSIT_CHANGE), argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
token == taskBinder &&
(change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0 &&
change.configuration.windowConfiguration.bounds.top ==
VALID_DRAG_AREA.bottom &&
change.configuration.windowConfiguration.bounds.left ==
- VALID_DRAG_AREA.left
- }
- })
+ VALID_DRAG_AREA.left }},
+ eq(taskPositioner))
}
@Test
@@ -456,6 +462,47 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
verify(mockDisplayLayout, times(2)).getStableBounds(any())
}
+ @Test
+ fun testIsResizingOrAnimatingResizeSet() {
+ Assert.assertFalse(taskPositioner.isResizingOrAnimating)
+
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_TOP or CTRL_TYPE_RIGHT,
+ STARTING_BOUNDS.left.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ taskPositioner.onDragPositioningMove(
+ STARTING_BOUNDS.left.toFloat() - 20,
+ STARTING_BOUNDS.top.toFloat() - 20
+ )
+
+ // isResizingOrAnimating should be set to true after move during a resize
+ Assert.assertTrue(taskPositioner.isResizingOrAnimating)
+
+ taskPositioner.onDragPositioningEnd(
+ STARTING_BOUNDS.left.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // isResizingOrAnimating should be not be set till false until after transition animation
+ Assert.assertTrue(taskPositioner.isResizingOrAnimating)
+ }
+
+ @Test
+ fun testIsResizingOrAnimatingResizeResetAfterStartAnimation() {
+ performDrag(
+ STARTING_BOUNDS.left.toFloat(), STARTING_BOUNDS.top.toFloat(),
+ STARTING_BOUNDS.left.toFloat() - 20, STARTING_BOUNDS.top.toFloat() - 20,
+ CTRL_TYPE_TOP or CTRL_TYPE_RIGHT)
+
+ taskPositioner.startAnimation(mockTransitionBinder, mockTransitionInfo, mockTransaction,
+ mockTransaction, mockFinishCallback)
+
+ // isResizingOrAnimating should be set to false until after transition successfully consumed
+ Assert.assertFalse(taskPositioner.isResizingOrAnimating)
+ }
+
private fun performDrag(
startX: Float,
startY: Float,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index fe508e23af33..32a91461e40f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -32,6 +32,7 @@ import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.argThat;
@@ -261,11 +262,6 @@ public class WindowDecorationTests extends ShellTestCase {
eq(new Rect(100, 300, 400, 364)));
}
- verify(mMockSurfaceControlFinishT)
- .setPosition(mMockTaskSurface, TASK_POSITION_IN_PARENT.x,
- TASK_POSITION_IN_PARENT.y);
- verify(mMockSurfaceControlFinishT)
- .setWindowCrop(mMockTaskSurface, 300, 100);
verify(mMockSurfaceControlStartT).setCornerRadius(mMockTaskSurface, CORNER_RADIUS);
verify(mMockSurfaceControlFinishT).setCornerRadius(mMockTaskSurface, CORNER_RADIUS);
verify(mMockSurfaceControlStartT)
@@ -642,6 +638,66 @@ public class WindowDecorationTests extends ShellTestCase {
eq(0) /* index */, eq(mandatorySystemGestures()));
}
+ @Test
+ public void testTaskPositionAndCropNotSetWhenFalse() {
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+
+ final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setBounds(TASK_BOUNDS)
+ .setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y)
+ .setVisible(true)
+ .setWindowingMode(WINDOWING_MODE_FREEFORM)
+ .build();
+ taskInfo.isFocused = true;
+ // Density is 2. Shadow radius is 10px. Caption height is 64px.
+ taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
+ final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
+
+
+ mRelayoutParams.mSetTaskPositionAndCrop = false;
+ windowDecor.relayout(taskInfo);
+
+ verify(mMockSurfaceControlStartT, never()).setWindowCrop(
+ eq(mMockTaskSurface), anyInt(), anyInt());
+ verify(mMockSurfaceControlFinishT, never()).setPosition(
+ eq(mMockTaskSurface), anyFloat(), anyFloat());
+ verify(mMockSurfaceControlFinishT, never()).setWindowCrop(
+ eq(mMockTaskSurface), anyInt(), anyInt());
+ }
+
+ @Test
+ public void testTaskPositionAndCropSetWhenSetTrue() {
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+
+ final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setBounds(TASK_BOUNDS)
+ .setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y)
+ .setVisible(true)
+ .setWindowingMode(WINDOWING_MODE_FREEFORM)
+ .build();
+ taskInfo.isFocused = true;
+ // Density is 2. Shadow radius is 10px. Caption height is 64px.
+ taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
+ final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
+
+ mRelayoutParams.mSetTaskPositionAndCrop = true;
+ windowDecor.relayout(taskInfo);
+
+ verify(mMockSurfaceControlStartT).setWindowCrop(
+ eq(mMockTaskSurface), anyInt(), anyInt());
+ verify(mMockSurfaceControlFinishT).setPosition(
+ eq(mMockTaskSurface), anyFloat(), anyFloat());
+ verify(mMockSurfaceControlFinishT).setWindowCrop(
+ eq(mMockTaskSurface), anyInt(), anyInt());
+ }
+
+
private TestWindowDecoration createWindowDecoration(ActivityManager.RunningTaskInfo taskInfo) {
return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer,
taskInfo, mMockTaskSurface, mWindowConfiguration,