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