From 8ac277ebd8bc9e10a8b5d09c2b974abb065c5ec9 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 24 May 2021 15:47:38 -0700 Subject: [PATCH] Taskbar drag starts internal pre-drag before system drag - TaskbarDragController now extends DragController. - Currently there is no pre-drag condition, so we immediately get onDragStart(), which starts the system global drag (which cancels the original internal drag). - Make the original view invisible during the drag and drop operation, across both internal and system drag events. - No longer handle onDragEvent() in TaskbarView, as TaskbarDragController handles all of it now. Test: Drag and drop from taskbar still works (bonus: starts from the correct registration point that you touched down on). Locally added a PreDragCondition and verified a seamless handoff to system drag and drop when the pre drag end condition was met. Bug: 182981908 Change-Id: I6bf48141a5eedfc6db6f461258e880ef8146e733 --- .../taskbar/LauncherTaskbarUIController.java | 2 +- .../taskbar/TaskbarActivityContext.java | 85 +++--- .../taskbar/TaskbarDragController.java | 261 ++++++++++++++++-- .../launcher3/taskbar/TaskbarDragLayer.java | 7 +- .../launcher3/taskbar/TaskbarDragView.java | 56 ++++ .../taskbar/TaskbarIconController.java | 19 +- .../launcher3/taskbar/TaskbarView.java | 33 +-- src/com/android/launcher3/BubbleTextView.java | 5 +- .../launcher3/dragndrop/DragController.java | 16 +- .../launcher3/dragndrop/DragDriver.java | 15 +- 10 files changed, 381 insertions(+), 118 deletions(-) create mode 100644 quickstep/src/com/android/launcher3/taskbar/TaskbarDragView.java diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index c2d107c22d..ee57dd9fe0 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -222,7 +222,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController { } public boolean isDraggingItem() { - return mTaskbarView.isDraggingItem(); + return mContext.getDragController().isDragging(); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 8c3d453b09..98b01b0a8c 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -28,9 +28,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.LauncherApps; import android.graphics.PixelFormat; -import android.graphics.Point; import android.graphics.Rect; -import android.graphics.drawable.Drawable; import android.os.Process; import android.os.SystemProperties; import android.util.Log; @@ -43,22 +41,14 @@ import android.view.WindowManager; import android.widget.Toast; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; -import com.android.launcher3.DragSource; -import com.android.launcher3.DropTarget; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.R; -import com.android.launcher3.dragndrop.DragController; -import com.android.launcher3.dragndrop.DragOptions; -import com.android.launcher3.dragndrop.DragView; -import com.android.launcher3.dragndrop.DraggableView; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.model.data.FolderInfo; -import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton; import com.android.launcher3.touch.ItemClickHandler; @@ -89,10 +79,13 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ private final LayoutInflater mLayoutInflater; private final TaskbarDragLayer mDragLayer; private final TaskbarIconController mIconController; - private final MyDragController mDragController; + private final TaskbarDragController mDragController; private final WindowManager mWindowManager; private WindowManager.LayoutParams mWindowLayoutParams; + private boolean mIsFullscreen; + // The size we should return to when we call setTaskbarWindowFullscreen(false) + private int mLastRequestedNonFullscreenHeight; private final SysUINavigationMode.Mode mNavMode; private final TaskbarNavButtonController mNavButtonController; @@ -114,8 +107,8 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode", () -> getPackageManager().isSafeMode()); - mOnTaskbarIconLongClickListener = - new TaskbarDragController(this)::startSystemDragOnLongClick; + mDragController = new TaskbarDragController(this); + mOnTaskbarIconLongClickListener = mDragController::startDragOnLongClick; mOnTaskbarIconClickListener = this::onTaskbarIconClicked; float taskbarIconSize = getResources().getDimension(R.dimen.taskbar_icon_size); @@ -126,7 +119,6 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ mDragLayer = (TaskbarDragLayer) mLayoutInflater .inflate(R.layout.taskbar, null, false); mIconController = new TaskbarIconController(this, mDragLayer); - mDragController = new MyDragController(this); Display display = windowContext.getDisplay(); Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY @@ -136,9 +128,10 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ } public void init() { + mLastRequestedNonFullscreenHeight = mDeviceProfile.taskbarSize; mWindowLayoutParams = new WindowManager.LayoutParams( MATCH_PARENT, - mDeviceProfile.taskbarSize, + mLastRequestedNonFullscreenHeight, TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); @@ -160,17 +153,6 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ mWindowManager.addView(mDragLayer, mWindowLayoutParams); } - /** - * Updates the TaskbarContainer height (pass deviceProfile.taskbarSize to reset). - */ - public void setTaskbarWindowHeight(int height) { - if (mWindowLayoutParams.height == height) { - return; - } - mWindowLayoutParams.height = height; - mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams); - } - public boolean canShowNavButtons() { return ENABLE_THREE_BUTTON_TASKBAR && mNavMode == Mode.THREE_BUTTONS; } @@ -196,7 +178,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ } @Override - public DragController getDragController() { + public TaskbarDragController getDragController() { return mDragController; } @@ -243,8 +225,30 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ /** * Updates the TaskbarContainer to MATCH_PARENT vs original Taskbar size. */ - protected void setTaskbarWindowFullscreen(boolean fullscreen) { - setTaskbarWindowHeight(fullscreen ? MATCH_PARENT : getDeviceProfile().taskbarSize); + public void setTaskbarWindowFullscreen(boolean fullscreen) { + mIsFullscreen = fullscreen; + setTaskbarWindowHeight(fullscreen ? MATCH_PARENT : mLastRequestedNonFullscreenHeight); + } + + /** + * Updates the TaskbarContainer height (pass deviceProfile.taskbarSize to reset). + */ + public void setTaskbarWindowHeight(int height) { + if (mWindowLayoutParams.height == height) { + return; + } + if (height != MATCH_PARENT) { + mLastRequestedNonFullscreenHeight = height; + if (mIsFullscreen) { + // We still need to be fullscreen, so defer any change to our height until we call + // setTaskbarWindowFullscreen(false). For example, this could happen when dragging + // from the gesture region, as the drag will cancel the gesture and reset launcher's + // state, which in turn normally would reset the taskbar window height as well. + return; + } + } + mWindowLayoutParams.height = height; + mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams); } protected void onTaskbarIconClicked(View view) { @@ -309,27 +313,4 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ AbstractFloatingView.closeAllOpenViews(this); } - - private static class MyDragController extends DragController { - MyDragController(TaskbarActivityContext activity) { - super(activity); - } - - @Override - protected DragView startDrag(@Nullable Drawable drawable, @Nullable View view, - DraggableView originalView, int dragLayerX, int dragLayerY, DragSource source, - ItemInfo dragInfo, Point dragOffset, Rect dragRegion, float initialDragViewScale, - float dragViewScaleOnDrop, DragOptions options) { - return null; - } - - @Override - protected void exitDrag() { - } - - @Override - protected DropTarget getDefaultDropTarget(int[] dropCoordinates) { - return null; - } - } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java index ee44927ce4..855c50728b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java @@ -20,19 +20,35 @@ import static android.view.View.VISIBLE; import android.content.ClipData; import android.content.ClipDescription; -import android.content.Context; import android.content.Intent; import android.content.pm.LauncherApps; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Point; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; import android.os.UserHandle; import android.view.DragEvent; +import android.view.MotionEvent; import android.view.View; +import androidx.annotation.Nullable; + +import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BubbleTextView; +import com.android.launcher3.DragSource; +import com.android.launcher3.DropTarget; import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; +import com.android.launcher3.accessibility.DragViewStateAnnouncer; +import com.android.launcher3.dragndrop.DragController; +import com.android.launcher3.dragndrop.DragDriver; +import com.android.launcher3.dragndrop.DragOptions; +import com.android.launcher3.dragndrop.DragView; +import com.android.launcher3.dragndrop.DraggableView; +import com.android.launcher3.graphics.DragPreviewProvider; +import com.android.launcher3.icons.FastBitmapDrawable; +import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.ClipDescriptionCompat; @@ -41,14 +57,20 @@ import com.android.systemui.shared.system.LauncherAppsCompat; /** * Handles long click on Taskbar items to start a system drag and drop operation. */ -public class TaskbarDragController { +public class TaskbarDragController extends DragController { - private final Context mContext; private final int mDragIconSize; + private final int[] mTempXY = new int[2]; - public TaskbarDragController(Context context) { - mContext = context; - Resources resources = mContext.getResources(); + // Where the initial touch was relative to the dragged icon. + private int mRegistrationX; + private int mRegistrationY; + + private boolean mIsSystemDragInProgress; + + public TaskbarDragController(TaskbarActivityContext activity) { + super(activity); + Resources resources = mActivity.getResources(); mDragIconSize = resources.getDimensionPixelSize(R.dimen.taskbar_icon_drag_icon_size); } @@ -57,18 +79,146 @@ public class TaskbarDragController { * generate the ClipDescription and Intent. * @return Whether {@link View#startDragAndDrop} started successfully. */ - protected boolean startSystemDragOnLongClick(View view) { + protected boolean startDragOnLongClick(View view) { if (!(view instanceof BubbleTextView)) { return false; } BubbleTextView btv = (BubbleTextView) view; - View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view) { + + mActivity.setTaskbarWindowFullscreen(true); + view.post(() -> { + startInternalDrag(btv); + btv.setVisibility(INVISIBLE); + }); + return true; + } + + private void startInternalDrag(BubbleTextView btv) { + float iconScale = 1f; + Drawable icon = btv.getIcon(); + if (icon instanceof FastBitmapDrawable) { + iconScale = ((FastBitmapDrawable) icon).getAnimatedScale(); + } + + // Clear the pressed state if necessary + btv.clearFocus(); + btv.setPressed(false); + btv.clearPressedBackground(); + + final DragPreviewProvider previewProvider = new DragPreviewProvider(btv); + final Drawable drawable = previewProvider.createDrawable(); + final float scale = previewProvider.getScaleAndPosition(drawable, mTempXY); + int dragLayerX = mTempXY[0]; + int dragLayerY = mTempXY[1]; + + Rect dragRect = new Rect(); + btv.getSourceVisualDragBounds(dragRect); + dragLayerY += dragRect.top; + + DragOptions dragOptions = new DragOptions(); + // TODO: open popup/pre-drag + // PopupContainerWithArrow popupContainer = PopupContainerWithArrow.showForIcon(view); + // if (popupContainer != null) { + // dragOptions.preDragCondition = popupContainer.createPreDragCondition(); + // } + + startDrag( + drawable, + /* view = */ null, + /* originalView = */ btv, + dragLayerX, + dragLayerY, + (View target, DropTarget.DragObject d, boolean success) -> {} /* DragSource */, + (WorkspaceItemInfo) btv.getTag(), + /* dragVisualizeOffset = */ null, + dragRect, + scale * iconScale, + scale, + dragOptions); + } + + @Override + protected DragView startDrag(@Nullable Drawable drawable, @Nullable View view, + DraggableView originalView, int dragLayerX, int dragLayerY, DragSource source, + ItemInfo dragInfo, Point dragOffset, Rect dragRegion, float initialDragViewScale, + float dragViewScaleOnDrop, DragOptions options) { + mOptions = options; + + mRegistrationX = mMotionDown.x - dragLayerX; + mRegistrationY = mMotionDown.y - dragLayerY; + + final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left; + final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top; + + mLastDropTarget = null; + + mDragObject = new DropTarget.DragObject(mActivity.getApplicationContext()); + mDragObject.originalView = originalView; + + mIsInPreDrag = mOptions.preDragCondition != null + && !mOptions.preDragCondition.shouldStartDrag(0); + + float scalePx = mDragIconSize - dragRegion.width(); + final DragView dragView = mDragObject.dragView = new TaskbarDragView( + mActivity, + drawable, + mRegistrationX, + mRegistrationY, + initialDragViewScale, + dragViewScaleOnDrop, + scalePx); + dragView.setItemInfo(dragInfo); + mDragObject.dragComplete = false; + + mDragObject.xOffset = mMotionDown.x - (dragLayerX + dragRegionLeft); + mDragObject.yOffset = mMotionDown.y - (dragLayerY + dragRegionTop); + + mDragDriver = DragDriver.create(this, mOptions, /* secondaryEventConsumer = */ ev -> {}); + if (!mOptions.isAccessibleDrag) { + mDragObject.stateAnnouncer = DragViewStateAnnouncer.createFor(dragView); + } + + mDragObject.dragSource = source; + mDragObject.dragInfo = dragInfo; + mDragObject.originalDragInfo = mDragObject.dragInfo.makeShallowCopy(); + + if (dragRegion != null) { + dragView.setDragRegion(new Rect(dragRegion)); + } + + dragView.show(mLastTouch.x, mLastTouch.y); + mDistanceSinceScroll = 0; + + if (!mIsInPreDrag) { + callOnDragStart(); + } else if (mOptions.preDragCondition != null) { + mOptions.preDragCondition.onPreDragStart(mDragObject); + } + + handleMoveEvent(mLastTouch.x, mLastTouch.y); + + return dragView; + } + + @Override + protected void callOnDragStart() { + super.callOnDragStart(); + // Pre-drag has ended, start the global system drag. + AbstractFloatingView.closeAllOpenViews(mActivity); + startSystemDrag((BubbleTextView) mDragObject.originalView); + } + + private void startSystemDrag(BubbleTextView btv) { + View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(btv) { + @Override public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) { shadowSize.set(mDragIconSize, mDragIconSize); - // TODO: should be based on last touch point on the icon. - shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2); + // The registration point was taken before the icon scaled to mDragIconSize, so + // offset the registration to where the touch is on the new size. + int offset = (mDragIconSize - btv.getIconSize()) / 2; + shadowTouchPoint.set(mRegistrationX + offset, mRegistrationY + offset); } @Override @@ -81,12 +231,12 @@ public class TaskbarDragController { } }; - Object tag = view.getTag(); + Object tag = btv.getTag(); ClipDescription clipDescription = null; Intent intent = null; if (tag instanceof WorkspaceItemInfo) { WorkspaceItemInfo item = (WorkspaceItemInfo) tag; - LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class); + LauncherApps launcherApps = mActivity.getSystemService(LauncherApps.class); clipDescription = new ClipDescription(item.title, new String[] { item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT @@ -116,28 +266,89 @@ public class TaskbarDragController { if (clipDescription != null && intent != null) { ClipData clipData = new ClipData(clipDescription, new ClipData.Item(intent)); - view.setOnDragListener(getDraggedViewDragListener()); - return view.startDragAndDrop(clipData, shadowBuilder, null /* localState */, - View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_OPAQUE); + if (btv.startDragAndDrop(clipData, shadowBuilder, null /* localState */, + View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_OPAQUE)) { + onSystemDragStarted(); + } } - return false; } - /** - * Hide the original Taskbar item while it is being dragged. - */ - private View.OnDragListener getDraggedViewDragListener() { - return (view, dragEvent) -> { + private void onSystemDragStarted() { + mIsSystemDragInProgress = true; + mActivity.getDragLayer().setOnDragListener((view, dragEvent) -> { switch (dragEvent.getAction()) { case DragEvent.ACTION_DRAG_STARTED: - view.setVisibility(INVISIBLE); + // Return true to tell system we are interested in events, so we get DRAG_ENDED. return true; case DragEvent.ACTION_DRAG_ENDED: - view.setVisibility(VISIBLE); - view.setOnDragListener(null); + mIsSystemDragInProgress = false; + maybeOnDragEnd(); return true; } return false; - }; + }); + } + + @Override + public boolean isDragging() { + return super.isDragging() || mIsSystemDragInProgress; + } + + /** + * Whether we started dragging the given view and the drag is still in progress. + */ + public boolean isDraggingView(View child) { + return isDragging() && mDragObject != null && mDragObject.originalView == child; + } + + private void maybeOnDragEnd() { + if (!isDragging()) { + ((View) mDragObject.originalView).setVisibility(VISIBLE); + } + } + + @Override + protected void callOnDragEnd() { + super.callOnDragEnd(); + maybeOnDragEnd(); + } + + @Override + protected float getX(MotionEvent ev) { + // We will resize to fill the screen while dragging, so use screen coordinates. This ensures + // we start at the correct position even though touch down is on the smaller DragLayer size. + return ev.getRawX(); + } + + @Override + protected float getY(MotionEvent ev) { + // We will resize to fill the screen while dragging, so use screen coordinates. This ensures + // we start at the correct position even though touch down is on the smaller DragLayer size. + return ev.getRawY(); + } + + @Override + protected Point getClampedDragLayerPos(float x, float y) { + // No need to clamp, as we will take up the entire screen. + mTmpPoint.set(Math.round(x), Math.round(y)); + return mTmpPoint; + } + + @Override + protected void exitDrag() { + if (mDragObject != null) { + mActivity.getDragLayer().removeView(mDragObject.dragView); + } + } + + @Override + public void addDropTarget(DropTarget target) { + // No-op as Taskbar currently doesn't support any drop targets internally. + // Note: if we do add internal DropTargets, we'll still need to ignore Folder. + } + + @Override + protected DropTarget getDefaultDropTarget(int[] dropCoordinates) { + return null; } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java index 45ec911527..2469f95bfb 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java @@ -40,7 +40,7 @@ public class TaskbarDragLayer extends BaseDragLayer { private final int mFolderMargin; private final Paint mTaskbarBackgroundPaint; - private TaskbarIconController.Callbacks mControllerCallbacks; + private TaskbarIconController.TaskbarDragLayerCallbacks mControllerCallbacks; private TaskbarView mTaskbarView; private final OnComputeInsetsListener mTaskbarInsetsComputer = this::onComputeTaskbarInsets; @@ -69,10 +69,11 @@ public class TaskbarDragLayer extends BaseDragLayer { @Override public void recreateControllers() { - mControllers = new TouchController[0]; + mControllers = new TouchController[] {mActivity.getDragController()}; } - public void init(TaskbarIconController.Callbacks callbacks, TaskbarView taskbarView) { + public void init(TaskbarIconController.TaskbarDragLayerCallbacks callbacks, + TaskbarView taskbarView) { mControllerCallbacks = callbacks; mTaskbarView = taskbarView; } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragView.java new file mode 100644 index 0000000000..cf28eff0c2 --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragView.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.taskbar; + +import android.graphics.drawable.Drawable; + +import com.android.launcher3.R; +import com.android.launcher3.dragndrop.DragView; + +/** + * A DragView drawn/used by the Taskbar. Note that this is only for the internal drag-and-drop, + * while the pre-drag is still in progress (i.e. when the long press popup is still open). After + * that ends, we switch to a system drag and drop view instead. + */ +public class TaskbarDragView extends DragView { + public TaskbarDragView(TaskbarActivityContext launcher, Drawable drawable, int registrationX, + int registrationY, float initialScale, float scaleOnDrop, float finalScaleDps) { + super(launcher, drawable, registrationX, registrationY, initialScale, scaleOnDrop, + finalScaleDps); + } + + @Override + public void animateTo(int toTouchX, int toTouchY, Runnable onCompleteRunnable, int duration) { + Runnable onAnimationEnd = () -> { + if (onCompleteRunnable != null) { + onCompleteRunnable.run(); + } + mActivity.getDragLayer().removeView(this); + }; + + duration = Math.max(duration, + getResources().getInteger(R.integer.config_dropAnimMinDuration)); + + animate() + .translationX(toTouchX - mRegistrationX) + .translationY(toTouchY - mRegistrationY) + .scaleX(mScaleOnDrop) + .scaleY(mScaleOnDrop) + .withEndAction(onAnimationEnd) + .setDuration(duration) + .start(); + } +} diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarIconController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarIconController.java index 683a5b9fc4..cf0694ba60 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarIconController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarIconController.java @@ -62,10 +62,11 @@ public class TaskbarIconController { ButtonProvider buttonProvider = new ButtonProvider(mActivity); mImeBarView.init(buttonProvider); - mTaskbarView.construct(clickListener, longClickListener, buttonProvider); + mTaskbarView.init(new TaskbarViewCallbacks(), clickListener, longClickListener, + buttonProvider); mTaskbarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize; - mDragLayer.init(new Callbacks(), mTaskbarView); + mDragLayer.init(new TaskbarDragLayerCallbacks(), mTaskbarView); } public void onDestroy() { @@ -102,7 +103,7 @@ public class TaskbarIconController { /** * Callbacks for {@link TaskbarDragLayer} to interact with the icon controller */ - public class Callbacks { + public class TaskbarDragLayerCallbacks { /** * Called to update the touchable insets @@ -160,4 +161,16 @@ public class TaskbarIconController { mImeBarView.setVisibility(alpha == 0 ? GONE : VISIBLE); } } + + /** + * Callbacks for {@link TaskbarView} to interact with the icon controller + */ + public class TaskbarViewCallbacks { + /** + * Returns whether no other controller is currently handling the given View's visibility. + */ + public boolean canUpdateViewVisibility(View child) { + return !mActivity.getDragController().isDraggingView(child); + } + } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index c6573a639c..ac7035876e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -24,7 +24,6 @@ import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.RectF; import android.util.AttributeSet; -import android.view.DragEvent; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -35,7 +34,6 @@ import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BubbleTextView; import com.android.launcher3.Insettable; import com.android.launcher3.R; @@ -62,7 +60,8 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa private final TaskbarActivityContext mActivityContext; - // Initialized in TaskbarController constructor. + // Initialized in init. + private TaskbarIconController.TaskbarViewCallbacks mControllerCallbacks; private View.OnClickListener mIconClickListener; private View.OnLongClickListener mIconLongClickListener; @@ -75,7 +74,6 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa // Prevents dispatching touches to children if true private boolean mTouchEnabled = true; - private boolean mIsDraggingItem; // Only non-null when the corresponding Folder is open. private @Nullable FolderIcon mLeaveBehindFolderIcon; @@ -118,8 +116,10 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa mHotseatIconsContainer = findViewById(R.id.hotseat_icons_layout); } - protected void construct(OnClickListener clickListener, OnLongClickListener longClickListener, - ButtonProvider buttonProvider) { + protected void init(TaskbarIconController.TaskbarViewCallbacks callbacks, + OnClickListener clickListener, OnLongClickListener longClickListener, + ButtonProvider buttonProvider) { + mControllerCallbacks = callbacks; mIconClickListener = clickListener; mIconLongClickListener = longClickListener; mButtonProvider = buttonProvider; @@ -225,6 +225,9 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa } private void updateHotseatItemVisibility(View hotseatView) { + if (!mControllerCallbacks.canUpdateViewVisibility(hotseatView)) { + return; + } hotseatView.setVisibility( hotseatView.getTag() != null ? VISIBLE : (mAreHolesAllowed ? INVISIBLE : GONE)); } @@ -349,24 +352,6 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa mSystemButtonContainer.addView(mButtonProvider.getRecents(), buttonParams); } - @Override - public boolean onDragEvent(DragEvent event) { - switch (event.getAction()) { - case DragEvent.ACTION_DRAG_STARTED: - mIsDraggingItem = true; - AbstractFloatingView.closeAllOpenViews(mActivityContext); - return true; - case DragEvent.ACTION_DRAG_ENDED: - mIsDraggingItem = false; - break; - } - return super.onDragEvent(event); - } - - public boolean isDraggingItem() { - return mIsDraggingItem; - } - /** * @return The bounding box of where the hotseat elements are relative to this TaskbarView. */ diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 786678631f..150db1e191 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -413,7 +413,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, } } - void clearPressedBackground() { + public void clearPressedBackground() { setPressed(false); setStayPressed(false); } @@ -859,8 +859,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, switch (display) { case DISPLAY_ALL_APPS: return grid.allAppsIconSizePx; - case DISPLAY_WORKSPACE: case DISPLAY_FOLDER: + return grid.folderChildIconSizePx; + case DISPLAY_WORKSPACE: default: return grid.iconSizePx; } diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java index 5731db4cbb..1e0edacfe8 100644 --- a/src/com/android/launcher3/dragndrop/DragController.java +++ b/src/com/android/launcher3/dragndrop/DragController.java @@ -74,7 +74,7 @@ public abstract class DragController /** Coordinate for last touch event **/ protected final Point mLastTouch = new Point(); - private final Point mTmpPoint = new Point(); + protected final Point mTmpPoint = new Point(); protected DropTarget.DragObject mDragObject; @@ -317,7 +317,7 @@ public abstract class DragController mDragObject.dragView.animateTo(mMotionDown.x, mMotionDown.y, onCompleteRunnable, duration); } - private void callOnDragEnd() { + protected void callOnDragEnd() { if (mIsInPreDrag && mOptions.preDragCondition != null) { mOptions.preDragCondition.onPreDragEnd(mDragObject, false /* dragStarted*/); } @@ -343,7 +343,7 @@ public abstract class DragController /** * Clamps the position to the drag layer bounds. */ - private Point getClampedDragLayerPos(float x, float y) { + protected Point getClampedDragLayerPos(float x, float y) { mActivity.getDragLayer().getLocalVisibleRect(mRectTemp); mTmpPoint.x = (int) Math.max(mRectTemp.left, Math.min(x, mRectTemp.right - 1)); mTmpPoint.y = (int) Math.max(mRectTemp.top, Math.min(y, mRectTemp.bottom - 1)); @@ -390,7 +390,7 @@ public abstract class DragController return false; } - Point dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY()); + Point dragLayerPos = getClampedDragLayerPos(getX(ev), getY(ev)); mLastTouch.set(dragLayerPos.x, dragLayerPos.y); if (ev.getAction() == MotionEvent.ACTION_DOWN) { // Remember location of down touch @@ -403,6 +403,14 @@ public abstract class DragController return mDragDriver != null && mDragDriver.onInterceptTouchEvent(ev); } + protected float getX(MotionEvent ev) { + return ev.getX(); + } + + protected float getY(MotionEvent ev) { + return ev.getY(); + } + /** * Call this from a drag source view. */ diff --git a/src/com/android/launcher3/dragndrop/DragDriver.java b/src/com/android/launcher3/dragndrop/DragDriver.java index d4ce3080c0..72e47e536c 100644 --- a/src/com/android/launcher3/dragndrop/DragDriver.java +++ b/src/com/android/launcher3/dragndrop/DragDriver.java @@ -165,8 +165,11 @@ public abstract class DragDriver { * Class for driving an internal (i.e. not using framework) drag/drop operation. */ static class InternalDragDriver extends DragDriver { + private final DragController mDragController; + InternalDragDriver(DragController dragController, Consumer sec) { super(dragController, sec); + mDragController = dragController; } @Override @@ -176,11 +179,14 @@ public abstract class DragDriver { switch (action) { case MotionEvent.ACTION_MOVE: - mEventListener.onDriverDragMove(ev.getX(), ev.getY()); + mEventListener.onDriverDragMove(mDragController.getX(ev), + mDragController.getY(ev)); break; case MotionEvent.ACTION_UP: - mEventListener.onDriverDragMove(ev.getX(), ev.getY()); - mEventListener.onDriverDragEnd(ev.getX(), ev.getY()); + mEventListener.onDriverDragMove(mDragController.getX(ev), + mDragController.getY(ev)); + mEventListener.onDriverDragEnd(mDragController.getX(ev), + mDragController.getY(ev)); break; case MotionEvent.ACTION_CANCEL: mEventListener.onDriverDragCancel(); @@ -197,7 +203,8 @@ public abstract class DragDriver { switch (action) { case MotionEvent.ACTION_UP: - mEventListener.onDriverDragEnd(ev.getX(), ev.getY()); + mEventListener.onDriverDragEnd(mDragController.getX(ev), + mDragController.getY(ev)); break; case MotionEvent.ACTION_CANCEL: mEventListener.onDriverDragCancel();