summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher3/AnotherWindowDropTarget.java61
-rw-r--r--src/com/android/launcher3/Launcher.java12
-rw-r--r--src/com/android/launcher3/compat/PinItemRequestCompat.java29
-rw-r--r--src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java5
-rw-r--r--src/com/android/launcher3/dragndrop/AddItemActivity.java65
-rw-r--r--src/com/android/launcher3/dragndrop/AnotherWindowDragSource.java67
-rw-r--r--src/com/android/launcher3/dragndrop/DragController.java4
-rw-r--r--src/com/android/launcher3/dragndrop/DragDriver.java60
-rw-r--r--src/com/android/launcher3/dragndrop/DragLayer.java53
-rw-r--r--src/com/android/launcher3/dragndrop/ExternalDragPreviewProvider.java79
-rw-r--r--src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java27
-rw-r--r--src/com/android/launcher3/dragndrop/PinItemDragListener.java259
-rw-r--r--src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java16
-rw-r--r--src/com/android/launcher3/widget/WidgetCell.java16
14 files changed, 411 insertions, 342 deletions
diff --git a/src/com/android/launcher3/AnotherWindowDropTarget.java b/src/com/android/launcher3/AnotherWindowDropTarget.java
deleted file mode 100644
index 052e5d09a..000000000
--- a/src/com/android/launcher3/AnotherWindowDropTarget.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2015 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;
-
-import android.content.Context;
-import android.graphics.PointF;
-import android.graphics.Rect;
-
-/**
- * Drop target used when another window (i.e. another process) has accepted a global system drag.
- * If the accepted item was a shortcut, we delete it from Launcher.
- */
-public class AnotherWindowDropTarget implements DropTarget {
- final Launcher mLauncher;
-
- public AnotherWindowDropTarget (Context context) { mLauncher = Launcher.getLauncher(context); }
-
- @Override
- public boolean isDropEnabled() { return true; }
-
- @Override
- public void onDrop(DragObject dragObject) {
- dragObject.deferDragViewCleanupPostAnimation = false;
- LauncherModel.deleteItemFromDatabase(mLauncher, (ShortcutInfo) dragObject.dragInfo);
- }
-
- @Override
- public void onDragEnter(DragObject dragObject) {}
-
- @Override
- public void onDragOver(DragObject dragObject) {}
-
- @Override
- public void onDragExit(DragObject dragObject) {}
-
- @Override
- public boolean acceptDrop(DragObject dragObject) {
- return dragObject.dragInfo instanceof ShortcutInfo;
- }
-
- @Override
- public void prepareAccessibilityDrop() {}
-
- // These methods are implemented in Views
- @Override
- public void getHitRectRelativeToDragLayer(Rect outRect) {}
-}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 8d8a70c0f..8dfc211a9 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -49,6 +49,7 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Parcelable;
import android.os.Process;
import android.os.StrictMode;
import android.os.SystemClock;
@@ -94,6 +95,7 @@ import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.DragView;
+import com.android.launcher3.dragndrop.PinItemDragListener;
import com.android.launcher3.dynamicui.ExtractedColors;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
@@ -826,7 +828,7 @@ public class Launcher extends BaseActivity
}
@Override
- protected void onActivityResult(
+ public void onActivityResult(
final int requestCode, final int resultCode, final Intent data) {
handleActivityResult(requestCode, resultCode, data);
if (mLauncherCallbacks != null) {
@@ -1752,6 +1754,14 @@ public class Launcher extends BaseActivity
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onHomeIntent();
}
+
+ Parcelable dragExtra = intent
+ .getParcelableExtra(PinItemDragListener.EXTRA_PIN_ITEM_DRAG_LISTENER);
+ if (dragExtra instanceof PinItemDragListener) {
+ PinItemDragListener dragListener = (PinItemDragListener) dragExtra;
+ dragListener.setLauncher(this);
+ mDragLayer.setOnDragListener(dragListener);
+ }
}
if (mLauncherCallbacks != null) {
diff --git a/src/com/android/launcher3/compat/PinItemRequestCompat.java b/src/com/android/launcher3/compat/PinItemRequestCompat.java
index 74d77659c..481310a15 100644
--- a/src/com/android/launcher3/compat/PinItemRequestCompat.java
+++ b/src/com/android/launcher3/compat/PinItemRequestCompat.java
@@ -21,13 +21,14 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.os.Bundle;
+import android.os.Parcel;
import android.os.Parcelable;
/**
* A wrapper around platform implementation of PinItemRequestCompat until the
* updated SDK is available.
*/
-public class PinItemRequestCompat {
+public class PinItemRequestCompat implements Parcelable {
public static final String EXTRA_PIN_ITEM_REQUEST = "android.content.pm.extra.PIN_ITEM_REQUEST";
@@ -83,6 +84,32 @@ public class PinItemRequestCompat {
}
}
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int i) {
+ parcel.writeParcelable(mObject, i);
+ }
+
+ public Intent toIntent() {
+ return new Intent().putExtra(EXTRA_PIN_ITEM_REQUEST, mObject);
+ }
+
+ public static final Parcelable.Creator<PinItemRequestCompat> CREATOR =
+ new Parcelable.Creator<PinItemRequestCompat>() {
+ public PinItemRequestCompat createFromParcel(Parcel source) {
+ Parcelable object = source.readParcelable(null);
+ return new PinItemRequestCompat(object);
+ }
+
+ public PinItemRequestCompat[] newArray(int size) {
+ return new PinItemRequestCompat[size];
+ }
+ };
+
public static PinItemRequestCompat getPinItemRequest(Intent intent) {
Parcelable extra = intent.getParcelableExtra(EXTRA_PIN_ITEM_REQUEST);
return extra == null ? null : new PinItemRequestCompat(extra);
diff --git a/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java b/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
index ece775986..1cfbd2061 100644
--- a/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
+++ b/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
@@ -35,6 +35,7 @@ import android.util.Log;
import android.widget.Toast;
import com.android.launcher3.IconCache;
+import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -67,7 +68,7 @@ public abstract class ShortcutConfigActivityInfo {
public abstract Drawable getFullResIcon(IconCache cache);
- public boolean startConfigActivity(Activity activity, int requestCode) {
+ public boolean startConfigActivity(Launcher activity, int requestCode) {
Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT)
.setComponent(getComponent());
try {
@@ -136,7 +137,7 @@ public abstract class ShortcutConfigActivityInfo {
}
@Override
- public boolean startConfigActivity(Activity activity, int requestCode) {
+ public boolean startConfigActivity(Launcher activity, int requestCode) {
if (getUser().equals(Process.myUserHandle())) {
return super.startConfigActivity(activity, requestCode);
}
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index 6c6f14124..423fdabfc 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -17,12 +17,23 @@
package com.android.launcher3.dragndrop;
import android.annotation.TargetApi;
+import android.app.ActivityOptions;
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
+import android.content.ClipData;
+import android.content.ClipDescription;
import android.content.Intent;
+import android.graphics.Canvas;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.os.Build;
import android.os.Bundle;
+import android.util.Log;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.View.*;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.InstallShortcutReceiver;
@@ -38,13 +49,18 @@ import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.WidgetCell;
import com.android.launcher3.widget.WidgetHostViewLoader;
+import com.android.launcher3.widget.WidgetImageView;
@TargetApi(Build.VERSION_CODES.N_MR1)
-public class AddItemActivity extends BaseActivity {
+public class AddItemActivity extends BaseActivity implements OnLongClickListener, OnTouchListener {
+
+ private static final int SHADOW_SIZE = 10;
private static final int REQUEST_BIND_APPWIDGET = 1;
private static final String STATE_EXTRA_WIDGET_ID = "state.widget.id";
+ private final PointF mLastTouchPos = new PointF();
+
private PinItemRequestCompat mRequest;
private LauncherAppState mApp;
private InvariantDeviceProfile mIdp;
@@ -86,11 +102,54 @@ public class AddItemActivity extends BaseActivity {
finish();
}
}
+
+ mWidgetCell.setOnTouchListener(this);
+ mWidgetCell.setOnLongClickListener(this);
+ }
+
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ mLastTouchPos.set(motionEvent.getX(), motionEvent.getY());
+ return false;
+ }
+
+ @Override
+ public boolean onLongClick(View view) {
+ // Find the position of the preview relative to the touch location.
+ WidgetImageView img = mWidgetCell.getWidgetView();
+ Rect bounds = img.getBitmapBounds();
+ bounds.offset(img.getLeft() - (int) mLastTouchPos.x, img.getTop() - (int) mLastTouchPos.y);
+
+ // Start home and pass the draw request params
+ PinItemDragListener listener = new PinItemDragListener(mRequest, bounds);
+ Intent homeIntent = new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME)
+ .setPackage(getPackageName())
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .putExtra(PinItemDragListener.EXTRA_PIN_ITEM_DRAG_LISTENER, listener);
+ startActivity(homeIntent,
+ ActivityOptions.makeCustomAnimation(this, 0, android.R.anim.fade_out).toBundle());
+
+ // Start a system drag and drop. We use a transparent bitmap as preview for system drag
+ // as the preview is handled internally by launcher.
+ ClipDescription description = new ClipDescription("", new String[]{listener.getMimeType()});
+ ClipData data = new ClipData(description, new ClipData.Item(""));
+ view.startDragAndDrop(data, new DragShadowBuilder(view) {
+
+ @Override
+ public void onDrawShadow(Canvas canvas) { }
+
+ @Override
+ public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
+ outShadowSize.set(SHADOW_SIZE, SHADOW_SIZE);
+ outShadowTouchPoint.set(SHADOW_SIZE / 2, SHADOW_SIZE / 2);
+ }
+ }, null, View.DRAG_FLAG_GLOBAL);
+ return false;
}
private void setupShortcut() {
- WidgetItem item = new WidgetItem(new PinShortcutRequestActivityInfo(
- mRequest.getShortcutInfo(), this));
+ WidgetItem item = new WidgetItem(new PinShortcutRequestActivityInfo(mRequest, this));
mWidgetCell.applyFromCellItem(item, mApp.getWidgetCache());
mWidgetCell.ensurePreview();
}
diff --git a/src/com/android/launcher3/dragndrop/AnotherWindowDragSource.java b/src/com/android/launcher3/dragndrop/AnotherWindowDragSource.java
deleted file mode 100644
index 162301069..000000000
--- a/src/com/android/launcher3/dragndrop/AnotherWindowDragSource.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2016 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.dragndrop;
-
-import android.content.Context;
-import android.view.View;
-
-import com.android.launcher3.DragSource;
-import com.android.launcher3.DropTarget.DragObject;
-import com.android.launcher3.ItemInfo;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
-
-/**
- * DragSource used when the drag started at another window.
- */
-public class AnotherWindowDragSource implements DragSource {
-
- private final Context mContext;
-
- AnotherWindowDragSource(Context context) {
- mContext = context;
- }
-
- @Override
- public boolean supportsAppInfoDropTarget() {
- return false;
- }
-
- @Override
- public boolean supportsDeleteDropTarget() {
- return false;
- }
-
- @Override
- public float getIntrinsicIconScaleFactor() {
- return 1;
- }
-
- @Override
- public void onDropCompleted(View target, DragObject d,
- boolean isFlingToDelete, boolean success) {
- if (!success) {
- Launcher.getLauncher(mContext).exitSpringLoadedDragModeDelayed(false, 0, null);
- }
-
- }
-
- @Override
- public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) {
- // TODO: Probably log something
- }
-}
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 745776db3..80c286027 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -36,7 +36,6 @@ import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.TouchController;
@@ -447,7 +446,8 @@ public class DragController implements DragDriver.EventListener, TouchController
/**
* Call this from a drag source view.
*/
- public boolean onDragEvent(DragEvent event) {
+ public boolean onDragEvent(long dragStartTime, DragEvent event) {
+ mFlingToDeleteHelper.recordDragEvent(dragStartTime, event);
return mDragDriver != null && mDragDriver.onDragEvent(event);
}
diff --git a/src/com/android/launcher3/dragndrop/DragDriver.java b/src/com/android/launcher3/dragndrop/DragDriver.java
index a90cfffdc..65c0f29b1 100644
--- a/src/com/android/launcher3/dragndrop/DragDriver.java
+++ b/src/com/android/launcher3/dragndrop/DragDriver.java
@@ -16,20 +16,13 @@
package com.android.launcher3.dragndrop;
-import android.content.ClipData;
-import android.content.ClipDescription;
import android.content.Context;
-import android.content.Intent;
import android.view.DragEvent;
import android.view.MotionEvent;
import com.android.launcher3.DropTarget.DragObject;
-import com.android.launcher3.InstallShortcutReceiver;
-import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
-import java.util.ArrayList;
-
/**
* Base class for driving a drag/drop operation.
*/
@@ -107,7 +100,6 @@ class SystemDragDriver extends DragDriver {
private final DragObject mDragObject;
private final Context mContext;
- boolean mReceivedDropEvent = false;
float mLastX = 0;
float mLastY = 0;
@@ -149,65 +141,21 @@ class SystemDragDriver extends DragDriver {
case DragEvent.ACTION_DROP:
mLastX = event.getX();
mLastY = event.getY();
- mReceivedDropEvent =
- updateInfoFromClipData(event.getClipData(), event.getClipDescription());
- return mReceivedDropEvent;
-
+ 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:
- if (mReceivedDropEvent) {
- mEventListener.onDriverDragEnd(mLastX, mLastY);
- } else {
- mEventListener.onDriverDragCancel();
- }
+ mEventListener.onDriverDragCancel();
return true;
default:
return false;
}
}
-
- private boolean updateInfoFromClipData(ClipData data, ClipDescription desc) {
- if (data == null) {
- return false;
- }
- ArrayList<Intent> intents = new ArrayList<>();
- int itemCount = data.getItemCount();
- for (int i = 0; i < itemCount; i++) {
- Intent intent = data.getItemAt(i).getIntent();
- if (intent == null) {
- continue;
- }
-
- // Give preference to shortcut intents.
- if (!Intent.ACTION_CREATE_SHORTCUT.equals(intent.getAction())) {
- intents.add(intent);
- continue;
- }
- ShortcutInfo info = InstallShortcutReceiver.fromShortcutIntent(mContext, intent);
- if (info != null) {
- mDragObject.dragInfo = info;
- return true;
- }
- return true;
- }
-
- // Try creating shortcuts just using the intent and label
- Intent fullIntent = new Intent().putExtra(Intent.EXTRA_SHORTCUT_NAME, desc.getLabel());
- for (Intent intent : intents) {
- fullIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, intent);
- ShortcutInfo info = InstallShortcutReceiver.fromShortcutIntent(mContext, fullIntent);
- if (info != null) {
- mDragObject.dragInfo = info;
- return true;
- }
- }
-
- return false;
- }
}
/**
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 4279cc319..de416e3bc 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -21,21 +21,13 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.annotation.TargetApi;
-import android.content.ClipDescription;
import android.content.Context;
-import android.content.Intent;
import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
-import android.os.Build;
import android.util.AttributeSet;
-import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -59,9 +51,7 @@ import com.android.launcher3.LauncherAppWidgetHostView;
import com.android.launcher3.PinchToOverviewListener;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
-import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
-import com.android.launcher3.Workspace;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.Folder;
@@ -373,49 +363,6 @@ public class DragLayer extends InsettableFrameLayout {
return false;
}
- @TargetApi(Build.VERSION_CODES.N)
- private void handleSystemDragStart(DragEvent event) {
- if (!FeatureFlags.LAUNCHER3_USE_SYSTEM_DRAG_DRIVER || !Utilities.ATLEAST_NOUGAT) {
- return;
- }
- if (mLauncher.isWorkspaceLocked()) {
- return;
- }
-
- ClipDescription description = event.getClipDescription();
- if (!description.hasMimeType(ClipDescription.MIMETYPE_TEXT_INTENT)) {
- return;
- }
- ShortcutInfo info = new ShortcutInfo();
- // Set a dummy intent until we get the final value
- info.intent = new Intent();
-
- // Since we are not going through the workspace for starting the drag, set drag related
- // information on the workspace before starting the drag.
- ExternalDragPreviewProvider previewProvider =
- new ExternalDragPreviewProvider(mLauncher, info);
- mLauncher.getWorkspace().prepareDragWithProvider(previewProvider);
-
- DragOptions options = new DragOptions();
- options.systemDndStartPoint = new Point((int) event.getX(), (int) event.getY());
-
- int halfPadding = previewProvider.previewPadding / 2;
- mDragController.startDrag(
- Bitmap.createBitmap(1, 1, Config.ARGB_8888),
- 0, 0,
- new AnotherWindowDragSource(mLauncher), info,
- new Point(- halfPadding, halfPadding),
- previewProvider.getPreviewBounds(), 1f, options);
- }
-
- @Override
- public boolean onDragEvent (DragEvent event) {
- if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
- handleSystemDragStart(event);
- }
- return mDragController.onDragEvent(event);
- }
-
/**
* Determine the rect of the descendant in this DragLayer's coordinates
*
diff --git a/src/com/android/launcher3/dragndrop/ExternalDragPreviewProvider.java b/src/com/android/launcher3/dragndrop/ExternalDragPreviewProvider.java
deleted file mode 100644
index e558487b8..000000000
--- a/src/com/android/launcher3/dragndrop/ExternalDragPreviewProvider.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2016 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.dragndrop;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.ItemInfo;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.graphics.DragPreviewProvider;
-import com.android.launcher3.graphics.HolographicOutlineHelper;
-
-/**
- * Extension of {@link DragPreviewProvider} which provides a dummy outline when drag starts from
- * a different window.
- * It just draws an empty circle to a placeholder outline.
- */
-public class ExternalDragPreviewProvider extends DragPreviewProvider {
-
- private final Launcher mLauncher;
- private final ItemInfo mAddInfo;
-
- private final int[] mOutlineSize;
-
- public ExternalDragPreviewProvider(Launcher launcher, ItemInfo addInfo) {
- super(null, launcher);
- mLauncher = launcher;
- mAddInfo = addInfo;
-
- mOutlineSize = mLauncher.getWorkspace().estimateItemSize(mAddInfo, false, false);
- }
-
- public Rect getPreviewBounds() {
- Rect rect = new Rect();
- DeviceProfile dp = mLauncher.getDeviceProfile();
- rect.left = blurSizeOutline / 2;
- rect.top = (mOutlineSize[1] - dp.cellHeightPx) / 2;
- rect.right = rect.left + dp.iconSizePx;
- rect.bottom = rect.top + dp.iconSizePx;
- return rect;
- }
-
- @Override
- public Bitmap createDragOutline(Canvas canvas) {
- final Bitmap b = Bitmap.createBitmap(mOutlineSize[0], mOutlineSize[1], Bitmap.Config.ALPHA_8);
- canvas.setBitmap(b);
-
- Paint paint = new Paint();
- paint.setColor(Color.WHITE);
- paint.setStyle(Paint.Style.FILL);
-
- // Use 0.9f times the radius for the actual circle to account for icon normalization.
- float radius = getPreviewBounds().width() * 0.5f;
- canvas.drawCircle(blurSizeOutline / 2 + radius,
- blurSizeOutline / 2 + radius, radius * 0.9f, paint);
-
- HolographicOutlineHelper.getInstance(mLauncher).applyExpensiveOutlineWithBlur(b, canvas);
- canvas.setBitmap(null);
- return b;
- }
-}
diff --git a/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java b/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java
index a2aa27d17..e79474483 100644
--- a/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java
+++ b/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java
@@ -17,6 +17,8 @@
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;
@@ -53,6 +55,31 @@ public class FlingToDeleteHelper {
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/dragndrop/PinItemDragListener.java b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
new file mode 100644
index 000000000..1a99cc886
--- /dev/null
+++ b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2017 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.dragndrop;
+
+import android.content.ClipDescription;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.DragEvent;
+import android.view.View;
+
+import com.android.launcher3.DeleteDropTarget;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.DragSource;
+import com.android.launcher3.DropTarget;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.PendingAddItemInfo;
+import com.android.launcher3.compat.PinItemRequestCompat;
+import com.android.launcher3.folder.Folder;
+import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.shortcuts.ShortcutInfoCompat;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.launcher3.widget.PendingAddShortcutInfo;
+import com.android.launcher3.widget.PendingAddWidgetInfo;
+import com.android.launcher3.widget.PendingItemPreviewProvider;
+
+import java.util.UUID;
+
+/**
+ * {@link DragSource} for handling drop from from a different window. This object is initialized
+ * in the source window and is passed on to the Launcher activity as an Intent extra.
+ */
+public class PinItemDragListener implements Parcelable, View.OnDragListener, DragSource {
+
+ private static final String TAG = "PinItemDragListener";
+
+ private static final String MIME_TYPE_PREFIX = "com.android.launcher3.drag_and_drop/";
+ public static final String EXTRA_PIN_ITEM_DRAG_LISTENER = "pin_item_drag_listener";
+
+ private final PinItemRequestCompat mRequest;
+
+ // Position of preview relative to the touch location
+ private final Rect mPreviewRect;
+
+ // Randomly generated id used to verify the drag event.
+ private final String mId;
+
+ private Launcher mLauncher;
+ private DragController mDragController;
+ private long mDragStartTime;
+
+ public PinItemDragListener(PinItemRequestCompat request, Rect previewRect) {
+ mRequest = request;
+ mPreviewRect = previewRect;
+ mId = UUID.randomUUID().toString();
+ }
+
+ private PinItemDragListener(Parcel parcel) {
+ mRequest = PinItemRequestCompat.CREATOR.createFromParcel(parcel);
+ mPreviewRect = Rect.CREATOR.createFromParcel(parcel);
+ mId = parcel.readString();
+ }
+
+ public String getMimeType() {
+ return MIME_TYPE_PREFIX + mId;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int i) {
+ mRequest.writeToParcel(parcel, i);
+ mPreviewRect.writeToParcel(parcel, i);
+ parcel.writeString(mId);
+ }
+
+ public void setLauncher(Launcher launcher) {
+ mLauncher = launcher;
+ mDragController = launcher.getDragController();
+ }
+
+ @Override
+ public boolean onDrag(View view, DragEvent event) {
+ if (mLauncher == null || mDragController == null) {
+ postCleanup();
+ return false;
+ }
+ if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
+ if (onDragStart(event)) {
+ return true;
+ } else {
+ postCleanup();
+ return false;
+ }
+ }
+ return mDragController.onDragEvent(mDragStartTime, event);
+ }
+
+ private boolean onDragStart(DragEvent event) {
+ if (!mRequest.isValid()) {
+ return false;
+ }
+ ClipDescription desc = event.getClipDescription();
+ if (desc == null || !desc.hasMimeType(getMimeType())) {
+ Log.e(TAG, "Someone started a dragAndDrop before us.");
+ return false;
+ }
+
+ if (mLauncher.isWorkspaceLocked()) {
+ // TODO: implement wait
+ return false;
+ }
+
+ final PendingAddItemInfo item;
+ final Bitmap preview;
+
+ Point dragShift = new Point(mPreviewRect.left, mPreviewRect.top);
+ if (mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT) {
+ item = new PendingAddShortcutInfo(
+ new PinShortcutRequestActivityInfo(mRequest, mLauncher));
+
+ ShortcutInfoCompat compat = new ShortcutInfoCompat(mRequest.getShortcutInfo());
+ Bitmap icon = LauncherIcons.createShortcutIcon(compat, mLauncher, false /* badged */);
+
+ // Create a preview same as the workspace cell size and draw the icon at the
+ // appropriate position.
+ int[] size = mLauncher.getWorkspace().estimateItemSize(item, true, false);
+ preview = Bitmap.createBitmap(size[0], size[1], Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(preview);
+ DeviceProfile dp = mLauncher.getDeviceProfile();
+ c.drawBitmap(icon, (size[0] - icon.getWidth()) / 2,
+ (size[1] - icon.getHeight() - dp.iconTextSizePx - dp.iconDrawablePaddingPx) / 2,
+ new Paint(Paint.FILTER_BITMAP_FLAG));
+ } else {
+ PendingAddWidgetInfo info = new PendingAddWidgetInfo(
+ LauncherAppWidgetProviderInfo.fromProviderInfo(
+ mLauncher, mRequest.getAppWidgetProviderInfo(mLauncher)));
+ int[] size = mLauncher.getWorkspace().estimateItemSize(info, true, false);
+
+ float minScale = 1.25f;
+ int maxWidth = Math.min((int) (mPreviewRect.width() * minScale), size[0]);
+ int[] previewSizeBeforeScale = new int[1];
+ preview = LauncherAppState.getInstance(mLauncher).getWidgetCache()
+ .generateWidgetPreview(mLauncher, info.info, maxWidth, null,
+ previewSizeBeforeScale);
+
+ dragShift.offset(
+ (mPreviewRect.width() - preview.getWidth()) / 2,
+ (mPreviewRect.height() - preview.getHeight()) / 2);
+ item = info;
+ }
+
+ PendingItemPreviewProvider previewProvider =
+ new PendingItemPreviewProvider(new View(mLauncher), item, preview);
+
+ // Since we are not going through the workspace for starting the drag, set drag related
+ // information on the workspace before starting the drag.
+ mLauncher.getWorkspace().prepareDragWithProvider(previewProvider);
+
+ Point downPos = new Point((int) event.getX(), (int) event.getY());
+ DragOptions options = new DragOptions();
+ options.systemDndStartPoint = downPos;
+
+ int x = downPos.x + dragShift.x;
+ int y = downPos.y + dragShift.y;
+ mDragController.startDrag(
+ preview, x, y, this, item, null, null, 1f, options);
+ mDragStartTime = SystemClock.uptimeMillis();
+ return true;
+ }
+
+ @Override
+ public boolean supportsAppInfoDropTarget() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsDeleteDropTarget() {
+ return false;
+ }
+
+ @Override
+ public float getIntrinsicIconScaleFactor() {
+ return 1f;
+ }
+
+ @Override
+ public void onDropCompleted(View target, DropTarget.DragObject d, boolean isFlingToDelete,
+ boolean success) {
+ if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() &&
+ !(target instanceof DeleteDropTarget) && !(target instanceof Folder))) {
+ // Exit spring loaded mode if we have not successfully dropped or have not handled the
+ // drop in Workspace
+ mLauncher.exitSpringLoadedDragModeDelayed(true,
+ Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
+ }
+ postCleanup();
+ }
+
+ @Override
+ public void fillInLogContainerData(View v, ItemInfo info, LauncherLogProto.Target target,
+ LauncherLogProto.Target targetParent) {
+ // TODO: We should probably log something
+ }
+
+ private void postCleanup() {
+ new Handler(Looper.getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ removeListener();
+ }
+ });
+ }
+
+ public void removeListener() {
+ if (mLauncher != null) {
+ mLauncher.getDragLayer().setOnDragListener(null);
+ }
+ }
+
+ public static final Parcelable.Creator<PinItemDragListener> CREATOR =
+ new Parcelable.Creator<PinItemDragListener>() {
+ public PinItemDragListener createFromParcel(Parcel source) {
+ return new PinItemDragListener(source);
+ }
+
+ public PinItemDragListener[] newArray(int size) {
+ return new PinItemDragListener[size];
+ }
+ };
+}
diff --git a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
index d1f878a17..2121b438a 100644
--- a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
+++ b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
@@ -26,7 +26,9 @@ import android.graphics.drawable.Drawable;
import android.os.Build;
import com.android.launcher3.IconCache;
+import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.compat.PinItemRequestCompat;
import com.android.launcher3.compat.ShortcutConfigActivityInfo;
/**
@@ -40,12 +42,15 @@ class PinShortcutRequestActivityInfo extends ShortcutConfigActivityInfo {
// actual existing class.
private static final String DUMMY_COMPONENT_CLASS = "pinned-shortcut";
+ private final PinItemRequestCompat mRequest;
private final ShortcutInfo mInfo;
private final Context mContext;
- public PinShortcutRequestActivityInfo(ShortcutInfo info, Context context) {
- super(new ComponentName(info.getPackage(), DUMMY_COMPONENT_CLASS), info.getUserHandle());
- mInfo = info;
+ public PinShortcutRequestActivityInfo(PinItemRequestCompat request, Context context) {
+ super(new ComponentName(request.getShortcutInfo().getPackage(), DUMMY_COMPONENT_CLASS),
+ request.getShortcutInfo().getUserHandle());
+ mRequest = request;
+ mInfo = request.getShortcutInfo();
mContext = context;
}
@@ -61,8 +66,9 @@ class PinShortcutRequestActivityInfo extends ShortcutConfigActivityInfo {
}
@Override
- public boolean startConfigActivity(Activity activity, int requestCode) {
- throw new RuntimeException("Not supported");
+ public boolean startConfigActivity(Launcher activity, int requestCode) {
+ activity.onActivityResult(requestCode, Activity.RESULT_OK, mRequest.toIntent());
+ return true;
}
@Override
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index 87247f417..455ec4ef8 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -144,12 +144,8 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
}
}
- public int[] getPreviewSize() {
- int[] maxSize = new int[2];
-
- maxSize[0] = mPresetPreviewSize;
- maxSize[1] = mPresetPreviewSize;
- return maxSize;
+ public WidgetImageView getWidgetView() {
+ return mWidgetImage;
}
public void applyPreview(Bitmap bitmap) {
@@ -166,12 +162,8 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
if (mActiveRequest != null) {
return;
}
- int[] size = getPreviewSize();
- if (DEBUG) {
- Log.d(TAG, String.format("[tag=%s] ensurePreview (%d, %d):",
- getTagToString(), size[0], size[1]));
- }
- mActiveRequest = mWidgetPreviewLoader.getPreview(mItem, size[0], size[1], this);
+ mActiveRequest = mWidgetPreviewLoader.getPreview(
+ mItem, mPresetPreviewSize, mPresetPreviewSize, this);
}
@Override