Merge "Don't animate the workspace background alpha during recents anim" into ub-launcher3-master
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 68f6667..f22cc48 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -20,6 +20,7 @@
 import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber;
 import static com.android.systemui.shared.recents.utilities.Utilities.getSurface;
 import static com.android.systemui.shared.recents.utilities.Utilities.postAtFrontOfQueueAsynchronously;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
 
 import android.animation.Animator;
@@ -258,6 +259,7 @@
         int launchedTaskIndex = recentsView.indexOfChild(v);
         int centerTaskIndex = recentsView.getCurrentPage();
         boolean launchingCenterTask = launchedTaskIndex == centerTaskIndex;
+        boolean isRtl = recentsView.isRtl();
         if (launchingCenterTask) {
             if (launchedTaskIndex - 1 >= recentsView.getFirstTaskIndex()) {
                 TaskView adjacentPage1 = (TaskView) recentsView.getPageAt(launchedTaskIndex - 1);
@@ -266,7 +268,7 @@
                                 new PropertyListBuilder()
                                         .scale(adjacentPage1.getScaleX() * mRecentsScale)
                                         .translationY(mRecentsTransY)
-                                        .translationX(mIsRtl ? mRecentsTransX : -mRecentsTransX)
+                                        .translationX(isRtl ? mRecentsTransX : -mRecentsTransX)
                                         .build());
                 launcherAnimator.play(adjacentTask1ScaleAndTranslate);
             }
@@ -277,7 +279,7 @@
                                 new PropertyListBuilder()
                                         .scale(adjacentTask2.getScaleX() * mRecentsScale)
                                         .translationY(mRecentsTransY)
-                                        .translationX(mIsRtl ? -mRecentsTransX : mRecentsTransX)
+                                        .translationX(isRtl ? -mRecentsTransX : mRecentsTransX)
                                         .build());
                 launcherAnimator.play(adjacentTask2ScaleAndTranslate);
             }
@@ -289,7 +291,7 @@
                     LauncherAnimUtils.ofPropertyValuesHolder(centerTask,
                             new PropertyListBuilder()
                                     .scale(v.getScaleX())
-                                    .translationX(mIsRtl ? -translationX : translationX)
+                                    .translationX(isRtl ? -translationX : translationX)
                                     .build());
             launcherAnimator.play(centerTaskParallaxToRight);
             int otherAdjacentTaskIndex = centerTaskIndex + (centerTaskIndex - launchedTaskIndex);
@@ -301,7 +303,7 @@
                         LauncherAnimUtils.ofPropertyValuesHolder(otherAdjacentTask,
                                 new PropertyListBuilder()
                                         .translationX(otherAdjacentTask.getTranslationX()
-                                                + (mIsRtl ? -translationX : translationX))
+                                                + (isRtl ? -translationX : translationX))
                                         .build());
                 launcherAnimator.play(otherAdjacentTaskParallaxToRight);
             }
@@ -423,17 +425,19 @@
      */
     private LauncherTransitionAnimator composeAppLaunchAnimator(View v,
             RemoteAnimationTargetCompat[] targets) {
-        return new LauncherTransitionAnimator(getLauncherAnimators(v),
+        return new LauncherTransitionAnimator(getLauncherAnimators(v, targets),
                 getWindowAnimators(v, targets));
     }
 
     /**
      * @return Animators that control the movements of the Launcher and icon of the opening target.
      */
-    private AnimatorSet getLauncherAnimators(View v) {
+    private AnimatorSet getLauncherAnimators(View v, RemoteAnimationTargetCompat[] targets) {
         AnimatorSet launcherAnimators = new AnimatorSet();
-        launcherAnimators.play(getLauncherContentAnimator(false /* show */));
         launcherAnimators.play(getIconAnimator(v));
+        if (launcherIsATargetWithMode(targets, MODE_CLOSING)) {
+            launcherAnimators.play(getLauncherContentAnimator(false /* show */));
+        }
         return launcherAnimators;
     }
 
@@ -494,8 +498,10 @@
         mFloatingView = new View(mLauncher);
         if (isBubbleTextView && v.getTag() instanceof ItemInfoWithIcon ) {
             // Create a copy of the app icon
-            mFloatingView.setBackground(
-                    DrawableFactory.get(mLauncher).newIcon((ItemInfoWithIcon) v.getTag()));
+            ItemInfoWithIcon info = (ItemInfoWithIcon) v.getTag();
+            FastBitmapDrawable d = DrawableFactory.get(mLauncher).newIcon(info);
+            d.setIsDisabled(info.isDisabled());
+            mFloatingView.setBackground(d);
         }
 
         // Position the floating view exactly on top of the original
@@ -681,10 +687,10 @@
         }
     }
 
