summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2019-02-12 12:23:45 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2019-02-12 12:23:45 +0000
commit192fb504b309025352bd16b08fa47e901ac3d6ec (patch)
tree95eae39faf9e516be2dba683bd40a344f42a6521
parent3cf3edac98214ec2c2bbd638b83a2e048bfbcaab (diff)
parent192fe76a05bd3f94ffa16f98e928a9e356dffa46 (diff)
Merge "Support touch event on letterbox surface"
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java9
-rw-r--r--services/core/java/com/android/server/wm/Letterbox.java127
2 files changed, 122 insertions, 14 deletions
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 727fb3babda6..0e8b2bdb0777 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -884,6 +884,10 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
dc.setFocusedApp(null);
mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
}
+ if (mLetterbox != null) {
+ mLetterbox.destroy();
+ mLetterbox = null;
+ }
if (!delayed) {
updateReportedVisibilityLocked();
@@ -1297,6 +1301,10 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
}
}
}
+
+ if (prevDc != mDisplayContent && mLetterbox != null) {
+ mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
+ }
}
/**
@@ -1846,6 +1854,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
if (needsLetterbox) {
if (mLetterbox == null) {
mLetterbox = new Letterbox(() -> makeChildSurface(null));
+ mLetterbox.attachInput(w);
}
getPosition(mTmpPoint);
mLetterbox.layout(getParent().getBounds(), w.getFrameLw(), mTmpPoint);
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index 987492024546..d67193ea9e69 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -20,7 +20,15 @@ import static android.view.SurfaceControl.HIDDEN;
import android.graphics.Point;
import android.graphics.Rect;
+import android.os.Binder;
+import android.os.Process;
+import android.view.InputChannel;
+import android.view.InputEventReceiver;
+import android.view.InputWindowHandle;
import android.view.SurfaceControl;
+import android.view.WindowManager;
+
+import com.android.server.UiThread;
import java.util.function.Supplier;
@@ -40,6 +48,7 @@ public class Letterbox {
private final LetterboxSurface mLeft = new LetterboxSurface("left");
private final LetterboxSurface mBottom = new LetterboxSurface("bottom");
private final LetterboxSurface mRight = new LetterboxSurface("right");
+ private final LetterboxSurface[] mSurfaces = { mLeft, mTop, mRight, mBottom };
/**
* Constructs a Letterbox.
@@ -87,8 +96,12 @@ public class Letterbox {
* Returns true if any part of the letterbox overlaps with the given {@code rect}.
*/
public boolean isOverlappingWith(Rect rect) {
- return mTop.isOverlappingWith(rect) || mLeft.isOverlappingWith(rect)
- || mBottom.isOverlappingWith(rect) || mRight.isOverlappingWith(rect);
+ for (LetterboxSurface surface : mSurfaces) {
+ if (surface.isOverlappingWith(rect)) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -107,25 +120,94 @@ public class Letterbox {
mOuter.setEmpty();
mInner.setEmpty();
- mTop.remove();
- mLeft.remove();
- mBottom.remove();
- mRight.remove();
+ for (LetterboxSurface surface : mSurfaces) {
+ surface.remove();
+ }
}
/** Returns whether a call to {@link #applySurfaceChanges} would change the surface. */
public boolean needsApplySurfaceChanges() {
- return mTop.needsApplySurfaceChanges()
- || mLeft.needsApplySurfaceChanges()
- || mBottom.needsApplySurfaceChanges()
- || mRight.needsApplySurfaceChanges();
+ for (LetterboxSurface surface : mSurfaces) {
+ if (surface.needsApplySurfaceChanges()) {
+ return true;
+ }
+ }
+ return false;
}
public void applySurfaceChanges(SurfaceControl.Transaction t) {
- mTop.applySurfaceChanges(t);
- mLeft.applySurfaceChanges(t);
- mBottom.applySurfaceChanges(t);
- mRight.applySurfaceChanges(t);
+ for (LetterboxSurface surface : mSurfaces) {
+ surface.applySurfaceChanges(t);
+ }
+ }
+
+ /** Enables touches to slide into other neighboring surfaces. */
+ void attachInput(WindowState win) {
+ for (LetterboxSurface surface : mSurfaces) {
+ surface.attachInput(win);
+ }
+ }
+
+ void onMovedToDisplay(int displayId) {
+ for (LetterboxSurface surface : mSurfaces) {
+ if (surface.mInputInterceptor != null) {
+ surface.mInputInterceptor.mWindowHandle.displayId = displayId;
+ }
+ }
+ }
+
+ private static class InputInterceptor {
+ final InputChannel mServerChannel;
+ final InputChannel mClientChannel;
+ final InputWindowHandle mWindowHandle;
+ final InputEventReceiver mInputEventReceiver;
+ final WindowManagerService mWmService;
+
+ InputInterceptor(String namePrefix, WindowState win) {
+ mWmService = win.mWmService;
+ final String name = namePrefix + (win.mAppToken != null ? win.mAppToken : win);
+ final InputChannel[] channels = InputChannel.openInputChannelPair(name);
+ mServerChannel = channels[0];
+ mClientChannel = channels[1];
+ mInputEventReceiver = new SimpleInputReceiver(mClientChannel);
+
+ final Binder token = new Binder();
+ mWmService.mInputManager.registerInputChannel(mServerChannel, token);
+
+ mWindowHandle = new InputWindowHandle(null /* inputApplicationHandle */,
+ null /* clientWindow */, win.getDisplayId());
+ mWindowHandle.name = name;
+ mWindowHandle.token = token;
+ mWindowHandle.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ | WindowManager.LayoutParams.FLAG_SLIPPERY;
+ mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
+ mWindowHandle.dispatchingTimeoutNanos =
+ WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+ mWindowHandle.visible = true;
+ mWindowHandle.ownerPid = Process.myPid();
+ mWindowHandle.ownerUid = Process.myUid();
+ mWindowHandle.scaleFactor = 1.0f;
+ }
+
+ void updateTouchableRegion(Rect frame) {
+ mWindowHandle.touchableRegion.set(frame);
+ mWindowHandle.touchableRegion.translate(-frame.left, -frame.top);
+ }
+
+ void dispose() {
+ mWmService.mInputManager.unregisterInputChannel(mServerChannel);
+ mInputEventReceiver.dispose();
+ mServerChannel.dispose();
+ mClientChannel.dispose();
+ }
+
+ private static class SimpleInputReceiver extends InputEventReceiver {
+ SimpleInputReceiver(InputChannel inputChannel) {
+ super(inputChannel, UiThread.getHandler().getLooper());
+ }
+ }
}
private class LetterboxSurface {
@@ -137,6 +219,8 @@ public class Letterbox {
private final Rect mLayoutFrameGlobal = new Rect();
private final Rect mLayoutFrameRelative = new Rect();
+ private InputInterceptor mInputInterceptor;
+
public LetterboxSurface(String type) {
mType = type;
}
@@ -154,11 +238,22 @@ public class Letterbox {
mSurface.setColor(new float[]{0, 0, 0});
}
+ void attachInput(WindowState win) {
+ if (mInputInterceptor != null) {
+ mInputInterceptor.dispose();
+ }
+ mInputInterceptor = new InputInterceptor("Letterbox_" + mType + "_", win);
+ }
+
public void remove() {
if (mSurface != null) {
mSurface.remove();
mSurface = null;
}
+ if (mInputInterceptor != null) {
+ mInputInterceptor.dispose();
+ mInputInterceptor = null;
+ }
}
public int getWidth() {
@@ -193,6 +288,10 @@ public class Letterbox {
t.setPosition(mSurface, mSurfaceFrameRelative.left, mSurfaceFrameRelative.top);
t.setWindowCrop(mSurface, mSurfaceFrameRelative.width(),
mSurfaceFrameRelative.height());
+ if (mInputInterceptor != null) {
+ mInputInterceptor.updateTouchableRegion(mSurfaceFrameRelative);
+ t.setInputWindowInfo(mSurface, mInputInterceptor.mWindowHandle);
+ }
t.show(mSurface);
} else if (mSurface != null) {
t.hide(mSurface);