Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a4a4b1c authored by Winson Chung's avatar Winson Chung
Browse files

Always use display coords for unhandled drop events

- If an app starts a drag with DRAG_FLAG_GLOBAL_SAME_APPLICATION, input
  will still report the drop over a non-notified window (ie. one that
  did not receive DRAG_STARTED) with window-relative coordinates instead
  of display coordinates that Shell expects.

Fixes: 438975251
Flag: EXEMPT bugfix
Test: atest DragDropControllerTests
Change-Id: I01183596b74f62267aadba65c0c3e2b5b707783f
parent 4cb14e51
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -368,8 +368,15 @@ class DragState {
        }

        final WindowState touchedWin = mService.mInputToWindowMap.get(token);
        final float displayX = touchedWin != null
                ? touchedWin.getBounds().left + inWindowX
                : inWindowX;
        final float displayY = touchedWin != null
                ? touchedWin.getBounds().top + inWindowY
                : inWindowY;
        if (!isWindowNotified(touchedWin)) {
            final DragEvent unhandledDropEvent = createUnhandledDropEvent(inWindowX, inWindowY);
            if (DEBUG_DRAG) Slog.d(TAG_WM, "Received drop for unnotified window " + touchedWin);
            final DragEvent unhandledDropEvent = createUnhandledDropEvent(displayX, displayY);
            // Delegate to the unhandled drag listener as a first pass
            if (mDragDropController.notifyUnhandledDrop(unhandledDropEvent, "unhandled-drop")) {
                // The unhandled drag listener will call back to notify whether it has consumed
@@ -387,8 +394,7 @@ class DragState {
        }

        if (DEBUG_DRAG) Slog.d(TAG_WM, "Sending DROP to " + touchedWin);
        final DragEvent unhandledDropEvent = createUnhandledDropEvent(
                touchedWin.getBounds().left + inWindowX, touchedWin.getBounds().top + inWindowY);
        final DragEvent unhandledDropEvent = createUnhandledDropEvent(displayX, displayY);

        final IBinder clientToken = touchedWin.mClient.asBinder();
        final DragEvent event = createDropEvent(inWindowX, inWindowY, touchedWin);
+17 −4
Original line number Diff line number Diff line
@@ -815,18 +815,31 @@ public class DragDropControllerTests extends WindowTestsBase {
        final IGlobalDragListener listener = mock(IGlobalDragListener.class);
        doReturn(mock(Binder.class)).when(listener).asBinder();
        mTarget.setGlobalDragListener(listener);
        final int invalidXY = 100_000;
        final int displayXY = 1000;
        startDrag(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG,
                ClipData.newPlainText("label", "Test"), (unused) -> {
                    // Give the window some bounds
                    mWindow.setBounds(new Rect(100, 100, 200, 200));

                    // Trigger an unhandled drop and verify the global drag listener was called
                    mTarget.reportDropWindow(mWindow.mInputChannelToken, invalidXY, invalidXY);
                    final int windowX = displayXY - mWindow.getBounds().left;
                    final int windowY = displayXY - mWindow.getBounds().top;
                    mTarget.reportDropWindow(mWindow.mInputChannelToken, windowX, windowY);
                    mTarget.handleMotionEvent(false /* keepHandling */, mWindow.getDisplayId(),
                            invalidXY, invalidXY);
                            displayXY, displayXY);
                    mTarget.reportDropResult(mWindow.mClient, false);
                    mTarget.onUnhandledDropCallback(true);
                    mToken = null;
                    try {
                        verify(listener, times(1)).onUnhandledDrop(any(), any());
                        final ArgumentCaptor<DragEvent> dragEventCaptor =
                                ArgumentCaptor.forClass(DragEvent.class);
                        verify(listener, times(1)).onUnhandledDrop(dragEventCaptor.capture(),
                                any());

                        // Verify that the drag event is in global coordinates
                        final DragEvent dragEvent = dragEventCaptor.getValue();
                        assertEquals(displayXY, (int) dragEvent.getX());
                        assertEquals(displayXY, (int) dragEvent.getY());
                    } catch (RemoteException e) {
                        fail("Failed to verify unhandled drop: " + e);
                    }