From 461d325b1c36ae0309aa8963482dec079fc35060 Mon Sep 17 00:00:00 2001 From: Jorge Gil Date: Fri, 3 Mar 2023 00:44:22 +0000 Subject: [PATCH] Do not mark mouse events as 'drag' on ACTION_DOWN An ACTION_DOWN event from a mouse was previously considered a 'drag event' even though it could also be just the start of a simple click. This caused the Desktop Mode to consume the click event without letting it pass through to the handle bar's click listener, resulting in the handle menu not being shown on mouse clicks. Instead, let DragDetector directly forward mouse events to the EventHandler since the it has no reason to take the slop threshold considerations unless they're touch events. Additionaly, adds 'drag' tracking to the window decor view model that is agnostic of the event source instead of peeking into the internal state of DragDetector, whose mDragEvent is now only used to detect *touch* drags. Bug: 270761142 Test: manual - use mouse/trackpad to click on the caption handle bar, verify it opens the handle menu Change-Id: I3a38acbf88f42ce9a372773599b39a893fd118e4 --- .../CaptionWindowDecorViewModel.java | 31 ++++++++++--------- .../DesktopModeWindowDecorViewModel.java | 29 ++++++----------- .../wm/shell/windowdecor/DragDetector.java | 17 ++++++---- 3 files changed, 36 insertions(+), 41 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java index 9224b3cbd798a..6b7ca421f5ed4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java @@ -193,6 +193,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { private final DragDetector mDragDetector; private int mDragPointerId = -1; + private boolean mIsDragging; private CaptionTouchEventListener( RunningTaskInfo taskInfo, @@ -223,19 +224,15 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { if (v.getId() != R.id.caption) { return false; } - mDragDetector.onMotionEvent(e); - - if (e.getAction() != MotionEvent.ACTION_DOWN) { - return false; + if (e.getAction() == MotionEvent.ACTION_DOWN) { + final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId); + if (!taskInfo.isFocused) { + final WindowContainerTransaction wct = new WindowContainerTransaction(); + wct.reorder(mTaskToken, true /* onTop */); + mSyncQueue.queue(wct); + } } - final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId); - if (taskInfo.isFocused) { - return false; - } - final WindowContainerTransaction wct = new WindowContainerTransaction(); - wct.reorder(mTaskToken, true /* onTop */); - mSyncQueue.queue(wct); - return true; + return mDragDetector.onMotionEvent(e); } /** @@ -253,20 +250,24 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { mDragPointerId = e.getPointerId(0); mDragPositioningCallback.onDragPositioningStart( 0 /* ctrlType */, e.getRawX(0), e.getRawY(0)); - break; + mIsDragging = false; + return false; } case MotionEvent.ACTION_MOVE: { int dragPointerIdx = e.findPointerIndex(mDragPointerId); mDragPositioningCallback.onDragPositioningMove( e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx)); - break; + mIsDragging = true; + return true; } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { int dragPointerIdx = e.findPointerIndex(mDragPointerId); mDragPositioningCallback.onDragPositioningEnd( e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx)); - break; + final boolean wasDragging = mIsDragging; + mIsDragging = false; + return wasDragging; } } return true; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java index c517f7be330b7..dee5f8fa74d87 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java @@ -223,6 +223,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { private final DragPositioningCallback mDragPositioningCallback; private final DragDetector mDragDetector; + private boolean mIsDragging; private int mDragPointerId = -1; private DesktopModeTouchEventListener( @@ -273,23 +274,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { if (id != R.id.caption_handle && id != R.id.desktop_mode_caption) { return false; } - switch (e.getAction()) { - case MotionEvent.ACTION_DOWN: - mDragDetector.onMotionEvent(e); - final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId); - if (taskInfo.isFocused) { - return mDragDetector.isDragEvent(); - } - return false; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - boolean res = mDragDetector.isDragEvent(); - mDragDetector.onMotionEvent(e); - return res; - default: - mDragDetector.onMotionEvent(e); - return mDragDetector.isDragEvent(); - } + return mDragDetector.onMotionEvent(e); } /** @@ -313,13 +298,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { mDragPointerId = e.getPointerId(0); mDragPositioningCallback.onDragPositioningStart( 0 /* ctrlType */, e.getRawX(0), e.getRawY(0)); - break; + mIsDragging = false; + return false; } case MotionEvent.ACTION_MOVE: { final int dragPointerIdx = e.findPointerIndex(mDragPointerId); mDragPositioningCallback.onDragPositioningMove( e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx)); - break; + mIsDragging = true; + return true; } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { @@ -336,7 +323,9 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { c -> c.moveToFullscreen(taskInfo)); } } - break; + final boolean wasDragging = mIsDragging; + mIsDragging = false; + return wasDragging; } } return true; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java index cf1850b923730..65b5a7a17afe8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java @@ -56,10 +56,15 @@ class DragDetector { * {@link #mEventHandler} handles the previous down event if the event shouldn't be passed */ boolean onMotionEvent(MotionEvent ev) { + final boolean isTouchScreen = + (ev.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN; + if (!isTouchScreen) { + // Only touches generate noisy moves, so mouse/trackpad events don't need to filtered + // to take the slop threshold into consideration. + return mEventHandler.handleMotionEvent(ev); + } switch (ev.getActionMasked()) { case ACTION_DOWN: { - // Only touch screens generate noisy moves. - mIsDragEvent = (ev.getSource() & SOURCE_TOUCHSCREEN) != SOURCE_TOUCHSCREEN; mDragPointerId = ev.getPointerId(0); float rawX = ev.getRawX(0); float rawY = ev.getRawY(0); @@ -72,8 +77,12 @@ class DragDetector { int dragPointerIndex = ev.findPointerIndex(mDragPointerId); float dx = ev.getRawX(dragPointerIndex) - mInputDownPoint.x; float dy = ev.getRawY(dragPointerIndex) - mInputDownPoint.y; + // Touches generate noisy moves, so only once the move is past the touch + // slop threshold should it be considered a drag. mIsDragEvent = Math.hypot(dx, dy) > mTouchSlop; } + // The event handler should only be notified about 'move' events if a drag has been + // detected. if (mIsDragEvent) { return mEventHandler.handleMotionEvent(ev); } else { @@ -94,10 +103,6 @@ class DragDetector { mTouchSlop = touchSlop; } - boolean isDragEvent() { - return mIsDragEvent; - } - private void resetState() { mIsDragEvent = false; mInputDownPoint.set(0, 0);