summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author nergi <nergi@google.com> 2025-01-06 13:29:32 +0900
committer nergi <nergi@google.com> 2025-01-09 13:06:13 +0900
commit8214656176a12d309d40b961ca7e5f4106c8fb1d (patch)
tree7e08afa091a0ba766be57b997eaedd58ee6b8bf6
parentbf3fec9ff8085c20152a9091e7c4362fdbdb7248 (diff)
[DnD] Pass displayId to DragEvent
To support APIs where drag surface is relinquished to caller and caller decides the animation, e.g. TaskbarDragController, DesktopTaskController, they need to know the displayId where the x, y refers to. Initially there're 2 alternatives here, to either pass -1, -1 as x, y to denote event happened on different display, or modify the API such as GlobalDragListener to also receives displayId as param. However, as it's beneficial for both ACTION_DRAG_ENDED and ACTION_DROP to have displayId, we might as well have it inside DragEvent. This also aligns with the native implementation where DragEvent also (extending InputEvent) contains displayId. Bug: 365512241 Test: atest WmTests:DragDropControllerTests Flag: EXEMPT new variable is unused Change-Id: I63b4289e5e11f22c5e8cdc2d4fc0453fb114c10b
-rw-r--r--core/java/android/view/DragEvent.java30
-rw-r--r--core/java/android/view/InputEventReceiver.java2
-rw-r--r--core/java/android/view/ViewRootImpl.java10
-rw-r--r--core/jni/android_view_InputEventReceiver.cpp5
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/GlobalDragListenerTest.kt6
-rw-r--r--services/core/java/com/android/server/wm/DragState.java9
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java16
7 files changed, 53 insertions, 25 deletions
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index b65e3ebc3871..77af312eac4a 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -157,6 +157,11 @@ public class DragEvent implements Parcelable {
private float mOffsetY;
/**
+ * The id of the display where the `mX` and `mY` of this event belongs to.
+ */
+ private int mDisplayId;
+
+ /**
* The View#DRAG_FLAG_* flags used to start the current drag, only provided if the target window
* has the {@link WindowManager.LayoutParams#PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP} flag
* and is only sent with {@link #ACTION_DRAG_STARTED} and {@link #ACTION_DROP}.
@@ -297,14 +302,15 @@ public class DragEvent implements Parcelable {
private DragEvent() {
}
- private void init(int action, float x, float y, float offsetX, float offsetY, int flags,
- ClipDescription description, ClipData data, SurfaceControl dragSurface,
+ private void init(int action, float x, float y, float offsetX, float offsetY, int displayId,
+ int flags, ClipDescription description, ClipData data, SurfaceControl dragSurface,
IDragAndDropPermissions dragAndDropPermissions, Object localState, boolean result) {
mAction = action;
mX = x;
mY = y;
mOffsetX = offsetX;
mOffsetY = offsetY;
+ mDisplayId = displayId;
mFlags = flags;
mClipDescription = description;
mClipData = data;
@@ -315,20 +321,20 @@ public class DragEvent implements Parcelable {
}
static DragEvent obtain() {
- return DragEvent.obtain(0, 0f, 0f, 0f, 0f, 0, null, null, null, null, null, false);
+ return DragEvent.obtain(0, 0f, 0f, 0f, 0f, 0, 0, null, null, null, null, null, false);
}
/** @hide */
public static DragEvent obtain(int action, float x, float y, float offsetX, float offsetY,
- int flags, Object localState, ClipDescription description, ClipData data,
+ int displayId, int flags, Object localState, ClipDescription description, ClipData data,
SurfaceControl dragSurface, IDragAndDropPermissions dragAndDropPermissions,
boolean result) {
final DragEvent ev;
synchronized (gRecyclerLock) {
if (gRecyclerTop == null) {
ev = new DragEvent();
- ev.init(action, x, y, offsetX, offsetY, flags, description, data, dragSurface,
- dragAndDropPermissions, localState, result);
+ ev.init(action, x, y, offsetX, offsetY, displayId, flags, description, data,
+ dragSurface, dragAndDropPermissions, localState, result);
return ev;
}
ev = gRecyclerTop;
@@ -339,7 +345,7 @@ public class DragEvent implements Parcelable {
ev.mRecycled = false;
ev.mNext = null;
- ev.init(action, x, y, offsetX, offsetY, flags, description, data, dragSurface,
+ ev.init(action, x, y, offsetX, offsetY, displayId, flags, description, data, dragSurface,
dragAndDropPermissions, localState, result);
return ev;
@@ -349,8 +355,9 @@ public class DragEvent implements Parcelable {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static DragEvent obtain(DragEvent source) {
return obtain(source.mAction, source.mX, source.mY, source.mOffsetX, source.mOffsetY,
- source.mFlags, source.mLocalState, source.mClipDescription, source.mClipData,
- source.mDragSurface, source.mDragAndDropPermissions, source.mDragResult);
+ source.mDisplayId, source.mFlags, source.mLocalState, source.mClipDescription,
+ source.mClipData, source.mDragSurface, source.mDragAndDropPermissions,
+ source.mDragResult);
}
/**
@@ -398,6 +405,11 @@ public class DragEvent implements Parcelable {
return mOffsetY;
}
+ /** @hide */
+ public int getDisplayId() {
+ return mDisplayId;
+ }
+
/**
* Returns the {@link android.content.ClipData} object sent to the system as part of the call
* to
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index 2cc05b0bc4b0..1c36eaf99afa 100644
--- a/core/java/android/view/InputEventReceiver.java
+++ b/core/java/android/view/InputEventReceiver.java
@@ -177,7 +177,7 @@ public abstract class InputEventReceiver {
* drag
* if true, the window associated with this input channel has just lost drag
*/
- public void onDragEvent(boolean isExiting, float x, float y) {
+ public void onDragEvent(boolean isExiting, float x, float y, int displayId) {
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 8ef0b0eebb8c..36671b901a6b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -10561,13 +10561,13 @@ public final class ViewRootImpl implements ViewParent,
}
@Override
- public void onDragEvent(boolean isExiting, float x, float y) {
+ public void onDragEvent(boolean isExiting, float x, float y, int displayId) {
// force DRAG_EXITED_EVENT if appropriate
DragEvent event = DragEvent.obtain(
- isExiting ? DragEvent.ACTION_DRAG_EXITED : DragEvent.ACTION_DRAG_LOCATION,
- x, y, 0 /* offsetX */, 0 /* offsetY */, 0 /* flags */, null/* localState */,
- null/* description */, null /* data */, null /* dragSurface */,
- null /* dragAndDropPermissions */, false /* result */);
+ isExiting ? DragEvent.ACTION_DRAG_EXITED : DragEvent.ACTION_DRAG_LOCATION, x, y,
+ 0 /* offsetX */, 0 /* offsetY */, displayId, 0 /* flags */,
+ null/* localState */, null/* description */, null /* data */,
+ null /* dragSurface */, null /* dragAndDropPermissions */, false /* result */);
dispatchDragEvent(event);
}
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index 3a1e8835c8db..6272fb1947c1 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -441,7 +441,8 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
}
env->CallVoidMethod(receiverObj.get(), gInputEventReceiverClassInfo.onDragEvent,
jboolean(dragEvent->isExiting()), dragEvent->getX(),
- dragEvent->getY());
+ dragEvent->getY(),
+ static_cast<jint>(dragEvent->getDisplayId().val()));
finishInputEvent(seq, /*handled=*/true);
continue;
}
@@ -643,7 +644,7 @@ int register_android_view_InputEventReceiver(JNIEnv* env) {
GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onPointerCaptureEvent",
"(Z)V");
gInputEventReceiverClassInfo.onDragEvent =
- GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onDragEvent", "(ZFF)V");
+ GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onDragEvent", "(ZFFI)V");
gInputEventReceiverClassInfo.onTouchModeChanged =
GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onTouchModeChanged", "(Z)V");
gInputEventReceiverClassInfo.onBatchedInputEventPending =
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/GlobalDragListenerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/GlobalDragListenerTest.kt
index d410151b4602..5389c94bc15d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/GlobalDragListenerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/GlobalDragListenerTest.kt
@@ -43,7 +43,7 @@ import org.mockito.kotlin.verify
*/
@SmallTest
@RunWith(AndroidJUnit4::class)
-class UnhandledDragControllerTest : ShellTestCase() {
+class GlobalDragListenerTest : ShellTestCase() {
private val mIWindowManager = mock<IWindowManager>()
private val mMainExecutor = mock<ShellExecutor>()
@@ -74,7 +74,7 @@ class UnhandledDragControllerTest : ShellTestCase() {
@Test
fun onUnhandledDrop_noListener_expectNotifyUnhandled() {
// Simulate an unhandled drop
- val dropEvent = DragEvent.obtain(ACTION_DROP, 0f, 0f, 0f, 0f, 0, null, null, null,
+ val dropEvent = DragEvent.obtain(ACTION_DROP, 0f, 0f, 0f, 0f, 0, 0, null, null, null,
null, null, false)
val wmCallback = mock<IUnhandledDragCallback>()
mController.onUnhandledDrop(dropEvent, wmCallback)
@@ -98,7 +98,7 @@ class UnhandledDragControllerTest : ShellTestCase() {
// Simulate an unhandled drop
val dragSurface = mock<SurfaceControl>()
- val dropEvent = DragEvent.obtain(ACTION_DROP, 0f, 0f, 0f, 0f, 0, null, null, null,
+ val dropEvent = DragEvent.obtain(ACTION_DROP, 0f, 0f, 0f, 0f, 0, 0, null, null, null,
dragSurface, null, false)
val wmCallback = mock<IUnhandledDragCallback>()
mController.onUnhandledDrop(dropEvent, wmCallback)
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 4a4e2461c2ca..d48b9b4a5d10 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -253,7 +253,8 @@ class DragState {
}
}
DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED, inWindowX,
- inWindowY, mThumbOffsetX, mThumbOffsetY, mFlags, null, null, null,
+ inWindowY, mThumbOffsetX, mThumbOffsetY,
+ mCurrentDisplayContent.getDisplayId(), mFlags, null, null, null,
dragSurface, null, mDragResult);
try {
if (DEBUG_DRAG) Slog.d(TAG_WM, "Sending DRAG_ENDED to " + ws);
@@ -791,10 +792,10 @@ class DragState {
ClipData data, boolean includeDragSurface, boolean includeDragFlags,
IDragAndDropPermissions dragAndDropPermissions) {
return DragEvent.obtain(action, x, y, mThumbOffsetX, mThumbOffsetY,
- includeDragFlags ? mFlags : 0,
+ mCurrentDisplayContent.getDisplayId(), includeDragFlags ? mFlags : 0,
null /* localState */, description, data,
- includeDragSurface ? mSurfaceControl : null,
- dragAndDropPermissions, false /* result */);
+ includeDragSurface ? mSurfaceControl : null, dragAndDropPermissions,
+ false /* result */);
}
private ValueAnimator createReturnAnimationLocked() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index 63c745ea6cd0..dc16de1aab5e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -415,8 +415,14 @@ public class DragDropControllerTests extends WindowTestsBase {
assertEquals(ACTION_DROP, dropEvent.getAction());
assertEquals(dropCoordsPx, dropEvent.getX(), 0.0 /* delta */);
assertEquals(dropCoordsPx, dropEvent.getY(), 0.0 /* delta */);
+ assertEquals(window2.getDisplayId(), dropEvent.getDisplayId());
mTarget.reportDropResult(iwindow2, true);
+ // Verify both windows received ACTION_DRAG_ENDED event.
+ assertEquals(ACTION_DRAG_ENDED, last(dragEvents).getAction());
+ assertEquals(window2.getDisplayId(), last(dragEvents).getDisplayId());
+ assertEquals(ACTION_DRAG_ENDED, last(dragEvents2).getAction());
+ assertEquals(window2.getDisplayId(), last(dragEvents2).getDisplayId());
} finally {
mTarget.mDeferDragStateClosed = false;
}
@@ -458,10 +464,12 @@ public class DragDropControllerTests extends WindowTestsBase {
try {
mTarget.mDeferDragStateClosed = true;
+ mTarget.handleMotionEvent(true, testDisplay.getDisplayId(), dropCoordsPx,
+ dropCoordsPx);
// x, y is window-local coordinate.
mTarget.reportDropWindow(window2.mInputChannelToken, dropCoordsPx,
dropCoordsPx);
- mTarget.handleMotionEvent(false, window2.getDisplayId(), dropCoordsPx,
+ mTarget.handleMotionEvent(false, testDisplay.getDisplayId(), dropCoordsPx,
dropCoordsPx);
mToken = window2.mClient.asBinder();
// Verify only window2 received the DROP event and coords are sent as-is
@@ -471,8 +479,14 @@ public class DragDropControllerTests extends WindowTestsBase {
assertEquals(ACTION_DROP, dropEvent.getAction());
assertEquals(dropCoordsPx, dropEvent.getX(), 0.0 /* delta */);
assertEquals(dropCoordsPx, dropEvent.getY(), 0.0 /* delta */);
+ assertEquals(testDisplay.getDisplayId(), dropEvent.getDisplayId());
mTarget.reportDropResult(iwindow2, true);
+ // Verify both windows received ACTION_DRAG_ENDED event.
+ assertEquals(ACTION_DRAG_ENDED, last(dragEvents).getAction());
+ assertEquals(testDisplay.getDisplayId(), last(dragEvents).getDisplayId());
+ assertEquals(ACTION_DRAG_ENDED, last(dragEvents2).getAction());
+ assertEquals(testDisplay.getDisplayId(), last(dragEvents2).getDisplayId());
} finally {
mTarget.mDeferDragStateClosed = false;
}