• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.window.util;
18 
19 import static android.view.Surface.ROTATION_0;
20 import static android.view.Surface.ROTATION_180;
21 import static android.view.Surface.ROTATION_270;
22 import static android.view.Surface.ROTATION_90;
23 
24 import android.app.Activity;
25 import android.graphics.Rect;
26 import android.hardware.display.DisplayManagerGlobal;
27 import android.view.DisplayInfo;
28 import android.view.Surface;
29 
30 import androidx.annotation.NonNull;
31 import androidx.annotation.Nullable;
32 
33 /**
34  * Util class for both Sidecar and Extensions.
35  */
36 public final class ExtensionHelper {
37 
ExtensionHelper()38     private ExtensionHelper() {
39         // Util class, no instances should be created.
40     }
41 
42     /**
43      * Rotates the input rectangle specified in default display orientation to the current display
44      * rotation.
45      */
rotateRectToDisplayRotation(int displayId, Rect inOutRect)46     public static void rotateRectToDisplayRotation(int displayId, Rect inOutRect) {
47         DisplayManagerGlobal dmGlobal = DisplayManagerGlobal.getInstance();
48         DisplayInfo displayInfo = dmGlobal.getDisplayInfo(displayId);
49         int rotation = displayInfo.rotation;
50 
51         boolean isSideRotation = rotation == ROTATION_90 || rotation == ROTATION_270;
52         int displayWidth = isSideRotation ? displayInfo.logicalHeight : displayInfo.logicalWidth;
53         int displayHeight = isSideRotation ? displayInfo.logicalWidth : displayInfo.logicalHeight;
54 
55         inOutRect.intersect(0, 0, displayWidth, displayHeight);
56 
57         rotateBounds(inOutRect, displayWidth, displayHeight, rotation);
58     }
59 
60     /**
61      * Rotates the input rectangle within parent bounds for a given delta.
62      */
rotateBounds(Rect inOutRect, int parentWidth, int parentHeight, @Surface.Rotation int delta)63     private static void rotateBounds(Rect inOutRect, int parentWidth, int parentHeight,
64             @Surface.Rotation int delta) {
65         int origLeft = inOutRect.left;
66         switch (delta) {
67             case ROTATION_0:
68                 return;
69             case ROTATION_90:
70                 inOutRect.left = inOutRect.top;
71                 inOutRect.top = parentWidth - inOutRect.right;
72                 inOutRect.right = inOutRect.bottom;
73                 inOutRect.bottom = parentWidth - origLeft;
74                 return;
75             case ROTATION_180:
76                 inOutRect.left = parentWidth - inOutRect.right;
77                 inOutRect.right = parentWidth - origLeft;
78                 return;
79             case ROTATION_270:
80                 inOutRect.left = parentHeight - inOutRect.bottom;
81                 inOutRect.bottom = inOutRect.right;
82                 inOutRect.right = parentHeight - inOutRect.top;
83                 inOutRect.top = origLeft;
84                 return;
85         }
86     }
87 
88     /** Transforms rectangle from absolute coordinate space to the window coordinate space. */
transformToWindowSpaceRect(Activity activity, Rect inOutRect)89     public static void transformToWindowSpaceRect(Activity activity, Rect inOutRect) {
90         Rect windowRect = getWindowBounds(activity);
91         if (windowRect == null) {
92             inOutRect.setEmpty();
93             return;
94         }
95         if (!Rect.intersects(inOutRect, windowRect)) {
96             inOutRect.setEmpty();
97             return;
98         }
99         inOutRect.intersect(windowRect);
100         inOutRect.offset(-windowRect.left, -windowRect.top);
101     }
102 
103     /**
104      * Gets the current window bounds in absolute coordinates.
105      */
106     @Nullable
getWindowBounds(@onNull Activity activity)107     private static Rect getWindowBounds(@NonNull Activity activity) {
108         return activity.getWindowManager().getCurrentWindowMetrics().getBounds();
109     }
110 
111     /**
112      * Checks if both dimensions of the given rect are zero at the same time.
113      */
isZero(@onNull Rect rect)114     public static boolean isZero(@NonNull Rect rect) {
115         return rect.height() == 0 && rect.width() == 0;
116     }
117 }
118