Separing the overview states for normal and quickstep builds

In QuickStep, adding a placeholder ScrollView and changing the state logic
appropriately to handle that

Change-Id: I10223c0692788d6e5dbf8c408c01cafb4e39bd2c
diff --git a/quickstep/res/layout/overview_panel.xml b/quickstep/res/layout/overview_panel.xml
new file mode 100644
index 0000000..466470f
--- /dev/null
+++ b/quickstep/res/layout/overview_panel.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.quickstep.RecentsView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:theme="@style/HomeScreenElementTheme"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_gravity="center_horizontal|bottom"
+    android:gravity="top">
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:orientation="horizontal">
+
+        <View
+            android:layout_width="300dp"
+            android:layout_height="match_parent"
+            android:background="#44FF0000"
+            android:layout_marginEnd="10dp"/>
+
+        <View
+            android:layout_width="300dp"
+            android:layout_height="match_parent"
+            android:background="#4400FF00"
+            android:layout_marginEnd="10dp"/>
+
+        <View
+            android:layout_width="300dp"
+            android:layout_height="match_parent"
+            android:background="#440000FF" />
+    </LinearLayout>
+
+</com.android.quickstep.RecentsView>
\ No newline at end of file
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index 0e7035a..51a8a5e 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -27,6 +27,7 @@
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
+import com.android.quickstep.RecentsView;
 
 /**
  * Definition for overview state
@@ -44,36 +45,18 @@
 
     @Override
     public float[] getWorkspaceScaleAndTranslation(Launcher launcher) {
-        DeviceProfile grid = launcher.getDeviceProfile();
-        Workspace ws = launcher.getWorkspace();
-        Rect insets = launcher.getDragLayer().getInsets();
-
-        int overviewButtonBarHeight = grid.getOverviewModeButtonBarHeight();
-        int scaledHeight = (int) (SCALE_FACTOR * ws.getNormalChildHeight());
-        Rect workspacePadding = grid.getWorkspacePadding(null);
-        int workspaceTop = insets.top + workspacePadding.top;
-        int workspaceBottom = ws.getViewportHeight() - insets.bottom - workspacePadding.bottom;
-        int overviewTop = insets.top;
-        int overviewBottom = ws.getViewportHeight() - insets.bottom - overviewButtonBarHeight;
-        int workspaceOffsetTopEdge =
-                workspaceTop + ((workspaceBottom - workspaceTop) - scaledHeight) / 2;
-        int overviewOffsetTopEdge = overviewTop + (overviewBottom - overviewTop - scaledHeight) / 2;
-        return new float[] {SCALE_FACTOR, -workspaceOffsetTopEdge + overviewOffsetTopEdge };
+        // TODO: Find a better transition
+        return new float[] {SCALE_FACTOR, 0};
     }
 
     @Override
     public void onStateEnabled(Launcher launcher) {
-        launcher.getWorkspace().setPageRearrangeEnabled(true);
-
-        if (isAccessibilityEnabled(launcher)) {
-            launcher.getOverviewPanel().getChildAt(0).performAccessibilityAction(
-                    AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
-        }
+        ((RecentsView) launcher.getOverviewPanel()).setViewVisible(true);
     }
 
     @Override
     public void onStateDisabled(Launcher launcher) {
-        launcher.getWorkspace().setPageRearrangeEnabled(false);
+        ((RecentsView) launcher.getOverviewPanel()).setViewVisible(false);
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index e43023a..540b200 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -16,6 +16,8 @@
 
 package com.android.launcher3.uioverrides;
 
+import android.view.View.AccessibilityDelegate;
+
 import com.android.launcher3.Launcher;
 import com.android.launcher3.VerticalSwipeController;
 import com.android.launcher3.util.TouchController;
@@ -25,4 +27,8 @@
     public static TouchController[] createTouchControllers(Launcher launcher) {
         return new TouchController[] {new VerticalSwipeController(launcher)};
     }
+
+    public static AccessibilityDelegate newPageIndicatorAccessibilityDelegate() {
+        return null;
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/RecentsView.java b/quickstep/src/com/android/quickstep/RecentsView.java
new file mode 100644
index 0000000..e474ecb
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/RecentsView.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.HorizontalScrollView;
+
+/**
+ * A placeholder view for recents
+ */
+public class RecentsView extends HorizontalScrollView {
+    public RecentsView(Context context) {
+        this(context, null);
+    }
+
+    public RecentsView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public RecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        setAlpha(0);
+    }
+
+    public void setViewVisible(boolean isVisible) { }
+}
diff --git a/res/layout/overview_panel.xml b/res/layout/overview_panel.xml
index d1ac56c..c795b81 100644
--- a/res/layout/overview_panel.xml
+++ b/res/layout/overview_panel.xml
@@ -14,11 +14,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<LinearLayout
+<com.android.launcher3.uioverrides.OverviewPanel
       xmlns:android="http://schemas.android.com/apk/res/android"