-    private boolean isLauncherInSetOfOpeningTargets(RemoteAnimationTargetCompat[] targets) {
+    private boolean launcherIsATargetWithMode(RemoteAnimationTargetCompat[] targets, int mode) {
         int launcherTaskId = mLauncher.getTaskId();
         for (RemoteAnimationTargetCompat target : targets) {
-            if (target.mode == MODE_OPENING && target.taskId == launcherTaskId) {
+            if (target.mode == mode && target.taskId == launcherTaskId) {
                 return true;
             }
         }
@@ -705,7 +711,7 @@
                     if ((Utilities.getPrefs(mLauncher)
                             .getBoolean("pref_use_screenshot_for_swipe_up", false)
                             && mLauncher.isInState(LauncherState.OVERVIEW))
-                            || !isLauncherInSetOfOpeningTargets(targets)) {
+                            || !launcherIsATargetWithMode(targets, MODE_OPENING)) {
                         // We use a separate transition for Overview mode. And we can skip the
                         // animation in cases where Launcher is not in the set of opening targets.
                         // This can happen when Launcher is already visible. ie. Closing a dialog.
@@ -741,7 +747,7 @@
         Matrix matrix = new Matrix();
         float height = mLauncher.getDeviceProfile().heightPx;
         float width = mLauncher.getDeviceProfile().widthPx;
-        float endX = (Utilities.isRtl(mLauncher.getResources()) ? -width : width) * 1.16f;
+        float endX = (mLauncher.<RecentsView>getOverviewPanel().isRtl() ? -width : width) * 1.16f;
 
         ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1);
         closingAnimator.setDuration(CLOSING_TRANSITION_DURATION_MS);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index 9ba2308..613968e 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -26,7 +26,6 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
 import com.android.quickstep.RecentsView;
@@ -111,7 +110,7 @@
                 scale * (halfWidth - ws.getPaddingLeft() - insets.left - childWidth / 2);
         float translationX = pageRect.centerX() - childCenter;
 
-        if (Utilities.isRtl(launcher.getResources())) {
+        if (launcher.<RecentsView>getOverviewPanel().isRtl()) {
             translationX -= offsetX / scale;
         } else {
             translationX += offsetX / scale;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 7d371e9..80ecb92 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -75,7 +75,7 @@
     public void setStateWithAnimation(final LauncherState toState,
             AnimatorSetBuilder builder, AnimationConfig config) {
         boolean settingEnabled = Utilities.getPrefs(mLauncher)
-            .getBoolean("pref_scroll_to_first_task", false);
+            .getBoolean("pref_scroll_to_first_task_default_true", true);
         mIsRecentsScrollingToFirstTask = mLauncher.isInState(NORMAL) && toState == OVERVIEW
                 && settingEnabled;
         // TODO: Instead of animating the workspace translationX, move the contents
diff --git a/quickstep/src/com/android/quickstep/RecentsView.java b/quickstep/src/com/android/quickstep/RecentsView.java
index ec0716c..9e07b49 100644
--- a/quickstep/src/com/android/quickstep/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/RecentsView.java
@@ -23,6 +23,8 @@
 
 import android.animation.LayoutTransition;
 import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
 import android.graphics.Bitmap;
 import android.graphics.BitmapShader;
 import android.graphics.Canvas;
@@ -62,7 +64,7 @@
 /**
  * A list of recent tasks.
  */
-public class RecentsView extends PagedView implements Insettable {
+public class RecentsView extends PagedView implements Insettable, OnSharedPreferenceChangeListener {
 
     private static final Rect sTempStableInsets = new Rect();
 
@@ -70,6 +72,8 @@
     public static final int SCROLL_TYPE_TASK = 1;
     public static final int SCROLL_TYPE_WORKSPACE = 2;
 
+    private static final String PREF_FLIP_RECENTS = "pref_flip_recents";
+
     private final Launcher mLauncher;
     private QuickScrubController mQuickScrubController;
     private final ScrollState mScrollState = new ScrollState();
@@ -130,7 +134,23 @@
         mQuickScrubController = new QuickScrubController(mLauncher, this);
         mModel = RecentsModel.getInstance(context);
 
-        mScrollState.isRtl = mIsRtl;
+        onSharedPreferenceChanged(Utilities.getPrefs(context), PREF_FLIP_RECENTS);
+    }
+
+    @Override
+    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
+        if (s.equals(PREF_FLIP_RECENTS)) {
+            mIsRtl = Utilities.isRtl(getResources());
+            if (sharedPreferences.getBoolean(PREF_FLIP_RECENTS, false)) {
+                mIsRtl = !mIsRtl;
+            }
+            setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
+            mScrollState.isRtl = mIsRtl;
+        }
+    }
+
+    public boolean isRtl() {
+        return mIsRtl;
     }
 
     public TaskView updateThumbnail(int taskId, ThumbnailData thumbnailData) {
@@ -172,12 +192,14 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         updateTaskStackListenerState();
+        Utilities.getPrefs(getContext()).registerOnSharedPreferenceChangeListener(this);
     }
 
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         updateTaskStackListenerState();
+        Utilities.getPrefs(getContext()).unregisterOnSharedPreferenceChangeListener(this);
     }
 
     @Override
diff --git a/res/drawable/round_rect_primary.xml b/res/drawable/round_rect_primary.xml
index 9f8f4da..16310f8 100644
--- a/res/drawable/round_rect_primary.xml
+++ b/res/drawable/round_rect_primary.xml
@@ -17,5 +17,5 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
     <solid android:color="?android:attr/colorPrimary" />
-    <corners android:radius="8dp" />
+    <corners android:radius="@dimen/bg_round_rect_radius" />
 </shape>
diff --git a/res/drawable/top_round_rect_primary.xml b/res/drawable/top_round_rect_primary.xml
new file mode 100644
index 0000000..1caaa02
--- /dev/null
+++ b/res/drawable/top_round_rect_primary.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <solid android:color="?android:attr/colorPrimary" />
+    <corners
+        android:topLeftRadius="@dimen/bg_round_rect_radius"
+        android:topRightRadius="@dimen/bg_round_rect_radius"
+        android:bottomLeftRadius="0dp"
+        android:bottomRightRadius="0dp"
+        />
+</shape>
diff --git a/res/layout/widgets_bottom_sheet.xml b/res/layout/widgets_bottom_sheet.xml
index e8c6961..6bf9048 100644
--- a/res/layout/widgets_bottom_sheet.xml
+++ b/res/layout/widgets_bottom_sheet.xml
@@ -20,7 +20,7 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:paddingTop="28dp"
-    android:background="?android:attr/colorPrimary"
+    android:background="@drawable/top_round_rect_primary"
     android:elevation="@dimen/deep_shortcuts_elevation"
     android:layout_gravity="bottom"
     android:theme="?attr/widgetsTheme">
diff --git a/res/layout/widgets_full_sheet.xml b/res/layout/widgets_full_sheet.xml
index 1535299..20eca9f 100644
--- a/res/layout/widgets_full_sheet.xml
+++ b/res/layout/widgets_full_sheet.xml
@@ -25,7 +25,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
 
-    <FrameLayout
+    <com.android.launcher3.views.TopRoundedCornerView
         android:id="@+id/container"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
@@ -60,5 +60,5 @@
             android:layout_gravity="bottom"
             android:background="?attr/allAppsNavBarScrimColor"
             android:focusable="false"  />
-    </FrameLayout>
+    </com.android.launcher3.views.TopRoundedCornerView>
 </com.android.launcher3.widget.WidgetsFullSheet>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2318e9e..381830c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -334,7 +334,7 @@
     <!-- Title of an overlay in All Apps. This overlay is letting a user know about their work profile, which is managed by their employer. "Work apps" are apps in a user's work profile.-->
     <string name="bottom_work_tab_user_education_title">Find work apps here</string>
     <!-- Text in an overlay in All Apps. This overlay is letting a user know about their work profile, which is managed by their employer.-->
-    <string name="bottom_work_tab_user_education_body">Each work app has an orange badge and is kept secure by your organization. Move apps to your Home screen for easier access.</string>
+    <string name="bottom_work_tab_user_education_body">Each work app has a badge and is kept secure by your organization. Move apps to your Home screen for easier access.</string>
     <!-- This string is in the work profile tab when a user has All Apps open on their phone. It describes the label of a toggle, "Work profile," as being managed by the user's employer.
     "Organization" is used to represent a variety of businesses, non-profits, and educational institutions).-->
     <string name="work_mode_on_label">Managed by your organization</string>
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 55bfef6..7209d9d 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -408,6 +408,11 @@
         if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
             mUserEventDispatcher = null;
             initDeviceProfile(mDeviceProfile.inv);
+            FileLog.d(TAG, "Config changed, my orientation=" +
+                    getResources().getConfiguration().orientation +
+                    ", new orientation=" + newConfig.orientation +
+                    ", old orientation=" + mOldConfig.orientation +
+                    ", isTransposed=" + mDeviceProfile.isVerticalBarLayout());
             dispatchDeviceProfileChanged();
 
             getRootView().dispatchInsets();
@@ -2752,18 +2757,20 @@
                     writer.println(prefix + "    " + tag.toString());
                 }
             }
-
-            try {
-                FileLog.flushAll(writer);
-            } catch (Exception e) {
-                // Ignore
-            }
         }
 
         writer.println(prefix + "Misc:");
         writer.print(prefix + "\tmWorkspaceLoading=" + mWorkspaceLoading);
         writer.print(" mPendingRequestArgs=" + mPendingRequestArgs);
         writer.println(" mPendingActivityResult=" + mPendingActivityResult);
+        writer.println(" deviceProfile isTransposed=" + getDeviceProfile().isVerticalBarLayout());
+        writer.println(" orientation=" + getResources().getConfiguration().orientation);
+
+        try {
+            FileLog.flushAll(writer);
+        } catch (Exception e) {
+            // Ignore
+        }
 
         mModel.dumpState(prefix, fd, writer, args);
 
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 138ea0f..053dc35 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -56,6 +56,7 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.logging.FileLog;
 import com.android.launcher3.model.DbDowngradeHelper;
+import com.android.launcher3.model.ModelWriter;
 import com.android.launcher3.provider.LauncherDbUtils;
 import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
 import com.android.launcher3.provider.RestoreDbTask;
@@ -320,6 +321,11 @@
 
     @Override
     public int delete(Uri uri, String selection, String[] selectionArgs) {
+        if (ModelWriter.DEBUG_DELETE) {
+            String args = selectionArgs == null ? null : TextUtils.join(",", selectionArgs);
+            FileLog.d(TAG, "Delete uri=" + uri + ", selection=" + selection
+                    + ", selectionArgs=" + args, new Exception());
+        }
         createDbIfNotExists();
         SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
 
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index ccb0a95..ca8039c 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -64,9 +64,6 @@
     private static final boolean DEBUG = false;
     protected static final int INVALID_PAGE = -1;
 
-    // the min drag distance for a fling to register, to prevent random page shifts
-    private static final int MIN_LENGTH_FOR_FLING = 25;
-
     public static final int PAGE_SNAP_ANIMATION_DURATION = 750;
     public static final int SLOW_PAGE_SNAP_ANIMATION_DURATION = 950;
 
@@ -182,7 +179,7 @@
     private static final Rect sTmpRect = new Rect();
 
     protected final Rect mInsets = new Rect();
-    protected final boolean mIsRtl;
+    protected boolean mIsRtl;
 
     // Similar to the platform implementation of isLayoutValid();
     protected boolean mIsLayoutValid;
@@ -1312,9 +1309,7 @@
                         SIGNIFICANT_MOVE_THRESHOLD;
 
                 mTotalMotionX += Math.abs(mLastMotionX + mLastMotionXRemainder - x);
-
-                boolean isFling = mTotalMotionX > MIN_LENGTH_FOR_FLING &&
-                        shouldFlingForVelocity(velocityX);
+                boolean isFling = mTotalMotionX > mTouchSlop && shouldFlingForVelocity(velocityX);
 
                 if (!mFreeScroll) {
                     // In the case that the page is moved far to one direction and then is flung
@@ -1892,6 +1887,14 @@
                 getNextPage() + 1, getChildCount());
     }
 
+    protected float getDownMotionX() {
+        return mDownMotionX;
+    }
+
+    protected float getDownMotionY() {
+        return mDownMotionY;
+    }
+
     @Override
     public boolean onHoverEvent(android.view.MotionEvent event) {
         return true;
diff --git a/src/com/android/launcher3/allapps/AllAppsPagedView.java b/src/com/android/launcher3/allapps/AllAppsPagedView.java
index 86186fd..3b4450b 100644
--- a/src/com/android/launcher3/allapps/AllAppsPagedView.java
+++ b/src/com/android/launcher3/allapps/AllAppsPagedView.java
@@ -18,12 +18,17 @@
 import android.content.Context;
 import android.util.AttributeSet;
 
+import android.view.MotionEvent;
 import com.android.launcher3.PagedView;
 import com.android.launcher3.R;
 
 public class AllAppsPagedView extends PagedView<PersonalWorkSlidingTabStrip> {
 
-    public AllAppsPagedView(Context context) {
+  final static float START_DAMPING_TOUCH_SLOP_ANGLE = (float) Math.PI / 6;
+  final static float MAX_SWIPE_ANGLE = (float) Math.PI / 3;
+  final static float TOUCH_SLOP_DAMPING_FACTOR = 4;
+
+  public AllAppsPagedView(Context context) {
         this(context, null);
     }
 
@@ -46,4 +51,30 @@
         super.onScrollChanged(l, t, oldl, oldt);
         mPageIndicator.setScroll(l, mMaxScrollX);
     }
+
+    @Override
+    protected void determineScrollingStart(MotionEvent ev) {
+        float absDeltaX = Math.abs(ev.getX() - getDownMotionX());
+        float absDeltaY = Math.abs(ev.getY() - getDownMotionY());
+
+        if (Float.compare(absDeltaX, 0f) == 0) return;
+
+        float slope = absDeltaY / absDeltaX;
+        float theta = (float) Math.atan(slope);
+
+        if (absDeltaX > mTouchSlop || absDeltaY > mTouchSlop) {
+            cancelCurrentPageLongPress();
+        }
+
+        if (theta > MAX_SWIPE_ANGLE) {
+            return;
+        } else if (theta > START_DAMPING_TOUCH_SLOP_ANGLE) {
+            theta -= START_DAMPING_TOUCH_SLOP_ANGLE;
+            float extraRatio = (float)
+                    Math.sqrt((theta / (MAX_SWIPE_ANGLE - START_DAMPING_TOUCH_SLOP_ANGLE)));
+            super.determineScrollingStart(ev, 1 + TOUCH_SLOP_DAMPING_FACTOR * extraRatio);
+        } else {
+            super.determineScrollingStart(ev);
+        }
+    }
 }
diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java
index 032ed78..40e0f49 100644
--- a/src/com/android/launcher3/model/ModelWriter.java
+++ b/src/com/android/launcher3/model/ModelWriter.java
@@ -32,6 +32,7 @@
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.LauncherSettings.Settings;
 import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.logging.FileLog;
 import com.android.launcher3.util.ContentWriter;
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.LooperExecutor;
@@ -46,6 +47,7 @@
 public class ModelWriter {
 
     private static final String TAG = "ModelWriter";
+    public static final boolean DEBUG_DELETE = true;
 
     private final Context mContext;
     private final BgDataModel mBgDataModel;
@@ -243,14 +245,21 @@
      * Removes the specified items from the database
      */
     public void deleteItemsFromDatabase(final Iterable<? extends ItemInfo> items) {
-        mWorkerExecutor.execute(new Runnable() {
-            public void run() {
-                for (ItemInfo item : items) {
-                    final Uri uri = Favorites.getContentUri(item.id);
-                    mContext.getContentResolver().delete(uri, null, null);
+        if (DEBUG_DELETE) {
+            // Log it on the colling thread to get the proper stack trace
+            FileLog.d(TAG, "Starting item deletion", new Exception());
+            for (ItemInfo item : items) {
+                FileLog.d(TAG, "deleting item " + item);
+            }
+            FileLog.d(TAG, "Finished deleting items");
+        }
 
-                    mBgDataModel.removeItem(mContext, item);
-                }
+        mWorkerExecutor.execute(() -> {
+            for (ItemInfo item : items) {
+                final Uri uri = Favorites.getContentUri(item.id);
+                mContext.getContentResolver().delete(uri, null, null);
+
+                mBgDataModel.removeItem(mContext, item);
             }
         });
     }
@@ -259,17 +268,20 @@
      * Remove the specified folder and all its contents from the database.
      */
     public void deleteFolderAndContentsFromDatabase(final FolderInfo info) {
-        mWorkerExecutor.execute(new Runnable() {
-            public void run() {
-                ContentResolver cr = mContext.getContentResolver();
-                cr.delete(LauncherSettings.Favorites.CONTENT_URI,
-                        LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
-                mBgDataModel.removeItem(mContext, info.contents);
-                info.contents.clear();
+        if (DEBUG_DELETE) {
+            // Log it on the colling thread to get the proper stack trace
+            FileLog.d(TAG, "Deleting folder " + info, new Exception());
+        }
 
-                cr.delete(LauncherSettings.Favorites.getContentUri(info.id), null, null);
-                mBgDataModel.removeItem(mContext, info);
-            }
+        mWorkerExecutor.execute(() -> {
+            ContentResolver cr = mContext.getContentResolver();
+            cr.delete(LauncherSettings.Favorites.CONTENT_URI,
+                    LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
+            mBgDataModel.removeItem(mContext, info.contents);
+            info.contents.clear();
+
+            cr.delete(LauncherSettings.Favorites.getContentUri(info.id), null, null);
+            mBgDataModel.removeItem(mContext, info);
         });
     }
 
diff --git a/src/com/android/launcher3/views/TopRoundedCornerView.java b/src/com/android/launcher3/views/TopRoundedCornerView.java
new file mode 100644
index 0000000..ba223c4
--- /dev/null
+++ b/src/com/android/launcher3/views/TopRoundedCornerView.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.views;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+import com.android.launcher3.R;
+
+/**
+ * View with top rounded corners.
+ */
+public class TopRoundedCornerView extends FrameLayout {
+
+    private final RectF mRect = new RectF();
+    private final Path mClipPath = new Path();
+    private float[] mRadii;
+
+    public TopRoundedCornerView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        int radius = getResources().getDimensionPixelSize(R.dimen.bg_round_rect_radius);
+        mRadii = new float[] {radius, radius, radius, radius, 0, 0, 0, 0};
+    }
+
+    public TopRoundedCornerView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        canvas.save();
+        canvas.clipPath(mClipPath);
+        super.draw(canvas);
+        canvas.restore();
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        mRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
+        mClipPath.reset();
+        mClipPath.addRoundRect(mRect, mRadii, Path.Direction.CW);
+    }
+}
diff --git a/src/com/android/launcher3/widget/WidgetsFullSheet.java b/src/com/android/launcher3/widget/WidgetsFullSheet.java
index d62a909..e461afc 100644
--- a/src/com/android/launcher3/widget/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsFullSheet.java
@@ -115,6 +115,7 @@
             mGradientView.setVisibility(View.INVISIBLE);
             widthUsed = 0;
         } else {
+            mGradientView.setVisibility(View.VISIBLE);
             Rect padding = mLauncher.getDeviceProfile().workspacePadding;
             widthUsed = Math.max(padding.left + padding.right,
                     2 * (mInsets.left + mInsets.right));