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
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index c2d107c..ee57dd9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -222,7 +222,7 @@
}
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 8c3d453..98b01b0 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.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.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 @@
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 @@
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 @@
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 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 @@
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 @@
}
@Override
- public DragController getDragController() {
+ public TaskbarDragController getDragController() {
return mDragController;
}
@@ -243,8 +225,30 @@
/**
* 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 @@
AbstractFloatingView.closeAllOpenViews(this);
}
-
- private static class MyDragController extends DragController<TaskbarActivityContext> {
- 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 ee44927..855c507 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -20,19 +20,35 @@
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 @@
/**
* Handles long click on Taskbar items to start a system drag and drop operation.
*/
-public class TaskbarDragController {
+public class TaskbarDragController extends DragController<TaskbarActivityContext> {
- 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 @@
* 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 @@
}
};
- 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 @@
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 45ec911..2469f95 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -40,7 +40,7 @@
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 @@
@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 0000000..cf28eff
--- /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<TaskbarActivityContext> {
+ 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 683a5b9..cf0694b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarIconController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarIconController.java
@@ -62,10 +62,11 @@
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 @@
/**
* 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 @@
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 c6573a6..ac70358 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.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.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 @@
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 @@
// 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 @@
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 @@
}
private void updateHotseatItemVisibility(View hotseatView) {
+ if (!mControllerCallbacks.canUpdateViewVisibility(hotseatView)) {
+ return;
+ }
hotseatView.setVisibility(
hotseatView.getTag() != null ? VISIBLE : (mAreHolesAllowed ? INVISIBLE : GONE));
}
@@ -349,24 +352,6 @@
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 7866786..150db1e 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -413,7 +413,7 @@
}
}
- void clearPressedBackground() {
+ public void clearPressedBackground() {
setPressed(false);
setStayPressed(false);
}
@@ -859,8 +859,9 @@
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 5731db4..1e0edac 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -74,7 +74,7 @@
/** 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 @@
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 @@
/**
* 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 @@
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 @@
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 d4ce308..72e47e5 100644
--- a/src/com/android/launcher3/dragndrop/DragDriver.java
+++ b/src/com/android/launcher3/dragndrop/DragDriver.java
@@ -165,8 +165,11 @@
* 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<MotionEvent> sec) {
super(dragController, sec);
+ mDragController = dragController;
}
@Override
@@ -176,11 +179,14 @@
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 @@
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();