diff --git a/quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml b/quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml index 7b3e37835f..cd64a94bab 100644 --- a/quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml +++ b/quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml @@ -13,25 +13,30 @@ See the License for the specific language governing permissions and limitations under the License. --> - - + android:clipChildren="false"> - + - + + + + diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java index 170102047b..6f2f9fb523 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java @@ -55,7 +55,7 @@ import com.android.launcher3.util.Themes; import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.fallback.FallbackRecentsStateController; import com.android.quickstep.fallback.FallbackRecentsView; -import com.android.quickstep.fallback.RecentsRootView; +import com.android.quickstep.fallback.RecentsDragLayer; import com.android.quickstep.fallback.RecentsState; import com.android.quickstep.util.RecentsAtomicAnimationFactory; import com.android.quickstep.views.OverviewActionsView; @@ -78,7 +78,8 @@ public final class RecentsActivity extends StatefulActivity { new ActivityTracker<>(); private Handler mUiHandler = new Handler(Looper.getMainLooper()); - private RecentsRootView mRecentsRootView; + + private RecentsDragLayer mDragLayer; private FallbackRecentsView mFallbackRecentsView; private OverviewActionsView mActionsView; @@ -89,13 +90,14 @@ public final class RecentsActivity extends StatefulActivity { /** * Init drag layer and overview panel views. */ - protected void initViews() { - setContentView(R.layout.fallback_recents_activity); - mRecentsRootView = findViewById(R.id.drag_layer); + protected void setupViews() { + inflateRootView(R.layout.fallback_recents_activity); + setContentView(getRootView()); + mDragLayer = findViewById(R.id.drag_layer); mFallbackRecentsView = findViewById(R.id.overview_panel); mActionsView = findViewById(R.id.overview_actions_view); - mRecentsRootView.recreateControllers(); + mDragLayer.recreateControllers(); mFallbackRecentsView.init(mActionsView); } @@ -105,12 +107,6 @@ public final class RecentsActivity extends StatefulActivity { super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig); } - public void onRootViewSizeChanged() { - if (isInMultiWindowMode()) { - onHandleConfigChanged(); - } - } - @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); @@ -130,7 +126,7 @@ public final class RecentsActivity extends StatefulActivity { dispatchDeviceProfileChanged(); reapplyUi(); - mRecentsRootView.recreateControllers(); + mDragLayer.recreateControllers(); } /** @@ -142,19 +138,14 @@ public final class RecentsActivity extends StatefulActivity { // In case we are reusing IDP, create a copy so that we don't conflict with Launcher // activity. - return (mRecentsRootView != null) && isInMultiWindowMode() + return (mDragLayer != null) && isInMultiWindowMode() ? dp.getMultiWindowProfile(this, getMultiWindowDisplaySize()) : dp.copy(this); } @Override public BaseDragLayer getDragLayer() { - return mRecentsRootView; - } - - @Override - public View getRootView() { - return mRecentsRootView; + return mDragLayer; } @Override @@ -252,7 +243,7 @@ public final class RecentsActivity extends StatefulActivity { mOldConfig = new Configuration(getResources().getConfiguration()); initDeviceProfile(); - initViews(); + setupViews(); getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW, Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java index 9242771dd9..d20bbe9780 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java @@ -106,12 +106,23 @@ public class FallbackRecentsView extends RecentsView } } + @Override + protected boolean shouldAddDummyTaskView(int runningTaskId) { + if (mHomeTaskInfo != null && mHomeTaskInfo.taskId == runningTaskId + && getTaskViewCount() == 0) { + // Do not add a dummy task if we are running over home with empty recents, so that we + // show the empty recents message instead of showing a dummy task and later removing it. + return false; + } + return super.shouldAddDummyTaskView(runningTaskId); + } + @Override protected void applyLoadPlan(ArrayList tasks) { // When quick-switching on 3p-launcher, we add a "dummy" tile corresponding to Launcher // as well. This tile is never shown as we have setCurrentTaskHidden, but allows use to // track the index of the next task appropriately, as if we are switching on any other app. - if (mHomeTaskInfo != null && mHomeTaskInfo.taskId == mRunningTaskId) { + if (mHomeTaskInfo != null && mHomeTaskInfo.taskId == mRunningTaskId && !tasks.isEmpty()) { // Check if the task list has running task boolean found = false; for (Task t : tasks) { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsDragLayer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsDragLayer.java new file mode 100644 index 0000000000..a00015a233 --- /dev/null +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsDragLayer.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep.fallback; + +import android.content.Context; +import android.graphics.Rect; +import android.util.AttributeSet; + +import com.android.launcher3.R; +import com.android.launcher3.util.Themes; +import com.android.launcher3.util.TouchController; +import com.android.launcher3.views.BaseDragLayer; +import com.android.quickstep.RecentsActivity; + +/** + * Drag layer for fallback recents activity + */ +public class RecentsDragLayer extends BaseDragLayer { + + public RecentsDragLayer(Context context, AttributeSet attrs) { + super(context, attrs, 1 /* alphaChannelCount */); + } + + @Override + public void recreateControllers() { + mControllers = new TouchController[] { + new RecentsTaskController(mActivity), + new FallbackNavBarTouchController(mActivity), + }; + } + + @Override + public void setInsets(Rect insets) { + super.setInsets(insets); + setBackground(insets.top == 0 || !mAllowSysuiScrims + ? null + : Themes.getAttrDrawable(getContext(), R.attr.workspaceStatusBarScrim)); + } +} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java deleted file mode 100644 index 7f5ec9bc12..0000000000 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.quickstep.fallback; - -import android.annotation.TargetApi; -import android.content.Context; -import android.graphics.Point; -import android.graphics.Rect; -import android.util.AttributeSet; - -import com.android.launcher3.R; -import com.android.launcher3.util.Themes; -import com.android.launcher3.util.TouchController; -import com.android.launcher3.views.BaseDragLayer; -import com.android.quickstep.RecentsActivity; - -public class RecentsRootView extends BaseDragLayer { - - private static final int MIN_SIZE = 10; - - private final Point mLastKnownSize = new Point(MIN_SIZE, MIN_SIZE); - - public RecentsRootView(Context context, AttributeSet attrs) { - super(context, attrs, 1 /* alphaChannelCount */); - setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | SYSTEM_UI_FLAG_LAYOUT_STABLE); - } - - public Point getLastKnownSize() { - return mLastKnownSize; - } - - @Override - public void recreateControllers() { - mControllers = new TouchController[] { - new RecentsTaskController(mActivity), - new FallbackNavBarTouchController(mActivity), - }; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // Check size changes before the actual measure, to avoid multiple measure calls. - int width = Math.max(MIN_SIZE, MeasureSpec.getSize(widthMeasureSpec)); - int height = Math.max(MIN_SIZE, MeasureSpec.getSize(heightMeasureSpec)); - if (mLastKnownSize.x != width || mLastKnownSize.y != height) { - mLastKnownSize.set(width, height); - mActivity.onRootViewSizeChanged(); - } - - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - - @TargetApi(23) - @Override - protected boolean fitSystemWindows(Rect insets) { - // Update device profile before notifying the children. - mActivity.getDeviceProfile().updateInsets(insets); - setInsets(insets); - return false; // Let children get the full insets - } - - @Override - public void setInsets(Rect insets) { - // If the insets haven't changed, this is a no-op. Avoid unnecessary layout caused by - // modifying child layout params. - if (!insets.equals(mInsets)) { - super.setInsets(insets); - } - setBackground(insets.top == 0 || !mAllowSysuiScrims - ? null - : Themes.getAttrDrawable(getContext(), R.attr.workspaceStatusBarScrim)); - } - - public void dispatchInsets() { - mActivity.getDeviceProfile().updateInsets(mInsets); - super.setInsets(mInsets); - } -} \ No newline at end of file diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 6380bbefa0..e89e56641b 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -105,6 +105,7 @@ import com.android.launcher3.anim.SpringProperty; import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.statehandlers.DepthController; +import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.touch.PagedOrientationHandler.CurveProperties; import com.android.launcher3.userevent.nano.LauncherLogProto; @@ -146,8 +147,8 @@ import java.util.function.Consumer; * A list of recent tasks. */ @TargetApi(Build.VERSION_CODES.P) -public abstract class RecentsView extends PagedView implements Insettable, - TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback, +public abstract class RecentsView extends PagedView implements + Insettable, TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback, InvariantDeviceProfile.OnIDPChangeListener, TaskVisualsChangeListener, SplitScreenBounds.OnChangeListener { @@ -389,12 +390,12 @@ public abstract class RecentsView extends PagedView impl setPageSpacing(getResources().getDimensionPixelSize(R.dimen.recents_page_spacing)); setEnableFreeScroll(true); mSizeStrategy = sizeStrategy; + mActivity = BaseActivity.fromContext(context); mOrientationState = new RecentsOrientedState( context, mSizeStrategy, this::animateRecentsRotationInPlace); mFastFlingVelocity = getResources() .getDimensionPixelSize(R.dimen.recents_fast_fling_velocity); - mActivity = BaseActivity.fromContext(context); mModel = RecentsModel.INSTANCE.get(context); mIdp = InvariantDeviceProfile.INSTANCE.get(context); @@ -1114,6 +1115,13 @@ public abstract class RecentsView extends PagedView impl animateActionsViewIn(); } + /** + * Returns true if we should add a dummy taskView for the running task id + */ + protected boolean shouldAddDummyTaskView(int runningTaskId) { + return getTaskView(runningTaskId) == null; + } + /** * Creates a task view (if necessary) to represent the task with the {@param runningTaskId}. * @@ -1121,7 +1129,7 @@ public abstract class RecentsView extends PagedView impl * is called. Also scrolls the view to this task. */ public void showCurrentTask(int runningTaskId) { - if (getTaskView(runningTaskId) == null) { + if (shouldAddDummyTaskView(runningTaskId)) { boolean wasEmpty = getChildCount() == 0; // Add an empty view for now until the task plan is loaded and applied final TaskView taskView = mTaskViewPool.getView(); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index ec32e62c2a..7fc64ea073 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -260,7 +260,6 @@ public class Launcher extends StatefulActivity implements Launche @Thunk Workspace mWorkspace; - private View mLauncherView; @Thunk DragLayer mDragLayer; private DragController mDragController; @@ -363,6 +362,7 @@ public class Launcher extends StatefulActivity implements Launche LauncherAppState app = LauncherAppState.getInstance(this); mOldConfig = new Configuration(getResources().getConfiguration()); mModel = app.getModel(); + mRotationHelper = new RotationHelper(this); InvariantDeviceProfile idp = app.getInvariantDeviceProfile(); initDeviceProfile(idp); @@ -382,8 +382,7 @@ public class Launcher extends StatefulActivity implements Launche appWidgetId -> getWorkspace().removeWidget(appWidgetId)); mAppWidgetHost.startListening(); - mLauncherView = LayoutInflater.from(this).inflate(R.layout.launcher, null); - + inflateRootView(R.layout.launcher); setupViews(); mPopupDataProvider = new PopupDataProvider(this::updateNotificationDots); @@ -420,7 +419,7 @@ public class Launcher extends StatefulActivity implements Launche // For handling default keys setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); - setContentView(mLauncherView); + setContentView(getRootView()); getRootView().dispatchInsets(); // Listen for broadcasts @@ -519,12 +518,6 @@ public class Launcher extends StatefulActivity implements Launche super.onConfigurationChanged(newConfig); } - @Override - public void reapplyUi(boolean cancelCurrentAnimation) { - getRootView().dispatchInsets(); - super.reapplyUi(cancelCurrentAnimation); - } - @Override public void onIdpChanged(int changeFlags, InvariantDeviceProfile idp) { onIdpChanged(idp); @@ -581,11 +574,6 @@ public class Launcher extends StatefulActivity implements Launche return mStateManager; } - @Override - public T findViewById(int id) { - return mLauncherView.findViewById(id); - } - private LauncherCallbacks mLauncherCallbacks; /** @@ -1118,10 +1106,6 @@ public class Launcher extends StatefulActivity implements Launche mHotseat = findViewById(R.id.hotseat); mHotseat.setWorkspace(mWorkspace); - mLauncherView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); - // Setup the drag layer mDragLayer.setup(mDragController, mWorkspace); @@ -1334,11 +1318,6 @@ public class Launcher extends StatefulActivity implements Launche return mAllAppsController; } - @Override - public LauncherRootView getRootView() { - return (LauncherRootView) mLauncherView; - } - @Override public DragLayer getDragLayer() { return mDragLayer; diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java index 6951ff2804..51504ce6a4 100644 --- a/src/com/android/launcher3/LauncherRootView.java +++ b/src/com/android/launcher3/LauncherRootView.java @@ -10,6 +10,8 @@ import android.util.AttributeSet; import android.view.ViewDebug; import android.view.WindowInsets; +import com.android.launcher3.statemanager.StatefulActivity; + import java.util.Collections; import java.util.List; @@ -17,7 +19,7 @@ public class LauncherRootView extends InsettableFrameLayout { private final Rect mTempRect = new Rect(); - private final Launcher mLauncher; + private final StatefulActivity mActivity; @ViewDebug.ExportedProperty(category = "launcher") private static final List SYSTEM_GESTURE_EXCLUSION_RECT = @@ -31,17 +33,17 @@ public class LauncherRootView extends InsettableFrameLayout { public LauncherRootView(Context context, AttributeSet attrs) { super(context, attrs); - mLauncher = Launcher.getLauncher(context); + mActivity = StatefulActivity.fromContext(context); } private void handleSystemWindowInsets(Rect insets) { // Update device profile before notifying th children. - mLauncher.getDeviceProfile().updateInsets(insets); + mActivity.getDeviceProfile().updateInsets(insets); boolean resetState = !insets.equals(mInsets); setInsets(insets); if (resetState) { - mLauncher.getStateManager().reapplyState(true /* cancelCurrentAnimation */); + mActivity.getStateManager().reapplyState(true /* cancelCurrentAnimation */); } } @@ -63,7 +65,7 @@ public class LauncherRootView extends InsettableFrameLayout { } public void dispatchInsets() { - mLauncher.getDeviceProfile().updateInsets(mInsets); + mActivity.getDeviceProfile().updateInsets(mInsets); super.setInsets(mInsets); } diff --git a/src/com/android/launcher3/statemanager/StatefulActivity.java b/src/com/android/launcher3/statemanager/StatefulActivity.java index 0a1607cf04..dbe5f42e31 100644 --- a/src/com/android/launcher3/statemanager/StatefulActivity.java +++ b/src/com/android/launcher3/statemanager/StatefulActivity.java @@ -18,10 +18,13 @@ package com.android.launcher3.statemanager; import static com.android.launcher3.LauncherState.FLAG_NON_INTERACTIVE; import android.os.Handler; +import android.view.LayoutInflater; +import android.view.View; import androidx.annotation.CallSuper; import com.android.launcher3.BaseDraggingActivity; +import com.android.launcher3.LauncherRootView; import com.android.launcher3.Utilities; import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory; import com.android.launcher3.statemanager.StateManager.StateHandler; @@ -38,6 +41,8 @@ public abstract class StatefulActivity> private final Runnable mHandleDeferredResume = this::handleDeferredResume; private boolean mDeferredResumePending; + private LauncherRootView mRootView; + /** * Create handlers to control the property changes for this activity */ @@ -55,6 +60,23 @@ public abstract class StatefulActivity> */ public abstract StateManager getStateManager(); + protected void inflateRootView(int layoutId) { + mRootView = (LauncherRootView) LayoutInflater.from(this).inflate(layoutId, null); + mRootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + } + + @Override + public final LauncherRootView getRootView() { + return mRootView; + } + + @Override + public T findViewById(int id) { + return mRootView.findViewById(id); + } + /** * Called when transition to the state starts */ @@ -87,6 +109,7 @@ public abstract class StatefulActivity> * the transition if requested. */ public void reapplyUi(boolean cancelCurrentAnimation) { + getRootView().dispatchInsets(); getStateManager().reapplyState(cancelCurrentAnimation); }