Merge "[Action Corner] Handle overview action in launcher" into main

This commit is contained in:
Helen Cheuk
2025-04-15 09:46:47 -07:00
committed by Android (Google) Code Review
4 changed files with 163 additions and 32 deletions

View File

@@ -48,11 +48,12 @@ import com.android.launcher3.util.RunnableList
import com.android.launcher3.util.coroutines.DispatcherProvider
import com.android.launcher3.util.coroutines.ProductionDispatchers
import com.android.quickstep.OverviewCommandHelper.CommandInfo.CommandStatus
import com.android.quickstep.OverviewCommandHelper.CommandType.HIDE
import com.android.quickstep.OverviewCommandHelper.CommandType.HIDE_ALT_TAB
import com.android.quickstep.OverviewCommandHelper.CommandType.HOME
import com.android.quickstep.OverviewCommandHelper.CommandType.KEYBOARD_INPUT
import com.android.quickstep.OverviewCommandHelper.CommandType.SHOW
import com.android.quickstep.OverviewCommandHelper.CommandType.SHOW_ALT_TAB
import com.android.quickstep.OverviewCommandHelper.CommandType.SHOW_WITH_FOCUS
import com.android.quickstep.OverviewCommandHelper.CommandType.TOGGLE
import com.android.quickstep.OverviewCommandHelper.CommandType.TOGGLE_OVERVIEW_PREVIOUS
import com.android.quickstep.fallback.window.RecentsWindowFlags.Companion.enableOverviewInWindow
import com.android.quickstep.util.ActiveGestureLog
import com.android.quickstep.util.ActiveGestureProtoLogProxy
@@ -159,7 +160,10 @@ constructor(
.toIntArray(),
)
fun canStartHomeSafely(): Boolean = commandQueue.isEmpty() || commandQueue.first().type == HOME
fun canStartHomeSafely(): Boolean =
commandQueue.isEmpty() ||
commandQueue.first().type == HOME ||
commandQueue.first().type == TOGGLE_OVERVIEW_PREVIOUS
/** Clear pending or completed commands from the queue */
fun clearPendingCommands() {
@@ -248,9 +252,9 @@ constructor(
onCallbackResult: () -> Unit,
): Boolean =
when (command.type) {
SHOW -> true // already visible
KEYBOARD_INPUT,
HIDE -> {
SHOW_WITH_FOCUS -> true // already visible
SHOW_ALT_TAB,
HIDE_ALT_TAB -> {
if (recentsView.isHandlingTouch) {
true
} else {
@@ -269,7 +273,15 @@ constructor(
onCallbackResult,
)
}
TOGGLE_OVERVIEW_PREVIOUS -> {
val taskView = recentsView.runningTaskView
if (taskView == null) {
recentsView.startHome()
} else {
taskView.launchWithAnimation()
}
true
}
HOME -> {
recentsView.startHome()
true
@@ -341,7 +353,7 @@ constructor(
}
when (command.type) {
HIDE -> {
HIDE_ALT_TAB -> {
if (
taskbarUIController == null ||
!shouldShowAltTabKqs(deviceProfile, command.displayId)
@@ -353,7 +365,7 @@ constructor(
if (keyboardTaskFocusIndex == -1) return true
}
KEYBOARD_INPUT ->
SHOW_ALT_TAB ->
if (
taskbarUIController != null &&
shouldShowAltTabKqs(deviceProfile, command.displayId)
@@ -374,14 +386,15 @@ constructor(
return true
}
SHOW ->
SHOW_WITH_FOCUS ->
// When Recents is not currently visible, the command's type is SHOW
// when overview is triggered via the keyboard overview button or Action+Tab
// keys (Not Alt+Tab which is KQS). The overview button on-screen in 3-button
// nav is TYPE_TOGGLE.
keyboardTaskFocusIndex = 0
TOGGLE -> {}
TOGGLE,
TOGGLE_OVERVIEW_PREVIOUS -> {}
}
recentsView?.setKeyboardTaskFocusIndex(
@@ -560,7 +573,11 @@ constructor(
private fun updateRecentsViewFocus(command: CommandInfo) {
val recentsView: RecentsView<*, *> = getVisibleRecentsView(command.displayId) ?: return
if (command.type != KEYBOARD_INPUT && command.type != HIDE && command.type != SHOW) {
if (
command.type != SHOW_ALT_TAB &&
command.type != HIDE_ALT_TAB &&
command.type != SHOW_WITH_FOCUS
) {
return
}
@@ -581,7 +598,7 @@ constructor(
private fun onRecentsViewFocusUpdated(command: CommandInfo) {
val recentsView: RecentsView<*, *> = getVisibleRecentsView(command.displayId) ?: return
if (command.type != HIDE || keyboardTaskFocusIndex == PagedView.INVALID_PAGE) {
if (command.type != HIDE_ALT_TAB || keyboardTaskFocusIndex == PagedView.INVALID_PAGE) {
return
}
recentsView.setKeyboardTaskFocusIndex(PagedView.INVALID_PAGE)
@@ -603,8 +620,8 @@ constructor(
val container = containerInterface.getCreatedContainer() ?: return
val event =
when (command.type) {
SHOW -> LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_SHORTCUT
HIDE -> LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_QUICK_SWITCH
SHOW_WITH_FOCUS -> LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_SHORTCUT
HIDE_ALT_TAB -> LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_QUICK_SWITCH
TOGGLE -> LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_3_BUTTON
else -> return
}
@@ -659,11 +676,17 @@ constructor(
}
enum class CommandType {
SHOW,
KEYBOARD_INPUT,
HIDE,
SHOW_WITH_FOCUS,
SHOW_ALT_TAB,
HIDE_ALT_TAB,
/** Toggle between overview and the next task */
TOGGLE, // Navigate to Overview
HOME, // Navigate to Home
/**
* Toggle between Overview and the previous screen before launching Overview, which can
* either be a task or the home screen.
*/
TOGGLE_OVERVIEW_PREVIOUS,
}
companion object {

View File

@@ -94,6 +94,7 @@ import com.android.launcher3.util.ScreenOnTracker;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.OverviewCommandHelper.CommandType;
import com.android.quickstep.OverviewComponentObserver.OverviewChangeListener;
import com.android.quickstep.actioncorner.ActionCornerHandler;
import com.android.quickstep.fallback.window.RecentsWindowFlags;
import com.android.quickstep.fallback.window.RecentsWindowManager;
import com.android.quickstep.fallback.window.RecentsWindowSwipeHandler;
@@ -238,9 +239,9 @@ public class TouchInteractionService extends Service {
int displayId = enableAltTabKqsOnConnectedDisplays.isTrue()
? SystemUiProxy.INSTANCE.get(tis).getFocusState().getFocusedDisplayId()
: DEFAULT_DISPLAY;
tis.mOverviewCommandHelper.addCommand(CommandType.KEYBOARD_INPUT, displayId);
tis.mOverviewCommandHelper.addCommand(CommandType.SHOW_ALT_TAB, displayId);
} else {
tis.mOverviewCommandHelper.addCommand(CommandType.SHOW);
tis.mOverviewCommandHelper.addCommand(CommandType.SHOW_WITH_FOCUS);
}
});
}
@@ -254,7 +255,7 @@ public class TouchInteractionService extends Service {
int displayId = enableAltTabKqsOnConnectedDisplays.isTrue()
? SystemUiProxy.INSTANCE.get(tis).getFocusState().getFocusedDisplayId()
: DEFAULT_DISPLAY;
tis.mOverviewCommandHelper.addCommand(CommandType.HIDE, displayId);
tis.mOverviewCommandHelper.addCommand(CommandType.HIDE_ALT_TAB, displayId);
}
});
}
@@ -451,7 +452,13 @@ public class TouchInteractionService extends Service {
@Override
public void onActionCornerActivated(int action, int displayId) {
//TODO: b/409036363 - Handle Home and Overview action corner
MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> {
ActionCornerHandler actionCornerHandler = tis.mActionCornerHandler;
if (actionCornerHandler == null) {
return;
}
actionCornerHandler.handleAction(action, displayId);
}));
}
private void executeForTouchInteractionService(
@@ -595,9 +602,9 @@ public class TouchInteractionService extends Service {
@Override
public void onHideOverview(int displayId) {
if (enableOverviewOnConnectedDisplays()) {
mOverviewCommandHelper.addCommand(CommandType.HIDE, displayId);
mOverviewCommandHelper.addCommand(CommandType.HIDE_ALT_TAB, displayId);
} else {
mOverviewCommandHelper.addCommand(CommandType.HIDE, DEFAULT_DISPLAY);
mOverviewCommandHelper.addCommand(CommandType.HIDE_ALT_TAB, DEFAULT_DISPLAY);
}
}
};
@@ -620,6 +627,7 @@ public class TouchInteractionService extends Service {
private InputEventReceiver mInputEventReceiver;
private TaskbarManager mTaskbarManager;
private ActionCornerHandler mActionCornerHandler;
private Function<GestureState, AnimatedFloat> mSwipeUpProxyProvider = i -> null;
private AllAppsActionManager mAllAppsActionManager;
private ActiveTrackpadList mTrackpadsConnected;
@@ -755,6 +763,7 @@ public class TouchInteractionService extends Service {
mOverviewCommandHelper = new OverviewCommandHelper(this,
mOverviewComponentObserver, mDisplayRepository, mTaskbarManager,
mTaskAnimationManagerRepository);
mActionCornerHandler = new ActionCornerHandler(mOverviewCommandHelper);
mUserUnlocked = true;
mInputConsumer.registerInputConsumer();
mDeviceStateRepository.forEach(/* createIfAbsent= */ true, deviceState ->

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2025 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.quickstep.actioncorner
import com.android.quickstep.OverviewCommandHelper
import com.android.quickstep.OverviewCommandHelper.CommandType.TOGGLE_OVERVIEW_PREVIOUS
import com.android.systemui.shared.system.actioncorner.ActionCornerConstants.Action
import com.android.systemui.shared.system.actioncorner.ActionCornerConstants.HOME
import com.android.systemui.shared.system.actioncorner.ActionCornerConstants.OVERVIEW
/**
* Handles actions triggered from action corners that are mapped to specific functionalities.
* Launcher supports both overview and home actions.
*/
class ActionCornerHandler(private val overviewCommandHelper: OverviewCommandHelper) {
fun handleAction(@Action action: Int, displayId: Int) {
when (action) {
// TODO(b/410798748): handle projected mode when launching overview
OVERVIEW -> overviewCommandHelper.addCommandsForAllDisplays(TOGGLE_OVERVIEW_PREVIOUS)
HOME -> {} // TODO(b/409036363): handle HOME action
else -> {}
}
}
}