Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a3dfef42 authored by Joshua Tsuji's avatar Joshua Tsuji
Browse files

Don't pull magnetized objects into the target unless they're dragged.

Test: manual
Bug: 153936889
Change-Id: I045cd8b937a706e4df25ad64ae12e6d292b9ff06
parent 64fb27fc
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -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
+31 −3
Original line number Diff line number Diff line
@@ -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<T : Any>(
    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<T : Any>(
        // 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<T : Any>(
    }

    /** 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
        }
    }

    /**
+8 −4
Original line number Diff line number Diff line
@@ -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)