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

Commit 4f228c30 authored by mattsziklay's avatar mattsziklay
Browse files

Prevent pilfering of resize events.

Adds a check to see if drag resize handler should handle an event when
other caption input is being handled. This is used in to prevent
pilfering in view model when we want a corner drag.

This fixes an issue where drag events in the area where caption and
resize handles intersect would trigger both drag types but immediately
cancel the drag resize, resulting in a reposition that sets bounds to
fullscreen on ACTION_UP.

This also restores the functionality of resize handles to be slightly
inside caption bounds.

Bug: 328413639
Test: Manual
Change-Id: I56a5ab2c22c4d32f3eac3ec745820d18cfe83b73
parent aab4db2c
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_HOVER_ENTER;
import static android.view.MotionEvent.ACTION_HOVER_EXIT;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.WindowInsets.Type.statusBars;

@@ -493,6 +494,12 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                        (int) e.getRawX(), (int) e.getRawY());
                final boolean isTransparentCaption =
                        TaskInfoKt.isTransparentCaptionBarAppearance(decoration.mTaskInfo);
                // MotionEvent's coordinates are relative to view, we want location in window
                // to offset position relative to caption as a whole.
                int[] viewLocation = new int[2];
                v.getLocationInWindow(viewLocation);
                final boolean isResizeEvent = decoration.shouldResizeListenerHandleEvent(e,
                        new Point(viewLocation[0], viewLocation[1]));
                // The caption window may be a spy window when the caption background is
                // transparent, which means events will fall through to the app window. Make
                // sure to cancel these events if they do not happen in the intersection of the
@@ -500,11 +507,11 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                // the drag-move or other caption gestures should take priority outside those
                // regions.
                mShouldPilferCaptionEvents = !(downInCustomizableCaptionRegion
                        && downInExclusionRegion && isTransparentCaption);
                        && downInExclusionRegion && isTransparentCaption) && !isResizeEvent;
            }

            if (!mShouldPilferCaptionEvents) {
                // The event will be handled by a window below.
                // The event will be handled by a window below or pilfered by resize handler.
                return false;
            }
            // Otherwise pilfer so that windows below receive cancellations for this gesture, and
@@ -604,7 +611,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                    // prevent the button's ripple effect from showing.
                    return !touchingButton;
                }
                case MotionEvent.ACTION_MOVE: {
                case ACTION_MOVE: {
                    // If a decor's resize drag zone is active, don't also try to reposition it.
                    if (decoration.isHandlingDragResize()) break;
                    decoration.closeMaximizeMenu();
@@ -863,7 +870,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                break;
            }

            case MotionEvent.ACTION_MOVE: {
            case ACTION_MOVE: {
                if (relevantDecor == null) {
                    return;
                }
+4 −0
Original line number Diff line number Diff line
@@ -421,6 +421,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        return mHandleMenu != null;
    }

    boolean shouldResizeListenerHandleEvent(MotionEvent e, Point offset) {
        return mDragResizeListener.shouldHandleEvent(e, offset);
    }

    boolean isHandlingDragResize() {
        return mDragResizeListener != null && mDragResizeListener.isHandlingDragResize();
    }
+29 −9
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP;

import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.input.InputManager;
@@ -321,6 +322,10 @@ class DragResizeInputListener implements AutoCloseable {
        }
    }

    boolean shouldHandleEvent(MotionEvent e, Point offset) {
        return mInputEventReceiver.shouldHandleEvent(e, offset);
    }

    boolean isHandlingDragResize() {
        return mInputEventReceiver.isHandlingEvents();
    }
@@ -408,18 +413,14 @@ class DragResizeInputListener implements AutoCloseable {
            boolean result = false;
            // 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;
            boolean isTouch = isTouchEvent(e);
            switch (e.getActionMasked()) {
                case MotionEvent.ACTION_DOWN: {
                    float x = e.getX(0);
                    float y = e.getY(0);
                    if (isTouch) {
                        mShouldHandleEvents = isInCornerBounds(x, y);
                    } else {
                        mShouldHandleEvents = isInResizeHandleBounds(x, y);
                    }
                    mShouldHandleEvents = shouldHandleEvent(e, isTouch, new Point() /* offset */);
                    if (mShouldHandleEvents) {
                        mDragPointerId = e.getPointerId(0);
                        float x = e.getX(0);
                        float y = e.getY(0);
                        float rawX = e.getRawX(0);
                        float rawY = e.getRawY(0);
                        int ctrlType = calculateCtrlType(isTouch, x, y);
@@ -447,7 +448,6 @@ class DragResizeInputListener implements AutoCloseable {
                }
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL: {
                    mInputManager.pilferPointers(mInputChannel.getToken());
                    if (mShouldHandleEvents) {
                        int dragPointerIndex = e.findPointerIndex(mDragPointerId);
                        final Rect taskBounds = mCallback.onDragPositioningEnd(
@@ -638,5 +638,25 @@ class DragResizeInputListener implements AutoCloseable {
                mLastCursorType = cursorType;
            }
        }

        private boolean shouldHandleEvent(MotionEvent e, Point offset) {
            return shouldHandleEvent(e, isTouchEvent(e), offset);
        }

        private boolean shouldHandleEvent(MotionEvent e, boolean isTouch, Point offset) {
            boolean result;
            final float x = e.getX(0) + offset.x;
            final float y = e.getY(0) + offset.y;
            if (isTouch) {
                result = isInCornerBounds(x, y);
            } else {
                result = isInResizeHandleBounds(x, y);
            }
            return result;
        }

        private boolean isTouchEvent(MotionEvent e) {
            return (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN;
        }
    }
}