mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-03-03 01:16:49 +00:00
Merge "Implement overlay window for Taskbar EDU and All Apps." into tm-qpr-dev am: c9928a1ddf
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/20154536 Change-Id: I1fe0c0d4410b83c657047b59fc6988ede9b3b880 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
@@ -211,7 +212,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
|
||||
@@ -243,7 +245,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());
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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<TaskbarActivityContext>
|
||||
public class TaskbarEduView extends AbstractSlideInView<TaskbarOverlayContext>
|
||||
implements Insettable {
|
||||
|
||||
private static final int DEFAULT_OPEN_DURATION = 500;
|
||||
|
||||
@@ -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
|
||||
@@ -158,8 +158,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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<TaskbarAllAppsContext> {
|
||||
ActivityAllAppsContainerView<TaskbarOverlayContext> {
|
||||
|
||||
public TaskbarAllAppsContainerView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
@@ -44,8 +45,8 @@ public class TaskbarAllAppsContainerView extends
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BaseAllAppsAdapter<TaskbarAllAppsContext> createAdapter(
|
||||
AlphabeticalAppsList<TaskbarAllAppsContext> appsList,
|
||||
protected BaseAllAppsAdapter<TaskbarOverlayContext> createAdapter(
|
||||
AlphabeticalAppsList<TaskbarOverlayContext> appsList,
|
||||
BaseAdapterProvider[] adapterProviders) {
|
||||
return new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), appsList,
|
||||
adapterProviders);
|
||||
|
||||
@@ -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.
|
||||
* <p>
|
||||
* 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<TaskbarAllAppsContext> 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<TaskbarAllAppsContext> 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<TaskbarAllAppsContext> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<ItemInfo> 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TaskbarAllAppsContext>
|
||||
public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarOverlayContext>
|
||||
implements Insettable, DeviceProfile.OnDeviceProfileChangeListener {
|
||||
private TaskbarAllAppsContainerView mAppsView;
|
||||
private float mShiftRange;
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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.
|
||||
* <p>
|
||||
* 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<TaskbarOverlayContext> 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<TaskbarOverlayContext> 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);
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<TaskbarOverlayContext> 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();
|
||||
}
|
||||
}
|
||||
@@ -188,7 +188,8 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
* Closes any overlays.
|
||||
*/
|
||||
public void closeOverlay() {
|
||||
Optional.ofNullable(getTaskbarController()).ifPresent(TaskbarUIController::hideAllApps);
|
||||
Optional.ofNullable(getTaskbarController()).ifPresent(
|
||||
TaskbarUIController::hideOverlayWindow);
|
||||
}
|
||||
|
||||
public void switchRunningTaskViewToScreenshot(HashMap<Integer, ThumbnailData> thumbnailDatas,
|
||||
|
||||
@@ -290,10 +290,6 @@ public final class LauncherActivityInterface extends
|
||||
} else {
|
||||
om.hideOverlay(150);
|
||||
}
|
||||
LauncherTaskbarUIController taskbarController = getTaskbarController();
|
||||
if (taskbarController != null) {
|
||||
taskbarController.hideEdu();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user