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 package com.android.launcher3.taskbar;
17 
18 import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
19 import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_CONTENT;
20 import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_FRAME;
21 import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION;
22 
23 import android.content.res.Resources;
24 import android.graphics.Rect;
25 
26 import com.android.launcher3.AbstractFloatingView;
27 import com.android.launcher3.R;
28 import com.android.launcher3.anim.AlphaUpdateListener;
29 import com.android.quickstep.AnimatedFloat;
30 import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo;
31 
32 /**
33  * Handles properties/data collection, then passes the results to TaskbarDragLayer to render.
34  */
35 public class TaskbarDragLayerController {
36 
37     private final TaskbarActivityContext mActivity;
38     private final TaskbarDragLayer mTaskbarDragLayer;
39     private final int mFolderMargin;
40 
41     // Alpha properties for taskbar background.
42     private final AnimatedFloat mBgTaskbar = new AnimatedFloat(this::updateBackgroundAlpha);
43     private final AnimatedFloat mBgNavbar = new AnimatedFloat(this::updateBackgroundAlpha);
44     private final AnimatedFloat mKeyguardBgTaskbar = new AnimatedFloat(this::updateBackgroundAlpha);
45     private final AnimatedFloat mNotificationShadeBgTaskbar = new AnimatedFloat(
46             this::updateBackgroundAlpha);
47     private final AnimatedFloat mImeBgTaskbar = new AnimatedFloat(this::updateBackgroundAlpha);
48     // Used to hide our background color when someone else (e.g. ScrimView) is handling it.
49     private final AnimatedFloat mBgOverride = new AnimatedFloat(this::updateBackgroundAlpha);
50 
51     // Translation property for taskbar background.
52     private final AnimatedFloat mBgOffset = new AnimatedFloat(this::updateBackgroundOffset);
53 
54     // Initialized in init.
55     private TaskbarControllers mControllers;
56     private AnimatedFloat mNavButtonDarkIntensityMultiplier;
57 
58     private float mLastSetBackgroundAlpha;
59 
TaskbarDragLayerController(TaskbarActivityContext activity, TaskbarDragLayer taskbarDragLayer)60     public TaskbarDragLayerController(TaskbarActivityContext activity,
61             TaskbarDragLayer taskbarDragLayer) {
62         mActivity = activity;
63         mTaskbarDragLayer = taskbarDragLayer;
64         final Resources resources = mTaskbarDragLayer.getResources();
65         mFolderMargin = resources.getDimensionPixelSize(R.dimen.taskbar_folder_margin);
66     }
67 
init(TaskbarControllers controllers)68     public void init(TaskbarControllers controllers) {
69         mControllers = controllers;
70         mTaskbarDragLayer.init(new TaskbarDragLayerCallbacks());
71 
72         mNavButtonDarkIntensityMultiplier = mControllers.navbarButtonsViewController
73                 .getNavButtonDarkIntensityMultiplier();
74 
75         mBgTaskbar.value = 1;
76         mKeyguardBgTaskbar.value = 1;
77         mNotificationShadeBgTaskbar.value = 1;
78         mImeBgTaskbar.value = 1;
79         mBgOverride.value = 1;
80         updateBackgroundAlpha();
81     }
82 
onDestroy()83     public void onDestroy() {
84         mTaskbarDragLayer.onDestroy();
85     }
86 
87     /**
88      * @return Bounds (in TaskbarDragLayer coordinates) where an opened Folder can display.
89      */
getFolderBoundingBox()90     public Rect getFolderBoundingBox() {
91         Rect boundingBox = new Rect(0, 0, mTaskbarDragLayer.getWidth(),
92                 mTaskbarDragLayer.getHeight() - mActivity.getDeviceProfile().taskbarSize);
93         boundingBox.inset(mFolderMargin, mFolderMargin);
94         return boundingBox;
95     }
96 
getTaskbarBackgroundAlpha()97     public AnimatedFloat getTaskbarBackgroundAlpha() {
98         return mBgTaskbar;
99     }
100 
getNavbarBackgroundAlpha()101     public AnimatedFloat getNavbarBackgroundAlpha() {
102         return mBgNavbar;
103     }
104 
getKeyguardBgTaskbar()105     public AnimatedFloat getKeyguardBgTaskbar() {
106         return mKeyguardBgTaskbar;
107     }
108 
getNotificationShadeBgTaskbar()109     public AnimatedFloat getNotificationShadeBgTaskbar() {
110         return mNotificationShadeBgTaskbar;
111     }
112 
getImeBgTaskbar()113     public AnimatedFloat getImeBgTaskbar() {
114         return mImeBgTaskbar;
115     }
116 
getOverrideBackgroundAlpha()117     public AnimatedFloat getOverrideBackgroundAlpha() {
118         return mBgOverride;
119     }
120 
getTaskbarBackgroundOffset()121     public AnimatedFloat getTaskbarBackgroundOffset() {
122         return mBgOffset;
123     }
124 
updateBackgroundAlpha()125     private void updateBackgroundAlpha() {
126         final float bgNavbar = mBgNavbar.value;
127         final float bgTaskbar = mBgTaskbar.value * mKeyguardBgTaskbar.value
128                 * mNotificationShadeBgTaskbar.value * mImeBgTaskbar.value;
129         mLastSetBackgroundAlpha = mBgOverride.value * Math.max(bgNavbar, bgTaskbar);
130         mTaskbarDragLayer.setTaskbarBackgroundAlpha(mLastSetBackgroundAlpha);
131 
132         updateNavBarDarkIntensityMultiplier();
133     }
134 
updateBackgroundOffset()135     private void updateBackgroundOffset() {
136         mTaskbarDragLayer.setTaskbarBackgroundOffset(mBgOffset.value);
137 
138         updateNavBarDarkIntensityMultiplier();
139     }
140 
updateNavBarDarkIntensityMultiplier()141     private void updateNavBarDarkIntensityMultiplier() {
142         // Zero out the app-requested dark intensity when we're drawing our own background.
143         float effectiveBgAlpha = mLastSetBackgroundAlpha * (1 - mBgOffset.value);
144         mNavButtonDarkIntensityMultiplier.updateValue(1 - effectiveBgAlpha);
145     }
146 
147     /**
148      * Callbacks for {@link TaskbarDragLayer} to interact with its controller.
149      */
150     public class TaskbarDragLayerCallbacks {
151 
152         /**
153          * Called to update the touchable insets.
154          * @see InsetsInfo#setTouchableInsets(int)
155          */
updateInsetsTouchability(InsetsInfo insetsInfo)156         public void updateInsetsTouchability(InsetsInfo insetsInfo) {
157             insetsInfo.touchableRegion.setEmpty();
158             // Always have nav buttons be touchable
159             mControllers.navbarButtonsViewController.addVisibleButtonsRegion(
160                     mTaskbarDragLayer, insetsInfo.touchableRegion);
161             boolean insetsIsTouchableRegion = true;
162 
163             if (mTaskbarDragLayer.getAlpha() < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) {
164                 // Let touches pass through us.
165                 insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
166             } else if (mControllers.navbarButtonsViewController.isImeVisible()) {
167                 insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
168             } else if (!mControllers.uiController.isTaskbarTouchable()) {
169                 // Let touches pass through us.
170                 insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
171             } else if (mControllers.taskbarViewController.areIconsVisible()
172                     || AbstractFloatingView.getOpenView(mActivity, TYPE_ALL) != null) {
173                 // Taskbar has some touchable elements, take over the full taskbar area
174                 insetsInfo.setTouchableInsets(mActivity.isTaskbarWindowFullscreen()
175                         ? TOUCHABLE_INSETS_FRAME : TOUCHABLE_INSETS_CONTENT);
176                 insetsIsTouchableRegion = false;
177             } else {
178                 insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
179             }
180             mActivity.excludeFromMagnificationRegion(insetsIsTouchableRegion);
181         }
182 
183         /**
184          * Called to update the {@link InsetsInfo#contentInsets}. This is reported to apps but our
185          * internal launcher will ignore these insets.
186          */
updateContentInsets(Rect outContentInsets)187         public void updateContentInsets(Rect outContentInsets) {
188             int contentHeight = mControllers.taskbarStashController
189                     .getContentHeightToReportToApps();
190             outContentInsets.top = mTaskbarDragLayer.getHeight() - contentHeight;
191         }
192 
193         /**
194          * Called when a child is removed from TaskbarDragLayer.
195          */
onDragLayerViewRemoved()196         public void onDragLayerViewRemoved() {
197             if (AbstractFloatingView.getAnyView(mActivity, TYPE_ALL) == null) {
198                 mActivity.setTaskbarWindowFullscreen(false);
199             }
200         }
201 
202         /**
203          * Returns how tall the background should be drawn at the bottom of the screen.
204          */
getTaskbarBackgroundHeight()205         public int getTaskbarBackgroundHeight() {
206             return mActivity.getDeviceProfile().taskbarSize;
207         }
208     }
209 }
210