Loading core/java/com/android/internal/policy/TaskResizingAlgorithm.java 0 → 100644 +179 −0 Original line number Diff line number Diff line /* * 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.internal.policy; import android.annotation.IntDef; import android.graphics.Point; import android.graphics.Rect; import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Given a move coordinate (x, y), the original taks bounds and relevant details, calculate the new * bounds. * * @hide */ public class TaskResizingAlgorithm { @IntDef(flag = true, value = { CTRL_NONE, CTRL_LEFT, CTRL_RIGHT, CTRL_TOP, CTRL_BOTTOM }) @Retention(RetentionPolicy.SOURCE) public @interface CtrlType {} public static final int CTRL_NONE = 0x0; public static final int CTRL_LEFT = 0x1; public static final int CTRL_RIGHT = 0x2; public static final int CTRL_TOP = 0x4; public static final int CTRL_BOTTOM = 0x8; // The minimal aspect ratio which needs to be met to count as landscape (or 1/.. for portrait). // Note: We do not use the 1.33 from the CDD here since the user is allowed to use what ever // aspect he desires. @VisibleForTesting public static final float MIN_ASPECT = 1.2f; /** * Given a (x, y) point and its original starting down point and its original bounds, calculate * and return a new resized bound. * @param x the new moved X point. * @param y the new moved Y point. * @param startDragX the original starting X point. * @param startDragY the original starting Y point. * @param originalBounds the original bound before resize. * @param ctrlType The type of resize operation. * @param minVisibleWidth The minimal width required for the new size. * @param minVisibleHeight The minimal height required for the new size. * @param maxVisibleSize The maximum size allowed. * @param preserveOrientation * @param startOrientationWasLandscape * @return */ public static Rect resizeDrag(float x, float y, float startDragX, float startDragY, Rect originalBounds, int ctrlType, int minVisibleWidth, int minVisibleHeight, Point maxVisibleSize, boolean preserveOrientation, boolean startOrientationWasLandscape) { // This is a resizing operation. // We need to keep various constraints: // 1. mMinVisible[Width/Height] <= [width/height] <= mMaxVisibleSize.[x/y] // 2. The orientation is kept - if required. final int deltaX = Math.round(x - startDragX); final int deltaY = Math.round(y - startDragY); int left = originalBounds.left; int top = originalBounds.top; int right = originalBounds.right; int bottom = originalBounds.bottom; // Calculate the resulting width and height of the drag operation. int width = right - left; int height = bottom - top; if ((ctrlType & CTRL_LEFT) != 0) { width = Math.max(minVisibleWidth, width - deltaX); } else if ((ctrlType & CTRL_RIGHT) != 0) { width = Math.max(minVisibleWidth, width + deltaX); } if ((ctrlType & CTRL_TOP) != 0) { height = Math.max(minVisibleHeight, height - deltaY); } else if ((ctrlType & CTRL_BOTTOM) != 0) { height = Math.max(minVisibleHeight, height + deltaY); } // If we have to preserve the orientation - check that we are doing so. final float aspect = (float) width / (float) height; if (preserveOrientation && ((startOrientationWasLandscape && aspect < MIN_ASPECT) || (!startOrientationWasLandscape && aspect > (1.0 / MIN_ASPECT)))) { // Calculate 2 rectangles fulfilling all requirements for either X or Y being the major // drag axis. What ever is producing the bigger rectangle will be chosen. int width1; int width2; int height1; int height2; if (startOrientationWasLandscape) { // Assuming that the width is our target we calculate the height. width1 = Math.max(minVisibleWidth, Math.min(maxVisibleSize.x, width)); height1 = Math.min(height, Math.round((float) width1 / MIN_ASPECT)); if (height1 < minVisibleHeight) { // If the resulting height is too small we adjust to the minimal size. height1 = minVisibleHeight; width1 = Math.max(minVisibleWidth, Math.min(maxVisibleSize.x, Math.round((float) height1 * MIN_ASPECT))); } // Assuming that the height is our target we calculate the width. height2 = Math.max(minVisibleHeight, Math.min(maxVisibleSize.y, height)); width2 = Math.max(width, Math.round((float) height2 * MIN_ASPECT)); if (width2 < minVisibleWidth) { // If the resulting width is too small we adjust to the minimal size. width2 = minVisibleWidth; height2 = Math.max(minVisibleHeight, Math.min(maxVisibleSize.y, Math.round((float) width2 / MIN_ASPECT))); } } else { // Assuming that the width is our target we calculate the height. width1 = Math.max(minVisibleWidth, Math.min(maxVisibleSize.x, width)); height1 = Math.max(height, Math.round((float) width1 * MIN_ASPECT)); if (height1 < minVisibleHeight) { // If the resulting height is too small we adjust to the minimal size. height1 = minVisibleHeight; width1 = Math.max(minVisibleWidth, Math.min(maxVisibleSize.x, Math.round((float) height1 / MIN_ASPECT))); } // Assuming that the height is our target we calculate the width. height2 = Math.max(minVisibleHeight, Math.min(maxVisibleSize.y, height)); width2 = Math.min(width, Math.round((float) height2 / MIN_ASPECT)); if (width2 < minVisibleWidth) { // If the resulting width is too small we adjust to the minimal size. width2 = minVisibleWidth; height2 = Math.max(minVisibleHeight, Math.min(maxVisibleSize.y, Math.round((float) width2 * MIN_ASPECT))); } } // Use the bigger of the two rectangles if the major change was positive, otherwise // do the opposite. final boolean grows = width > (right - left) || height > (bottom - top); if (grows == (width1 * height1 > width2 * height2)) { width = width1; height = height1; } else { width = width2; height = height2; } } // Generate the final bounds by keeping the opposite drag edge constant. if ((ctrlType & CTRL_LEFT) != 0) { left = right - width; } else { // Note: The right might have changed - if we pulled at the right or not. right = left + width; } if ((ctrlType & CTRL_TOP) != 0) { top = bottom - height; } else { // Note: The height might have changed - if we pulled at the bottom or not. bottom = top + height; } return new Rect(left, top, right, bottom); } } services/core/java/com/android/server/wm/TaskPositioner.java +12 −141 Original line number Diff line number Diff line Loading @@ -20,6 +20,11 @@ import static android.app.ActivityTaskManager.RESIZE_MODE_USER; import static android.app.ActivityTaskManager.RESIZE_MODE_USER_FORCED; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_BOTTOM; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_LEFT; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_NONE; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_RIGHT; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_TOP; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; Loading @@ -29,7 +34,6 @@ import static com.android.server.wm.WindowManagerService.dipToPixel; import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP; import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP; import android.annotation.IntDef; import android.annotation.NonNull; import android.app.IActivityTaskManager; import android.graphics.Point; Loading @@ -55,11 +59,10 @@ import android.view.SurfaceControl; import android.view.WindowManager; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.TaskResizingAlgorithm; import com.android.internal.policy.TaskResizingAlgorithm.CtrlType; import com.android.server.protolog.common.ProtoLog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; class TaskPositioner implements IBinder.DeathRecipient { private static final boolean DEBUG_ORIENTATION_VIOLATIONS = false; private static final String TAG_LOCAL = "TaskPositioner"; Loading @@ -67,33 +70,10 @@ class TaskPositioner implements IBinder.DeathRecipient { private static Factory sFactory; @IntDef(flag = true, value = { CTRL_NONE, CTRL_LEFT, CTRL_RIGHT, CTRL_TOP, CTRL_BOTTOM }) @Retention(RetentionPolicy.SOURCE) @interface CtrlType {} private static final int CTRL_NONE = 0x0; private static final int CTRL_LEFT = 0x1; private static final int CTRL_RIGHT = 0x2; private static final int CTRL_TOP = 0x4; private static final int CTRL_BOTTOM = 0x8; public static final float RESIZING_HINT_ALPHA = 0.5f; public static final int RESIZING_HINT_DURATION_MS = 0; // The minimal aspect ratio which needs to be met to count as landscape (or 1/.. for portrait). // Note: We do not use the 1.33 from the CDD here since the user is allowed to use what ever // aspect he desires. @VisibleForTesting static final float MIN_ASPECT = 1.2f; private final WindowManagerService mService; private final IActivityTaskManager mActivityManager; private WindowPositionerEventReceiver mInputEventReceiver; Loading Loading @@ -477,122 +457,13 @@ class TaskPositioner implements IBinder.DeathRecipient { */ @VisibleForTesting void resizeDrag(float x, float y) { // This is a resizing operation. // We need to keep various constraints: // 1. mMinVisible[Width/Height] <= [width/height] <= mMaxVisibleSize.[x/y] // 2. The orientation is kept - if required. final int deltaX = Math.round(x - mStartDragX); final int deltaY = Math.round(y - mStartDragY); int left = mWindowOriginalBounds.left; int top = mWindowOriginalBounds.top; int right = mWindowOriginalBounds.right; int bottom = mWindowOriginalBounds.bottom; // Calculate the resulting width and height of the drag operation. int width = right - left; int height = bottom - top; if ((mCtrlType & CTRL_LEFT) != 0) { width = Math.max(mMinVisibleWidth, width - deltaX); } else if ((mCtrlType & CTRL_RIGHT) != 0) { width = Math.max(mMinVisibleWidth, width + deltaX); } if ((mCtrlType & CTRL_TOP) != 0) { height = Math.max(mMinVisibleHeight, height - deltaY); } else if ((mCtrlType & CTRL_BOTTOM) != 0) { height = Math.max(mMinVisibleHeight, height + deltaY); } // If we have to preserve the orientation - check that we are doing so. final float aspect = (float) width / (float) height; if (mPreserveOrientation && ((mStartOrientationWasLandscape && aspect < MIN_ASPECT) || (!mStartOrientationWasLandscape && aspect > (1.0 / MIN_ASPECT)))) { // Calculate 2 rectangles fulfilling all requirements for either X or Y being the major // drag axis. What ever is producing the bigger rectangle will be chosen. int width1; int width2; int height1; int height2; if (mStartOrientationWasLandscape) { // Assuming that the width is our target we calculate the height. width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, width)); height1 = Math.min(height, Math.round((float)width1 / MIN_ASPECT)); if (height1 < mMinVisibleHeight) { // If the resulting height is too small we adjust to the minimal size. height1 = mMinVisibleHeight; width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, Math.round((float)height1 * MIN_ASPECT))); } // Assuming that the height is our target we calculate the width. height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, height)); width2 = Math.max(width, Math.round((float)height2 * MIN_ASPECT)); if (width2 < mMinVisibleWidth) { // If the resulting width is too small we adjust to the minimal size. width2 = mMinVisibleWidth; height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, Math.round((float)width2 / MIN_ASPECT))); } } else { // Assuming that the width is our target we calculate the height. width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, width)); height1 = Math.max(height, Math.round((float)width1 * MIN_ASPECT)); if (height1 < mMinVisibleHeight) { // If the resulting height is too small we adjust to the minimal size. height1 = mMinVisibleHeight; width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, Math.round((float)height1 / MIN_ASPECT))); } // Assuming that the height is our target we calculate the width. height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, height)); width2 = Math.min(width, Math.round((float)height2 / MIN_ASPECT)); if (width2 < mMinVisibleWidth) { // If the resulting width is too small we adjust to the minimal size. width2 = mMinVisibleWidth; height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, Math.round((float)width2 * MIN_ASPECT))); } } // Use the bigger of the two rectangles if the major change was positive, otherwise // do the opposite. final boolean grows = width > (right - left) || height > (bottom - top); if (grows == (width1 * height1 > width2 * height2)) { width = width1; height = height1; } else { width = width2; height = height2; } } // Update mWindowDragBounds to the new drag size. updateDraggedBounds(left, top, right, bottom, width, height); } /** * Given the old coordinates and the new width and height, update the mWindowDragBounds. * * @param left The original left bound before the user started dragging. * @param top The original top bound before the user started dragging. * @param right The original right bound before the user started dragging. * @param bottom The original bottom bound before the user started dragging. * @param newWidth The new dragged width. * @param newHeight The new dragged height. */ void updateDraggedBounds(int left, int top, int right, int bottom, int newWidth, int newHeight) { // Generate the final bounds by keeping the opposite drag edge constant. if ((mCtrlType & CTRL_LEFT) != 0) { left = right - newWidth; } else { // Note: The right might have changed - if we pulled at the right or not. right = left + newWidth; } if ((mCtrlType & CTRL_TOP) != 0) { top = bottom - newHeight; } else { // Note: The height might have changed - if we pulled at the bottom or not. bottom = top + newHeight; updateDraggedBounds(TaskResizingAlgorithm.resizeDrag(x, y, mStartDragX, mStartDragY, mWindowOriginalBounds, mCtrlType, mMinVisibleWidth, mMinVisibleHeight, mMaxVisibleSize, mPreserveOrientation, mStartOrientationWasLandscape)); } mWindowDragBounds.set(left, top, right, bottom); private void updateDraggedBounds(Rect newBounds) { mWindowDragBounds.set(newBounds); checkBoundsForOrientationViolations(mWindowDragBounds); } Loading services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java +1 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.TaskPositioner.MIN_ASPECT; import static com.android.internal.policy.TaskResizingAlgorithm.MIN_ASPECT; import static com.android.server.wm.WindowManagerService.dipToPixel; import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP; import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP; Loading Loading
core/java/com/android/internal/policy/TaskResizingAlgorithm.java 0 → 100644 +179 −0 Original line number Diff line number Diff line /* * 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.internal.policy; import android.annotation.IntDef; import android.graphics.Point; import android.graphics.Rect; import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Given a move coordinate (x, y), the original taks bounds and relevant details, calculate the new * bounds. * * @hide */ public class TaskResizingAlgorithm { @IntDef(flag = true, value = { CTRL_NONE, CTRL_LEFT, CTRL_RIGHT, CTRL_TOP, CTRL_BOTTOM }) @Retention(RetentionPolicy.SOURCE) public @interface CtrlType {} public static final int CTRL_NONE = 0x0; public static final int CTRL_LEFT = 0x1; public static final int CTRL_RIGHT = 0x2; public static final int CTRL_TOP = 0x4; public static final int CTRL_BOTTOM = 0x8; // The minimal aspect ratio which needs to be met to count as landscape (or 1/.. for portrait). // Note: We do not use the 1.33 from the CDD here since the user is allowed to use what ever // aspect he desires. @VisibleForTesting public static final float MIN_ASPECT = 1.2f; /** * Given a (x, y) point and its original starting down point and its original bounds, calculate * and return a new resized bound. * @param x the new moved X point. * @param y the new moved Y point. * @param startDragX the original starting X point. * @param startDragY the original starting Y point. * @param originalBounds the original bound before resize. * @param ctrlType The type of resize operation. * @param minVisibleWidth The minimal width required for the new size. * @param minVisibleHeight The minimal height required for the new size. * @param maxVisibleSize The maximum size allowed. * @param preserveOrientation * @param startOrientationWasLandscape * @return */ public static Rect resizeDrag(float x, float y, float startDragX, float startDragY, Rect originalBounds, int ctrlType, int minVisibleWidth, int minVisibleHeight, Point maxVisibleSize, boolean preserveOrientation, boolean startOrientationWasLandscape) { // This is a resizing operation. // We need to keep various constraints: // 1. mMinVisible[Width/Height] <= [width/height] <= mMaxVisibleSize.[x/y] // 2. The orientation is kept - if required. final int deltaX = Math.round(x - startDragX); final int deltaY = Math.round(y - startDragY); int left = originalBounds.left; int top = originalBounds.top; int right = originalBounds.right; int bottom = originalBounds.bottom; // Calculate the resulting width and height of the drag operation. int width = right - left; int height = bottom - top; if ((ctrlType & CTRL_LEFT) != 0) { width = Math.max(minVisibleWidth, width - deltaX); } else if ((ctrlType & CTRL_RIGHT) != 0) { width = Math.max(minVisibleWidth, width + deltaX); } if ((ctrlType & CTRL_TOP) != 0) { height = Math.max(minVisibleHeight, height - deltaY); } else if ((ctrlType & CTRL_BOTTOM) != 0) { height = Math.max(minVisibleHeight, height + deltaY); } // If we have to preserve the orientation - check that we are doing so. final float aspect = (float) width / (float) height; if (preserveOrientation && ((startOrientationWasLandscape && aspect < MIN_ASPECT) || (!startOrientationWasLandscape && aspect > (1.0 / MIN_ASPECT)))) { // Calculate 2 rectangles fulfilling all requirements for either X or Y being the major // drag axis. What ever is producing the bigger rectangle will be chosen. int width1; int width2; int height1; int height2; if (startOrientationWasLandscape) { // Assuming that the width is our target we calculate the height. width1 = Math.max(minVisibleWidth, Math.min(maxVisibleSize.x, width)); height1 = Math.min(height, Math.round((float) width1 / MIN_ASPECT)); if (height1 < minVisibleHeight) { // If the resulting height is too small we adjust to the minimal size. height1 = minVisibleHeight; width1 = Math.max(minVisibleWidth, Math.min(maxVisibleSize.x, Math.round((float) height1 * MIN_ASPECT))); } // Assuming that the height is our target we calculate the width. height2 = Math.max(minVisibleHeight, Math.min(maxVisibleSize.y, height)); width2 = Math.max(width, Math.round((float) height2 * MIN_ASPECT)); if (width2 < minVisibleWidth) { // If the resulting width is too small we adjust to the minimal size. width2 = minVisibleWidth; height2 = Math.max(minVisibleHeight, Math.min(maxVisibleSize.y, Math.round((float) width2 / MIN_ASPECT))); } } else { // Assuming that the width is our target we calculate the height. width1 = Math.max(minVisibleWidth, Math.min(maxVisibleSize.x, width)); height1 = Math.max(height, Math.round((float) width1 * MIN_ASPECT)); if (height1 < minVisibleHeight) { // If the resulting height is too small we adjust to the minimal size. height1 = minVisibleHeight; width1 = Math.max(minVisibleWidth, Math.min(maxVisibleSize.x, Math.round((float) height1 / MIN_ASPECT))); } // Assuming that the height is our target we calculate the width. height2 = Math.max(minVisibleHeight, Math.min(maxVisibleSize.y, height)); width2 = Math.min(width, Math.round((float) height2 / MIN_ASPECT)); if (width2 < minVisibleWidth) { // If the resulting width is too small we adjust to the minimal size. width2 = minVisibleWidth; height2 = Math.max(minVisibleHeight, Math.min(maxVisibleSize.y, Math.round((float) width2 * MIN_ASPECT))); } } // Use the bigger of the two rectangles if the major change was positive, otherwise // do the opposite. final boolean grows = width > (right - left) || height > (bottom - top); if (grows == (width1 * height1 > width2 * height2)) { width = width1; height = height1; } else { width = width2; height = height2; } } // Generate the final bounds by keeping the opposite drag edge constant. if ((ctrlType & CTRL_LEFT) != 0) { left = right - width; } else { // Note: The right might have changed - if we pulled at the right or not. right = left + width; } if ((ctrlType & CTRL_TOP) != 0) { top = bottom - height; } else { // Note: The height might have changed - if we pulled at the bottom or not. bottom = top + height; } return new Rect(left, top, right, bottom); } }
services/core/java/com/android/server/wm/TaskPositioner.java +12 −141 Original line number Diff line number Diff line Loading @@ -20,6 +20,11 @@ import static android.app.ActivityTaskManager.RESIZE_MODE_USER; import static android.app.ActivityTaskManager.RESIZE_MODE_USER_FORCED; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_BOTTOM; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_LEFT; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_NONE; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_RIGHT; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_TOP; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; Loading @@ -29,7 +34,6 @@ import static com.android.server.wm.WindowManagerService.dipToPixel; import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP; import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP; import android.annotation.IntDef; import android.annotation.NonNull; import android.app.IActivityTaskManager; import android.graphics.Point; Loading @@ -55,11 +59,10 @@ import android.view.SurfaceControl; import android.view.WindowManager; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.TaskResizingAlgorithm; import com.android.internal.policy.TaskResizingAlgorithm.CtrlType; import com.android.server.protolog.common.ProtoLog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; class TaskPositioner implements IBinder.DeathRecipient { private static final boolean DEBUG_ORIENTATION_VIOLATIONS = false; private static final String TAG_LOCAL = "TaskPositioner"; Loading @@ -67,33 +70,10 @@ class TaskPositioner implements IBinder.DeathRecipient { private static Factory sFactory; @IntDef(flag = true, value = { CTRL_NONE, CTRL_LEFT, CTRL_RIGHT, CTRL_TOP, CTRL_BOTTOM }) @Retention(RetentionPolicy.SOURCE) @interface CtrlType {} private static final int CTRL_NONE = 0x0; private static final int CTRL_LEFT = 0x1; private static final int CTRL_RIGHT = 0x2; private static final int CTRL_TOP = 0x4; private static final int CTRL_BOTTOM = 0x8; public static final float RESIZING_HINT_ALPHA = 0.5f; public static final int RESIZING_HINT_DURATION_MS = 0; // The minimal aspect ratio which needs to be met to count as landscape (or 1/.. for portrait). // Note: We do not use the 1.33 from the CDD here since the user is allowed to use what ever // aspect he desires. @VisibleForTesting static final float MIN_ASPECT = 1.2f; private final WindowManagerService mService; private final IActivityTaskManager mActivityManager; private WindowPositionerEventReceiver mInputEventReceiver; Loading Loading @@ -477,122 +457,13 @@ class TaskPositioner implements IBinder.DeathRecipient { */ @VisibleForTesting void resizeDrag(float x, float y) { // This is a resizing operation. // We need to keep various constraints: // 1. mMinVisible[Width/Height] <= [width/height] <= mMaxVisibleSize.[x/y] // 2. The orientation is kept - if required. final int deltaX = Math.round(x - mStartDragX); final int deltaY = Math.round(y - mStartDragY); int left = mWindowOriginalBounds.left; int top = mWindowOriginalBounds.top; int right = mWindowOriginalBounds.right; int bottom = mWindowOriginalBounds.bottom; // Calculate the resulting width and height of the drag operation. int width = right - left; int height = bottom - top; if ((mCtrlType & CTRL_LEFT) != 0) { width = Math.max(mMinVisibleWidth, width - deltaX); } else if ((mCtrlType & CTRL_RIGHT) != 0) { width = Math.max(mMinVisibleWidth, width + deltaX); } if ((mCtrlType & CTRL_TOP) != 0) { height = Math.max(mMinVisibleHeight, height - deltaY); } else if ((mCtrlType & CTRL_BOTTOM) != 0) { height = Math.max(mMinVisibleHeight, height + deltaY); } // If we have to preserve the orientation - check that we are doing so. final float aspect = (float) width / (float) height; if (mPreserveOrientation && ((mStartOrientationWasLandscape && aspect < MIN_ASPECT) || (!mStartOrientationWasLandscape && aspect > (1.0 / MIN_ASPECT)))) { // Calculate 2 rectangles fulfilling all requirements for either X or Y being the major // drag axis. What ever is producing the bigger rectangle will be chosen. int width1; int width2; int height1; int height2; if (mStartOrientationWasLandscape) { // Assuming that the width is our target we calculate the height. width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, width)); height1 = Math.min(height, Math.round((float)width1 / MIN_ASPECT)); if (height1 < mMinVisibleHeight) { // If the resulting height is too small we adjust to the minimal size. height1 = mMinVisibleHeight; width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, Math.round((float)height1 * MIN_ASPECT))); } // Assuming that the height is our target we calculate the width. height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, height)); width2 = Math.max(width, Math.round((float)height2 * MIN_ASPECT)); if (width2 < mMinVisibleWidth) { // If the resulting width is too small we adjust to the minimal size. width2 = mMinVisibleWidth; height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, Math.round((float)width2 / MIN_ASPECT))); } } else { // Assuming that the width is our target we calculate the height. width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, width)); height1 = Math.max(height, Math.round((float)width1 * MIN_ASPECT)); if (height1 < mMinVisibleHeight) { // If the resulting height is too small we adjust to the minimal size. height1 = mMinVisibleHeight; width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, Math.round((float)height1 / MIN_ASPECT))); } // Assuming that the height is our target we calculate the width. height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, height)); width2 = Math.min(width, Math.round((float)height2 / MIN_ASPECT)); if (width2 < mMinVisibleWidth) { // If the resulting width is too small we adjust to the minimal size. width2 = mMinVisibleWidth; height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, Math.round((float)width2 * MIN_ASPECT))); } } // Use the bigger of the two rectangles if the major change was positive, otherwise // do the opposite. final boolean grows = width > (right - left) || height > (bottom - top); if (grows == (width1 * height1 > width2 * height2)) { width = width1; height = height1; } else { width = width2; height = height2; } } // Update mWindowDragBounds to the new drag size. updateDraggedBounds(left, top, right, bottom, width, height); } /** * Given the old coordinates and the new width and height, update the mWindowDragBounds. * * @param left The original left bound before the user started dragging. * @param top The original top bound before the user started dragging. * @param right The original right bound before the user started dragging. * @param bottom The original bottom bound before the user started dragging. * @param newWidth The new dragged width. * @param newHeight The new dragged height. */ void updateDraggedBounds(int left, int top, int right, int bottom, int newWidth, int newHeight) { // Generate the final bounds by keeping the opposite drag edge constant. if ((mCtrlType & CTRL_LEFT) != 0) { left = right - newWidth; } else { // Note: The right might have changed - if we pulled at the right or not. right = left + newWidth; } if ((mCtrlType & CTRL_TOP) != 0) { top = bottom - newHeight; } else { // Note: The height might have changed - if we pulled at the bottom or not. bottom = top + newHeight; updateDraggedBounds(TaskResizingAlgorithm.resizeDrag(x, y, mStartDragX, mStartDragY, mWindowOriginalBounds, mCtrlType, mMinVisibleWidth, mMinVisibleHeight, mMaxVisibleSize, mPreserveOrientation, mStartOrientationWasLandscape)); } mWindowDragBounds.set(left, top, right, bottom); private void updateDraggedBounds(Rect newBounds) { mWindowDragBounds.set(newBounds); checkBoundsForOrientationViolations(mWindowDragBounds); } Loading
services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java +1 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.TaskPositioner.MIN_ASPECT; import static com.android.internal.policy.TaskResizingAlgorithm.MIN_ASPECT; import static com.android.server.wm.WindowManagerService.dipToPixel; import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP; import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP; Loading