Prevent drag-to-open from cycling pressed state, propagate hotspot

Avoids unnecessary changes to pressed state. Ensures hotspot propagates
to both the list view and the list item view since both receive the
pressed state.

Bug: 19134424
Change-Id: If2496ce2042e43fe1c1efd527eeca10dc53e1f4a
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index fe8b08b..d85bbb9 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -1648,19 +1648,32 @@
         private void setPressedItem(View child, int position, float x, float y) {
             mDrawsInPressedState = true;
 
-            // Ordering is essential. First update the pressed state and layout
-            // the children. This will ensure the selector actually gets drawn.
-            setPressed(true);
-            layoutChildren();
+            // Ordering is essential. First, update the container's pressed state.
+            drawableHotspotChanged(x, y);
+            if (!isPressed()) {
+                setPressed(true);
+            }
+
+            // Next, run layout if we need to stabilize child positions.
+            if (mDataChanged) {
+                layoutChildren();
+            }
 
             // Manage the pressed view based on motion position. This allows us to
             // play nicely with actual touch and scroll events.
             final View motionView = getChildAt(mMotionPosition - mFirstPosition);
-            if (motionView != null) {
+            if (motionView != null && motionView != child && motionView.isPressed()) {
                 motionView.setPressed(false);
             }
             mMotionPosition = position;
-            child.setPressed(true);
+
+            // Offset for child coordinates.
+            final float childX = x - child.getLeft();
+            final float childY = y - child.getTop();
+            child.drawableHotspotChanged(childX, childY);
+            if (!child.isPressed()) {
+                child.setPressed(true);
+            }
 
             // Ensure that keyboard focus starts from the last touched position.
             setSelectedPositionInt(position);