Loading core/java/com/android/internal/policy/PipSnapAlgorithm.java +16 −0 Original line number Original line Diff line number Diff line Loading @@ -41,8 +41,12 @@ public class PipSnapAlgorithm { // Allows snapping to anywhere along the edge of the screen // Allows snapping to anywhere along the edge of the screen private static final int SNAP_MODE_EDGE = 2; private static final int SNAP_MODE_EDGE = 2; // The friction multiplier to control how slippery the PIP is when flung private static final float SCROLL_FRICTION_MULTIPLIER = 8f; private static final float SCROLL_FRICTION_MULTIPLIER = 8f; // The fraction of the stack width to show when minimized private static final float MINIMIZED_VISIBLE_FRACTION = 0.25f; private final Context mContext; private final Context mContext; private final ArrayList<Integer> mSnapGravities = new ArrayList<>(); private final ArrayList<Integer> mSnapGravities = new ArrayList<>(); Loading Loading @@ -121,6 +125,18 @@ public class PipSnapAlgorithm { return newBounds; return newBounds; } } /** * Applies the offset to the {@param stackBounds} to adjust it to a minimized state. */ public void applyMinimizedOffset(Rect stackBounds, Rect movementBounds, Point displaySize) { int visibleWidth = (int) (MINIMIZED_VISIBLE_FRACTION * stackBounds.width()); if (stackBounds.left <= movementBounds.centerX()) { stackBounds.offsetTo(-stackBounds.width() + visibleWidth, stackBounds.top); } else { stackBounds.offsetTo(displaySize.x - visibleWidth, stackBounds.top); } } /** /** * @return returns a fraction that describes where along the {@param movementBounds} the * @return returns a fraction that describes where along the {@param movementBounds} the * {@param stackBounds} are. If the {@param stackBounds} are not currently on the * {@param stackBounds} are. If the {@param stackBounds} are not currently on the Loading core/res/res/values/config.xml +2 −2 Original line number Original line Diff line number Diff line Loading @@ -2492,11 +2492,11 @@ <!-- Default insets [LEFT/RIGHTxTOP/BOTTOM] from the screen edge for picture-in-picture windows. <!-- Default insets [LEFT/RIGHTxTOP/BOTTOM] from the screen edge for picture-in-picture windows. These values are in DPs and will be converted to pixel sizes internally. --> These values are in DPs and will be converted to pixel sizes internally. --> <string translatable="false" name="config_defaultPictureInPictureScreenEdgeInsets">10x10</string> <string translatable="false" name="config_defaultPictureInPictureScreenEdgeInsets">8x8</string> <!-- Max default size [WIDTHxHEIGHT] on screen for picture-in-picture windows to fit inside. <!-- Max default size [WIDTHxHEIGHT] on screen for picture-in-picture windows to fit inside. These values are in DPs and will be converted to pixel sizes internally. --> These values are in DPs and will be converted to pixel sizes internally. --> <string translatable="false" name="config_defaultPictureInPictureSize">216x135</string> <string translatable="false" name="config_defaultPictureInPictureSize">192x120</string> <!-- The default gravity for the picture-in-picture window. <!-- The default gravity for the picture-in-picture window. Currently, this maps to Gravity.BOTTOM | Gravity.RIGHT --> Currently, this maps to Gravity.BOTTOM | Gravity.RIGHT --> Loading packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +13 −12 Original line number Original line Diff line number Diff line Loading @@ -71,8 +71,6 @@ public class PipTouchHandler implements TunerService.Tunable { private static final int EXPAND_STACK_DURATION = 225; private static final int EXPAND_STACK_DURATION = 225; private static final int MINIMIZE_STACK_MAX_DURATION = 200; private static final int MINIMIZE_STACK_MAX_DURATION = 200; // The fraction of the stack width to show when minimized private static final float MINIMIZED_VISIBLE_FRACTION = 0.25f; // The fraction of the stack width that the user has to drag offscreen to minimize the PIP // The fraction of the stack width that the user has to drag offscreen to minimize the PIP private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.15f; private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.15f; // The fraction of the stack width that the user has to move when flinging to dismiss the PIP // The fraction of the stack width that the user has to move when flinging to dismiss the PIP Loading Loading @@ -396,6 +394,8 @@ public class PipTouchHandler implements TunerService.Tunable { * Flings the minimized PIP to the closest minimized snap target. * Flings the minimized PIP to the closest minimized snap target. */ */ private void flingToMinimizedSnapTarget(float velocityY) { private void flingToMinimizedSnapTarget(float velocityY) { // We currently only allow flinging the minimized stack up and down, so just lock the // movement bounds to the current stack bounds horizontally Rect movementBounds = new Rect(mPinnedStackBounds.left, mBoundedPinnedStackBounds.top, Rect movementBounds = new Rect(mPinnedStackBounds.left, mBoundedPinnedStackBounds.top, mPinnedStackBounds.left, mBoundedPinnedStackBounds.bottom); mPinnedStackBounds.left, mBoundedPinnedStackBounds.bottom); Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mPinnedStackBounds, Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mPinnedStackBounds, Loading @@ -414,16 +414,11 @@ public class PipTouchHandler implements TunerService.Tunable { * Animates the PIP to the minimized state, slightly offscreen. * Animates the PIP to the minimized state, slightly offscreen. */ */ private void animateToClosestMinimizedTarget() { private void animateToClosestMinimizedTarget() { Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(mBoundedPinnedStackBounds, mPinnedStackBounds); Point displaySize = new Point(); Point displaySize = new Point(); mContext.getDisplay().getRealSize(displaySize); mContext.getDisplay().getRealSize(displaySize); int visibleWidth = (int) (MINIMIZED_VISIBLE_FRACTION * mPinnedStackBounds.width()); Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(mBoundedPinnedStackBounds, if (mPinnedStackBounds.left < 0) { mPinnedStackBounds); toBounds.offsetTo(-toBounds.width() + visibleWidth, toBounds.top); mSnapAlgorithm.applyMinimizedOffset(toBounds, mBoundedPinnedStackBounds, displaySize); } else if (mPinnedStackBounds.right > displaySize.x) { toBounds.offsetTo(displaySize.x - visibleWidth, toBounds.top); } mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds, mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds, toBounds, MINIMIZE_STACK_MAX_DURATION, LINEAR_OUT_SLOW_IN, toBounds, MINIMIZE_STACK_MAX_DURATION, LINEAR_OUT_SLOW_IN, mUpdatePinnedStackBoundsListener); mUpdatePinnedStackBoundsListener); Loading Loading @@ -635,7 +630,7 @@ public class PipTouchHandler implements TunerService.Tunable { setMinimizedState(false); setMinimizedState(false); } } if (isDraggingOffscreen) { if (touchState.allowDraggingOffscreen() && isDraggingOffscreen) { // Move the pinned stack, but ignore the vertical movement // Move the pinned stack, but ignore the vertical movement float left = mPinnedStackBounds.left + touchState.getLastTouchDelta().x; float left = mPinnedStackBounds.left + touchState.getLastTouchDelta().x; mTmpBounds.set(mPinnedStackBounds); mTmpBounds.set(mPinnedStackBounds); Loading Loading @@ -685,7 +680,7 @@ public class PipTouchHandler implements TunerService.Tunable { setMinimizedState(false); setMinimizedState(false); } } if (isDraggingOffscreen) { if (touchState.allowDraggingOffscreen() && isDraggingOffscreen) { // Move the pinned stack, but ignore the vertical movement // Move the pinned stack, but ignore the vertical movement float left = mPinnedStackBounds.left + touchState.getLastTouchDelta().x; float left = mPinnedStackBounds.left + touchState.getLastTouchDelta().x; mTmpBounds.set(mPinnedStackBounds); mTmpBounds.set(mPinnedStackBounds); Loading Loading @@ -769,6 +764,12 @@ public class PipTouchHandler implements TunerService.Tunable { private PipTouchGesture mDefaultMovementGesture = new PipTouchGesture() { private PipTouchGesture mDefaultMovementGesture = new PipTouchGesture() { @Override @Override boolean onMove(PipTouchState touchState) { boolean onMove(PipTouchState touchState) { if (touchState.startedDragging()) { // For now, once the user has started a drag that the other gestures have not // intercepted, disallow those gestures from intercepting again to drag offscreen touchState.setDisallowDraggingOffscreen(); } if (touchState.isDragging()) { if (touchState.isDragging()) { // Move the pinned stack freely // Move the pinned stack freely PointF lastDelta = touchState.getLastTouchDelta(); PointF lastDelta = touchState.getLastTouchDelta(); Loading packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java +16 −0 Original line number Original line Diff line number Diff line Loading @@ -40,6 +40,7 @@ public class PipTouchState { private final PointF mVelocity = new PointF(); private final PointF mVelocity = new PointF(); private boolean mIsDragging = false; private boolean mIsDragging = false; private boolean mStartedDragging = false; private boolean mStartedDragging = false; private boolean mAllowDraggingOffscreen = false; private int mActivePointerId; private int mActivePointerId; public PipTouchState(ViewConfiguration viewConfig) { public PipTouchState(ViewConfiguration viewConfig) { Loading @@ -59,6 +60,7 @@ public class PipTouchState { mDownTouch.set(mLastTouch); mDownTouch.set(mLastTouch); mIsDragging = false; mIsDragging = false; mStartedDragging = false; mStartedDragging = false; mAllowDraggingOffscreen = true; break; break; } } case MotionEvent.ACTION_MOVE: { case MotionEvent.ACTION_MOVE: { Loading Loading @@ -159,6 +161,20 @@ public class PipTouchState { return mStartedDragging; return mStartedDragging; } } /** * Disallows dragging offscreen for the duration of the current gesture. */ public void setDisallowDraggingOffscreen() { mAllowDraggingOffscreen = false; } /** * @return whether dragging offscreen is allowed during this gesture. */ public boolean allowDraggingOffscreen() { return mAllowDraggingOffscreen; } private void initOrResetVelocityTracker() { private void initOrResetVelocityTracker() { if (mVelocityTracker == null) { if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); mVelocityTracker = VelocityTracker.obtain(); Loading services/core/java/com/android/server/wm/PinnedStackController.java +12 −1 Original line number Original line Diff line number Diff line Loading @@ -256,6 +256,12 @@ class PinnedStackController { false /* adjustForIme */); false /* adjustForIme */); mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds, mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds, snapFraction); snapFraction); if (mIsMinimized) { final Point displaySize = new Point(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); mSnapAlgorithm.applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds, displaySize); } } } return postChangeStackBounds; return postChangeStackBounds; } } Loading Loading @@ -285,7 +291,12 @@ class PinnedStackController { final Rect toBounds = new Rect(stackBounds); final Rect toBounds = new Rect(stackBounds); if (adjustedForIme) { if (adjustedForIme) { // IME visible // IME visible if (stackBounds.top == prevMovementBounds.bottom) { // If the PIP is resting on top of the IME, then adjust it with the hiding IME toBounds.offsetTo(toBounds.left, movementBounds.bottom); } else { toBounds.offset(0, Math.min(0, movementBounds.bottom - stackBounds.top)); toBounds.offset(0, Math.min(0, movementBounds.bottom - stackBounds.top)); } } else { } else { // IME hidden // IME hidden if (stackBounds.top == prevMovementBounds.bottom) { if (stackBounds.top == prevMovementBounds.bottom) { Loading Loading
core/java/com/android/internal/policy/PipSnapAlgorithm.java +16 −0 Original line number Original line Diff line number Diff line Loading @@ -41,8 +41,12 @@ public class PipSnapAlgorithm { // Allows snapping to anywhere along the edge of the screen // Allows snapping to anywhere along the edge of the screen private static final int SNAP_MODE_EDGE = 2; private static final int SNAP_MODE_EDGE = 2; // The friction multiplier to control how slippery the PIP is when flung private static final float SCROLL_FRICTION_MULTIPLIER = 8f; private static final float SCROLL_FRICTION_MULTIPLIER = 8f; // The fraction of the stack width to show when minimized private static final float MINIMIZED_VISIBLE_FRACTION = 0.25f; private final Context mContext; private final Context mContext; private final ArrayList<Integer> mSnapGravities = new ArrayList<>(); private final ArrayList<Integer> mSnapGravities = new ArrayList<>(); Loading Loading @@ -121,6 +125,18 @@ public class PipSnapAlgorithm { return newBounds; return newBounds; } } /** * Applies the offset to the {@param stackBounds} to adjust it to a minimized state. */ public void applyMinimizedOffset(Rect stackBounds, Rect movementBounds, Point displaySize) { int visibleWidth = (int) (MINIMIZED_VISIBLE_FRACTION * stackBounds.width()); if (stackBounds.left <= movementBounds.centerX()) { stackBounds.offsetTo(-stackBounds.width() + visibleWidth, stackBounds.top); } else { stackBounds.offsetTo(displaySize.x - visibleWidth, stackBounds.top); } } /** /** * @return returns a fraction that describes where along the {@param movementBounds} the * @return returns a fraction that describes where along the {@param movementBounds} the * {@param stackBounds} are. If the {@param stackBounds} are not currently on the * {@param stackBounds} are. If the {@param stackBounds} are not currently on the Loading
core/res/res/values/config.xml +2 −2 Original line number Original line Diff line number Diff line Loading @@ -2492,11 +2492,11 @@ <!-- Default insets [LEFT/RIGHTxTOP/BOTTOM] from the screen edge for picture-in-picture windows. <!-- Default insets [LEFT/RIGHTxTOP/BOTTOM] from the screen edge for picture-in-picture windows. These values are in DPs and will be converted to pixel sizes internally. --> These values are in DPs and will be converted to pixel sizes internally. --> <string translatable="false" name="config_defaultPictureInPictureScreenEdgeInsets">10x10</string> <string translatable="false" name="config_defaultPictureInPictureScreenEdgeInsets">8x8</string> <!-- Max default size [WIDTHxHEIGHT] on screen for picture-in-picture windows to fit inside. <!-- Max default size [WIDTHxHEIGHT] on screen for picture-in-picture windows to fit inside. These values are in DPs and will be converted to pixel sizes internally. --> These values are in DPs and will be converted to pixel sizes internally. --> <string translatable="false" name="config_defaultPictureInPictureSize">216x135</string> <string translatable="false" name="config_defaultPictureInPictureSize">192x120</string> <!-- The default gravity for the picture-in-picture window. <!-- The default gravity for the picture-in-picture window. Currently, this maps to Gravity.BOTTOM | Gravity.RIGHT --> Currently, this maps to Gravity.BOTTOM | Gravity.RIGHT --> Loading
packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +13 −12 Original line number Original line Diff line number Diff line Loading @@ -71,8 +71,6 @@ public class PipTouchHandler implements TunerService.Tunable { private static final int EXPAND_STACK_DURATION = 225; private static final int EXPAND_STACK_DURATION = 225; private static final int MINIMIZE_STACK_MAX_DURATION = 200; private static final int MINIMIZE_STACK_MAX_DURATION = 200; // The fraction of the stack width to show when minimized private static final float MINIMIZED_VISIBLE_FRACTION = 0.25f; // The fraction of the stack width that the user has to drag offscreen to minimize the PIP // The fraction of the stack width that the user has to drag offscreen to minimize the PIP private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.15f; private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.15f; // The fraction of the stack width that the user has to move when flinging to dismiss the PIP // The fraction of the stack width that the user has to move when flinging to dismiss the PIP Loading Loading @@ -396,6 +394,8 @@ public class PipTouchHandler implements TunerService.Tunable { * Flings the minimized PIP to the closest minimized snap target. * Flings the minimized PIP to the closest minimized snap target. */ */ private void flingToMinimizedSnapTarget(float velocityY) { private void flingToMinimizedSnapTarget(float velocityY) { // We currently only allow flinging the minimized stack up and down, so just lock the // movement bounds to the current stack bounds horizontally Rect movementBounds = new Rect(mPinnedStackBounds.left, mBoundedPinnedStackBounds.top, Rect movementBounds = new Rect(mPinnedStackBounds.left, mBoundedPinnedStackBounds.top, mPinnedStackBounds.left, mBoundedPinnedStackBounds.bottom); mPinnedStackBounds.left, mBoundedPinnedStackBounds.bottom); Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mPinnedStackBounds, Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mPinnedStackBounds, Loading @@ -414,16 +414,11 @@ public class PipTouchHandler implements TunerService.Tunable { * Animates the PIP to the minimized state, slightly offscreen. * Animates the PIP to the minimized state, slightly offscreen. */ */ private void animateToClosestMinimizedTarget() { private void animateToClosestMinimizedTarget() { Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(mBoundedPinnedStackBounds, mPinnedStackBounds); Point displaySize = new Point(); Point displaySize = new Point(); mContext.getDisplay().getRealSize(displaySize); mContext.getDisplay().getRealSize(displaySize); int visibleWidth = (int) (MINIMIZED_VISIBLE_FRACTION * mPinnedStackBounds.width()); Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(mBoundedPinnedStackBounds, if (mPinnedStackBounds.left < 0) { mPinnedStackBounds); toBounds.offsetTo(-toBounds.width() + visibleWidth, toBounds.top); mSnapAlgorithm.applyMinimizedOffset(toBounds, mBoundedPinnedStackBounds, displaySize); } else if (mPinnedStackBounds.right > displaySize.x) { toBounds.offsetTo(displaySize.x - visibleWidth, toBounds.top); } mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds, mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds, toBounds, MINIMIZE_STACK_MAX_DURATION, LINEAR_OUT_SLOW_IN, toBounds, MINIMIZE_STACK_MAX_DURATION, LINEAR_OUT_SLOW_IN, mUpdatePinnedStackBoundsListener); mUpdatePinnedStackBoundsListener); Loading Loading @@ -635,7 +630,7 @@ public class PipTouchHandler implements TunerService.Tunable { setMinimizedState(false); setMinimizedState(false); } } if (isDraggingOffscreen) { if (touchState.allowDraggingOffscreen() && isDraggingOffscreen) { // Move the pinned stack, but ignore the vertical movement // Move the pinned stack, but ignore the vertical movement float left = mPinnedStackBounds.left + touchState.getLastTouchDelta().x; float left = mPinnedStackBounds.left + touchState.getLastTouchDelta().x; mTmpBounds.set(mPinnedStackBounds); mTmpBounds.set(mPinnedStackBounds); Loading Loading @@ -685,7 +680,7 @@ public class PipTouchHandler implements TunerService.Tunable { setMinimizedState(false); setMinimizedState(false); } } if (isDraggingOffscreen) { if (touchState.allowDraggingOffscreen() && isDraggingOffscreen) { // Move the pinned stack, but ignore the vertical movement // Move the pinned stack, but ignore the vertical movement float left = mPinnedStackBounds.left + touchState.getLastTouchDelta().x; float left = mPinnedStackBounds.left + touchState.getLastTouchDelta().x; mTmpBounds.set(mPinnedStackBounds); mTmpBounds.set(mPinnedStackBounds); Loading Loading @@ -769,6 +764,12 @@ public class PipTouchHandler implements TunerService.Tunable { private PipTouchGesture mDefaultMovementGesture = new PipTouchGesture() { private PipTouchGesture mDefaultMovementGesture = new PipTouchGesture() { @Override @Override boolean onMove(PipTouchState touchState) { boolean onMove(PipTouchState touchState) { if (touchState.startedDragging()) { // For now, once the user has started a drag that the other gestures have not // intercepted, disallow those gestures from intercepting again to drag offscreen touchState.setDisallowDraggingOffscreen(); } if (touchState.isDragging()) { if (touchState.isDragging()) { // Move the pinned stack freely // Move the pinned stack freely PointF lastDelta = touchState.getLastTouchDelta(); PointF lastDelta = touchState.getLastTouchDelta(); Loading
packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java +16 −0 Original line number Original line Diff line number Diff line Loading @@ -40,6 +40,7 @@ public class PipTouchState { private final PointF mVelocity = new PointF(); private final PointF mVelocity = new PointF(); private boolean mIsDragging = false; private boolean mIsDragging = false; private boolean mStartedDragging = false; private boolean mStartedDragging = false; private boolean mAllowDraggingOffscreen = false; private int mActivePointerId; private int mActivePointerId; public PipTouchState(ViewConfiguration viewConfig) { public PipTouchState(ViewConfiguration viewConfig) { Loading @@ -59,6 +60,7 @@ public class PipTouchState { mDownTouch.set(mLastTouch); mDownTouch.set(mLastTouch); mIsDragging = false; mIsDragging = false; mStartedDragging = false; mStartedDragging = false; mAllowDraggingOffscreen = true; break; break; } } case MotionEvent.ACTION_MOVE: { case MotionEvent.ACTION_MOVE: { Loading Loading @@ -159,6 +161,20 @@ public class PipTouchState { return mStartedDragging; return mStartedDragging; } } /** * Disallows dragging offscreen for the duration of the current gesture. */ public void setDisallowDraggingOffscreen() { mAllowDraggingOffscreen = false; } /** * @return whether dragging offscreen is allowed during this gesture. */ public boolean allowDraggingOffscreen() { return mAllowDraggingOffscreen; } private void initOrResetVelocityTracker() { private void initOrResetVelocityTracker() { if (mVelocityTracker == null) { if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); mVelocityTracker = VelocityTracker.obtain(); Loading
services/core/java/com/android/server/wm/PinnedStackController.java +12 −1 Original line number Original line Diff line number Diff line Loading @@ -256,6 +256,12 @@ class PinnedStackController { false /* adjustForIme */); false /* adjustForIme */); mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds, mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds, snapFraction); snapFraction); if (mIsMinimized) { final Point displaySize = new Point(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); mSnapAlgorithm.applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds, displaySize); } } } return postChangeStackBounds; return postChangeStackBounds; } } Loading Loading @@ -285,7 +291,12 @@ class PinnedStackController { final Rect toBounds = new Rect(stackBounds); final Rect toBounds = new Rect(stackBounds); if (adjustedForIme) { if (adjustedForIme) { // IME visible // IME visible if (stackBounds.top == prevMovementBounds.bottom) { // If the PIP is resting on top of the IME, then adjust it with the hiding IME toBounds.offsetTo(toBounds.left, movementBounds.bottom); } else { toBounds.offset(0, Math.min(0, movementBounds.bottom - stackBounds.top)); toBounds.offset(0, Math.min(0, movementBounds.bottom - stackBounds.top)); } } else { } else { // IME hidden // IME hidden if (stackBounds.top == prevMovementBounds.bottom) { if (stackBounds.top == prevMovementBounds.bottom) { Loading