blob: 2a593f15a9de6411f962ec28647512749fdd6c82 [file] [log] [blame]
/*
* Copyright (C) 2021 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 androidx.window.util;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import android.app.Activity;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.view.DisplayInfo;
import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/**
* Util class for both Sidecar and Extensions.
*/
public final class ExtensionHelper {
private ExtensionHelper() {
// Util class, no instances should be created.
}
/**
* Rotates the input rectangle specified in default display orientation to the current display
* rotation.
*/
public static void rotateRectToDisplayRotation(int displayId, Rect inOutRect) {
DisplayManagerGlobal dmGlobal = DisplayManagerGlobal.getInstance();
DisplayInfo displayInfo = dmGlobal.getDisplayInfo(displayId);
int rotation = displayInfo.rotation;
boolean isSideRotation = rotation == ROTATION_90 || rotation == ROTATION_270;
int displayWidth = isSideRotation ? displayInfo.logicalHeight : displayInfo.logicalWidth;
int displayHeight = isSideRotation ? displayInfo.logicalWidth : displayInfo.logicalHeight;
inOutRect.intersect(0, 0, displayWidth, displayHeight);
rotateBounds(inOutRect, displayWidth, displayHeight, rotation);
}
/**
* Rotates the input rectangle within parent bounds for a given delta.
*/
private static void rotateBounds(Rect inOutRect, int parentWidth, int parentHeight,
@Surface.Rotation int delta) {
int origLeft = inOutRect.left;
switch (delta) {
case ROTATION_0:
return;
case ROTATION_90:
inOutRect.left = inOutRect.top;
inOutRect.top = parentWidth - inOutRect.right;
inOutRect.right = inOutRect.bottom;
inOutRect.bottom = parentWidth - origLeft;
return;
case ROTATION_180:
inOutRect.left = parentWidth - inOutRect.right;
inOutRect.right = parentWidth - origLeft;
return;
case ROTATION_270:
inOutRect.left = parentHeight - inOutRect.bottom;
inOutRect.bottom = inOutRect.right;
inOutRect.right = parentHeight - inOutRect.top;
inOutRect.top = origLeft;
return;
}
}
/** Transforms rectangle from absolute coordinate space to the window coordinate space. */
public static void transformToWindowSpaceRect(Activity activity, Rect inOutRect) {
Rect windowRect = getWindowBounds(activity);
if (windowRect == null) {
inOutRect.setEmpty();
return;
}
if (!Rect.intersects(inOutRect, windowRect)) {
inOutRect.setEmpty();
return;
}
inOutRect.intersect(windowRect);
inOutRect.offset(-windowRect.left, -windowRect.top);
}
/**
* Gets the current window bounds in absolute coordinates.
*/
@Nullable
private static Rect getWindowBounds(@NonNull Activity activity) {
return activity.getWindowManager().getCurrentWindowMetrics().getBounds();
}
/**
* Checks if both dimensions of the given rect are zero at the same time.
*/
public static boolean isZero(@NonNull Rect rect) {
return rect.height() == 0 && rect.width() == 0;
}
}