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

Commit 767e205d authored by mattsziklay's avatar mattsziklay
Browse files

Update input sink to entire screen while resizing.

When a drag resize event has begun, increase the size of the input sink
to cover the entire screen. This prevents input and focus requests from
reaching any task behind the one being dragged.

Bug: 296926373
Test: Manual - drag task to various sizes/positions and attempt to have
another task steal focus

Change-Id: I27c15ef73ce28270cca92ac327b1c8cb68a8a60a
parent 57ea0232
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -149,7 +149,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
                    mDecorationContainerSurface,
                    mDecorationContainerSurface,
                    mDragPositioningCallback,
                    mDragPositioningCallback,
                    mSurfaceControlBuilderSupplier,
                    mSurfaceControlBuilderSupplier,
                    mSurfaceControlTransactionSupplier);
                    mSurfaceControlTransactionSupplier,
                    mDisplayController);
        }
        }


        final int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext())
        final int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext())
+2 −1
Original line number Original line Diff line number Diff line
@@ -293,7 +293,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                    mDecorationContainerSurface,
                    mDecorationContainerSurface,
                    mDragPositioningCallback,
                    mDragPositioningCallback,
                    mSurfaceControlBuilderSupplier,
                    mSurfaceControlBuilderSupplier,
                    mSurfaceControlTransactionSupplier);
                    mSurfaceControlTransactionSupplier,
                    mDisplayController);
        }
        }


        final int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext())
        final int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext())