-      xmlns:launcher="http://schemas.android.com/apk/res-auto"
       android:theme="@style/HomeScreenElementTheme"
-      launcher:layout_ignoreInsets="true"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_gravity="center_horizontal|bottom"
@@ -73,4 +71,4 @@
         android:textColor="?attr/workspaceTextColor"
         android:textSize="12sp" />
 
-</LinearLayout>
\ No newline at end of file
+</com.android.launcher3.uioverrides.OverviewPanel>
\ No newline at end of file
diff --git a/res/values/config.xml b/res/values/config.xml
index 7a33ae6..54328e1 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -1,8 +1,4 @@
 <resources>
-<!-- Dynamic Grid -->
-    <!-- Out of 100, the percent of space the overview bar should try and take vertically. -->
-    <integer name="config_dynamic_grid_overview_icon_zone_percentage">22</integer>
-
 <!-- Miscellaneous -->
     <bool name="config_largeHeap">false</bool>
     <bool name="is_tablet">false</bool>
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 8aaad13..6030e08 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -65,12 +65,6 @@
 
     private static final float TALL_DEVICE_ASPECT_RATIO_THRESHOLD = 2.0f;
 
-    // Overview mode
-    private final int overviewModeMinIconZoneHeightPx;
-    private final int overviewModeMaxIconZoneHeightPx;
-    private final int overviewModeBarItemWidthPx;
-    private final int overviewModeBarSpacerWidthPx;
-    private final float overviewModeIconZoneRatio;
 
     // Workspace
     private final int desiredWorkspaceLeftRightMarginPx;
@@ -196,16 +190,6 @@
                 res.getDimensionPixelSize(R.dimen.dynamic_grid_workspace_page_spacing);
         topWorkspacePadding =
                 res.getDimensionPixelSize(R.dimen.dynamic_grid_workspace_top_padding);
-        overviewModeMinIconZoneHeightPx =
-                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_min_icon_zone_height);
-        overviewModeMaxIconZoneHeightPx =
-                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_max_icon_zone_height);
-        overviewModeBarItemWidthPx =
-                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_item_width);
-        overviewModeBarSpacerWidthPx =
-                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_spacer_width);
-        overviewModeIconZoneRatio =
-                res.getInteger(R.integer.config_dynamic_grid_overview_icon_zone_percentage) / 100f;
         iconDrawablePaddingOriginalPx =
                 res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
         dropTargetBarSizePx = res.getDimensionPixelSize(R.dimen.dynamic_grid_drop_target_size);
@@ -570,13 +554,6 @@
         }
     }
 
-    public int getOverviewModeButtonBarHeight() {
-        int zoneHeight = (int) (overviewModeIconZoneRatio * availableHeightPx);
-        return Utilities.boundToRange(zoneHeight,
-                overviewModeMinIconZoneHeightPx,
-                overviewModeMaxIconZoneHeightPx);
-    }
-
     public static int calculateCellWidth(int width, int countX) {
         return width / countX;
     }
