Merge "Prevent handle menu from opening on drag." into tm-qpr-dev

This commit is contained in:
Matt Sziklay
2022-11-15 18:03:47 +00:00
committed by Android (Google) Code Review
4 changed files with 122 additions and 25 deletions

View File

@@ -124,7 +124,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
TaskPositioner taskPositioner = new TaskPositioner(mTaskOrganizer, windowDecoration, TaskPositioner taskPositioner = new TaskPositioner(mTaskOrganizer, windowDecoration,
mDragStartListener); mDragStartListener);
CaptionTouchEventListener touchEventListener = CaptionTouchEventListener touchEventListener =
new CaptionTouchEventListener(taskInfo, taskPositioner); new CaptionTouchEventListener(taskInfo, taskPositioner,
windowDecoration.getDragDetector());
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener); windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
windowDecoration.setDragResizeCallback(taskPositioner); windowDecoration.setDragResizeCallback(taskPositioner);
setupWindowDecorationForTransition(taskInfo, startT, finishT); setupWindowDecorationForTransition(taskInfo, startT, finishT);
@@ -173,16 +174,18 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
private final int mTaskId; private final int mTaskId;
private final WindowContainerToken mTaskToken; private final WindowContainerToken mTaskToken;
private final DragResizeCallback mDragResizeCallback; private final DragResizeCallback mDragResizeCallback;
private final DragDetector mDragDetector;
private int mDragPointerId = -1; private int mDragPointerId = -1;
private boolean mDragActive = false;
private CaptionTouchEventListener( private CaptionTouchEventListener(
RunningTaskInfo taskInfo, RunningTaskInfo taskInfo,
DragResizeCallback dragResizeCallback) { DragResizeCallback dragResizeCallback,
DragDetector dragDetector) {
mTaskId = taskInfo.taskId; mTaskId = taskInfo.taskId;
mTaskToken = taskInfo.token; mTaskToken = taskInfo.token;
mDragResizeCallback = dragResizeCallback; mDragResizeCallback = dragResizeCallback;
mDragDetector = dragDetector;
} }
@Override @Override
@@ -231,19 +234,21 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
@Override @Override
public boolean onTouch(View v, MotionEvent e) { public boolean onTouch(View v, MotionEvent e) {
boolean isDrag = false;
int id = v.getId(); int id = v.getId();
if (id != R.id.caption_handle && id != R.id.caption) { if (id != R.id.caption_handle && id != R.id.caption) {
return false; return false;
} }
if (id == R.id.caption_handle || mDragActive) { if (id == R.id.caption_handle) {
isDrag = mDragDetector.detectDragEvent(e);
handleEventForMove(e); handleEventForMove(e);
} }
if (e.getAction() != MotionEvent.ACTION_DOWN) { if (e.getAction() != MotionEvent.ACTION_DOWN) {
return false; return isDrag;
} }
RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId); RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
if (taskInfo.isFocused) { if (taskInfo.isFocused) {
return false; return isDrag;
} }
WindowContainerTransaction wct = new WindowContainerTransaction(); WindowContainerTransaction wct = new WindowContainerTransaction();
wct.reorder(mTaskToken, true /* onTop */); wct.reorder(mTaskToken, true /* onTop */);
@@ -251,6 +256,10 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
return true; return true;
} }
/**
* @param e {@link MotionEvent} to process
* @return {@code true} if a drag is happening; or {@code false} if it is not
*/
private void handleEventForMove(MotionEvent e) { private void handleEventForMove(MotionEvent e) {
RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId); RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
int windowingMode = mDesktopModeController int windowingMode = mDesktopModeController
@@ -259,12 +268,12 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
return; return;
} }
switch (e.getActionMasked()) { switch (e.getActionMasked()) {
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN: {
mDragActive = true; mDragPointerId = e.getPointerId(0);
mDragPointerId = e.getPointerId(0);
mDragResizeCallback.onDragResizeStart( mDragResizeCallback.onDragResizeStart(
0 /* ctrlType */, e.getRawX(0), e.getRawY(0)); 0 /* ctrlType */, e.getRawX(0), e.getRawY(0));
break; break;
}
case MotionEvent.ACTION_MOVE: { case MotionEvent.ACTION_MOVE: {
int dragPointerIdx = e.findPointerIndex(mDragPointerId); int dragPointerIdx = e.findPointerIndex(mDragPointerId);
mDragResizeCallback.onDragResizeMove( mDragResizeCallback.onDragResizeMove(
@@ -273,7 +282,6 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
} }
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: { case MotionEvent.ACTION_CANCEL: {
mDragActive = false;
int dragPointerIdx = e.findPointerIndex(mDragPointerId); int dragPointerIdx = e.findPointerIndex(mDragPointerId);
int statusBarHeight = mDisplayController.getDisplayLayout(taskInfo.displayId) int statusBarHeight = mDisplayController.getDisplayLayout(taskInfo.displayId)
.stableInsets().top; .stableInsets().top;

View File

@@ -62,6 +62,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
private boolean mDesktopActive; private boolean mDesktopActive;
private DragDetector mDragDetector;
private AdditionalWindow mHandleMenu; private AdditionalWindow mHandleMenu;
CaptionWindowDecoration( CaptionWindowDecoration(
@@ -79,6 +81,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
mChoreographer = choreographer; mChoreographer = choreographer;
mSyncQueue = syncQueue; mSyncQueue = syncQueue;
mDesktopActive = DesktopModeStatus.isActive(mContext); mDesktopActive = DesktopModeStatus.isActive(mContext);
mDragDetector = new DragDetector(ViewConfiguration.get(context).getScaledTouchSlop());
} }
void setCaptionListeners( void setCaptionListeners(
@@ -92,6 +95,10 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
mDragResizeCallback = dragResizeCallback; mDragResizeCallback = dragResizeCallback;
} }
DragDetector getDragDetector() {
return mDragDetector;
}
@Override @Override
void relayout(ActivityManager.RunningTaskInfo taskInfo) { void relayout(ActivityManager.RunningTaskInfo taskInfo) {
final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
@@ -182,6 +189,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
} }
int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext()).getScaledTouchSlop(); int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext()).getScaledTouchSlop();
mDragDetector.setTouchSlop(touchSlop);
int resize_handle = mResult.mRootView.getResources() int resize_handle = mResult.mRootView.getResources()
.getDimensionPixelSize(R.dimen.freeform_resize_handle); .getDimensionPixelSize(R.dimen.freeform_resize_handle);
int resize_corner = mResult.mRootView.getResources() int resize_corner = mResult.mRootView.getResources()

View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wm.shell.windowdecor;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_UP;
import android.graphics.PointF;
import android.view.MotionEvent;
/**
* A detector for touch inputs that differentiates between drag and click inputs.
* All touch events must be passed through this class to track a drag event.
*/
public class DragDetector {
private int mTouchSlop;
private PointF mInputDownPoint;
private boolean mIsDragEvent;
private int mDragPointerId;
public DragDetector(int touchSlop) {
mTouchSlop = touchSlop;
mInputDownPoint = new PointF();
mIsDragEvent = false;
mDragPointerId = -1;
}
/**
* Determine if {@link MotionEvent} is part of a drag event.
* @return {@code true} if this is a drag event, {@code false} if not
*/
public boolean detectDragEvent(MotionEvent ev) {
switch (ev.getAction()) {
case ACTION_DOWN: {
mDragPointerId = ev.getPointerId(0);
float rawX = ev.getRawX(0);
float rawY = ev.getRawY(0);
mInputDownPoint.set(rawX, rawY);
return false;
}
case ACTION_MOVE: {
if (!mIsDragEvent) {
int dragPointerIndex = ev.findPointerIndex(mDragPointerId);
float dx = ev.getRawX(dragPointerIndex) - mInputDownPoint.x;
float dy = ev.getRawY(dragPointerIndex) - mInputDownPoint.y;
if (Math.hypot(dx, dy) > mTouchSlop) {
mIsDragEvent = true;
}
}
return mIsDragEvent;
}
case ACTION_UP: {
boolean result = mIsDragEvent;
mIsDragEvent = false;
mInputDownPoint.set(0, 0);
mDragPointerId = -1;
return result;
}
case ACTION_CANCEL: {
mIsDragEvent = false;
mInputDownPoint.set(0, 0);
mDragPointerId = -1;
return false;
}
}
return mIsDragEvent;
}
public void setTouchSlop(int touchSlop) {
mTouchSlop = touchSlop;
}
}

View File

@@ -22,7 +22,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERL
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import android.content.Context; import android.content.Context;
import android.graphics.PointF;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.Region; import android.graphics.Region;
import android.hardware.input.InputManager; import android.hardware.input.InputManager;
@@ -38,6 +37,7 @@ import android.view.InputEventReceiver;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.PointerIcon; import android.view.PointerIcon;
import android.view.SurfaceControl; import android.view.SurfaceControl;
import android.view.ViewConfiguration;
import android.view.WindowManagerGlobal; import android.view.WindowManagerGlobal;
import com.android.internal.view.BaseIWindow; import com.android.internal.view.BaseIWindow;
@@ -76,7 +76,7 @@ class DragResizeInputListener implements AutoCloseable {
private Rect mRightBottomCornerBounds; private Rect mRightBottomCornerBounds;
private int mDragPointerId = -1; private int mDragPointerId = -1;
private int mTouchSlop; private DragDetector mDragDetector;
DragResizeInputListener( DragResizeInputListener(
Context context, Context context,
@@ -115,6 +115,7 @@ class DragResizeInputListener implements AutoCloseable {
mInputEventReceiver = new TaskResizeInputEventReceiver( mInputEventReceiver = new TaskResizeInputEventReceiver(
mInputChannel, mHandler, mChoreographer); mInputChannel, mHandler, mChoreographer);
mCallback = callback; mCallback = callback;
mDragDetector = new DragDetector(ViewConfiguration.get(context).getScaledTouchSlop());
} }
/** /**
@@ -146,7 +147,7 @@ class DragResizeInputListener implements AutoCloseable {
mHeight = height; mHeight = height;
mResizeHandleThickness = resizeHandleThickness; mResizeHandleThickness = resizeHandleThickness;
mCornerSize = cornerSize; mCornerSize = cornerSize;
mTouchSlop = touchSlop; mDragDetector.setTouchSlop(touchSlop);
Region touchRegion = new Region(); Region touchRegion = new Region();
final Rect topInputBounds = new Rect(0, 0, mWidth, mResizeHandleThickness); final Rect topInputBounds = new Rect(0, 0, mWidth, mResizeHandleThickness);
@@ -228,7 +229,6 @@ class DragResizeInputListener implements AutoCloseable {
private boolean mConsumeBatchEventScheduled; private boolean mConsumeBatchEventScheduled;
private boolean mShouldHandleEvents; private boolean mShouldHandleEvents;
private boolean mDragging; private boolean mDragging;
private final PointF mActionDownPoint = new PointF();
private TaskResizeInputEventReceiver( private TaskResizeInputEventReceiver(
InputChannel inputChannel, Handler handler, Choreographer choreographer) { InputChannel inputChannel, Handler handler, Choreographer choreographer) {
@@ -276,7 +276,9 @@ class DragResizeInputListener implements AutoCloseable {
// Check if this is a touch event vs mouse event. // Check if this is a touch event vs mouse event.
// Touch events are tracked in four corners. Other events are tracked in resize edges. // Touch events are tracked in four corners. Other events are tracked in resize edges.
boolean isTouch = (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN; boolean isTouch = (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN;
if (isTouch) {
mDragging = mDragDetector.detectDragEvent(e);
}
switch (e.getActionMasked()) { switch (e.getActionMasked()) {
case MotionEvent.ACTION_DOWN: { case MotionEvent.ACTION_DOWN: {
float x = e.getX(0); float x = e.getX(0);
@@ -290,7 +292,6 @@ class DragResizeInputListener implements AutoCloseable {
mDragPointerId = e.getPointerId(0); mDragPointerId = e.getPointerId(0);
float rawX = e.getRawX(0); float rawX = e.getRawX(0);
float rawY = e.getRawY(0); float rawY = e.getRawY(0);
mActionDownPoint.set(rawX, rawY);
int ctrlType = calculateCtrlType(isTouch, x, y); int ctrlType = calculateCtrlType(isTouch, x, y);
mCallback.onDragResizeStart(ctrlType, rawX, rawY); mCallback.onDragResizeStart(ctrlType, rawX, rawY);
result = true; result = true;
@@ -304,14 +305,7 @@ class DragResizeInputListener implements AutoCloseable {
int dragPointerIndex = e.findPointerIndex(mDragPointerId); int dragPointerIndex = e.findPointerIndex(mDragPointerId);
float rawX = e.getRawX(dragPointerIndex); float rawX = e.getRawX(dragPointerIndex);
float rawY = e.getRawY(dragPointerIndex); float rawY = e.getRawY(dragPointerIndex);
if (isTouch) { if (!isTouch) {
// Check for touch slop for touch events
float dx = rawX - mActionDownPoint.x;
float dy = rawY - mActionDownPoint.y;
if (!mDragging && Math.hypot(dx, dy) > mTouchSlop) {
mDragging = true;
}
} else {
// For all other types allow immediate dragging. // For all other types allow immediate dragging.
mDragging = true; mDragging = true;
} }
@@ -330,7 +324,6 @@ class DragResizeInputListener implements AutoCloseable {
} }
mDragging = false; mDragging = false;
mShouldHandleEvents = false; mShouldHandleEvents = false;
mActionDownPoint.set(0, 0);
mDragPointerId = -1; mDragPointerId = -1;
result = true; result = true;
break; break;