9f11519936
When desktop stashed state changes, show a persistent popup on home screen to select an app that will be launched on desktop. Flag: persist.wm.debug.desktop_mode_2 Bug: 261234402 Test: launch an app on desktop, swipe home, observe the popup, launch an app, observe app is launched on desktop and popup is hidden Test: stash desktop apps by going home while on desktop, press on the "exit desktop" button in the popup, observe popup is hidden, launch an app, observe it is launched in fullscreen Change-Id: I66fe0ab977fa7b2059f149d7d0ab0cf92192c967
253 lines
8.4 KiB
Java
253 lines
8.4 KiB
Java
/*
|
|
* 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.statehandlers;
|
|
|
|
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
|
|
|
import android.os.SystemProperties;
|
|
import android.util.Log;
|
|
import android.view.View;
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
import com.android.launcher3.Launcher;
|
|
import com.android.launcher3.LauncherState;
|
|
import com.android.launcher3.statemanager.StatefulActivity;
|
|
import com.android.launcher3.uioverrides.QuickstepLauncher;
|
|
import com.android.quickstep.SystemUiProxy;
|
|
import com.android.quickstep.views.DesktopAppSelectView;
|
|
import com.android.wm.shell.desktopmode.IDesktopTaskListener;
|
|
|
|
/**
|
|
* Controls the visibility of the workspace and the resumed / paused state when desktop mode
|
|
* is enabled.
|
|
*/
|
|
public class DesktopVisibilityController {
|
|
|
|
private static final String TAG = "DesktopVisController";
|
|
private static final boolean DEBUG = false;
|
|
|
|
private final Launcher mLauncher;
|
|
|
|
private boolean mFreeformTasksVisible;
|
|
private boolean mInOverviewState;
|
|
private boolean mGestureInProgress;
|
|
|
|
@Nullable
|
|
private IDesktopTaskListener mDesktopTaskListener;
|
|
private DesktopAppSelectView mSelectAppToast;
|
|
|
|
public DesktopVisibilityController(Launcher launcher) {
|
|
mLauncher = launcher;
|
|
}
|
|
|
|
/**
|
|
* Register a listener with System UI to receive updates about desktop tasks state
|
|
*/
|
|
public void registerSystemUiListener() {
|
|
mDesktopTaskListener = new IDesktopTaskListener.Stub() {
|
|
@Override
|
|
public void onVisibilityChanged(int displayId, boolean visible) {
|
|
// TODO(b/261234402): move visibility from sysui state to listener
|
|
}
|
|
|
|
@Override
|
|
public void onStashedChanged(int displayId, boolean stashed) {
|
|
MAIN_EXECUTOR.execute(() -> {
|
|
if (displayId == mLauncher.getDisplayId()) {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "desktop stashed changed value=" + stashed);
|
|
}
|
|
if (stashed) {
|
|
showSelectAppToast();
|
|
} else {
|
|
hideSelectAppToast();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
};
|
|
SystemUiProxy.INSTANCE.get(mLauncher).setDesktopTaskListener(mDesktopTaskListener);
|
|
}
|
|
|
|
/**
|
|
* Clear listener from System UI that was set with {@link #registerSystemUiListener()}
|
|
*/
|
|
public void unregisterSystemUiListener() {
|
|
SystemUiProxy.INSTANCE.get(mLauncher).setDesktopTaskListener(null);
|
|
}
|
|
|
|
/**
|
|
* Whether desktop mode is supported.
|
|
*/
|
|
private boolean isDesktopModeSupported() {
|
|
return SystemProperties.getBoolean("persist.wm.debug.desktop_mode", false)
|
|
|| SystemProperties.getBoolean("persist.wm.debug.desktop_mode_2", false);
|
|
}
|
|
|
|
/**
|
|
* Whether freeform windows are visible in desktop mode.
|
|
*/
|
|
public boolean areFreeformTasksVisible() {
|
|
return mFreeformTasksVisible;
|
|
}
|
|
|
|
/**
|
|
* Sets whether freeform windows are visible and updates launcher visibility based on that.
|
|
*/
|
|
public void setFreeformTasksVisible(boolean freeformTasksVisible) {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "setFreeformTasksVisible: visible=" + freeformTasksVisible);
|
|
}
|
|
if (!isDesktopModeSupported()) {
|
|
return;
|
|
}
|
|
|
|
if (freeformTasksVisible != mFreeformTasksVisible) {
|
|
mFreeformTasksVisible = freeformTasksVisible;
|
|
if (mFreeformTasksVisible) {
|
|
setLauncherViewsVisibility(View.INVISIBLE);
|
|
if (!mInOverviewState) {
|
|
// When freeform is visible & we're not in overview, we want launcher to appear
|
|
// paused, this ensures that taskbar displays.
|
|
markLauncherPaused();
|
|
}
|
|
} else {
|
|
setLauncherViewsVisibility(View.VISIBLE);
|
|
// If freeform isn't visible ensure that launcher appears resumed to behave
|
|
// normally.
|
|
markLauncherResumed();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets whether the overview is visible and updates launcher visibility based on that.
|
|
*/
|
|
public void setOverviewStateEnabled(boolean overviewStateEnabled) {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "setOverviewStateEnabled: enabled=" + overviewStateEnabled);
|
|
}
|
|
if (!isDesktopModeSupported()) {
|
|
return;
|
|
}
|
|
if (overviewStateEnabled != mInOverviewState) {
|
|
mInOverviewState = overviewStateEnabled;
|
|
if (mInOverviewState) {
|
|
setLauncherViewsVisibility(View.VISIBLE);
|
|
markLauncherResumed();
|
|
} else if (mFreeformTasksVisible) {
|
|
setLauncherViewsVisibility(View.INVISIBLE);
|
|
markLauncherPaused();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Whether recents gesture is currently in progress.
|
|
*/
|
|
public boolean isGestureInProgress() {
|
|
return mGestureInProgress;
|
|
}
|
|
|
|
/**
|
|
* Sets whether recents gesture is in progress.
|
|
*/
|
|
public void setGestureInProgress(boolean gestureInProgress) {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "setGestureInProgress: inProgress=" + gestureInProgress);
|
|
}
|
|
if (!isDesktopModeSupported()) {
|
|
return;
|
|
}
|
|
if (gestureInProgress != mGestureInProgress) {
|
|
mGestureInProgress = gestureInProgress;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle launcher moving to home due to home gesture or home button press.
|
|
*/
|
|
public void onHomeActionTriggered() {
|
|
if (areFreeformTasksVisible()) {
|
|
SystemUiProxy.INSTANCE.get(mLauncher).stashDesktopApps(mLauncher.getDisplayId());
|
|
}
|
|
}
|
|
|
|
private void setLauncherViewsVisibility(int visibility) {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "setLauncherViewsVisibility: visibility=" + visibility);
|
|
}
|
|
View workspaceView = mLauncher.getWorkspace();
|
|
if (workspaceView != null) {
|
|
workspaceView.setVisibility(visibility);
|
|
}
|
|
View dragLayer = mLauncher.getDragLayer();
|
|
if (dragLayer != null) {
|
|
dragLayer.setVisibility(visibility);
|
|
}
|
|
}
|
|
|
|
private void markLauncherPaused() {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "markLauncherPaused");
|
|
}
|
|
StatefulActivity<LauncherState> activity =
|
|
QuickstepLauncher.ACTIVITY_TRACKER.getCreatedActivity();
|
|
if (activity != null) {
|
|
activity.setPaused();
|
|
}
|
|
}
|
|
|
|
private void markLauncherResumed() {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "markLauncherResumed");
|
|
}
|
|
StatefulActivity<LauncherState> activity =
|
|
QuickstepLauncher.ACTIVITY_TRACKER.getCreatedActivity();
|
|
// Check activity state before calling setResumed(). Launcher may have been actually
|
|
// paused (eg fullscreen task moved to front).
|
|
// In this case we should not mark the activity as resumed.
|
|
if (activity != null && activity.isResumed()) {
|
|
activity.setResumed();
|
|
}
|
|
}
|
|
|
|
private void showSelectAppToast() {
|
|
if (mSelectAppToast != null) {
|
|
return;
|
|
}
|
|
if (DEBUG) {
|
|
Log.d(TAG, "show toast to select desktop apps");
|
|
}
|
|
Runnable onCloseCallback = () -> {
|
|
SystemUiProxy.INSTANCE.get(mLauncher).hideStashedDesktopApps(mLauncher.getDisplayId());
|
|
};
|
|
mSelectAppToast = DesktopAppSelectView.show(mLauncher, onCloseCallback);
|
|
}
|
|
|
|
private void hideSelectAppToast() {
|
|
if (mSelectAppToast == null) {
|
|
return;
|
|
}
|
|
if (DEBUG) {
|
|
Log.d(TAG, "hide toast to select desktop apps");
|
|
}
|
|
mSelectAppToast.hide();
|
|
mSelectAppToast = null;
|
|
}
|
|
}
|