Refactor TaskPositioner resizing logic into a shareable class.
So this can be used by other resizing not done by the framework (e.g. PIP resizing done via SysUI). Bug: 147361175 Test: Compile Change-Id: I0010b292af5ea48e4303a4faaf9c0bbe49d5d64f
This commit is contained in:
179
core/java/com/android/internal/policy/TaskResizingAlgorithm.java
Normal file
179
core/java/com/android/internal/policy/TaskResizingAlgorithm.java
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user