+2 −1
Original line number Original line Diff line number Diff line
@@ -40,8 +40,9 @@ public interface DragPositioningCallback {
     *                 {@code 0} to indicate it's a move
     *                 {@code 0} to indicate it's a move
     * @param x x coordinate in window decoration coordinate system where the drag starts
     * @param x x coordinate in window decoration coordinate system where the drag starts
     * @param y y coordinate in window decoration coordinate system where the drag starts
     * @param y y coordinate in window decoration coordinate system where the drag starts
     * @return the starting task bounds
     */
     */
    void onDragPositioningStart(@CtrlType int ctrlType, float x, float y);
    Rect onDragPositioningStart(@CtrlType int ctrlType, float x, float y);


    /**
    /**
     * Called when the pointer moves during a drag-resize or drag-move.
     * Called when the pointer moves during a drag-resize or drag-move.
+60 −28
Original line number Original line Diff line number Diff line
@@ -50,6 +50,8 @@ import android.view.ViewConfiguration;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerGlobal;


import com.android.internal.view.BaseIWindow;
import com.android.internal.view.BaseIWindow;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;


import java.util.function.Supplier;
import java.util.function.Supplier;


@@ -78,6 +80,7 @@ class DragResizeInputListener implements AutoCloseable {
    private final SurfaceControl mInputSinkSurface;
    private final SurfaceControl mInputSinkSurface;
    private final BaseIWindow mFakeSinkWindow;
    private final BaseIWindow mFakeSinkWindow;
    private final InputChannel mSinkInputChannel;
    private final InputChannel mSinkInputChannel;
    private final DisplayController mDisplayController;


    private int mTaskWidth;
    private int mTaskWidth;
    private int mTaskHeight;
    private int mTaskHeight;
@@ -92,6 +95,7 @@ class DragResizeInputListener implements AutoCloseable {


    private int mDragPointerId = -1;
    private int mDragPointerId = -1;
    private DragDetector mDragDetector;
    private DragDetector mDragDetector;
    private final Region mTouchRegion = new Region();


    DragResizeInputListener(
    DragResizeInputListener(
            Context context,
            Context context,
@@ -102,7 +106,8 @@ class DragResizeInputListener implements AutoCloseable {
            SurfaceControl decorationSurface,
            SurfaceControl decorationSurface,
            DragPositioningCallback callback,
            DragPositioningCallback callback,
            Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
            Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
            Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier) {
            Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
            DisplayController displayController) {
        mInputManager = context.getSystemService(InputManager.class);
        mInputManager = context.getSystemService(InputManager.class);
        mHandler = handler;
        mHandler = handler;
        mChoreographer = choreographer;
        mChoreographer = choreographer;
@@ -110,6 +115,7 @@ class DragResizeInputListener implements AutoCloseable {
        mDisplayId = displayId;
        mDisplayId = displayId;
        mTaskCornerRadius = taskCornerRadius;
        mTaskCornerRadius = taskCornerRadius;
        mDecorationSurface = decorationSurface;
        mDecorationSurface = decorationSurface;
        mDisplayController = displayController;
        // Use a fake window as the backing surface is a container layer, and we don't want to
        // Use a fake window as the backing surface is a container layer, and we don't want to
        // create a buffer layer for it, so we can't use ViewRootImpl.
        // create a buffer layer for it, so we can't use ViewRootImpl.
        mFakeWindow = new BaseIWindow();
        mFakeWindow = new BaseIWindow();
@@ -195,34 +201,34 @@ class DragResizeInputListener implements AutoCloseable {
        mCornerSize = cornerSize;
        mCornerSize = cornerSize;
        mDragDetector.setTouchSlop(touchSlop);
        mDragDetector.setTouchSlop(touchSlop);


        Region touchRegion = new Region();
        mTouchRegion.setEmpty();
        final Rect topInputBounds = new Rect(
        final Rect topInputBounds = new Rect(
                -mResizeHandleThickness,
                -mResizeHandleThickness,
                -mResizeHandleThickness,
                -mResizeHandleThickness,
                mTaskWidth + mResizeHandleThickness,
                mTaskWidth + mResizeHandleThickness,
                0);
                0);
        touchRegion.union(topInputBounds);
        mTouchRegion.union(topInputBounds);


        final Rect leftInputBounds = new Rect(
        final Rect leftInputBounds = new Rect(
                -mResizeHandleThickness,
                -mResizeHandleThickness,
                0,
                0,
                0,
                0,
                mTaskHeight);
                mTaskHeight);
        touchRegion.union(leftInputBounds);
        mTouchRegion.union(leftInputBounds);


        final Rect rightInputBounds = new Rect(
        final Rect rightInputBounds = new Rect(
                mTaskWidth,
                mTaskWidth,
                0,
                0,
                mTaskWidth + mResizeHandleThickness,
                mTaskWidth + mResizeHandleThickness,
                mTaskHeight);
                mTaskHeight);
        touchRegion.union(rightInputBounds);
        mTouchRegion.union(rightInputBounds);


        final Rect bottomInputBounds = new Rect(
        final Rect bottomInputBounds = new Rect(
                -mResizeHandleThickness,
                -mResizeHandleThickness,
                mTaskHeight,
                mTaskHeight,
                mTaskWidth + mResizeHandleThickness,
                mTaskWidth + mResizeHandleThickness,
                mTaskHeight + mResizeHandleThickness);
                mTaskHeight + mResizeHandleThickness);
        touchRegion.union(bottomInputBounds);
        mTouchRegion.union(bottomInputBounds);


        // Set up touch areas in each corner.
        // Set up touch areas in each corner.
        int cornerRadius = mCornerSize / 2;
        int cornerRadius = mCornerSize / 2;
@@ -231,28 +237,28 @@ class DragResizeInputListener implements AutoCloseable {
                -cornerRadius,
                -cornerRadius,
                cornerRadius,
                cornerRadius,
                cornerRadius);
                cornerRadius);
        touchRegion.union(mLeftTopCornerBounds);
        mTouchRegion.union(mLeftTopCornerBounds);


        mRightTopCornerBounds = new Rect(
        mRightTopCornerBounds = new Rect(
                mTaskWidth - cornerRadius,
                mTaskWidth - cornerRadius,
                -cornerRadius,
                -cornerRadius,
                mTaskWidth + cornerRadius,
                mTaskWidth + cornerRadius,
                cornerRadius);
                cornerRadius);
        touchRegion.union(mRightTopCornerBounds);
        mTouchRegion.union(mRightTopCornerBounds);


        mLeftBottomCornerBounds = new Rect(
        mLeftBottomCornerBounds = new Rect(
                -cornerRadius,
                -cornerRadius,
                mTaskHeight - cornerRadius,
                mTaskHeight - cornerRadius,
                cornerRadius,
                cornerRadius,
                mTaskHeight + cornerRadius);
                mTaskHeight + cornerRadius);
        touchRegion.union(mLeftBottomCornerBounds);
        mTouchRegion.union(mLeftBottomCornerBounds);


        mRightBottomCornerBounds = new Rect(
        mRightBottomCornerBounds = new Rect(
                mTaskWidth - cornerRadius,
                mTaskWidth - cornerRadius,
                mTaskHeight - cornerRadius,
                mTaskHeight - cornerRadius,
                mTaskWidth + cornerRadius,
                mTaskWidth + cornerRadius,
                mTaskHeight + cornerRadius);
                mTaskHeight + cornerRadius);
        touchRegion.union(mRightBottomCornerBounds);
        mTouchRegion.union(mRightBottomCornerBounds);


        try {
        try {
            mWindowSession.updateInputChannel(
            mWindowSession.updateInputChannel(
@@ -262,7 +268,7 @@ class DragResizeInputListener implements AutoCloseable {
                    FLAG_NOT_FOCUSABLE,
                    FLAG_NOT_FOCUSABLE,
                    PRIVATE_FLAG_TRUSTED_OVERLAY,
                    PRIVATE_FLAG_TRUSTED_OVERLAY,
                    INPUT_FEATURE_SPY,
                    INPUT_FEATURE_SPY,
                    touchRegion);
                    mTouchRegion);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            e.rethrowFromSystemServer();
        }
        }
@@ -281,19 +287,8 @@ class DragResizeInputListener implements AutoCloseable {
        // issue. However, were there touchscreen-only a region out of the task bounds, mouse
        // issue. However, were there touchscreen-only a region out of the task bounds, mouse
        // gestures will become no-op in that region, even though the mouse gestures may appear to
        // gestures will become no-op in that region, even though the mouse gestures may appear to
        // be performed on the input window behind the resize handle.
        // be performed on the input window behind the resize handle.
        touchRegion.op(0, 0, mTaskWidth, mTaskHeight, Region.Op.DIFFERENCE);
        mTouchRegion.op(0, 0, mTaskWidth, mTaskHeight, Region.Op.DIFFERENCE);
        try {
        updateSinkInputChannel(mTouchRegion);
            mWindowSession.updateInputChannel(
                    mSinkInputChannel.getToken(),
                    mDisplayId,
                    mInputSinkSurface,
                    FLAG_NOT_FOCUSABLE,
                    0 /* privateFlags */,
                    INPUT_FEATURE_NO_INPUT_CHANNEL,
                    touchRegion);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
        return true;
        return true;
    }
    }


