Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +9 −2 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.service.notification.NotificationListenerService.REASON_CA import static android.view.View.INVISIBLE; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; import static android.view.View.VISIBLE; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.TRANSIT_CHANGE; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME; Loading Loading @@ -1590,20 +1591,26 @@ public class BubbleController implements ConfigurationChangeListener, * Expands and selects a bubble created from a running task in a different mode. * Expands and selects a bubble created from a running task in a different mode. * * * @param taskInfo the task. * @param taskInfo the task. * @param dragData optional information about the task when it is being dragged into a bubble */ */ public void expandStackAndSelectBubble(ActivityManager.RunningTaskInfo taskInfo) { public void expandStackAndSelectBubble(ActivityManager.RunningTaskInfo taskInfo, @Nullable BubbleTransitions.DragData dragData) { if (!BubbleAnythingFlagHelper.enableBubbleToFullscreen()) return; if (!BubbleAnythingFlagHelper.enableBubbleToFullscreen()) return; Bubble b = mBubbleData.getOrCreateBubble(taskInfo); // Removes from overflow Bubble b = mBubbleData.getOrCreateBubble(taskInfo); // Removes from overflow ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - intent=%s", taskInfo.taskId); ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - intent=%s", taskInfo.taskId); if (b.isInflated()) { if (b.isInflated()) { mBubbleData.setSelectedBubbleAndExpandStack(b); mBubbleData.setSelectedBubbleAndExpandStack(b); if (dragData != null && dragData.getPendingWct() != null) { mTransitions.startTransition(TRANSIT_CHANGE, dragData.getPendingWct(), /* handler= */ null); } } else { } else { b.enable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE); b.enable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE); // Lazy init stack view when a bubble is created // Lazy init stack view when a bubble is created ensureBubbleViewsAndWindowCreated(); ensureBubbleViewsAndWindowCreated(); mBubbleTransitions.startConvertToBubble(b, taskInfo, mExpandedViewManager, mBubbleTransitions.startConvertToBubble(b, taskInfo, mExpandedViewManager, mBubbleTaskViewFactory, mBubblePositioner, mStackView, mLayerView, mBubbleTaskViewFactory, mBubblePositioner, mStackView, mLayerView, mBubbleIconFactory, mInflateSynchronously); mBubbleIconFactory, dragData, mInflateSynchronously); } } } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java +57 −4 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.View.INVISIBLE; import static android.view.View.INVISIBLE; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CHANGE; import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE; import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManager; Loading Loading @@ -92,10 +94,10 @@ public class BubbleTransitions { BubbleExpandedViewManager expandedViewManager, BubbleTaskViewFactory factory, BubbleExpandedViewManager expandedViewManager, BubbleTaskViewFactory factory, BubblePositioner positioner, BubbleStackView stackView, BubblePositioner positioner, BubbleStackView stackView, BubbleBarLayerView layerView, BubbleIconFactory iconFactory, BubbleBarLayerView layerView, BubbleIconFactory iconFactory, boolean inflateSync) { DragData dragData, boolean inflateSync) { return new ConvertToBubble(bubble, taskInfo, mContext, return new ConvertToBubble(bubble, taskInfo, mContext, expandedViewManager, factory, positioner, stackView, layerView, iconFactory, expandedViewManager, factory, positioner, stackView, layerView, iconFactory, inflateSync); dragData, inflateSync); } } /** /** Loading Loading @@ -148,6 +150,39 @@ public class BubbleTransitions { default void continueCollapse() {} default void continueCollapse() {} } } /** * Information about the task when it is being dragged to a bubble */ public static class DragData { private final Rect mBounds; private final WindowContainerTransaction mPendingWct; /** * @param bounds bounds of the dragged task when the drag was released * @param wct pending operations to be applied when finishing the drag */ public DragData(@Nullable Rect bounds, @Nullable WindowContainerTransaction wct) { mBounds = bounds; mPendingWct = wct; } /** * @return bounds of the dragged task when the drag was released */ @Nullable public Rect getBounds() { return mBounds; } /** * @return pending operations to be applied when finishing the drag */ @Nullable public WindowContainerTransaction getPendingWct() { return mPendingWct; } } /** /** * BubbleTransition that coordinates the process of a non-bubble task becoming a bubble. The * BubbleTransition that coordinates the process of a non-bubble task becoming a bubble. The * steps are as follows: * steps are as follows: Loading @@ -167,6 +202,7 @@ public class BubbleTransitions { class ConvertToBubble implements Transitions.TransitionHandler, BubbleTransition { class ConvertToBubble implements Transitions.TransitionHandler, BubbleTransition { final BubbleBarLayerView mLayerView; final BubbleBarLayerView mLayerView; Bubble mBubble; Bubble mBubble; @Nullable DragData mDragData; IBinder mTransition; IBinder mTransition; Transitions.TransitionFinishCallback mFinishCb; Transitions.TransitionFinishCallback mFinishCb; WindowContainerTransaction mFinishWct = null; WindowContainerTransaction mFinishWct = null; Loading @@ -182,10 +218,12 @@ public class BubbleTransitions { ConvertToBubble(Bubble bubble, TaskInfo taskInfo, Context context, ConvertToBubble(Bubble bubble, TaskInfo taskInfo, Context context, BubbleExpandedViewManager expandedViewManager, BubbleTaskViewFactory factory, BubbleExpandedViewManager expandedViewManager, BubbleTaskViewFactory factory, BubblePositioner positioner, BubbleStackView stackView, BubblePositioner positioner, BubbleStackView stackView, BubbleBarLayerView layerView, BubbleIconFactory iconFactory, boolean inflateSync) { BubbleBarLayerView layerView, BubbleIconFactory iconFactory, @Nullable DragData dragData, boolean inflateSync) { mBubble = bubble; mBubble = bubble; mTaskInfo = taskInfo; mTaskInfo = taskInfo; mLayerView = layerView; mLayerView = layerView; mDragData = dragData; mBubble.setInflateSynchronously(inflateSync); mBubble.setInflateSynchronously(inflateSync); mBubble.setPreparingTransition(this); mBubble.setPreparingTransition(this); mBubble.inflate( mBubble.inflate( Loading @@ -208,6 +246,9 @@ public class BubbleTransitions { final Rect launchBounds = new Rect(); final Rect launchBounds = new Rect(); mLayerView.getExpandedViewRestBounds(launchBounds); mLayerView.getExpandedViewRestBounds(launchBounds); WindowContainerTransaction wct = new WindowContainerTransaction(); WindowContainerTransaction wct = new WindowContainerTransaction(); if (mDragData != null && mDragData.getPendingWct() != null) { wct.merge(mDragData.getPendingWct(), true); } if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW) { if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW) { if (mTaskInfo.getParentTaskId() != INVALID_TASK_ID) { if (mTaskInfo.getParentTaskId() != INVALID_TASK_ID) { wct.reparent(mTaskInfo.token, null, true); wct.reparent(mTaskInfo.token, null, true); Loading @@ -226,7 +267,7 @@ public class BubbleTransitions { state.mVisible = true; state.mVisible = true; } } mTaskViewTransitions.enqueueExternal(tv.getController(), () -> { mTaskViewTransitions.enqueueExternal(tv.getController(), () -> { mTransition = mTransitions.startTransition(TRANSIT_CHANGE, wct, this); mTransition = mTransitions.startTransition(TRANSIT_CONVERT_TO_BUBBLE, wct, this); return mTransition; return mTransition; }); }); } } Loading Loading @@ -292,6 +333,11 @@ public class BubbleTransitions { } } mFinishCb = finishCallback; mFinishCb = finishCallback; if (mDragData != null && mDragData.getBounds() != null) { // Override start bounds with the dragged task bounds mStartBounds.set(mDragData.getBounds()); } // Now update state (and talk to launcher) in parallel with snapshot stuff // Now update state (and talk to launcher) in parallel with snapshot stuff mBubbleData.notificationEntryUpdated(mBubble, /* suppressFlyout= */ true, mBubbleData.notificationEntryUpdated(mBubble, /* suppressFlyout= */ true, /* showInShade= */ false); /* showInShade= */ false); Loading @@ -303,6 +349,13 @@ public class BubbleTransitions { mStartBounds.left - info.getRoot(0).getOffset().x, mStartBounds.left - info.getRoot(0).getOffset().x, mStartBounds.top - info.getRoot(0).getOffset().y); mStartBounds.top - info.getRoot(0).getOffset().y); startTransaction.setLayer(mSnapshot, Integer.MAX_VALUE); startTransaction.setLayer(mSnapshot, Integer.MAX_VALUE); BubbleBarExpandedView bbev = mBubble.getBubbleBarExpandedView(); if (bbev != null) { // Corners get reset during the animation. Add them back startTransaction.setCornerRadius(mSnapshot, bbev.getRestingCornerRadius()); } startTransaction.apply(); startTransaction.apply(); mTaskViewTransitions.onExternalDone(transition); mTaskViewTransitions.onExternalDone(transition); Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +4 −3 Original line number Original line Diff line number Diff line Loading @@ -915,14 +915,15 @@ public abstract class WMShellModule { Transitions transitions, Transitions transitions, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, @DynamicOverride DesktopUserRepositories desktopUserRepositories, @DynamicOverride DesktopUserRepositories desktopUserRepositories, InteractionJankMonitor interactionJankMonitor) { InteractionJankMonitor interactionJankMonitor, Optional<BubbleController> bubbleController) { return ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS_BUGFIX.isTrue() return ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS_BUGFIX.isTrue() ? new SpringDragToDesktopTransitionHandler( ? new SpringDragToDesktopTransitionHandler( context, transitions, rootTaskDisplayAreaOrganizer, desktopUserRepositories, context, transitions, rootTaskDisplayAreaOrganizer, desktopUserRepositories, interactionJankMonitor) interactionJankMonitor, bubbleController) : new DefaultDragToDesktopTransitionHandler( : new DefaultDragToDesktopTransitionHandler( context, transitions, rootTaskDisplayAreaOrganizer, desktopUserRepositories, context, transitions, rootTaskDisplayAreaOrganizer, desktopUserRepositories, interactionJankMonitor); interactionJankMonitor, bubbleController); } } @WMSingleton @WMSingleton Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +13 −5 Original line number Original line Diff line number Diff line Loading @@ -2689,15 +2689,22 @@ class DesktopTasksController( } } /** Requests a task be transitioned from whatever mode it's in to a bubble. */ /** Requests a task be transitioned from whatever mode it's in to a bubble. */ fun requestFloat(taskInfo: RunningTaskInfo) { @JvmOverloads fun requestFloat(taskInfo: RunningTaskInfo, left: Boolean? = null) { val isDragging = dragToDesktopTransitionHandler.inProgress val isDragging = dragToDesktopTransitionHandler.inProgress val shouldRequestFloat = val shouldRequestFloat = taskInfo.isFullscreen || taskInfo.isFreeform || isDragging || taskInfo.isMultiWindow taskInfo.isFullscreen || taskInfo.isFreeform || isDragging || taskInfo.isMultiWindow if (!shouldRequestFloat) return if (!shouldRequestFloat) return if (isDragging) { if (isDragging) { releaseVisualIndicator() releaseVisualIndicator() val cancelState = if (left == true) DragToDesktopTransitionHandler.CancelState.CANCEL_BUBBLE_LEFT else DragToDesktopTransitionHandler.CancelState.CANCEL_BUBBLE_RIGHT dragToDesktopTransitionHandler.cancelDragToDesktopTransition(cancelState) } else { } else { bubbleController.ifPresent { it.expandStackAndSelectBubble(taskInfo) } bubbleController.ifPresent { it.expandStackAndSelectBubble(taskInfo, /* dragData= */ null) } } } } } Loading Loading @@ -2975,10 +2982,11 @@ class DesktopTasksController( ) ) requestSplit(taskInfo, leftOrTop = false) requestSplit(taskInfo, leftOrTop = false) } } IndicatorType.TO_BUBBLE_LEFT_INDICATOR, IndicatorType.TO_BUBBLE_LEFT_INDICATOR -> { requestFloat(taskInfo, left = true) } IndicatorType.TO_BUBBLE_RIGHT_INDICATOR -> { IndicatorType.TO_BUBBLE_RIGHT_INDICATOR -> { // TODO(b/388851898): move to bubble requestFloat(taskInfo, left = false) cancelDragToDesktop(taskInfo) } } } } return indicatorType return indicatorType Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt +76 −8 Original line number Original line Diff line number Diff line Loading @@ -37,6 +37,8 @@ import com.android.internal.jank.InteractionJankMonitor import com.android.internal.protolog.ProtoLog import com.android.internal.protolog.ProtoLog import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.animation.FloatProperties import com.android.wm.shell.animation.FloatProperties import com.android.wm.shell.bubbles.BubbleController import com.android.wm.shell.bubbles.BubbleTransitions import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP Loading @@ -49,10 +51,12 @@ import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UND import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.transition.Transitions import com.android.wm.shell.transition.Transitions import com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE import com.android.wm.shell.transition.Transitions.TransitionHandler import com.android.wm.shell.transition.Transitions.TransitionHandler import com.android.wm.shell.windowdecor.MoveToDesktopAnimator import com.android.wm.shell.windowdecor.MoveToDesktopAnimator import com.android.wm.shell.windowdecor.MoveToDesktopAnimator.Companion.DRAG_FREEFORM_SCALE import com.android.wm.shell.windowdecor.MoveToDesktopAnimator.Companion.DRAG_FREEFORM_SCALE import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener import java.util.Optional import java.util.function.Supplier import java.util.function.Supplier import kotlin.math.max import kotlin.math.max Loading @@ -72,6 +76,7 @@ sealed class DragToDesktopTransitionHandler( private val taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, private val taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, private val desktopUserRepositories: DesktopUserRepositories, private val desktopUserRepositories: DesktopUserRepositories, protected val interactionJankMonitor: InteractionJankMonitor, protected val interactionJankMonitor: InteractionJankMonitor, private val bubbleController: Optional<BubbleController>, protected val transactionSupplier: Supplier<SurfaceControl.Transaction>, protected val transactionSupplier: Supplier<SurfaceControl.Transaction>, ) : TransitionHandler { ) : TransitionHandler { Loading Loading @@ -241,6 +246,20 @@ sealed class DragToDesktopTransitionHandler( state.startTransitionFinishCb?.onTransitionFinished(/* wct= */ null) state.startTransitionFinishCb?.onTransitionFinished(/* wct= */ null) requestSplitFromScaledTask(splitPosition, wct) requestSplitFromScaledTask(splitPosition, wct) clearState() clearState() } else if ( state.draggedTaskChange != null && (cancelState == CancelState.CANCEL_BUBBLE_LEFT || cancelState == CancelState.CANCEL_BUBBLE_RIGHT) ) { if (!bubbleController.isPresent) { startCancelAnimation() } else { // Animation is handled by BubbleController val wct = WindowContainerTransaction() restoreWindowOrder(wct, state) // TODO(b/388851898): pass along information about left or right side requestBubbleFromScaledTask(wct) } } else { } else { // There's no dragged task, this can happen when the "cancel" happened too quickly // There's no dragged task, this can happen when the "cancel" happened too quickly // before the "start" transition is even ready (like on a fling gesture). The // before the "start" transition is even ready (like on a fling gesture). The Loading @@ -256,6 +275,13 @@ sealed class DragToDesktopTransitionHandler( @SplitPosition splitPosition: Int, @SplitPosition splitPosition: Int, wct: WindowContainerTransaction, wct: WindowContainerTransaction, ) { ) { val state = requireTransitionState() val taskInfo = state.draggedTaskChange?.taskInfo ?: error("Expected non-null taskInfo") val animatedTaskBounds = getAnimatedTaskBounds() requestSplitSelect(wct, taskInfo, splitPosition, animatedTaskBounds) } private fun getAnimatedTaskBounds(): Rect { val state = requireTransitionState() val state = requireTransitionState() val taskInfo = state.draggedTaskChange?.taskInfo ?: error("Expected non-null taskInfo") val taskInfo = state.draggedTaskChange?.taskInfo ?: error("Expected non-null taskInfo") val taskBounds = Rect(taskInfo.configuration.windowConfiguration.bounds) val taskBounds = Rect(taskInfo.configuration.windowConfiguration.bounds) Loading @@ -264,14 +290,12 @@ sealed class DragToDesktopTransitionHandler( val scaledHeight = taskBounds.height() * taskScale val scaledHeight = taskBounds.height() * taskScale val dragPosition = PointF(state.dragAnimator.position) val dragPosition = PointF(state.dragAnimator.position) state.dragAnimator.cancelAnimator() state.dragAnimator.cancelAnimator() val animatedTaskBounds = return Rect( Rect( dragPosition.x.toInt(), dragPosition.x.toInt(), dragPosition.y.toInt(), dragPosition.y.toInt(), (dragPosition.x + scaledWidth).toInt(), (dragPosition.x + scaledWidth).toInt(), (dragPosition.y + scaledHeight).toInt(), (dragPosition.y + scaledHeight).toInt(), ) ) requestSplitSelect(wct, taskInfo, splitPosition, animatedTaskBounds) } } private fun requestSplitSelect( private fun requestSplitSelect( Loading @@ -294,6 +318,25 @@ sealed class DragToDesktopTransitionHandler( splitScreenController.requestEnterSplitSelect(taskInfo, wct, splitPosition, taskBounds) splitScreenController.requestEnterSplitSelect(taskInfo, wct, splitPosition, taskBounds) } } private fun requestBubbleFromScaledTask(wct: WindowContainerTransaction) { // TODO(b/391928049): update density once we can drag from desktop to bubble val state = requireTransitionState() val taskInfo = state.draggedTaskChange?.taskInfo ?: error("Expected non-null taskInfo") val taskBounds = getAnimatedTaskBounds() state.dragAnimator.cancelAnimator() requestBubble(wct, taskInfo, taskBounds) } private fun requestBubble( wct: WindowContainerTransaction, taskInfo: RunningTaskInfo, taskBounds: Rect = Rect(taskInfo.configuration.windowConfiguration.bounds), ) { val controller = bubbleController.orElseThrow { IllegalStateException("BubbleController not set") } controller.expandStackAndSelectBubble(taskInfo, BubbleTransitions.DragData(taskBounds, wct)) } override fun startAnimation( override fun startAnimation( transition: IBinder, transition: IBinder, info: TransitionInfo, info: TransitionInfo, Loading Loading @@ -446,6 +489,16 @@ sealed class DragToDesktopTransitionHandler( state.startTransitionFinishTransaction?.apply() state.startTransitionFinishTransaction?.apply() state.startTransitionFinishCb?.onTransitionFinished(/* wct= */ null) state.startTransitionFinishCb?.onTransitionFinished(/* wct= */ null) requestSplitSelect(wct, taskInfo, splitPosition) requestSplitSelect(wct, taskInfo, splitPosition) } else if ( state.cancelState == CancelState.CANCEL_BUBBLE_LEFT || state.cancelState == CancelState.CANCEL_BUBBLE_RIGHT ) { val taskInfo = state.draggedTaskChange?.taskInfo ?: error("Expected non-null task info.") val wct = WindowContainerTransaction() restoreWindowOrder(wct) // TODO(b/388851898): pass along information about left or right side requestBubble(wct, taskInfo) } } return true return true } } Loading Loading @@ -476,6 +529,13 @@ sealed class DragToDesktopTransitionHandler( clearState() clearState() return return } } // In case of bubble animation, finish the initial desktop drag animation, but keep the // current animation running and have bubbles take over if (info.type == TRANSIT_CONVERT_TO_BUBBLE) { state.startTransitionFinishCb?.onTransitionFinished(/* wct= */ null) clearState() return } val isCancelTransition = val isCancelTransition = info.type == TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP && info.type == TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP && transition == state.cancelTransitionToken && transition == state.cancelTransitionToken && Loading Loading @@ -869,6 +929,10 @@ sealed class DragToDesktopTransitionHandler( CANCEL_SPLIT_LEFT, CANCEL_SPLIT_LEFT, /** A cancel event where the task will request to enter split on the right side. */ /** A cancel event where the task will request to enter split on the right side. */ CANCEL_SPLIT_RIGHT, CANCEL_SPLIT_RIGHT, /** A cancel event where the task will request to bubble on the left side. */ CANCEL_BUBBLE_LEFT, /** A cancel event where the task will request to bubble on the right side. */ CANCEL_BUBBLE_RIGHT, } } companion object { companion object { Loading @@ -887,6 +951,7 @@ constructor( taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, desktopUserRepositories: DesktopUserRepositories, desktopUserRepositories: DesktopUserRepositories, interactionJankMonitor: InteractionJankMonitor, interactionJankMonitor: InteractionJankMonitor, bubbleController: Optional<BubbleController>, transactionSupplier: Supplier<SurfaceControl.Transaction> = Supplier { transactionSupplier: Supplier<SurfaceControl.Transaction> = Supplier { SurfaceControl.Transaction() SurfaceControl.Transaction() }, }, Loading @@ -897,6 +962,7 @@ constructor( taskDisplayAreaOrganizer, taskDisplayAreaOrganizer, desktopUserRepositories, desktopUserRepositories, interactionJankMonitor, interactionJankMonitor, bubbleController, transactionSupplier, transactionSupplier, ) { ) { Loading Loading @@ -925,6 +991,7 @@ constructor( taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, desktopUserRepositories: DesktopUserRepositories, desktopUserRepositories: DesktopUserRepositories, interactionJankMonitor: InteractionJankMonitor, interactionJankMonitor: InteractionJankMonitor, bubbleController: Optional<BubbleController>, transactionSupplier: Supplier<SurfaceControl.Transaction> = Supplier { transactionSupplier: Supplier<SurfaceControl.Transaction> = Supplier { SurfaceControl.Transaction() SurfaceControl.Transaction() }, }, Loading @@ -935,6 +1002,7 @@ constructor( taskDisplayAreaOrganizer, taskDisplayAreaOrganizer, desktopUserRepositories, desktopUserRepositories, interactionJankMonitor, interactionJankMonitor, bubbleController, transactionSupplier, transactionSupplier, ) { ) { Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +9 −2 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.service.notification.NotificationListenerService.REASON_CA import static android.view.View.INVISIBLE; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; import static android.view.View.VISIBLE; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.TRANSIT_CHANGE; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME; Loading Loading @@ -1590,20 +1591,26 @@ public class BubbleController implements ConfigurationChangeListener, * Expands and selects a bubble created from a running task in a different mode. * Expands and selects a bubble created from a running task in a different mode. * * * @param taskInfo the task. * @param taskInfo the task. * @param dragData optional information about the task when it is being dragged into a bubble */ */ public void expandStackAndSelectBubble(ActivityManager.RunningTaskInfo taskInfo) { public void expandStackAndSelectBubble(ActivityManager.RunningTaskInfo taskInfo, @Nullable BubbleTransitions.DragData dragData) { if (!BubbleAnythingFlagHelper.enableBubbleToFullscreen()) return; if (!BubbleAnythingFlagHelper.enableBubbleToFullscreen()) return; Bubble b = mBubbleData.getOrCreateBubble(taskInfo); // Removes from overflow Bubble b = mBubbleData.getOrCreateBubble(taskInfo); // Removes from overflow ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - intent=%s", taskInfo.taskId); ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - intent=%s", taskInfo.taskId); if (b.isInflated()) { if (b.isInflated()) { mBubbleData.setSelectedBubbleAndExpandStack(b); mBubbleData.setSelectedBubbleAndExpandStack(b); if (dragData != null && dragData.getPendingWct() != null) { mTransitions.startTransition(TRANSIT_CHANGE, dragData.getPendingWct(), /* handler= */ null); } } else { } else { b.enable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE); b.enable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE); // Lazy init stack view when a bubble is created // Lazy init stack view when a bubble is created ensureBubbleViewsAndWindowCreated(); ensureBubbleViewsAndWindowCreated(); mBubbleTransitions.startConvertToBubble(b, taskInfo, mExpandedViewManager, mBubbleTransitions.startConvertToBubble(b, taskInfo, mExpandedViewManager, mBubbleTaskViewFactory, mBubblePositioner, mStackView, mLayerView, mBubbleTaskViewFactory, mBubblePositioner, mStackView, mLayerView, mBubbleIconFactory, mInflateSynchronously); mBubbleIconFactory, dragData, mInflateSynchronously); } } } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java +57 −4 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.View.INVISIBLE; import static android.view.View.INVISIBLE; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CHANGE; import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE; import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManager; Loading Loading @@ -92,10 +94,10 @@ public class BubbleTransitions { BubbleExpandedViewManager expandedViewManager, BubbleTaskViewFactory factory, BubbleExpandedViewManager expandedViewManager, BubbleTaskViewFactory factory, BubblePositioner positioner, BubbleStackView stackView, BubblePositioner positioner, BubbleStackView stackView, BubbleBarLayerView layerView, BubbleIconFactory iconFactory, BubbleBarLayerView layerView, BubbleIconFactory iconFactory, boolean inflateSync) { DragData dragData, boolean inflateSync) { return new ConvertToBubble(bubble, taskInfo, mContext, return new ConvertToBubble(bubble, taskInfo, mContext, expandedViewManager, factory, positioner, stackView, layerView, iconFactory, expandedViewManager, factory, positioner, stackView, layerView, iconFactory, inflateSync); dragData, inflateSync); } } /** /** Loading Loading @@ -148,6 +150,39 @@ public class BubbleTransitions { default void continueCollapse() {} default void continueCollapse() {} } } /** * Information about the task when it is being dragged to a bubble */ public static class DragData { private final Rect mBounds; private final WindowContainerTransaction mPendingWct; /** * @param bounds bounds of the dragged task when the drag was released * @param wct pending operations to be applied when finishing the drag */ public DragData(@Nullable Rect bounds, @Nullable WindowContainerTransaction wct) { mBounds = bounds; mPendingWct = wct; } /** * @return bounds of the dragged task when the drag was released */ @Nullable public Rect getBounds() { return mBounds; } /** * @return pending operations to be applied when finishing the drag */ @Nullable public WindowContainerTransaction getPendingWct() { return mPendingWct; } } /** /** * BubbleTransition that coordinates the process of a non-bubble task becoming a bubble. The * BubbleTransition that coordinates the process of a non-bubble task becoming a bubble. The * steps are as follows: * steps are as follows: Loading @@ -167,6 +202,7 @@ public class BubbleTransitions { class ConvertToBubble implements Transitions.TransitionHandler, BubbleTransition { class ConvertToBubble implements Transitions.TransitionHandler, BubbleTransition { final BubbleBarLayerView mLayerView; final BubbleBarLayerView mLayerView; Bubble mBubble; Bubble mBubble; @Nullable DragData mDragData; IBinder mTransition; IBinder mTransition; Transitions.TransitionFinishCallback mFinishCb; Transitions.TransitionFinishCallback mFinishCb; WindowContainerTransaction mFinishWct = null; WindowContainerTransaction mFinishWct = null; Loading @@ -182,10 +218,12 @@ public class BubbleTransitions { ConvertToBubble(Bubble bubble, TaskInfo taskInfo, Context context, ConvertToBubble(Bubble bubble, TaskInfo taskInfo, Context context, BubbleExpandedViewManager expandedViewManager, BubbleTaskViewFactory factory, BubbleExpandedViewManager expandedViewManager, BubbleTaskViewFactory factory, BubblePositioner positioner, BubbleStackView stackView, BubblePositioner positioner, BubbleStackView stackView, BubbleBarLayerView layerView, BubbleIconFactory iconFactory, boolean inflateSync) { BubbleBarLayerView layerView, BubbleIconFactory iconFactory, @Nullable DragData dragData, boolean inflateSync) { mBubble = bubble; mBubble = bubble; mTaskInfo = taskInfo; mTaskInfo = taskInfo; mLayerView = layerView; mLayerView = layerView; mDragData = dragData; mBubble.setInflateSynchronously(inflateSync); mBubble.setInflateSynchronously(inflateSync); mBubble.setPreparingTransition(this); mBubble.setPreparingTransition(this); mBubble.inflate( mBubble.inflate( Loading @@ -208,6 +246,9 @@ public class BubbleTransitions { final Rect launchBounds = new Rect(); final Rect launchBounds = new Rect(); mLayerView.getExpandedViewRestBounds(launchBounds); mLayerView.getExpandedViewRestBounds(launchBounds); WindowContainerTransaction wct = new WindowContainerTransaction(); WindowContainerTransaction wct = new WindowContainerTransaction(); if (mDragData != null && mDragData.getPendingWct() != null) { wct.merge(mDragData.getPendingWct(), true); } if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW) { if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW) { if (mTaskInfo.getParentTaskId() != INVALID_TASK_ID) { if (mTaskInfo.getParentTaskId() != INVALID_TASK_ID) { wct.reparent(mTaskInfo.token, null, true); wct.reparent(mTaskInfo.token, null, true); Loading @@ -226,7 +267,7 @@ public class BubbleTransitions { state.mVisible = true; state.mVisible = true; } } mTaskViewTransitions.enqueueExternal(tv.getController(), () -> { mTaskViewTransitions.enqueueExternal(tv.getController(), () -> { mTransition = mTransitions.startTransition(TRANSIT_CHANGE, wct, this); mTransition = mTransitions.startTransition(TRANSIT_CONVERT_TO_BUBBLE, wct, this); return mTransition; return mTransition; }); }); } } Loading Loading @@ -292,6 +333,11 @@ public class BubbleTransitions { } } mFinishCb = finishCallback; mFinishCb = finishCallback; if (mDragData != null && mDragData.getBounds() != null) { // Override start bounds with the dragged task bounds mStartBounds.set(mDragData.getBounds()); } // Now update state (and talk to launcher) in parallel with snapshot stuff // Now update state (and talk to launcher) in parallel with snapshot stuff mBubbleData.notificationEntryUpdated(mBubble, /* suppressFlyout= */ true, mBubbleData.notificationEntryUpdated(mBubble, /* suppressFlyout= */ true, /* showInShade= */ false); /* showInShade= */ false); Loading @@ -303,6 +349,13 @@ public class BubbleTransitions { mStartBounds.left - info.getRoot(0).getOffset().x, mStartBounds.left - info.getRoot(0).getOffset().x, mStartBounds.top - info.getRoot(0).getOffset().y); mStartBounds.top - info.getRoot(0).getOffset().y); startTransaction.setLayer(mSnapshot, Integer.MAX_VALUE); startTransaction.setLayer(mSnapshot, Integer.MAX_VALUE); BubbleBarExpandedView bbev = mBubble.getBubbleBarExpandedView(); if (bbev != null) { // Corners get reset during the animation. Add them back startTransaction.setCornerRadius(mSnapshot, bbev.getRestingCornerRadius()); } startTransaction.apply(); startTransaction.apply(); mTaskViewTransitions.onExternalDone(transition); mTaskViewTransitions.onExternalDone(transition); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +4 −3 Original line number Original line Diff line number Diff line Loading @@ -915,14 +915,15 @@ public abstract class WMShellModule { Transitions transitions, Transitions transitions, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, @DynamicOverride DesktopUserRepositories desktopUserRepositories, @DynamicOverride DesktopUserRepositories desktopUserRepositories, InteractionJankMonitor interactionJankMonitor) { InteractionJankMonitor interactionJankMonitor, Optional<BubbleController> bubbleController) { return ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS_BUGFIX.isTrue() return ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS_BUGFIX.isTrue() ? new SpringDragToDesktopTransitionHandler( ? new SpringDragToDesktopTransitionHandler( context, transitions, rootTaskDisplayAreaOrganizer, desktopUserRepositories, context, transitions, rootTaskDisplayAreaOrganizer, desktopUserRepositories, interactionJankMonitor) interactionJankMonitor, bubbleController) : new DefaultDragToDesktopTransitionHandler( : new DefaultDragToDesktopTransitionHandler( context, transitions, rootTaskDisplayAreaOrganizer, desktopUserRepositories, context, transitions, rootTaskDisplayAreaOrganizer, desktopUserRepositories, interactionJankMonitor); interactionJankMonitor, bubbleController); } } @WMSingleton @WMSingleton Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +13 −5 Original line number Original line Diff line number Diff line Loading @@ -2689,15 +2689,22 @@ class DesktopTasksController( } } /** Requests a task be transitioned from whatever mode it's in to a bubble. */ /** Requests a task be transitioned from whatever mode it's in to a bubble. */ fun requestFloat(taskInfo: RunningTaskInfo) { @JvmOverloads fun requestFloat(taskInfo: RunningTaskInfo, left: Boolean? = null) { val isDragging = dragToDesktopTransitionHandler.inProgress val isDragging = dragToDesktopTransitionHandler.inProgress val shouldRequestFloat = val shouldRequestFloat = taskInfo.isFullscreen || taskInfo.isFreeform || isDragging || taskInfo.isMultiWindow taskInfo.isFullscreen || taskInfo.isFreeform || isDragging || taskInfo.isMultiWindow if (!shouldRequestFloat) return if (!shouldRequestFloat) return if (isDragging) { if (isDragging) { releaseVisualIndicator() releaseVisualIndicator() val cancelState = if (left == true) DragToDesktopTransitionHandler.CancelState.CANCEL_BUBBLE_LEFT else DragToDesktopTransitionHandler.CancelState.CANCEL_BUBBLE_RIGHT dragToDesktopTransitionHandler.cancelDragToDesktopTransition(cancelState) } else { } else { bubbleController.ifPresent { it.expandStackAndSelectBubble(taskInfo) } bubbleController.ifPresent { it.expandStackAndSelectBubble(taskInfo, /* dragData= */ null) } } } } } Loading Loading @@ -2975,10 +2982,11 @@ class DesktopTasksController( ) ) requestSplit(taskInfo, leftOrTop = false) requestSplit(taskInfo, leftOrTop = false) } } IndicatorType.TO_BUBBLE_LEFT_INDICATOR, IndicatorType.TO_BUBBLE_LEFT_INDICATOR -> { requestFloat(taskInfo, left = true) } IndicatorType.TO_BUBBLE_RIGHT_INDICATOR -> { IndicatorType.TO_BUBBLE_RIGHT_INDICATOR -> { // TODO(b/388851898): move to bubble requestFloat(taskInfo, left = false) cancelDragToDesktop(taskInfo) } } } } return indicatorType return indicatorType Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt +76 −8 Original line number Original line Diff line number Diff line Loading @@ -37,6 +37,8 @@ import com.android.internal.jank.InteractionJankMonitor import com.android.internal.protolog.ProtoLog import com.android.internal.protolog.ProtoLog import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.animation.FloatProperties import com.android.wm.shell.animation.FloatProperties import com.android.wm.shell.bubbles.BubbleController import com.android.wm.shell.bubbles.BubbleTransitions import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP Loading @@ -49,10 +51,12 @@ import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UND import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.transition.Transitions import com.android.wm.shell.transition.Transitions import com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE import com.android.wm.shell.transition.Transitions.TransitionHandler import com.android.wm.shell.transition.Transitions.TransitionHandler import com.android.wm.shell.windowdecor.MoveToDesktopAnimator import com.android.wm.shell.windowdecor.MoveToDesktopAnimator import com.android.wm.shell.windowdecor.MoveToDesktopAnimator.Companion.DRAG_FREEFORM_SCALE import com.android.wm.shell.windowdecor.MoveToDesktopAnimator.Companion.DRAG_FREEFORM_SCALE import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener import java.util.Optional import java.util.function.Supplier import java.util.function.Supplier import kotlin.math.max import kotlin.math.max Loading @@ -72,6 +76,7 @@ sealed class DragToDesktopTransitionHandler( private val taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, private val taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, private val desktopUserRepositories: DesktopUserRepositories, private val desktopUserRepositories: DesktopUserRepositories, protected val interactionJankMonitor: InteractionJankMonitor, protected val interactionJankMonitor: InteractionJankMonitor, private val bubbleController: Optional<BubbleController>, protected val transactionSupplier: Supplier<SurfaceControl.Transaction>, protected val transactionSupplier: Supplier<SurfaceControl.Transaction>, ) : TransitionHandler { ) : TransitionHandler { Loading Loading @@ -241,6 +246,20 @@ sealed class DragToDesktopTransitionHandler( state.startTransitionFinishCb?.onTransitionFinished(/* wct= */ null) state.startTransitionFinishCb?.onTransitionFinished(/* wct= */ null) requestSplitFromScaledTask(splitPosition, wct) requestSplitFromScaledTask(splitPosition, wct) clearState() clearState() } else if ( state.draggedTaskChange != null && (cancelState == CancelState.CANCEL_BUBBLE_LEFT || cancelState == CancelState.CANCEL_BUBBLE_RIGHT) ) { if (!bubbleController.isPresent) { startCancelAnimation() } else { // Animation is handled by BubbleController val wct = WindowContainerTransaction() restoreWindowOrder(wct, state) // TODO(b/388851898): pass along information about left or right side requestBubbleFromScaledTask(wct) } } else { } else { // There's no dragged task, this can happen when the "cancel" happened too quickly // There's no dragged task, this can happen when the "cancel" happened too quickly // before the "start" transition is even ready (like on a fling gesture). The // before the "start" transition is even ready (like on a fling gesture). The Loading @@ -256,6 +275,13 @@ sealed class DragToDesktopTransitionHandler( @SplitPosition splitPosition: Int, @SplitPosition splitPosition: Int, wct: WindowContainerTransaction, wct: WindowContainerTransaction, ) { ) { val state = requireTransitionState() val taskInfo = state.draggedTaskChange?.taskInfo ?: error("Expected non-null taskInfo") val animatedTaskBounds = getAnimatedTaskBounds() requestSplitSelect(wct, taskInfo, splitPosition, animatedTaskBounds) } private fun getAnimatedTaskBounds(): Rect { val state = requireTransitionState() val state = requireTransitionState() val taskInfo = state.draggedTaskChange?.taskInfo ?: error("Expected non-null taskInfo") val taskInfo = state.draggedTaskChange?.taskInfo ?: error("Expected non-null taskInfo") val taskBounds = Rect(taskInfo.configuration.windowConfiguration.bounds) val taskBounds = Rect(taskInfo.configuration.windowConfiguration.bounds) Loading @@ -264,14 +290,12 @@ sealed class DragToDesktopTransitionHandler( val scaledHeight = taskBounds.height() * taskScale val scaledHeight = taskBounds.height() * taskScale val dragPosition = PointF(state.dragAnimator.position) val dragPosition = PointF(state.dragAnimator.position) state.dragAnimator.cancelAnimator() state.dragAnimator.cancelAnimator() val animatedTaskBounds = return Rect( Rect( dragPosition.x.toInt(), dragPosition.x.toInt(), dragPosition.y.toInt(), dragPosition.y.toInt(), (dragPosition.x + scaledWidth).toInt(), (dragPosition.x + scaledWidth).toInt(), (dragPosition.y + scaledHeight).toInt(), (dragPosition.y + scaledHeight).toInt(), ) ) requestSplitSelect(wct, taskInfo, splitPosition, animatedTaskBounds) } } private fun requestSplitSelect( private fun requestSplitSelect( Loading @@ -294,6 +318,25 @@ sealed class DragToDesktopTransitionHandler( splitScreenController.requestEnterSplitSelect(taskInfo, wct, splitPosition, taskBounds) splitScreenController.requestEnterSplitSelect(taskInfo, wct, splitPosition, taskBounds) } } private fun requestBubbleFromScaledTask(wct: WindowContainerTransaction) { // TODO(b/391928049): update density once we can drag from desktop to bubble val state = requireTransitionState() val taskInfo = state.draggedTaskChange?.taskInfo ?: error("Expected non-null taskInfo") val taskBounds = getAnimatedTaskBounds() state.dragAnimator.cancelAnimator() requestBubble(wct, taskInfo, taskBounds) } private fun requestBubble( wct: WindowContainerTransaction, taskInfo: RunningTaskInfo, taskBounds: Rect = Rect(taskInfo.configuration.windowConfiguration.bounds), ) { val controller = bubbleController.orElseThrow { IllegalStateException("BubbleController not set") } controller.expandStackAndSelectBubble(taskInfo, BubbleTransitions.DragData(taskBounds, wct)) } override fun startAnimation( override fun startAnimation( transition: IBinder, transition: IBinder, info: TransitionInfo, info: TransitionInfo, Loading Loading @@ -446,6 +489,16 @@ sealed class DragToDesktopTransitionHandler( state.startTransitionFinishTransaction?.apply() state.startTransitionFinishTransaction?.apply() state.startTransitionFinishCb?.onTransitionFinished(/* wct= */ null) state.startTransitionFinishCb?.onTransitionFinished(/* wct= */ null) requestSplitSelect(wct, taskInfo, splitPosition) requestSplitSelect(wct, taskInfo, splitPosition) } else if ( state.cancelState == CancelState.CANCEL_BUBBLE_LEFT || state.cancelState == CancelState.CANCEL_BUBBLE_RIGHT ) { val taskInfo = state.draggedTaskChange?.taskInfo ?: error("Expected non-null task info.") val wct = WindowContainerTransaction() restoreWindowOrder(wct) // TODO(b/388851898): pass along information about left or right side requestBubble(wct, taskInfo) } } return true return true } } Loading Loading @@ -476,6 +529,13 @@ sealed class DragToDesktopTransitionHandler( clearState() clearState() return return } } // In case of bubble animation, finish the initial desktop drag animation, but keep the // current animation running and have bubbles take over if (info.type == TRANSIT_CONVERT_TO_BUBBLE) { state.startTransitionFinishCb?.onTransitionFinished(/* wct= */ null) clearState() return } val isCancelTransition = val isCancelTransition = info.type == TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP && info.type == TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP && transition == state.cancelTransitionToken && transition == state.cancelTransitionToken && Loading Loading @@ -869,6 +929,10 @@ sealed class DragToDesktopTransitionHandler( CANCEL_SPLIT_LEFT, CANCEL_SPLIT_LEFT, /** A cancel event where the task will request to enter split on the right side. */ /** A cancel event where the task will request to enter split on the right side. */ CANCEL_SPLIT_RIGHT, CANCEL_SPLIT_RIGHT, /** A cancel event where the task will request to bubble on the left side. */ CANCEL_BUBBLE_LEFT, /** A cancel event where the task will request to bubble on the right side. */ CANCEL_BUBBLE_RIGHT, } } companion object { companion object { Loading @@ -887,6 +951,7 @@ constructor( taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, desktopUserRepositories: DesktopUserRepositories, desktopUserRepositories: DesktopUserRepositories, interactionJankMonitor: InteractionJankMonitor, interactionJankMonitor: InteractionJankMonitor, bubbleController: Optional<BubbleController>, transactionSupplier: Supplier<SurfaceControl.Transaction> = Supplier { transactionSupplier: Supplier<SurfaceControl.Transaction> = Supplier { SurfaceControl.Transaction() SurfaceControl.Transaction() }, }, Loading @@ -897,6 +962,7 @@ constructor( taskDisplayAreaOrganizer, taskDisplayAreaOrganizer, desktopUserRepositories, desktopUserRepositories, interactionJankMonitor, interactionJankMonitor, bubbleController, transactionSupplier, transactionSupplier, ) { ) { Loading Loading @@ -925,6 +991,7 @@ constructor( taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, desktopUserRepositories: DesktopUserRepositories, desktopUserRepositories: DesktopUserRepositories, interactionJankMonitor: InteractionJankMonitor, interactionJankMonitor: InteractionJankMonitor, bubbleController: Optional<BubbleController>, transactionSupplier: Supplier<SurfaceControl.Transaction> = Supplier { transactionSupplier: Supplier<SurfaceControl.Transaction> = Supplier { SurfaceControl.Transaction() SurfaceControl.Transaction() }, }, Loading @@ -935,6 +1002,7 @@ constructor( taskDisplayAreaOrganizer, taskDisplayAreaOrganizer, desktopUserRepositories, desktopUserRepositories, interactionJankMonitor, interactionJankMonitor, bubbleController, transactionSupplier, transactionSupplier, ) { ) { Loading