diff options
4 files changed, 77 insertions, 12 deletions
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 ca91d580b4ac..716f8b81f158 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 @@ -57,6 +57,7 @@ import android.view.MotionEvent; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.View; +import android.view.ViewConfiguration; import android.view.WindowManager; import android.window.TransitionInfo; import android.window.WindowContainerToken; @@ -362,7 +363,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { private class DesktopModeTouchEventListener extends GestureDetector.SimpleOnGestureListener implements View.OnClickListener, View.OnTouchListener, View.OnLongClickListener, - DragDetector.MotionEventHandler{ + DragDetector.MotionEventHandler { private final int mTaskId; private final WindowContainerToken mTaskToken; @@ -371,6 +372,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { private final GestureDetector mGestureDetector; private boolean mIsDragging; + private boolean mHasLongClicked; private boolean mShouldClick; private int mDragPointerId = -1; @@ -394,11 +396,9 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { RunningTaskInfo remainingTask = getOtherSplitTask(mTaskId); mSplitScreenController.moveTaskToFullscreen(remainingTask.taskId); } - decoration.closeMaximizeMenu(); } else if (id == R.id.back_button) { mTaskOperations.injectBackKey(); } else if (id == R.id.caption_handle || id == R.id.open_menu_button) { - decoration.closeMaximizeMenu(); if (!decoration.isHandleMenuActive()) { moveTaskToFront(mTaskOrganizer.getRunningTaskInfo(mTaskId)); decoration.createHandleMenu(); @@ -433,7 +433,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { mDesktopTasksController.ifPresent(c -> c.moveToNextDisplay(mTaskId)); } } else if (id == R.id.maximize_window) { - moveTaskToFront(decoration.mTaskInfo); if (decoration.isMaximizeMenuActive()) { decoration.closeMaximizeMenu(); return; @@ -467,10 +466,26 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { public boolean onTouch(View v, MotionEvent e) { final int id = v.getId(); if (id != R.id.caption_handle && id != R.id.desktop_mode_caption - && id != R.id.open_menu_button && id != R.id.close_window) { + && id != R.id.open_menu_button && id != R.id.close_window + && id != R.id.maximize_window) { return false; } moveTaskToFront(mTaskOrganizer.getRunningTaskInfo(mTaskId)); + + if (!mHasLongClicked) { + final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId); + decoration.closeMaximizeMenu(); + } + + final long eventDuration = e.getEventTime() - e.getDownTime(); + final boolean shouldLongClick = id == R.id.maximize_window && !mIsDragging + && !mHasLongClicked && eventDuration >= ViewConfiguration.getLongPressTimeout(); + if (shouldLongClick) { + v.performLongClick(); + mHasLongClicked = true; + return true; + } + return mDragDetector.onMotionEvent(v, e); } @@ -483,7 +498,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { if (decoration.isMaximizeMenuActive()) { decoration.closeMaximizeMenu(); } else { - decoration.closeHandleMenu(); decoration.createMaximizeMenu(); } return true; @@ -519,11 +533,13 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { e.getRawY(0)); mIsDragging = false; mShouldClick = true; + mHasLongClicked = false; return true; } case MotionEvent.ACTION_MOVE: { final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId); + decoration.closeMaximizeMenu(); if (e.findPointerIndex(mDragPointerId) == -1) { mDragPointerId = e.getPointerId(0); } @@ -542,7 +558,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { case MotionEvent.ACTION_CANCEL: { final boolean wasDragging = mIsDragging; if (!wasDragging) { - if (mShouldClick && v != null) { + if (mShouldClick && v != null && !mHasLongClicked) { v.performClick(); mShouldClick = false; return true; @@ -685,14 +701,16 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { // If an UP/CANCEL action is received outside of caption bounds, turn off handle menu private void handleEventOutsideFocusedCaption(MotionEvent ev, DesktopModeWindowDecoration relevantDecor) { + // Returns if event occurs within caption + if (relevantDecor == null || relevantDecor.checkTouchEventInCaption(ev)) { + return; + } + final int action = ev.getActionMasked(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { - if (relevantDecor == null) { - return; - } - if (!mTransitionDragActive) { relevantDecor.closeHandleMenuIfNeeded(ev); + relevantDecor.closeMaximizeMenuIfNeeded(ev); } } } @@ -1024,7 +1042,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { public void onDragStart(int taskId) { final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId); decoration.closeHandleMenu(); - decoration.closeMaximizeMenu(); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java index a976584e9811..eba1a36ef29f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java @@ -521,6 +521,20 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin } } + /** + * Close an open maximize menu if input is outside of menu coordinates + * + * @param ev the tapped point to compare against + */ + void closeMaximizeMenuIfNeeded(MotionEvent ev) { + if (!isMaximizeMenuActive()) return; + + final PointF inputPoint = offsetCaptionLocation(ev); + if (!mMaximizeMenu.isValidMenuInput(inputPoint)) { + closeMaximizeMenu(); + } + } + boolean isFocused() { return mTaskInfo.isFocused; } @@ -560,6 +574,13 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin } /** + * Returns true if motion event is within the caption's root view's bounds. + */ + boolean checkTouchEventInCaption(MotionEvent ev) { + return checkEventInCaptionView(ev, getCaptionViewId()); + } + + /** * Check a passed MotionEvent if a click has occurred on any button on this caption * Note this should only be called when a regular onClick is not possible * (i.e. the button was clicked through status bar layer) @@ -574,6 +595,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin clickIfPointInView(new PointF(ev.getX(), ev.getY()), handle); } else { mHandleMenu.checkClickEvent(ev); + closeHandleMenuIfNeeded(ev); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt index 050d1e9df392..921708faab16 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt @@ -25,6 +25,7 @@ import android.view.LayoutInflater import android.view.SurfaceControl import android.view.SurfaceControl.Transaction import android.view.SurfaceControlViewHost +import android.view.View import android.view.View.OnClickListener import android.view.WindowManager import android.view.WindowlessWindowManager @@ -151,4 +152,28 @@ class MaximizeMenu( R.id.maximize_menu_snap_left_button ).setOnClickListener(onClickListener) } + + /** + * A valid menu input is one of the following: + * An input that happens in the menu views. + * Any input before the views have been laid out. + * + * @param inputPoint the input to compare against. + */ + fun isValidMenuInput(inputPoint: PointF): Boolean { + val menuView = maximizeMenu?.mWindowViewHost?.view ?: return true + return !viewsLaidOut() || pointInView(menuView, inputPoint.x - menuPosition.x, + inputPoint.y - menuPosition.y) + } + + private fun pointInView(v: View, x: Float, y: Float): Boolean { + return v.left <= x && v.right >= x && v.top <= y && v.bottom >= y + } + + /** + * Check if the views for maximize menu can be seen. + */ + private fun viewsLaidOut(): Boolean { + return maximizeMenu?.mWindowViewHost?.view?.isLaidOut ?: false + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt index d64312a1c0c8..b739ad3793e4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt @@ -41,6 +41,7 @@ internal class DesktopModeAppControlsWindowDecorationViewHolder( openMenuButton.setOnTouchListener(onCaptionTouchListener) closeWindowButton.setOnClickListener(onCaptionButtonClickListener) maximizeWindowButton.setOnClickListener(onCaptionButtonClickListener) + maximizeWindowButton.setOnTouchListener(onCaptionTouchListener) maximizeWindowButton.onLongClickListener = onLongClickListener closeWindowButton.setOnTouchListener(onCaptionTouchListener) appNameTextView.text = appName |