@@ -597,16 +574,6 @@
         return isVerticalBarLayout() || isLargeTablet;
     }
 
-    private int getVisibleChildCount(ViewGroup parent) {
-        int visibleChildren = 0;
-        for (int i = 0; i < parent.getChildCount(); i++) {
-            if (parent.getChildAt(i).getVisibility() != View.GONE) {
-                visibleChildren++;
-            }
-        }
-        return visibleChildren;
-    }
-
     public void layout(Launcher launcher, boolean notifyListeners) {
         FrameLayout.LayoutParams lp;
         boolean hasVerticalBarLayout = isVerticalBarLayout();
@@ -701,20 +668,6 @@
             pageIndicator.setLayoutParams(lp);
         }
 
-        // Layout the Overview Mode
-        ViewGroup overviewMode = launcher.getOverviewPanel();
-        if (overviewMode != null) {
-            int visibleChildCount = getVisibleChildCount(overviewMode);
-            int totalItemWidth = visibleChildCount * overviewModeBarItemWidthPx;
-            int maxWidth = totalItemWidth + (visibleChildCount - 1) * overviewModeBarSpacerWidthPx;
-
-            lp = (FrameLayout.LayoutParams) overviewMode.getLayoutParams();
-            lp.width = Math.min(availableWidthPx, maxWidth);
-            lp.height = getOverviewModeButtonBarHeight();
-            lp.bottomMargin = mInsets.bottom;
-            overviewMode.setLayoutParams(lp);
-        }
-
         // Layout the AllAppsRecyclerView
         View view = launcher.findViewById(R.id.apps_list_view);
         int paddingLeftRight = desiredWorkspaceLeftRightMarginPx + cellLayoutPaddingLeftRightPx;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 67c0578..75968ae 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -88,7 +88,6 @@
 import android.view.View.OnLongClickListener;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
 import android.view.animation.OvershootInterpolator;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Toast;
@@ -910,7 +909,7 @@
         }
     }
 
-    protected boolean hasSettings() {
+    public boolean hasSettings() {
         if (mLauncherCallbacks != null) {
             return mLauncherCallbacks.hasSettings();
         } else {
@@ -976,32 +975,6 @@
         return handled;
     }
 
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_MENU) {
-            // Ignore the menu key if we are currently dragging or are on the custom content screen
-            if (!mDragController.isDragging()) {
-                // Close any open floating view
-                AbstractFloatingView.closeAllOpenViews(this);
-
-                // Show the overview mode if we are on the workspace
-                if (isInState(NORMAL) && !mWorkspace.isSwitchingState()) {
-                    mStateManager.goToState(OVERVIEW, true /* animate */, new Runnable() {
-                        @Override
-                        public void run() {
-                            // Hitting the menu button when in touch mode does not trigger touch
-                            // mode to be disabled, so if requested, force focus on one of the
-                            // overview panel buttons.
-                            mOverviewPanel.requestFocusFromTouch();
-                        }
-                    });
-                }
-            }
-            return true;
-        }
-        return super.onKeyUp(keyCode, event);
-    }
-
     private String getTypedText() {
         return mDefaultKeySsb.toString();
     }
@@ -1056,6 +1029,7 @@
         mFocusHandler = mDragLayer.getFocusIndicatorHelper();
         mWorkspace = mDragLayer.findViewById(R.id.workspace);
         mWorkspace.initParentViews(mDragLayer);
+        mOverviewPanel = findViewById(R.id.overview_panel);
 
         mLauncherView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
@@ -1070,9 +1044,6 @@
             mHotseat.setOnLongClickListener(this);
         }
 
-        // Setup the overview panel
-        setupOverviewPanel();
-
         // Setup the workspace
         mWorkspace.setHapticFeedbackEnabled(false);
         mWorkspace.setOnLongClickListener(this);
