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