Resizing docked stack by dragging dock divider.

Change-Id: Icc9df00446780f8cd81df4654ace07f33346e901
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index ad207d4..8c5d319 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.ActivityManager.DOCKED_STACK_ID;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -23,11 +24,19 @@
 import static android.view.WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING;
 import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+import static com.android.server.wm.TaskStack.DOCKED_BOTTOM;
+import static com.android.server.wm.TaskStack.DOCKED_INVALID;
+import static com.android.server.wm.TaskStack.DOCKED_LEFT;
+import static com.android.server.wm.TaskStack.DOCKED_RIGHT;
+import static com.android.server.wm.TaskStack.DOCKED_TOP;
 
 import android.content.Context;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
+import android.os.RemoteException;
+import android.util.Slog;
 import android.view.LayoutInflater;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
@@ -35,13 +44,20 @@
 /**
  * Controls showing and hiding of a docked stack divider on the display.
  */
-public class DockedStackDividerController {
+public class DockedStackDividerController implements View.OnTouchListener {
     private static final String TAG = "DockedStackDivider";
     private final Context mContext;
     private final int mDividerWidth;
     private final DisplayContent mDisplayContent;
     private View mView;
     private Rect mTmpRect = new Rect();
+    private Rect mLastResizeRect = new Rect();
+    private int mStartX;
+    private int mStartY;
+    private TaskStack mTaskStack;
+    private Rect mOriginalRect = new Rect();
+    private int mDockSide;
+
 
     DockedStackDividerController(Context context, DisplayContent displayContent) {
         mContext = context;
@@ -53,6 +69,7 @@
     private void addDivider() {
         View view = LayoutInflater.from(mContext).inflate(
                 com.android.internal.R.layout.docked_stack_divider, null);
+        view.setOnTouchListener(this);
         WindowManagerGlobal manager = WindowManagerGlobal.getInstance();
         WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                 mDividerWidth, MATCH_PARENT, TYPE_DOCK_DIVIDER,
@@ -65,6 +82,7 @@
     }
 
     private void removeDivider() {
+        mView.setOnTouchListener(null);
         WindowManagerGlobal manager = WindowManagerGlobal.getInstance();
         manager.removeView(mView, true /* immediate */);
         mView = null;
@@ -75,7 +93,7 @@
     }
 
     void update() {
-        TaskStack stack = mDisplayContent.getDockedStack();
+        TaskStack stack = mDisplayContent.getDockedStackLocked();
         if (stack != null && mView == null) {
             addDivider();
         } else if (stack == null && mView != null) {
@@ -87,9 +105,8 @@
         return mDividerWidth;
     }
 
-
     void positionDockedStackedDivider(Rect frame) {
-        TaskStack stack = mDisplayContent.getDockedStack();
+        TaskStack stack = mDisplayContent.getDockedStackLocked();
         if (stack == null) {
             // Unfortunately we might end up with still having a divider, even though the underlying
             // stack was already removed. This is because we are on AM thread and the removal of the
@@ -99,19 +116,84 @@
         final @TaskStack.DockSide int side = stack.getDockSide();
         stack.getBounds(mTmpRect);
         switch (side) {
-            case TaskStack.DOCKED_LEFT:
+            case DOCKED_LEFT:
                 frame.set(mTmpRect.right, frame.top, mTmpRect.right + frame.width(), frame.bottom);
                 break;
-            case TaskStack.DOCKED_TOP:
+            case DOCKED_TOP:
                 frame.set(frame.left, mTmpRect.bottom, mTmpRect.right,
                         mTmpRect.bottom + frame.height());
                 break;
-            case TaskStack.DOCKED_RIGHT:
+            case DOCKED_RIGHT:
                 frame.set(mTmpRect.left - frame.width(), frame.top, mTmpRect.left, frame.bottom);
                 break;
-            case TaskStack.DOCKED_BOTTOM:
+            case DOCKED_BOTTOM:
                 frame.set(frame.left, mTmpRect.top - frame.height(), frame.right, mTmpRect.top);
                 break;
         }
     }
+
+    @Override
+    public boolean onTouch(View v, MotionEvent event) {
+        final int action = event.getAction() & MotionEvent.ACTION_MASK;
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                // We use raw values, because getX/Y() would give us results relative to the
+                // dock divider bounds.
+                mStartX = (int) event.getRawX();
+                mStartY = (int) event.getRawY();
+                synchronized (mDisplayContent.mService.mWindowMap) {
+                    mTaskStack = mDisplayContent.getDockedStackLocked();
+                    mTaskStack.getBounds(mOriginalRect);
+                    mDockSide = mTaskStack.getDockSide();
+                }
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (mTaskStack != null) {
+                    resizeStack(event);
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                mTaskStack = null;
+                mDockSide = TaskStack.DOCKED_INVALID;
+                break;
+        }
+        return true;
+    }
+
+    private void resizeStack(MotionEvent event) {
+        mTmpRect.set(mOriginalRect);
+        final int deltaX = (int) event.getRawX() - mStartX;
+        final int deltaY = (int) event.getRawY() - mStartY;
+        switch (mDockSide) {
+            case DOCKED_LEFT:
+                mTmpRect.right += deltaX;
+                break;
+            case DOCKED_TOP:
+                mTmpRect.bottom += deltaY;
+                break;
+            case DOCKED_RIGHT:
+                mTmpRect.left += deltaX;
+                break;
+            case DOCKED_BOTTOM:
+                mTmpRect.top += deltaY;
+                break;
+        }
+        if (mTmpRect.equals(mLastResizeRect)) {
+            return;
+        }
+        mLastResizeRect.set(mTmpRect);
+        try {
+            mDisplayContent.mService.mActivityManager.resizeStack(DOCKED_STACK_ID, mTmpRect);
+        } catch (RemoteException e) {
+        }
+    }
+
+    boolean isResizing() {
+        return mTaskStack != null;
+    }
+
+    int getWidthAdjustment() {
+        return getWidth() / 2;
+    }
 }