Merge "Disallow scroll to the AddDesktopButton" into main
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index cc746eb..ca6e24c 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -636,3 +636,13 @@
description: "Enables gesture navigation handling on connected displays"
bug: "382130680"
}
+
+flag {
+ name: "enable_taskbar_behind_shade"
+ namespace: "lse_desktop_experience"
+ description: "Keeps taskbar behind notification shade when its pulled down"
+ bug: "343194358"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/DisplayModel.kt b/quickstep/src/com/android/quickstep/DisplayModel.kt
index cbc2f7d..27a3379 100644
--- a/quickstep/src/com/android/quickstep/DisplayModel.kt
+++ b/quickstep/src/com/android/quickstep/DisplayModel.kt
@@ -20,28 +20,28 @@
import android.hardware.display.DisplayManager
import android.util.Log
import android.util.SparseArray
+import android.view.Display
import androidx.core.util.valueIterator
+import com.android.launcher3.util.Executors
import com.android.quickstep.DisplayModel.DisplayResource
+import java.io.PrintWriter
/** data model for managing resources with lifecycles that match that of the connected display */
abstract class DisplayModel<RESOURCE_TYPE : DisplayResource>(val context: Context) {
companion object {
- private const val TAG = "DisplayViewModel"
+ private const val TAG = "DisplayModel"
private const val DEBUG = false
}
- protected val displayManager =
- context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
- protected val displayResourceArray = SparseArray<RESOURCE_TYPE>()
+ private val displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
+ private val displayResourceArray = SparseArray<RESOURCE_TYPE>()
- abstract fun createDisplayResource(displayId: Int)
-
- protected val displayListener: DisplayManager.DisplayListener =
+ private val displayListener: DisplayManager.DisplayListener =
(object : DisplayManager.DisplayListener {
override fun onDisplayAdded(displayId: Int) {
if (DEBUG) Log.d(TAG, "onDisplayAdded: displayId=$displayId")
- createDisplayResource(displayId)
+ storeDisplayResource(displayId)
}
override fun onDisplayRemoved(displayId: Int) {
@@ -54,6 +54,17 @@
}
})
+ protected abstract fun createDisplayResource(display: Display): RESOURCE_TYPE
+
+ protected fun registerDisplayListener() {
+ displayManager.registerDisplayListener(displayListener, Executors.MAIN_EXECUTOR.handler)
+ // In the scenario where displays were added before this display listener was
+ // registered, we should store the DisplayResources for those displays directly.
+ displayManager.displays
+ .filter { getDisplayResource(it.displayId) == null }
+ .forEach { storeDisplayResource(it.displayId) }
+ }
+
fun destroy() {
displayResourceArray.valueIterator().forEach { displayResource ->
displayResource.cleanup()
@@ -73,7 +84,36 @@
displayResourceArray.remove(displayId)
}
- abstract class DisplayResource() {
+ fun storeDisplayResource(displayId: Int) {
+ if (DEBUG) Log.d(TAG, "store: displayId=$displayId")
+ getDisplayResource(displayId)?.let {
+ return
+ }
+ val display = displayManager.getDisplay(displayId)
+ if (display == null) {
+ if (DEBUG)
+ Log.w(
+ TAG,
+ "storeDisplayResource: could not create display for displayId=$displayId",
+ Exception(),
+ )
+ return
+ }
+ displayResourceArray[displayId] = createDisplayResource(display)
+ }
+
+ fun dump(prefix: String, writer: PrintWriter) {
+ writer.println("${prefix}${this::class.simpleName}: display resources=[")
+
+ displayResourceArray.valueIterator().forEach { displayResource ->
+ displayResource.dump("${prefix}\t", writer)
+ }
+ writer.println("${prefix}]")
+ }
+
+ abstract class DisplayResource {
abstract fun cleanup()
+
+ abstract fun dump(prefix: String, writer: PrintWriter)
}
}
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index e1d4536..699c5df 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -30,6 +30,7 @@
import android.content.Intent;
import android.os.SystemClock;
+import android.view.Display;
import android.view.MotionEvent;
import android.view.RemoteAnimationTarget;
import android.window.TransitionInfo;
@@ -158,6 +159,7 @@
private final BaseContainerInterface mContainerInterface;
private final MultiStateCallback mStateCallback;
private final int mGestureId;
+ private final int mDisplayId;
public enum TrackpadGestureType {
NONE,
@@ -190,7 +192,8 @@
private boolean mHandlingAtomicEvent;
private boolean mIsInExtendedSlopRegion;
- public GestureState(OverviewComponentObserver componentObserver, int gestureId) {
+ public GestureState(OverviewComponentObserver componentObserver, int displayId, int gestureId) {
+ mDisplayId = displayId;
mHomeIntent = componentObserver.getHomeIntent();
mOverviewIntent = componentObserver.getOverviewIntent();
mContainerInterface = componentObserver.getContainerInterface();
@@ -200,6 +203,7 @@
}
public GestureState(GestureState other) {
+ mDisplayId = other.mDisplayId;
mHomeIntent = other.mHomeIntent;
mOverviewIntent = other.mOverviewIntent;
mContainerInterface = other.mContainerInterface;
@@ -214,6 +218,7 @@
public GestureState() {
// Do nothing, only used for initializing the gesture state prior to user unlock
+ mDisplayId = Display.DEFAULT_DISPLAY;
mHomeIntent = new Intent();
mOverviewIntent = new Intent();
mContainerInterface = null;
@@ -285,6 +290,13 @@
}
/**
+ * @return the id for the display this particular gesture was performed on.
+ */
+ public int getDisplayId() {
+ return mDisplayId;
+ }
+
+ /**
* Sets if the gesture is is from the trackpad, if so, whether 3-finger, or 4-finger
*/
public void setTrackpadGestureType(TrackpadGestureType trackpadGestureType) {
@@ -545,6 +557,7 @@
public void dump(String prefix, PrintWriter pw) {
pw.println(prefix + "GestureState:");
+ pw.println(prefix + "\tdisplayID=" + mDisplayId);
pw.println(prefix + "\tgestureID=" + mGestureId);
pw.println(prefix + "\trunningTask=" + mRunningTask);
pw.println(prefix + "\tendTarget=" + mEndTarget);
diff --git a/quickstep/src/com/android/quickstep/InputConsumer.java b/quickstep/src/com/android/quickstep/InputConsumer.java
index 0185737..081ed9d 100644
--- a/quickstep/src/com/android/quickstep/InputConsumer.java
+++ b/quickstep/src/com/android/quickstep/InputConsumer.java
@@ -17,6 +17,7 @@
import android.annotation.TargetApi;
import android.os.Build;
+import android.view.Display;
import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -66,6 +67,10 @@
int getType();
+ default int getDisplayId() {
+ return Display.DEFAULT_DISPLAY;
+ }
+
/**
* Returns true if the user has crossed the threshold for it to be an explicit action.
*/
diff --git a/quickstep/src/com/android/quickstep/InputConsumerUtils.kt b/quickstep/src/com/android/quickstep/InputConsumerUtils.kt
index c340c92..cd3ac12 100644
--- a/quickstep/src/com/android/quickstep/InputConsumerUtils.kt
+++ b/quickstep/src/com/android/quickstep/InputConsumerUtils.kt
@@ -76,7 +76,12 @@
val bubbleControllers = tac?.bubbleControllers
if (bubbleControllers != null && BubbleBarInputConsumer.isEventOnBubbles(tac, event)) {
val consumer: InputConsumer =
- BubbleBarInputConsumer(context, bubbleControllers, inputMonitorCompat)
+ BubbleBarInputConsumer(
+ context,
+ gestureState.displayId,
+ bubbleControllers,
+ inputMonitorCompat,
+ )
logInputConsumerSelectionReason(
consumer,
newCompoundString("event is on bubbles, creating new input consumer"),
@@ -285,7 +290,13 @@
"%ssystem dialog is showing, using SysUiOverlayInputConsumer",
SUBSTRING_PREFIX,
)
- base = SysUiOverlayInputConsumer(context, deviceState, inputMonitorCompat)
+ base =
+ SysUiOverlayInputConsumer(
+ context,
+ gestureState.displayId,
+ deviceState,
+ inputMonitorCompat,
+ )
}
if (
@@ -299,7 +310,13 @@
"%sTrackpad 3-finger gesture, using TrackpadStatusBarInputConsumer",
SUBSTRING_PREFIX,
)
- base = TrackpadStatusBarInputConsumer(context, base, inputMonitorCompat)
+ base =
+ TrackpadStatusBarInputConsumer(
+ context,
+ gestureState.displayId,
+ base,
+ inputMonitorCompat,
+ )
}
if (deviceState.isScreenPinningActive) {
@@ -322,7 +339,14 @@
reasonPrefix,
SUBSTRING_PREFIX,
)
- base = OneHandedModeInputConsumer(context, deviceState, base, inputMonitorCompat)
+ base =
+ OneHandedModeInputConsumer(
+ context,
+ gestureState.displayId,
+ deviceState,
+ base,
+ inputMonitorCompat,
+ )
}
if (deviceState.isAccessibilityMenuAvailable) {
@@ -332,7 +356,14 @@
reasonPrefix,
SUBSTRING_PREFIX,
)
- base = AccessibilityInputConsumer(context, deviceState, base, inputMonitorCompat)
+ base =
+ AccessibilityInputConsumer(
+ context,
+ gestureState.displayId,
+ deviceState,
+ base,
+ inputMonitorCompat,
+ )
}
} else {
val reasonPrefix = "device is not in gesture navigation mode"
@@ -354,7 +385,14 @@
reasonPrefix,
SUBSTRING_PREFIX,
)
- base = OneHandedModeInputConsumer(context, deviceState, base, inputMonitorCompat)
+ base =
+ OneHandedModeInputConsumer(
+ context,
+ gestureState.displayId,
+ deviceState,
+ base,
+ inputMonitorCompat,
+ )
}
}
logInputConsumerSelectionReason(base, reasonString)
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt b/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
index afdb403..fff85f6 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
@@ -399,6 +399,7 @@
val gestureState =
touchInteractionService.createGestureState(
+ focusedDisplayId,
GestureState.DEFAULT_STATE,
GestureState.TrackpadGestureType.NONE,
)
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 74f24ee..6710096 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -325,13 +325,6 @@
}
/**
- * @return the display id for the display that Launcher is running on.
- */
- public int getDisplayId() {
- return DEFAULT_DISPLAY;
- }
-
- /**
* @return whether the user has completed setup wizard
*/
public boolean isUserSetupComplete() {
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index cb11afa..64a8c25 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -318,7 +318,7 @@
mRecentsAnimationStartPending = getSystemUiProxy().startRecentsActivity(intent, options,
mCallbacks, gestureState.useSyntheticRecentsTransition());
RecentsDisplayModel.getINSTANCE().get(mCtx)
- .getRecentsWindowManager(mDeviceState.getDisplayId())
+ .getRecentsWindowManager(gestureState.getDisplayId())
.startRecentsWindow(mCallbacks);
} else {
mRecentsAnimationStartPending = getSystemUiProxy().startRecentsActivity(intent,
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index ffc0770..8bc8549 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -40,6 +40,7 @@
import android.app.PendingIntent;
import android.app.Service;
+import android.content.Context;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.Intent;
@@ -57,6 +58,7 @@
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.MotionEvent;
+import android.window.DesktopModeFlags;
import androidx.annotation.BinderThread;
import androidx.annotation.NonNull;
@@ -140,6 +142,9 @@
private static final ConstantItem<Boolean> HAS_ENABLED_QUICKSTEP_ONCE = backedUpItem(
"launcher.has_enabled_quickstep_once", false, EncryptionType.ENCRYPTED);
+ private static final DesktopModeFlags.DesktopModeFlag ENABLE_GESTURE_NAV_ON_CONNECTED_DISPLAYS =
+ new DesktopModeFlags.DesktopModeFlag(Flags::enableGestureNavOnConnectedDisplays, false);
+
private final TISBinder mTISBinder = new TISBinder(this);
/**
@@ -555,6 +560,7 @@
private @Nullable ResetGestureInputConsumer mResetGestureInputConsumer;
private GestureState mGestureState = DEFAULT_STATE;
+ private InputMonitorDisplayModel mInputMonitorDisplayModel;
private InputMonitorCompat mInputMonitorCompat;
private InputEventReceiver mInputEventReceiver;
@@ -604,9 +610,34 @@
ScreenOnTracker.INSTANCE.get(this).addListener(mScreenOnListener);
}
+ @Nullable
+ private InputEventReceiver getInputEventReceiver(int displayId) {
+ if (ENABLE_GESTURE_NAV_ON_CONNECTED_DISPLAYS.isTrue()) {
+ InputMonitorResource inputMonitorResource = mInputMonitorDisplayModel == null
+ ? null : mInputMonitorDisplayModel.getDisplayResource(displayId);
+ return inputMonitorResource == null ? null : inputMonitorResource.inputEventReceiver;
+ }
+ return mInputEventReceiver;
+ }
+
+ @Nullable
+ private InputMonitorCompat getInputMonitorCompat(int displayId) {
+ if (ENABLE_GESTURE_NAV_ON_CONNECTED_DISPLAYS.isTrue()) {
+ InputMonitorResource inputMonitorResource = mInputMonitorDisplayModel == null
+ ? null : mInputMonitorDisplayModel.getDisplayResource(displayId);
+ return inputMonitorResource == null ? null : inputMonitorResource.inputMonitorCompat;
+ }
+ return mInputMonitorCompat;
+ }
+
private void disposeEventHandlers(String reason) {
Log.d(TAG, "disposeEventHandlers: Reason: " + reason
+ " instance=" + System.identityHashCode(this));
+ if (ENABLE_GESTURE_NAV_ON_CONNECTED_DISPLAYS.isTrue()) {
+ if (mInputMonitorDisplayModel == null) return;
+ mInputMonitorDisplayModel.destroy();
+ return;
+ }
if (mInputEventReceiver != null) {
mInputEventReceiver.dispose();
mInputEventReceiver = null;
@@ -625,10 +656,13 @@
&& (mTrackpadsConnected.isEmpty())) {
return;
}
-
- mInputMonitorCompat = new InputMonitorCompat("swipe-up", mDeviceState.getDisplayId());
- mInputEventReceiver = mInputMonitorCompat.getInputReceiver(Looper.getMainLooper(),
- mMainChoreographer, this::onInputEvent);
+ if (ENABLE_GESTURE_NAV_ON_CONNECTED_DISPLAYS.isTrue()) {
+ mInputMonitorDisplayModel = new InputMonitorDisplayModel(this);
+ } else {
+ mInputMonitorCompat = new InputMonitorCompat("swipe-up", Display.DEFAULT_DISPLAY);
+ mInputEventReceiver = mInputMonitorCompat.getInputReceiver(Looper.getMainLooper(),
+ mMainChoreographer, this::onInputEvent);
+ }
mRotationTouchHelper.updateGestureTouchRegions();
}
@@ -787,8 +821,9 @@
}
private void onInputEvent(InputEvent ev) {
+ int displayId = ev.getDisplayId();
if (!(ev instanceof MotionEvent)) {
- ActiveGestureProtoLogProxy.logUnknownInputEvent(ev.toString());
+ ActiveGestureProtoLogProxy.logUnknownInputEvent(displayId, ev.toString());
return;
}
MotionEvent event = (MotionEvent) ev;
@@ -797,19 +832,19 @@
TestProtocol.SEQUENCE_TIS, "TouchInteractionService.onInputEvent", event);
if (!LockedUserState.get(this).isUserUnlocked()) {
- ActiveGestureProtoLogProxy.logOnInputEventUserLocked();
+ ActiveGestureProtoLogProxy.logOnInputEventUserLocked(displayId);
return;
}
NavigationMode currentNavMode = mDeviceState.getMode();
if (mGestureStartNavMode != null && mGestureStartNavMode != currentNavMode) {
ActiveGestureProtoLogProxy.logOnInputEventNavModeSwitched(
- mGestureStartNavMode.name(), currentNavMode.name());
+ displayId, mGestureStartNavMode.name(), currentNavMode.name());
event.setAction(ACTION_CANCEL);
} else if (mDeviceState.isButtonNavMode()
&& !mDeviceState.supportsAssistantGestureInButtonNav()
&& !isTrackpadMotionEvent(event)) {
- ActiveGestureProtoLogProxy.logOnInputEventThreeButtonNav();
+ ActiveGestureProtoLogProxy.logOnInputEventThreeButtonNav(displayId);
return;
}
@@ -825,12 +860,15 @@
}
if (mTaskAnimationManager.shouldIgnoreMotionEvents()) {
if (action == ACTION_DOWN || isHoverActionWithoutConsumer) {
- ActiveGestureProtoLogProxy.logOnInputIgnoringFollowingEvents();
+ ActiveGestureProtoLogProxy.logOnInputIgnoringFollowingEvents(displayId);
}
return;
}
}
+ InputMonitorCompat inputMonitorCompat = getInputMonitorCompat(displayId);
+ InputEventReceiver inputEventReceiver = getInputEventReceiver(displayId);
+
if (action == ACTION_DOWN || isHoverActionWithoutConsumer) {
mGestureStartNavMode = currentNavMode;
} else if (action == ACTION_UP || action == ACTION_CANCEL) {
@@ -857,10 +895,14 @@
if (mDeviceState.canTriggerAssistantAction(event)) {
reasonString.append(" and event can trigger assistant action, "
+ "consuming gesture for assistant action");
- mGestureState =
- createGestureState(mGestureState, getTrackpadGestureType(event));
+ mGestureState = createGestureState(
+ displayId, mGestureState, getTrackpadGestureType(event));
mUncheckedConsumer = tryCreateAssistantInputConsumer(
- this, mDeviceState, mInputMonitorCompat, mGestureState, event);
+ this,
+ mDeviceState,
+ inputMonitorCompat,
+ mGestureState,
+ event);
} else {
reasonString.append(" but event cannot trigger Assistant, "
+ "consuming gesture as no-op");
@@ -875,8 +917,8 @@
// Clone the previous gesture state since onConsumerAboutToBeSwitched might trigger
// onConsumerInactive and wipe the previous gesture state
GestureState prevGestureState = new GestureState(mGestureState);
- GestureState newGestureState = createGestureState(mGestureState,
- getTrackpadGestureType(event));
+ GestureState newGestureState = createGestureState(
+ displayId, mGestureState, getTrackpadGestureType(event));
mConsumer.onConsumerAboutToBeSwitched();
mGestureState = newGestureState;
mConsumer = newConsumer(
@@ -887,10 +929,10 @@
prevGestureState,
mGestureState,
mTaskAnimationManager,
- mInputMonitorCompat,
+ inputMonitorCompat,
getSwipeUpHandlerFactory(),
this::onConsumerInactive,
- mInputEventReceiver,
+ inputEventReceiver,
mTaskbarManager,
mSwipeUpProxyProvider,
mOverviewCommandHelper,
@@ -903,18 +945,19 @@
+ "consuming gesture for assistant action"
: "event is a trackpad multi-finger swipe and event can trigger assistant "
+ "action, consuming gesture for assistant action");
- mGestureState = createGestureState(mGestureState, getTrackpadGestureType(event));
+ mGestureState = createGestureState(
+ displayId, mGestureState, getTrackpadGestureType(event));
// Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we
// should not interrupt it. QuickSwitch assumes that interruption can only
// happen if the next gesture is also quick switch.
mUncheckedConsumer = tryCreateAssistantInputConsumer(
- this, mDeviceState, mInputMonitorCompat, mGestureState, event);
+ this, mDeviceState, inputMonitorCompat, mGestureState, event);
} else if (mDeviceState.canTriggerOneHandedAction(event)) {
reasonString.append("event can trigger one-handed action, "
+ "consuming gesture for one-handed action");
// Consume gesture event for triggering one handed feature.
- mUncheckedConsumer = new OneHandedModeInputConsumer(this, mDeviceState,
- InputConsumer.NO_OP, mInputMonitorCompat);
+ mUncheckedConsumer = new OneHandedModeInputConsumer(
+ this, displayId, mDeviceState, InputConsumer.NO_OP, inputMonitorCompat);
} else {
mUncheckedConsumer = InputConsumer.NO_OP;
}
@@ -929,25 +972,28 @@
if (mUncheckedConsumer != InputConsumer.NO_OP) {
switch (action) {
case ACTION_DOWN:
- ActiveGestureProtoLogProxy.logOnInputEventActionDown(reasonString);
+ ActiveGestureProtoLogProxy.logOnInputEventActionDown(displayId, reasonString);
// fall through
case ACTION_UP:
ActiveGestureProtoLogProxy.logOnInputEventActionUp(
(int) event.getRawX(),
(int) event.getRawY(),
action,
- MotionEvent.classificationToString(event.getClassification()));
+ MotionEvent.classificationToString(event.getClassification()),
+ displayId);
break;
case ACTION_MOVE:
ActiveGestureProtoLogProxy.logOnInputEventActionMove(
MotionEvent.actionToString(action),
MotionEvent.classificationToString(event.getClassification()),
- event.getPointerCount());
+ event.getPointerCount(),
+ displayId);
break;
default: {
ActiveGestureProtoLogProxy.logOnInputEventGenericAction(
MotionEvent.actionToString(action),
- MotionEvent.classificationToString(event.getClassification()));
+ MotionEvent.classificationToString(event.getClassification()),
+ displayId);
}
}
}
@@ -971,7 +1017,7 @@
}
if (cleanUpConsumer) {
- reset();
+ reset(displayId);
}
traceToken.close();
}
@@ -990,13 +1036,15 @@
return event.isHoverEvent() && event.getSource() == InputDevice.SOURCE_MOUSE;
}
- public GestureState createGestureState(GestureState previousGestureState,
+ public GestureState createGestureState(
+ int displayId,
+ GestureState previousGestureState,
GestureState.TrackpadGestureType trackpadGestureType) {
final GestureState gestureState;
TopTaskTracker.CachedTaskInfo taskInfo;
if (mTaskAnimationManager.isRecentsAnimationRunning()) {
- gestureState = new GestureState(mOverviewComponentObserver,
- ActiveGestureLog.INSTANCE.getLogId());
+ gestureState = new GestureState(
+ mOverviewComponentObserver, displayId, ActiveGestureLog.INSTANCE.getLogId());
TopTaskTracker.CachedTaskInfo previousTaskInfo = previousGestureState.getRunningTask();
// previousTaskInfo can be null iff previousGestureState == GestureState.DEFAULT_STATE
taskInfo = previousTaskInfo != null
@@ -1007,7 +1055,9 @@
gestureState.updatePreviouslyAppearedTaskIds(
previousGestureState.getPreviouslyAppearedTaskIds());
} else {
- gestureState = new GestureState(mOverviewComponentObserver,
+ gestureState = new GestureState(
+ mOverviewComponentObserver,
+ displayId,
ActiveGestureLog.INSTANCE.incrementLogId());
taskInfo = TopTaskTracker.INSTANCE.get(this).getCachedTopTask(false);
gestureState.updateRunningTask(taskInfo);
@@ -1035,17 +1085,18 @@
*/
private void onConsumerInactive(InputConsumer caller) {
if (mConsumer != null && mConsumer.getActiveConsumerInHierarchy() == caller) {
- reset();
+ reset(caller.getDisplayId());
}
}
- private void reset() {
+ private void reset(int displayId) {
mConsumer = mUncheckedConsumer = getDefaultInputConsumer();
mGestureState = DEFAULT_STATE;
// By default, use batching of the input events, but check receiver before using in the rare
// case that the monitor was disposed before the swipe settled
- if (mInputEventReceiver != null) {
- mInputEventReceiver.setBatchingEnabled(true);
+ InputEventReceiver inputEventReceiver = getInputEventReceiver(displayId);
+ if (inputEventReceiver != null) {
+ inputEventReceiver.setBatchingEnabled(true);
}
}
@@ -1125,6 +1176,11 @@
pw.println("Input state:");
pw.println("\tmInputMonitorCompat=" + mInputMonitorCompat);
pw.println("\tmInputEventReceiver=" + mInputEventReceiver);
+ if (mInputMonitorDisplayModel == null) {
+ pw.println("\tmInputMonitorDisplayModel=null");
+ } else {
+ mInputMonitorDisplayModel.dump("\t", pw);
+ }
DisplayController.INSTANCE.get(this).dump(pw);
pw.println("TouchState:");
RecentsViewContainer createdOverviewContainer = mOverviewComponentObserver == null ? null
@@ -1171,4 +1227,53 @@
gestureState, touchTimeMs, mTaskAnimationManager.isRecentsAnimationRunning(),
mInputConsumer, MSDLPlayerWrapper.INSTANCE.get(this));
}
+
+ /**
+ * Helper class that keeps track of external displays and prepares input monitors for each.
+ */
+ private class InputMonitorDisplayModel extends DisplayModel<InputMonitorResource> {
+
+ private InputMonitorDisplayModel(Context context) {
+ super(context);
+ registerDisplayListener();
+ }
+
+ @NonNull
+ @Override
+ public InputMonitorResource createDisplayResource(@NonNull Display display) {
+ return new InputMonitorResource(display.getDisplayId());
+ }
+ }
+
+ private class InputMonitorResource extends DisplayModel.DisplayResource {
+
+ private final int displayId;
+
+ private final InputMonitorCompat inputMonitorCompat;
+ private final InputEventReceiver inputEventReceiver;
+
+ private InputMonitorResource(int displayId) {
+ this.displayId = displayId;
+ inputMonitorCompat = new InputMonitorCompat("swipe-up", displayId);
+ inputEventReceiver = inputMonitorCompat.getInputReceiver(
+ Looper.getMainLooper(),
+ TouchInteractionService.this.mMainChoreographer,
+ TouchInteractionService.this::onInputEvent);
+ }
+
+ @Override
+ public void cleanup() {
+ inputEventReceiver.dispose();
+ inputMonitorCompat.dispose();
+ }
+
+ @Override
+ public void dump(String prefix , PrintWriter writer) {
+ writer.println(prefix + "InputMonitorResource:");
+
+ writer.println(prefix + "\tdisplayId=" + displayId);
+ writer.println(prefix + "\tinputMonitorCompat=" + inputMonitorCompat);
+ writer.println(prefix + "\tinputEventReceiver=" + inputEventReceiver);
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/fallback/window/RecentsDisplayModel.kt b/quickstep/src/com/android/quickstep/fallback/window/RecentsDisplayModel.kt
index 95a3ec2..116b8f2 100644
--- a/quickstep/src/com/android/quickstep/fallback/window/RecentsDisplayModel.kt
+++ b/quickstep/src/com/android/quickstep/fallback/window/RecentsDisplayModel.kt
@@ -17,19 +17,18 @@
package com.android.quickstep.fallback.window
import android.content.Context
-import android.util.Log
import android.view.Display
import com.android.launcher3.Flags
import com.android.launcher3.dagger.ApplicationContext
import com.android.launcher3.dagger.LauncherAppSingleton
import com.android.launcher3.util.DaggerSingletonObject
import com.android.launcher3.util.DaggerSingletonTracker
-import com.android.launcher3.util.Executors
import com.android.launcher3.util.WallpaperColorHints
import com.android.quickstep.DisplayModel
import com.android.quickstep.FallbackWindowInterface
import com.android.quickstep.dagger.QuickstepBaseAppComponent
import com.android.quickstep.fallback.window.RecentsDisplayModel.RecentsDisplayResource
+import java.io.PrintWriter
import javax.inject.Inject
@LauncherAppSingleton
@@ -58,42 +57,17 @@
init {
if (enableOverviewInWindow()) {
- displayManager.registerDisplayListener(displayListener, Executors.MAIN_EXECUTOR.handler)
- // In the scenario where displays were added before this display listener was
- // registered, we should store the RecentsDisplayResources for those displays
- // directly.
- displayManager.displays
- .filter { getDisplayResource(it.displayId) == null }
- .forEach { storeRecentsDisplayResource(it.displayId, it) }
+ registerDisplayListener()
tracker.addCloseable { destroy() }
}
}
- override fun createDisplayResource(displayId: Int) {
- if (DEBUG) Log.d(TAG, "createDisplayResource: displayId=$displayId")
- getDisplayResource(displayId)?.let {
- return
- }
- val display = displayManager.getDisplay(displayId)
- if (display == null) {
- if (DEBUG)
- Log.w(
- TAG,
- "createDisplayResource: could not create display for displayId=$displayId",
- Exception(),
- )
- return
- }
- storeRecentsDisplayResource(displayId, display)
- }
-
- private fun storeRecentsDisplayResource(displayId: Int, display: Display) {
- displayResourceArray[displayId] =
- RecentsDisplayResource(
- displayId,
- context.createDisplayContext(display),
- wallpaperColorHints.hints,
- )
+ override fun createDisplayResource(display: Display): RecentsDisplayResource {
+ return RecentsDisplayResource(
+ display.displayId,
+ context.createDisplayContext(display),
+ wallpaperColorHints.hints,
+ )
}
fun getRecentsWindowManager(displayId: Int): RecentsWindowManager? {
@@ -105,8 +79,8 @@
}
data class RecentsDisplayResource(
- var displayId: Int,
- var displayContext: Context,
+ val displayId: Int,
+ val displayContext: Context,
val wallpaperColorHints: Int,
) : DisplayResource() {
val recentsWindowManager = RecentsWindowManager(displayContext, wallpaperColorHints)
@@ -116,5 +90,15 @@
override fun cleanup() {
recentsWindowManager.destroy()
}
+
+ override fun dump(prefix: String, writer: PrintWriter) {
+ writer.println("${prefix}RecentsDisplayResource:")
+
+ writer.println("${prefix}\tdisplayId=${displayId}")
+ writer.println("${prefix}\tdisplayContext=${displayContext}")
+ writer.println("${prefix}\twallpaperColorHints=${wallpaperColorHints}")
+ writer.println("${prefix}\trecentsWindowManager=${recentsWindowManager}")
+ writer.println("${prefix}\tfallbackWindowInterface=${fallbackWindowInterface}")
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java
index 5adc960..1d85feb 100644
--- a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java
@@ -163,7 +163,7 @@
&& endTarget == GestureState.GestureEndTarget.HOME;
if (fromHomeToHome) {
RecentsWindowManager manager =
- mRecentsDisplayModel.getRecentsWindowManager(mDeviceState.getDisplayId());
+ mRecentsDisplayModel.getRecentsWindowManager(mGestureState.getDisplayId());
if (manager != null) {
manager.startHome(/* finishRecentsAnimation= */ false);
}
@@ -228,7 +228,7 @@
recentsCallback = () -> {
callback.run();
RecentsWindowManager manager =
- mRecentsDisplayModel.getRecentsWindowManager(mDeviceState.getDisplayId());
+ mRecentsDisplayModel.getRecentsWindowManager(mGestureState.getDisplayId());
if (manager != null) {
manager.startHome();
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
index 4e5d037..365c80c 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
@@ -56,9 +56,13 @@
private float mDownY;
private float mTotalY;
- public AccessibilityInputConsumer(Context context, RecentsAnimationDeviceState deviceState,
- InputConsumer delegate, InputMonitorCompat inputMonitor) {
- super(delegate, inputMonitor);
+ public AccessibilityInputConsumer(
+ Context context,
+ int displayId,
+ RecentsAnimationDeviceState deviceState,
+ InputConsumer delegate,
+ InputMonitorCompat inputMonitor) {
+ super(displayId, delegate, inputMonitor);
mContext = context;
mVelocityTracker = VelocityTracker.obtain();
mMinGestureDistance = context.getResources()
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
index 222ccd3..365014d 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
@@ -95,7 +95,7 @@
InputMonitorCompat inputMonitor,
RecentsAnimationDeviceState deviceState,
MotionEvent startEvent) {
- super(delegate, inputMonitor);
+ super(gestureState.getDisplayId(), delegate, inputMonitor);
final Resources res = context.getResources();
mContext = context;
mDragDistThreshold = res.getDimension(R.dimen.gestures_assistant_drag_threshold);
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/BubbleBarInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/BubbleBarInputConsumer.java
index b2e7015..86d7190 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/BubbleBarInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/BubbleBarInputConsumer.java
@@ -57,12 +57,19 @@
private final int mTouchSlop;
private final PointF mDownPos = new PointF();
private final PointF mLastPos = new PointF();
+
+ private final int mDisplayId;
+
private long mDownTime;
private final long mTimeForLongPress;
private int mActivePointerId = INVALID_POINTER_ID;
- public BubbleBarInputConsumer(Context context, BubbleControllers bubbleControllers,
+ public BubbleBarInputConsumer(
+ Context context,
+ int displayId,
+ BubbleControllers bubbleControllers,
InputMonitorCompat inputMonitorCompat) {
+ mDisplayId = displayId;
mBubbleStashController = bubbleControllers.bubbleStashController;
mBubbleBarViewController = bubbleControllers.bubbleBarViewController;
mBubbleBarSwipeController = bubbleControllers.bubbleBarSwipeController.orElse(null);
@@ -78,6 +85,11 @@
}
@Override
+ public int getDisplayId() {
+ return mDisplayId;
+ }
+
+ @Override
public void onMotionEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action) {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
index 4afd92a..0b1a6c4 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
@@ -17,15 +17,24 @@
protected final InputConsumer mDelegate;
protected final InputMonitorCompat mInputMonitor;
+ private final int mDisplayId;
+
protected int mState;
- public DelegateInputConsumer(InputConsumer delegate, InputMonitorCompat inputMonitor) {
+ public DelegateInputConsumer(
+ int displayId, InputConsumer delegate, InputMonitorCompat inputMonitor) {
+ mDisplayId = displayId;
mDelegate = delegate;
mInputMonitor = inputMonitor;
mState = STATE_INACTIVE;
}
@Override
+ public int getDisplayId() {
+ return mDisplayId;
+ }
+
+ @Override
public InputConsumer getActiveConsumerInHierarchy() {
if (mState == STATE_ACTIVE) {
return this;
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index 503b900..e192702 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -108,8 +108,11 @@
private RecentsAnimationController mRecentsAnimationController;
- public DeviceLockedInputConsumer(Context context, RecentsAnimationDeviceState deviceState,
- TaskAnimationManager taskAnimationManager, GestureState gestureState,
+ public DeviceLockedInputConsumer(
+ Context context,
+ RecentsAnimationDeviceState deviceState,
+ TaskAnimationManager taskAnimationManager,
+ GestureState gestureState,
InputMonitorCompat inputMonitorCompat) {
mContext = context;
mTaskAnimationManager = taskAnimationManager;
@@ -138,6 +141,11 @@
}
@Override
+ public int getDisplayId() {
+ return mGestureState.getDisplayId();
+ }
+
+ @Override
public void onMotionEvent(MotionEvent ev) {
if (mVelocityTracker == null) {
return;
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
index a703c23..e7e2074 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
@@ -74,10 +74,14 @@
private MotionEvent mCurrentMotionEvent; // Most recent motion event.
private boolean mDeepPressLogged; // Whether deep press has been logged for the current touch.
- public NavHandleLongPressInputConsumer(Context context, InputConsumer delegate,
- InputMonitorCompat inputMonitor, RecentsAnimationDeviceState deviceState,
- NavHandle navHandle, GestureState gestureState) {
- super(delegate, inputMonitor);
+ public NavHandleLongPressInputConsumer(
+ Context context,
+ InputConsumer delegate,
+ InputMonitorCompat inputMonitor,
+ RecentsAnimationDeviceState deviceState,
+ NavHandle navHandle,
+ GestureState gestureState) {
+ super(gestureState.getDisplayId(), delegate, inputMonitor);
mScreenWidth = DisplayController.INSTANCE.get(context).getInfo().currentSize.x;
mDeepPressEnabled = DeviceConfigWrapper.get().getEnableLpnhDeepPress();
ContextualSearchStateManager contextualSearchStateManager =
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
index 83b556d..67cb992 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
@@ -61,9 +61,13 @@
private boolean mPassedSlop;
private boolean mIsStopGesture;
- public OneHandedModeInputConsumer(Context context, RecentsAnimationDeviceState deviceState,
- InputConsumer delegate, InputMonitorCompat inputMonitor) {
- super(delegate, inputMonitor);
+ public OneHandedModeInputConsumer(
+ Context context,
+ int displayId,
+ RecentsAnimationDeviceState deviceState,
+ InputConsumer delegate,
+ InputMonitorCompat inputMonitor) {
+ super(displayId, delegate, inputMonitor);
mContext = context;
mDeviceState = deviceState;
mDragDistThreshold = context.getResources().getDimensionPixelSize(
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index dd2b2be..5963a7c 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -126,11 +126,17 @@
// The callback called upon finishing the recents transition if it was force-canceled
private Runnable mForceFinishRecentsTransitionCallback;
- public OtherActivityInputConsumer(Context base, RecentsAnimationDeviceState deviceState,
- TaskAnimationManager taskAnimationManager, GestureState gestureState,
- boolean isDeferredDownTarget, Consumer<OtherActivityInputConsumer> onCompleteCallback,
- InputMonitorCompat inputMonitorCompat, InputEventReceiver inputEventReceiver,
- boolean disableHorizontalSwipe, Factory handlerFactory) {
+ public OtherActivityInputConsumer(
+ Context base,
+ RecentsAnimationDeviceState deviceState,
+ TaskAnimationManager taskAnimationManager,
+ GestureState gestureState,
+ boolean isDeferredDownTarget,
+ Consumer<OtherActivityInputConsumer> onCompleteCallback,
+ InputMonitorCompat inputMonitorCompat,
+ InputEventReceiver inputEventReceiver,
+ boolean disableHorizontalSwipe,
+ Factory handlerFactory) {
super(base);
mDeviceState = deviceState;
mNavBarPosition = mDeviceState.getNavBarPosition();
@@ -166,6 +172,11 @@
}
@Override
+ public int getDisplayId() {
+ return mGestureState.getDisplayId();
+ }
+
+ @Override
public boolean isConsumerDetachedFromGesture() {
return true;
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
index a236eca..4658cb0 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
@@ -55,12 +55,16 @@
private final int[] mLocationOnScreen = new int[2];
private final boolean mStartingInActivityBounds;
+
private boolean mTargetHandledTouch;
private boolean mHasSetTouchModeForFirstDPadEvent;
private boolean mIsWaitingForAttachToWindow;
- public OverviewInputConsumer(GestureState gestureState, T container,
- @Nullable InputMonitorCompat inputMonitor, boolean startingInActivityBounds) {
+ public OverviewInputConsumer(
+ GestureState gestureState,
+ T container,
+ @Nullable InputMonitorCompat inputMonitor,
+ boolean startingInActivityBounds) {
mContainer = container;
mInputMonitor = inputMonitor;
mStartingInActivityBounds = startingInActivityBounds;
@@ -77,6 +81,11 @@
}
@Override
+ public int getDisplayId() {
+ return mGestureState.getDisplayId();
+ }
+
+ @Override
public boolean allowInterceptByParent() {
return !mTargetHandledTouch;
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
index be47df9..7838e86 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
@@ -43,9 +43,12 @@
private final TriggerSwipeUpTouchTracker mTriggerSwipeUpTracker;
private final GestureState mGestureState;
- public OverviewWithoutFocusInputConsumer(Context context,
- RecentsAnimationDeviceState deviceState, GestureState gestureState,
- InputMonitorCompat inputMonitor, boolean disableHorizontalSwipe) {
+ public OverviewWithoutFocusInputConsumer(
+ Context context,
+ RecentsAnimationDeviceState deviceState,
+ GestureState gestureState,
+ InputMonitorCompat inputMonitor,
+ boolean disableHorizontalSwipe) {
mContext = context;
mGestureState = gestureState;
mInputMonitor = inputMonitor;
@@ -59,6 +62,11 @@
}
@Override
+ public int getDisplayId() {
+ return mGestureState.getDisplayId();
+ }
+
+ @Override
public boolean allowInterceptByParent() {
return !mTriggerSwipeUpTracker.interceptedTouch();
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
index c91bebe..52aaa03 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
@@ -89,9 +89,12 @@
private RecentsAnimationController mRecentsAnimationController;
private Boolean mFlingEndsOnHome;
- public ProgressDelegateInputConsumer(Context context,
- TaskAnimationManager taskAnimationManager, GestureState gestureState,
- InputMonitorCompat inputMonitorCompat, AnimatedFloat progress) {
+ public ProgressDelegateInputConsumer(
+ Context context,
+ TaskAnimationManager taskAnimationManager,
+ GestureState gestureState,
+ InputMonitorCompat inputMonitorCompat,
+ AnimatedFloat progress) {
mContext = context;
mTaskAnimationManager = taskAnimationManager;
mGestureState = gestureState;
@@ -118,6 +121,11 @@
}
@Override
+ public int getDisplayId() {
+ return mGestureState.getDisplayId();
+ }
+
+ @Override
public void onMotionEvent(MotionEvent ev) {
if (mFlingEndsOnHome == null) {
mSwipeDetector.onTouchEvent(ev);
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
index d73c23f..9dc27de 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
@@ -36,9 +36,12 @@
private final float mMotionPauseMinDisplacement;
private final MotionPauseDetector mMotionPauseDetector;
+ private final int mDisplayId;
+
private float mTouchDownY;
public ScreenPinnedInputConsumer(Context context, GestureState gestureState) {
+ mDisplayId = gestureState.getDisplayId();
mMotionPauseMinDisplacement = context.getResources().getDimension(
R.dimen.motion_pause_detector_min_displacement_from_app);
mMotionPauseDetector = new MotionPauseDetector(context, true /* makePauseHarderToTrigger*/);
@@ -61,6 +64,11 @@
}
@Override
+ public int getDisplayId() {
+ return mDisplayId;
+ }
+
+ @Override
public void onMotionEvent(MotionEvent ev) {
float y = ev.getY();
switch (ev.getAction()) {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java
index 871d075..ad1a01b 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java
@@ -47,11 +47,15 @@
private final InputMonitorCompat mInputMonitor;
private final TriggerSwipeUpTouchTracker mTriggerSwipeUpTracker;
+ private final int mDisplayId;
+
public SysUiOverlayInputConsumer(
Context context,
+ int displayId,
RecentsAnimationDeviceState deviceState,
InputMonitorCompat inputMonitor) {
mContext = context;
+ mDisplayId = displayId;
mInputMonitor = inputMonitor;
mTriggerSwipeUpTracker = new TriggerSwipeUpTouchTracker(context, true,
deviceState.getNavBarPosition(), this);
@@ -63,6 +67,11 @@
}
@Override
+ public int getDisplayId() {
+ return mDisplayId;
+ }
+
+ @Override
public boolean allowInterceptByParent() {
return !mTriggerSwipeUpTracker.interceptedTouch();
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
index 49bff8d..dbe6e14 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
@@ -89,10 +89,14 @@
// Velocity defined as dp per s
private float mTaskbarSlowVelocityYThreshold;
- public TaskbarUnstashInputConsumer(Context context, InputConsumer delegate,
- InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext,
- OverviewCommandHelper overviewCommandHelper, GestureState gestureState) {
- super(delegate, inputMonitor);
+ public TaskbarUnstashInputConsumer(
+ Context context,
+ InputConsumer delegate,
+ InputMonitorCompat inputMonitor,
+ TaskbarActivityContext taskbarActivityContext,
+ OverviewCommandHelper overviewCommandHelper,
+ GestureState gestureState) {
+ super(gestureState.getDisplayId(), delegate, inputMonitor);
mTaskbarActivityContext = taskbarActivityContext;
mOverviewCommandHelper = overviewCommandHelper;
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TrackpadStatusBarInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TrackpadStatusBarInputConsumer.java
index f3e21e1..a53a395 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TrackpadStatusBarInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TrackpadStatusBarInputConsumer.java
@@ -35,9 +35,12 @@
private final PointF mDown = new PointF();
private boolean mHasPassedTouchSlop;
- public TrackpadStatusBarInputConsumer(Context context, InputConsumer delegate,
+ public TrackpadStatusBarInputConsumer(
+ Context context,
+ int displayId,
+ InputConsumer delegate,
InputMonitorCompat inputMonitor) {
- super(delegate, inputMonitor);
+ super(displayId, delegate, inputMonitor);
mSystemUiProxy = SystemUiProxy.INSTANCE.get(context);
mTouchSlop = 2 * ViewConfiguration.get(context).getScaledTouchSlop();
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index e265e61..c63cddf 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -34,6 +34,7 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.view.Display;
import android.view.View;
import android.view.ViewOutlineProvider;
@@ -84,8 +85,8 @@
SwipeUpGestureTutorialController(TutorialFragment tutorialFragment, TutorialType tutorialType) {
super(tutorialFragment, tutorialType);
- mTaskViewSwipeUpAnimation = new ViewSwipeUpAnimation(mContext,
- new GestureState(OverviewComponentObserver.INSTANCE.get(mContext), -1));
+ mTaskViewSwipeUpAnimation = new ViewSwipeUpAnimation(mContext, new GestureState(
+ OverviewComponentObserver.INSTANCE.get(mContext), Display.DEFAULT_DISPLAY, -1));
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext)
.getDeviceProfile(mContext)
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index b844079..661fe89 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -378,6 +378,29 @@
}
/**
+ * Calculates the crop rect for desktop tasks given the current matrix.
+ */
+ private void calculateDesktopTaskCropRect() {
+ // The approach here is to map a rect that represents the untransformed thumbnail position
+ // using the current matrix. This will give us a rect that can be intersected with
+ // [mFullTaskSize]. Using the intersection, we then compute how much of the task window that
+ // needs to be cropped (which will be nothing if the window is entirely within the desktop).
+ mTempRectF.set(0, 0, mThumbnailPosition.width(), mThumbnailPosition.height());
+ mMatrix.mapRect(mTempRectF);
+
+ float offsetX = mTempRectF.left;
+ float offsetY = mTempRectF.top;
+ float scale = mThumbnailPosition.width() / mTempRectF.width();
+
+ if (mTempRectF.intersect(mFullTaskSize.left, mFullTaskSize.top, mFullTaskSize.right,
+ mFullTaskSize.bottom)) {
+ mTempRectF.offset(-offsetX, -offsetY);
+ mTempRectF.scale(scale);
+ mTempRectF.round(mTmpCropRect);
+ }
+ }
+
+ /**
* Applies the rotation on the matrix to so that it maps from launcher coordinate space to
* window coordinate space.
*/
@@ -442,7 +465,16 @@
mMatrix.postTranslate(mTaskRect.left, mTaskRect.top);
if (mTaskRectTransform != null) {
mMatrix.postConcat(mTaskRectTransform);
+
+ // Calculate cropping for desktop tasks. The order is important since it uses the
+ // current matrix. Therefore we calculate it here, after applying the task rect
+ // transform, but before applying scaling/translation that affects the whole
+ // recentsview.
+ if (mIsDesktopTask) {
+ calculateDesktopTaskCropRect();
+ }
}
+
mOrientationState.getOrientationHandler().setPrimary(mMatrix, MATRIX_POST_TRANSLATE,
taskPrimaryTranslation.value);
mOrientationState.getOrientationHandler().setSecondary(mMatrix, MATRIX_POST_TRANSLATE,
diff --git a/quickstep/src/com/android/quickstep/views/IconAppChipView.kt b/quickstep/src/com/android/quickstep/views/IconAppChipView.kt
index 8d53552..c20aa11 100644
--- a/quickstep/src/com/android/quickstep/views/IconAppChipView.kt
+++ b/quickstep/src/com/android/quickstep/views/IconAppChipView.kt
@@ -428,7 +428,6 @@
private const val INDEX_CONTENT_ALPHA = 0
private const val INDEX_COLOR_FILTER_ALPHA = 1
private const val INDEX_MODAL_ALPHA = 2
-
/** Used to hide the app chip for 90:10 flex split. */
private const val INDEX_MINIMUM_RATIO_ALPHA = 3
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt
index 276318c..f58ecbc 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskView.kt
@@ -309,8 +309,10 @@
// progress: 0 = show icon and no insets; 1 = don't show icon and show full insets.
protected var fullscreenProgress = 0f
set(value) {
- field = Utilities.boundToRange(value, 0f, 1f)
- onFullscreenProgressChanged(field)
+ if (value != field) {
+ field = Utilities.boundToRange(value, 0f, 1f)
+ onFullscreenProgressChanged(field)
+ }
}
// gridProgress 0 = carousel; 1 = 2 row grid.
@@ -490,8 +492,10 @@
// 1 = The TaskView is settled and no longer transitioning
private var settledProgress = 1f
set(value) {
- field = value
- onSettledProgressUpdated(field)
+ if (value != field) {
+ field = value
+ onSettledProgressUpdated(field)
+ }
}
private val settledProgressPropertyFactory =
@@ -1687,7 +1691,9 @@
protected open fun onFullscreenProgressChanged(fullscreenProgress: Float) {
taskContainers.forEach {
- it.iconView.setVisibility(if (fullscreenProgress < 1) VISIBLE else INVISIBLE)
+ if (!enableOverviewIconMenu()) {
+ it.iconView.setVisibility(if (fullscreenProgress < 1) VISIBLE else INVISIBLE)
+ }
it.overlay.setFullscreenProgress(fullscreenProgress)
}
settledProgressFullscreen =
diff --git a/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureProtoLogProxy.java b/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureProtoLogProxy.java
index 37c64cf..18a5338 100644
--- a/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureProtoLogProxy.java
+++ b/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureProtoLogProxy.java
@@ -159,31 +159,37 @@
ProtoLog.d(ACTIVE_GESTURE_LOG, "cleanUpRecentsAnimation");
}
- public static void logOnInputEventUserLocked() {
- ActiveGestureLog.INSTANCE.addLog(
- "TIS.onInputEvent: Cannot process input event: user is locked");
+ public static void logOnInputEventUserLocked(int displayId) {
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "TIS.onInputEvent(displayId=%d): Cannot process input event: user is locked",
+ displayId));
if (!enableActiveGestureProtoLog() || !isProtoLogInitialized()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
- "TIS.onInputEvent: Cannot process input event: user is locked");
+ "TIS.onInputEvent(displayId=%d): Cannot process input event: user is locked",
+ displayId);
}
- public static void logOnInputIgnoringFollowingEvents() {
- ActiveGestureLog.INSTANCE.addLog("TIS.onMotionEvent: A new gesture has been started, "
+ public static void logOnInputIgnoringFollowingEvents(int displayId) {
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "TIS.onMotionEvent(displayId=%d): A new gesture has been started, "
+ "but a previously-requested recents animation hasn't started. "
- + "Ignoring all following motion events.",
+ + "Ignoring all following motion events.", displayId),
RECENTS_ANIMATION_START_PENDING);
if (!enableActiveGestureProtoLog() || !isProtoLogInitialized()) return;
- ProtoLog.d(ACTIVE_GESTURE_LOG, "TIS.onMotionEvent: A new gesture has been started, "
- + "but a previously-requested recents animation hasn't started. "
- + "Ignoring all following motion events.");
+ ProtoLog.d(ACTIVE_GESTURE_LOG,
+ "TIS.onMotionEvent(displayId=%d): A new gesture has been started, "
+ + "but a previously-requested recents animation hasn't started. "
+ + "Ignoring all following motion events.", displayId);
}
- public static void logOnInputEventThreeButtonNav() {
- ActiveGestureLog.INSTANCE.addLog("TIS.onInputEvent: Cannot process input event: "
- + "using 3-button nav and event is not a trackpad event");
+ public static void logOnInputEventThreeButtonNav(int displayId) {
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "TIS.onInputEvent(displayId=%d): Cannot process input event: "
+ + "using 3-button nav and event is not a trackpad event", displayId));
if (!enableActiveGestureProtoLog() || !isProtoLogInitialized()) return;
- ProtoLog.d(ACTIVE_GESTURE_LOG, "TIS.onInputEvent: Cannot process input event: "
- + "using 3-button nav and event is not a trackpad event");
+ ProtoLog.d(ACTIVE_GESTURE_LOG,
+ "TIS.onInputEvent(displayId=%d): Cannot process input event: "
+ + "using 3-button nav and event is not a trackpad event", displayId);
}
public static void logPreloadRecentsAnimation() {
@@ -322,61 +328,84 @@
}
public static void logOnInputEventActionUp(
- int x, int y, int action, @NonNull String classification) {
+ int x, int y, int action, @NonNull String classification, int displayId) {
String actionString = MotionEvent.actionToString(action);
ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "onMotionEvent(%d, %d): %s, %s", x, y, actionString, classification),
+ "onMotionEvent(%d, %d): %s, %s, displayId=%d",
+ x,
+ y,
+ actionString,
+ classification,
+ displayId),
/* gestureEvent= */ action == ACTION_DOWN
? MOTION_DOWN
: MOTION_UP);
if (!enableActiveGestureProtoLog() || !isProtoLogInitialized()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
- "onMotionEvent(%d, %d): %s, %s", x, y, actionString, classification);
+ "onMotionEvent(%d, %d): %s, %s, displayId=%d",
+ x,
+ y,
+ actionString,
+ classification,
+ displayId);
}
public static void logOnInputEventActionMove(
- @NonNull String action, @NonNull String classification, int pointerCount) {
+ @NonNull String action,
+ @NonNull String classification,
+ int pointerCount,
+ int displayId) {
ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "onMotionEvent: %s, %s, pointerCount: %d",
+ "onMotionEvent: %s, %s, pointerCount: %d, displayId=%d",
action,
classification,
- pointerCount),
+ pointerCount,
+ displayId),
MOTION_MOVE);
if (!enableActiveGestureProtoLog() || !isProtoLogInitialized()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
- "onMotionEvent: %s, %s, pointerCount: %d", action, classification, pointerCount);
+ "onMotionEvent: %s, %s, pointerCount: %d, displayId=%d",
+ action,
+ classification,
+ pointerCount,
+ displayId);
}
public static void logOnInputEventGenericAction(
- @NonNull String action, @NonNull String classification) {
+ @NonNull String action, @NonNull String classification, int displayId) {
ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "onMotionEvent: %s, %s", action, classification));
+ "onMotionEvent: %s, %s, displayId=%d", action, classification, displayId));
if (!enableActiveGestureProtoLog() || !isProtoLogInitialized()) return;
- ProtoLog.d(ACTIVE_GESTURE_LOG, "onMotionEvent: %s, %s", action, classification);
+ ProtoLog.d(ACTIVE_GESTURE_LOG,
+ "onMotionEvent: %s, %s, displayId=%d", action, classification, displayId);
}
public static void logOnInputEventNavModeSwitched(
- @NonNull String startNavMode, @NonNull String currentNavMode) {
+ int displayId, @NonNull String startNavMode, @NonNull String currentNavMode) {
ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "TIS.onInputEvent: Navigation mode switched mid-gesture (%s -> %s); "
+ "TIS.onInputEvent(displayId=%d): Navigation mode switched mid-gesture (%s -> %s); "
+ "cancelling gesture.",
+ displayId,
startNavMode,
currentNavMode),
NAVIGATION_MODE_SWITCHED);
if (!enableActiveGestureProtoLog() || !isProtoLogInitialized()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
- "TIS.onInputEvent: Navigation mode switched mid-gesture (%s -> %s); "
+ "TIS.onInputEvent(displayId=%d): Navigation mode switched mid-gesture (%s -> %s); "
+ "cancelling gesture.",
+ displayId,
startNavMode,
currentNavMode);
}
- public static void logUnknownInputEvent(@NonNull String event) {
+ public static void logUnknownInputEvent(int displayId, @NonNull String event) {
ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "TIS.onInputEvent: Cannot process input event: received unknown event %s", event));
+ "TIS.onInputEvent(displayId=%d): Cannot process input event: "
+ + "received unknown event %s", displayId, event));
if (!enableActiveGestureProtoLog() || !isProtoLogInitialized()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
- "TIS.onInputEvent: Cannot process input event: received unknown event %s", event);
+ "TIS.onInputEvent(displayId=%d): Cannot process input event: "
+ + "received unknown event %s", displayId, event);
}
public static void logFinishRunningRecentsAnimation(boolean toHome) {
@@ -433,11 +462,13 @@
ProtoLog.d(ACTIVE_GESTURE_LOG, "Launching side task id=%d", taskId);
}
- public static void logOnInputEventActionDown(@NonNull ActiveGestureLog.CompoundString reason) {
+ public static void logOnInputEventActionDown(
+ int displayId, @NonNull ActiveGestureLog.CompoundString reason) {
ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "TIS.onMotionEvent: ").append(reason));
+ "TIS.onMotionEvent(displayId=%d): ", displayId).append(reason));
if (!enableActiveGestureProtoLog() || !isProtoLogInitialized()) return;
- ProtoLog.d(ACTIVE_GESTURE_LOG, "TIS.onMotionEvent: %s", reason.toString());
+ ProtoLog.d(ACTIVE_GESTURE_LOG,
+ "TIS.onMotionEvent(displayId=%d): %s", displayId, reason.toString());
}
public static void logStartNewTask(@NonNull ActiveGestureLog.CompoundString tasks) {
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/DisplayModelTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/DisplayModelTest.kt
index a939e84..fa7907f 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/DisplayModelTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/DisplayModelTest.kt
@@ -21,6 +21,7 @@
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import java.io.PrintWriter
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Test
@@ -37,25 +38,29 @@
override fun cleanup() {
isCleanupCalled = true
}
+
+ override fun dump(prefix: String, writer: PrintWriter) {
+ // No-Op
+ }
}
private val testableDisplayModel =
object : DisplayModel<TestableResource>(context) {
- override fun createDisplayResource(displayId: Int) {
- displayResourceArray.put(displayId, TestableResource())
+ override fun createDisplayResource(display: Display): TestableResource {
+ return TestableResource()
}
}
@Test
fun testCreate() {
- testableDisplayModel.createDisplayResource(Display.DEFAULT_DISPLAY)
+ testableDisplayModel.storeDisplayResource(Display.DEFAULT_DISPLAY)
val resource = testableDisplayModel.getDisplayResource(Display.DEFAULT_DISPLAY)
assertNotNull(resource)
}
@Test
fun testCleanAndDelete() {
- testableDisplayModel.createDisplayResource(Display.DEFAULT_DISPLAY)
+ testableDisplayModel.storeDisplayResource(Display.DEFAULT_DISPLAY)
val resource = testableDisplayModel.getDisplayResource(Display.DEFAULT_DISPLAY)!!
assertNotNull(resource)
testableDisplayModel.deleteDisplayResource(Display.DEFAULT_DISPLAY)
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt
index af741f6..35f1218 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt
@@ -91,7 +91,14 @@
.bindRotationHelper(mock(RotationTouchHelper::class.java))
.bindRecentsState(mock(RecentsAnimationDeviceState::class.java))
)
- gestureState = spy(GestureState(OverviewComponentObserver.INSTANCE.get(sandboxContext), 0))
+ gestureState =
+ spy(
+ GestureState(
+ OverviewComponentObserver.INSTANCE.get(sandboxContext),
+ DEFAULT_DISPLAY,
+ 0,
+ )
+ )
underTest =
LauncherSwipeHandlerV2(
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/window/RecentsDisplayModelTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/window/RecentsDisplayModelTest.kt
index 44ea73e..0119679 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/window/RecentsDisplayModelTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/window/RecentsDisplayModelTest.kt
@@ -88,16 +88,16 @@
@Test
fun testCreateSeparateInstances() {
- val display = Display.DEFAULT_DISPLAY + 1
- runOnMainSync { recentsDisplayModel.createDisplayResource(display) }
+ val displayId = Display.DEFAULT_DISPLAY + 1
+ runOnMainSync { recentsDisplayModel.storeDisplayResource(displayId) }
val defaultManager = recentsDisplayModel.getRecentsWindowManager(Display.DEFAULT_DISPLAY)
- val secondaryManager = recentsDisplayModel.getRecentsWindowManager(display)
+ val secondaryManager = recentsDisplayModel.getRecentsWindowManager(displayId)
Assert.assertNotSame(defaultManager, secondaryManager)
val defaultInterface =
recentsDisplayModel.getFallbackWindowInterface(Display.DEFAULT_DISPLAY)
- val secondInterface = recentsDisplayModel.getFallbackWindowInterface(display)
+ val secondInterface = recentsDisplayModel.getFallbackWindowInterface(displayId)
Assert.assertNotSame(defaultInterface, secondInterface)
}
diff --git a/quickstep/tests/src/com/android/quickstep/InputConsumerUtilsTest.java b/quickstep/tests/src/com/android/quickstep/InputConsumerUtilsTest.java
index e2ca91a..ef6f55e 100644
--- a/quickstep/tests/src/com/android/quickstep/InputConsumerUtilsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/InputConsumerUtilsTest.java
@@ -30,6 +30,7 @@
import android.annotation.Nullable;
import android.os.Looper;
import android.view.Choreographer;
+import android.view.Display;
import android.view.MotionEvent;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -99,7 +100,8 @@
@Rule public final SandboxApplication mContext = new SandboxApplication();
- @NonNull private final InputMonitorCompat mInputMonitorCompat = new InputMonitorCompat("", 0);
+ @NonNull private final InputMonitorCompat mInputMonitorCompat =
+ new InputMonitorCompat("", Display.DEFAULT_DISPLAY);
private TaskAnimationManager mTaskAnimationManager;
private InputChannelCompat.InputEventReceiver mInputEventReceiver;
@@ -196,7 +198,6 @@
@Before
public void setupDeviceState() {
- when(mDeviceState.getDisplayId()).thenReturn(0);
when(mDeviceState.canStartTrackpadGesture()).thenReturn(true);
when(mDeviceState.canStartSystemGesture()).thenReturn(true);
when(mDeviceState.isFullyGesturalNavMode()).thenReturn(true);
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 1c87bce..1af48a9 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -433,18 +433,17 @@
(Math.abs(recentsView.getTopRowTaskCountForTablet()
- recentsView.getBottomRowTaskCountForTablet()) <= 1)));
- // TODO(b/308841019): Re-enable after fixing Overview jank when dismiss
-// // Test dismissing more tasks.
-// assertIsInState(
-// "Launcher internal state didn't remain in Overview", ExpectedState.OVERVIEW);
-// overview.getCurrentTask().dismiss();
-// assertIsInState(
-// "Launcher internal state didn't remain in Overview", ExpectedState.OVERVIEW);
-// overview.getCurrentTask().dismiss();
-// runOnRecentsView(recentsView -> assertTrue(
-// "Grid did not rebalance after multiple dismissals",
-// (Math.abs(recentsView.getTopRowTaskCountForTablet()
-// - recentsView.getBottomRowTaskCountForTablet()) <= 1)));
+ // Test dismissing more tasks.
+ assertIsInState(
+ "Launcher internal state didn't remain in Overview", ExpectedState.OVERVIEW);
+ overview.getCurrentTask().dismiss();
+ assertIsInState(
+ "Launcher internal state didn't remain in Overview", ExpectedState.OVERVIEW);
+ overview.getCurrentTask().dismiss();
+ runOnRecentsView(recentsView -> assertTrue(
+ "Grid did not rebalance after multiple dismissals",
+ (Math.abs(recentsView.getTopRowTaskCountForTablet()
+ - recentsView.getBottomRowTaskCountForTablet()) <= 1)));
// Test dismissing all tasks.
mLauncher.goHome().switchToOverview().dismissAllTasks();
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 613b430..c4086b2 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -521,17 +521,13 @@
mDragObject.dragComplete = true;
if (mIsInPreDrag) {
- if (dropTarget != null) {
- dropTarget.onDragExit(mDragObject);
- }
- return;
+ mDragObject.cancelled = true;
}
-
// Drop onto the target.
boolean accepted = false;
if (dropTarget != null) {
dropTarget.onDragExit(mDragObject);
- if (dropTarget.acceptDrop(mDragObject)) {
+ if (!mIsInPreDrag && dropTarget.acceptDrop(mDragObject)) {
if (flingAnimation != null) {
flingAnimation.run();
} else {
diff --git a/src/com/android/launcher3/dragndrop/LauncherDragController.java b/src/com/android/launcher3/dragndrop/LauncherDragController.java
index 4aa3673..e3b8965 100644
--- a/src/com/android/launcher3/dragndrop/LauncherDragController.java
+++ b/src/com/android/launcher3/dragndrop/LauncherDragController.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.dragndrop;
+import static android.view.View.VISIBLE;
+
import static com.android.launcher3.AbstractFloatingView.TYPE_DISCOVERY_BOUNCE;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
import static com.android.launcher3.LauncherState.EDIT_MODE;
@@ -25,6 +27,7 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.HapticFeedbackConstants;
+import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
@@ -33,10 +36,13 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
+import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
+import com.android.launcher3.dragndrop.DragOptions.PreDragCondition;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.util.TouchUtil;
import com.android.launcher3.widget.util.WidgetDragScaleUtils;
/**
@@ -47,6 +53,9 @@
private static final boolean PROFILE_DRAWING_DURING_DRAG = false;
private final FlingToDeleteHelper mFlingToDeleteHelper;
+ /** Whether or not the drag operation is triggered by mouse right click. */
+ private boolean mIsInMouseRightClick = false;
+
public LauncherDragController(Launcher launcher) {
super(launcher);
mFlingToDeleteHelper = new FlingToDeleteHelper(launcher);
@@ -69,6 +78,27 @@
android.os.Debug.startMethodTracing("Launcher");
}
+ if (mIsInMouseRightClick && options.preDragCondition == null
+ && originalView instanceof View v) {
+ options.preDragCondition = new PreDragCondition() {
+
+ @Override
+ public boolean shouldStartDrag(double distanceDragged) {
+ return false;
+ }
+
+ @Override
+ public void onPreDragStart(DragObject dragObject) {
+ // Set it to visible so the text of FolderIcon would not flash (avoid it from
+ // being invisible and then visible)
+ v.setVisibility(VISIBLE);
+ }
+
+ @Override
+ public void onPreDragEnd(DragObject dragObject, boolean dragStarted) { }
+ };
+ }
+
mActivity.hideKeyboard();
AbstractFloatingView.closeOpenViews(mActivity, false, TYPE_DISCOVERY_BOUNCE);
@@ -191,7 +221,7 @@
@Override
protected void exitDrag() {
- if (!mActivity.isInState(EDIT_MODE)) {
+ if (!mIsInPreDrag && !mActivity.isInState(EDIT_MODE)) {
mActivity.getStateManager().goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
}
}
@@ -218,4 +248,13 @@
dropCoordinates);
return mActivity.getWorkspace();
}
+
+ /**
+ * Intercepts touch events from a drag source view.
+ */
+ @Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ mIsInMouseRightClick = TouchUtil.isMouseRightClickDownOrMove(ev);
+ return super.onControllerInterceptTouchEvent(ev);
+ }
}