Bug: 309481654 Change-Id: Id7b5db662d578eb625171055d30c37cd59e7d73c Flag: EXEMPT refactor since it is removing obsolete code with no changes to current behavior.
359 lines
13 KiB
Java
359 lines
13 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 android.view.View.VISIBLE;
|
|
|
|
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
|
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
|
import static com.android.window.flags.Flags.enableDesktopWindowingWallpaperActivity;
|
|
|
|
import android.os.Debug;
|
|
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.launcher3.util.DisplayController;
|
|
import com.android.quickstep.GestureState;
|
|
import com.android.quickstep.SystemUiProxy;
|
|
import com.android.wm.shell.desktopmode.IDesktopTaskListener;
|
|
|
|
import java.util.HashSet;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* 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 final Set<DesktopVisibilityListener> mDesktopVisibilityListeners = new HashSet<>();
|
|
|
|
private int mVisibleDesktopTasksCount;
|
|
private boolean mInOverviewState;
|
|
private boolean mBackgroundStateEnabled;
|
|
private boolean mGestureInProgress;
|
|
|
|
@Nullable
|
|
private IDesktopTaskListener mDesktopTaskListener;
|
|
|
|
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 onTasksVisibilityChanged(int displayId, int visibleTasksCount) {
|
|
MAIN_EXECUTOR.execute(() -> {
|
|
if (displayId == mLauncher.getDisplayId()) {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "desktop visible tasks count changed=" + visibleTasksCount);
|
|
}
|
|
setVisibleDesktopTasksCount(visibleTasksCount);
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void onStashedChanged(int displayId, boolean stashed) {
|
|
Log.w(TAG, "IDesktopTaskListener: onStashedChanged is deprecated");
|
|
}
|
|
};
|
|
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 tasks are visible in desktop mode.
|
|
*/
|
|
public boolean areDesktopTasksVisible() {
|
|
boolean desktopTasksVisible = mVisibleDesktopTasksCount > 0;
|
|
if (DEBUG) {
|
|
Log.d(TAG, "areDesktopTasksVisible: desktopVisible=" + desktopTasksVisible
|
|
+ " overview=" + mInOverviewState);
|
|
}
|
|
return desktopTasksVisible && !mInOverviewState;
|
|
}
|
|
|
|
/**
|
|
* Number of visible desktop windows in desktop mode.
|
|
*/
|
|
public int getVisibleDesktopTasksCount() {
|
|
return mVisibleDesktopTasksCount;
|
|
}
|
|
|
|
/** Registers a listener for Desktop Mode visibility updates. */
|
|
public void registerDesktopVisibilityListener(DesktopVisibilityListener listener) {
|
|
mDesktopVisibilityListeners.add(listener);
|
|
}
|
|
|
|
/** Removes a previously registered Desktop Mode visibility listener. */
|
|
public void unregisterDesktopVisibilityListener(DesktopVisibilityListener listener) {
|
|
mDesktopVisibilityListeners.remove(listener);
|
|
}
|
|
|
|
/**
|
|
* Sets the number of desktop windows that are visible and updates launcher visibility based on
|
|
* it.
|
|
*/
|
|
public void setVisibleDesktopTasksCount(int visibleTasksCount) {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "setVisibleDesktopTasksCount: visibleTasksCount=" + visibleTasksCount
|
|
+ " currentValue=" + mVisibleDesktopTasksCount);
|
|
}
|
|
|
|
if (visibleTasksCount != mVisibleDesktopTasksCount) {
|
|
final boolean wasVisible = mVisibleDesktopTasksCount > 0;
|
|
final boolean isVisible = visibleTasksCount > 0;
|
|
final boolean wereDesktopTasksVisibleBefore = areDesktopTasksVisible();
|
|
mVisibleDesktopTasksCount = visibleTasksCount;
|
|
final boolean areDesktopTasksVisibleNow = areDesktopTasksVisible();
|
|
if (wereDesktopTasksVisibleBefore != areDesktopTasksVisibleNow) {
|
|
notifyDesktopVisibilityListeners(areDesktopTasksVisibleNow);
|
|
}
|
|
|
|
if (!enableDesktopWindowingWallpaperActivity() && wasVisible != isVisible) {
|
|
// TODO: b/333533253 - Remove after flag rollout
|
|
if (mVisibleDesktopTasksCount > 0) {
|
|
setLauncherViewsVisibility(View.INVISIBLE);
|
|
if (!mInOverviewState) {
|
|
// When desktop tasks are visible & we're not in overview, we want launcher
|
|
// to appear paused, this ensures that taskbar displays.
|
|
markLauncherPaused();
|
|
}
|
|
} else {
|
|
setLauncherViewsVisibility(View.VISIBLE);
|
|
// If desktop tasks aren't visible, ensure that launcher appears resumed to
|
|
// behave normally.
|
|
markLauncherResumed();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Process launcher state change and update launcher view visibility based on desktop state
|
|
*/
|
|
public void onLauncherStateChanged(LauncherState state) {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "onLauncherStateChanged: newState=" + state);
|
|
}
|
|
setBackgroundStateEnabled(state == BACKGROUND_APP);
|
|
// Desktop visibility tracks overview and background state separately
|
|
setOverviewStateEnabled(state != BACKGROUND_APP && state.overviewUi);
|
|
}
|
|
|
|
private void setOverviewStateEnabled(boolean overviewStateEnabled) {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "setOverviewStateEnabled: enabled=" + overviewStateEnabled
|
|
+ " currentValue=" + mInOverviewState);
|
|
}
|
|
if (overviewStateEnabled != mInOverviewState) {
|
|
final boolean wereDesktopTasksVisibleBefore = areDesktopTasksVisible();
|
|
mInOverviewState = overviewStateEnabled;
|
|
final boolean areDesktopTasksVisibleNow = areDesktopTasksVisible();
|
|
if (wereDesktopTasksVisibleBefore != areDesktopTasksVisibleNow) {
|
|
notifyDesktopVisibilityListeners(areDesktopTasksVisibleNow);
|
|
}
|
|
|
|
if (enableDesktopWindowingWallpaperActivity()) {
|
|
return;
|
|
}
|
|
// TODO: b/333533253 - Clean up after flag rollout
|
|
|
|
if (mInOverviewState) {
|
|
setLauncherViewsVisibility(View.VISIBLE);
|
|
markLauncherResumed();
|
|
} else if (areDesktopTasksVisibleNow && !mGestureInProgress) {
|
|
// Switching out of overview state and gesture finished.
|
|
// If desktop tasks are still visible, hide launcher again.
|
|
setLauncherViewsVisibility(View.INVISIBLE);
|
|
markLauncherPaused();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void notifyDesktopVisibilityListeners(boolean areDesktopTasksVisible) {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "notifyDesktopVisibilityListeners: visible=" + areDesktopTasksVisible);
|
|
}
|
|
for (DesktopVisibilityListener listener : mDesktopVisibilityListeners) {
|
|
listener.onDesktopVisibilityChanged(areDesktopTasksVisible);
|
|
}
|
|
DisplayController.handleInfoChangeForDesktopMode(mLauncher);
|
|
}
|
|
|
|
/**
|
|
* TODO: b/333533253 - Remove after flag rollout
|
|
*/
|
|
private void setBackgroundStateEnabled(boolean backgroundStateEnabled) {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "setBackgroundStateEnabled: enabled=" + backgroundStateEnabled
|
|
+ " currentValue=" + mBackgroundStateEnabled);
|
|
}
|
|
if (backgroundStateEnabled != mBackgroundStateEnabled) {
|
|
mBackgroundStateEnabled = backgroundStateEnabled;
|
|
if (mBackgroundStateEnabled) {
|
|
setLauncherViewsVisibility(View.VISIBLE);
|
|
markLauncherResumed();
|
|
} else if (areDesktopTasksVisible() && !mGestureInProgress) {
|
|
// Switching out of background state. If desktop tasks are visible, pause launcher.
|
|
setLauncherViewsVisibility(View.INVISIBLE);
|
|
markLauncherPaused();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Whether recents gesture is currently in progress.
|
|
*
|
|
* TODO: b/333533253 - Remove after flag rollout
|
|
*/
|
|
public boolean isRecentsGestureInProgress() {
|
|
return mGestureInProgress;
|
|
}
|
|
|
|
/**
|
|
* Notify controller that recents gesture has started.
|
|
*
|
|
* TODO: b/333533253 - Remove after flag rollout
|
|
*/
|
|
public void setRecentsGestureStart() {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "setRecentsGestureStart");
|
|
}
|
|
setRecentsGestureInProgress(true);
|
|
}
|
|
|
|
/**
|
|
* Notify controller that recents gesture finished with the given
|
|
* {@link com.android.quickstep.GestureState.GestureEndTarget}
|
|
*
|
|
* TODO: b/333533253 - Remove after flag rollout
|
|
*/
|
|
public void setRecentsGestureEnd(@Nullable GestureState.GestureEndTarget endTarget) {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "setRecentsGestureEnd: endTarget=" + endTarget);
|
|
}
|
|
setRecentsGestureInProgress(false);
|
|
|
|
if (endTarget == null) {
|
|
// Gesture did not result in a new end target. Ensure launchers gets paused again.
|
|
markLauncherPaused();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* TODO: b/333533253 - Remove after flag rollout
|
|
*/
|
|
private void setRecentsGestureInProgress(boolean gestureInProgress) {
|
|
if (gestureInProgress != mGestureInProgress) {
|
|
mGestureInProgress = gestureInProgress;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* TODO: b/333533253 - Remove after flag rollout
|
|
*/
|
|
private void setLauncherViewsVisibility(int visibility) {
|
|
if (enableDesktopWindowingWallpaperActivity()) {
|
|
return;
|
|
}
|
|
if (DEBUG) {
|
|
Log.d(TAG, "setLauncherViewsVisibility: visibility=" + visibility + " "
|
|
+ Debug.getCaller());
|
|
}
|
|
View workspaceView = mLauncher.getWorkspace();
|
|
if (workspaceView != null) {
|
|
workspaceView.setVisibility(visibility);
|
|
}
|
|
View dragLayer = mLauncher.getDragLayer();
|
|
if (dragLayer != null) {
|
|
dragLayer.setVisibility(visibility);
|
|
}
|
|
if (mLauncher instanceof QuickstepLauncher ql && ql.getTaskbarUIController() != null
|
|
&& mVisibleDesktopTasksCount != 0) {
|
|
ql.getTaskbarUIController().onLauncherVisibilityChanged(visibility == VISIBLE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* TODO: b/333533253 - Remove after flag rollout
|
|
*/
|
|
private void markLauncherPaused() {
|
|
if (enableDesktopWindowingWallpaperActivity()) {
|
|
return;
|
|
}
|
|
if (DEBUG) {
|
|
Log.d(TAG, "markLauncherPaused " + Debug.getCaller());
|
|
}
|
|
StatefulActivity<LauncherState> activity =
|
|
QuickstepLauncher.ACTIVITY_TRACKER.getCreatedActivity();
|
|
if (activity != null) {
|
|
activity.setPaused();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* TODO: b/333533253 - Remove after flag rollout
|
|
*/
|
|
private void markLauncherResumed() {
|
|
if (enableDesktopWindowingWallpaperActivity()) {
|
|
return;
|
|
}
|
|
if (DEBUG) {
|
|
Log.d(TAG, "markLauncherResumed " + Debug.getCaller());
|
|
}
|
|
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();
|
|
}
|
|
}
|
|
|
|
/** A listener for when the user enters/exits Desktop Mode. */
|
|
public interface DesktopVisibilityListener {
|
|
/**
|
|
* Callback for when the user enters or exits Desktop Mode
|
|
*
|
|
* @param visible whether Desktop Mode is now visible
|
|
*/
|
|
void onDesktopVisibilityChanged(boolean visible);
|
|
}
|
|
}
|