@@ -309,6 +304,21 @@ class DragResizeInputListener implements AutoCloseable {
        return region;
        return region;
    }
    }


    private void updateSinkInputChannel(Region region) {
        try {
            mWindowSession.updateInputChannel(
                    mSinkInputChannel.getToken(),
                    mDisplayId,
                    mInputSinkSurface,
                    FLAG_NOT_FOCUSABLE,
                    0 /* privateFlags */,
                    INPUT_FEATURE_NO_INPUT_CHANNEL,
                    region);
        } catch (RemoteException ex) {
            ex.rethrowFromSystemServer();
        }
    }

    @Override
    @Override
    public void close() {
    public void close() {
        mInputEventReceiver.dispose();
        mInputEventReceiver.dispose();
@@ -337,6 +347,7 @@ class DragResizeInputListener implements AutoCloseable {
        private boolean mConsumeBatchEventScheduled;
        private boolean mConsumeBatchEventScheduled;
        private boolean mShouldHandleEvents;
        private boolean mShouldHandleEvents;
        private int mLastCursorType = PointerIcon.TYPE_DEFAULT;
        private int mLastCursorType = PointerIcon.TYPE_DEFAULT;
        private Rect mDragStartTaskBounds;


        private TaskResizeInputEventReceiver(
        private TaskResizeInputEventReceiver(
                InputChannel inputChannel, Handler handler, Choreographer choreographer) {
                InputChannel inputChannel, Handler handler, Choreographer choreographer) {
@@ -398,12 +409,15 @@ class DragResizeInputListener implements AutoCloseable {
                    }
                    }
                    if (mShouldHandleEvents) {
                    if (mShouldHandleEvents) {
                        mInputManager.pilferPointers(mInputChannel.getToken());
                        mInputManager.pilferPointers(mInputChannel.getToken());

                        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);
                        int ctrlType = calculateCtrlType(isTouch, x, y);
                        int ctrlType = calculateCtrlType(isTouch, x, y);
                        mCallback.onDragPositioningStart(ctrlType, rawX, rawY);
                        mDragStartTaskBounds = mCallback.onDragPositioningStart(ctrlType,
                                rawX, rawY);
                        // Increase the input sink region to cover the whole screen; this is to
                        // prevent input and focus from going to other tasks during a drag resize.
                        updateInputSinkRegionForDrag(mDragStartTaskBounds);
                        result = true;
                        result = true;
                    }
                    }
                    break;
                    break;
@@ -415,7 +429,8 @@ 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);
                    mCallback.onDragPositioningMove(rawX, rawY);
                    final Rect taskBounds = mCallback.onDragPositioningMove(rawX, rawY);
                    updateInputSinkRegionForDrag(taskBounds);
                    result = true;
                    result = true;
                    break;
                    break;
                }
                }
