Merge "Use spy windows to resize tasks" into udc-qpr-dev

This commit is contained in:
Garfield Tan
2023-07-05 18:02:26 +00:00
committed by Android (Google) Code Review
5 changed files with 115 additions and 12 deletions

View File

@@ -145,7 +145,9 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
mDisplay.getDisplayId(),
0 /* taskCornerRadius */,
mDecorationContainerSurface,
mDragPositioningCallback);
mDragPositioningCallback,
mSurfaceControlBuilderSupplier,
mSurfaceControlTransactionSupplier);
}
final int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext())

View File

@@ -234,7 +234,9 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mDisplay.getDisplayId(),
mRelayoutParams.mCornerRadius,
mDecorationContainerSurface,
mDragPositioningCallback);
mDragPositioningCallback,
mSurfaceControlBuilderSupplier,
mSurfaceControlTransactionSupplier);
}
final int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext())

View File

@@ -22,7 +22,9 @@ import android.annotation.IntDef;
* Callback called when receiving drag-resize or drag-move related input events.
*/
public interface DragPositioningCallback {
@IntDef({CTRL_TYPE_UNDEFINED, CTRL_TYPE_LEFT, CTRL_TYPE_RIGHT, CTRL_TYPE_TOP, CTRL_TYPE_BOTTOM})
@IntDef(flag = true, value = {
CTRL_TYPE_UNDEFINED, CTRL_TYPE_LEFT, CTRL_TYPE_RIGHT, CTRL_TYPE_TOP, CTRL_TYPE_BOTTOM
})
@interface CtrlType {}
int CTRL_TYPE_UNDEFINED = 0;

View File

@@ -18,8 +18,11 @@ package com.android.wm.shell.windowdecor;
import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_BOTTOM;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_LEFT;
@@ -48,6 +51,8 @@ import android.view.WindowManagerGlobal;
import com.android.internal.view.BaseIWindow;
import java.util.function.Supplier;
/**
* An input event listener registered to InputDispatcher to receive input events on task edges and
* and corners. Converts them to drag resize requests.
@@ -60,6 +65,7 @@ class DragResizeInputListener implements AutoCloseable {
private final Handler mHandler;
private final Choreographer mChoreographer;
private final InputManager mInputManager;
private final Supplier<SurfaceControl.Transaction> mSurfaceControlTransactionSupplier;
private final int mDisplayId;
private final BaseIWindow mFakeWindow;
@@ -69,6 +75,10 @@ class DragResizeInputListener implements AutoCloseable {
private final TaskResizeInputEventReceiver mInputEventReceiver;
private final DragPositioningCallback mCallback;
private final SurfaceControl mInputSinkSurface;
private final BaseIWindow mFakeSinkWindow;
private final InputChannel mSinkInputChannel;
private int mTaskWidth;
private int mTaskHeight;
private int mResizeHandleThickness;
@@ -90,15 +100,18 @@ class DragResizeInputListener implements AutoCloseable {
int displayId,
int taskCornerRadius,
SurfaceControl decorationSurface,
DragPositioningCallback callback) {
DragPositioningCallback callback,
Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier) {
mInputManager = context.getSystemService(InputManager.class);
mHandler = handler;
mChoreographer = choreographer;
mSurfaceControlTransactionSupplier = surfaceControlTransactionSupplier;
mDisplayId = displayId;
mTaskCornerRadius = taskCornerRadius;
mDecorationSurface = decorationSurface;
// 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.
// 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.
mFakeWindow = new BaseIWindow();
mFakeWindow.setSession(mWindowSession);
mFocusGrantToken = new Binder();
@@ -111,7 +124,7 @@ class DragResizeInputListener implements AutoCloseable {
null /* hostInputToken */,
FLAG_NOT_FOCUSABLE,
PRIVATE_FLAG_TRUSTED_OVERLAY,
0 /* inputFeatures */,
INPUT_FEATURE_SPY,
TYPE_APPLICATION,
null /* windowToken */,
mFocusGrantToken,
@@ -126,6 +139,35 @@ class DragResizeInputListener implements AutoCloseable {
mCallback = callback;
mDragDetector = new DragDetector(mInputEventReceiver);
mDragDetector.setTouchSlop(ViewConfiguration.get(context).getScaledTouchSlop());
mInputSinkSurface = surfaceControlBuilderSupplier.get()
.setName("TaskInputSink of " + decorationSurface)
.setContainerLayer()
.setParent(mDecorationSurface)
.build();
mSurfaceControlTransactionSupplier.get()
.setLayer(mInputSinkSurface, WindowDecoration.INPUT_SINK_Z_ORDER)
.show(mInputSinkSurface)
.apply();
mFakeSinkWindow = new BaseIWindow();
mSinkInputChannel = new InputChannel();
try {
mWindowSession.grantInputChannel(
mDisplayId,
mInputSinkSurface,
mFakeSinkWindow,
null /* hostInputToken */,
FLAG_NOT_FOCUSABLE,
0 /* privateFlags */,
INPUT_FEATURE_NO_INPUT_CHANNEL,
TYPE_INPUT_CONSUMER,
null /* windowToken */,
mFocusGrantToken,
"TaskInputSink of " + decorationSurface,
mSinkInputChannel);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
}
/**
@@ -219,7 +261,35 @@ class DragResizeInputListener implements AutoCloseable {
mDecorationSurface,
FLAG_NOT_FOCUSABLE,
PRIVATE_FLAG_TRUSTED_OVERLAY,
0 /* inputFeatures */,
INPUT_FEATURE_SPY,
touchRegion);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
mSurfaceControlTransactionSupplier.get()
.setWindowCrop(mInputSinkSurface, mTaskWidth, mTaskHeight)
.apply();
// The touch region of the TaskInputSink should be the touch region of this
// DragResizeInputHandler minus the task bounds. Pilfering events isn't enough to prevent
// input windows from handling down events, which will bring tasks in the back to front.
//
// Note not the entire touch region responds to both mouse and touchscreen events.
// Therefore, in the region that only responds to one of them, it would be a no-op to
// perform a gesture in the other type of events. We currently only have a mouse-only region
// out of the task bounds, and due to the roughness of touchscreen events, it's not a severe
// 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
// be performed on the input window behind the resize handle.
touchRegion.op(0, 0, mTaskWidth, mTaskHeight, Region.Op.DIFFERENCE);
try {
mWindowSession.updateInputChannel(
mSinkInputChannel.getToken(),
mDisplayId,
mInputSinkSurface,
FLAG_NOT_FOCUSABLE,
0 /* privateFlags */,
INPUT_FEATURE_NO_INPUT_CHANNEL,
touchRegion);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
@@ -248,6 +318,16 @@ class DragResizeInputListener implements AutoCloseable {
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
mSinkInputChannel.dispose();
try {
mWindowSession.remove(mFakeSinkWindow);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
mSurfaceControlTransactionSupplier.get()
.remove(mInputSinkSurface)
.apply();
}
private class TaskResizeInputEventReceiver extends InputEventReceiver
@@ -316,6 +396,8 @@ class DragResizeInputListener implements AutoCloseable {
mShouldHandleEvents = isInResizeHandleBounds(x, y);
}
if (mShouldHandleEvents) {
mInputManager.pilferPointers(mInputChannel.getToken());
mDragPointerId = e.getPointerId(0);
float rawX = e.getRawX(0);
float rawY = e.getRawY(0);

View File

@@ -63,6 +63,24 @@ import java.util.function.Supplier;
public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
implements AutoCloseable {
/**
* The Z-order of {@link #mCaptionContainerSurface}.
* <p>
* We use {@link #mDecorationContainerSurface} to define input window for task resizing; by
* layering it in front of {@link #mCaptionContainerSurface}, we can allow it to handle input
* prior to caption view itself, treating corner inputs as resize events rather than
* repositioning.
*/
static final int CAPTION_LAYER_Z_ORDER = -1;
/**
* The Z-order of the task input sink in {@link DragPositioningCallback}.
* <p>
* This task input sink is used to prevent undesired dispatching of motion events out of task
* bounds; by layering it behind {@link #mCaptionContainerSurface}, we allow captions to handle
* input events first.
*/
static final int INPUT_SINK_Z_ORDER = -2;
/**
* System-wide context. Only used to create context with overridden configurations.
*/
@@ -238,11 +256,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
final int captionHeight = loadDimensionPixelSize(resources, params.mCaptionHeightId);
final int captionWidth = taskBounds.width();
// We use mDecorationContainerSurface to define input window for task resizing; by layering
// it in front of mCaptionContainerSurface, we can allow it to handle input prior to
// caption view itself, treating corner inputs as resize events rather than repositioning.
startT.setWindowCrop(mCaptionContainerSurface, captionWidth, captionHeight)
.setLayer(mCaptionContainerSurface, -1)
.setLayer(mCaptionContainerSurface, CAPTION_LAYER_Z_ORDER)
.show(mCaptionContainerSurface);
if (ViewRootImpl.CAPTION_ON_SHELL) {