Loading packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +10 −1 Original line number Diff line number Diff line Loading @@ -449,12 +449,21 @@ public class PipTaskOrganizer extends TaskOrganizer { * {@link #scheduleResizePip}. */ public void scheduleFinishResizePip(Rect destinationBounds) { scheduleFinishResizePip(destinationBounds, null); } /** * Same as {@link #scheduleFinishResizePip} but with a callback. */ public void scheduleFinishResizePip(Rect destinationBounds, Consumer<Rect> updateBoundsCallback) { final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); mSurfaceTransactionHelper .crop(tx, mLeash, destinationBounds) .resetScale(tx, mLeash, destinationBounds) .round(tx, mLeash, mInPip); scheduleFinishResizePip(tx, destinationBounds, TRANSITION_DIRECTION_NONE, null); scheduleFinishResizePip(tx, destinationBounds, TRANSITION_DIRECTION_NONE, updateBoundsCallback); } private void scheduleFinishResizePip(SurfaceControl.Transaction tx, Loading packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java +92 −26 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.graphics.PointF; import android.graphics.Rect; import android.graphics.Region; import android.hardware.input.InputManager; import android.os.Handler; import android.os.Looper; import android.provider.DeviceConfig; import android.util.DisplayMetrics; Loading @@ -45,6 +46,7 @@ import com.android.systemui.pip.PipTaskOrganizer; import com.android.systemui.util.DeviceConfigProxy; import java.util.concurrent.Executor; import java.util.function.Supplier; /** * Helper on top of PipTouchHandler that handles inputs OUTSIDE of the PIP window, which is used to Loading @@ -66,8 +68,15 @@ public class PipResizeGestureHandler { private final Point mMinSize = new Point(); private final Rect mLastResizeBounds = new Rect(); private final Rect mLastDownBounds = new Rect(); private final Rect mTmpBounds = new Rect(); private final Rect mDragCornerSize = new Rect(); private final Rect mTmpTopLeftCorner = new Rect(); private final Rect mTmpTopRightCorner = new Rect(); private final Rect mTmpBottomLeftCorner = new Rect(); private final Rect mTmpBottomRightCorner = new Rect(); private final Rect mDisplayBounds = new Rect(); private final int mDelta; private final Supplier<Rect> mMovementBoundsSupplier; private final Runnable mUpdateMovementBoundsRunnable; private boolean mAllowGesture; private boolean mIsAttached; Loading @@ -82,7 +91,8 @@ public class PipResizeGestureHandler { public PipResizeGestureHandler(Context context, PipBoundsHandler pipBoundsHandler, PipMotionHelper motionHelper, DeviceConfigProxy deviceConfig, PipTaskOrganizer pipTaskOrganizer) { PipTaskOrganizer pipTaskOrganizer, Supplier<Rect> movementBoundsSupplier, Runnable updateMovementBoundsRunnable) { final Resources res = context.getResources(); context.getDisplay().getMetrics(mDisplayMetrics); mDisplayId = context.getDisplayId(); Loading @@ -90,6 +100,8 @@ public class PipResizeGestureHandler { mPipBoundsHandler = pipBoundsHandler; mMotionHelper = motionHelper; mPipTaskOrganizer = pipTaskOrganizer; mMovementBoundsSupplier = movementBoundsSupplier; mUpdateMovementBoundsRunnable = updateMovementBoundsRunnable; context.getDisplay().getRealSize(mMaxSize); mDelta = res.getDimensionPixelSize(R.dimen.pip_resize_edge_size); Loading @@ -110,6 +122,14 @@ public class PipResizeGestureHandler { }); } private void resetDragCorners() { mDragCornerSize.set(0, 0, mDelta, mDelta); mTmpTopLeftCorner.set(mDragCornerSize); mTmpTopRightCorner.set(mDragCornerSize); mTmpBottomLeftCorner.set(mDragCornerSize); mTmpBottomRightCorner.set(mDragCornerSize); } private void disposeInputChannel() { if (mInputEventReceiver != null) { mInputEventReceiver.dispose(); Loading Loading @@ -154,34 +174,75 @@ public class PipResizeGestureHandler { } } private boolean isWithinTouchRegion(int x, int y) { /** * Check whether the current x,y coordinate is within the region in which drag-resize should * start. * This consists of 4 small squares on the 4 corners of the PIP window, a quarter of which * overlaps with the PIP window while the rest goes outside of the PIP window. * _ _ _ _ * |_|_|_________|_|_| * |_|_| |_|_| * | PIP | * | WINDOW | * _|_ _|_ * |_|_|_________|_|_| * |_|_| |_|_| */ public boolean isWithinTouchRegion(int x, int y) { final Rect currentPipBounds = mMotionHelper.getBounds(); if (currentPipBounds == null) { return false; } resetDragCorners(); mTmpTopLeftCorner.offset(currentPipBounds.left - mDelta / 2, currentPipBounds.top - mDelta / 2); mTmpTopRightCorner.offset(currentPipBounds.right - mDelta / 2, currentPipBounds.top - mDelta / 2); mTmpBottomLeftCorner.offset(currentPipBounds.left - mDelta / 2, currentPipBounds.bottom - mDelta / 2); mTmpBottomRightCorner.offset(currentPipBounds.right - mDelta / 2, currentPipBounds.bottom - mDelta / 2); mTmpBounds.set(currentPipBounds); mTmpBounds.inset(-mDelta, -mDelta); mTmpRegion.setEmpty(); mTmpRegion.op(mTmpTopLeftCorner, Region.Op.UNION); mTmpRegion.op(mTmpTopRightCorner, Region.Op.UNION); mTmpRegion.op(mTmpBottomLeftCorner, Region.Op.UNION); mTmpRegion.op(mTmpBottomRightCorner, Region.Op.UNION); return mTmpRegion.contains(x, y); } private void setCtrlType(int x, int y) { final Rect currentPipBounds = mMotionHelper.getBounds(); mTmpRegion.set(mTmpBounds); mTmpRegion.op(currentPipBounds, Region.Op.DIFFERENCE); Rect movementBounds = mMovementBoundsSupplier.get(); mDisplayBounds.set(movementBounds.left, movementBounds.top, movementBounds.right + currentPipBounds.width(), movementBounds.bottom + currentPipBounds.height()); if (mTmpRegion.contains(x, y)) { if (x < currentPipBounds.left) { if (mTmpTopLeftCorner.contains(x, y) && currentPipBounds.top != mDisplayBounds.top && currentPipBounds.left != mDisplayBounds.left) { mCtrlType |= CTRL_LEFT; mCtrlType |= CTRL_TOP; } if (x > currentPipBounds.right) { if (mTmpTopRightCorner.contains(x, y) && currentPipBounds.top != mDisplayBounds.top && currentPipBounds.right != mDisplayBounds.right) { mCtrlType |= CTRL_RIGHT; } if (y < currentPipBounds.top) { mCtrlType |= CTRL_TOP; } if (y > currentPipBounds.bottom) { if (mTmpBottomRightCorner.contains(x, y) && currentPipBounds.bottom != mDisplayBounds.bottom && currentPipBounds.right != mDisplayBounds.right) { mCtrlType |= CTRL_RIGHT; mCtrlType |= CTRL_BOTTOM; } return true; if (mTmpBottomLeftCorner.contains(x, y) && currentPipBounds.bottom != mDisplayBounds.bottom && currentPipBounds.left != mDisplayBounds.left) { mCtrlType |= CTRL_LEFT; mCtrlType |= CTRL_BOTTOM; } return false; } private void onMotionEvent(MotionEvent ev) { Loading @@ -190,6 +251,7 @@ public class PipResizeGestureHandler { mLastResizeBounds.setEmpty(); mAllowGesture = isWithinTouchRegion((int) ev.getX(), (int) ev.getY()); if (mAllowGesture) { setCtrlType((int) ev.getX(), (int) ev.getY()); mDownPoint.set(ev.getX(), ev.getY()); mLastDownBounds.set(mMotionHelper.getBounds()); } Loading @@ -214,10 +276,14 @@ public class PipResizeGestureHandler { break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds); mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds, (Rect bounds) -> { new Handler(Looper.getMainLooper()).post(() -> { mMotionHelper.synchronizePinnedStackBounds(); mUpdateMovementBoundsRunnable.run(); mCtrlType = CTRL_NONE; mAllowGesture = false; }); }); break; } } Loading packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +11 −1 Original line number Diff line number Diff line Loading @@ -232,7 +232,8 @@ public class PipTouchHandler { mMenuController, mSnapAlgorithm, mFlingAnimationUtils, floatingContentCoordinator); mPipResizeGestureHandler = new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper, deviceConfig, pipTaskOrganizer); deviceConfig, pipTaskOrganizer, this::getMovementBounds, this::updateMovementBounds); mTouchState = new PipTouchState(ViewConfiguration.get(context), mHandler, () -> mMenuController.showMenuWithDelay(MENU_STATE_FULL, mMotionHelper.getBounds(), true /* allowMenuTimeout */, willResizeMenu())); Loading Loading @@ -572,6 +573,11 @@ public class PipTouchHandler { MotionEvent ev = (MotionEvent) inputEvent; if (mPipResizeGestureHandler.isWithinTouchRegion((int) ev.getX(), (int) ev.getY())) { return true; } if (mMagnetizedPip.maybeConsumeMotionEvent(ev)) { // If the first touch event occurs within the magnetic field, pass the ACTION_DOWN event // to the touch state. Touch state needs a DOWN event in order to later process MOVE Loading Loading @@ -937,6 +943,10 @@ public class PipTouchHandler { isMenuExpanded && willResizeMenu() ? mExpandedShortestEdgeSize : 0); } private Rect getMovementBounds() { return mMovementBounds; } /** * @return whether the menu will resize as a part of showing the full menu. */ Loading Loading
packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +10 −1 Original line number Diff line number Diff line Loading @@ -449,12 +449,21 @@ public class PipTaskOrganizer extends TaskOrganizer { * {@link #scheduleResizePip}. */ public void scheduleFinishResizePip(Rect destinationBounds) { scheduleFinishResizePip(destinationBounds, null); } /** * Same as {@link #scheduleFinishResizePip} but with a callback. */ public void scheduleFinishResizePip(Rect destinationBounds, Consumer<Rect> updateBoundsCallback) { final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); mSurfaceTransactionHelper .crop(tx, mLeash, destinationBounds) .resetScale(tx, mLeash, destinationBounds) .round(tx, mLeash, mInPip); scheduleFinishResizePip(tx, destinationBounds, TRANSITION_DIRECTION_NONE, null); scheduleFinishResizePip(tx, destinationBounds, TRANSITION_DIRECTION_NONE, updateBoundsCallback); } private void scheduleFinishResizePip(SurfaceControl.Transaction tx, Loading
packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java +92 −26 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.graphics.PointF; import android.graphics.Rect; import android.graphics.Region; import android.hardware.input.InputManager; import android.os.Handler; import android.os.Looper; import android.provider.DeviceConfig; import android.util.DisplayMetrics; Loading @@ -45,6 +46,7 @@ import com.android.systemui.pip.PipTaskOrganizer; import com.android.systemui.util.DeviceConfigProxy; import java.util.concurrent.Executor; import java.util.function.Supplier; /** * Helper on top of PipTouchHandler that handles inputs OUTSIDE of the PIP window, which is used to Loading @@ -66,8 +68,15 @@ public class PipResizeGestureHandler { private final Point mMinSize = new Point(); private final Rect mLastResizeBounds = new Rect(); private final Rect mLastDownBounds = new Rect(); private final Rect mTmpBounds = new Rect(); private final Rect mDragCornerSize = new Rect(); private final Rect mTmpTopLeftCorner = new Rect(); private final Rect mTmpTopRightCorner = new Rect(); private final Rect mTmpBottomLeftCorner = new Rect(); private final Rect mTmpBottomRightCorner = new Rect(); private final Rect mDisplayBounds = new Rect(); private final int mDelta; private final Supplier<Rect> mMovementBoundsSupplier; private final Runnable mUpdateMovementBoundsRunnable; private boolean mAllowGesture; private boolean mIsAttached; Loading @@ -82,7 +91,8 @@ public class PipResizeGestureHandler { public PipResizeGestureHandler(Context context, PipBoundsHandler pipBoundsHandler, PipMotionHelper motionHelper, DeviceConfigProxy deviceConfig, PipTaskOrganizer pipTaskOrganizer) { PipTaskOrganizer pipTaskOrganizer, Supplier<Rect> movementBoundsSupplier, Runnable updateMovementBoundsRunnable) { final Resources res = context.getResources(); context.getDisplay().getMetrics(mDisplayMetrics); mDisplayId = context.getDisplayId(); Loading @@ -90,6 +100,8 @@ public class PipResizeGestureHandler { mPipBoundsHandler = pipBoundsHandler; mMotionHelper = motionHelper; mPipTaskOrganizer = pipTaskOrganizer; mMovementBoundsSupplier = movementBoundsSupplier; mUpdateMovementBoundsRunnable = updateMovementBoundsRunnable; context.getDisplay().getRealSize(mMaxSize); mDelta = res.getDimensionPixelSize(R.dimen.pip_resize_edge_size); Loading @@ -110,6 +122,14 @@ public class PipResizeGestureHandler { }); } private void resetDragCorners() { mDragCornerSize.set(0, 0, mDelta, mDelta); mTmpTopLeftCorner.set(mDragCornerSize); mTmpTopRightCorner.set(mDragCornerSize); mTmpBottomLeftCorner.set(mDragCornerSize); mTmpBottomRightCorner.set(mDragCornerSize); } private void disposeInputChannel() { if (mInputEventReceiver != null) { mInputEventReceiver.dispose(); Loading Loading @@ -154,34 +174,75 @@ public class PipResizeGestureHandler { } } private boolean isWithinTouchRegion(int x, int y) { /** * Check whether the current x,y coordinate is within the region in which drag-resize should * start. * This consists of 4 small squares on the 4 corners of the PIP window, a quarter of which * overlaps with the PIP window while the rest goes outside of the PIP window. * _ _ _ _ * |_|_|_________|_|_| * |_|_| |_|_| * | PIP | * | WINDOW | * _|_ _|_ * |_|_|_________|_|_| * |_|_| |_|_| */ public boolean isWithinTouchRegion(int x, int y) { final Rect currentPipBounds = mMotionHelper.getBounds(); if (currentPipBounds == null) { return false; } resetDragCorners(); mTmpTopLeftCorner.offset(currentPipBounds.left - mDelta / 2, currentPipBounds.top - mDelta / 2); mTmpTopRightCorner.offset(currentPipBounds.right - mDelta / 2, currentPipBounds.top - mDelta / 2); mTmpBottomLeftCorner.offset(currentPipBounds.left - mDelta / 2, currentPipBounds.bottom - mDelta / 2); mTmpBottomRightCorner.offset(currentPipBounds.right - mDelta / 2, currentPipBounds.bottom - mDelta / 2); mTmpBounds.set(currentPipBounds); mTmpBounds.inset(-mDelta, -mDelta); mTmpRegion.setEmpty(); mTmpRegion.op(mTmpTopLeftCorner, Region.Op.UNION); mTmpRegion.op(mTmpTopRightCorner, Region.Op.UNION); mTmpRegion.op(mTmpBottomLeftCorner, Region.Op.UNION); mTmpRegion.op(mTmpBottomRightCorner, Region.Op.UNION); return mTmpRegion.contains(x, y); } private void setCtrlType(int x, int y) { final Rect currentPipBounds = mMotionHelper.getBounds(); mTmpRegion.set(mTmpBounds); mTmpRegion.op(currentPipBounds, Region.Op.DIFFERENCE); Rect movementBounds = mMovementBoundsSupplier.get(); mDisplayBounds.set(movementBounds.left, movementBounds.top, movementBounds.right + currentPipBounds.width(), movementBounds.bottom + currentPipBounds.height()); if (mTmpRegion.contains(x, y)) { if (x < currentPipBounds.left) { if (mTmpTopLeftCorner.contains(x, y) && currentPipBounds.top != mDisplayBounds.top && currentPipBounds.left != mDisplayBounds.left) { mCtrlType |= CTRL_LEFT; mCtrlType |= CTRL_TOP; } if (x > currentPipBounds.right) { if (mTmpTopRightCorner.contains(x, y) && currentPipBounds.top != mDisplayBounds.top && currentPipBounds.right != mDisplayBounds.right) { mCtrlType |= CTRL_RIGHT; } if (y < currentPipBounds.top) { mCtrlType |= CTRL_TOP; } if (y > currentPipBounds.bottom) { if (mTmpBottomRightCorner.contains(x, y) && currentPipBounds.bottom != mDisplayBounds.bottom && currentPipBounds.right != mDisplayBounds.right) { mCtrlType |= CTRL_RIGHT; mCtrlType |= CTRL_BOTTOM; } return true; if (mTmpBottomLeftCorner.contains(x, y) && currentPipBounds.bottom != mDisplayBounds.bottom && currentPipBounds.left != mDisplayBounds.left) { mCtrlType |= CTRL_LEFT; mCtrlType |= CTRL_BOTTOM; } return false; } private void onMotionEvent(MotionEvent ev) { Loading @@ -190,6 +251,7 @@ public class PipResizeGestureHandler { mLastResizeBounds.setEmpty(); mAllowGesture = isWithinTouchRegion((int) ev.getX(), (int) ev.getY()); if (mAllowGesture) { setCtrlType((int) ev.getX(), (int) ev.getY()); mDownPoint.set(ev.getX(), ev.getY()); mLastDownBounds.set(mMotionHelper.getBounds()); } Loading @@ -214,10 +276,14 @@ public class PipResizeGestureHandler { break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds); mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds, (Rect bounds) -> { new Handler(Looper.getMainLooper()).post(() -> { mMotionHelper.synchronizePinnedStackBounds(); mUpdateMovementBoundsRunnable.run(); mCtrlType = CTRL_NONE; mAllowGesture = false; }); }); break; } } Loading
packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +11 −1 Original line number Diff line number Diff line Loading @@ -232,7 +232,8 @@ public class PipTouchHandler { mMenuController, mSnapAlgorithm, mFlingAnimationUtils, floatingContentCoordinator); mPipResizeGestureHandler = new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper, deviceConfig, pipTaskOrganizer); deviceConfig, pipTaskOrganizer, this::getMovementBounds, this::updateMovementBounds); mTouchState = new PipTouchState(ViewConfiguration.get(context), mHandler, () -> mMenuController.showMenuWithDelay(MENU_STATE_FULL, mMotionHelper.getBounds(), true /* allowMenuTimeout */, willResizeMenu())); Loading Loading @@ -572,6 +573,11 @@ public class PipTouchHandler { MotionEvent ev = (MotionEvent) inputEvent; if (mPipResizeGestureHandler.isWithinTouchRegion((int) ev.getX(), (int) ev.getY())) { return true; } if (mMagnetizedPip.maybeConsumeMotionEvent(ev)) { // If the first touch event occurs within the magnetic field, pass the ACTION_DOWN event // to the touch state. Touch state needs a DOWN event in order to later process MOVE Loading Loading @@ -937,6 +943,10 @@ public class PipTouchHandler { isMenuExpanded && willResizeMenu() ? mExpandedShortestEdgeSize : 0); } private Rect getMovementBounds() { return mMovementBounds; } /** * @return whether the menu will resize as a part of showing the full menu. */ Loading