More drag/drop adjustments:
* Make View.onDragEvent() public instead of protected.
* No longer @hide View.startDrag()
* Properly manage the boundaries of DRAG_STARTED / DRAG_ENDED notifications
to windows (and as a result don't send bogus empty DRAG_STARTED events or
double-recycle pooled DragEvents)
Change-Id: Ib75f5c1417640c82a5b043c555e02d6e6f4b4d9c
diff --git a/api/current.xml b/api/current.xml
index 08e8670..a866669 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -201443,7 +201443,7 @@
static="false"
final="false"
deprecated="not deprecated"
- visibility="protected"
+ visibility="public"
>
<parameter name="event" type="android.view.DragEvent">
</parameter>
@@ -203185,6 +203185,23 @@
<parameter name="animation" type="android.view.animation.Animation">
</parameter>
</method>
+<method name="startDrag"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="android.content.ClipData">
+</parameter>
+<parameter name="thumbBuilder" type="android.view.View.DragThumbnailBuilder">
+</parameter>
+<parameter name="myWindowOnly" type="boolean">
+</parameter>
+</method>
<method name="unscheduleDrawable"
return="void"
abstract="false"
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 35b806a..472f7b4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9898,11 +9898,10 @@
}
/**
- * Drag and drop. App calls startDrag(), then callbacks to onMeasureDragThumbnail()
- * and onDrawDragThumbnail() happen, then the drag operation is handed over to the
- * OS.
+ * Drag and drop. App calls startDrag(), then callbacks to the thumbnail builder's
+ * onProvideThumbnailMetrics() and onDrawThumbnail() methods happen, then the drag
+ * operation is handed over to the OS.
* !!! TODO: real docs
- * @hide
*/
public final boolean startDrag(ClipData data, DragThumbnailBuilder thumbBuilder,
boolean myWindowOnly) {
@@ -10027,7 +10026,7 @@
* For DRAG_ENDED_EVENT, the 'event' argument may be null. The view should return
* to its normal visual state.
*/
- protected boolean onDragEvent(DragEvent event) {
+ public boolean onDragEvent(DragEvent event) {
return false;
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 5ebc981..5b3a091 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -938,11 +938,16 @@
if (ViewDebug.DEBUG_DRAG) Log.d(View.VIEW_LOG_TAG, "Drop event: " + event);
View target = findFrontmostDroppableChildAt(event.mX, event.mY, mLocalPoint);
if (target != null) {
+ if (ViewDebug.DEBUG_DRAG) Log.d(View.VIEW_LOG_TAG, " dispatch drop to " + target);
event.mX = mLocalPoint.x;
event.mY = mLocalPoint.y;
retval = target.dispatchDragEvent(event);
event.mX = tx;
event.mY = ty;
+ } else {
+ if (ViewDebug.DEBUG_DRAG) {
+ Log.d(View.VIEW_LOG_TAG, " not dropped on an accepting view");
+ }
}
} break;
}
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 30aed69..59f7434 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -505,7 +505,7 @@
InputChannel mServerChannel, mClientChannel;
WindowState mTargetWindow;
ArrayList<WindowState> mNotifiedWindows;
- boolean mDragEnded;
+ boolean mDragInProgress;
private final Rect tmpRect = new Rect();
@@ -562,6 +562,7 @@
// works correctly in calling out to the apps.
mDataDescription = new ClipDescription(mData);
mNotifiedWindows.clear();
+ mDragInProgress = true;
if (DEBUG_DRAG) {
Slog.d(TAG, "broadcasting DRAG_STARTED of " + mDataDescription);
@@ -586,7 +587,7 @@
* process, so it's safe for the caller to call recycle() on the event afterwards.
*/
private void sendDragStartedLw(WindowState newWin, DragEvent event) {
- if (!mDragEnded && newWin.isPotentialDragTarget()) {
+ if (mDragInProgress && newWin.isPotentialDragTarget()) {
try {
// clone for local callees since dispatch will recycle the event
if (Process.myPid() == newWin.mSession.mPid) {
@@ -606,20 +607,22 @@
* was begun. This is a rare case.
*/
private void sendDragStartedIfNeededLw(WindowState newWin) {
- // If we have sent the drag-started, we needn't do so again
- for (WindowState ws : mNotifiedWindows) {
- if (ws == newWin) {
- return;
+ if (mDragInProgress) {
+ // If we have sent the drag-started, we needn't do so again
+ for (WindowState ws : mNotifiedWindows) {
+ if (ws == newWin) {
+ return;
+ }
}
+ if (DEBUG_DRAG) {
+ Slog.d(TAG, "sending DRAG_STARTED to new window " + newWin);
+ }
+ DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_STARTED, 0, 0,
+ mDataDescription, null);
+ // sendDragStartedLw() clones 'event' if the window is process-local
+ sendDragStartedLw(newWin, event);
+ event.recycle();
}
- if (DEBUG_DRAG) {
- Slog.d(TAG, "sending DRAG_STARTED to new window " + newWin);
- }
- DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_STARTED, 0, 0,
- mDataDescription, null);
- // sendDragStartedLw() clones 'event' if the window is process-local
- sendDragStartedLw(newWin, event);
- event.recycle();
}
void broadcastDragEnded() {
@@ -636,7 +639,7 @@
}
}
mNotifiedWindows.clear();
- mDragEnded = true;
+ mDragInProgress = false;
}
evt.recycle();
}