@@ -1097,43 +1068,6 @@
         mAllAppsController.setupViews(mAppsView, mHotseat, mWorkspace);
     }
 
-    private void setupOverviewPanel() {
-        mOverviewPanel = findViewById(R.id.overview_panel);
-
-        // Bind wallpaper button actions
-        View wallpaperButton = findViewById(R.id.wallpaper_button);
-        new OverviewButtonClickListener(ControlType.WALLPAPER_BUTTON) {
-            @Override
-            public void handleViewClick(View view) {
-                onClickWallpaperPicker(view);
-            }
-        }.attachTo(wallpaperButton);
-
-        // Bind widget button actions
-        new OverviewButtonClickListener(ControlType.WIDGETS_BUTTON) {
-            @Override
-            public void handleViewClick(View view) {
-                onClickAddWidgetButton(view);
-            }
-        }.attachTo(findViewById(R.id.widget_button));
-
-        // Bind settings actions
-        View settingsButton = findViewById(R.id.settings_button);
-        boolean hasSettings = hasSettings();
-        if (hasSettings) {
-            new OverviewButtonClickListener(ControlType.SETTINGS_BUTTON) {
-                @Override
-                public void handleViewClick(View view) {
-                    onClickSettingsButton(view);
-                }
-            }.attachTo(settingsButton);
-        } else {
-            settingsButton.setVisibility(View.GONE);
-        }
-
-        mOverviewPanel.setAlpha(0f);
-    }
-
     /**
      * Sets the all apps button. This method is called from {@link Hotseat}.
      * TODO: Get rid of this.
@@ -2119,19 +2053,6 @@
     }
 
     /**
-     * Event handler for the (Add) Widgets button that appears after a long press
-     * on the home screen.
-     */
-    public void onClickAddWidgetButton(View view) {
-        if (LOGD) Log.d(TAG, "onClickAddWidgetButton");
-        if (mIsSafeModeEnabled) {
-            Toast.makeText(this, R.string.safemode_widget_error, Toast.LENGTH_SHORT).show();
-        } else {
-            WidgetsFullSheet.show(this, true /* animated */);
-        }
-    }
-
-    /**
      * Event handler for the wallpaper picker button that appears after a long press
      * on the home screen.
      */
@@ -2164,19 +2085,6 @@
         }
     }
 
