diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index 350ce293a13f8..79d2eddfaec42 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -266,6 +266,10 @@ public class PipTouchHandler { mMagnetizedPip = mMotionHelper.getMagnetizedPip(); mMagneticTarget = mMagnetizedPip.addTarget(mTargetView, 0); + + // Set the magnetic field radius equal to twice the size of the target. + mMagneticTarget.setMagneticFieldRadiusPx(targetSize * 2); + mMagnetizedPip.setPhysicsAnimatorUpdateListener(mMotionHelper.mResizePipUpdateListener); mMagnetizedPip.setMagnetListener(new MagnetizedObject.MagnetListener() { @Override @@ -504,9 +508,6 @@ public class PipTouchHandler { mTargetView.setTranslationY(mTargetViewContainer.getHeight()); mTargetViewContainer.setVisibility(View.VISIBLE); - // Set the magnetic field radius to half of PIP's width. - mMagneticTarget.setMagneticFieldRadiusPx(mMotionHelper.getBounds().width()); - // Cancel in case we were in the middle of animating it out. mMagneticTargetAnimator.cancel(); mMagneticTargetAnimator diff --git a/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt b/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt index f27bdbfbeda05..e905e67720741 100644 --- a/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt +++ b/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt @@ -27,6 +27,7 @@ import android.provider.Settings import android.view.MotionEvent import android.view.VelocityTracker import android.view.View +import android.view.ViewConfiguration import androidx.dynamicanimation.animation.DynamicAnimation import androidx.dynamicanimation.animation.FloatPropertyCompat import androidx.dynamicanimation.animation.SpringForce @@ -146,6 +147,10 @@ abstract class MagnetizedObject( private val velocityTracker: VelocityTracker = VelocityTracker.obtain() private val vibrator: Vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator + private var touchDown = PointF() + private var touchSlop = 0 + private var movedBeyondSlop = false + /** Whether touch events are presently occurring within the magnetic field area of a target. */ val objectStuckToTarget: Boolean get() = targetObjectIsStuckTo != null @@ -324,15 +329,32 @@ abstract class MagnetizedObject( // When a gesture begins, recalculate target views' positions on the screen in case they // have changed. Also, clear state. if (ev.action == MotionEvent.ACTION_DOWN) { - updateTargetViewLocations() + updateTargetViews() - // Clear the velocity tracker and assume we're not stuck to a target yet. + // Clear the velocity tracker and stuck target. velocityTracker.clear() targetObjectIsStuckTo = null + + // Set the touch down coordinates and reset movedBeyondSlop. + touchDown.set(ev.rawX, ev.rawY) + movedBeyondSlop = false } + // Always pass events to the VelocityTracker. addMovement(ev) + // If we haven't yet moved beyond the slop distance, check if we have. + if (!movedBeyondSlop) { + val dragDistance = hypot(ev.rawX - touchDown.x, ev.rawY - touchDown.y) + if (dragDistance > touchSlop) { + // If we're beyond the slop distance, save that and continue. + movedBeyondSlop = true + } else { + // Otherwise, don't do anything yet. + return false + } + } + val targetObjectIsInMagneticFieldOf = associatedTargets.firstOrNull { target -> val distanceFromTargetCenter = hypot( ev.rawX - target.centerOnScreen.x, @@ -559,8 +581,14 @@ abstract class MagnetizedObject( } /** Updates the locations on screen of all of the [associatedTargets]. */ - internal fun updateTargetViewLocations() { + internal fun updateTargetViews() { associatedTargets.forEach { it.updateLocationOnScreen() } + + // Update the touch slop, since the configuration may have changed. + if (associatedTargets.size > 0) { + touchSlop = + ViewConfiguration.get(associatedTargets[0].targetView.context).scaledTouchSlop + } } /** diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/magnetictarget/MagnetizedObjectTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/magnetictarget/MagnetizedObjectTest.kt index f6b7b74d4bfc2..251ca9c8dcb2d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/magnetictarget/MagnetizedObjectTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/util/magnetictarget/MagnetizedObjectTest.kt @@ -186,8 +186,8 @@ class MagnetizedObjectTest : SysuiTestCase() { @Test fun testMotionEventConsumption_downInMagneticField() { - // We should consume DOWN events if they occur in the field. - assertTrue(magnetizedObject.maybeConsumeMotionEvent(getMotionEvent( + // We should not consume DOWN events even if they occur in the field. + assertFalse(magnetizedObject.maybeConsumeMotionEvent(getMotionEvent( x = targetCenterX, y = targetCenterY, action = MotionEvent.ACTION_DOWN))) } @@ -342,10 +342,14 @@ class MagnetizedObjectTest : SysuiTestCase() { // Trigger the magnet animation, and block the test until it ends. PhysicsAnimatorTestUtils.setAllAnimationsBlock(true) magnetizedObject.maybeConsumeMotionEvent(getMotionEvent( - x = targetCenterX, - y = targetCenterY, + x = targetCenterX - 250, + y = targetCenterY - 250, action = MotionEvent.ACTION_DOWN)) + magnetizedObject.maybeConsumeMotionEvent(getMotionEvent( + x = targetCenterX, + y = targetCenterY)) + // The object's (top-left) position should now position it centered over the target. assertEquals(targetCenterX - objectSize / 2, objectX) assertEquals(targetCenterY - objectSize / 2, objectY)