diff options
| -rw-r--r-- | core/java/android/view/ViewGroup.java | 44 | ||||
| -rw-r--r-- | core/java/android/view/ViewRoot.java | 17 | ||||
| -rw-r--r-- | services/java/com/android/server/WindowManagerService.java | 2 |
3 files changed, 44 insertions, 19 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() { diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 55ebded..1cbc8324 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -687,7 +687,7 @@ public class WindowManagerService extends IWindowManager.Stub } } if (touchedWin != null) { - if (DEBUG_DRAG) { + if (false && DEBUG_DRAG) { Slog.d(TAG, "sending DRAG_LOCATION to " + touchedWin); } DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_LOCATION, |