@@ -423,8 +438,13 @@ class DragResizeInputListener implements AutoCloseable {
                case MotionEvent.ACTION_CANCEL: {
                case MotionEvent.ACTION_CANCEL: {
                    if (mShouldHandleEvents) {
                    if (mShouldHandleEvents) {
                        int dragPointerIndex = e.findPointerIndex(mDragPointerId);
                        int dragPointerIndex = e.findPointerIndex(mDragPointerId);
                        mCallback.onDragPositioningEnd(
                        final Rect taskBounds = mCallback.onDragPositioningEnd(
                                e.getRawX(dragPointerIndex), e.getRawY(dragPointerIndex));
                                e.getRawX(dragPointerIndex), e.getRawY(dragPointerIndex));
                        // If taskBounds has changed, setGeometry will be called and update the
                        // sink region. Otherwise, we should revert it here.
                        if (taskBounds.equals(mDragStartTaskBounds)) {
                            updateSinkInputChannel(mTouchRegion);
                        }
                    }
                    }
                    mShouldHandleEvents = false;
                    mShouldHandleEvents = false;
                    mDragPointerId = -1;
                    mDragPointerId = -1;
@@ -444,6 +464,18 @@ class DragResizeInputListener implements AutoCloseable {
            return result;
            return result;
        }
        }


        private void updateInputSinkRegionForDrag(Rect taskBounds) {
            final DisplayLayout layout = mDisplayController.getDisplayLayout(mDisplayId);
            final Region dragTouchRegion = new Region(-taskBounds.left,
                    -taskBounds.top,
                    -taskBounds.left + layout.width(),
                    -taskBounds.top + layout.height());
            // Remove the localized task bounds from the touch region.
            taskBounds.offsetTo(0, 0);
            dragTouchRegion.op(taskBounds, Region.Op.DIFFERENCE);
            updateSinkInputChannel(dragTouchRegion);
        }

        private boolean isInCornerBounds(float xf, float yf) {
        private boolean isInCornerBounds(float xf, float yf) {
            return calculateCornersCtrlType(xf, yf) != 0;
            return calculateCornersCtrlType(xf, yf) != 0;
        }
        }
+2 −1
Original line number Original line Diff line number Diff line
@@ -68,7 +68,7 @@ class FluidResizeTaskPositioner implements DragPositioningCallback {
    }
    }


    @Override
    @Override
    public void onDragPositioningStart(int ctrlType, float x, float y) {
    public Rect onDragPositioningStart(int ctrlType, float x, float y) {
        mCtrlType = ctrlType;
        mCtrlType = ctrlType;
        mTaskBoundsAtDragStart.set(
        mTaskBoundsAtDragStart.set(
                mWindowDecoration.mTaskInfo.configuration.windowConfiguration.getBounds());
                mWindowDecoration.mTaskInfo.configuration.windowConfiguration.getBounds());
@@ -87,6 +87,7 @@ class FluidResizeTaskPositioner implements DragPositioningCallback {
            mDisplayController.getDisplayLayout(mWindowDecoration.mDisplay.getDisplayId())
            mDisplayController.getDisplayLayout(mWindowDecoration.mDisplay.getDisplayId())
                    .getStableBounds(mStableBounds);
                    .getStableBounds(mStableBounds);
        }
        }
        return mRepositionTaskBounds;
    }
    }


    @Override
    @Override
Loading