Decoupling some drag and drop code handling
> Removing some special checks around accessibility drag
> Unifying folder alarm code path for accessible and normal DnD
> Maintaining mDragStartTime inside the dragDriver instead of the callers
> Simplifying some accessibility callbacks
Future cl will create a Accessibility DragDriver and unify it with
other DnD flow
Change-Id: I1919ef218de0174678110f271b450bcb9aaf4a5c
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 2b0da43..34d7067 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -155,7 +155,7 @@
@Override
public final void onDragEnter(DragObject d) {
- if (!d.accessibleDrag && !mTextVisible) {
+ if (!mAccessibleDrag && !mTextVisible) {
// Show tooltip
hideTooltip();
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index e3eb387..4742bbc 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -53,8 +53,6 @@
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.accessibility.DragAndDropAccessibilityDelegate;
-import com.android.launcher3.accessibility.FolderAccessibilityHelper;
-import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.config.FeatureFlags;
@@ -79,9 +77,6 @@
import java.util.Stack;
public class CellLayout extends ViewGroup implements Transposable {
- public static final int WORKSPACE_ACCESSIBILITY_DRAG = 2;
- public static final int FOLDER_ACCESSIBILITY_DRAG = 1;
-
private static final String TAG = "CellLayout";
private static final boolean LOGD = false;
@@ -182,7 +177,6 @@
private static final Paint sPaint = new Paint();
// Related to accessible drag and drop
- private DragAndDropAccessibilityDelegate mTouchHelper;
private boolean mUseTouchHelper = false;
private RotationMode mRotationMode = RotationMode.NORMAL;
@@ -292,26 +286,20 @@
addView(mShortcutsAndWidgets);
}
- public void enableAccessibleDrag(boolean enable, int dragType) {
- mUseTouchHelper = enable;
- if (!enable) {
- ViewCompat.setAccessibilityDelegate(this, null);
- setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
- getShortcutsAndWidgets().setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
- setOnClickListener(null);
- } else {
- if (dragType == WORKSPACE_ACCESSIBILITY_DRAG &&
- !(mTouchHelper instanceof WorkspaceAccessibilityHelper)) {
- mTouchHelper = new WorkspaceAccessibilityHelper(this);
- } else if (dragType == FOLDER_ACCESSIBILITY_DRAG &&
- !(mTouchHelper instanceof FolderAccessibilityHelper)) {
- mTouchHelper = new FolderAccessibilityHelper(this);
- }
- ViewCompat.setAccessibilityDelegate(this, mTouchHelper);
- setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
- getShortcutsAndWidgets().setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
- setOnClickListener(mTouchHelper);
- }
+
+ /**
+ * Sets or clears a delegate used for accessible drag and drop
+ */
+ public void setDragAndDropAccessibilityDelegate(DragAndDropAccessibilityDelegate delegate) {
+ setOnClickListener(delegate);
+ setOnHoverListener(delegate);
+ ViewCompat.setAccessibilityDelegate(this, delegate);
+
+ mUseTouchHelper = delegate != null;
+ int accessibilityFlag = mUseTouchHelper
+ ? IMPORTANT_FOR_ACCESSIBILITY_YES : IMPORTANT_FOR_ACCESSIBILITY_NO;
+ setImportantForAccessibility(accessibilityFlag);
+ getShortcutsAndWidgets().setImportantForAccessibility(accessibilityFlag);
// Invalidate the accessibility hierarchy
if (getParent() != null) {
@@ -339,15 +327,6 @@
}
@Override
- public boolean dispatchHoverEvent(MotionEvent event) {
- // Always attempt to dispatch hover events to accessibility first.
- if (mUseTouchHelper && mTouchHelper.dispatchHoverEvent(event)) {
- return true;
- }
- return super.dispatchHoverEvent(event);
- }
-
- @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mUseTouchHelper ||
(mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev))) {
diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java
index a32fd12..c03011b 100644
--- a/src/com/android/launcher3/DropTarget.java
+++ b/src/com/android/launcher3/DropTarget.java
@@ -59,9 +59,6 @@
/** Where the drag originated */
public DragSource dragSource = null;
- /** The object is part of an accessible drag operation */
- public boolean accessibleDrag;
-
/** Indicates that the drag operation was cancelled */
public boolean cancelled = false;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 1413a5c..1dd2e41 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -339,6 +339,8 @@
}
};
+ private long mLastTouchUpTime = -1;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
Object traceToken = TraceHelper.INSTANCE.beginSection(ON_CREATE_EVT,
@@ -1115,7 +1117,7 @@
super.onPause();
mDragController.cancelDrag();
- mDragController.resetLastGestureUpTime();
+ mLastTouchUpTime = -1;
mDropTargetBar.animateToVisibility(false);
if (!mDeferOverlayCallbacks) {
@@ -1838,6 +1840,9 @@
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_UP) {
+ mLastTouchUpTime = System.currentTimeMillis();
+ }
TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev);
return super.dispatchTouchEvent(ev);
}
@@ -2465,8 +2470,12 @@
}
private boolean canRunNewAppsAnimation() {
- long diff = System.currentTimeMillis() - mDragController.getLastGestureUpTime();
- return diff > (NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS * 1000);
+ if (mDragController.isDragging()) {
+ return false;
+ } else {
+ return (System.currentTimeMillis() - mLastTouchUpTime)
+ > (NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS * 1000);
+ }
}
private ValueAnimator createNewAppBounceAnimation(View v, int i) {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index ead6018..46493b7 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -192,10 +192,7 @@
final WallpaperOffsetInterpolator mWallpaperOffset;
private boolean mUnlockWallpaperFromDefaultPageOnLayout;
- // Variables relating to the creation of user folders by hovering shortcuts over shortcuts
- private static final int FOLDER_CREATION_TIMEOUT = 0;
public static final int REORDER_TIMEOUT = 650;
- private final Alarm mFolderCreationAlarm = new Alarm();
private final Alarm mReorderAlarm = new Alarm();
private PreviewBackground mFolderCreateBg;
private FolderIcon mDragOverFolderIcon = null;
@@ -567,11 +564,6 @@
addView(newScreen, insertIndex);
mStateTransitionAnimation.applyChildState(
mLauncher.getStateManager().getState(), newScreen, insertIndex);
-
- if (mLauncher.getAccessibilityDelegate().isInAccessibleDrag()) {
- newScreen.enableAccessibleDrag(true, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG);
- }
-
return newScreen;
}
@@ -818,11 +810,6 @@
if (indexOfChild(cl) < currentPage) {
pageShift++;
}
-
- if (isInAccessibleDrag) {
- cl.enableAccessibleDrag(false, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG);
- }
-
removeView(cl);
} else {
// if this is the last screen, convert it to the empty screen
@@ -1444,14 +1431,14 @@
child.setVisibility(INVISIBLE);
if (options.isAccessibleDrag) {
- mDragController.addDragListener(new AccessibleDragListenerAdapter(
- this, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG) {
- @Override
- protected void enableAccessibleDrag(boolean enable) {
- super.enableAccessibleDrag(enable);
- setEnableForLayout(mLauncher.getHotseat(),enable);
- }
- });
+ mDragController.addDragListener(
+ new AccessibleDragListenerAdapter(this, WorkspaceAccessibilityHelper::new) {
+ @Override
+ protected void enableAccessibleDrag(boolean enable) {
+ super.enableAccessibleDrag(enable);
+ setEnableForLayout(mLauncher.getHotseat(), enable);
+ }
+ });
}
beginDragShared(child, this, options);
@@ -1883,12 +1870,10 @@
final LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell;
AppWidgetProviderInfo pInfo = hostView.getAppWidgetInfo();
if (pInfo != null && pInfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE
- && !d.accessibleDrag) {
- onCompleteRunnable = new Runnable() {
- public void run() {
- if (!isPageInTransition()) {
- AppWidgetResizeFrame.showForWidget(hostView, cellLayout);
- }
+ && !options.isAccessibleDrag) {
+ onCompleteRunnable = () -> {
+ if (!isPageInTransition()) {
+ AppWidgetResizeFrame.showForWidget(hostView, cellLayout);
}
};
}
@@ -2088,8 +2073,6 @@
if (mFolderCreateBg != null) {
mFolderCreateBg.animateToRest();
}
- mFolderCreationAlarm.setOnAlarmListener(null);
- mFolderCreationAlarm.cancelAlarm();
}
private void cleanupAddToFolder() {
@@ -2196,7 +2179,7 @@
float targetCellDistance = mDragTargetLayout.getDistanceFromCell(
mDragViewVisualCenter[0], mDragViewVisualCenter[1], mTargetCell);
- manageFolderFeedback(mDragTargetLayout, mTargetCell, targetCellDistance, d);
+ manageFolderFeedback(targetCellDistance, d);
boolean nearestDropOccupied = mDragTargetLayout.isNearestDropLocationOccupied((int)
mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX,
@@ -2294,8 +2277,7 @@
return null;
}
- private void manageFolderFeedback(CellLayout targetLayout,
- int[] targetCell, float distance, DragObject dragObject) {
+ private void manageFolderFeedback(float distance, DragObject dragObject) {
if (distance > mMaxDistanceForFolderCreation) {
if (mDragMode != DRAG_MODE_NONE) {
setDragMode(DRAG_MODE_NONE);
@@ -2306,18 +2288,18 @@
final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]);
ItemInfo info = dragObject.dragInfo;
boolean userFolderPending = willCreateUserFolder(info, dragOverView, false);
- if (mDragMode == DRAG_MODE_NONE && userFolderPending &&
- !mFolderCreationAlarm.alarmPending()) {
+ if (mDragMode == DRAG_MODE_NONE && userFolderPending) {
- FolderCreationAlarmListener listener = new
- FolderCreationAlarmListener(targetLayout, targetCell[0], targetCell[1]);
+ mFolderCreateBg = new PreviewBackground();
+ mFolderCreateBg.setup(mLauncher, mLauncher, null,
+ dragOverView.getMeasuredWidth(), dragOverView.getPaddingTop());
- if (!dragObject.accessibleDrag) {
- mFolderCreationAlarm.setOnAlarmListener(listener);
- mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT);
- } else {
- listener.onAlarm(mFolderCreationAlarm);
- }
+ // The full preview background should appear behind the icon
+ mFolderCreateBg.isClipping = false;
+
+ mFolderCreateBg.animateToAccept(mDragTargetLayout, mTargetCell[0], mTargetCell[1]);
+ mDragTargetLayout.clearDragOutlines();
+ setDragMode(DRAG_MODE_CREATE_FOLDER);
if (dragObject.stateAnnouncer != null) {
dragObject.stateAnnouncer.announce(WorkspaceAccessibilityHelper
@@ -2330,8 +2312,8 @@
if (willAddToFolder && mDragMode == DRAG_MODE_NONE) {
mDragOverFolderIcon = ((FolderIcon) dragOverView);
mDragOverFolderIcon.onDragEnter(info);
- if (targetLayout != null) {
- targetLayout.clearDragOutlines();
+ if (mDragTargetLayout != null) {
+ mDragTargetLayout.clearDragOutlines();
}
setDragMode(DRAG_MODE_ADD_TO_FOLDER);
@@ -2350,33 +2332,6 @@
}
}
- class FolderCreationAlarmListener implements OnAlarmListener {
- final CellLayout layout;
- final int cellX;
- final int cellY;
-
- final PreviewBackground bg = new PreviewBackground();
-
- public FolderCreationAlarmListener(CellLayout layout, int cellX, int cellY) {
- this.layout = layout;
- this.cellX = cellX;
- this.cellY = cellY;
-
- BubbleTextView cell = (BubbleTextView) layout.getChildAt(cellX, cellY);
- bg.setup(mLauncher, mLauncher, null, cell.getMeasuredWidth(), cell.getPaddingTop());
-
- // The full preview background should appear behind the icon
- bg.isClipping = false;
- }
-
- public void onAlarm(Alarm alarm) {
- mFolderCreateBg = bg;
- mFolderCreateBg.animateToAccept(layout, cellX, cellY);
- layout.clearDragOutlines();
- setDragMode(DRAG_MODE_CREATE_FOLDER);
- }
- }
-
class ReorderAlarmListener implements OnAlarmListener {
final float[] dragViewCenter;
final int minSpanX, minSpanY, spanX, spanY;
diff --git a/src/com/android/launcher3/accessibility/AccessibleDragListenerAdapter.java b/src/com/android/launcher3/accessibility/AccessibleDragListenerAdapter.java
index f8df5d7..0d7df2b 100644
--- a/src/com/android/launcher3/accessibility/AccessibleDragListenerAdapter.java
+++ b/src/com/android/launcher3/accessibility/AccessibleDragListenerAdapter.java
@@ -16,7 +16,9 @@
package com.android.launcher3.accessibility;
+import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewGroup.OnHierarchyChangeListener;
import com.android.launcher3.CellLayout;
import com.android.launcher3.DropTarget.DragObject;
@@ -24,36 +26,55 @@
import com.android.launcher3.dragndrop.DragController.DragListener;
import com.android.launcher3.dragndrop.DragOptions;
+import java.util.function.Function;
+
/**
* Utility listener to enable/disable accessibility drag flags for a ViewGroup
* containing CellLayouts
*/
-public class AccessibleDragListenerAdapter implements DragListener {
+public class AccessibleDragListenerAdapter implements DragListener, OnHierarchyChangeListener {
private final ViewGroup mViewGroup;
- private final int mDragType;
+ private final Function<CellLayout, DragAndDropAccessibilityDelegate> mDelegateFactory;
/**
- * @param parent
- * @param dragType either {@link CellLayout#WORKSPACE_ACCESSIBILITY_DRAG} or
- * {@link CellLayout#FOLDER_ACCESSIBILITY_DRAG}
+ * @param parent the viewgroup containing all the children
+ * @param delegateFactory function to create no delegates
*/
- public AccessibleDragListenerAdapter(ViewGroup parent, int dragType) {
+ public AccessibleDragListenerAdapter(ViewGroup parent,
+ Function<CellLayout, DragAndDropAccessibilityDelegate> delegateFactory) {
mViewGroup = parent;
- mDragType = dragType;
+ mDelegateFactory = delegateFactory;
}
@Override
public void onDragStart(DragObject dragObject, DragOptions options) {
+ mViewGroup.setOnHierarchyChangeListener(this);
enableAccessibleDrag(true);
}
@Override
public void onDragEnd() {
+ mViewGroup.setOnHierarchyChangeListener(null);
enableAccessibleDrag(false);
Launcher.getLauncher(mViewGroup.getContext()).getDragController().removeDragListener(this);
}
+
+ @Override
+ public void onChildViewAdded(View parent, View child) {
+ if (parent == mViewGroup) {
+ setEnableForLayout((CellLayout) child, true);
+ }
+ }
+
+ @Override
+ public void onChildViewRemoved(View parent, View child) {
+ if (parent == mViewGroup) {
+ setEnableForLayout((CellLayout) child, false);
+ }
+ }
+
protected void enableAccessibleDrag(boolean enable) {
for (int i = 0; i < mViewGroup.getChildCount(); i++) {
setEnableForLayout((CellLayout) mViewGroup.getChildAt(i), enable);
@@ -61,6 +82,6 @@
}
protected final void setEnableForLayout(CellLayout layout, boolean enable) {
- layout.enableAccessibleDrag(enable, mDragType);
+ layout.setDragAndDropAccessibilityDelegate(enable ? mDelegateFactory.apply(layout) : null);
}
}
diff --git a/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java
index 117296d..ddb547f 100644
--- a/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java
@@ -19,24 +19,26 @@
import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
+import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
+import android.view.View.OnHoverListener;
import android.view.accessibility.AccessibilityEvent;
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
+import androidx.customview.widget.ExploreByTouchHelper;
+
import com.android.launcher3.CellLayout;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import java.util.List;
-import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
-import androidx.customview.widget.ExploreByTouchHelper;
-
/**
* Helper class to make drag-and-drop in a {@link CellLayout} accessible.
*/
public abstract class DragAndDropAccessibilityDelegate extends ExploreByTouchHelper
- implements OnClickListener {
+ implements OnClickListener, OnHoverListener {
protected static final int INVALID_POSITION = -1;
private static final int[] sTempArray = new int[2];
@@ -123,6 +125,11 @@
node.setFocusable(true);
}
+ @Override
+ public boolean onHover(View view, MotionEvent motionEvent) {
+ return dispatchHoverEvent(motionEvent);
+ }
+
protected abstract String getLocationDescriptionForIconDrop(int id);
protected abstract String getConfirmationForIconDrop(int id);
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index 0b439ec..6f7f8e6 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -7,6 +7,7 @@
import android.app.AlertDialog;
import android.appwidget.AppWidgetProviderInfo;
import android.content.DialogInterface;
+import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
@@ -400,11 +401,11 @@
Rect pos = new Rect();
mLauncher.getDragLayer().getDescendantRectRelativeToSelf(item, pos);
- mLauncher.getDragController().prepareAccessibleDrag(pos.centerX(), pos.centerY());
mLauncher.getDragController().addDragListener(this);
DragOptions options = new DragOptions();
options.isAccessibleDrag = true;
+ options.simulatedDndStartPoint = new Point(pos.centerX(), pos.centerY());
ItemLongClickListener.beginDrag(item, mLauncher, info, options);
}
diff --git a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
index 75693c6..9b91a1d 100644
--- a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
@@ -26,7 +26,6 @@
import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
-import android.os.SystemClock;
import android.util.Log;
import android.view.DragEvent;
import android.view.View;
@@ -63,7 +62,6 @@
protected Launcher mLauncher;
private DragController mDragController;
- private long mDragStartTime;
public BaseItemDragListener(Rect previewRect, int previewBitmapWidth, int previewViewWidth) {
mPreviewRect = previewRect;
@@ -102,7 +100,7 @@
return false;
}
}
- return mDragController.onDragEvent(mDragStartTime, event);
+ return mDragController.onDragEvent(event);
}
protected boolean onDragStart(DragEvent event) {
@@ -118,7 +116,7 @@
Point downPos = new Point((int) event.getX(), (int) event.getY());
DragOptions options = new DragOptions();
- options.systemDndStartPoint = downPos;
+ options.simulatedDndStartPoint = downPos;
options.preDragCondition = preDragCondition;
// We use drag event position as the screenPos for the preview image. Since mPreviewRect
@@ -128,7 +126,6 @@
// to source window.
createDragHelper().startDrag(new Rect(mPreviewRect),
mPreviewBitmapWidth, mPreviewViewWidth, downPos, this, options);
- mDragStartTime = SystemClock.uptimeMillis();
return true;
}
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index de7bc6d..1539747 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -43,7 +43,6 @@
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.util.UiThreadHelper;
@@ -61,8 +60,8 @@
*/
private static final int DEEP_PRESS_DISTANCE_FACTOR = 3;
- @Thunk Launcher mLauncher;
- private FlingToDeleteHelper mFlingToDeleteHelper;
+ private final Launcher mLauncher;
+ private final FlingToDeleteHelper mFlingToDeleteHelper;
// temporaries to avoid gc thrash
private Rect mRectTemp = new Rect();
@@ -77,11 +76,12 @@
/** Options controlling the drag behavior. */
private DragOptions mOptions;
- /** X coordinate of the down event. */
- private int mMotionDownX;
+ /** Coordinate for motion down event */
+ private final Point mMotionDown = new Point();
+ /** Coordinate for last touch event **/
+ private final Point mLastTouch = new Point();
- /** Y coordinate of the down event. */
- private int mMotionDownY;
+ private final Point mTmpPoint = new Point();
private DropTarget.DragObject mDragObject;
@@ -96,12 +96,9 @@
private DropTarget mLastDropTarget;
- private final int[] mLastTouch = new int[2];
- private long mLastTouchUpTime = -1;
private int mLastTouchClassification;
private int mDistanceSinceScroll = 0;
- private int mTmpPoint[] = new int[2];
private Rect mDragLayerRect = new Rect();
private boolean mIsInPreDrag;
@@ -159,13 +156,13 @@
AbstractFloatingView.closeOpenViews(mLauncher, false, TYPE_DISCOVERY_BOUNCE);
mOptions = options;
- if (mOptions.systemDndStartPoint != null) {
- mLastTouch[0] = mMotionDownX = mOptions.systemDndStartPoint.x;
- mLastTouch[1] = mMotionDownY = mOptions.systemDndStartPoint.y;
+ if (mOptions.simulatedDndStartPoint != null) {
+ mLastTouch.x = mMotionDown.x = mOptions.simulatedDndStartPoint.x;
+ mLastTouch.y = mMotionDown.y = mOptions.simulatedDndStartPoint.y;
}
- final int registrationX = mMotionDownX - dragLayerX;
- final int registrationY = mMotionDownY - dragLayerY;
+ final int registrationX = mMotionDown.x - dragLayerX;
+ final int registrationY = mMotionDown.y - dragLayerY;
final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
@@ -184,17 +181,13 @@
registrationY, initialDragViewScale, dragViewScaleOnDrop, scaleDps);
dragView.setItemInfo(dragInfo);
mDragObject.dragComplete = false;
- if (mOptions.isAccessibleDrag) {
- // For an accessible drag, we assume the view is being dragged from the center.
- mDragObject.xOffset = b.getWidth() / 2;
- mDragObject.yOffset = b.getHeight() / 2;
- mDragObject.accessibleDrag = true;
- } else {
- mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);
- mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);
- mDragObject.stateAnnouncer = DragViewStateAnnouncer.createFor(dragView);
- mDragDriver = DragDriver.create(mLauncher, this, mDragObject, mOptions);
+ mDragObject.xOffset = mMotionDown.x - (dragLayerX + dragRegionLeft);
+ mDragObject.yOffset = mMotionDown.y - (dragLayerY + dragRegionTop);
+
+ mDragDriver = DragDriver.create(this, mOptions, mFlingToDeleteHelper::recordMotionEvent);
+ if (!mOptions.isAccessibleDrag) {
+ mDragObject.stateAnnouncer = DragViewStateAnnouncer.createFor(dragView);
}
mDragObject.dragSource = source;
@@ -210,7 +203,7 @@
}
mLauncher.getDragLayer().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- dragView.show(mLastTouch[0], mLastTouch[1]);
+ dragView.show(mLastTouch.x, mLastTouch.y);
mDistanceSinceScroll = 0;
if (!mIsInPreDrag) {
@@ -219,7 +212,7 @@
mOptions.preDragCondition.onPreDragStart(mDragObject);
}
- handleMoveEvent(mLastTouch[0], mLastTouch[1]);
+ handleMoveEvent(mLastTouch.x, mLastTouch.y);
mLauncher.getUserEventDispatcher().resetActionDurationMillis();
return dragView;
}
@@ -336,7 +329,7 @@
}
}
};
- mDragObject.dragView.animateTo(mMotionDownX, mMotionDownY, onCompleteRunnable, duration);
+ mDragObject.dragView.animateTo(mMotionDown.x, mMotionDown.y, onCompleteRunnable, duration);
}
private void callOnDragEnd() {
@@ -365,30 +358,17 @@
/**
* Clamps the position to the drag layer bounds.
*/
- private int[] getClampedDragLayerPos(float x, float y) {
+ private Point getClampedDragLayerPos(float x, float y) {
mLauncher.getDragLayer().getLocalVisibleRect(mDragLayerRect);
- mTmpPoint[0] = (int) Math.max(mDragLayerRect.left, Math.min(x, mDragLayerRect.right - 1));
- mTmpPoint[1] = (int) Math.max(mDragLayerRect.top, Math.min(y, mDragLayerRect.bottom - 1));
+ mTmpPoint.x = (int) Math.max(mDragLayerRect.left, Math.min(x, mDragLayerRect.right - 1));
+ mTmpPoint.y = (int) Math.max(mDragLayerRect.top, Math.min(y, mDragLayerRect.bottom - 1));
return mTmpPoint;
}
- public long getLastGestureUpTime() {
- if (mDragDriver != null) {
- return System.currentTimeMillis();
- } else {
- return mLastTouchUpTime;
- }
- }
-
- public void resetLastGestureUpTime() {
- mLastTouchUpTime = -1;
- }
-
@Override
public void onDriverDragMove(float x, float y) {
- final int[] dragLayerPos = getClampedDragLayerPos(x, y);
-
- handleMoveEvent(dragLayerPos[0], dragLayerPos[1]);
+ Point dragLayerPos = getClampedDragLayerPos(x, y);
+ handleMoveEvent(dragLayerPos.x, dragLayerPos.y);
}
@Override
@@ -422,53 +402,38 @@
/**
* Call this from a drag source view.
*/
+ @Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
if (mOptions != null && mOptions.isAccessibleDrag) {
return false;
}
- // Update the velocity tracker
- mFlingToDeleteHelper.recordMotionEvent(ev);
+ Point dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
+ mLastTouch.set(dragLayerPos.x, dragLayerPos.y);
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ // Remember location of down touch
+ mMotionDown.set(dragLayerPos.x, dragLayerPos.y);
+ }
- final int action = ev.getAction();
- final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
- final int dragLayerX = dragLayerPos[0];
- final int dragLayerY = dragLayerPos[1];
- mLastTouch[0] = dragLayerX;
- mLastTouch[1] = dragLayerY;
if (ATLEAST_Q) {
mLastTouchClassification = ev.getClassification();
}
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- // Remember location of down touch
- mMotionDownX = dragLayerX;
- mMotionDownY = dragLayerY;
- break;
- case MotionEvent.ACTION_UP:
- mLastTouchUpTime = System.currentTimeMillis();
- break;
- }
-
return mDragDriver != null && mDragDriver.onInterceptTouchEvent(ev);
}
/**
* Call this from a drag source view.
*/
- public boolean onDragEvent(long dragStartTime, DragEvent event) {
- mFlingToDeleteHelper.recordDragEvent(dragStartTime, event);
- return mDragDriver != null && mDragDriver.onDragEvent(event);
+ @Override
+ public boolean onControllerTouchEvent(MotionEvent ev) {
+ return mDragDriver != null && mDragDriver.onTouchEvent(ev);
}
/**
- * Call this from a drag view.
+ * Call this from a drag source view.
*/
- public void onDragViewAnimationEnd() {
- if (mDragDriver != null) {
- mDragDriver.onDragViewAnimationEnd();
- }
+ public boolean onDragEvent(DragEvent event) {
+ return mDragDriver != null && mDragDriver.onDragEvent(event);
}
/**
@@ -493,9 +458,8 @@
checkTouchMove(dropTarget);
// Check if we are hovering over the scroll areas
- mDistanceSinceScroll += Math.hypot(mLastTouch[0] - x, mLastTouch[1] - y);
- mLastTouch[0] = x;
- mLastTouch[1] = y;
+ mDistanceSinceScroll += Math.hypot(mLastTouch.x - x, mLastTouch.y - y);
+ mLastTouch.set(x, y);
int distanceDragged = mDistanceSinceScroll;
if (ATLEAST_Q && mLastTouchClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS) {
@@ -513,7 +477,7 @@
public void forceTouchMove() {
int[] dummyCoordinates = mCoordinatesTemp;
- DropTarget dropTarget = findDropTarget(mLastTouch[0], mLastTouch[1], dummyCoordinates);
+ DropTarget dropTarget = findDropTarget(mLastTouch.x, mLastTouch.y, dummyCoordinates);
mDragObject.x = dummyCoordinates[0];
mDragObject.y = dummyCoordinates[1];
checkTouchMove(dropTarget);
@@ -537,44 +501,6 @@
}
/**
- * Call this from a drag source view.
- */
- public boolean onControllerTouchEvent(MotionEvent ev) {
- if (mDragDriver == null || mOptions == null || mOptions.isAccessibleDrag) {
- return false;
- }
-
- // Update the velocity tracker
- mFlingToDeleteHelper.recordMotionEvent(ev);
-
- final int action = ev.getAction();
- final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
- final int dragLayerX = dragLayerPos[0];
- final int dragLayerY = dragLayerPos[1];
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- // Remember where the motion event started
- mMotionDownX = dragLayerX;
- mMotionDownY = dragLayerY;
- break;
- }
-
- return mDragDriver.onTouchEvent(ev);
- }
-
- /**
- * Since accessible drag and drop won't cause the same sequence of touch events, we manually
- * inject the appropriate state which would have been otherwise initiated via touch events.
- */
- public void prepareAccessibleDrag(int x, int y) {
- mMotionDownX = x;
- mMotionDownY = y;
- mLastTouch[0] = x;
- mLastTouch[1] = y;
- }
-
- /**
* As above, since accessible drag and drop won't cause the same sequence of touch events,
* we manually ensure appropriate drag and drop events get emulated for accessible drag.
*/
diff --git a/src/com/android/launcher3/dragndrop/DragDriver.java b/src/com/android/launcher3/dragndrop/DragDriver.java
index 87461d5..d4ce308 100644
--- a/src/com/android/launcher3/dragndrop/DragDriver.java
+++ b/src/com/android/launcher3/dragndrop/DragDriver.java
@@ -16,19 +16,19 @@
package com.android.launcher3.dragndrop;
-import android.content.Context;
-import android.util.Log;
+import android.os.SystemClock;
import android.view.DragEvent;
import android.view.MotionEvent;
-import com.android.launcher3.DropTarget.DragObject;
-import com.android.launcher3.testing.TestProtocol;
+import java.util.function.Consumer;
/**
* Base class for driving a drag/drop operation.
*/
public abstract class DragDriver {
+
protected final EventListener mEventListener;
+ protected final Consumer<MotionEvent> mSecondaryEventConsumer;
public interface EventListener {
void onDriverDragMove(float x, float y);
@@ -37,131 +37,175 @@
void onDriverDragCancel();
}
- public DragDriver(EventListener eventListener) {
+ public DragDriver(EventListener eventListener, Consumer<MotionEvent> sec) {
mEventListener = eventListener;
+ mSecondaryEventConsumer = sec;
}
/**
- * Handles ending of the DragView animation.
+ * Called to handle system touch event
*/
- public void onDragViewAnimationEnd() { }
-
public boolean onTouchEvent(MotionEvent ev) {
- final int action = ev.getAction();
-
- switch (action) {
- case MotionEvent.ACTION_MOVE:
- mEventListener.onDriverDragMove(ev.getX(), ev.getY());
- break;
- case MotionEvent.ACTION_UP:
- mEventListener.onDriverDragMove(ev.getX(), ev.getY());
- mEventListener.onDriverDragEnd(ev.getX(), ev.getY());
- break;
- case MotionEvent.ACTION_CANCEL:
- mEventListener.onDriverDragCancel();
- break;
- }
-
- return true;
+ return false;
}
- public abstract boolean onDragEvent (DragEvent event);
-
-
+ /**
+ * Called to handle system touch intercept event
+ */
public boolean onInterceptTouchEvent(MotionEvent ev) {
- final int action = ev.getAction();
-
- switch (action) {
- case MotionEvent.ACTION_UP:
- mEventListener.onDriverDragEnd(ev.getX(), ev.getY());
- break;
- case MotionEvent.ACTION_CANCEL:
- mEventListener.onDriverDragCancel();
- break;
- }
-
- return true;
+ return false;
}
- public static DragDriver create(Context context, DragController dragController,
- DragObject dragObject, DragOptions options) {
- if (options.systemDndStartPoint != null) {
- return new SystemDragDriver(dragController, context, dragObject);
+ /**
+ * Called to handle system drag event
+ */
+ public boolean onDragEvent(DragEvent event) {
+ return false;
+ }
+
+ /**
+ * Created a driver for handing the actual events
+ */
+ public static DragDriver create(DragController dragController, DragOptions options,
+ Consumer<MotionEvent> sec) {
+ if (options.simulatedDndStartPoint != null) {
+ if (options.isAccessibleDrag) {
+ return null;
+ }
+ return new SystemDragDriver(dragController, sec);
} else {
- return new InternalDragDriver(dragController);
+ return new InternalDragDriver(dragController, sec);
+ }
+ }
+
+ /**
+ * Class for driving a system (i.e. framework) drag/drop operation.
+ */
+ static class SystemDragDriver extends DragDriver {
+
+ private final long mDragStartTime;
+ float mLastX = 0;
+ float mLastY = 0;
+
+ SystemDragDriver(DragController dragController, Consumer<MotionEvent> sec) {
+ super(dragController, sec);
+ mDragStartTime = SystemClock.uptimeMillis();
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ return false;
+ }
+
+ /**
+ * It creates a temporary {@link MotionEvent} object for secondary consumer
+ */
+ private void simulateSecondaryMotionEvent(DragEvent event) {
+ final int motionAction;
+ switch (event.getAction()) {
+ case DragEvent.ACTION_DRAG_STARTED:
+ motionAction = MotionEvent.ACTION_DOWN;
+ break;
+ case DragEvent.ACTION_DRAG_LOCATION:
+ motionAction = MotionEvent.ACTION_MOVE;
+ break;
+ case DragEvent.ACTION_DRAG_ENDED:
+ motionAction = MotionEvent.ACTION_UP;
+ break;
+ default:
+ return;
+ }
+ MotionEvent emulatedEvent = MotionEvent.obtain(mDragStartTime,
+ SystemClock.uptimeMillis(), motionAction, event.getX(), event.getY(), 0);
+ mSecondaryEventConsumer.accept(emulatedEvent);
+ emulatedEvent.recycle();
+ }
+
+ @Override
+ public boolean onDragEvent(DragEvent event) {
+ simulateSecondaryMotionEvent(event);
+ final int action = event.getAction();
+
+ switch (action) {
+ case DragEvent.ACTION_DRAG_STARTED:
+ mLastX = event.getX();
+ mLastY = event.getY();
+ return true;
+
+ case DragEvent.ACTION_DRAG_ENTERED:
+ return true;
+
+ case DragEvent.ACTION_DRAG_LOCATION:
+ mLastX = event.getX();
+ mLastY = event.getY();
+ mEventListener.onDriverDragMove(event.getX(), event.getY());
+ return true;
+
+ case DragEvent.ACTION_DROP:
+ mLastX = event.getX();
+ mLastY = event.getY();
+ mEventListener.onDriverDragMove(event.getX(), event.getY());
+ mEventListener.onDriverDragEnd(mLastX, mLastY);
+ return true;
+ case DragEvent.ACTION_DRAG_EXITED:
+ mEventListener.onDriverDragExitWindow();
+ return true;
+
+ case DragEvent.ACTION_DRAG_ENDED:
+ mEventListener.onDriverDragCancel();
+ return true;
+
+ default:
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Class for driving an internal (i.e. not using framework) drag/drop operation.
+ */
+ static class InternalDragDriver extends DragDriver {
+ InternalDragDriver(DragController dragController, Consumer<MotionEvent> sec) {
+ super(dragController, sec);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ mSecondaryEventConsumer.accept(ev);
+ final int action = ev.getAction();
+
+ switch (action) {
+ case MotionEvent.ACTION_MOVE:
+ mEventListener.onDriverDragMove(ev.getX(), ev.getY());
+ break;
+ case MotionEvent.ACTION_UP:
+ mEventListener.onDriverDragMove(ev.getX(), ev.getY());
+ mEventListener.onDriverDragEnd(ev.getX(), ev.getY());
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ mEventListener.onDriverDragCancel();
+ break;
+ }
+
+ return true;
+ }
+
+
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ mSecondaryEventConsumer.accept(ev);
+ final int action = ev.getAction();
+
+ switch (action) {
+ case MotionEvent.ACTION_UP:
+ mEventListener.onDriverDragEnd(ev.getX(), ev.getY());
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ mEventListener.onDriverDragCancel();
+ break;
+ }
+ return true;
}
}
}
-/**
- * Class for driving a system (i.e. framework) drag/drop operation.
- */
-class SystemDragDriver extends DragDriver {
- float mLastX = 0;
- float mLastY = 0;
-
- SystemDragDriver(DragController dragController, Context context, DragObject dragObject) {
- super(dragController);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- return false;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- return false;
- }
-
- @Override
- public boolean onDragEvent (DragEvent event) {
- final int action = event.getAction();
-
- switch (action) {
- case DragEvent.ACTION_DRAG_STARTED:
- mLastX = event.getX();
- mLastY = event.getY();
- return true;
-
- case DragEvent.ACTION_DRAG_ENTERED:
- return true;
-
- case DragEvent.ACTION_DRAG_LOCATION:
- mLastX = event.getX();
- mLastY = event.getY();
- mEventListener.onDriverDragMove(event.getX(), event.getY());
- return true;
-
- case DragEvent.ACTION_DROP:
- mLastX = event.getX();
- mLastY = event.getY();
- mEventListener.onDriverDragMove(event.getX(), event.getY());
- mEventListener.onDriverDragEnd(mLastX, mLastY);
- return true;
- case DragEvent.ACTION_DRAG_EXITED:
- mEventListener.onDriverDragExitWindow();
- return true;
-
- case DragEvent.ACTION_DRAG_ENDED:
- mEventListener.onDriverDragCancel();
- return true;
-
- default:
- return false;
- }
- }
-}
-
-/**
- * Class for driving an internal (i.e. not using framework) drag/drop operation.
- */
-class InternalDragDriver extends DragDriver {
- InternalDragDriver(DragController dragController) {
- super(dragController);
- }
-
- @Override
- public boolean onDragEvent (DragEvent event) { return false; }
-}
diff --git a/src/com/android/launcher3/dragndrop/DragOptions.java b/src/com/android/launcher3/dragndrop/DragOptions.java
index 2d19f36..959602b 100644
--- a/src/com/android/launcher3/dragndrop/DragOptions.java
+++ b/src/com/android/launcher3/dragndrop/DragOptions.java
@@ -28,8 +28,11 @@
/** Whether or not an accessible drag operation is in progress. */
public boolean isAccessibleDrag = false;
- /** Specifies the start location for the system DnD, null when using internal DnD */
- public Point systemDndStartPoint = null;
+ /**
+ * Specifies the start location for a simulated DnD (like system drag or accessibility drag),
+ * null when using internal DnD
+ */
+ public Point simulatedDndStartPoint = null;
/** Determines when a pre-drag should transition to a drag. By default, this is immediate. */
public PreDragCondition preDragCondition = null;
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 145885a..7c76d34 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -19,8 +19,6 @@
import static com.android.launcher3.Utilities.getBadge;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.animation.FloatArrayEvaluator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -146,15 +144,6 @@
}
});
- mAnim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (!mAnimationCancelled) {
- mDragController.onDragViewAnimationEnd();
- }
- }
- });
-
mBitmap = bitmap;
setDragRegion(new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()));
diff --git a/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java b/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java
index 06b5c40..7788f93 100644
--- a/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java
+++ b/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java
@@ -17,8 +17,6 @@
package com.android.launcher3.dragndrop;
import android.graphics.PointF;
-import android.os.SystemClock;
-import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
@@ -55,31 +53,6 @@
mVelocityTracker.addMovement(ev);
}
- /**
- * Same as {@link #recordMotionEvent}. It creates a temporary {@link MotionEvent} object
- * using {@param event} for tracking velocity.
- */
- public void recordDragEvent(long dragStartTime, DragEvent event) {
- final int motionAction;
- switch (event.getAction()) {
- case DragEvent.ACTION_DRAG_STARTED:
- motionAction = MotionEvent.ACTION_DOWN;
- break;
- case DragEvent.ACTION_DRAG_LOCATION:
- motionAction = MotionEvent.ACTION_MOVE;
- break;
- case DragEvent.ACTION_DRAG_ENDED:
- motionAction = MotionEvent.ACTION_UP;
- break;
- default:
- return;
- }
- MotionEvent emulatedEvent = MotionEvent.obtain(dragStartTime, SystemClock.uptimeMillis(),
- motionAction, event.getX(), event.getY(), 0);
- recordMotionEvent(emulatedEvent);
- emulatedEvent.recycle();
- }
-
public void releaseVelocityTracker() {
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 5f496f4..c20717a 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -85,6 +85,7 @@
import com.android.launcher3.Workspace.ItemOperator;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
+import com.android.launcher3.accessibility.FolderAccessibilityHelper;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragController.DragListener;
@@ -271,16 +272,15 @@
mDragController.addDragListener(this);
if (options.isAccessibleDrag) {
mDragController.addDragListener(new AccessibleDragListenerAdapter(
- mContent, CellLayout.FOLDER_ACCESSIBILITY_DRAG) {
-
- @Override
- protected void enableAccessibleDrag(boolean enable) {
- super.enableAccessibleDrag(enable);
- mFooter.setImportantForAccessibility(enable
- ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
- : IMPORTANT_FOR_ACCESSIBILITY_AUTO);
- }
- });
+ mContent, FolderAccessibilityHelper::new) {
+ @Override
+ protected void enableAccessibleDrag(boolean enable) {
+ super.enableAccessibleDrag(enable);
+ mFooter.setImportantForAccessibility(enable
+ ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+ : IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+ }
+ });
}
mLauncher.getWorkspace().beginDragShared(v, this, options);