If task dragged to outer disallowed area, position back under the area
If user drags task into the task positioner's mOuterDisallowedAreaForEndBounds there are two possible outcomes. If the motion's y position is less that the Inner disallowed area for end bound's height, transition to WINDOWING_MODE_FULLSCREEN. Else, move the task bounds under the outer area. Test: Drag freeform task into status bar area. Task should jump back when y is greater than 16dp and move to fullscreen otherwise + VeiledResizeTaskPositionerTest + FluidResizeTaskPositionerTest Bug: 280831213 Change-Id: I1259ec499e93602620dc78fbddd2edbbd8e7b622
This commit is contained in:
@@ -419,4 +419,8 @@
|
||||
<dimen name="freeform_resize_handle">15dp</dimen>
|
||||
|
||||
<dimen name="freeform_resize_corner">44dp</dimen>
|
||||
|
||||
<!-- The height of the area at the top of the screen where a freeform task will transition to
|
||||
fullscreen if dragged until the top bound of the task is within the area. -->
|
||||
<dimen name="desktop_mode_transition_area_height">16dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -100,6 +100,10 @@ class DesktopTasksController(
|
||||
}
|
||||
}
|
||||
|
||||
private val transitionAreaHeight
|
||||
get() = context.resources.getDimensionPixelSize(
|
||||
com.android.wm.shell.R.dimen.desktop_mode_transition_area_height)
|
||||
|
||||
init {
|
||||
desktopMode = DesktopModeImpl()
|
||||
if (DesktopModeStatus.isProto2Enabled()) {
|
||||
@@ -700,13 +704,12 @@ class DesktopTasksController(
|
||||
y: Float
|
||||
) {
|
||||
if (taskInfo.windowingMode == WINDOWING_MODE_FREEFORM) {
|
||||
val statusBarHeight = getStatusBarHeight(taskInfo)
|
||||
if (y <= statusBarHeight && visualIndicator == null) {
|
||||
if (y <= transitionAreaHeight && visualIndicator == null) {
|
||||
visualIndicator = DesktopModeVisualIndicator(syncQueue, taskInfo,
|
||||
displayController, context, taskSurface, shellTaskOrganizer,
|
||||
rootTaskDisplayAreaOrganizer)
|
||||
visualIndicator?.createFullscreenIndicatorWithAnimatedBounds()
|
||||
} else if (y > statusBarHeight && visualIndicator != null) {
|
||||
} else if (y > transitionAreaHeight && visualIndicator != null) {
|
||||
releaseVisualIndicator()
|
||||
}
|
||||
}
|
||||
@@ -726,8 +729,7 @@ class DesktopTasksController(
|
||||
y: Float,
|
||||
windowDecor: DesktopModeWindowDecoration
|
||||
) {
|
||||
val statusBarHeight = getStatusBarHeight(taskInfo)
|
||||
if (y <= statusBarHeight && taskInfo.windowingMode == WINDOWING_MODE_FREEFORM) {
|
||||
if (y <= transitionAreaHeight && taskInfo.windowingMode == WINDOWING_MODE_FREEFORM) {
|
||||
windowDecor.incrementRelayoutBlock()
|
||||
moveToFullscreenWithAnimation(taskInfo, position)
|
||||
}
|
||||
@@ -746,9 +748,9 @@ class DesktopTasksController(
|
||||
taskSurface: SurfaceControl,
|
||||
y: Float
|
||||
) {
|
||||
// If the motion event is above the status bar, return since we do not need to show the
|
||||
// visual indicator at this point.
|
||||
if (y < getStatusBarHeight(taskInfo)) {
|
||||
// If the motion event is above the status bar and the visual indicator is not yet visible,
|
||||
// return since we do not need to show the visual indicator at this point.
|
||||
if (y < getStatusBarHeight(taskInfo) && visualIndicator == null) {
|
||||
return
|
||||
}
|
||||
if (visualIndicator == null) {
|
||||
|
||||
@@ -193,7 +193,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
||||
|
||||
final DragPositioningCallback dragPositioningCallback =
|
||||
new FluidResizeTaskPositioner(mTaskOrganizer, windowDecoration, mDisplayController,
|
||||
null /* disallowedAreaForEndBounds */);
|
||||
0 /* disallowedAreaForEndBoundsHeight */);
|
||||
final CaptionTouchEventListener touchEventListener =
|
||||
new CaptionTouchEventListener(taskInfo, dragPositioningCallback);
|
||||
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
|
||||
|
||||
@@ -845,7 +845,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
|
||||
windowDecoration.createResizeVeil();
|
||||
|
||||
final DragPositioningCallback dragPositioningCallback = createDragPositioningCallback(
|
||||
windowDecoration, taskInfo);
|
||||
windowDecoration);
|
||||
final DesktopModeTouchEventListener touchEventListener =
|
||||
new DesktopModeTouchEventListener(taskInfo, dragPositioningCallback);
|
||||
|
||||
@@ -858,24 +858,17 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
|
||||
incrementEventReceiverTasks(taskInfo.displayId);
|
||||
}
|
||||
private DragPositioningCallback createDragPositioningCallback(
|
||||
@NonNull DesktopModeWindowDecoration windowDecoration,
|
||||
@NonNull RunningTaskInfo taskInfo) {
|
||||
final int screenWidth = mDisplayController.getDisplayLayout(taskInfo.displayId).width();
|
||||
final Rect disallowedAreaForEndBounds;
|
||||
if (DesktopModeStatus.isProto2Enabled()) {
|
||||
disallowedAreaForEndBounds = new Rect(0, 0, screenWidth,
|
||||
getStatusBarHeight(taskInfo.displayId));
|
||||
} else {
|
||||
disallowedAreaForEndBounds = null;
|
||||
}
|
||||
@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, disallowedAreaForEndBounds, mDragStartListener,
|
||||
mTransactionFactory);
|
||||
mDisplayController, mDragStartListener, mTransactionFactory,
|
||||
transitionAreaHeight);
|
||||
} else {
|
||||
return new VeiledResizeTaskPositioner(mTaskOrganizer, windowDecoration,
|
||||
mDisplayController, disallowedAreaForEndBounds, mDragStartListener,
|
||||
mTransitions);
|
||||
mDisplayController, mDragStartListener, mTransitions,
|
||||
transitionAreaHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,8 +83,6 @@ public class DragPositioningCallbackUtility {
|
||||
// Make sure the new resizing destination in any direction falls within the stable bounds.
|
||||
// If not, set the bounds back to the old location that was valid to avoid conflicts with
|
||||
// some regions such as the gesture area.
|
||||
displayController.getDisplayLayout(windowDecoration.mDisplay.getDisplayId())
|
||||
.getStableBounds(stableBounds);
|
||||
if ((ctrlType & CTRL_TYPE_LEFT) != 0) {
|
||||
final int candidateLeft = repositionTaskBounds.left + (int) delta.x;
|
||||
repositionTaskBounds.left = (candidateLeft > stableBounds.left)
|
||||
@@ -136,7 +134,7 @@ public class DragPositioningCallbackUtility {
|
||||
repositionTaskBounds.top);
|
||||
}
|
||||
|
||||
static void updateTaskBounds(Rect repositionTaskBounds, Rect taskBoundsAtDragStart,
|
||||
private static void updateTaskBounds(Rect repositionTaskBounds, Rect taskBoundsAtDragStart,
|
||||
PointF repositionStartPoint, float x, float y) {
|
||||
final float deltaX = x - repositionStartPoint.x;
|
||||
final float deltaY = y - repositionStartPoint.y;
|
||||
@@ -144,6 +142,23 @@ public class DragPositioningCallbackUtility {
|
||||
repositionTaskBounds.offset((int) deltaX, (int) deltaY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates repositionTaskBounds to the final bounds of the task after the drag is finished. If
|
||||
* the bounds are outside of the stable bounds, they are shifted to place task at the top of the
|
||||
* stable bounds.
|
||||
*/
|
||||
static void onDragEnd(Rect repositionTaskBounds, Rect taskBoundsAtDragStart, Rect stableBounds,
|
||||
PointF repositionStartPoint, float x, float y) {
|
||||
updateTaskBounds(repositionTaskBounds, taskBoundsAtDragStart, repositionStartPoint,
|
||||
x, y);
|
||||
|
||||
// If task is outside of stable bounds (in the status bar area), shift the task down.
|
||||
if (stableBounds.top > repositionTaskBounds.top) {
|
||||
final int yShift = stableBounds.top - repositionTaskBounds.top;
|
||||
repositionTaskBounds.offset(0, yShift);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a bounds change to a task.
|
||||
* @param windowDecoration decor of task we are changing bounds for
|
||||
|
||||
@@ -21,8 +21,6 @@ import android.graphics.Rect;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.WindowContainerTransaction;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
|
||||
@@ -42,28 +40,31 @@ class FluidResizeTaskPositioner implements DragPositioningCallback {
|
||||
private final Rect mTaskBoundsAtDragStart = new Rect();
|
||||
private final PointF mRepositionStartPoint = new PointF();
|
||||
private final Rect mRepositionTaskBounds = new Rect();
|
||||
// If a task move (not resize) finishes in this region, the positioner will not attempt to
|
||||
// If a task move (not resize) finishes with the positions y less than this value, do not
|
||||
// finalize the bounds there using WCT#setBounds
|
||||
private final Rect mDisallowedAreaForEndBounds;
|
||||
private final int mDisallowedAreaForEndBoundsHeight;
|
||||
private boolean mHasDragResized;
|
||||
private int mCtrlType;
|
||||
|
||||
FluidResizeTaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration,
|
||||
DisplayController displayController, @Nullable Rect disallowedAreaForEndBounds) {
|
||||
this(taskOrganizer, windowDecoration, displayController, disallowedAreaForEndBounds,
|
||||
dragStartListener -> {}, SurfaceControl.Transaction::new);
|
||||
DisplayController displayController, int disallowedAreaForEndBoundsHeight) {
|
||||
this(taskOrganizer, windowDecoration, displayController, dragStartListener -> {},
|
||||
SurfaceControl.Transaction::new, disallowedAreaForEndBoundsHeight);
|
||||
}
|
||||
|
||||
FluidResizeTaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration,
|
||||
DisplayController displayController, @Nullable Rect disallowedAreaForEndBounds,
|
||||
DisplayController displayController,
|
||||
DragPositioningCallbackUtility.DragStartListener dragStartListener,
|
||||
Supplier<SurfaceControl.Transaction> supplier) {
|
||||
Supplier<SurfaceControl.Transaction> supplier,
|
||||
int disallowedAreaForEndBoundsHeight) {
|
||||
mTaskOrganizer = taskOrganizer;
|
||||
mWindowDecoration = windowDecoration;
|
||||
mDisplayController = displayController;
|
||||
mDisallowedAreaForEndBounds = new Rect(disallowedAreaForEndBounds);
|
||||
mDragStartListener = dragStartListener;
|
||||
mTransactionSupplier = supplier;
|
||||
mDisallowedAreaForEndBoundsHeight = disallowedAreaForEndBoundsHeight;
|
||||
mDisplayController.getDisplayLayout(windowDecoration.mDisplay.getDisplayId())
|
||||
.getStableBounds(mStableBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -121,10 +122,10 @@ class FluidResizeTaskPositioner implements DragPositioningCallback {
|
||||
}
|
||||
mTaskOrganizer.applyTransaction(wct);
|
||||
} else if (mCtrlType == CTRL_TYPE_UNDEFINED
|
||||
&& !mDisallowedAreaForEndBounds.contains((int) x, (int) y)) {
|
||||
&& y > mDisallowedAreaForEndBoundsHeight) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
DragPositioningCallbackUtility.updateTaskBounds(mRepositionTaskBounds,
|
||||
mTaskBoundsAtDragStart, mRepositionStartPoint, x, y);
|
||||
DragPositioningCallbackUtility.onDragEnd(mRepositionTaskBounds,
|
||||
mTaskBoundsAtDragStart, mStableBounds, mRepositionStartPoint, x, y);
|
||||
wct.setBounds(mWindowDecoration.mTaskInfo.token, mRepositionTaskBounds);
|
||||
mTaskOrganizer.applyTransaction(wct);
|
||||
}
|
||||
|
||||
@@ -53,33 +53,35 @@ public class VeiledResizeTaskPositioner implements DragPositioningCallback,
|
||||
private final Rect mTaskBoundsAtDragStart = new Rect();
|
||||
private final PointF mRepositionStartPoint = new PointF();
|
||||
private final Rect mRepositionTaskBounds = new Rect();
|
||||
// If a task move (not resize) finishes in this region, the positioner will not attempt to
|
||||
// If a task move (not resize) finishes with the positions y less than this value, do not
|
||||
// finalize the bounds there using WCT#setBounds
|
||||
private final Rect mDisallowedAreaForEndBounds;
|
||||
private final int mDisallowedAreaForEndBoundsHeight;
|
||||
private final Supplier<SurfaceControl.Transaction> mTransactionSupplier;
|
||||
private int mCtrlType;
|
||||
|
||||
public VeiledResizeTaskPositioner(ShellTaskOrganizer taskOrganizer,
|
||||
DesktopModeWindowDecoration windowDecoration, DisplayController displayController,
|
||||
Rect disallowedAreaForEndBounds,
|
||||
DragPositioningCallbackUtility.DragStartListener dragStartListener,
|
||||
Transitions transitions) {
|
||||
this(taskOrganizer, windowDecoration, displayController, disallowedAreaForEndBounds,
|
||||
dragStartListener, SurfaceControl.Transaction::new, transitions);
|
||||
Transitions transitions,
|
||||
int disallowedAreaForEndBoundsHeight) {
|
||||
this(taskOrganizer, windowDecoration, displayController, dragStartListener,
|
||||
SurfaceControl.Transaction::new, transitions, disallowedAreaForEndBoundsHeight);
|
||||
}
|
||||
|
||||
public VeiledResizeTaskPositioner(ShellTaskOrganizer taskOrganizer,
|
||||
DesktopModeWindowDecoration windowDecoration, DisplayController displayController,
|
||||
Rect disallowedAreaForEndBounds,
|
||||
DragPositioningCallbackUtility.DragStartListener dragStartListener,
|
||||
Supplier<SurfaceControl.Transaction> supplier, Transitions transitions) {
|
||||
Supplier<SurfaceControl.Transaction> supplier, Transitions transitions,
|
||||
int disallowedAreaForEndBoundsHeight) {
|
||||
mTaskOrganizer = taskOrganizer;
|
||||
mDesktopWindowDecoration = windowDecoration;
|
||||
mDisplayController = displayController;
|
||||
mDragStartListener = dragStartListener;
|
||||
mDisallowedAreaForEndBounds = new Rect(disallowedAreaForEndBounds);
|
||||
mTransactionSupplier = supplier;
|
||||
mTransitions = transitions;
|
||||
mDisallowedAreaForEndBoundsHeight = disallowedAreaForEndBoundsHeight;
|
||||
mDisplayController.getDisplayLayout(windowDecoration.mDisplay.getDisplayId())
|
||||
.getStableBounds(mStableBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,8 +112,7 @@ public class VeiledResizeTaskPositioner implements DragPositioningCallback,
|
||||
} else if (mCtrlType == CTRL_TYPE_UNDEFINED) {
|
||||
final SurfaceControl.Transaction t = mTransactionSupplier.get();
|
||||
DragPositioningCallbackUtility.setPositionOnDrag(mDesktopWindowDecoration,
|
||||
mRepositionTaskBounds, mTaskBoundsAtDragStart, mRepositionStartPoint, t,
|
||||
x, y);
|
||||
mRepositionTaskBounds, mTaskBoundsAtDragStart, mRepositionStartPoint, t, x, y);
|
||||
t.apply();
|
||||
}
|
||||
}
|
||||
@@ -138,9 +139,9 @@ public class VeiledResizeTaskPositioner implements DragPositioningCallback,
|
||||
// won't be called.
|
||||
mDesktopWindowDecoration.hideResizeVeil();
|
||||
}
|
||||
} else if (!mDisallowedAreaForEndBounds.contains((int) x, (int) y)) {
|
||||
DragPositioningCallbackUtility.updateTaskBounds(mRepositionTaskBounds,
|
||||
mTaskBoundsAtDragStart, mRepositionStartPoint, x, y);
|
||||
} else if (y > mDisallowedAreaForEndBoundsHeight) {
|
||||
DragPositioningCallbackUtility.onDragEnd(mRepositionTaskBounds,
|
||||
mTaskBoundsAtDragStart, mStableBounds, mRepositionStartPoint, x, y);
|
||||
DragPositioningCallbackUtility.applyTaskBoundsChange(new WindowContainerTransaction(),
|
||||
mDesktopWindowDecoration, mRepositionTaskBounds, mTaskOrganizer);
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase {
|
||||
@Mock private DesktopModeWindowDecorViewModel.InputMonitorFactory mMockInputMonitorFactory;
|
||||
@Mock private Supplier<SurfaceControl.Transaction> mTransactionFactory;
|
||||
@Mock private SurfaceControl.Transaction mTransaction;
|
||||
@Mock private Display mDisplay;
|
||||
private final List<InputManager> mMockInputManagers = new ArrayList<>();
|
||||
|
||||
private DesktopModeWindowDecorViewModel mDesktopModeWindowDecorViewModel;
|
||||
@@ -126,6 +127,9 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase {
|
||||
final InputChannel[] inputChannels = InputChannel.openInputChannelPair(TAG);
|
||||
inputChannels[0].dispose();
|
||||
when(mInputMonitor.getInputChannel()).thenReturn(inputChannels[1]);
|
||||
|
||||
mDesktopModeWindowDecoration.mDisplay = mDisplay;
|
||||
doReturn(Display.DEFAULT_DISPLAY).when(mDisplay).getDisplayId();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_UNDEFI
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentMatchers.eq
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.any
|
||||
import org.mockito.Mockito.argThat
|
||||
@@ -71,16 +72,6 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
||||
taskPositioner =
|
||||
FluidResizeTaskPositioner(
|
||||
mockShellTaskOrganizer,
|
||||
mockWindowDecoration,
|
||||
mockDisplayController,
|
||||
DISALLOWED_AREA_FOR_END_BOUNDS,
|
||||
mockDragStartListener,
|
||||
mockTransactionFactory
|
||||
)
|
||||
|
||||
whenever(taskToken.asBinder()).thenReturn(taskBinder)
|
||||
whenever(mockDisplayController.getDisplayLayout(DISPLAY_ID)).thenReturn(mockDisplayLayout)
|
||||
whenever(mockDisplayLayout.densityDpi()).thenReturn(DENSITY_DPI)
|
||||
@@ -101,6 +92,15 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
|
||||
}
|
||||
mockWindowDecoration.mDisplay = mockDisplay
|
||||
whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
|
||||
|
||||
taskPositioner = FluidResizeTaskPositioner(
|
||||
mockShellTaskOrganizer,
|
||||
mockWindowDecoration,
|
||||
mockDisplayController,
|
||||
mockDragStartListener,
|
||||
mockTransactionFactory,
|
||||
DISALLOWED_AREA_FOR_END_BOUNDS_HEIGHT
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -544,7 +544,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
|
||||
)
|
||||
|
||||
val newX = STARTING_BOUNDS.right.toFloat() + 5
|
||||
val newY = STARTING_BOUNDS.top.toFloat() + 5
|
||||
val newY = DISALLOWED_AREA_FOR_END_BOUNDS_HEIGHT.toFloat() - 1
|
||||
taskPositioner.onDragPositioningMove(
|
||||
newX,
|
||||
newY
|
||||
@@ -614,6 +614,38 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
|
||||
})
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDragResize_drag_taskPositionedInStableBounds() {
|
||||
taskPositioner.onDragPositioningStart(
|
||||
CTRL_TYPE_UNDEFINED, // drag
|
||||
STARTING_BOUNDS.left.toFloat(),
|
||||
STARTING_BOUNDS.top.toFloat()
|
||||
)
|
||||
|
||||
val newX = STARTING_BOUNDS.left.toFloat()
|
||||
val newY = STABLE_BOUNDS.top.toFloat() - 5
|
||||
taskPositioner.onDragPositioningMove(
|
||||
newX,
|
||||
newY
|
||||
)
|
||||
verify(mockTransaction).setPosition(any(), eq(newX), eq(newY))
|
||||
|
||||
taskPositioner.onDragPositioningEnd(
|
||||
newX,
|
||||
newY
|
||||
)
|
||||
// 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 ->
|
||||
return@argThat wct.changes.any { (token, change) ->
|
||||
token == taskBinder &&
|
||||
(change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0 &&
|
||||
change.configuration.windowConfiguration.bounds.top ==
|
||||
STABLE_BOUNDS.top
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TASK_ID = 5
|
||||
private const val MIN_WIDTH = 10
|
||||
@@ -622,10 +654,11 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
|
||||
private const val DEFAULT_MIN = 40
|
||||
private const val DISPLAY_ID = 1
|
||||
private const val NAVBAR_HEIGHT = 50
|
||||
private const val CAPTION_HEIGHT = 50
|
||||
private const val DISALLOWED_AREA_FOR_END_BOUNDS_HEIGHT = 10
|
||||
private val DISPLAY_BOUNDS = Rect(0, 0, 2400, 1600)
|
||||
private val STARTING_BOUNDS = Rect(0, 0, 100, 100)
|
||||
private val STARTING_BOUNDS = Rect(100, 100, 200, 200)
|
||||
private val STABLE_INSETS = Rect(0, 50, 0, 0)
|
||||
private val DISALLOWED_AREA_FOR_END_BOUNDS = Rect(0, 0, 300, 300)
|
||||
private val DISALLOWED_RESIZE_AREA = Rect(
|
||||
DISPLAY_BOUNDS.left,
|
||||
DISPLAY_BOUNDS.bottom - NAVBAR_HEIGHT,
|
||||
@@ -633,7 +666,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
|
||||
DISPLAY_BOUNDS.bottom)
|
||||
private val STABLE_BOUNDS = Rect(
|
||||
DISPLAY_BOUNDS.left,
|
||||
DISPLAY_BOUNDS.top,
|
||||
DISPLAY_BOUNDS.top + CAPTION_HEIGHT,
|
||||
DISPLAY_BOUNDS.right,
|
||||
DISPLAY_BOUNDS.bottom - NAVBAR_HEIGHT
|
||||
)
|
||||
|
||||
@@ -89,17 +89,6 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
||||
taskPositioner =
|
||||
VeiledResizeTaskPositioner(
|
||||
mockShellTaskOrganizer,
|
||||
mockDesktopWindowDecoration,
|
||||
mockDisplayController,
|
||||
DISALLOWED_AREA_FOR_END_BOUNDS,
|
||||
mockDragStartListener,
|
||||
mockTransactionFactory,
|
||||
mockTransitions
|
||||
)
|
||||
|
||||
whenever(taskToken.asBinder()).thenReturn(taskBinder)
|
||||
whenever(mockDisplayController.getDisplayLayout(DISPLAY_ID)).thenReturn(mockDisplayLayout)
|
||||
whenever(mockDisplayLayout.densityDpi()).thenReturn(DENSITY_DPI)
|
||||
@@ -119,6 +108,17 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
|
||||
}
|
||||
mockDesktopWindowDecoration.mDisplay = mockDisplay
|
||||
whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
|
||||
|
||||
taskPositioner =
|
||||
VeiledResizeTaskPositioner(
|
||||
mockShellTaskOrganizer,
|
||||
mockDesktopWindowDecoration,
|
||||
mockDisplayController,
|
||||
mockDragStartListener,
|
||||
mockTransactionFactory,
|
||||
mockTransitions,
|
||||
DISALLOWED_AREA_FOR_END_BOUNDS_HEIGHT
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -269,7 +269,7 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
|
||||
)
|
||||
|
||||
val newX = STARTING_BOUNDS.left.toFloat() + 5
|
||||
val newY = STARTING_BOUNDS.top.toFloat() + 5
|
||||
val newY = DISALLOWED_AREA_FOR_END_BOUNDS_HEIGHT.toFloat() - 1
|
||||
taskPositioner.onDragPositioningMove(
|
||||
newX,
|
||||
newY
|
||||
@@ -334,6 +334,38 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
|
||||
})
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDragResize_drag_taskPositionedInStableBounds() {
|
||||
taskPositioner.onDragPositioningStart(
|
||||
CTRL_TYPE_UNDEFINED, // drag
|
||||
STARTING_BOUNDS.left.toFloat(),
|
||||
STARTING_BOUNDS.top.toFloat()
|
||||
)
|
||||
|
||||
val newX = STARTING_BOUNDS.left.toFloat()
|
||||
val newY = STABLE_BOUNDS.top.toFloat() - 5
|
||||
taskPositioner.onDragPositioningMove(
|
||||
newX,
|
||||
newY
|
||||
)
|
||||
verify(mockTransaction).setPosition(any(), eq(newX), eq(newY))
|
||||
|
||||
taskPositioner.onDragPositioningEnd(
|
||||
newX,
|
||||
newY
|
||||
)
|
||||
// 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 ->
|
||||
return@argThat wct.changes.any { (token, change) ->
|
||||
token == taskBinder &&
|
||||
(change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0 &&
|
||||
change.configuration.windowConfiguration.bounds.top ==
|
||||
STABLE_BOUNDS.top
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TASK_ID = 5
|
||||
private const val MIN_WIDTH = 10
|
||||
@@ -342,12 +374,13 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
|
||||
private const val DEFAULT_MIN = 40
|
||||
private const val DISPLAY_ID = 1
|
||||
private const val NAVBAR_HEIGHT = 50
|
||||
private const val CAPTION_HEIGHT = 50
|
||||
private const val DISALLOWED_AREA_FOR_END_BOUNDS_HEIGHT = 10
|
||||
private val DISPLAY_BOUNDS = Rect(0, 0, 2400, 1600)
|
||||
private val STARTING_BOUNDS = Rect(0, 0, 100, 100)
|
||||
private val DISALLOWED_AREA_FOR_END_BOUNDS = Rect(0, 0, 50, 50)
|
||||
private val STARTING_BOUNDS = Rect(100, 100, 200, 200)
|
||||
private val STABLE_BOUNDS = Rect(
|
||||
DISPLAY_BOUNDS.left,
|
||||
DISPLAY_BOUNDS.top,
|
||||
DISPLAY_BOUNDS.top + CAPTION_HEIGHT,
|
||||
DISPLAY_BOUNDS.right,
|
||||
DISPLAY_BOUNDS.bottom - NAVBAR_HEIGHT
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user