-    /**
-     * Event handler for a click on the settings button that appears after a long press
-     * on the home screen.
-     */
-    public void onClickSettingsButton(View v) {
-        if (LOGD) Log.d(TAG, "onClickSettingsButton");
-        Intent intent = new Intent(Intent.ACTION_APPLICATION_PREFERENCES)
-                .setPackage(getPackageName());
-        intent.setSourceBounds(getViewBounds(v));
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        startActivity(intent, getActivityLaunchOptions(v));
-    }
-
     private void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info) {
         try {
             StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 32f96df..daa9bd0 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -61,7 +61,6 @@
 import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener;
 import com.android.launcher3.LauncherStateManager.AnimationConfig;
 import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
-import com.android.launcher3.accessibility.OverviewAccessibilityDelegate;
 import com.android.launcher3.accessibility.OverviewScreenAccessibilityDelegate;
 import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
 import com.android.launcher3.anim.AnimationLayerSet;
@@ -82,6 +81,7 @@
 import com.android.launcher3.popup.PopupContainerWithArrow;
 import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
 import com.android.launcher3.uioverrides.OverviewState;
+import com.android.launcher3.uioverrides.UiFactory;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
@@ -454,7 +454,7 @@
     @Override
     public void initParentViews(View parent) {
         super.initParentViews(parent);
-        mPageIndicator.setAccessibilityDelegate(new OverviewAccessibilityDelegate());
+        mPageIndicator.setAccessibilityDelegate(UiFactory.newPageIndicatorAccessibilityDelegate());
     }
 
     private void setupLayoutTransition() {
diff --git a/src/com/android/launcher3/accessibility/OverviewAccessibilityDelegate.java b/src_ui_overrides/com/android/launcher3/uioverrides/OverviewAccessibilityDelegate.java
similarity index 91%
rename from src/com/android/launcher3/accessibility/OverviewAccessibilityDelegate.java
rename to src_ui_overrides/com/android/launcher3/uioverrides/OverviewAccessibilityDelegate.java
index 771353e..88a1e10 100644
--- a/src/com/android/launcher3/accessibility/OverviewAccessibilityDelegate.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/OverviewAccessibilityDelegate.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.launcher3.accessibility;
+package com.android.launcher3.uioverrides;
 
 import android.content.Context;
 import android.os.Bundle;
@@ -55,6 +55,7 @@
     @Override
     public boolean performAccessibilityAction(View host, int action, Bundle args) {
         Launcher launcher = Launcher.getLauncher(host.getContext());
+        OverviewPanel overviewPanel = launcher.findViewById(R.id.overview_panel);
         if (action == OVERVIEW) {
             launcher.getStateManager().goToState(LauncherState.OVERVIEW);
             return true;
@@ -62,10 +63,10 @@
             launcher.onClickWallpaperPicker(host);
             return true;
         } else if (action == WIDGETS) {
-            launcher.onClickAddWidgetButton(host);
+            overviewPanel.onClickAddWidgetButton();
             return true;
         } else if (action == SETTINGS) {
-            launcher.onClickSettingsButton(host);
+            overviewPanel.onClickSettingsButton(host);
             return true;
         }
         return super.performAccessibilityAction(host, action, args);
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/OverviewPanel.java b/src_ui_overrides/com/android/launcher3/uioverrides/OverviewPanel.java
new file mode 100644
index 0000000..1fb56e7
--- /dev/null
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/OverviewPanel.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.uioverrides;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.Toast;
+
+import com.android.launcher3.Insettable;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
+import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
+import com.android.launcher3.widget.WidgetsFullSheet;
+
+public class OverviewPanel extends LinearLayout implements Insettable, View.OnClickListener,
+        View.OnLongClickListener {
+
+    // Out of 100, the percent of space the overview bar should try and take vertically.
+    private static final float OVERVIEW_ICON_ZONE_RATIO = 0.22f;
+
+    private final Launcher mLauncher;
+
+    public OverviewPanel(Context context) {
+        this(context, null);
+    }
+
+    public OverviewPanel(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public OverviewPanel(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        mLauncher = Launcher.getLauncher(context);
+        setAlpha(0);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        int visibleChildCount = 3;
+        // Attach buttons.
+        attachListeners(findViewById(R.id.wallpaper_button));
+        attachListeners(findViewById(R.id.widget_button));
+
+        View settingsButton = findViewById(R.id.settings_button);
+        if (mLauncher.hasSettings()) {
+            attachListeners(settingsButton);
+        } else {
+            settingsButton.setVisibility(GONE);
+            visibleChildCount--;
+        }
+
+        // Init UI
+        Resources res = getResources();
+        int itemWidthPx =
+                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_item_width);
+        int spacerWidthPx =
+                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_spacer_width);
+
+        int totalItemWidth = visibleChildCount * itemWidthPx;
+        int maxWidth = totalItemWidth + (visibleChildCount - 1) * spacerWidthPx;
+
+        getLayoutParams().width = Math.min(mLauncher.getDeviceProfile().availableWidthPx, maxWidth);
+        getLayoutParams().height = getButtonBarHeight(mLauncher);
+    }
+
+    private void attachListeners(View view) {
+        view.setOnClickListener(this);
+        view.setOnLongClickListener(this);
+    }
+
+    @Override
+    public void setInsets(Rect insets) {
+        ((FrameLayout.LayoutParams) getLayoutParams()).bottomMargin = insets.bottom;
+    }
+
+    @Override
+    public void onClick(View view) {
+        handleViewClick(view, Action.Touch.TAP);
+    }
+
+    @Override
+    public boolean onLongClick(View view) {
+        return handleViewClick(view, Action.Touch.LONGPRESS);
+    }
+
+    private boolean handleViewClick(View view, int action) {
+        if (mLauncher.getWorkspace().isSwitchingState()) {
+            return false;
+        }
+
+        final int controlType;
+        if (view.getId() == R.id.wallpaper_button) {
+            mLauncher.onClickWallpaperPicker(view);
+            controlType = ControlType.WALLPAPER_BUTTON;
+        } else if (view.getId() == R.id.widget_button) {
+            onClickAddWidgetButton();
+            controlType = ControlType.WIDGETS_BUTTON;
+        } else if (view.getId() == R.id.settings_button) {
+            onClickSettingsButton(view);
+            controlType = ControlType.SETTINGS_BUTTON;
+        } else {
+            return false;
+        }
+
+        mLauncher.getUserEventDispatcher().logActionOnControl(action, controlType);
+        return true;
+    }
+
+    /**
+     * Event handler for the (Add) Widgets button that appears after a long press
+     * on the home screen.
+     */
+    public void onClickAddWidgetButton() {
+        if (getContext().getPackageManager().isSafeMode()) {
+            Toast.makeText(mLauncher, R.string.safemode_widget_error, Toast.LENGTH_SHORT).show();
+        } else {
+            WidgetsFullSheet.show(mLauncher, true /* animated */);
+        }
+    }
+
+    /**
+     * Event handler for a click on the settings button that appears after a long press
+     * on the home screen.
+     */
+    public void onClickSettingsButton(View v) {
+        Intent intent = new Intent(Intent.ACTION_APPLICATION_PREFERENCES)
+                .setPackage(getContext().getPackageName());
+        intent.setSourceBounds(mLauncher.getViewBounds(v));
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        getContext().startActivity(intent, mLauncher.getActivityLaunchOptions(v));
+    }
+
+
+    public static int getButtonBarHeight(Launcher launcher) {
+        int zoneHeight = (int) (OVERVIEW_ICON_ZONE_RATIO *
+                launcher.getDeviceProfile().availableWidthPx);
+        Resources res = launcher.getResources();
+        int overviewModeMinIconZoneHeightPx =
+                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_min_icon_zone_height);
+        int overviewModeMaxIconZoneHeightPx =
+                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_max_icon_zone_height);
+        return Utilities.boundToRange(zoneHeight,
+                overviewModeMinIconZoneHeightPx,
+                overviewModeMaxIconZoneHeightPx);
+    }
+}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/OverviewState.java b/src_ui_overrides/com/android/launcher3/uioverrides/OverviewState.java
index 0e7035a..9e2ad98 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/OverviewState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/OverviewState.java
@@ -48,7 +48,7 @@
         Workspace ws = launcher.getWorkspace();
         Rect insets = launcher.getDragLayer().getInsets();
 
-        int overviewButtonBarHeight = grid.getOverviewModeButtonBarHeight();
+        int overviewButtonBarHeight = OverviewPanel.getButtonBarHeight(launcher);
         int scaledHeight = (int) (SCALE_FACTOR * ws.getNormalChildHeight());
         Rect workspacePadding = grid.getWorkspacePadding(null);
         int workspaceTop = insets.top + workspacePadding.top;
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
index e217f70..6776150 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
@@ -16,6 +16,8 @@
 
 package com.android.launcher3.uioverrides;
 
+import android.view.View.AccessibilityDelegate;
+
 import com.android.launcher3.Launcher;
 import com.android.launcher3.VerticalSwipeController;
 import com.android.launcher3.util.TouchController;
@@ -26,4 +28,8 @@
         return new TouchController[] {
                 new VerticalSwipeController(launcher), new PinchToOverviewListener(launcher)};
     }
+
+    public static AccessibilityDelegate newPageIndicatorAccessibilityDelegate() {
+        return new OverviewAccessibilityDelegate();
+    }
 }