Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java +18 −10 Original line number Diff line number Diff line Loading @@ -124,7 +124,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { TaskPositioner taskPositioner = new TaskPositioner(mTaskOrganizer, windowDecoration, mDragStartListener); CaptionTouchEventListener touchEventListener = new CaptionTouchEventListener(taskInfo, taskPositioner); new CaptionTouchEventListener(taskInfo, taskPositioner, windowDecoration.getDragDetector()); windowDecoration.setCaptionListeners(touchEventListener, touchEventListener); windowDecoration.setDragResizeCallback(taskPositioner); setupWindowDecorationForTransition(taskInfo, startT, finishT); Loading Loading @@ -173,16 +174,18 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { private final int mTaskId; private final WindowContainerToken mTaskToken; private final DragResizeCallback mDragResizeCallback; private final DragDetector mDragDetector; private int mDragPointerId = -1; private boolean mDragActive = false; private CaptionTouchEventListener( RunningTaskInfo taskInfo, DragResizeCallback dragResizeCallback) { DragResizeCallback dragResizeCallback, DragDetector dragDetector) { mTaskId = taskInfo.taskId; mTaskToken = taskInfo.token; mDragResizeCallback = dragResizeCallback; mDragDetector = dragDetector; } @Override Loading Loading @@ -231,19 +234,21 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { @Override public boolean onTouch(View v, MotionEvent e) { boolean isDrag = false; int id = v.getId(); if (id != R.id.caption_handle && id != R.id.caption) { return false; } if (id == R.id.caption_handle || mDragActive) { if (id == R.id.caption_handle) { isDrag = mDragDetector.detectDragEvent(e); handleEventForMove(e); } if (e.getAction() != MotionEvent.ACTION_DOWN) { return false; return isDrag; } RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId); if (taskInfo.isFocused) { return false; return isDrag; } WindowContainerTransaction wct = new WindowContainerTransaction(); wct.reorder(mTaskToken, true /* onTop */); Loading @@ -251,6 +256,10 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { 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) { RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId); int windowingMode = mDesktopModeController Loading @@ -259,12 +268,12 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { return; } switch (e.getActionMasked()) { case MotionEvent.ACTION_DOWN: mDragActive = true; case MotionEvent.ACTION_DOWN: { mDragPointerId = e.getPointerId(0); mDragResizeCallback.onDragResizeStart( 0 /* ctrlType */, e.getRawX(0), e.getRawY(0)); break; } case MotionEvent.ACTION_MOVE: { int dragPointerIdx = e.findPointerIndex(mDragPointerId); mDragResizeCallback.onDragResizeMove( Loading @@ -273,7 +282,6 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { mDragActive = false; int dragPointerIdx = e.findPointerIndex(mDragPointerId); int statusBarHeight = mDisplayController.getDisplayLayout(taskInfo.displayId) .stableInsets().top; Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java +9 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL private boolean mDesktopActive; private DragDetector mDragDetector; private AdditionalWindow mHandleMenu; CaptionWindowDecoration( Loading @@ -79,6 +81,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL mChoreographer = choreographer; mSyncQueue = syncQueue; mDesktopActive = DesktopModeStatus.isActive(mContext); mDragDetector = new DragDetector(ViewConfiguration.get(context).getScaledTouchSlop()); } void setCaptionListeners( Loading @@ -92,6 +95,10 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL mDragResizeCallback = dragResizeCallback; } DragDetector getDragDetector() { return mDragDetector; } @Override void relayout(ActivityManager.RunningTaskInfo taskInfo) { final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); Loading Loading @@ -182,6 +189,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL } int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext()).getScaledTouchSlop(); mDragDetector.setTouchSlop(touchSlop); int resize_handle = mResult.mRootView.getResources() .getDimensionPixelSize(R.dimen.freeform_resize_handle); int resize_corner = mResult.mRootView.getResources() Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java 0 → 100644 +87 −0 Original line number Diff line number Diff line /* * 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; } } libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java +8 −15 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERL import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import android.content.Context; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.Region; import android.hardware.input.InputManager; Loading @@ -38,6 +37,7 @@ import android.view.InputEventReceiver; import android.view.MotionEvent; import android.view.PointerIcon; import android.view.SurfaceControl; import android.view.ViewConfiguration; import android.view.WindowManagerGlobal; import com.android.internal.view.BaseIWindow; Loading Loading @@ -76,7 +76,7 @@ class DragResizeInputListener implements AutoCloseable { private Rect mRightBottomCornerBounds; private int mDragPointerId = -1; private int mTouchSlop; private DragDetector mDragDetector; DragResizeInputListener( Context context, Loading Loading @@ -115,6 +115,7 @@ class DragResizeInputListener implements AutoCloseable { mInputEventReceiver = new TaskResizeInputEventReceiver( mInputChannel, mHandler, mChoreographer); mCallback = callback; mDragDetector = new DragDetector(ViewConfiguration.get(context).getScaledTouchSlop()); } /** Loading Loading @@ -146,7 +147,7 @@ class DragResizeInputListener implements AutoCloseable { mHeight = height; mResizeHandleThickness = resizeHandleThickness; mCornerSize = cornerSize; mTouchSlop = touchSlop; mDragDetector.setTouchSlop(touchSlop); Region touchRegion = new Region(); final Rect topInputBounds = new Rect(0, 0, mWidth, mResizeHandleThickness); Loading Loading @@ -228,7 +229,6 @@ class DragResizeInputListener implements AutoCloseable { private boolean mConsumeBatchEventScheduled; private boolean mShouldHandleEvents; private boolean mDragging; private final PointF mActionDownPoint = new PointF(); private TaskResizeInputEventReceiver( InputChannel inputChannel, Handler handler, Choreographer choreographer) { Loading Loading @@ -276,7 +276,9 @@ class DragResizeInputListener implements AutoCloseable { // Check if this is a touch event vs mouse event. // Touch events are tracked in four corners. Other events are tracked in resize edges. boolean isTouch = (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN; if (isTouch) { mDragging = mDragDetector.detectDragEvent(e); } switch (e.getActionMasked()) { case MotionEvent.ACTION_DOWN: { float x = e.getX(0); Loading @@ -290,7 +292,6 @@ class DragResizeInputListener implements AutoCloseable { mDragPointerId = e.getPointerId(0); float rawX = e.getRawX(0); float rawY = e.getRawY(0); mActionDownPoint.set(rawX, rawY); int ctrlType = calculateCtrlType(isTouch, x, y); mCallback.onDragResizeStart(ctrlType, rawX, rawY); result = true; Loading @@ -304,14 +305,7 @@ class DragResizeInputListener implements AutoCloseable { int dragPointerIndex = e.findPointerIndex(mDragPointerId); float rawX = e.getRawX(dragPointerIndex); float rawY = e.getRawY(dragPointerIndex); 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 { if (!isTouch) { // For all other types allow immediate dragging. mDragging = true; } Loading @@ -330,7 +324,6 @@ class DragResizeInputListener implements AutoCloseable { } mDragging = false; mShouldHandleEvents = false; mActionDownPoint.set(0, 0); mDragPointerId = -1; result = true; break; Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java +18 −10 Original line number Diff line number Diff line Loading @@ -124,7 +124,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { TaskPositioner taskPositioner = new TaskPositioner(mTaskOrganizer, windowDecoration, mDragStartListener); CaptionTouchEventListener touchEventListener = new CaptionTouchEventListener(taskInfo, taskPositioner); new CaptionTouchEventListener(taskInfo, taskPositioner, windowDecoration.getDragDetector()); windowDecoration.setCaptionListeners(touchEventListener, touchEventListener); windowDecoration.setDragResizeCallback(taskPositioner); setupWindowDecorationForTransition(taskInfo, startT, finishT); Loading Loading @@ -173,16 +174,18 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { private final int mTaskId; private final WindowContainerToken mTaskToken; private final DragResizeCallback mDragResizeCallback; private final DragDetector mDragDetector; private int mDragPointerId = -1; private boolean mDragActive = false; private CaptionTouchEventListener( RunningTaskInfo taskInfo, DragResizeCallback dragResizeCallback) { DragResizeCallback dragResizeCallback, DragDetector dragDetector) { mTaskId = taskInfo.taskId; mTaskToken = taskInfo.token; mDragResizeCallback = dragResizeCallback; mDragDetector = dragDetector; } @Override Loading Loading @@ -231,19 +234,21 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { @Override public boolean onTouch(View v, MotionEvent e) { boolean isDrag = false; int id = v.getId(); if (id != R.id.caption_handle && id != R.id.caption) { return false; } if (id == R.id.caption_handle || mDragActive) { if (id == R.id.caption_handle) { isDrag = mDragDetector.detectDragEvent(e); handleEventForMove(e); } if (e.getAction() != MotionEvent.ACTION_DOWN) { return false; return isDrag; } RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId); if (taskInfo.isFocused) { return false; return isDrag; } WindowContainerTransaction wct = new WindowContainerTransaction(); wct.reorder(mTaskToken, true /* onTop */); Loading @@ -251,6 +256,10 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { 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) { RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId); int windowingMode = mDesktopModeController Loading @@ -259,12 +268,12 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { return; } switch (e.getActionMasked()) { case MotionEvent.ACTION_DOWN: mDragActive = true; case MotionEvent.ACTION_DOWN: { mDragPointerId = e.getPointerId(0); mDragResizeCallback.onDragResizeStart( 0 /* ctrlType */, e.getRawX(0), e.getRawY(0)); break; } case MotionEvent.ACTION_MOVE: { int dragPointerIdx = e.findPointerIndex(mDragPointerId); mDragResizeCallback.onDragResizeMove( Loading @@ -273,7 +282,6 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { mDragActive = false; int dragPointerIdx = e.findPointerIndex(mDragPointerId); int statusBarHeight = mDisplayController.getDisplayLayout(taskInfo.displayId) .stableInsets().top; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java +9 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL private boolean mDesktopActive; private DragDetector mDragDetector; private AdditionalWindow mHandleMenu; CaptionWindowDecoration( Loading @@ -79,6 +81,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL mChoreographer = choreographer; mSyncQueue = syncQueue; mDesktopActive = DesktopModeStatus.isActive(mContext); mDragDetector = new DragDetector(ViewConfiguration.get(context).getScaledTouchSlop()); } void setCaptionListeners( Loading @@ -92,6 +95,10 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL mDragResizeCallback = dragResizeCallback; } DragDetector getDragDetector() { return mDragDetector; } @Override void relayout(ActivityManager.RunningTaskInfo taskInfo) { final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); Loading Loading @@ -182,6 +189,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL } int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext()).getScaledTouchSlop(); mDragDetector.setTouchSlop(touchSlop); int resize_handle = mResult.mRootView.getResources() .getDimensionPixelSize(R.dimen.freeform_resize_handle); int resize_corner = mResult.mRootView.getResources() Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java 0 → 100644 +87 −0 Original line number Diff line number Diff line /* * 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; } }
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java +8 −15 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERL import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import android.content.Context; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.Region; import android.hardware.input.InputManager; Loading @@ -38,6 +37,7 @@ import android.view.InputEventReceiver; import android.view.MotionEvent; import android.view.PointerIcon; import android.view.SurfaceControl; import android.view.ViewConfiguration; import android.view.WindowManagerGlobal; import com.android.internal.view.BaseIWindow; Loading Loading @@ -76,7 +76,7 @@ class DragResizeInputListener implements AutoCloseable { private Rect mRightBottomCornerBounds; private int mDragPointerId = -1; private int mTouchSlop; private DragDetector mDragDetector; DragResizeInputListener( Context context, Loading Loading @@ -115,6 +115,7 @@ class DragResizeInputListener implements AutoCloseable { mInputEventReceiver = new TaskResizeInputEventReceiver( mInputChannel, mHandler, mChoreographer); mCallback = callback; mDragDetector = new DragDetector(ViewConfiguration.get(context).getScaledTouchSlop()); } /** Loading Loading @@ -146,7 +147,7 @@ class DragResizeInputListener implements AutoCloseable { mHeight = height; mResizeHandleThickness = resizeHandleThickness; mCornerSize = cornerSize; mTouchSlop = touchSlop; mDragDetector.setTouchSlop(touchSlop); Region touchRegion = new Region(); final Rect topInputBounds = new Rect(0, 0, mWidth, mResizeHandleThickness); Loading Loading @@ -228,7 +229,6 @@ class DragResizeInputListener implements AutoCloseable { private boolean mConsumeBatchEventScheduled; private boolean mShouldHandleEvents; private boolean mDragging; private final PointF mActionDownPoint = new PointF(); private TaskResizeInputEventReceiver( InputChannel inputChannel, Handler handler, Choreographer choreographer) { Loading Loading @@ -276,7 +276,9 @@ class DragResizeInputListener implements AutoCloseable { // Check if this is a touch event vs mouse event. // Touch events are tracked in four corners. Other events are tracked in resize edges. boolean isTouch = (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN; if (isTouch) { mDragging = mDragDetector.detectDragEvent(e); } switch (e.getActionMasked()) { case MotionEvent.ACTION_DOWN: { float x = e.getX(0); Loading @@ -290,7 +292,6 @@ class DragResizeInputListener implements AutoCloseable { mDragPointerId = e.getPointerId(0); float rawX = e.getRawX(0); float rawY = e.getRawY(0); mActionDownPoint.set(rawX, rawY); int ctrlType = calculateCtrlType(isTouch, x, y); mCallback.onDragResizeStart(ctrlType, rawX, rawY); result = true; Loading @@ -304,14 +305,7 @@ class DragResizeInputListener implements AutoCloseable { int dragPointerIndex = e.findPointerIndex(mDragPointerId); float rawX = e.getRawX(dragPointerIndex); float rawY = e.getRawY(dragPointerIndex); 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 { if (!isTouch) { // For all other types allow immediate dragging. mDragging = true; } Loading @@ -330,7 +324,6 @@ class DragResizeInputListener implements AutoCloseable { } mDragging = false; mShouldHandleEvents = false; mActionDownPoint.set(0, 0); mDragPointerId = -1; result = true; break; Loading