• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.uioverrides.states;
17 
18 import static com.android.app.animation.Interpolators.DECELERATE_2;
19 import static com.android.launcher3.Flags.enableDesktopExplodedView;
20 import static com.android.launcher3.Flags.enableOverviewBackgroundWallpaperBlur;
21 import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
22 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
23 
24 import android.content.Context;
25 import android.graphics.Rect;
26 import android.os.SystemProperties;
27 
28 import com.android.launcher3.DeviceProfile;
29 import com.android.launcher3.Launcher;
30 import com.android.launcher3.LauncherState;
31 import com.android.launcher3.R;
32 import com.android.launcher3.util.DisplayController;
33 import com.android.launcher3.util.Themes;
34 import com.android.launcher3.views.ActivityContext;
35 import com.android.quickstep.util.BaseDepthController;
36 import com.android.quickstep.util.LayoutUtils;
37 import com.android.quickstep.views.RecentsView;
38 import com.android.quickstep.views.TaskView;
39 import com.android.systemui.shared.system.BlurUtils;
40 
41 /**
42  * Definition for overview state
43  */
44 public class OverviewState extends LauncherState {
45 
46     private static final int OVERVIEW_SLIDE_IN_DURATION = 380;
47     private static final int OVERVIEW_POP_IN_DURATION = 250;
48     private static final int OVERVIEW_EXIT_DURATION = 250;
49 
50     protected static final Rect sTempRect = new Rect();
51 
52     private static final int STATE_FLAGS = FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED
53             | FLAG_DISABLE_RESTORE | FLAG_RECENTS_VIEW_VISIBLE | FLAG_WORKSPACE_INACCESSIBLE
54             | FLAG_CLOSE_POPUPS;
55 
OverviewState(int id)56     public OverviewState(int id) {
57         this(id, STATE_FLAGS);
58     }
59 
OverviewState(int id, int stateFlags)60     protected OverviewState(int id, int stateFlags) {
61         this(id, LAUNCHER_STATE_OVERVIEW, stateFlags);
62     }
63 
OverviewState(int id, int logContainer, int stateFlags)64     protected OverviewState(int id, int logContainer, int stateFlags) {
65         super(id, logContainer, stateFlags);
66     }
67 
68     @Override
getTransitionDuration(ActivityContext context, boolean isToState)69     public int getTransitionDuration(ActivityContext context, boolean isToState) {
70         if (isToState) {
71             // In gesture modes, overview comes in all the way from the side, so give it more time.
72             return DisplayController.getNavigationMode(context.asContext()).hasGestures
73                     ? OVERVIEW_SLIDE_IN_DURATION
74                     : OVERVIEW_POP_IN_DURATION;
75         } else {
76             // When exiting Overview, exit quickly.
77             return OVERVIEW_EXIT_DURATION;
78         }
79     }
80 
81     @Override
getWorkspaceScaleAndTranslation(Launcher launcher)82     public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
83         RecentsView recentsView = launcher.getOverviewPanel();
84         recentsView.getTaskSize(sTempRect);
85         float scale;
86         DeviceProfile deviceProfile = launcher.getDeviceProfile();
87         if (deviceProfile.isTwoPanels) {
88             // In two panel layout, width does not include both panels or space between them, so
89             // use height instead. We do not use height for handheld, as cell layout can be
90             // shorter than a task and we want the workspace to scale down to task size.
91             scale = (float) sTempRect.height() / deviceProfile.getCellLayoutHeight();
92         } else {
93             scale = (float) sTempRect.width() / deviceProfile.getCellLayoutWidth();
94         }
95         float parallaxFactor = 0.5f;
96         return new ScaleAndTranslation(scale, 0, -getDefaultSwipeHeight(launcher) * parallaxFactor);
97     }
98 
99     @Override
getOverviewScaleAndOffset(Launcher launcher)100     public float[] getOverviewScaleAndOffset(Launcher launcher) {
101         return new float[] {NO_SCALE, NO_OFFSET};
102     }
103 
104     @Override
getWorkspacePageAlphaProvider(Launcher launcher)105     public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
106         return new PageAlphaProvider(DECELERATE_2) {
107             @Override
108             public float getPageAlpha(int pageIndex) {
109                 return 0;
110             }
111         };
112     }
113 
114     @Override
115     public int getVisibleElements(Launcher launcher) {
116         int elements = CLEAR_ALL_BUTTON | OVERVIEW_ACTIONS | ADD_DESK_BUTTON;
117         DeviceProfile dp = launcher.getDeviceProfile();
118         boolean showFloatingSearch;
119         if (dp.isPhone) {
120             // Only show search in phone overview in portrait mode.
121             showFloatingSearch = !dp.isLandscape;
122         } else {
123             // Only show search in tablet overview if taskbar is not visible.
124             showFloatingSearch = !dp.isTaskbarPresent || isTaskbarStashed(launcher);
125         }
126         if (showFloatingSearch) {
127             elements |= FLOATING_SEARCH_BAR;
128         }
129         if (launcher.isSplitSelectionActive()) {
130             elements &= ~CLEAR_ALL_BUTTON & ~ADD_DESK_BUTTON;
131         }
132         return elements;
133     }
134 
135     @Override
136     public float getSplitSelectTranslation(Launcher launcher) {
137         if (!launcher.isSplitSelectionActive()) {
138             return 0f;
139         }
140         RecentsView recentsView = launcher.getOverviewPanel();
141         return recentsView.getSplitSelectTranslation();
142     }
143 
144     @Override
145     public int getFloatingSearchBarRestingMarginBottom(Launcher launcher) {
146         return areElementsVisible(launcher, FLOATING_SEARCH_BAR) ? 0
147                 : super.getFloatingSearchBarRestingMarginBottom(launcher);
148     }
149 
150     @Override
151     public boolean shouldFloatingSearchBarUsePillWhenUnfocused(Launcher launcher) {
152         DeviceProfile dp = launcher.getDeviceProfile();
153         return dp.isPhone && !dp.isLandscape;
154     }
155 
156     @Override
157     public boolean isTaskbarAlignedWithHotseat(Launcher launcher) {
158         return false;
159     }
160 
161     @Override
162     public int getWorkspaceScrimColor(Launcher launcher) {
163         return enableOverviewBackgroundWallpaperBlur() && BlurUtils.supportsBlursOnWindows()
164                 ? Themes.getAttrColor(launcher, R.attr.overviewScrimColorOverBlur)
165                 : Themes.getAttrColor(launcher, R.attr.overviewScrimColor);
166     }
167 
168     @Override
169     public boolean displayOverviewTasksAsGrid(DeviceProfile deviceProfile) {
170         return deviceProfile.isTablet;
171     }
172 
173     @Override
174     public boolean detachDesktopCarousel() {
175         return false;
176     }
177 
178     @Override
179     public boolean showExplodedDesktopView() {
180         return enableDesktopExplodedView();
181     }
182 
183     @Override
184     public boolean disallowTaskbarGlobalDrag() {
185         // Disable global drag in overview
186         return true;
187     }
188 
189     @Override
190     public boolean allowTaskbarInitialSplitSelection() {
191         // Allow split select from taskbar items in overview
192         return true;
193     }
194 
195     @Override
196     public String getDescription(Launcher launcher) {
197         return launcher.getString(R.string.accessibility_recent_apps);
198     }
199 
200     @Override
201     public int getTitle() {
202         return R.string.accessibility_recent_apps;
203     }
204 
205     public static float getDefaultSwipeHeight(Launcher launcher) {
206         return LayoutUtils.getDefaultSwipeHeight(launcher, launcher.getDeviceProfile());
207     }
208 
209     @Override
210     protected float getDepthUnchecked(Context context) {
211         // TODO(178661709): revert to always scaled
212         if (enableScalingRevealHomeAnimation()) {
213             return SystemProperties.getBoolean("ro.launcher.depth.overview", true)
214                     ? BaseDepthController.DEPTH_70_PERCENT
215                     : BaseDepthController.DEPTH_0_PERCENT;
216         } else {
217             return SystemProperties.getBoolean("ro.launcher.depth.overview", true) ? 1 : 0;
218         }
219     }
220 
221     @Override
222     public void onBackInvoked(Launcher launcher) {
223         RecentsView recentsView = launcher.getOverviewPanel();
224         TaskView taskView = recentsView.getRunningTaskView();
225         if (taskView != null) {
226             if (recentsView.isTaskViewFullyVisible(taskView)) {
227                 taskView.launchWithAnimation();
228             } else {
229                 recentsView.snapToPage(recentsView.indexOfChild(taskView));
230             }
231         } else {
232             super.onBackInvoked(launcher);
233         }
234     }
235 
236     public static OverviewState newBackgroundState(int id) {
237         return new BackgroundAppState(id);
238     }
239 
240     public static OverviewState newSwitchState(int id) {
241         return new QuickSwitchState(id);
242     }
243 
244     /**
245      *  New Overview substate that represents the overview in modal mode (one task shown on its own)
246      */
247     public static OverviewState newModalTaskState(int id) {
248         return new OverviewModalTaskState(id);
249     }
250 
251     /**
252      * New Overview substate representing state where 1 app for split screen has been selected and
253      * pinned and user is selecting the second one
254      */
255     public static OverviewState newSplitSelectState(int id) {
256         return new SplitScreenSelectState(id);
257     }
258 }
259