OSDN Git Service

Add back button for freeform window
[android-x86/frameworks-base.git] / core / java / com / android / internal / widget / DecorCaptionView.java
index fc68b84..f4763f6 100644 (file)
@@ -16,6 +16,7 @@
 
 package com.android.internal.widget;
 
+import android.app.Activity;
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.Rect;
@@ -46,7 +47,7 @@ import java.util.ArrayList;
  * After creating the view, the function {@link #setPhoneWindow} needs to be called to make
  * the connection to it's owning PhoneWindow.
  * Note: At this time the application can change various attributes of the DecorView which
- * will break things (in settle/unexpected ways):
+ * will break things (in subtle/unexpected ways):
  * <ul>
  * <li>setOutlineProvider</li>
  * <li>setSurfaceFormat</li>
@@ -82,13 +83,12 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
     // True if the window is being dragged.
     private boolean mDragging = false;
 
-    // True when the left mouse button got released while dragging.
-    private boolean mLeftMouseButtonReleased;
-
     private boolean mOverlayWithAppContent = false;
 
     private View mCaption;
     private View mContent;
+    private View mPip;
+    private View mMinimize;
     private View mMaximize;
     private View mClose;
 
@@ -105,7 +105,13 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
     private GestureDetector mGestureDetector;
     private final Rect mCloseRect = new Rect();
     private final Rect mMaximizeRect = new Rect();
+    private final Rect mMinimizeRect = new Rect();
+    private final Rect mPipRect = new Rect();
     private View mClickTarget;
+    // region @boringdroid
+    private View mBack;
+    private final Rect mBackRect = new Rect();
+    // endregion
 
     public DecorCaptionView(Context context) {
         super(context);
@@ -146,6 +152,11 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
         // By changing the outline provider to BOUNDS, the window can remove its
         // background without removing the shadow.
         mOwner.getDecorView().setOutlineProvider(ViewOutlineProvider.BOUNDS);
+        // region @boringdroid
+        mBack = findViewById(R.id.back_window);
+        // endregion
+        mPip = findViewById(R.id.pip_window);
+        mMinimize = findViewById(R.id.minimize_window);
         mMaximize = findViewById(R.id.maximize_window);
         mClose = findViewById(R.id.close_window);
     }
@@ -157,6 +168,18 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
             final int x = (int) ev.getX();
             final int y = (int) ev.getY();
+            // region @boringdroid
+            if (mBackRect.contains(x, y)) {
+                mClickTarget = mBack;
+            }
+            // endregion
+            // Only offset y for containment tests because the actual views are already translated.
+            if (mPipRect.contains(x, y)) {
+                mClickTarget = mPip;
+            }
+            if (mMinimizeRect.contains(x, y)) {
+                mClickTarget = mMinimize;
+            }
             if (mMaximizeRect.contains(x, y)) {
                 mClickTarget = mMaximize;
             }
@@ -187,6 +210,8 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
         // input device we are listening to.
         final int x = (int) e.getX();
         final int y = (int) e.getY();
+        final boolean fromMouse = e.getToolType(e.getActionIndex()) == MotionEvent.TOOL_TYPE_MOUSE;
+        final boolean primaryButton = (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0;
         switch (e.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
                 if (!mShow) {
@@ -195,8 +220,7 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
                 }
                 // Checking for a drag action is started if we aren't dragging already and the
                 // starting event is either a left mouse button or any other input device.
-                if (((e.getToolType(e.getActionIndex()) != MotionEvent.TOOL_TYPE_MOUSE ||
-                        (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0))) {
+                if (!fromMouse || primaryButton) {
                     mCheckForDragging = true;
                     mTouchDownX = x;
                     mTouchDownY = y;
@@ -204,19 +228,13 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
                 break;
 
             case MotionEvent.ACTION_MOVE:
-                if (!mDragging && mCheckForDragging && passedSlop(x, y)) {
+                if (!mDragging && mCheckForDragging && (fromMouse || passedSlop(x, y))) {
                     mCheckForDragging = false;
                     mDragging = true;
-                    mLeftMouseButtonReleased = false;
                     startMovingTask(e.getRawX(), e.getRawY());
-                } else if (mDragging && !mLeftMouseButtonReleased) {
-                    if (e.getToolType(e.getActionIndex()) == MotionEvent.TOOL_TYPE_MOUSE &&
-                            (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) == 0) {
-                        // There is no separate mouse button up call and if the user mixes mouse
-                        // button drag actions, we stop dragging once he releases the button.
-                        mLeftMouseButtonReleased = true;
-                        break;
-                    }
+                    // After the above call the framework will take over the input.
+                    // This handler will receive ACTION_CANCEL soon (possible after a few spurious
+                    // ACTION_MOVE events which are safe to ignore).
                 }
                 break;
 
@@ -306,10 +324,20 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
         if (mCaption.getVisibility() != View.GONE) {
             mCaption.layout(0, 0, mCaption.getMeasuredWidth(), mCaption.getMeasuredHeight());
             captionHeight = mCaption.getBottom() - mCaption.getTop();
+            // region @boringdroid
+            mBack.getHitRect(mBackRect);
+            // endregion
+            mPip.getHitRect(mPipRect);
+            mMinimize.getHitRect(mMinimizeRect);
             mMaximize.getHitRect(mMaximizeRect);
             mClose.getHitRect(mCloseRect);
         } else {
             captionHeight = 0;
+            // region @boringdroid
+            mBackRect.setEmpty();
+            // endregion
+            mPipRect.setEmpty();
+            mMinimizeRect.setEmpty();
             mMaximizeRect.setEmpty();
             mCloseRect.setEmpty();
         }
@@ -324,8 +352,12 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
         }
 
         // This assumes that the caption bar is at the top.
-        mOwner.notifyRestrictedCaptionAreaCallback(mMaximize.getLeft(), mMaximize.getTop(),
+        // region @boringdroid
+        // mOwner.notifyRestrictedCaptionAreaCallback(mPip.getLeft(), mMaximize.getTop(),
+        //         mClose.getRight(), mClose.getBottom());
+        mOwner.notifyRestrictedCaptionAreaCallback(mBack.getLeft(), mBack.getTop(),
                 mClose.getRight(), mClose.getBottom());
+        // endregion
     }
     /**
      * Determine if the workspace is entirely covered by the window.
@@ -361,6 +393,20 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
         }
     }
 
+    private void minimizeWindow() {
+        Window.WindowControllerCallback callback = mOwner.getWindowControllerCallback();
+        if (callback != null) {
+            callback.moveTaskToBack(true);
+               }
+    }
+
+    private void pipWindow() {
+        Window.WindowControllerCallback callback = mOwner.getWindowControllerCallback();
+        if (callback != null) {
+                       callback.enterPictureInPictureModeIfPossible(); /* Send the task to PIP mode if the task supports it. */
+               }
+    }
+
     public boolean isCaptionShowing() {
         return mShow;
     }
@@ -413,10 +459,25 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
 
     @Override
     public boolean onSingleTapUp(MotionEvent e) {
-        if (mClickTarget == mMaximize) {
+        // region @boringdroid
+        if (mClickTarget == mBack) {
+            Window.WindowControllerCallback callback = mOwner.getWindowControllerCallback();
+            if (callback instanceof Activity) {
+                Activity activity = (Activity) callback;
+                activity.onBackPressed();
+            }
+            return true;
+        }
+        // endregion
+        if (mClickTarget == mMinimize) {
+            minimizeWindow();
+        } else if (mClickTarget == mPip) {
+            pipWindow();
+        } else if (mClickTarget == mMaximize) {
             maximizeWindow();
         } else if (mClickTarget == mClose) {
-            mOwner.dispatchOnWindowDismissed(true /*finishTask*/);
+            mOwner.dispatchOnWindowDismissed(
+                    true /*finishTask*/, false /*suppressWindowTransition*/);
         }
         return true;
     }