• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 package com.android.quickstep.util;
17 
18 import static android.view.Surface.ROTATION_0;
19 import static android.view.Surface.ROTATION_180;
20 
21 import android.annotation.TargetApi;
22 import android.content.Context;
23 import android.os.Build;
24 import android.view.WindowManager;
25 import android.view.WindowMetrics;
26 
27 import androidx.annotation.NonNull;
28 import androidx.annotation.Nullable;
29 import androidx.annotation.UiThread;
30 
31 import com.android.launcher3.R;
32 import com.android.launcher3.util.DisplayController;
33 import com.android.launcher3.util.WindowBounds;
34 
35 import java.util.ArrayList;
36 
37 /**
38  * Utility class to hold the information abound a window bounds for split screen
39  */
40 @TargetApi(Build.VERSION_CODES.R)
41 public class SplitScreenBounds {
42 
43     public static final SplitScreenBounds INSTANCE = new SplitScreenBounds();
44     private final ArrayList<OnChangeListener> mListeners = new ArrayList<>();
45 
46     @Nullable
47     private WindowBounds mBounds;
48 
SplitScreenBounds()49     private SplitScreenBounds() { }
50 
51     @UiThread
setSecondaryWindowBounds(@onNull WindowBounds bounds)52     public void setSecondaryWindowBounds(@NonNull WindowBounds bounds) {
53         if (!bounds.equals(mBounds)) {
54             mBounds = bounds;
55             for (OnChangeListener listener : mListeners) {
56                 listener.onSecondaryWindowBoundsChanged();
57             }
58         }
59     }
60 
getSecondaryWindowBounds(Context context)61     public @NonNull WindowBounds getSecondaryWindowBounds(Context context) {
62         if (mBounds == null) {
63             mBounds = createDefaultWindowBounds(context);
64         }
65         return mBounds;
66     }
67 
68     /**
69      * Creates window bounds as 50% of device size
70      */
createDefaultWindowBounds(Context context)71     private static WindowBounds createDefaultWindowBounds(Context context) {
72         WindowMetrics wm = context.getSystemService(WindowManager.class).getMaximumWindowMetrics();
73         WindowBounds bounds = WindowBounds.fromWindowMetrics(wm);
74 
75         int rotation = DisplayController.INSTANCE.get(context).getInfo().rotation;
76         int halfDividerSize = context.getResources()
77                 .getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
78 
79         if (rotation == ROTATION_0 || rotation == ROTATION_180) {
80             bounds.bounds.top = bounds.insets.top + bounds.availableSize.y / 2 + halfDividerSize;
81             bounds.insets.top = 0;
82         } else {
83             bounds.bounds.left = bounds.insets.left + bounds.availableSize.x / 2 + halfDividerSize;
84             bounds.insets.left = 0;
85         }
86         return new WindowBounds(bounds.bounds, bounds.insets);
87     }
88 
addOnChangeListener(OnChangeListener listener)89     public void addOnChangeListener(OnChangeListener listener) {
90         mListeners.add(listener);
91     }
92 
removeOnChangeListener(OnChangeListener listener)93     public void removeOnChangeListener(OnChangeListener listener) {
94         mListeners.remove(listener);
95     }
96 
97     /**
98      * Interface to receive window bounds changes
99      */
100     public interface OnChangeListener {
101 
102         /**
103          * Called when window bounds for secondary window changes
104          */
onSecondaryWindowBoundsChanged()105         void onSecondaryWindowBoundsChanged();
106     }
107 }
108