• 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.WindowConfiguration;
25 import android.content.Context;
26 import android.graphics.Rect;
27 import android.hardware.display.DisplayManagerGlobal;
28 import android.view.DisplayInfo;
29 import android.view.Surface;
30 import android.view.WindowManager;
31 
32 import androidx.annotation.NonNull;
33 import androidx.annotation.UiContext;
34 
35 /**
36  * Util class for both Sidecar and Extensions.
37  */
38 public final class ExtensionHelper {
39 
ExtensionHelper()40     private ExtensionHelper() {
41         // Util class, no instances should be created.
42     }
43 
44     /**
45      * Rotates the input rectangle specified in default display orientation to the current display
46      * rotation.
47      */
rotateRectToDisplayRotation(int displayId, Rect inOutRect)48     public static void rotateRectToDisplayRotation(int displayId, Rect inOutRect) {
49         DisplayManagerGlobal dmGlobal = DisplayManagerGlobal.getInstance();
50         DisplayInfo displayInfo = dmGlobal.getDisplayInfo(displayId);
51         int rotation = displayInfo.rotation;
52 
53         boolean isSideRotation = rotation == ROTATION_90 || rotation == ROTATION_270;
54         int displayWidth = isSideRotation ? displayInfo.logicalHeight : displayInfo.logicalWidth;
55         int displayHeight = isSideRotation ? displayInfo.logicalWidth : displayInfo.logicalHeight;
56 
57         inOutRect.intersect(0, 0, displayWidth, displayHeight);
58 
59         rotateBounds(inOutRect, displayWidth, displayHeight, rotation);
60     }
61 
62     /**
63      * Rotates the input rectangle within parent bounds for a given delta.
64      */
rotateBounds(Rect inOutRect, int parentWidth, int parentHeight, @Surface.Rotation int delta)65     private static void rotateBounds(Rect inOutRect, int parentWidth, int parentHeight,
66             @Surface.Rotation int delta) {
67         int origLeft = inOutRect.left;
68         switch (delta) {
69             case ROTATION_0:
70                 return;
71             case ROTATION_90:
72                 inOutRect.left = inOutRect.top;
73                 inOutRect.top = parentWidth - inOutRect.right;
74                 inOutRect.right = inOutRect.bottom;
75                 inOutRect.bottom = parentWidth - origLeft;
76                 return;
77             case ROTATION_180:
78                 inOutRect.left = parentWidth - inOutRect.right;
79                 inOutRect.right = parentWidth - origLeft;
80                 return;
81             case ROTATION_270:
82                 inOutRect.left = parentHeight - inOutRect.bottom;
83                 inOutRect.bottom = inOutRect.right;
84                 inOutRect.right = parentHeight - inOutRect.top;
85                 inOutRect.top = origLeft;
86                 return;
87         }
88     }
89 
90     /** Transforms rectangle from absolute coordinate space to the window coordinate space. */
transformToWindowSpaceRect(@onNull @iContext Context context, Rect inOutRect)91     public static void transformToWindowSpaceRect(@NonNull @UiContext Context context,
92             Rect inOutRect) {
93         transformToWindowSpaceRect(getWindowBounds(context), inOutRect);
94     }
95 
96     /** @see ExtensionHelper#transformToWindowSpaceRect(Context, Rect) */
transformToWindowSpaceRect(@onNull WindowConfiguration windowConfiguration, Rect inOutRect)97     public static void transformToWindowSpaceRect(@NonNull WindowConfiguration windowConfiguration,
98             Rect inOutRect) {
99         transformToWindowSpaceRect(windowConfiguration.getBounds(), inOutRect);
100     }
101 
transformToWindowSpaceRect(@onNull Rect bounds, @NonNull Rect inOutRect)102     private static void transformToWindowSpaceRect(@NonNull Rect bounds, @NonNull Rect inOutRect) {
103         if (!inOutRect.intersect(bounds)) {
104             inOutRect.setEmpty();
105             return;
106         }
107         inOutRect.offset(-bounds.left, -bounds.top);
108     }
109 
110     /**
111      * Gets the current window bounds in absolute coordinates.
112      */
113     @NonNull
getWindowBounds(@onNull @iContext Context context)114     private static Rect getWindowBounds(@NonNull @UiContext Context context) {
115         return context.getSystemService(WindowManager.class).getCurrentWindowMetrics().getBounds();
116     }
117 
118     /**
119      * Checks if both dimensions of the given rect are zero at the same time.
120      */
isZero(@onNull Rect rect)121     public static boolean isZero(@NonNull Rect rect) {
122         return rect.height() == 0 && rect.width() == 0;
123     }
124 }
125