131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/*
231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License.
631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at
731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and
1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License.
1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17a5902524d4403885eb4c50360bf3465c6be796efJoe Onoratopackage com.android.launcher2;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.content.Context;
206e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chungimport android.content.res.Resources;
2100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.graphics.Bitmap;
22b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chungimport android.graphics.Point;
23043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.graphics.PointF;
2400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.graphics.Rect;
2500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.os.Handler;
260280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.os.IBinder;
2700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.os.Vibrator;
2800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.util.Log;
2900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.view.KeyEvent;
3000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.view.MotionEvent;
31043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.view.VelocityTracker;
320280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.view.View;
33a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroyimport android.view.ViewConfiguration;
3400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.view.inputmethod.InputMethodManager;
3500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
36120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohenimport com.android.launcher.R;
37c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen
38c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohenimport java.util.ArrayList;
3931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
4031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
4100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Class for initiating a drag within a view or across multiple views.
4231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
4300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratopublic class DragController {
442e5c432a0aa7e83031575df73bed43a297e2eed3Joe Onorato    private static final String TAG = "Launcher.DragController";
452e5c432a0aa7e83031575df73bed43a297e2eed3Joe Onorato
4600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Indicates the drag is a move.  */
4700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public static int DRAG_ACTION_MOVE = 0;
4800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
4900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Indicates the drag is a copy.  */
5000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public static int DRAG_ACTION_COPY = 1;
5100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
52aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung    private static final int SCROLL_DELAY = 500;
53aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung    private static final int RESCROLL_DELAY = 750;
5461b0c69d3fe331d3de338322396d5de691d58613Winson Chung    private static final int VIBRATE_DURATION = 15;
5500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
5600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private static final boolean PROFILE_DRAWING_DURING_DRAG = false;
5700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
5800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private static final int SCROLL_OUTSIDE_ZONE = 0;
5900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private static final int SCROLL_WAITING_IN_ZONE = 1;
6000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
6154fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy    static final int SCROLL_NONE = -1;
621262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    static final int SCROLL_LEFT = 0;
631262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    static final int SCROLL_RIGHT = 1;
6400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
65043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private static final float MAX_FLING_DEGREES = 35f;
66043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
678dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    private Launcher mLauncher;
6800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private Handler mHandler;
698ef85c7a01376a98ce64d8fceb423a6f58e60d9dJeff Brown    private final Vibrator mVibrator;
7000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
7100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    // temporaries to avoid gc thrash
7200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private Rect mRectTemp = new Rect();
7300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private final int[] mCoordinatesTemp = new int[2];
7400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
7500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Whether or not we're dragging. */
7600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private boolean mDragging;
7700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
7800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** X coordinate of the down event. */
79e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    private int mMotionDownX;
8000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
8100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Y coordinate of the down event. */
82e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    private int mMotionDownY;
8300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
84658db74c24817892f1a379b16620744f38f60e40Joe Onorato    /** the area at the edge of the screen that makes the workspace go left
85658db74c24817892f1a379b16620744f38f60e40Joe Onorato     *   or right while you're dragging.
86658db74c24817892f1a379b16620744f38f60e40Joe Onorato     */
87658db74c24817892f1a379b16620744f38f60e40Joe Onorato    private int mScrollZone;
88658db74c24817892f1a379b16620744f38f60e40Joe Onorato
899932a9b1e66fed4b5f38ce50f13d56331bbdcd7eAdam Cohen    private DropTarget.DragObject mDragObject;
9000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
9100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Who can receive drop events */
9200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private ArrayList<DropTarget> mDropTargets = new ArrayList<DropTarget>();
934ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy    private ArrayList<DragListener> mListeners = new ArrayList<DragListener>();
94043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private DropTarget mFlingToDeleteDropTarget;
9500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
9600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** The window token used as the parent for the DragView. */
9700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private IBinder mWindowToken;
9800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
9900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** The view that will be scrolled when dragging to the left and right edges of the screen. */
10000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private View mScrollView;
10100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
102ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    private View mMoveTarget;
103ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
10400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DragScroller mDragScroller;
10500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private int mScrollState = SCROLL_OUTSIDE_ZONE;
10600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private ScrollRunnable mScrollRunnable = new ScrollRunnable();
10700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
10800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DropTarget mLastDropTarget;
10900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
11000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private InputMethodManager mInputMethodManager;
11100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
112a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy    private int mLastTouch[] = new int[2];
113318eee06ae69ac5ef8fddde984eb2f7601d2101dWinson Chung    private long mLastTouchUpTime = -1;
114a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy    private int mDistanceSinceScroll = 0;
115a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy
116273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung    private int mTmpPoint[] = new int[2];
117273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung    private Rect mDragLayerRect = new Rect();
118273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung
119043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    protected int mFlingToDeleteThresholdVelocity;
120043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private VelocityTracker mVelocityTracker;
121043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
12231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Interface to receive notifications when a drag starts or stops
12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
12531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    interface DragListener {
12631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
12731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        /**
12831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         * A drag has begun
12931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         *
13031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         * @param source An object representing where the drag originated
13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         * @param info The data associated with the object that is being dragged
13231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         * @param dragAction The drag action: either {@link DragController#DRAG_ACTION_MOVE}
13331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         *        or {@link DragController#DRAG_ACTION_COPY}
13431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         */
1355162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato        void onDragStart(DragSource source, Object info, int dragAction);
13631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
13731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        /**
138e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung         * The drag has ended
13931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         */
14031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        void onDragEnd();
14131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
14231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
14400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Used to create a new DragLayer from XML.
14500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *
14600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * @param context The application's context.
14731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
1488dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    public DragController(Launcher launcher) {
1496e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        Resources r = launcher.getResources();
1508dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mLauncher = launcher;
15100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mHandler = new Handler();
1526e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        mScrollZone = r.getDimensionPixelSize(R.dimen.scroll_zone);
153043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mVelocityTracker = VelocityTracker.obtain();
1546e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        mVibrator = (Vibrator) launcher.getSystemService(Context.VIBRATOR_SERVICE);
155043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
1566e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        float density = r.getDisplayMetrics().density;
1576e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        mFlingToDeleteThresholdVelocity =
1586e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung                (int) (r.getInteger(R.integer.config_flingToDeleteMinVelocity) * density);
15900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
16031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1611262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public boolean dragging() {
1621262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        return mDragging;
1631262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
1641262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
16531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
1665162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * Starts a drag.
167a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     *
16831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param v The view that is being dragged
169e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param bmp The bitmap that represents the view being dragged
170e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param source An object representing where the drag originated
171e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param dragInfo The data associated with the object that is being dragged
172e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
173e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     *        {@link #DRAG_ACTION_COPY}
174e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
175e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     *          Makes dragging feel more precise, e.g. you can clip out a transparent border
176e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
177e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    public void startDrag(View v, Bitmap bmp, DragSource source, Object dragInfo, int dragAction,
17805713af127d765cc28a8b2fd548a90347c90d6cbMichael Jurka            Point extraPadding, float initialDragViewScale) {
179e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        int[] loc = mCoordinatesTemp;
1808dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mLauncher.getDragLayer().getLocationInDragLayer(v, loc);
18105713af127d765cc28a8b2fd548a90347c90d6cbMichael Jurka        int viewExtraPaddingLeft = extraPadding != null ? extraPadding.x : 0;
18205713af127d765cc28a8b2fd548a90347c90d6cbMichael Jurka        int viewExtraPaddingTop = extraPadding != null ? extraPadding.y : 0;
18305713af127d765cc28a8b2fd548a90347c90d6cbMichael Jurka        int dragLayerX = loc[0] + v.getPaddingLeft() + viewExtraPaddingLeft +
18472d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung                (int) ((initialDragViewScale * bmp.getWidth() - bmp.getWidth()) / 2);
18505713af127d765cc28a8b2fd548a90347c90d6cbMichael Jurka        int dragLayerY = loc[1] + v.getPaddingTop() + viewExtraPaddingTop +
18672d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung                (int) ((initialDragViewScale * bmp.getHeight() - bmp.getHeight()) / 2);
187e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
18805713af127d765cc28a8b2fd548a90347c90d6cbMichael Jurka        startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, dragAction, null,
18905713af127d765cc28a8b2fd548a90347c90d6cbMichael Jurka                null, initialDragViewScale);
190e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
191e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        if (dragAction == DRAG_ACTION_MOVE) {
192e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung            v.setVisibility(View.GONE);
193e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        }
194e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    }
195e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
196e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
197e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * Starts a drag.
198e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     *
1995162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * @param b The bitmap to display as the drag image.  It will be re-scaled to the
2005162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     *          enlarged size.
2018dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen     * @param dragLayerX The x position in the DragLayer of the left-top of the bitmap.
2028dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen     * @param dragLayerY The y position in the DragLayer of the left-top of the bitmap.
2035162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * @param source An object representing where the drag originated
204ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy     * @param dragInfo The data associated with the object that is being dragged
2055162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
2065162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     *        {@link #DRAG_ACTION_COPY}
207a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
208a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     *          Makes dragging feel more precise, e.g. you can clip out a transparent border
209a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     */
2108dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    public void startDrag(Bitmap b, int dragLayerX, int dragLayerY,
21172d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung            DragSource source, Object dragInfo, int dragAction, Point dragOffset, Rect dragRegion,
21272d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung            float initialDragViewScale) {
21300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (PROFILE_DRAWING_DURING_DRAG) {
21400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            android.os.Debug.startMethodTracing("Launcher");
21500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
21600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
21700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        // Hide soft keyboard, if visible
21800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (mInputMethodManager == null) {
21900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            mInputMethodManager = (InputMethodManager)
2208dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                    mLauncher.getSystemService(Context.INPUT_METHOD_SERVICE);
22100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
22200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mInputMethodManager.hideSoftInputFromWindow(mWindowToken, 0);
22300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
2244ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy        for (DragListener listener : mListeners) {
2254ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy            listener.onDragStart(source, dragInfo, dragAction);
22600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
22700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
2288dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        final int registrationX = mMotionDownX - dragLayerX;
2298dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        final int registrationY = mMotionDownY - dragLayerY;
23000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
231a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
232a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
233e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen
23400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragging = true;
235cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen
2369932a9b1e66fed4b5f38ce50f13d56331bbdcd7eAdam Cohen        mDragObject = new DropTarget.DragObject();
2379932a9b1e66fed4b5f38ce50f13d56331bbdcd7eAdam Cohen
238bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        mDragObject.dragComplete = false;
2398dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);
2408dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);
241cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.dragSource = source;
242cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.dragInfo = dragInfo;
24300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
24400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mVibrator.vibrate(VIBRATE_DURATION);
24500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
2468dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX,
24772d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung                registrationY, 0, 0, b.getWidth(), b.getHeight(), initialDragViewScale);
248a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
249b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung        if (dragOffset != null) {
250b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung            dragView.setDragVisualizeOffset(new Point(dragOffset));
251b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung        }
252a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        if (dragRegion != null) {
253e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen            dragView.setDragRegion(new Rect(dragRegion));
254a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
255a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
2568dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        dragView.show(mMotionDownX, mMotionDownY);
2578dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        handleMoveEvent(mMotionDownX, mMotionDownY);
25800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
25900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
26000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
26100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Draw the view into a bitmap.
26200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
263120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    Bitmap getViewBitmap(View v) {
26400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.clearFocus();
26500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setPressed(false);
26600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
26700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        boolean willNotCache = v.willNotCacheDrawing();
26800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setWillNotCacheDrawing(false);
26900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
27000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        // Reset the drawing cache background color to fully transparent
27100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        // for the duration of this operation
27200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        int color = v.getDrawingCacheBackgroundColor();
27300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setDrawingCacheBackgroundColor(0);
274120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        float alpha = v.getAlpha();
275120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        v.setAlpha(1.0f);
27600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
27700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (color != 0) {
27800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            v.destroyDrawingCache();
27900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
28000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.buildDrawingCache();
28100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        Bitmap cacheBitmap = v.getDrawingCache();
2823f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler        if (cacheBitmap == null) {
2833f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler            Log.e(TAG, "failed getViewBitmap(" + v + ")", new RuntimeException());
2843f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler            return null;
2853f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler        }
28600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
28700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
28800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
28900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        // Restore the view
29000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.destroyDrawingCache();
291120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        v.setAlpha(alpha);
29200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setWillNotCacheDrawing(willNotCache);
29300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setDrawingCacheBackgroundColor(color);
29400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
29500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return bitmap;
29600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
29700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
29800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
29900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Call this from a drag source view like this:
30000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *
30100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * <pre>
30200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *  @Override
30300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *  public boolean dispatchKeyEvent(KeyEvent event) {
30400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *      return mDragController.dispatchKeyEvent(this, event)
30500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *              || super.dispatchKeyEvent(event);
30600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * </pre>
30700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
30800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public boolean dispatchKeyEvent(KeyEvent event) {
30900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return mDragging;
31000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
31100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
312304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung    public boolean isDragging() {
313304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung        return mDragging;
314304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung    }
315304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung
31624b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato    /**
31724b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato     * Stop dragging without dropping.
31824b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato     */
31924b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato    public void cancelDrag() {
320621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung        if (mDragging) {
321c07918d0053fc7d2a19d7b013565a5d2e7d4af51Winson Chung            if (mLastDropTarget != null) {
322c07918d0053fc7d2a19d7b013565a5d2e7d4af51Winson Chung                mLastDropTarget.onDragExit(mDragObject);
323c07918d0053fc7d2a19d7b013565a5d2e7d4af51Winson Chung            }
32441bb19d2775836e30ebf42f681b4617bc71600aaWinson Chung            mDragObject.deferDragViewCleanupPostAnimation = false;
32536cc09b07b19198f4ea886583cef462ade27192cAdam Cohen            mDragObject.cancelled = true;
326bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mDragObject.dragComplete = true;
327a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung            mDragObject.dragSource.onDropCompleted(null, mDragObject, false, false);
328621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung        }
32924b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato        endDrag();
33024b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato    }
33183892cc0768bd6d7f0827886e9e7a2eb3eed2b01Winson Chung    public void onAppsRemoved(ArrayList<ApplicationInfo> appInfos, Context context) {
332a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung        // Cancel the current drag if we are removing an app that we are dragging
333a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung        if (mDragObject != null) {
334a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung            Object rawDragInfo = mDragObject.dragInfo;
335a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung            if (rawDragInfo instanceof ShortcutInfo) {
336a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung                ShortcutInfo dragInfo = (ShortcutInfo) rawDragInfo;
33783892cc0768bd6d7f0827886e9e7a2eb3eed2b01Winson Chung                for (ApplicationInfo info : appInfos) {
3387bcadad93f97e79d95ae879fe165de2e2371f613Michael Jurka                    // Added null checks to prevent NPE we've seen in the wild
3397bcadad93f97e79d95ae879fe165de2e2371f613Michael Jurka                    if (dragInfo != null &&
340cd81073eac537e9f85eeee14588d513ea8a56e17Winson Chung                        dragInfo.intent != null) {
34183892cc0768bd6d7f0827886e9e7a2eb3eed2b01Winson Chung                        boolean isSameComponent =
34283892cc0768bd6d7f0827886e9e7a2eb3eed2b01Winson Chung                                dragInfo.intent.getComponent().equals(info.componentName);
34383892cc0768bd6d7f0827886e9e7a2eb3eed2b01Winson Chung                        if (isSameComponent) {
34411a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                            cancelDrag();
34511a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                            return;
34611a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                        }
347a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung                    }
348a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung                }
349a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung            }
350a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung        }
351a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung    }
35224b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato
35300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private void endDrag() {
35400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (mDragging) {
35500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            mDragging = false;
356aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung            clearScrollRunnable();
357043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            boolean isDeferred = false;
358cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            if (mDragObject.dragView != null) {
359043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                isDeferred = mDragObject.deferDragViewCleanupPostAnimation;
360043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                if (!isDeferred) {
3617bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                    mDragObject.dragView.remove();
3627bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                }
363cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                mDragObject.dragView = null;
36400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
365043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
366043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            // Only end the drag if we are not deferred
367043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            if (!isDeferred) {
368043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                for (DragListener listener : mListeners) {
369043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    listener.onDragEnd();
370043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                }
371043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            }
372043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
373043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
374043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        releaseVelocityTracker();
375043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
376043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
377043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    /**
378043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * This only gets called as a result of drag view cleanup being deferred in endDrag();
379043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     */
380043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    void onDeferredEndDrag(DragView dragView) {
381043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        dragView.remove();
382043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
383043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // If we skipped calling onDragEnd() before, do it now
384043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        for (DragListener listener : mListeners) {
385043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            listener.onDragEnd();
38600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
38700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
38800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
389a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung    void onDeferredEndFling(DropTarget.DragObject d) {
390a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        d.dragSource.onFlingToDeleteCompleted();
391a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung    }
392a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung
39300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
394273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung     * Clamps the position to the drag layer bounds.
395273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung     */
396273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung    private int[] getClampedDragLayerPos(float x, float y) {
397273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        mLauncher.getDragLayer().getLocalVisibleRect(mDragLayerRect);
398273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        mTmpPoint[0] = (int) Math.max(mDragLayerRect.left, Math.min(x, mDragLayerRect.right - 1));
399273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        mTmpPoint[1] = (int) Math.max(mDragLayerRect.top, Math.min(y, mDragLayerRect.bottom - 1));
400273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        return mTmpPoint;
401273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung    }
402273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung
403a2413751e3a698aef9c87411a639637883856939Winson Chung    long getLastGestureUpTime() {
404a2413751e3a698aef9c87411a639637883856939Winson Chung        if (mDragging) {
405a2413751e3a698aef9c87411a639637883856939Winson Chung            return System.currentTimeMillis();
406a2413751e3a698aef9c87411a639637883856939Winson Chung        } else {
407a2413751e3a698aef9c87411a639637883856939Winson Chung            return mLastTouchUpTime;
408a2413751e3a698aef9c87411a639637883856939Winson Chung        }
409a2413751e3a698aef9c87411a639637883856939Winson Chung    }
410a2413751e3a698aef9c87411a639637883856939Winson Chung
411a2413751e3a698aef9c87411a639637883856939Winson Chung    void resetLastGestureUpTime() {
412a2413751e3a698aef9c87411a639637883856939Winson Chung        mLastTouchUpTime = -1;
413a2413751e3a698aef9c87411a639637883856939Winson Chung    }
414a2413751e3a698aef9c87411a639637883856939Winson Chung
415273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung    /**
41600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Call this from a drag source view.
41700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
41800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public boolean onInterceptTouchEvent(MotionEvent ev) {
4193a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka        @SuppressWarnings("all") // suppress dead code warning
4203a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka        final boolean debug = false;
4213a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka        if (debug) {
422a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato            Log.d(Launcher.TAG, "DragController.onInterceptTouchEvent " + ev + " mDragging="
4239c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    + mDragging);
4249c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        }
42500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
426043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Update the velocity tracker
427043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        acquireVelocityTrackerAndAddMovement(ev);
428043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
429043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final int action = ev.getAction();
430273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
431273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        final int dragLayerX = dragLayerPos[0];
432273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        final int dragLayerY = dragLayerPos[1];
43300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
43400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        switch (action) {
43500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            case MotionEvent.ACTION_MOVE:
43600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                break;
43700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            case MotionEvent.ACTION_DOWN:
43800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                // Remember location of down touch
4398dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                mMotionDownX = dragLayerX;
4408dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                mMotionDownY = dragLayerY;
44100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mLastDropTarget = null;
44200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                break;
44300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            case MotionEvent.ACTION_UP:
444a2413751e3a698aef9c87411a639637883856939Winson Chung                mLastTouchUpTime = System.currentTimeMillis();
44500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDragging) {
446043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    PointF vec = isFlingingToDelete(mDragObject.dragSource);
447043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    if (vec != null) {
448043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                        dropOnFlingToDeleteTarget(dragLayerX, dragLayerY, vec);
449043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    } else {
450043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                        drop(dragLayerX, dragLayerY);
451043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    }
45200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
45300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                endDrag();
45400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                break;
455621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung            case MotionEvent.ACTION_CANCEL:
456621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung                cancelDrag();
457621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung                break;
45800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
45900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
46000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return mDragging;
46100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
46200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
46300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
464ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy     * Sets the view that should handle move events.
465ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy     */
466ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    void setMoveTarget(View view) {
467ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy        mMoveTarget = view;
468ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    }
469ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
470ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    public boolean dispatchUnhandledMove(View focused, int direction) {
471ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy        return mMoveTarget != null && mMoveTarget.dispatchUnhandledMove(focused, direction);
472ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    }
473ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
474aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung    private void clearScrollRunnable() {
475aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung        mHandler.removeCallbacks(mScrollRunnable);
476aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung        if (mScrollState == SCROLL_WAITING_IN_ZONE) {
477aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung            mScrollState = SCROLL_OUTSIDE_ZONE;
478aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung            mScrollRunnable.setDirection(SCROLL_RIGHT);
479aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung            mDragScroller.onExitScrollArea();
480360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            mLauncher.getDragLayer().onExitScrollArea();
481aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung        }
482aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung    }
483aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung
484de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy    private void handleMoveEvent(int x, int y) {
485cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.dragView.move(x, y);
486de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy
487de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        // Drop on someone?
488de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        final int[] coordinates = mCoordinatesTemp;
489de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        DropTarget dropTarget = findDropTarget(x, y, coordinates);
490cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.x = coordinates[0];
491cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.y = coordinates[1];
49225460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        checkTouchMove(dropTarget);
49325460a1d5cb473033408c9e76898bb77e785c66fWinson Chung
49425460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        // Check if we are hovering over the scroll areas
49525460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        mDistanceSinceScroll +=
49625460a1d5cb473033408c9e76898bb77e785c66fWinson Chung            Math.sqrt(Math.pow(mLastTouch[0] - x, 2) + Math.pow(mLastTouch[1] - y, 2));
49725460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        mLastTouch[0] = x;
49825460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        mLastTouch[1] = y;
49925460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        checkScrollState(x, y);
50025460a1d5cb473033408c9e76898bb77e785c66fWinson Chung    }
50125460a1d5cb473033408c9e76898bb77e785c66fWinson Chung
50225460a1d5cb473033408c9e76898bb77e785c66fWinson Chung    public void forceTouchMove() {
50325460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        int[] dummyCoordinates = mCoordinatesTemp;
50425460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        DropTarget dropTarget = findDropTarget(mLastTouch[0], mLastTouch[1], dummyCoordinates);
50525460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        checkTouchMove(dropTarget);
50625460a1d5cb473033408c9e76898bb77e785c66fWinson Chung    }
50725460a1d5cb473033408c9e76898bb77e785c66fWinson Chung
50825460a1d5cb473033408c9e76898bb77e785c66fWinson Chung    private void checkTouchMove(DropTarget dropTarget) {
509de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        if (dropTarget != null) {
510cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            DropTarget delegate = dropTarget.getDropTargetDelegate(mDragObject);
511de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            if (delegate != null) {
512de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                dropTarget = delegate;
513de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
514de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy
515de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            if (mLastDropTarget != dropTarget) {
516de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                if (mLastDropTarget != null) {
517cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                    mLastDropTarget.onDragExit(mDragObject);
518de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                }
519cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                dropTarget.onDragEnter(mDragObject);
520de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
521cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            dropTarget.onDragOver(mDragObject);
522de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        } else {
523de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            if (mLastDropTarget != null) {
524cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                mLastDropTarget.onDragExit(mDragObject);
525de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
526de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        }
527de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        mLastDropTarget = dropTarget;
52825460a1d5cb473033408c9e76898bb77e785c66fWinson Chung    }
529de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy
53025460a1d5cb473033408c9e76898bb77e785c66fWinson Chung    private void checkScrollState(int x, int y) {
5318dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        final int slop = ViewConfiguration.get(mLauncher).getScaledWindowTouchSlop();
532aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung        final int delay = mDistanceSinceScroll < slop ? RESCROLL_DELAY : SCROLL_DELAY;
533fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung        final DragLayer dragLayer = mLauncher.getDragLayer();
534fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung        final boolean isRtl = (dragLayer.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
535fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung        final int forwardDirection = isRtl ? SCROLL_RIGHT : SCROLL_LEFT;
536fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung        final int backwardsDirection = isRtl ? SCROLL_LEFT : SCROLL_RIGHT;
537a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy
5383f4e1423804d64a38cb69e4511d7b80783564827Winson Chung        if (x < mScrollZone) {
539aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung            if (mScrollState == SCROLL_OUTSIDE_ZONE) {
540de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                mScrollState = SCROLL_WAITING_IN_ZONE;
541fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung                if (mDragScroller.onEnterScrollArea(x, y, forwardDirection)) {
542fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung                    dragLayer.onEnterScrollArea(forwardDirection);
543fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung                    mScrollRunnable.setDirection(forwardDirection);
544aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung                    mHandler.postDelayed(mScrollRunnable, delay);
5453e0839e5f830ab7e64223ebe186d97729eda3e22Winson Chung                }
546de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
5473f4e1423804d64a38cb69e4511d7b80783564827Winson Chung        } else if (x > mScrollView.getWidth() - mScrollZone) {
548aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung            if (mScrollState == SCROLL_OUTSIDE_ZONE) {
549de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                mScrollState = SCROLL_WAITING_IN_ZONE;
550fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung                if (mDragScroller.onEnterScrollArea(x, y, backwardsDirection)) {
551fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung                    dragLayer.onEnterScrollArea(backwardsDirection);
552fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung                    mScrollRunnable.setDirection(backwardsDirection);
553aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung                    mHandler.postDelayed(mScrollRunnable, delay);
5543e0839e5f830ab7e64223ebe186d97729eda3e22Winson Chung                }
555de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
556de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        } else {
557aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung            clearScrollRunnable();
558de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        }
559de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy    }
560de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy
561ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    /**
56200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Call this from a drag source view.
56300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
56400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public boolean onTouchEvent(MotionEvent ev) {
56500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (!mDragging) {
56600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            return false;
56700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
56800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
569043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Update the velocity tracker
570043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        acquireVelocityTrackerAndAddMovement(ev);
571043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
57200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final int action = ev.getAction();
573273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
574273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        final int dragLayerX = dragLayerPos[0];
575273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        final int dragLayerY = dragLayerPos[1];
57600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
57700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        switch (action) {
57800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        case MotionEvent.ACTION_DOWN:
57900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            // Remember where the motion event started
5808dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            mMotionDownX = dragLayerX;
5818dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            mMotionDownY = dragLayerY;
58200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
5838dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            if ((dragLayerX < mScrollZone) || (dragLayerX > mScrollView.getWidth() - mScrollZone)) {
58400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mScrollState = SCROLL_WAITING_IN_ZONE;
58500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
58600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            } else {
58700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mScrollState = SCROLL_OUTSIDE_ZONE;
58800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
58900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            break;
59000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        case MotionEvent.ACTION_MOVE:
5918dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            handleMoveEvent(dragLayerX, dragLayerY);
59200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            break;
59300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        case MotionEvent.ACTION_UP:
594b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy            // Ensure that we've processed a move event at the current pointer location.
5958dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            handleMoveEvent(dragLayerX, dragLayerY);
5963bc21c35fa167ac233e19df0c9a01b0a07173ed8Winson Chung            mHandler.removeCallbacks(mScrollRunnable);
597043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
59800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            if (mDragging) {
599043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                PointF vec = isFlingingToDelete(mDragObject.dragSource);
600043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                if (vec != null) {
601043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    dropOnFlingToDeleteTarget(dragLayerX, dragLayerY, vec);
602043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                } else {
603043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    drop(dragLayerX, dragLayerY);
604043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                }
60500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
60600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            endDrag();
60700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            break;
60800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        case MotionEvent.ACTION_CANCEL:
6093bc21c35fa167ac233e19df0c9a01b0a07173ed8Winson Chung            mHandler.removeCallbacks(mScrollRunnable);
61024b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato            cancelDrag();
611621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung            break;
61200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
61300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
61400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return true;
61500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
61600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
617043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    /**
618043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * Determines whether the user flung the current item to delete it.
619043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     *
620043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * @return the vector at which the item was flung, or null if no fling was detected.
621043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     */
622043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private PointF isFlingingToDelete(DragSource source) {
623043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mFlingToDeleteDropTarget == null) return null;
624043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (!source.supportsFlingToDelete()) return null;
625043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
626043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        ViewConfiguration config = ViewConfiguration.get(mLauncher);
627043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mVelocityTracker.computeCurrentVelocity(1000, config.getScaledMaximumFlingVelocity());
628043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
629043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mVelocityTracker.getYVelocity() < mFlingToDeleteThresholdVelocity) {
630043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            // Do a quick dot product test to ensure that we are flinging upwards
631043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            PointF vel = new PointF(mVelocityTracker.getXVelocity(),
632043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    mVelocityTracker.getYVelocity());
633043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            PointF upVec = new PointF(0f, -1f);
634043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            float theta = (float) Math.acos(((vel.x * upVec.x) + (vel.y * upVec.y)) /
635043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    (vel.length() * upVec.length()));
636043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            if (theta <= Math.toRadians(MAX_FLING_DEGREES)) {
637043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                return vel;
638043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            }
639043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
640043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        return null;
641043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
642043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
643043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private void dropOnFlingToDeleteTarget(float x, float y, PointF vel) {
644043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final int[] coordinates = mCoordinatesTemp;
645043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
646043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDragObject.x = coordinates[0];
647043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDragObject.y = coordinates[1];
648043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
649043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Clean up dragging on the target if it's not the current fling delete target otherwise,
650043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // start dragging to it.
651043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mLastDropTarget != null && mFlingToDeleteDropTarget != mLastDropTarget) {
652043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mLastDropTarget.onDragExit(mDragObject);
653043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
654043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
655043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Drop onto the fling-to-delete target
656043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        boolean accepted = false;
657043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mFlingToDeleteDropTarget.onDragEnter(mDragObject);
658232decb008661d82ed2ca6d5f3080ee5a50d3be1Winson Chung        // We must set dragComplete to true _only_ after we "enter" the fling-to-delete target for
659232decb008661d82ed2ca6d5f3080ee5a50d3be1Winson Chung        // "drop"
660232decb008661d82ed2ca6d5f3080ee5a50d3be1Winson Chung        mDragObject.dragComplete = true;
661043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mFlingToDeleteDropTarget.onDragExit(mDragObject);
662043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mFlingToDeleteDropTarget.acceptDrop(mDragObject)) {
663043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mFlingToDeleteDropTarget.onFlingToDelete(mDragObject, mDragObject.x, mDragObject.y,
664043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    vel);
665043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            accepted = true;
666043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
667a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        mDragObject.dragSource.onDropCompleted((View) mFlingToDeleteDropTarget, mDragObject, true,
668043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                accepted);
669043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
670043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
671b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy    private void drop(float x, float y) {
67200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final int[] coordinates = mCoordinatesTemp;
673b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy        final DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);
67400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
675cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.x = coordinates[0];
676cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.y = coordinates[1];
677b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy        boolean accepted = false;
67800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (dropTarget != null) {
679bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mDragObject.dragComplete = true;
680cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            dropTarget.onDragExit(mDragObject);
681cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            if (dropTarget.acceptDrop(mDragObject)) {
682cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                dropTarget.onDrop(mDragObject);
683b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy                accepted = true;
68400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
68500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
686a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        mDragObject.dragSource.onDropCompleted((View) dropTarget, mDragObject, false, accepted);
68700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
68800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
68900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {
69000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final Rect r = mRectTemp;
69100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
69200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final ArrayList<DropTarget> dropTargets = mDropTargets;
69300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final int count = dropTargets.size();
69400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        for (int i=count-1; i>=0; i--) {
695440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DropTarget target = dropTargets.get(i);
6960280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            if (!target.isDropEnabled())
6970280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                continue;
6980280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
69900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            target.getHitRect(r);
700440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
7018dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            // Convert the hit rect to DragLayer coordinates
7028dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            target.getLocationInDragLayer(dropCoordinates);
70300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            r.offset(dropCoordinates[0] - target.getLeft(), dropCoordinates[1] - target.getTop());
704440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
705cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            mDragObject.x = x;
706cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            mDragObject.y = y;
70700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            if (r.contains(x, y)) {
708cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                DropTarget delegate = target.getDropTargetDelegate(mDragObject);
709440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                if (delegate != null) {
710440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                    target = delegate;
7118dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                    target.getLocationInDragLayer(dropCoordinates);
712440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                }
713440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
714440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                // Make dropCoordinates relative to the DropTarget
71500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                dropCoordinates[0] = x - dropCoordinates[0];
71600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                dropCoordinates[1] = y - dropCoordinates[1];
717440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
71800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                return target;
71900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
72000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
72100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return null;
72200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
72300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
72400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setDragScoller(DragScroller scroller) {
72500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragScroller = scroller;
72600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
72700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
72800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setWindowToken(IBinder token) {
72900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mWindowToken = token;
73000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
73100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
73231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
73331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Sets the drag listner which will be notified when a drag starts or ends.
73431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
7354ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy    public void addDragListener(DragListener l) {
7364ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy        mListeners.add(l);
73700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
73800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
73931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
74031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Remove a previously installed drag listener.
74131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
74200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void removeDragListener(DragListener l) {
7434ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy        mListeners.remove(l);
74400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
74500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
74600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
74700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Add a DropTarget to the list of potential places to receive drop events.
74800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
74900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void addDropTarget(DropTarget target) {
75000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDropTargets.add(target);
75100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
75200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
75300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
75400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Don't send drop events to <em>target</em> any more.
75500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
75600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void removeDropTarget(DropTarget target) {
75700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDropTargets.remove(target);
75800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
75900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
76000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
761043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * Sets the current fling-to-delete drop target.
762043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     */
763043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    public void setFlingToDeleteDropTarget(DropTarget target) {
764043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mFlingToDeleteDropTarget = target;
765043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
766043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
767043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) {
768043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mVelocityTracker == null) {
769043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mVelocityTracker = VelocityTracker.obtain();
770043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
771043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mVelocityTracker.addMovement(ev);
772043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
773043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
774043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private void releaseVelocityTracker() {
775043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mVelocityTracker != null) {
776043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mVelocityTracker.recycle();
777043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mVelocityTracker = null;
778043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
779043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
780043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
781043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    /**
78200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Set which view scrolls for touch events near the edge of the screen.
78300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
78400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setScrollView(View v) {
78500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mScrollView = v;
78600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
78700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
7885f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy    DragView getDragView() {
789cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        return mDragObject.dragView;
7905f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy    }
7915f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy
79200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private class ScrollRunnable implements Runnable {
79300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        private int mDirection;
79400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
79500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        ScrollRunnable() {
79600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
79700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
79800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        public void run() {
79900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            if (mDragScroller != null) {
80000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDirection == SCROLL_LEFT) {
80100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragScroller.scrollLeft();
80200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                } else {
80300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragScroller.scrollRight();
80400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
80500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mScrollState = SCROLL_OUTSIDE_ZONE;
806a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy                mDistanceSinceScroll = 0;
807a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy                mDragScroller.onExitScrollArea();
808360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung                mLauncher.getDragLayer().onExitScrollArea();
809aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung
810aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung                if (isDragging()) {
81125460a1d5cb473033408c9e76898bb77e785c66fWinson Chung                    // Check the scroll again so that we can requeue the scroller if necessary
81225460a1d5cb473033408c9e76898bb77e785c66fWinson Chung                    checkScrollState(mLastTouch[0], mLastTouch[1]);
813aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung                }
81400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
81500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
81600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
81700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        void setDirection(int direction) {
81800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            mDirection = direction;
81900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
82000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
82131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
822