diff options
| author | 2025-01-06 13:29:32 +0900 | |
|---|---|---|
| committer | 2025-01-09 13:06:13 +0900 | |
| commit | 8214656176a12d309d40b961ca7e5f4106c8fb1d (patch) | |
| tree | 7e08afa091a0ba766be57b997eaedd58ee6b8bf6 | |
| parent | bf3fec9ff8085c20152a9091e7c4362fdbdb7248 (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
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; } |