From 2d6371aa34325e6a513c9172982679ac95258196 Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Mon, 10 Oct 2022 23:34:05 +0000 Subject: [PATCH] Implement overlay window for Taskbar EDU and All Apps. Having EDU in the same window as Taskbar causes it to be above All Apps and other system views such as the notification tray. This change refactors the existing All Apps window to accomodate more AFVs so that EDU can also exist in it. Demo: http://shortn/_Qcki3gwvf7 Test: Manual Fix: 232177330 Change-Id: I1bef31d798041a90a0c3e033e71be63898fa5fbc --- .../taskbar/LauncherTaskbarUIController.java | 7 - .../taskbar/TaskbarActivityContext.java | 6 +- .../launcher3/taskbar/TaskbarControllers.java | 7 +- .../taskbar/TaskbarEduController.java | 13 +- .../launcher3/taskbar/TaskbarEduView.java | 3 +- .../taskbar/TaskbarInsetsController.kt | 9 +- .../taskbar/TaskbarUIController.java | 6 +- .../allapps/TaskbarAllAppsContainerView.java | 7 +- .../allapps/TaskbarAllAppsContext.java | 248 ------------------ .../allapps/TaskbarAllAppsController.java | 175 ++---------- .../allapps/TaskbarAllAppsSlideInView.java | 3 +- .../allapps/TaskbarAllAppsViewController.java | 7 +- .../overlay/TaskbarOverlayContext.java | 146 +++++++++++ .../overlay/TaskbarOverlayController.java | 197 ++++++++++++++ .../overlay/TaskbarOverlayDragLayer.java | 126 +++++++++ .../quickstep/BaseActivityInterface.java | 3 +- .../quickstep/LauncherActivityInterface.java | 4 - .../launcher3/AbstractFloatingView.java | 1 + 18 files changed, 530 insertions(+), 438 deletions(-) delete mode 100644 quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java create mode 100644 quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java create mode 100644 quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java create mode 100644 quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 5178968b4a..566d126ba5 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -276,13 +276,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController { && !mLauncher.getOnboardingPrefs().getBoolean(OnboardingPrefs.TASKBAR_EDU_SEEN); } - /** - * Manually ends the taskbar education flow. - */ - public void hideEdu() { - mControllers.taskbarEduController.hideEdu(); - } - @Override public void onTaskbarIconLaunched(ItemInfo item) { InstanceId instanceId = new InstanceIdSequence().newInstanceId(); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index c69dc0d8c4..69778596a1 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -76,6 +76,7 @@ import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.popup.PopupDataProvider; import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController; +import com.android.launcher3.taskbar.overlay.TaskbarOverlayController; import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.touch.ItemClickHandler; @@ -206,7 +207,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext { new TaskbarAutohideSuspendController(this), new TaskbarPopupController(this), new TaskbarForceVisibleImmersiveController(this), - new TaskbarAllAppsController(this, dp), + new TaskbarOverlayController(this, dp), + new TaskbarAllAppsController(), new TaskbarInsetsController(this), new VoiceInteractionWindowController(this), isDesktopMode @@ -238,7 +240,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { /** Updates {@link DeviceProfile} instances for any Taskbar windows. */ public void updateDeviceProfile(DeviceProfile dp, NavigationMode navMode) { mNavMode = navMode; - mControllers.taskbarAllAppsController.updateDeviceProfile(dp); + mControllers.taskbarOverlayController.updateDeviceProfile(dp); mDeviceProfile = dp.copy(this); updateIconSize(getResources()); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java index 707023b2ec..9c2d21ef8c 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java @@ -22,6 +22,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController; +import com.android.launcher3.taskbar.overlay.TaskbarOverlayController; import com.android.systemui.shared.rotation.RotationButtonController; import java.io.PrintWriter; @@ -54,6 +55,7 @@ public class TaskbarControllers { public final TaskbarInsetsController taskbarInsetsController; public final VoiceInteractionWindowController voiceInteractionWindowController; public final TaskbarRecentAppsController taskbarRecentAppsController; + public final TaskbarOverlayController taskbarOverlayController; @Nullable private LoggableTaskbarController[] mControllersToLog = null; @@ -81,6 +83,7 @@ public class TaskbarControllers { TaskbarAutohideSuspendController taskbarAutoHideSuspendController, TaskbarPopupController taskbarPopupController, TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController, + TaskbarOverlayController taskbarOverlayController, TaskbarAllAppsController taskbarAllAppsController, TaskbarInsetsController taskbarInsetsController, VoiceInteractionWindowController voiceInteractionWindowController, @@ -101,6 +104,7 @@ public class TaskbarControllers { this.taskbarAutohideSuspendController = taskbarAutoHideSuspendController; this.taskbarPopupController = taskbarPopupController; this.taskbarForceVisibleImmersiveController = taskbarForceVisibleImmersiveController; + this.taskbarOverlayController = taskbarOverlayController; this.taskbarAllAppsController = taskbarAllAppsController; this.taskbarInsetsController = taskbarInsetsController; this.voiceInteractionWindowController = voiceInteractionWindowController; @@ -129,6 +133,7 @@ public class TaskbarControllers { taskbarEduController.init(this); taskbarPopupController.init(this); taskbarForceVisibleImmersiveController.init(this); + taskbarOverlayController.init(this); taskbarAllAppsController.init(this, sharedState.allAppsVisible); navButtonController.init(this); taskbarInsetsController.init(this); @@ -179,7 +184,7 @@ public class TaskbarControllers { taskbarAutohideSuspendController.onDestroy(); taskbarPopupController.onDestroy(); taskbarForceVisibleImmersiveController.onDestroy(); - taskbarAllAppsController.onDestroy(); + taskbarOverlayController.onDestroy(); navButtonController.onDestroy(); taskbarInsetsController.onDestroy(); voiceInteractionWindowController.onDestroy(); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java index 95b93febe0..16cc0ac0af 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java @@ -35,6 +35,7 @@ import android.view.View; import com.android.launcher3.R; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.model.data.ItemInfo; +import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext; import com.android.launcher3.uioverrides.PredictedAppIcon; import java.io.PrintWriter; @@ -87,8 +88,10 @@ public class TaskbarEduController implements TaskbarControllers.LoggableTaskbarC void showEdu() { mActivity.setTaskbarWindowFullscreen(true); mActivity.getDragLayer().post(() -> { - mTaskbarEduView = (TaskbarEduView) mActivity.getLayoutInflater().inflate( - R.layout.taskbar_edu, mActivity.getDragLayer(), false); + TaskbarOverlayContext overlayContext = + mControllers.taskbarOverlayController.requestWindow(); + mTaskbarEduView = (TaskbarEduView) overlayContext.getLayoutInflater().inflate( + R.layout.taskbar_edu, overlayContext.getDragLayer(), false); mTaskbarEduView.init(new TaskbarEduCallbacks()); mControllers.navbarButtonsViewController.setSlideInViewVisible(true); mTaskbarEduView.setOnCloseBeginListener( @@ -99,12 +102,6 @@ public class TaskbarEduController implements TaskbarControllers.LoggableTaskbarC }); } - void hideEdu() { - if (mTaskbarEduView != null) { - mTaskbarEduView.close(true /* animate */); - } - } - /** * Starts the given animation, ending the previous animation first if it's still playing. */ diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java index c0cbbd697d..bb87f48a92 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java @@ -28,10 +28,11 @@ import android.widget.Button; import com.android.launcher3.Insettable; import com.android.launcher3.R; +import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext; import com.android.launcher3.views.AbstractSlideInView; /** Education view about the Taskbar. */ -public class TaskbarEduView extends AbstractSlideInView +public class TaskbarEduView extends AbstractSlideInView implements Insettable { private static final int DEFAULT_OPEN_DURATION = 500; diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt index 079e8a1f2d..8ad1968719 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt @@ -29,7 +29,7 @@ import android.view.WindowManager import android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD import android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION import com.android.launcher3.AbstractFloatingView -import com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_ALL_APPS +import com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_OVERLAY_PROXY import com.android.launcher3.DeviceProfile import com.android.launcher3.anim.AlphaUpdateListener import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController @@ -143,8 +143,11 @@ class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTask } else if (controllers.taskbarDragController.isSystemDragInProgress) { // Let touches pass through us. insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION) - } else if (AbstractFloatingView.hasOpenView(context, TYPE_TASKBAR_ALL_APPS)) { - // Let touches pass through us. + } else if (AbstractFloatingView.hasOpenView(context, TYPE_TASKBAR_OVERLAY_PROXY)) { + // Let touches pass through us if icons are hidden. + if (controllers.taskbarViewController.areIconsVisible()) { + insetsInfo.touchableRegion.set(touchableRegion) + } insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION) } else if (controllers.taskbarViewController.areIconsVisible() || AbstractFloatingView.hasOpenView(context, AbstractFloatingView.TYPE_ALL) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java index 114bfecb6e..49dba95151 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java @@ -80,10 +80,10 @@ public class TaskbarUIController { } /** - * Manually closes the all apps window. + * Manually closes the overlay window. */ - public void hideAllApps() { - mControllers.taskbarAllAppsController.hide(); + public void hideOverlayWindow() { + mControllers.taskbarOverlayController.hideWindow(); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java index 51fa4d9f3a..ce51f7dc71 100644 --- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java +++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java @@ -24,10 +24,11 @@ import com.android.launcher3.allapps.AllAppsGridAdapter; import com.android.launcher3.allapps.AlphabeticalAppsList; import com.android.launcher3.allapps.BaseAdapterProvider; import com.android.launcher3.allapps.BaseAllAppsAdapter; +import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext; /** All apps container accessible from taskbar. */ public class TaskbarAllAppsContainerView extends - ActivityAllAppsContainerView { + ActivityAllAppsContainerView { public TaskbarAllAppsContainerView(Context context, AttributeSet attrs) { this(context, attrs, 0); @@ -44,8 +45,8 @@ public class TaskbarAllAppsContainerView extends } @Override - protected BaseAllAppsAdapter createAdapter( - AlphabeticalAppsList appsList, + protected BaseAllAppsAdapter createAdapter( + AlphabeticalAppsList appsList, BaseAdapterProvider[] adapterProviders) { return new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), appsList, adapterProviders); diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java deleted file mode 100644 index 0372f67b75..0000000000 --- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2022 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.launcher3.taskbar.allapps; - -import static android.view.KeyEvent.ACTION_UP; -import static android.view.KeyEvent.KEYCODE_BACK; -import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; -import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; - -import android.content.Context; -import android.graphics.Insets; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewTreeObserver; -import android.view.ViewTreeObserver.OnComputeInternalInsetsListener; -import android.view.WindowInsets; - -import com.android.launcher3.AbstractFloatingView; -import com.android.launcher3.DeviceProfile; -import com.android.launcher3.R; -import com.android.launcher3.Utilities; -import com.android.launcher3.allapps.ActivityAllAppsContainerView; -import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider; -import com.android.launcher3.allapps.search.SearchAdapterProvider; -import com.android.launcher3.dot.DotInfo; -import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.popup.PopupDataProvider; -import com.android.launcher3.taskbar.BaseTaskbarContext; -import com.android.launcher3.taskbar.TaskbarActivityContext; -import com.android.launcher3.taskbar.TaskbarControllers; -import com.android.launcher3.taskbar.TaskbarDragController; -import com.android.launcher3.taskbar.TaskbarStashController; -import com.android.launcher3.testing.TestLogging; -import com.android.launcher3.testing.shared.TestProtocol; -import com.android.launcher3.util.OnboardingPrefs; -import com.android.launcher3.util.TouchController; -import com.android.launcher3.views.BaseDragLayer; - -/** - * Window context for the taskbar all apps overlay. - *

