summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorChris Tate <ctate@google.com>2010-11-02 15:55:39 -0700
committerChris Tate <ctate@google.com>2010-11-02 15:55:39 -0700
commit9d1ab883293b047b654935b84d0803c8c383be91 (patch)
treee41a26d0f18e08f033d880e4a3de5c1a75db417d /core
parent4b8d36b30ad2e87f3969034eb42dc14b99f03686 (diff)
downloadframeworks_base-9d1ab883293b047b654935b84d0803c8c383be91.zip
frameworks_base-9d1ab883293b047b654935b84d0803c8c383be91.tar.gz
frameworks_base-9d1ab883293b047b654935b84d0803c8c383be91.tar.bz2
Fix drag enter/exit reporting
Now, each ViewGroup is tracking which of its child views [which might themselves be ViewGroups] is currently under the drag point, and when the drag leaves that child, a DRAG_EXITED is synthesized and dispatched all the way down to the leaf view previously under the point. ENTERED is still *not* dispatched down like this; instead, it's calculated and synthesized directly at each level based on the new LOCATION. The ViewRoot still tracks the leaf drag target, but solely for the purpose of reporting changes to the OS after full dispatch of a new LOCATION -- the entered/exited messaging is no longer initiated at the ViewRoot level. Change-Id: I0089cc538b7e33a0440187543fcfd2f8b12e197d
Diffstat (limited to 'core')
-rw-r--r--core/java/android/view/ViewGroup.java44
-rw-r--r--core/java/android/view/ViewRoot.java17
2 files changed, 43 insertions, 18 deletions
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 0f9312c..ad343a3 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -870,7 +870,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
switch (event.mAction) {
case DragEvent.ACTION_DRAG_STARTED: {
// clear state to recalculate which views we drag over
- root.setDragFocus(event, null);
+ mCurrentDragView = null;
// Now dispatch down to our children, caching the responses
mChildAcceptsDrag = false;
@@ -915,11 +915,28 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final View target = findFrontmostDroppableChildAt(event.mX, event.mY, mLocalPoint);
// If we've changed apparent drag target, tell the view root which view
- // we're over now. This will in turn send out DRAG_ENTERED / DRAG_EXITED
- // notifications as appropriate.
+ // we're over now [for purposes of the eventual drag-recipient-changed
+ // notifications to the framework] and tell the new target that the drag
+ // has entered its bounds. The root will see setDragFocus() calls all
+ // the way down to the final leaf view that is handling the LOCATION event
+ // before reporting the new potential recipient to the framework.
if (mCurrentDragView != target) {
- root.setDragFocus(event, target);
+ root.setDragFocus(target);
+
+ final int action = event.mAction;
+ // If we've dragged off of a child view, send it the EXITED message
+ if (mCurrentDragView != null) {
+ event.mAction = DragEvent.ACTION_DRAG_EXITED;
+ mCurrentDragView.dispatchDragEvent(event);
+ }
mCurrentDragView = target;
+
+ // If we've dragged over a new child view, send it the ENTERED message
+ if (target != null) {
+ event.mAction = DragEvent.ACTION_DRAG_ENTERED;
+ target.dispatchDragEvent(event);
+ }
+ event.mAction = action; // restore the event's original state
}
// Dispatch the actual drag location notice, localized into its coordinates
@@ -934,6 +951,25 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
} break;
+ /* Entered / exited dispatch
+ *
+ * DRAG_ENTERED is not dispatched downwards from ViewGroup. The reason for this is
+ * that we're about to get the corresponding LOCATION event, which we will use to
+ * determine which of our children is the new target; at that point we will
+ * push a DRAG_ENTERED down to the new target child [which may itself be a ViewGroup].
+ *
+ * DRAG_EXITED *is* dispatched all the way down immediately: once we know the
+ * drag has left this ViewGroup, we know by definition that every contained subview
+ * is also no longer under the drag point.
+ */
+
+ case DragEvent.ACTION_DRAG_EXITED: {
+ if (mCurrentDragView != null) {
+ mCurrentDragView.dispatchDragEvent(event);
+ mCurrentDragView = null;
+ }
+ } break;
+
case DragEvent.ACTION_DROP: {
if (ViewDebug.DEBUG_DRAG) Log.d(View.VIEW_LOG_TAG, "Drop event: " + event);
View target = findFrontmostDroppableChildAt(event.mX, event.mY, mLocalPoint);
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 22a7773..c7c2071 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -2493,11 +2493,12 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
// a window boundary, so the current drag target within this one must have
// just been exited. Send it the usual notifications and then we're done
// for now.
- setDragFocus(event, null);
+ mView.dispatchDragEvent(event);
} else {
// Cache the drag description when the operation starts, then fill it in
// on subsequent calls as a convenience
if (what == DragEvent.ACTION_DRAG_STARTED) {
+ mCurrentDragView = null; // Start the current-recipient tracking
mDragDescription = event.mClipDescription;
} else {
event.mClipDescription = mDragDescription;
@@ -2557,22 +2558,10 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
outLocation.y = (int) mLastTouchPoint.y;
}
- public void setDragFocus(DragEvent event, View newDragTarget) {
- final int action = event.mAction;
- // If we've dragged off of a view, send it the EXITED message
+ public void setDragFocus(View newDragTarget) {
if (mCurrentDragView != newDragTarget) {
- if (mCurrentDragView != null) {
- event.mAction = DragEvent.ACTION_DRAG_EXITED;
- mCurrentDragView.dispatchDragEvent(event);
- }
mCurrentDragView = newDragTarget;
}
- // If we've dragged over a new view, send it the ENTERED message
- if (newDragTarget != null) {
- event.mAction = DragEvent.ACTION_DRAG_ENTERED;
- newDragTarget.dispatchDragEvent(event);
- }
- event.mAction = action; // restore the event's original state
}
private AudioManager getAudioManager() {