Loading libs/WindowManager/Shell/res/values/dimen.xml +2 −0 Original line number Diff line number Diff line Loading @@ -270,6 +270,8 @@ <dimen name="bubble_bar_expanded_view_switch_offset">48dp</dimen> <!-- Minimum width of the bubble bar manage menu. --> <dimen name="bubble_bar_manage_menu_min_width">200dp</dimen> <!-- The Bubble Bar drop zone square size. --> <dimen name="bubble_bar_drop_zone_side_size">200dp</dimen> <!-- Size of the dismiss icon in the bubble bar manage menu. --> <dimen name="bubble_bar_manage_menu_dismiss_icon_size">16dp</dimen> <!-- Padding of the bubble bar manage menu, provides space for menu shadows --> Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +44 −2 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ import com.android.launcher3.icons.BubbleIconFactory; import com.android.wm.shell.Flags; import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.bubbles.bar.BubbleBarDragListener; import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import com.android.wm.shell.bubbles.shortcut.BubbleShortcutHelper; import com.android.wm.shell.common.DisplayController; Loading Loading @@ -148,7 +149,8 @@ import java.util.function.IntConsumer; * The controller manages addition, removal, and visible state of bubbles on screen. */ public class BubbleController implements ConfigurationChangeListener, RemoteCallable<BubbleController>, Bubbles.SysuiProxy.Provider { RemoteCallable<BubbleController>, Bubbles.SysuiProxy.Provider, BubbleBarDragListener { private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES; Loading Loading @@ -416,7 +418,6 @@ public class BubbleController implements ConfigurationChangeListener, mBubbleData.setListener(mBubbleDataListener); mBubbleData.setSuppressionChangedListener(this::onBubbleMetadataFlagChanged); mDataRepository.setSuppressionChangedListener(this::onBubbleMetadataFlagChanged); mBubbleData.setPendingIntentCancelledListener(bubble -> { if (bubble.getBubbleIntent() == null) { return; Loading Loading @@ -844,6 +845,47 @@ public class BubbleController implements ConfigurationChangeListener, } } @Override public void onDragItemOverBubbleBarDragZone(@Nullable BubbleBarLocation bubbleBarLocation) { if (bubbleBarLocation == null) return; if (isShowingAsBubbleBar() && BubbleAnythingFlagHelper.enableCreateAnyBubble()) { //TODO(b/388894910) show expanded view drop mBubbleStateListener.onDragItemOverBubbleBarDragZone(bubbleBarLocation); } } @Override public void onItemDraggedOutsideBubbleBarDropZone() { if (isShowingAsBubbleBar() && BubbleAnythingFlagHelper.enableCreateAnyBubble()) { //TODO(b/388894910) hide expanded view drop mBubbleStateListener.onItemDraggedOutsideBubbleBarDropZone(); } } @Override public void onItemDroppedOverBubbleBarDragZone(@Nullable BubbleBarLocation bubbleBarLocation) { if (bubbleBarLocation == null) return; if (isShowingAsBubbleBar() && BubbleAnythingFlagHelper.enableCreateAnyBubble()) { //TODO(b/388894910) handle item drop with expandStackAndSelectBubble() } } @Override public Map<BubbleBarLocation, Rect> getBubbleBarDropZones(int l, int t, int r, int b) { Map<BubbleBarLocation, Rect> result = new HashMap<>(); if (isShowingAsBubbleBar() && BubbleAnythingFlagHelper.enableCreateAnyBubble()) { // TODO(b/393172431) : Utilise DragZoneFactory once it is ready final int bubbleBarDropZoneSideSize = getContext().getResources().getDimensionPixelSize( R.dimen.bubble_bar_drop_zone_side_size); int top = t - bubbleBarDropZoneSideSize; result.put(BubbleBarLocation.LEFT, new Rect(l, top, l + bubbleBarDropZoneSideSize, b)); result.put(BubbleBarLocation.RIGHT, new Rect(r - bubbleBarDropZoneSideSize, top, r, b)); } return result; } /** Whether this userId belongs to the current user. */ private boolean isCurrentProfile(int userId) { return userId == UserHandle.USER_ALL Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarDragListener.kt 0 → 100644 +39 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.bubbles.bar import android.graphics.Rect import com.android.wm.shell.shared.bubbles.BubbleBarLocation /** Controller that takes care of the bubble bar drag events. */ interface BubbleBarDragListener { /** Called when the drag event is over the bubble bar drop zone. */ fun onDragItemOverBubbleBarDragZone(location: BubbleBarLocation) /** Called when the drag event leaves the bubble bar drop zone. */ fun onItemDraggedOutsideBubbleBarDropZone() /** Called when the drop event happens over the bubble bar drop zone. */ fun onItemDroppedOverBubbleBarDragZone(location: BubbleBarLocation?) /** * Returns mapping of the bubble bar locations to the corresponding * [rect][android.graphics.Rect] zone. */ fun getBubbleBarDropZones(l: Int, t: Int, r: Int, b: Int): Map<BubbleBarLocation, Rect> } libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +12 −5 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser; import com.android.wm.shell.apptoweb.AssistContentRequester; import com.android.wm.shell.appzoomout.AppZoomOutController; import com.android.wm.shell.back.BackAnimationController; import com.android.wm.shell.bubbles.bar.BubbleBarDragListener; import com.android.wm.shell.bubbles.BubbleController; import com.android.wm.shell.bubbles.BubbleData; import com.android.wm.shell.bubbles.BubbleDataRepository; Loading Loading @@ -169,19 +170,18 @@ import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationPromo import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController; import com.android.wm.shell.windowdecor.tiling.DesktopTilingDecorViewModel; import java.util.ArrayList; import java.util.List; import java.util.Optional; import dagger.Binds; import dagger.Lazy; import dagger.Module; import dagger.Provides; import kotlinx.coroutines.CoroutineScope; import kotlinx.coroutines.ExperimentalCoroutinesApi; import kotlinx.coroutines.MainCoroutineDispatcher; import java.util.ArrayList; import java.util.List; import java.util.Optional; /** * Provides dependencies from {@link com.android.wm.shell}, these dependencies are only accessible * from components within the WM subcomponent (can be explicitly exposed to the SysUIComponent, see Loading Loading @@ -1412,6 +1412,7 @@ public abstract class WMShellModule { IconProvider iconProvider, GlobalDragListener globalDragListener, Transitions transitions, Lazy<BubbleController> bubbleControllerLazy, @ShellMainThread ShellExecutor mainExecutor) { return new DragAndDropController( context, Loading @@ -1424,6 +1425,12 @@ public abstract class WMShellModule { iconProvider, globalDragListener, transitions, new Lazy<>() { @Override public BubbleBarDragListener get() { return bubbleControllerLazy.get(); } }, mainExecutor); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +8 −1 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ import com.android.internal.protolog.ProtoLog; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.bubbles.bar.BubbleBarDragListener; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; Loading @@ -80,6 +81,8 @@ import java.util.ArrayList; import java.util.function.Consumer; import java.util.function.Function; import dagger.Lazy; /** * Handles the global drag and drop handling for the Shell. */ Loading @@ -101,6 +104,7 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll private final GlobalDragListener mGlobalDragListener; private final Transitions mTransitions; private SplitScreenController mSplitScreen; private Lazy<BubbleBarDragListener> mBubbleBarDragController; private ShellExecutor mMainExecutor; private ArrayList<DragAndDropListener> mListeners = new ArrayList<>(); Loading Loading @@ -143,6 +147,7 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll IconProvider iconProvider, GlobalDragListener globalDragListener, Transitions transitions, Lazy<BubbleBarDragListener> bubbleBarDragController, ShellExecutor mainExecutor) { mContext = context; mShellController = shellController; Loading @@ -153,6 +158,7 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll mIconProvider = iconProvider; mGlobalDragListener = globalDragListener; mTransitions = transitions; mBubbleBarDragController = bubbleBarDragController; mMainExecutor = mainExecutor; shellInit.addInitCallback(this::onInit, this); } Loading Loading @@ -246,7 +252,8 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll R.layout.global_drop_target, null); rootView.setOnDragListener(this); rootView.setVisibility(View.INVISIBLE); DragLayoutProvider dragLayout = new DragLayout(context, mSplitScreen, mIconProvider); DragLayoutProvider dragLayout = new DragLayout(context, mSplitScreen, mBubbleBarDragController.get(), mIconProvider); dragLayout.addDraggingView(rootView); try { wm.addView(rootView, layoutParams); Loading Loading
libs/WindowManager/Shell/res/values/dimen.xml +2 −0 Original line number Diff line number Diff line Loading @@ -270,6 +270,8 @@ <dimen name="bubble_bar_expanded_view_switch_offset">48dp</dimen> <!-- Minimum width of the bubble bar manage menu. --> <dimen name="bubble_bar_manage_menu_min_width">200dp</dimen> <!-- The Bubble Bar drop zone square size. --> <dimen name="bubble_bar_drop_zone_side_size">200dp</dimen> <!-- Size of the dismiss icon in the bubble bar manage menu. --> <dimen name="bubble_bar_manage_menu_dismiss_icon_size">16dp</dimen> <!-- Padding of the bubble bar manage menu, provides space for menu shadows --> Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +44 −2 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ import com.android.launcher3.icons.BubbleIconFactory; import com.android.wm.shell.Flags; import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.bubbles.bar.BubbleBarDragListener; import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import com.android.wm.shell.bubbles.shortcut.BubbleShortcutHelper; import com.android.wm.shell.common.DisplayController; Loading Loading @@ -148,7 +149,8 @@ import java.util.function.IntConsumer; * The controller manages addition, removal, and visible state of bubbles on screen. */ public class BubbleController implements ConfigurationChangeListener, RemoteCallable<BubbleController>, Bubbles.SysuiProxy.Provider { RemoteCallable<BubbleController>, Bubbles.SysuiProxy.Provider, BubbleBarDragListener { private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES; Loading Loading @@ -416,7 +418,6 @@ public class BubbleController implements ConfigurationChangeListener, mBubbleData.setListener(mBubbleDataListener); mBubbleData.setSuppressionChangedListener(this::onBubbleMetadataFlagChanged); mDataRepository.setSuppressionChangedListener(this::onBubbleMetadataFlagChanged); mBubbleData.setPendingIntentCancelledListener(bubble -> { if (bubble.getBubbleIntent() == null) { return; Loading Loading @@ -844,6 +845,47 @@ public class BubbleController implements ConfigurationChangeListener, } } @Override public void onDragItemOverBubbleBarDragZone(@Nullable BubbleBarLocation bubbleBarLocation) { if (bubbleBarLocation == null) return; if (isShowingAsBubbleBar() && BubbleAnythingFlagHelper.enableCreateAnyBubble()) { //TODO(b/388894910) show expanded view drop mBubbleStateListener.onDragItemOverBubbleBarDragZone(bubbleBarLocation); } } @Override public void onItemDraggedOutsideBubbleBarDropZone() { if (isShowingAsBubbleBar() && BubbleAnythingFlagHelper.enableCreateAnyBubble()) { //TODO(b/388894910) hide expanded view drop mBubbleStateListener.onItemDraggedOutsideBubbleBarDropZone(); } } @Override public void onItemDroppedOverBubbleBarDragZone(@Nullable BubbleBarLocation bubbleBarLocation) { if (bubbleBarLocation == null) return; if (isShowingAsBubbleBar() && BubbleAnythingFlagHelper.enableCreateAnyBubble()) { //TODO(b/388894910) handle item drop with expandStackAndSelectBubble() } } @Override public Map<BubbleBarLocation, Rect> getBubbleBarDropZones(int l, int t, int r, int b) { Map<BubbleBarLocation, Rect> result = new HashMap<>(); if (isShowingAsBubbleBar() && BubbleAnythingFlagHelper.enableCreateAnyBubble()) { // TODO(b/393172431) : Utilise DragZoneFactory once it is ready final int bubbleBarDropZoneSideSize = getContext().getResources().getDimensionPixelSize( R.dimen.bubble_bar_drop_zone_side_size); int top = t - bubbleBarDropZoneSideSize; result.put(BubbleBarLocation.LEFT, new Rect(l, top, l + bubbleBarDropZoneSideSize, b)); result.put(BubbleBarLocation.RIGHT, new Rect(r - bubbleBarDropZoneSideSize, top, r, b)); } return result; } /** Whether this userId belongs to the current user. */ private boolean isCurrentProfile(int userId) { return userId == UserHandle.USER_ALL Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarDragListener.kt 0 → 100644 +39 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.bubbles.bar import android.graphics.Rect import com.android.wm.shell.shared.bubbles.BubbleBarLocation /** Controller that takes care of the bubble bar drag events. */ interface BubbleBarDragListener { /** Called when the drag event is over the bubble bar drop zone. */ fun onDragItemOverBubbleBarDragZone(location: BubbleBarLocation) /** Called when the drag event leaves the bubble bar drop zone. */ fun onItemDraggedOutsideBubbleBarDropZone() /** Called when the drop event happens over the bubble bar drop zone. */ fun onItemDroppedOverBubbleBarDragZone(location: BubbleBarLocation?) /** * Returns mapping of the bubble bar locations to the corresponding * [rect][android.graphics.Rect] zone. */ fun getBubbleBarDropZones(l: Int, t: Int, r: Int, b: Int): Map<BubbleBarLocation, Rect> }
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +12 −5 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser; import com.android.wm.shell.apptoweb.AssistContentRequester; import com.android.wm.shell.appzoomout.AppZoomOutController; import com.android.wm.shell.back.BackAnimationController; import com.android.wm.shell.bubbles.bar.BubbleBarDragListener; import com.android.wm.shell.bubbles.BubbleController; import com.android.wm.shell.bubbles.BubbleData; import com.android.wm.shell.bubbles.BubbleDataRepository; Loading Loading @@ -169,19 +170,18 @@ import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationPromo import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController; import com.android.wm.shell.windowdecor.tiling.DesktopTilingDecorViewModel; import java.util.ArrayList; import java.util.List; import java.util.Optional; import dagger.Binds; import dagger.Lazy; import dagger.Module; import dagger.Provides; import kotlinx.coroutines.CoroutineScope; import kotlinx.coroutines.ExperimentalCoroutinesApi; import kotlinx.coroutines.MainCoroutineDispatcher; import java.util.ArrayList; import java.util.List; import java.util.Optional; /** * Provides dependencies from {@link com.android.wm.shell}, these dependencies are only accessible * from components within the WM subcomponent (can be explicitly exposed to the SysUIComponent, see Loading Loading @@ -1412,6 +1412,7 @@ public abstract class WMShellModule { IconProvider iconProvider, GlobalDragListener globalDragListener, Transitions transitions, Lazy<BubbleController> bubbleControllerLazy, @ShellMainThread ShellExecutor mainExecutor) { return new DragAndDropController( context, Loading @@ -1424,6 +1425,12 @@ public abstract class WMShellModule { iconProvider, globalDragListener, transitions, new Lazy<>() { @Override public BubbleBarDragListener get() { return bubbleControllerLazy.get(); } }, mainExecutor); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +8 −1 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ import com.android.internal.protolog.ProtoLog; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.bubbles.bar.BubbleBarDragListener; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; Loading @@ -80,6 +81,8 @@ import java.util.ArrayList; import java.util.function.Consumer; import java.util.function.Function; import dagger.Lazy; /** * Handles the global drag and drop handling for the Shell. */ Loading @@ -101,6 +104,7 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll private final GlobalDragListener mGlobalDragListener; private final Transitions mTransitions; private SplitScreenController mSplitScreen; private Lazy<BubbleBarDragListener> mBubbleBarDragController; private ShellExecutor mMainExecutor; private ArrayList<DragAndDropListener> mListeners = new ArrayList<>(); Loading Loading @@ -143,6 +147,7 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll IconProvider iconProvider, GlobalDragListener globalDragListener, Transitions transitions, Lazy<BubbleBarDragListener> bubbleBarDragController, ShellExecutor mainExecutor) { mContext = context; mShellController = shellController; Loading @@ -153,6 +158,7 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll mIconProvider = iconProvider; mGlobalDragListener = globalDragListener; mTransitions = transitions; mBubbleBarDragController = bubbleBarDragController; mMainExecutor = mainExecutor; shellInit.addInitCallback(this::onInit, this); } Loading Loading @@ -246,7 +252,8 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll R.layout.global_drop_target, null); rootView.setOnDragListener(this); rootView.setVisibility(View.INVISIBLE); DragLayoutProvider dragLayout = new DragLayout(context, mSplitScreen, mIconProvider); DragLayoutProvider dragLayout = new DragLayout(context, mSplitScreen, mBubbleBarDragController.get(), mIconProvider); dragLayout.addDraggingView(rootView); try { wm.addView(rootView, layoutParams); Loading