- * All apps has its own window and needs a window context. Some properties are delegated to the - * {@link TaskbarActivityContext} such as {@link DeviceProfile} and {@link PopupDataProvider}. - */ -class TaskbarAllAppsContext extends BaseTaskbarContext { - private final TaskbarActivityContext mTaskbarContext; - private final OnboardingPrefs mOnboardingPrefs; - - private final TaskbarAllAppsController mWindowController; - private final TaskbarAllAppsViewController mAllAppsViewController; - private final TaskbarDragController mDragController; - private final TaskbarAllAppsDragLayer mDragLayer; - private final TaskbarAllAppsContainerView mAppsView; - - // We automatically stash taskbar when all apps is opened in gesture navigation mode. - private final boolean mWillTaskbarBeVisuallyStashed; - private final int mStashedTaskbarHeight; - - TaskbarAllAppsContext( - TaskbarActivityContext taskbarContext, - TaskbarAllAppsController windowController, - TaskbarControllers taskbarControllers) { - super(taskbarContext.createWindowContext(TYPE_APPLICATION_OVERLAY, null)); - mTaskbarContext = taskbarContext; - mWindowController = windowController; - mDragController = new TaskbarDragController(this); - mOnboardingPrefs = new OnboardingPrefs<>(this, Utilities.getPrefs(this)); - - mDragLayer = new TaskbarAllAppsDragLayer(this); - TaskbarAllAppsSlideInView slideInView = (TaskbarAllAppsSlideInView) mLayoutInflater.inflate( - R.layout.taskbar_all_apps, mDragLayer, false); - mAllAppsViewController = new TaskbarAllAppsViewController( - this, - slideInView, - windowController, - taskbarControllers); - mAppsView = slideInView.getAppsView(); - - TaskbarStashController taskbarStashController = taskbarControllers.taskbarStashController; - mWillTaskbarBeVisuallyStashed = taskbarStashController.supportsVisualStashing(); - mStashedTaskbarHeight = taskbarStashController.getStashedHeight(); - } - - TaskbarAllAppsViewController getAllAppsViewController() { - return mAllAppsViewController; - } - - @Override - public DeviceProfile getDeviceProfile() { - return mWindowController.getDeviceProfile(); - } - - @Override - public TaskbarDragController getDragController() { - return mDragController; - } - - @Override - public TaskbarAllAppsDragLayer getDragLayer() { - return mDragLayer; - } - - @Override - public TaskbarAllAppsContainerView getAppsView() { - return mAppsView; - } - - @Override - public OnboardingPrefs getOnboardingPrefs() { - return mOnboardingPrefs; - } - - @Override - public boolean isBindingItems() { - return mTaskbarContext.isBindingItems(); - } - - @Override - public View.OnClickListener getItemOnClickListener() { - return mTaskbarContext.getItemOnClickListener(); - } - - @Override - public PopupDataProvider getPopupDataProvider() { - return mTaskbarContext.getPopupDataProvider(); - } - - @Override - public DotInfo getDotInfoForItem(ItemInfo info) { - return mTaskbarContext.getDotInfoForItem(info); - } - - @Override - public void onDragStart() {} - - @Override - public void onDragEnd() { - mWindowController.maybeCloseWindow(); - } - - @Override - public void onPopupVisibilityChanged(boolean isVisible) {} - - @Override - public SearchAdapterProvider createSearchAdapterProvider( - ActivityAllAppsContainerView appsView) { - return new DefaultSearchAdapterProvider(this); - } - - /** Root drag layer for this context. */ - private static class TaskbarAllAppsDragLayer extends - BaseDragLayer implements OnComputeInternalInsetsListener { - - private TaskbarAllAppsDragLayer(Context context) { - super(context, null, 1); - setClipChildren(false); - recreateControllers(); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - getViewTreeObserver().addOnComputeInternalInsetsListener(this); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - getViewTreeObserver().removeOnComputeInternalInsetsListener(this); - } - - @Override - public void recreateControllers() { - mControllers = new TouchController[]{mActivity.mDragController}; - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev); - return super.dispatchTouchEvent(ev); - } - - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) { - AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity); - if (topView != null && topView.onBackPressed()) { - return true; - } - } - return super.dispatchKeyEvent(event); - } - - @Override - public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo inoutInfo) { - if (mActivity.mDragController.isSystemDragInProgress()) { - inoutInfo.touchableRegion.setEmpty(); - inoutInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); - } - } - - @Override - public WindowInsets onApplyWindowInsets(WindowInsets insets) { - return updateInsetsDueToStashing(insets); - } - - /** - * Taskbar automatically stashes when opening all apps, but we don't report the insets as - * changing to avoid moving the underlying app. But internally, the apps view should still - * layout according to the stashed insets rather than the unstashed insets. So this method - * does two things: - * 1) Sets navigationBars bottom inset to stashedHeight. - * 2) Sets tappableInsets bottom inset to 0. - */ - private WindowInsets updateInsetsDueToStashing(WindowInsets oldInsets) { - if (!mActivity.mWillTaskbarBeVisuallyStashed) { - return oldInsets; - } - WindowInsets.Builder updatedInsetsBuilder = new WindowInsets.Builder(oldInsets); - - Insets oldNavInsets = oldInsets.getInsets(WindowInsets.Type.navigationBars()); - Insets newNavInsets = Insets.of(oldNavInsets.left, oldNavInsets.top, oldNavInsets.right, - mActivity.mStashedTaskbarHeight); - updatedInsetsBuilder.setInsets(WindowInsets.Type.navigationBars(), newNavInsets); - - Insets oldTappableInsets = oldInsets.getInsets(WindowInsets.Type.tappableElement()); - Insets newTappableInsets = Insets.of(oldTappableInsets.left, oldTappableInsets.top, - oldTappableInsets.right, 0); - updatedInsetsBuilder.setInsets(WindowInsets.Type.tappableElement(), newTappableInsets); - - return updatedInsetsBuilder.build(); - } - } -} diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java index 1671a0f1d7..ea37944d69 100644 --- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java +++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java @@ -15,34 +15,17 @@ */ package com.android.launcher3.taskbar.allapps; -import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; -import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; - -import static com.android.launcher3.AbstractFloatingView.TYPE_ALL; -import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE; - -import android.content.Context; -import android.graphics.PixelFormat; -import android.view.Gravity; -import android.view.MotionEvent; -import android.view.WindowManager; -import android.view.WindowManager.LayoutParams; - import androidx.annotation.Nullable; -import com.android.launcher3.AbstractFloatingView; -import com.android.launcher3.DeviceProfile; +import com.android.launcher3.R; import com.android.launcher3.appprediction.PredictionRowView; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.taskbar.TaskbarActivityContext; import com.android.launcher3.taskbar.TaskbarControllers; -import com.android.systemui.shared.system.TaskStackChangeListener; -import com.android.systemui.shared.system.TaskStackChangeListeners; +import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext; import java.util.List; -import java.util.Optional; /** * Handles the all apps overlay window initialization, updates, and its data. @@ -57,36 +40,14 @@ import java.util.Optional; */ public final class TaskbarAllAppsController { - private static final String WINDOW_TITLE = "Taskbar All Apps"; - - private final TaskbarActivityContext mTaskbarContext; - private final TaskbarAllAppsProxyView mProxyView; - private final LayoutParams mLayoutParams; - - private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() { - @Override - public void onTaskStackChanged() { - mProxyView.close(false); - } - }; - - private DeviceProfile mDeviceProfile; private TaskbarControllers mControllers; - /** Window context for all apps if it is open. */ - private @Nullable TaskbarAllAppsContext mAllAppsContext; + private @Nullable TaskbarAllAppsContainerView mAppsView; // Application data models. private AppInfo[] mApps; private int mAppsModelFlags; private List mPredictedApps; - public TaskbarAllAppsController(TaskbarActivityContext context, DeviceProfile dp) { - mDeviceProfile = dp; - mTaskbarContext = context; - mProxyView = new TaskbarAllAppsProxyView(mTaskbarContext); - mLayoutParams = createLayoutParams(); - } - /** Initialize the controller. */ public void init(TaskbarControllers controllers, boolean allAppsVisible) { if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) { @@ -111,8 +72,8 @@ public final class TaskbarAllAppsController { mApps = apps; mAppsModelFlags = flags; - if (mAllAppsContext != null) { - mAllAppsContext.getAppsView().getAppsStore().setApps(mApps, mAppsModelFlags); + if (mAppsView != null) { + mAppsView.getAppsStore().setApps(mApps, mAppsModelFlags); } } @@ -123,8 +84,8 @@ public final class TaskbarAllAppsController { } mPredictedApps = predictedApps; - if (mAllAppsContext != null) { - mAllAppsContext.getAppsView().getFloatingHeaderView() + if (mAppsView != null) { + mAppsView.getFloatingHeaderView() .findFixedRowByType(PredictionRowView.class) .setPredictedApps(mPredictedApps); } @@ -136,120 +97,30 @@ public final class TaskbarAllAppsController { } private void show(boolean animate) { - if (mProxyView.isOpen()) { + if (mAppsView != null) { return; } - mProxyView.show(); // mControllers and getSharedState should never be null here. Do not handle null-pointer // to catch invalid states. mControllers.getSharedState().allAppsVisible = true; - mAllAppsContext = new TaskbarAllAppsContext(mTaskbarContext, this, mControllers); - mAllAppsContext.getDragController().init(mControllers); - TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener); - Optional.ofNullable(mAllAppsContext.getSystemService(WindowManager.class)) - .ifPresent(m -> m.addView(mAllAppsContext.getDragLayer(), mLayoutParams)); + TaskbarOverlayContext overlayContext = + mControllers.taskbarOverlayController.requestWindow(); + TaskbarAllAppsSlideInView slideInView = + (TaskbarAllAppsSlideInView) overlayContext.getLayoutInflater().inflate( + R.layout.taskbar_all_apps, overlayContext.getDragLayer(), false); + slideInView.addOnCloseListener(() -> { + mControllers.getSharedState().allAppsVisible = false; + mAppsView = null; + }); + TaskbarAllAppsViewController viewController = new TaskbarAllAppsViewController( + overlayContext, slideInView, mControllers); - mAllAppsContext.getAppsView().getAppsStore().setApps(mApps, mAppsModelFlags); - mAllAppsContext.getAppsView().getFloatingHeaderView() + viewController.show(animate); + mAppsView = overlayContext.getAppsView(); + mAppsView.getAppsStore().setApps(mApps, mAppsModelFlags); + mAppsView.getFloatingHeaderView() .findFixedRowByType(PredictionRowView.class) .setPredictedApps(mPredictedApps); - mAllAppsContext.getAllAppsViewController().show(animate); - } - - /** Closes the {@link TaskbarAllAppsContainerView}. */ - public void hide() { - mProxyView.close(true); - } - - /** - * Removes the all apps window from the hierarchy, if all floating views are closed and there is - * no system drag operation in progress. - *

- * This method should be called after an exit animation finishes, if applicable. - */ - void maybeCloseWindow() { - if (mAllAppsContext != null && (AbstractFloatingView.hasOpenView(mAllAppsContext, TYPE_ALL) - || mAllAppsContext.getDragController().isSystemDragInProgress())) { - return; - } - mProxyView.close(false); - // mControllers and getSharedState should never be null here. Do not handle null-pointer - // to catch invalid states. - mControllers.getSharedState().allAppsVisible = false; - onDestroy(); - } - - /** Destroys the controller and any All Apps window if present. */ - public void onDestroy() { - TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener); - Optional.ofNullable(mAllAppsContext) - .map(c -> c.getSystemService(WindowManager.class)) - .ifPresent(m -> m.removeViewImmediate(mAllAppsContext.getDragLayer())); - mAllAppsContext = null; - } - - /** Updates {@link DeviceProfile} instance for Taskbar's All Apps window. */ - public void updateDeviceProfile(DeviceProfile dp) { - mDeviceProfile = dp; - Optional.ofNullable(mAllAppsContext).ifPresent(c -> { - AbstractFloatingView.closeAllOpenViewsExcept(c, false, TYPE_REBIND_SAFE); - c.dispatchDeviceProfileChanged(); - }); - } - - DeviceProfile getDeviceProfile() { - return mDeviceProfile; - } - - private LayoutParams createLayoutParams() { - LayoutParams layoutParams = new LayoutParams( - TYPE_APPLICATION_OVERLAY, - WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, - PixelFormat.TRANSLUCENT); - layoutParams.setTitle(WINDOW_TITLE); - layoutParams.gravity = Gravity.BOTTOM; - layoutParams.packageName = mTaskbarContext.getPackageName(); - layoutParams.setFitInsetsTypes(0); // Handled by container view. - layoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; - layoutParams.setSystemApplicationOverlay(true); - return layoutParams; - } - - /** - * Proxy view connecting taskbar drag layer to the all apps window. - *

- * The all apps view is in a separate window and has its own drag layer, but this proxy lets it - * behave as though its in the taskbar drag layer. For instance, when the taskbar closes all - * {@link AbstractFloatingView} instances, the all apps window will also close. - */ - private class TaskbarAllAppsProxyView extends AbstractFloatingView { - - private TaskbarAllAppsProxyView(Context context) { - super(context, null); - } - - private void show() { - mIsOpen = true; - mTaskbarContext.getDragLayer().addView(this); - } - - @Override - protected void handleClose(boolean animate) { - mTaskbarContext.getDragLayer().removeView(this); - Optional.ofNullable(mAllAppsContext) - .map(TaskbarAllAppsContext::getAllAppsViewController) - .ifPresent(v -> v.close(animate)); - } - - @Override - protected boolean isOfType(int type) { - return (type & TYPE_TASKBAR_ALL_APPS) != 0; - } - - @Override - public boolean onControllerInterceptTouchEvent(MotionEvent ev) { - return false; - } } } diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java index 9d48c8de89..c8bfc2aed0 100644 --- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java +++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java @@ -28,10 +28,11 @@ import android.view.animation.Interpolator; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; import com.android.launcher3.R; +import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext; import com.android.launcher3.views.AbstractSlideInView; /** Wrapper for taskbar all apps with slide-in behavior. */ -public class TaskbarAllAppsSlideInView extends AbstractSlideInView +public class TaskbarAllAppsSlideInView extends AbstractSlideInView implements Insettable, DeviceProfile.OnDeviceProfileChangeListener { private TaskbarAllAppsContainerView mAppsView; private float mShiftRange; diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java index 128fa5e81e..54392b21c0 100644 --- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java @@ -25,6 +25,7 @@ import com.android.launcher3.appprediction.PredictionRowView; import com.android.launcher3.taskbar.NavbarButtonsViewController; import com.android.launcher3.taskbar.TaskbarControllers; import com.android.launcher3.taskbar.TaskbarStashController; +import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext; /** * Handles the {@link TaskbarAllAppsContainerView} behavior and synchronizes its transitions with @@ -32,16 +33,15 @@ import com.android.launcher3.taskbar.TaskbarStashController; */ final class TaskbarAllAppsViewController { - private final TaskbarAllAppsContext mContext; + private final TaskbarOverlayContext mContext; private final TaskbarAllAppsSlideInView mSlideInView; private final TaskbarAllAppsContainerView mAppsView; private final TaskbarStashController mTaskbarStashController; private final NavbarButtonsViewController mNavbarButtonsViewController; TaskbarAllAppsViewController( - TaskbarAllAppsContext context, + TaskbarOverlayContext context, TaskbarAllAppsSlideInView slideInView, - TaskbarAllAppsController windowController, TaskbarControllers taskbarControllers) { mContext = context; @@ -53,7 +53,6 @@ final class TaskbarAllAppsViewController { setUpIconLongClick(); setUpAppDivider(); setUpTaskbarStashing(); - mSlideInView.addOnCloseListener(windowController::maybeCloseWindow); } /** Starts the {@link TaskbarAllAppsSlideInView} enter transition. */ diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java new file mode 100644 index 0000000000..5701de0e9c --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2022 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.launcher3.taskbar.overlay; + +import android.content.Context; +import android.view.View; + +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.R; +import com.android.launcher3.Utilities; +import com.android.launcher3.allapps.ActivityAllAppsContainerView; +import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider; +import com.android.launcher3.allapps.search.SearchAdapterProvider; +import com.android.launcher3.dot.DotInfo; +import com.android.launcher3.model.data.ItemInfo; +import com.android.launcher3.popup.PopupDataProvider; +import com.android.launcher3.taskbar.BaseTaskbarContext; +import com.android.launcher3.taskbar.TaskbarActivityContext; +import com.android.launcher3.taskbar.TaskbarControllers; +import com.android.launcher3.taskbar.TaskbarDragController; +import com.android.launcher3.taskbar.TaskbarStashController; +import com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView; +import com.android.launcher3.util.OnboardingPrefs; + +/** + * Window context for the taskbar overlays such as All Apps and EDU. + *

+ * Overlays have their own window and need a window context. Some properties are delegated to the + * {@link TaskbarActivityContext} such as {@link PopupDataProvider}. + */ +public class TaskbarOverlayContext extends BaseTaskbarContext { + private final TaskbarActivityContext mTaskbarContext; + private final OnboardingPrefs mOnboardingPrefs; + + private final TaskbarOverlayController mOverlayController; + private final TaskbarDragController mDragController; + private final TaskbarOverlayDragLayer mDragLayer; + + // We automatically stash taskbar when All Apps is opened in gesture navigation mode. + private final boolean mWillTaskbarBeVisuallyStashed; + private final int mStashedTaskbarHeight; + + public TaskbarOverlayContext( + Context windowContext, + TaskbarActivityContext taskbarContext, + TaskbarControllers controllers) { + super(windowContext); + mTaskbarContext = taskbarContext; + mOverlayController = controllers.taskbarOverlayController; + mDragController = new TaskbarDragController(this); + mDragController.init(controllers); + mOnboardingPrefs = new OnboardingPrefs<>(this, Utilities.getPrefs(this)); + mDragLayer = new TaskbarOverlayDragLayer(this); + + TaskbarStashController taskbarStashController = controllers.taskbarStashController; + mWillTaskbarBeVisuallyStashed = taskbarStashController.supportsVisualStashing(); + mStashedTaskbarHeight = taskbarStashController.getStashedHeight(); + } + + boolean willTaskbarBeVisuallyStashed() { + return mWillTaskbarBeVisuallyStashed; + } + + int getStashedTaskbarHeight() { + return mStashedTaskbarHeight; + } + + public TaskbarOverlayController getOverlayController() { + return mOverlayController; + } + + @Override + public DeviceProfile getDeviceProfile() { + return mOverlayController.getDeviceProfile(); + } + + @Override + public TaskbarDragController getDragController() { + return mDragController; + } + + @Override + public TaskbarOverlayDragLayer getDragLayer() { + return mDragLayer; + } + + @Override + public TaskbarAllAppsContainerView getAppsView() { + return mDragLayer.findViewById(R.id.apps_view); + } + + @Override + public OnboardingPrefs getOnboardingPrefs() { + return mOnboardingPrefs; + } + + @Override + public boolean isBindingItems() { + return mTaskbarContext.isBindingItems(); + } + + @Override + public View.OnClickListener getItemOnClickListener() { + return mTaskbarContext.getItemOnClickListener(); + } + + @Override + public PopupDataProvider getPopupDataProvider() { + return mTaskbarContext.getPopupDataProvider(); + } + + @Override + public DotInfo getDotInfoForItem(ItemInfo info) { + return mTaskbarContext.getDotInfoForItem(info); + } + + @Override + public void onDragStart() {} + + @Override + public void onDragEnd() { + mOverlayController.maybeCloseWindow(); + } + + @Override + public void onPopupVisibilityChanged(boolean isVisible) {} + + @Override + public SearchAdapterProvider createSearchAdapterProvider( + ActivityAllAppsContainerView appsView) { + return new DefaultSearchAdapterProvider(this); + } +} diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java new file mode 100644 index 0000000000..0574058dcc --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2022 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.launcher3.taskbar.overlay; + +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; + +import static com.android.launcher3.AbstractFloatingView.TYPE_ALL; +import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.PixelFormat; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.WindowManager; +import android.view.WindowManager.LayoutParams; + +import androidx.annotation.Nullable; + +import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.taskbar.TaskbarActivityContext; +import com.android.launcher3.taskbar.TaskbarControllers; +import com.android.systemui.shared.system.TaskStackChangeListener; +import com.android.systemui.shared.system.TaskStackChangeListeners; + +import java.util.Optional; + +/** + * Handles the Taskbar overlay window lifecycle. + *

+ * Overlays need to be inflated in a separate window so that have the correct hierarchy. For + * instance, they need to be below the notification tray. If there are multiple overlays open, the + * same window is used. + */ +public final class TaskbarOverlayController { + + private static final String WINDOW_TITLE = "Taskbar Overlay"; + + private final TaskbarActivityContext mTaskbarContext; + private final Context mWindowContext; + private final TaskbarOverlayProxyView mProxyView; + private final LayoutParams mLayoutParams; + + private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() { + @Override + public void onTaskStackChanged() { + mProxyView.close(false); + } + }; + + private DeviceProfile mDeviceProfile; + private @Nullable TaskbarOverlayContext mOverlayContext; + private TaskbarControllers mControllers; // Initialized in init. + + public TaskbarOverlayController( + TaskbarActivityContext taskbarContext, DeviceProfile deviceProfile) { + mTaskbarContext = taskbarContext; + mWindowContext = mTaskbarContext.createWindowContext(TYPE_APPLICATION_OVERLAY, null); + mProxyView = new TaskbarOverlayProxyView(); + mLayoutParams = createLayoutParams(); + mDeviceProfile = deviceProfile; + } + + /** Initialize the controller. */ + public void init(TaskbarControllers controllers) { + mControllers = controllers; + } + + /** + * Creates a window for Taskbar overlays, if it does not already exist. Returns the window + * context for the current overlay window. + */ + public TaskbarOverlayContext requestWindow() { + if (mOverlayContext == null) { + mOverlayContext = new TaskbarOverlayContext( + mWindowContext, mTaskbarContext, mControllers); + } + + if (!mProxyView.isOpen()) { + mProxyView.show(); + Optional.ofNullable(mOverlayContext.getSystemService(WindowManager.class)) + .ifPresent(m -> m.addView(mOverlayContext.getDragLayer(), mLayoutParams)); + TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener); + } + + return mOverlayContext; + } + + /** Hides the current overlay window with animation. */ + public void hideWindow() { + mProxyView.close(true); + } + + /** + * Removes the overlay window from the hierarchy, if all floating views are closed and there is + * no system drag operation in progress. + *

+ * This method should be called after an exit animation finishes, if applicable. + */ + @SuppressLint("WrongConstant") + void maybeCloseWindow() { + if (mOverlayContext != null && (AbstractFloatingView.hasOpenView(mOverlayContext, TYPE_ALL) + || mOverlayContext.getDragController().isSystemDragInProgress())) { + return; + } + mProxyView.close(false); + onDestroy(); + } + + /** Destroys the controller and any overlay window if present. */ + public void onDestroy() { + TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener); + Optional.ofNullable(mOverlayContext) + .map(c -> c.getSystemService(WindowManager.class)) + .ifPresent(m -> m.removeViewImmediate(mOverlayContext.getDragLayer())); + mOverlayContext = null; + } + + /** The current device profile for the overlay window. */ + public DeviceProfile getDeviceProfile() { + return mDeviceProfile; + } + + /** Updates {@link DeviceProfile} instance for Taskbar's overlay window. */ + public void updateDeviceProfile(DeviceProfile dp) { + mDeviceProfile = dp; + Optional.ofNullable(mOverlayContext).ifPresent(c -> { + AbstractFloatingView.closeAllOpenViewsExcept(c, false, TYPE_REBIND_SAFE); + c.dispatchDeviceProfileChanged(); + }); + } + + @SuppressLint("WrongConstant") + private LayoutParams createLayoutParams() { + LayoutParams layoutParams = new LayoutParams( + TYPE_APPLICATION_OVERLAY, + LayoutParams.FLAG_SPLIT_TOUCH, + PixelFormat.TRANSLUCENT); + layoutParams.setTitle(WINDOW_TITLE); + layoutParams.gravity = Gravity.BOTTOM; + layoutParams.packageName = mTaskbarContext.getPackageName(); + layoutParams.setFitInsetsTypes(0); // Handled by container view. + layoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + layoutParams.setSystemApplicationOverlay(true); + return layoutParams; + } + + /** + * Proxy view connecting taskbar drag layer to the overlay window. + * + * Overlays are in a separate window and has its own drag layer, but this proxy lets its views + * behave as though they are in the taskbar drag layer. For instance, when the taskbar closes + * all {@link AbstractFloatingView} instances, the overlay window will also close. + */ + private class TaskbarOverlayProxyView extends AbstractFloatingView { + + private TaskbarOverlayProxyView() { + super(mTaskbarContext, null); + } + + private void show() { + mIsOpen = true; + mTaskbarContext.getDragLayer().addView(this); + } + + @Override + protected void handleClose(boolean animate) { + mTaskbarContext.getDragLayer().removeView(this); + Optional.ofNullable(mOverlayContext).ifPresent(c -> closeAllOpenViews(c, animate)); + } + + @Override + protected boolean isOfType(int type) { + return (type & TYPE_TASKBAR_OVERLAY_PROXY) != 0; + } + + @Override + public boolean onControllerInterceptTouchEvent(MotionEvent ev) { + return false; + } + } +} diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java new file mode 100644 index 0000000000..044afd6725 --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2022 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.launcher3.taskbar.overlay; + +import static android.view.KeyEvent.ACTION_UP; +import static android.view.KeyEvent.KEYCODE_BACK; +import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; + +import android.content.Context; +import android.graphics.Insets; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewTreeObserver; +import android.view.WindowInsets; + +import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.testing.TestLogging; +import com.android.launcher3.testing.shared.TestProtocol; +import com.android.launcher3.util.TouchController; +import com.android.launcher3.views.BaseDragLayer; + +/** Root drag layer for the Taskbar overlay window. */ +public class TaskbarOverlayDragLayer extends + BaseDragLayer implements + ViewTreeObserver.OnComputeInternalInsetsListener { + + TaskbarOverlayDragLayer(Context context) { + super(context, null, 1); + setClipChildren(false); + recreateControllers(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + getViewTreeObserver().addOnComputeInternalInsetsListener(this); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + getViewTreeObserver().removeOnComputeInternalInsetsListener(this); + } + + @Override + public void recreateControllers() { + mControllers = new TouchController[]{mActivity.getDragController()}; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev); + return super.dispatchTouchEvent(ev); + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) { + AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity); + if (topView != null && topView.onBackPressed()) { + return true; + } + } + return super.dispatchKeyEvent(event); + } + + @Override + public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo inoutInfo) { + if (mActivity.getDragController().isSystemDragInProgress()) { + inoutInfo.touchableRegion.setEmpty(); + inoutInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); + } + } + + @Override + public WindowInsets onApplyWindowInsets(WindowInsets insets) { + return updateInsetsDueToStashing(insets); + } + + @Override + public void onViewRemoved(View child) { + super.onViewRemoved(child); + mActivity.getOverlayController().maybeCloseWindow(); + } + + /** + * Taskbar automatically stashes when opening all apps, but we don't report the insets as + * changing to avoid moving the underlying app. But internally, the apps view should still + * layout according to the stashed insets rather than the unstashed insets. So this method + * does two things: + * 1) Sets navigationBars bottom inset to stashedHeight. + * 2) Sets tappableInsets bottom inset to 0. + */ + private WindowInsets updateInsetsDueToStashing(WindowInsets oldInsets) { + if (!mActivity.willTaskbarBeVisuallyStashed()) { + return oldInsets; + } + WindowInsets.Builder updatedInsetsBuilder = new WindowInsets.Builder(oldInsets); + + Insets oldNavInsets = oldInsets.getInsets(WindowInsets.Type.navigationBars()); + Insets newNavInsets = Insets.of(oldNavInsets.left, oldNavInsets.top, oldNavInsets.right, + mActivity.getStashedTaskbarHeight()); + updatedInsetsBuilder.setInsets(WindowInsets.Type.navigationBars(), newNavInsets); + + Insets oldTappableInsets = oldInsets.getInsets(WindowInsets.Type.tappableElement()); + Insets newTappableInsets = Insets.of(oldTappableInsets.left, oldTappableInsets.top, + oldTappableInsets.right, 0); + updatedInsetsBuilder.setInsets(WindowInsets.Type.tappableElement(), newTappableInsets); + + return updatedInsetsBuilder.build(); + } +} diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java index a343c2d965..d4320043b0 100644 --- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java +++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java @@ -188,7 +188,8 @@ public abstract class BaseActivityInterface thumbnailDatas, diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java index 1cb17cb815..93be8d214e 100644 --- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java +++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java @@ -289,10 +289,6 @@ public final class LauncherActivityInterface extends } else { om.hideOverlay(150); } - LauncherTaskbarUIController taskbarController = getTaskbarController(); - if (taskbarController != null) { - taskbarController.hideEdu(); - } } @Override diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java index 5ee6fce1f7..73acd878c7 100644 --- a/src/com/android/launcher3/AbstractFloatingView.java +++ b/src/com/android/launcher3/AbstractFloatingView.java @@ -94,6 +94,7 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch public static final int TYPE_TASKBAR_EDUCATION_DIALOG = 1 << 16; public static final int TYPE_TASKBAR_ALL_APPS = 1 << 17; public static final int TYPE_ADD_TO_HOME_CONFIRMATION = 1 << 18; + public static final int TYPE_TASKBAR_OVERLAY_PROXY = 1 << 19; public static final int TYPE_ALL = TYPE_FOLDER | TYPE_ACTION_POPUP | TYPE_WIDGETS_BOTTOM_SHEET | TYPE_WIDGET_RESIZE_FRAME | TYPE_WIDGETS_FULL_SHEET