Reland - Not refresh predicted app in right click

When users right click the mouse/touchpad, predicted apps in hotseat refresh and it is weird.
It refreshes because the right click is treated as a drag and a drag would trigger predicted apps refresh.
This fix adds a PreDragCondition when right click to avoid it from starting drag.

Bug: 343650193
Test: Manual, connect to touchpad and right click on widget and folderIcon
Flag: com.android.launcher3.remove_apps_refresh_on_right_click
Change-Id: Id0be87beb8a0e9baf78a4ba8ec4c93462ec7bb3e
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index 9f505a4..d3f5515 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -666,3 +666,13 @@
     purpose: PURPOSE_BUGFIX
   }
 }
+
+flag {
+  name: "remove_apps_refresh_on_right_click"
+  namespace: "launcher"
+  description: "Remove predicted apps refresh on right click"
+  bug: "343650193"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 4127dd1..284faba 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3.dragndrop;
 
+import static com.android.launcher3.Flags.removeAppsRefreshOnRightClick;
 import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_NOT_PINNABLE;
 
 import android.graphics.Point;
@@ -521,17 +522,21 @@
 
         mDragObject.dragComplete = true;
         if (mIsInPreDrag) {
-            if (dropTarget != null) {
-                dropTarget.onDragExit(mDragObject);
+            if (removeAppsRefreshOnRightClick()) {
+                mDragObject.cancelled = true;
+            } else {
+                if (dropTarget != null) {
+                    dropTarget.onDragExit(mDragObject);
+                }
+                return;
             }
-            return;
         }
 
         // Drop onto the target.
         boolean accepted = false;
         if (dropTarget != null) {
             dropTarget.onDragExit(mDragObject);
-            if (dropTarget.acceptDrop(mDragObject)) {
+            if (!mIsInPreDrag && dropTarget.acceptDrop(mDragObject)) {
                 if (flingAnimation != null) {
                     flingAnimation.run();
                 } else {
diff --git a/src/com/android/launcher3/dragndrop/LauncherDragController.java b/src/com/android/launcher3/dragndrop/LauncherDragController.java
index 4aa3673..dd433c0 100644
--- a/src/com/android/launcher3/dragndrop/LauncherDragController.java
+++ b/src/com/android/launcher3/dragndrop/LauncherDragController.java
@@ -15,7 +15,10 @@
  */
 package com.android.launcher3.dragndrop;
 
+import static android.view.View.VISIBLE;
+
 import static com.android.launcher3.AbstractFloatingView.TYPE_DISCOVERY_BOUNCE;
+import static com.android.launcher3.Flags.removeAppsRefreshOnRightClick;
 import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
 import static com.android.launcher3.LauncherState.EDIT_MODE;
 import static com.android.launcher3.LauncherState.NORMAL;
@@ -25,6 +28,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.view.HapticFeedbackConstants;
+import android.view.MotionEvent;
 import android.view.View;
 
 import androidx.annotation.Nullable;
@@ -33,10 +37,13 @@
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.DragSource;
 import com.android.launcher3.DropTarget;
+import com.android.launcher3.DropTarget.DragObject;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.accessibility.DragViewStateAnnouncer;
+import com.android.launcher3.dragndrop.DragOptions.PreDragCondition;
 import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.util.TouchUtil;
 import com.android.launcher3.widget.util.WidgetDragScaleUtils;
 
 /**
@@ -47,6 +54,9 @@
     private static final boolean PROFILE_DRAWING_DURING_DRAG = false;
     private final FlingToDeleteHelper mFlingToDeleteHelper;
 
+    /** Whether or not the drag operation is triggered by mouse right click. */
+    private boolean mIsInMouseRightClick = false;
+
     public LauncherDragController(Launcher launcher) {
         super(launcher);
         mFlingToDeleteHelper = new FlingToDeleteHelper(launcher);
@@ -69,6 +79,28 @@
             android.os.Debug.startMethodTracing("Launcher");
         }
 
+        if (removeAppsRefreshOnRightClick() && mIsInMouseRightClick
+                && options.preDragCondition == null
+                && originalView instanceof View v) {
+            options.preDragCondition = new PreDragCondition() {
+
+                @Override
+                public boolean shouldStartDrag(double distanceDragged) {
+                    return false;
+                }
+
+                @Override
+                public void onPreDragStart(DragObject dragObject) {
+                    // Set it to visible so the text of FolderIcon would not flash (avoid it from
+                    // being invisible and then visible)
+                    v.setVisibility(VISIBLE);
+                }
+
+                @Override
+                public void onPreDragEnd(DragObject dragObject, boolean dragStarted) { }
+            };
+        }
+
         mActivity.hideKeyboard();
         AbstractFloatingView.closeOpenViews(mActivity, false, TYPE_DISCOVERY_BOUNCE);
 
@@ -191,7 +223,7 @@
 
     @Override
     protected void exitDrag() {
-        if (!mActivity.isInState(EDIT_MODE)) {
+        if (!mIsInPreDrag && !mActivity.isInState(EDIT_MODE)) {
             mActivity.getStateManager().goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
         }
     }
@@ -218,4 +250,13 @@
                 dropCoordinates);
         return mActivity.getWorkspace();
     }
+
+    /**
+     * Intercepts touch events from a drag source view.
+     */
+    @Override
+    public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+        mIsInMouseRightClick = TouchUtil.isMouseRightClickDownOrMove(ev);
+        return super.onControllerInterceptTouchEvent(ev);
+    }
 }
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 2803256..0ae9519 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -102,7 +102,6 @@
 import com.android.launcher3.pageindicators.PageIndicatorDots;
 import com.android.launcher3.util.Executors;
 import com.android.launcher3.util.LauncherBindableItemsContainer;
-import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
 import com.android.launcher3.util.Thunk;
 import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.views.BaseDragLayer;
@@ -1116,13 +1115,15 @@
             View icon = (mCurrentDragView != null && mCurrentDragView.getTag() == info)
                     ? mCurrentDragView : mContent.createNewView(info);
             ArrayList<View> views = getIconsInReadingOrder();
-            info.rank = Utilities.boundToRange(info.rank, 0, views.size());
-            views.add(info.rank, icon);
-            mContent.arrangeChildren(views);
-            mItemsInvalidated = true;
+            if (!views.contains(icon)) {
+                info.rank = Utilities.boundToRange(info.rank, 0, views.size());
+                views.add(info.rank, icon);
+                mContent.arrangeChildren(views);
+                mItemsInvalidated = true;
 
-            try (SuppressInfoChanges s = new SuppressInfoChanges()) {
-                mFolderIcon.onDrop(d, true /* itemReturnedOnFailedDrop */);
+                try (SuppressInfoChanges s = new SuppressInfoChanges()) {
+                    mFolderIcon.onDrop(d, true /* itemReturnedOnFailedDrop */);
+                }
             }
         }