First pass of the Launcher Overlay interface / impl

-> Added simple reference launcher extension
-> Make launcher able to handle a null qsb

Change-Id: Ib1575243cac800a335e95bbf00cdc394bb4741c3
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 48fc0c9..7d65f46 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -204,6 +204,8 @@
 
     protected boolean mAllowLongPress = true;
 
+    private boolean mWasInOverscroll = false;
+
     // Page Indicator
     private int mPageIndicatorViewId;
     private PageIndicator mPageIndicator;
@@ -625,6 +627,7 @@
 
     // a method that subclasses can override to add behavior
     protected void onPageEndMoving() {
+        mWasInOverscroll = false;
     }
 
     /**
@@ -663,6 +666,7 @@
         if (isXBeforeFirstPage) {
             super.scrollTo(0, y);
             if (mAllowOverScroll) {
+                mWasInOverscroll = true;
                 if (isRtl) {
                     overScroll(x - mMaxScrollX);
                 } else {
@@ -672,6 +676,7 @@
         } else if (isXAfterLastPage) {
             super.scrollTo(mMaxScrollX, y);
             if (mAllowOverScroll) {
+                mWasInOverscroll = true;
                 if (isRtl) {
                     overScroll(x);
                 } else {
@@ -679,6 +684,10 @@
                 }
             }
         } else {
+            if (mWasInOverscroll) {
+                overScroll(0);
+                mWasInOverscroll = false;
+            }
             mOverScrollX = x;
             super.scrollTo(x, y);
         }
@@ -1513,6 +1522,7 @@
                 mLastMotionXRemainder = 0;
                 mTouchX = getViewportOffsetX() + getScrollX();
                 mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+                onScrollInteractionBegin();
                 pageBeginMoving();
             }
         }
@@ -1752,6 +1762,7 @@
             mActivePointerId = ev.getPointerId(0);
 
             if (mTouchState == TOUCH_STATE_SCROLLING) {
+                onScrollInteractionBegin();
                 pageBeginMoving();
             }
             break;
@@ -1940,6 +1951,7 @@
                             getScrollY(), vX, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0);
                     invalidate();
                 }
+                onScrollInteractionEnd();
             } else if (mTouchState == TOUCH_STATE_PREV_PAGE) {
                 // at this point we have not moved beyond the touch slop
                 // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
@@ -2025,6 +2037,15 @@
         mActivePointerId = INVALID_POINTER;
     }
 
+    /**
+     * Triggered by scrolling via touch
+     */
+    protected void onScrollInteractionBegin() {
+    }
+
+    protected void onScrollInteractionEnd() {
+    }
+
     protected void onUnhandledTap(MotionEvent ev) {
         ((Launcher) getContext()).onClick(this);
     }