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
17fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevpackage com.android.launcher3.dragndrop;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.Animator;
20716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.AnimatorListenerAdapter;
21716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.TimeInterpolator;
22716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.ValueAnimator;
23716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.ValueAnimator.AnimatorUpdateListener;
2431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
25716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.content.res.Resources;
26360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chungimport android.graphics.Canvas;
270fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyalimport android.graphics.Color;
286788269814a678af976dfc7d6135993e172ce586Adam Cohenimport android.graphics.Rect;
2995cdb3a0211650e76adb451588ce89fd585b178fTony Wickhamimport android.graphics.Region;
30ff4f201fadb131e7c367f64296e3a08090946adaMario Bertschlerimport android.support.v4.graphics.ColorUtils;
3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
3226279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.KeyEvent;
3308ca40f97670ad56ea01a81a439e89a484f9fdb5Sunny Goyalimport android.view.LayoutInflater;
3426279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.MotionEvent;
3526279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.View;
3626279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.ViewGroup;
373371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityEvent;
383371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityManager;
39716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.view.animation.DecelerateInterpolator;
403e8f811f31a2275e778244427271f77f4116c08bAdam Cohenimport android.view.animation.Interpolator;
4131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.widget.FrameLayout;
42ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohenimport android.widget.TextView;
4331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
44740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyalimport com.android.launcher3.AbstractFloatingView;
45fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.AppWidgetResizeFrame;
46fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.CellLayout;
471bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickhamimport com.android.launcher3.DropTargetBar;
48740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyalimport com.android.launcher3.ExtendedEditText;
49fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.InsettableFrameLayout;
50fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.Launcher;
51fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.LauncherAppWidgetHostView;
52dadb304b4682998c43b9c07bef45b9a9380f3287Tony Wickhamimport com.android.launcher3.PinchToOverviewListener;
53f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.R;
54fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.ShortcutAndWidgetContainer;
55fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.Utilities;
56645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Songimport com.android.launcher3.allapps.AllAppsTransitionController;
579c43182ff1d095b1bbaacedefe6e0f4c2deb17e3Tony Wickhamimport com.android.launcher3.config.FeatureFlags;
58ff4f201fadb131e7c367f64296e3a08090946adaMario Bertschlerimport com.android.launcher3.dynamicui.WallpaperColorInfo;
59261194387beebaa7927ec4e310274218b651494dSunny Goyalimport com.android.launcher3.folder.Folder;
60261194387beebaa7927ec4e310274218b651494dSunny Goyalimport com.android.launcher3.folder.FolderIcon;
613333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyalimport com.android.launcher3.keyboard.ViewGroupFocusHelper;
62c6cf493b07fc7234c2a0a164318fd9aeb02e48f3Jon Mirandaimport com.android.launcher3.logging.LoggerUtils;
63a69369450281376cb207be554199bb4895843eb2Mario Bertschlerimport com.android.launcher3.util.Themes;
64091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
65645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Songimport com.android.launcher3.util.TouchController;
66343a77e609382bcb9b1d69ea235a9e6d779b719eTony Wickhamimport com.android.launcher3.widget.WidgetsBottomSheet;
67bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
681d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohenimport java.util.ArrayList;
696788269814a678af976dfc7d6135993e172ce586Adam Cohen
7031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
710e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka * A ViewGroup that coordinates dragging across its descendants
7231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
73a6d0492e5f0dd4e1b43d4034a770241dc65f8f8cAdam Cohenpublic class DragLayer extends InsettableFrameLayout {
740fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal
75b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    public static final int ANIMATION_END_DISAPPEAR = 0;
76b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
77b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal
78b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    private final int[] mTmpXY = new int[2];
79b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal
80091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk DragController mDragController;
8131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
82716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private Launcher mLauncher;
83716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
846788269814a678af976dfc7d6135993e172ce586Adam Cohen    // Variables relating to resizing widgets
857066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal    private final boolean mIsRtl;
866788269814a678af976dfc7d6135993e172ce586Adam Cohen    private AppWidgetResizeFrame mCurrentResizeFrame;
87716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
88716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    // Variables relating to animation of views after drop
89716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private ValueAnimator mDropAnim = null;
90b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    private final TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
91091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk DragView mDropView = null;
92091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk int mAnchorViewInitialScrollX = 0;
93091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk View mAnchorView = null;
948dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen
953371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean mHoverPointClosesFolder = false;
96b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    private final Rect mHitRect = new Rect();
9795cdb3a0211650e76adb451588ce89fd585b178fTony Wickham    private final Rect mHighlightRect = new Rect();
986788269814a678af976dfc7d6135993e172ce586Adam Cohen
99b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    private TouchCompleteListener mTouchCompleteListener;
100b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen
101432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    private int mTopViewIndex;
1022d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen    private int mChildCountOnLastUpdate = -1;
10355bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi
1046c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    // Darkening scrim
1056c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    private float mBackgroundAlpha = 0;
1066c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen
1070f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    // Related to adjacent page hints
1080f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    private final Rect mScrollChildPosition = new Rect();
1093333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal    private final ViewGroupFocusHelper mFocusIndicatorHelper;
110ff4f201fadb131e7c367f64296e3a08090946adaMario Bertschler    private final WallpaperColorInfo mWallpaperColorInfo;
1113333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal
112dadb304b4682998c43b9c07bef45b9a9380f3287Tony Wickham    // Related to pinch-to-go-to-overview gesture.
1139c43182ff1d095b1bbaacedefe6e0f4c2deb17e3Tony Wickham    private PinchToOverviewListener mPinchListener = null;
114645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
115645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    // Handles all apps pull up interaction
116645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    private AllAppsTransitionController mAllAppsController;
117645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
118645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    private TouchController mActiveController;
11931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
12031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to create a new DragLayer from XML.
12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
12231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1230e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
12531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public DragLayer(Context context, AttributeSet attrs) {
12631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs);
127be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung
128be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        // Disable multitouch across the workspace/all apps/customize tray
129be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        setMotionEventSplittingEnabled(false);
13021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        setChildrenDrawingOrderEnabled(true);
131360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
132f5440cbd6c0525769d24b890e16313a728831e04Sunny Goyal        mIsRtl = Utilities.isRtl(getResources());
1333333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal        mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
134ff4f201fadb131e7c367f64296e3a08090946adaMario Bertschler        mWallpaperColorInfo = WallpaperColorInfo.getInstance(getContext());
13531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
13631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
137645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    public void setup(Launcher launcher, DragController dragController,
138645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            AllAppsTransitionController allAppsTransitionController) {
1394c98d9235d164680186180974719f551cf935d08Winson Chung        mLauncher = launcher;
140645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        mDragController = dragController;
141645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        mAllAppsController = allAppsTransitionController;
142dadb304b4682998c43b9c07bef45b9a9380f3287Tony Wickham
143e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham        boolean isAccessibilityEnabled = ((AccessibilityManager) mLauncher.getSystemService(
144e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham                Context.ACCESSIBILITY_SERVICE)).isEnabled();
145e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham        onAccessibilityStateChanged(isAccessibilityEnabled);
14631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
14776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
1483333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal    public ViewGroupFocusHelper getFocusIndicatorHelper() {
1493333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal        return mFocusIndicatorHelper;
1503333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal    }
1513333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal
15231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
15331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean dispatchKeyEvent(KeyEvent event) {
15400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
15531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
15631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
157e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham    public void onAccessibilityStateChanged(boolean isAccessibilityEnabled) {
158e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham        mPinchListener = FeatureFlags.LAUNCHER3_DISABLE_PINCH_TO_OVERVIEW || isAccessibilityEnabled
159e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham                ? null : new PinchToOverviewListener(mLauncher);
160e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham    }
161e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham
1627744169812e0d35531e9de258785af1f2ec9bed3Hyunyoung Song    public boolean isEventOverPageIndicator(MotionEvent ev) {
163740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        return isEventOverView(mLauncher.getWorkspace().getPageIndicator(), ev);
1647744169812e0d35531e9de258785af1f2ec9bed3Hyunyoung Song    }
1657744169812e0d35531e9de258785af1f2ec9bed3Hyunyoung Song
166a9a8a4221709cc3fda48fd80d4213d25183b8bf7Hyunyoung Song    public boolean isEventOverHotseat(MotionEvent ev) {
1671bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        return isEventOverView(mLauncher.getHotseat(), ev);
168a9a8a4221709cc3fda48fd80d4213d25183b8bf7Hyunyoung Song    }
169a9a8a4221709cc3fda48fd80d4213d25183b8bf7Hyunyoung Song
1703371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean isEventOverFolder(Folder folder, MotionEvent ev) {
1711bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        return isEventOverView(folder, ev);
1723371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
1733371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
174ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    private boolean isEventOverDropTargetBar(MotionEvent ev) {
1751bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        return isEventOverView(mLauncher.getDropTargetBar(), ev);
1761bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    }
1771bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
17858a9c4b7d2aa3772f56fea32f82cf29d410dc499Hyunyoung Song    public boolean isEventOverView(View view, MotionEvent ev) {
1791bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        getDescendantRectRelativeToSelf(view, mHitRect);
18047328fd53f43fd0c2ed14ad925dd04483f9229a0Sunny Goyal        return mHitRect.contains((int) ev.getX(), (int) ev.getY());
181ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    }
182ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal
18376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
184740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mLauncher);
185740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        if (topView != null && intercept) {
186740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal            ExtendedEditText textView = topView.getActiveTextView();
187740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal            if (textView != null) {
188740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal                if (!isEventOverView(textView, ev)) {
189740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal                    textView.dispatchBackKey();
190740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal                    return true;
191740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal                }
192740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal            } else if (!isEventOverView(topView, ev)) {
1932f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                if (isInAccessibleDrag()) {
1942f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                    // Do not close the container if in drag and drop.
1952f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                    if (!isEventOverDropTargetBar(ev)) {
1962f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                        return true;
1972f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                    }
1982f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                } else {
199c6cf493b07fc7234c2a0a164318fd9aeb02e48f3Jon Miranda                    mLauncher.getUserEventDispatcher().logActionTapOutside(
200c6cf493b07fc7234c2a0a164318fd9aeb02e48f3Jon Miranda                            LoggerUtils.newContainerTarget(topView.getLogContainerType()));
201740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal                    topView.close(true);
202740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal
2032f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                    // We let touches on the original icon go through so that users can launch
2042f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                    // the app with one tap if they don't find a shortcut they want.
205740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal                    View extendedTouch = topView.getExtendedTouchView();
206740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal                    return extendedTouch == null || !isEventOverView(extendedTouch, ev);
207ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                }
20876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            }
2092801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
2106788269814a678af976dfc7d6135993e172ce586Adam Cohen        return false;
2116788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
2126788269814a678af976dfc7d6135993e172ce586Adam Cohen
21331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
21431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onInterceptTouchEvent(MotionEvent ev) {
215b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        int action = ev.getAction();
216b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen
217b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        if (action == MotionEvent.ACTION_DOWN) {
218c001cf562017d08cd48b67de8f377ca08881e70eHyunyoung Song            // Cancel discovery bounce animation when a user start interacting on anywhere on
219c001cf562017d08cd48b67de8f377ca08881e70eHyunyoung Song            // dray layer even if mAllAppsController is NOT the active controller.
220c001cf562017d08cd48b67de8f377ca08881e70eHyunyoung Song            // TODO: handle other input other than touch
221c001cf562017d08cd48b67de8f377ca08881e70eHyunyoung Song            mAllAppsController.cancelDiscoveryAnimation();
22276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            if (handleTouchDown(ev, true)) {
2236788269814a678af976dfc7d6135993e172ce586Adam Cohen                return true;
224d1837cc69eb222371afdd30890f7215d117510f2Patrick Dubroy            }
225b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
226b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            if (mTouchCompleteListener != null) {
227b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen                mTouchCompleteListener.onTouchComplete();
228b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            }
229b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            mTouchCompleteListener = null;
2301b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen        }
23198cbd62e1f6d57ccef1758fb82dd245f7354fb73Tony Wickham        mActiveController = null;
23298cbd62e1f6d57ccef1758fb82dd245f7354fb73Tony Wickham
2336ad72f02fd233f2294222477102e83d721100493Sunny Goyal        if (mCurrentResizeFrame != null
2346ad72f02fd233f2294222477102e83d721100493Sunny Goyal                && mCurrentResizeFrame.onControllerInterceptTouchEvent(ev)) {
2356ad72f02fd233f2294222477102e83d721100493Sunny Goyal            mActiveController = mCurrentResizeFrame;
2366ad72f02fd233f2294222477102e83d721100493Sunny Goyal            return true;
2376ad72f02fd233f2294222477102e83d721100493Sunny Goyal        } else {
2386ad72f02fd233f2294222477102e83d721100493Sunny Goyal            clearResizeFrame();
2396ad72f02fd233f2294222477102e83d721100493Sunny Goyal        }
2406ad72f02fd233f2294222477102e83d721100493Sunny Goyal
2416ad72f02fd233f2294222477102e83d721100493Sunny Goyal        if (mDragController.onControllerInterceptTouchEvent(ev)) {
242645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            mActiveController = mDragController;
243645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            return true;
244645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
2451bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
246d725f644b70239332a4440173e6411e9ffb169a0Hyunyoung Song        if (mAllAppsController.onControllerInterceptTouchEvent(ev)) {
247645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            mActiveController = mAllAppsController;
248645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            return true;
24950e5165b78c75ccb022f0954699f49c579547115Tony Wickham        }
25050e5165b78c75ccb022f0954699f49c579547115Tony Wickham
251343a77e609382bcb9b1d69ea235a9e6d779b719eTony Wickham        WidgetsBottomSheet widgetsBottomSheet = WidgetsBottomSheet.getOpen(mLauncher);
252343a77e609382bcb9b1d69ea235a9e6d779b719eTony Wickham        if (widgetsBottomSheet != null && widgetsBottomSheet.onControllerInterceptTouchEvent(ev)) {
253343a77e609382bcb9b1d69ea235a9e6d779b719eTony Wickham            mActiveController = widgetsBottomSheet;
25450e5165b78c75ccb022f0954699f49c579547115Tony Wickham            return true;
255645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
256645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
2576ad72f02fd233f2294222477102e83d721100493Sunny Goyal        if (mPinchListener != null && mPinchListener.onControllerInterceptTouchEvent(ev)) {
258c5b31965d9bcb4c9899e2d1c45b5c95c70bac9f2Tony Wickham            // Stop listening for scrolling etc. (onTouchEvent() handles the rest of the pinch.)
259645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            mActiveController = mPinchListener;
260c5b31965d9bcb4c9899e2d1c45b5c95c70bac9f2Tony Wickham            return true;
261dadb304b4682998c43b9c07bef45b9a9380f3287Tony Wickham        }
262645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        return false;
26331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
26431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
26531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
2663371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    public boolean onInterceptHoverEvent(MotionEvent ev) {
267023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka        if (mLauncher == null || mLauncher.getWorkspace() == null) {
268023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka            return false;
269023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka        }
270740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        Folder currentFolder = Folder.getOpen(mLauncher);
2713371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (currentFolder == null) {
2723371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return false;
2733371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        } else {
2748b805b17158886035b38261eb611d8641701ae43Michael Jurka                AccessibilityManager accessibilityManager = (AccessibilityManager)
2758b805b17158886035b38261eb611d8641701ae43Michael Jurka                        getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
2768b805b17158886035b38261eb611d8641701ae43Michael Jurka            if (accessibilityManager.isTouchExplorationEnabled()) {
2773371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                final int action = ev.getAction();
278ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                boolean isOverFolderOrSearchBar;
2793371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                switch (action) {
2803371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    case MotionEvent.ACTION_HOVER_ENTER:
281ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        isOverFolderOrSearchBar = isEventOverFolder(currentFolder, ev) ||
282ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                            (isInAccessibleDrag() && isEventOverDropTargetBar(ev));
283ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        if (!isOverFolderOrSearchBar) {
2843371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
2853371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = true;
2863371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
2873371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        }
288693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu                        mHoverPointClosesFolder = false;
289693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu                        break;
2903371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    case MotionEvent.ACTION_HOVER_MOVE:
291ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        isOverFolderOrSearchBar = isEventOverFolder(currentFolder, ev) ||
292ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                            (isInAccessibleDrag() && isEventOverDropTargetBar(ev));
293ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        if (!isOverFolderOrSearchBar && !mHoverPointClosesFolder) {
2943371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
2953371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = true;
2963371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
297ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        } else if (!isOverFolderOrSearchBar) {
2983371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
2993371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        }
300693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu                        mHoverPointClosesFolder = false;
3013371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                }
3023371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            }
3033371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
3043371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
3053371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
3063371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
3073371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private void sendTapOutsideFolderAccessibilityEvent(boolean isEditingName) {
30852851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        int stringId = isEditingName ? R.string.folder_tap_to_rename : R.string.folder_tap_to_close;
30952851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        Utilities.sendCustomAccessibilityEvent(
31052851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal                this, AccessibilityEvent.TYPE_VIEW_FOCUSED, getContext().getString(stringId));
31183ca480941b3dd635b62347008fc8d7859d82002Winson Chung    }
31283ca480941b3dd635b62347008fc8d7859d82002Winson Chung
313ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    private boolean isInAccessibleDrag() {
314ae50284e0a838139c67caf0064a0977c871497faSunny Goyal        return mLauncher.getAccessibilityDelegate().isInAccessibleDrag();
315ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    }
316ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal
31783ca480941b3dd635b62347008fc8d7859d82002Winson Chung    @Override
31883ca480941b3dd635b62347008fc8d7859d82002Winson Chung    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
3197d552c8b18cfad9f32fb5028c53960a9f19dc0a8Sunny Goyal        // Shortcuts can appear above folder
320740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        View topView = AbstractFloatingView.getTopOpenView(mLauncher);
3217d552c8b18cfad9f32fb5028c53960a9f19dc0a8Sunny Goyal        if (topView != null) {
32252851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            if (child == topView) {
32352851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal                return super.onRequestSendAccessibilityEvent(child, event);
32452851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            }
32552851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            if (isInAccessibleDrag() && child instanceof DropTargetBar) {
32652851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal                return super.onRequestSendAccessibilityEvent(child, event);
32752851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            }
32852851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            // Skip propagating onRequestSendAccessibilityEvent for all other children
32952851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            // which are not topView
33052851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            return false;
33183ca480941b3dd635b62347008fc8d7859d82002Winson Chung        }
33283ca480941b3dd635b62347008fc8d7859d82002Winson Chung        return super.onRequestSendAccessibilityEvent(child, event);
33383ca480941b3dd635b62347008fc8d7859d82002Winson Chung    }
33483ca480941b3dd635b62347008fc8d7859d82002Winson Chung
33583ca480941b3dd635b62347008fc8d7859d82002Winson Chung    @Override
33683ca480941b3dd635b62347008fc8d7859d82002Winson Chung    public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
337740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        View topView = AbstractFloatingView.getTopOpenView(mLauncher);
33852851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        if (topView != null) {
33952851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            // Only add the top view as a child for accessibility when it is open
34052851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            childrenForAccessibility.add(topView);
341ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal
342ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal            if (isInAccessibleDrag()) {
34347328fd53f43fd0c2ed14ad925dd04483f9229a0Sunny Goyal                childrenForAccessibility.add(mLauncher.getDropTargetBar());
344ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal            }
34583ca480941b3dd635b62347008fc8d7859d82002Winson Chung        } else {
34683ca480941b3dd635b62347008fc8d7859d82002Winson Chung            super.addChildrenForAccessibility(childrenForAccessibility);
34783ca480941b3dd635b62347008fc8d7859d82002Winson Chung        }
3483371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
3493371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
3503371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    @Override
3513371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    public boolean onHoverEvent(MotionEvent ev) {
3523371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        // If we've received this, we've already done the necessary handling
3533371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        // in onInterceptHoverEvent. Return true to consume the event.
3543371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
3553371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
3563371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
3573371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    @Override
35831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
3596788269814a678af976dfc7d6135993e172ce586Adam Cohen        int action = ev.getAction();
3606788269814a678af976dfc7d6135993e172ce586Adam Cohen
361b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        if (action == MotionEvent.ACTION_DOWN) {
362b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            if (handleTouchDown(ev, false)) {
363b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen                return true;
364b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            }
365b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
366b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            if (mTouchCompleteListener != null) {
367b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen                mTouchCompleteListener.onTouchComplete();
3686788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
369b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            mTouchCompleteListener = null;
3706788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3716788269814a678af976dfc7d6135993e172ce586Adam Cohen
372645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (mActiveController != null) {
3736ad72f02fd233f2294222477102e83d721100493Sunny Goyal            return mActiveController.onControllerTouchEvent(ev);
374645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
375645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        return false;
37691a9c9636f10f1e12cd1f660b2e330634fbdc7dcRomain Guy    }
377ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
37835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    /**
37935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * Determine the rect of the descendant in this DragLayer's coordinates
38035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     *
38135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param descendant The descendant whose coordinates we want to find.
38235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param r The rect into which to place the results.
38335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @return The factor by which this descendant is scaled relative to this DragLayer.
38435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     */
385ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen    public float getDescendantRectRelativeToSelf(View descendant, Rect r) {
386716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mTmpXY[0] = 0;
387716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mTmpXY[1] = 0;
388ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY);
3897d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
3908dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        r.set(mTmpXY[0], mTmpXY[1],
3917d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                (int) (mTmpXY[0] + scale * descendant.getMeasuredWidth()),
3927d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                (int) (mTmpXY[1] + scale * descendant.getMeasuredHeight()));
393ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        return scale;
394716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
39576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
396307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen    public float getLocationInDragLayer(View child, int[] loc) {
39735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        loc[0] = 0;
39835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        loc[1] = 0;
399307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        return getDescendantCoordRelativeToSelf(child, loc);
40035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    }
40135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen
4027d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
4037d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        return getDescendantCoordRelativeToSelf(descendant, coord, false);
4047d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    }
4057d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
40635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    /**
40735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * Given a coordinate relative to the descendant, find the coordinate in this DragLayer's
40835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * coordinates.
40935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     *
41035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param descendant The descendant to which the passed coordinate is relative.
41135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param coord The coordinate that we want mapped.
4127d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     * @param includeRootScroll Whether or not to account for the scroll of the root descendant:
4137d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     *          sometimes this is relevant as in a child's coordinates within the root descendant.
414307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     * @return The factor by which this descendant is scaled relative to this DragLayer. Caution
415307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     *         this scale factor is assumed to be equal in X and Y, and so if at any point this
416307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     *         assumption fails, we will need to return a pair of scale factors.
41735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     */
4187d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    public float getDescendantCoordRelativeToSelf(View descendant, int[] coord,
4197d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            boolean includeRootScroll) {
420e8b5d20d94cb03878137a7fdf65d7a88270b73f8Sunny Goyal        return Utilities.getDescendantCoordRelativeToAncestor(descendant, this,
421c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung                coord, includeRootScroll);
422c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung    }
423c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung
4247d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    /**
4257d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     * Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}.
4267d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     */
4275e0e94f0b2ae79770dd07b66441fda6e063e64eaSunny Goyal    public void mapCoordInSelfToDescendant(View descendant, int[] coord) {
4285e0e94f0b2ae79770dd07b66441fda6e063e64eaSunny Goyal        Utilities.mapCoordInSelfToDescendant(descendant, this, coord);
42976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
43076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
4313e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    public void getViewRectRelativeToSelf(View v, Rect r) {
4323e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int[] loc = new int[2];
4338dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        getLocationInWindow(loc);
4343e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int x = loc[0];
4353e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int y = loc[1];
436716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
4378dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        v.getLocationInWindow(loc);
4383e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int vX = loc[0];
4393e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int vY = loc[1];
440716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
4413e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int left = vX - x;
4423e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int top = vY - y;
4433e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        r.set(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight());
444716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
445716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
446ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    @Override
447ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    public boolean dispatchUnhandledMove(View focused, int direction) {
4488dd5168b0582a20a4ede5ccfd21d227118fd9743Tony Wickham        // Consume the unhandled move if a container is open, to avoid switching pages underneath.
449740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        boolean isContainerOpen = AbstractFloatingView.getTopOpenView(mLauncher) != null;
4508dd5168b0582a20a4ede5ccfd21d227118fd9743Tony Wickham        return isContainerOpen || mDragController.dispatchUnhandledMove(focused, direction);
451ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    }
452120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen
453bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    @Override
454b8b48733a994fbaf7346170d7fba01da2d31f5d4Jon Miranda    public void setInsets(Rect insets) {
455b8b48733a994fbaf7346170d7fba01da2d31f5d4Jon Miranda        super.setInsets(insets);
456a69369450281376cb207be554199bb4895843eb2Mario Bertschler        setBackground(insets.top == 0 ? null
457a69369450281376cb207be554199bb4895843eb2Mario Bertschler                : Themes.getAttrDrawable(getContext(), R.attr.workspaceStatusBarScrim));
458b8b48733a994fbaf7346170d7fba01da2d31f5d4Jon Miranda    }
459b8b48733a994fbaf7346170d7fba01da2d31f5d4Jon Miranda
460b8b48733a994fbaf7346170d7fba01da2d31f5d4Jon Miranda    @Override
461bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    public LayoutParams generateLayoutParams(AttributeSet attrs) {
462bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        return new LayoutParams(getContext(), attrs);
463bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    }
464bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
465bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    @Override
466bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    protected LayoutParams generateDefaultLayoutParams() {
467bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
468bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    }
469bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
470bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    // Override to allow type-checking of LayoutParams.
471bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    @Override
472bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
473bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        return p instanceof LayoutParams;
474bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    }
475bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
476bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    @Override
477bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
478bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        return new LayoutParams(p);
479bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    }
480bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
481bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    public static class LayoutParams extends InsettableFrameLayout.LayoutParams {
4826788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int x, y;
4836788269814a678af976dfc7d6135993e172ce586Adam Cohen        public boolean customPosition = false;
4846788269814a678af976dfc7d6135993e172ce586Adam Cohen
485bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        public LayoutParams(Context c, AttributeSet attrs) {
486bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen            super(c, attrs);
487bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        }
488bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
4896788269814a678af976dfc7d6135993e172ce586Adam Cohen        public LayoutParams(int width, int height) {
4906788269814a678af976dfc7d6135993e172ce586Adam Cohen            super(width, height);
4916788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4926788269814a678af976dfc7d6135993e172ce586Adam Cohen
493bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        public LayoutParams(ViewGroup.LayoutParams lp) {
494bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen            super(lp);
495bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        }
496bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
4976788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setWidth(int width) {
4986788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.width = width;
4996788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5006788269814a678af976dfc7d6135993e172ce586Adam Cohen
5016788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getWidth() {
5026788269814a678af976dfc7d6135993e172ce586Adam Cohen            return width;
5036788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5046788269814a678af976dfc7d6135993e172ce586Adam Cohen
5056788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setHeight(int height) {
5066788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.height = height;
5076788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5086788269814a678af976dfc7d6135993e172ce586Adam Cohen
5096788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getHeight() {
5106788269814a678af976dfc7d6135993e172ce586Adam Cohen            return height;
5116788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5126788269814a678af976dfc7d6135993e172ce586Adam Cohen
5136788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setX(int x) {
5146788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.x = x;
5156788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5166788269814a678af976dfc7d6135993e172ce586Adam Cohen
5176788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getX() {
5186788269814a678af976dfc7d6135993e172ce586Adam Cohen            return x;
5196788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5206788269814a678af976dfc7d6135993e172ce586Adam Cohen
5216788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setY(int y) {
5226788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.y = y;
5236788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5246788269814a678af976dfc7d6135993e172ce586Adam Cohen
5256788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getY() {
5266788269814a678af976dfc7d6135993e172ce586Adam Cohen            return y;
5276788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5286788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
5296788269814a678af976dfc7d6135993e172ce586Adam Cohen
5306788269814a678af976dfc7d6135993e172ce586Adam Cohen    protected void onLayout(boolean changed, int l, int t, int r, int b) {
5316788269814a678af976dfc7d6135993e172ce586Adam Cohen        super.onLayout(changed, l, t, r, b);
5326788269814a678af976dfc7d6135993e172ce586Adam Cohen        int count = getChildCount();
5336788269814a678af976dfc7d6135993e172ce586Adam Cohen        for (int i = 0; i < count; i++) {
5346788269814a678af976dfc7d6135993e172ce586Adam Cohen            View child = getChildAt(i);
5356788269814a678af976dfc7d6135993e172ce586Adam Cohen            final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
5366788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (flp instanceof LayoutParams) {
5376788269814a678af976dfc7d6135993e172ce586Adam Cohen                final LayoutParams lp = (LayoutParams) flp;
5386788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (lp.customPosition) {
5396788269814a678af976dfc7d6135993e172ce586Adam Cohen                    child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
5406788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
5416788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
5426788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5436788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
5446788269814a678af976dfc7d6135993e172ce586Adam Cohen
5456ad72f02fd233f2294222477102e83d721100493Sunny Goyal    public void clearResizeFrame() {
5466ad72f02fd233f2294222477102e83d721100493Sunny Goyal        if (mCurrentResizeFrame != null) {
5476ad72f02fd233f2294222477102e83d721100493Sunny Goyal            removeView(mCurrentResizeFrame);
5486ad72f02fd233f2294222477102e83d721100493Sunny Goyal            mCurrentResizeFrame = null;
5496788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5506788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
5516788269814a678af976dfc7d6135993e172ce586Adam Cohen
5526ad72f02fd233f2294222477102e83d721100493Sunny Goyal    public void addResizeFrame(LauncherAppWidgetHostView widget, CellLayout cellLayout) {
5536ad72f02fd233f2294222477102e83d721100493Sunny Goyal        clearResizeFrame();
5546788269814a678af976dfc7d6135993e172ce586Adam Cohen
55508ca40f97670ad56ea01a81a439e89a484f9fdb5Sunny Goyal        mCurrentResizeFrame = (AppWidgetResizeFrame) LayoutInflater.from(mLauncher)
55608ca40f97670ad56ea01a81a439e89a484f9fdb5Sunny Goyal                .inflate(R.layout.app_widget_resize_frame, this, false);
55708ca40f97670ad56ea01a81a439e89a484f9fdb5Sunny Goyal        mCurrentResizeFrame.setupForWidget(widget, cellLayout, this);
55808ca40f97670ad56ea01a81a439e89a484f9fdb5Sunny Goyal        ((LayoutParams) mCurrentResizeFrame.getLayoutParams()).customPosition = true;
5596788269814a678af976dfc7d6135993e172ce586Adam Cohen
56008ca40f97670ad56ea01a81a439e89a484f9fdb5Sunny Goyal        addView(mCurrentResizeFrame);
5616ad72f02fd233f2294222477102e83d721100493Sunny Goyal        mCurrentResizeFrame.snapToWidget(false);
5626788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
563716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
5647bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha,
5657bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable,
5667bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            int duration) {
567b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        Rect r = new Rect();
568b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        getViewRectRelativeToSelf(dragView, r);
569b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        final int fromX = r.left;
570b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        final int fromY = r.top;
571b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen
5727bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        animateViewIntoPosition(dragView, fromX, fromY, pos[0], pos[1], alpha, 1, 1, scaleX, scaleY,
573ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                onFinishRunnable, animationEndStyle, duration, null);
574ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
575ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
576557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    public void animateViewIntoPosition(DragView dragView, final View child,
57728f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen            final Runnable onFinishAnimationRunnable, View anchorView) {
57828f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen        animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, anchorView);
579ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen    }
580ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen
581ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen    public void animateViewIntoPosition(DragView dragView, final View child, int duration,
5826441de0ec2a71862798dd51180d0811b42edd514Adam Cohen            final Runnable onFinishAnimationRunnable, View anchorView) {
583a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka        ShortcutAndWidgetContainer parentChildren = (ShortcutAndWidgetContainer) child.getParent();
584716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        CellLayout.LayoutParams lp =  (CellLayout.LayoutParams) child.getLayoutParams();
585eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung        parentChildren.measureChild(child);
586716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
5873e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        Rect r = new Rect();
5883e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        getViewRectRelativeToSelf(dragView, r);
589716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
590716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        int coord[] = new int[2];
591307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        float childScale = child.getScaleX();
592307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        coord[0] = lp.x + (int) (child.getMeasuredWidth() * (1 - childScale) / 2);
593307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        coord[1] = lp.y + (int) (child.getMeasuredHeight() * (1 - childScale) / 2);
594eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung
5958dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        // Since the child hasn't necessarily been laid out, we force the lp to be updated with
596ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        // the correct coordinates (above) and use these to determine the final location
597557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord);
598307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        // We need to account for the scale of the child itself, as the above only accounts for
599307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        // for the scale in parents.
600307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        scale *= childScale;
601ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        int toX = coord[0];
602ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        int toY = coord[1];
603eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung        float toScale = scale;
6044497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn        if (child instanceof TextView) {
6054497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            TextView tv = (TextView) child;
606eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            // Account for the source scale of the icon (ie. from AllApps to Workspace, in which
607eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            // the workspace may have smaller icon bounds).
608eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            toScale = scale / dragView.getIntrinsicIconScaleFactor();
6094497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn
6104497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // The child may be scaled (always about the center of the view) so to account for it,
6114497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // we have to offset the position by the scaled size.  Once we do that, we can center
6124497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // the drag view about the scaled child view.
613eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            toY += Math.round(toScale * tv.getPaddingTop());
614eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            toY -= dragView.getMeasuredHeight() * (1 - toScale) / 2;
61595abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal            if (dragView.getDragVisualizeOffset() != null) {
61695abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal                toY -=  Math.round(toScale * dragView.getDragVisualizeOffset().y);
61795abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal            }
61895abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal
6194497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
6204497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn        } else if (child instanceof FolderIcon) {
621ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            // Account for holographic blur padding on the drag view
6225f8afe6280eae34620067696173e71943e1a30a3Winson Chung            toY += Math.round(scale * (child.getPaddingTop() - dragView.getDragRegionTop()));
623c9c57631a985a8e1a4eac17ef0952bd344e281a2Jon Miranda            toY -= scale * dragView.getBlurSizeOutline() / 2;
624307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen            toY -= (1 - scale) * dragView.getMeasuredHeight() / 2;
625ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            // Center in the x coordinate about the target's drawable
626ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
627ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        } else {
628ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toY -= (Math.round(scale * (dragView.getHeight() - child.getMeasuredHeight()))) / 2;
629ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toX -= (Math.round(scale * (dragView.getMeasuredWidth()
630ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen                    - child.getMeasuredWidth()))) / 2;
631ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        }
632716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
633ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        final int fromX = r.left;
634ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        final int fromY = r.top;
635716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        child.setVisibility(INVISIBLE);
6368dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        Runnable onCompleteRunnable = new Runnable() {
6378dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void run() {
6388dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                child.setVisibility(VISIBLE);
639d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                if (onFinishAnimationRunnable != null) {
640d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                    onFinishAnimationRunnable.run();
641d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                }
6428dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
6438dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        };
644eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung        animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, toScale, toScale,
645d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                onCompleteRunnable, ANIMATION_END_DISAPPEAR, duration, anchorView);
646557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    }
647557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung
648d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen    public void animateViewIntoPosition(final DragView view, final int fromX, final int fromY,
649ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            final int toX, final int toY, float finalAlpha, float initScaleX, float initScaleY,
650ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            float finalScaleX, float finalScaleY, Runnable onCompleteRunnable,
651ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            int animationEndStyle, int duration, View anchorView) {
6528dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        Rect from = new Rect(fromX, fromY, fromX +
6538dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                view.getMeasuredWidth(), fromY + view.getMeasuredHeight());
6543e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        Rect to = new Rect(toX, toY, toX + view.getMeasuredWidth(), toY + view.getMeasuredHeight());
655ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        animateView(view, from, to, finalAlpha, initScaleX, initScaleY, finalScaleX, finalScaleY, duration,
656ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                null, null, onCompleteRunnable, animationEndStyle, anchorView);
6573e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    }
6583e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
659b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen    /**
660b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * This method animates a view at the end of a drag and drop animation.
661b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *
662b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param view The view to be animated. This view is drawn directly into DragLayer, and so
663b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        doesn't need to be a child of DragLayer.
664b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param from The initial location of the view. Only the left and top parameters are used.
665b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param to The final location of the view. Only the left and top parameters are used. This
666b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        location doesn't account for scaling, and so should be centered about the desired
667b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        final location (including scaling).
668b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param finalAlpha The final alpha of the view, in case we want it to fade as it animates.
6696178f13e2d1f0c1a89cea74538b51993ef3439e3Sunny Goyal     * @param finalScaleX The final scale of the view. The view is scaled about its center.
6706178f13e2d1f0c1a89cea74538b51993ef3439e3Sunny Goyal     * @param finalScaleY The final scale of the view. The view is scaled about its center.
671b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param duration The duration of the animation.
672b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param motionInterpolator The interpolator to use for the location of the view.
673b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param alphaInterpolator The interpolator to use for the alpha of the view.
674b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param onCompleteRunnable Optional runnable to run on animation completion.
6756178f13e2d1f0c1a89cea74538b51993ef3439e3Sunny Goyal     * @param animationEndStyle Whether or not to fade out the view once the animation completes.
6766178f13e2d1f0c1a89cea74538b51993ef3439e3Sunny Goyal     *        {@link #ANIMATION_END_DISAPPEAR} or {@link #ANIMATION_END_REMAIN_VISIBLE}.
6776441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     * @param anchorView If not null, this represents the view which the animated view stays
6786441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     *        anchored to in case scrolling is currently taking place. Note: currently this is
6796441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     *        only used for the X dimension for the case of the workspace.
680b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     */
6817bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void animateView(final DragView view, final Rect from, final Rect to,
6827bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final float finalAlpha, final float initScaleX, final float initScaleY,
6837bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final float finalScaleX, final float finalScaleY, int duration,
6847bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final Interpolator motionInterpolator, final Interpolator alphaInterpolator,
6857bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final Runnable onCompleteRunnable, final int animationEndStyle, View anchorView) {
6867bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
687716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        // Calculate the duration of the animation based on the object's distance
688f7a29e83f06909b378dba39c83a522375682710aSunny Goyal        final float dist = (float) Math.hypot(to.left - from.left, to.top - from.top);
689716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        final Resources res = getResources();
690716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
6913e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
6923e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        // If duration < 0, this is a cue to compute the duration based on the distance
6933e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (duration < 0) {
694dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal            duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
695dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal            if (dist < maxDist) {
696dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal                duration *= mCubicEaseOutInterpolator.getInterpolation(dist / maxDist);
6973e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
698dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal            duration = Math.max(duration, res.getInteger(R.integer.config_dropAnimMinDuration));
699716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        }
700716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
701043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Fall back to cubic ease out interpolator for the animation if none is specified
702043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        TimeInterpolator interpolator = null;
7033e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (alphaInterpolator == null || motionInterpolator == null) {
704043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            interpolator = mCubicEaseOutInterpolator;
7053e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        }
706716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
707043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Animate the view
7087bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        final float initAlpha = view.getAlpha();
709043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float dropViewScale = view.getScaleX();
710043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        AnimatorUpdateListener updateCb = new AnimatorUpdateListener() {
711043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
712716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
713716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen                final float percent = (Float) animation.getAnimatedValue();
7147bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                final int width = view.getMeasuredWidth();
7157bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                final int height = view.getMeasuredHeight();
716716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
7173e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                float alphaPercent = alphaInterpolator == null ? percent :
7183e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                        alphaInterpolator.getInterpolation(percent);
7193e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                float motionPercent = motionInterpolator == null ? percent :
7203e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                        motionInterpolator.getInterpolation(percent);
721a1cdab039292f3d809528c0e2e38580b37864d8dWinson Chung
7227bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float initialScaleX = initScaleX * dropViewScale;
7237bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float initialScaleY = initScaleY * dropViewScale;
7247bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float scaleX = finalScaleX * percent + initialScaleX * (1 - percent);
7257bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float scaleY = finalScaleY * percent + initialScaleY * (1 - percent);
7267bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float alpha = finalAlpha * alphaPercent + initAlpha * (1 - alphaPercent);
7277bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
7287bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float fromLeft = from.left + (initialScaleX - 1f) * width / 2;
7297bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float fromTop = from.top + (initialScaleY - 1f) * height / 2;
7307bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
7317bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int x = (int) (fromLeft + Math.round(((to.left - fromLeft) * motionPercent)));
7327bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int y = (int) (fromTop + Math.round(((to.top - fromTop) * motionPercent)));
7337bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
73428f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen                int anchorAdjust = mAnchorView == null ? 0 : (int) (mAnchorView.getScaleX() *
73528f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen                    (mAnchorViewInitialScrollX - mAnchorView.getScrollX()));
73628f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen
73728f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen                int xPos = x - mDropView.getScrollX() + anchorAdjust;
7387bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int yPos = y - mDropView.getScrollY();
7397bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
7407bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setTranslationX(xPos);
7417bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setTranslationY(yPos);
7427bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setScaleX(scaleX);
7437bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setScaleY(scaleY);
7447bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setAlpha(alpha);
745716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            }
746043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
747043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        animateView(view, updateCb, duration, interpolator, onCompleteRunnable, animationEndStyle,
748043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                anchorView);
749043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
750043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
751043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    public void animateView(final DragView view, AnimatorUpdateListener updateCb, int duration,
752043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            TimeInterpolator interpolator, final Runnable onCompleteRunnable,
753043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            final int animationEndStyle, View anchorView) {
754043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Clean up the previous animations
755043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mDropAnim != null) mDropAnim.cancel();
756043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
757043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Show the drop view if it was previously hidden
758043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView = view;
759043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView.cancelAnimation();
760d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        mDropView.requestLayout();
761043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
762043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Set the anchor view if the page is scrolling
763043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (anchorView != null) {
764043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mAnchorViewInitialScrollX = anchorView.getScrollX();
765043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
766043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mAnchorView = anchorView;
767043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
768043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Create and start the animation
769043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim = new ValueAnimator();
770043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setInterpolator(interpolator);
771043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setDuration(duration);
772043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setFloatValues(0f, 1f);
773043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.addUpdateListener(updateCb);
7743e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        mDropAnim.addListener(new AnimatorListenerAdapter() {
7753e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            public void onAnimationEnd(Animator animation) {
7768dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                if (onCompleteRunnable != null) {
7778dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                    onCompleteRunnable.run();
7788dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                }
779ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                switch (animationEndStyle) {
780ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_DISAPPEAR:
781ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    clearAnimatedView();
782ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
783ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_REMAIN_VISIBLE:
784ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
7853e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                }
7863e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
7873e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        });
788716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mDropAnim.start();
789716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
790716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
791ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public void clearAnimatedView() {
7927bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mDropAnim != null) {
7937bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            mDropAnim.cancel();
7947bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
7957bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mDropView != null) {
7962d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            mDragController.onDeferredEndDrag(mDropView);
7977bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
798ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        mDropView = null;
799ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        invalidate();
800ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
801ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
802ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public View getAnimatedView() {
803ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        return mDropView;
804ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
805ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
806716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    @Override
8078b805b17158886035b38261eb611d8641701ae43Michael Jurka    public void onChildViewAdded(View parent, View child) {
808a6d0492e5f0dd4e1b43d4034a770241dc65f8f8cAdam Cohen        super.onChildViewAdded(parent, child);
80921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        updateChildIndices();
81021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
81121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
81221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    @Override
8138b805b17158886035b38261eb611d8641701ae43Michael Jurka    public void onChildViewRemoved(View parent, View child) {
81421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        updateChildIndices();
81521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
81621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
817432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    @Override
818432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    public void bringChildToFront(View child) {
819432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        super.bringChildToFront(child);
820432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        updateChildIndices();
821432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    }
822432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen
82321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    private void updateChildIndices() {
824432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        mTopViewIndex = -1;
82555bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi        int childCount = getChildCount();
82655bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi        for (int i = 0; i < childCount; i++) {
827b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen            if (getChildAt(i) instanceof DragView) {
828432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen                mTopViewIndex = i;
82955bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi            }
83021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
8312d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen        mChildCountOnLastUpdate = childCount;
83221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
83321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
83421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    @Override
83521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    protected int getChildDrawingOrder(int childCount, int i) {
8362d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen        if (mChildCountOnLastUpdate != childCount) {
8372d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            // between platform versions 17 and 18, behavior for onChildViewRemoved / Added changed.
8382d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            // Pre-18, the child was not added / removed by the time of those callbacks. We need to
8392d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            // force update our representation of things here to avoid crashing on pre-18 devices
8402d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            // in certain instances.
8412d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            updateChildIndices();
8422d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen        }
8432d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen
844432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        // i represents the current draw iteration
845432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        if (mTopViewIndex == -1) {
846432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            // in general we do nothing
84721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return i;
848432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        } else if (i == childCount - 1) {
849432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            // if we have a top index, we return it when drawing last item (highest z-order)
850432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            return mTopViewIndex;
851432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        } else if (i < mTopViewIndex) {
85221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return i;
85355bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi        } else {
854432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            // for indexes greater than the top index, we fetch one item above to shift for the
855432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            // displacement of the top index
856432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            return i + 1;
85721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
85821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
859360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
86095cdb3a0211650e76adb451588ce89fd585b178fTony Wickham    public void invalidateScrim() {
86195cdb3a0211650e76adb451588ce89fd585b178fTony Wickham        if (mBackgroundAlpha > 0.0f) {
86295cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            invalidate();
86395cdb3a0211650e76adb451588ce89fd585b178fTony Wickham        }
86495cdb3a0211650e76adb451588ce89fd585b178fTony Wickham    }
86595cdb3a0211650e76adb451588ce89fd585b178fTony Wickham
866360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    @Override
867360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    protected void dispatchDraw(Canvas canvas) {
8680fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal        // Draw the background below children.
8690fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal        if (mBackgroundAlpha > 0.0f) {
87095cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            // Update the scroll position first to ensure scrim cutout is in the right place.
87195cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            mLauncher.getWorkspace().computeScrollWithoutInvalidation();
87295cdb3a0211650e76adb451588ce89fd585b178fTony Wickham
8736c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen            int alpha = (int) (mBackgroundAlpha * 255);
87495cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            CellLayout currCellLayout = mLauncher.getWorkspace().getCurrentDragOverlappingLayout();
87595cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            canvas.save();
87695cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            if (currCellLayout != null && currCellLayout != mLauncher.getHotseat().getLayout()) {
87795cdb3a0211650e76adb451588ce89fd585b178fTony Wickham                // Cut a hole in the darkening scrim on the page that should be highlighted, if any.
8786178f13e2d1f0c1a89cea74538b51993ef3439e3Sunny Goyal                getDescendantRectRelativeToSelf(currCellLayout, mHighlightRect);
87995cdb3a0211650e76adb451588ce89fd585b178fTony Wickham                canvas.clipRect(mHighlightRect, Region.Op.DIFFERENCE);
88095cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            }
881ff4f201fadb131e7c367f64296e3a08090946adaMario Bertschler            // for super light wallpaper it needs to be darken for contrast to workspace
882ff4f201fadb131e7c367f64296e3a08090946adaMario Bertschler            // for dark wallpapers the text is white so darkening works as well
883ff4f201fadb131e7c367f64296e3a08090946adaMario Bertschler            int color = ColorUtils.compositeColors(0x66000000, mWallpaperColorInfo.getMainColor());
884ff4f201fadb131e7c367f64296e3a08090946adaMario Bertschler            canvas.drawColor(ColorUtils.setAlphaComponent(color, alpha));
88595cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            canvas.restore();
8866c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen        }
8876c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen
8883333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal        mFocusIndicatorHelper.draw(canvas);
889360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        super.dispatchDraw(canvas);
8908cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen    }
891360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
8926c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    public void setBackgroundAlpha(float alpha) {
8936c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen        if (alpha != mBackgroundAlpha) {
8946c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen            mBackgroundAlpha = alpha;
8956c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen            invalidate();
8966c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen        }
8976c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    }
8986c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen
8996c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    public float getBackgroundAlpha() {
9006c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen        return mBackgroundAlpha;
9016c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    }
9026c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen
90352851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal    @Override
90452851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
905740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        View topView = AbstractFloatingView.getTopOpenView(mLauncher);
90652851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        if (topView != null) {
90752851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            return topView.requestFocus(direction, previouslyFocusedRect);
90852851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        } else {
90952851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
91052851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        }
91152851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal    }
91252851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal
91352851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal    @Override
91452851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
915740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        View topView = AbstractFloatingView.getTopOpenView(mLauncher);
91652851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        if (topView != null) {
91752851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            topView.addFocusables(views, direction);
91852851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        } else {
91952851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            super.addFocusables(views, direction, focusableMode);
92052851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        }
92152851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal    }
92252851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal
923b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    public void setTouchCompleteListener(TouchCompleteListener listener) {
924b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        mTouchCompleteListener = listener;
925b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    }
926b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen
927b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    public interface TouchCompleteListener {
928b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        public void onTouchComplete();
929b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    }
93031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
931