diff options
| author | Vishnu Nair <vishnun@google.com> | 2021-10-19 17:33:41 -0700 |
|---|---|---|
| committer | Vishnu Nair <vishnun@google.com> | 2021-10-20 10:42:01 -0700 |
| commit | 426124bc8a4eabacedc78db4547285e503cdabb8 (patch) | |
| tree | af6b61fb31058a44fe9f133592cdbc59d750a1ed | |
| parent | 4743b44cf98f16c84735d66cc46dc2ba90138d1c (diff) | |
WM: Use task bounds for modal window touchable region
If the task is organized and the window is modal then use the parent
surface control to set the touchable region.
Bug: 168252846
Test: Dismiss dialog in splitscreen mode by tapping outside
Change-Id: I8fdd850a142022f979b12a66bb8ead32438123e3
| -rw-r--r-- | core/java/android/view/WindowManager.java | 10 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/InputMonitor.java | 42 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowState.java | 11 |
3 files changed, 37 insertions, 26 deletions
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 51cd95e42742..c25fde472431 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -4750,6 +4750,16 @@ public interface WindowManager extends ViewManager { return Integer.toString(inputFeature); } } + + /** + * True if the window should consume all pointer events itself, regardless of whether they + * are inside of the window. If the window is modal, its touchable region will expand to the + * size of its task. + * @hide + */ + public boolean isModal() { + return (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0; + } } /** diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 1e7b676fbfe4..6afd3355b0a1 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -51,7 +51,6 @@ import static com.android.server.wm.WindowManagerService.LOGTAG_INPUT_FOCUS; import static java.lang.Integer.MAX_VALUE; import android.annotation.Nullable; -import android.graphics.Rect; import android.graphics.Region; import android.os.Handler; import android.os.IBinder; @@ -303,9 +302,6 @@ final class InputMonitor { && !mDisableWallpaperTouchEvents; inputWindowHandle.setHasWallpaper(hasWallpaper); - final Rect frame = w.getFrame(); - inputWindowHandle.setFrame(frame.left, frame.top, frame.right, frame.bottom); - // Surface insets are hardcoded to be the same in all directions // and we could probably deprecate the "left/right/top/bottom" concept. // we avoid reintroducing this concept by just choosing one of them here. @@ -315,11 +311,19 @@ final class InputMonitor { // what is on screen to what is actually being touched in the UI. inputWindowHandle.setScaleFactor(w.mGlobalScale != 1f ? (1f / w.mGlobalScale) : 1f); - final int flags = w.getSurfaceTouchableRegion(mTmpRegion, w.mAttrs.flags); - inputWindowHandle.setTouchableRegion(mTmpRegion); + // Update layout params flags to force the window to be not touch modal. We do this to + // restrict the window's touchable region to the task even if it request touches outside its + // window bounds. An example is a dialog in primary split should get touches outside its + // window within the primary task but should not get any touches going to the secondary + // task. + int flags = w.mAttrs.flags; + if (w.mAttrs.isModal()) { + flags = flags | FLAG_NOT_TOUCH_MODAL; + } inputWindowHandle.setLayoutParamsFlags(flags); - boolean useSurfaceCrop = false; + boolean useSurfaceBoundsAsTouchRegion = false; + SurfaceControl touchableRegionCrop = null; final Task task = w.getTask(); if (task != null) { // TODO(b/165794636): Remove the special case for freeform window once drag resizing is @@ -331,20 +335,22 @@ final class InputMonitor { // we need to make sure that these changes in crop are reflected in the input // windows, and so ensure this flag is set so that the input crop always reflects // the surface hierarchy. - // TODO(b/168252846): we have some issues with modal-windows, so we need to cross - // that bridge now that we organize full-screen Tasks. - inputWindowHandle.setTouchableRegionCrop(null /* Use this surfaces crop */); - inputWindowHandle.setReplaceTouchableRegionWithCrop(true); - useSurfaceCrop = true; + useSurfaceBoundsAsTouchRegion = true; + + if (w.mAttrs.isModal()) { + TaskFragment parent = w.getTaskFragment(); + touchableRegionCrop = parent != null ? parent.getSurfaceControl() : null; + } } else if (task.cropWindowsToRootTaskBounds() && !w.inFreeformWindowingMode()) { - inputWindowHandle.setTouchableRegionCrop(task.getRootTask().getSurfaceControl()); - inputWindowHandle.setReplaceTouchableRegionWithCrop(false); - useSurfaceCrop = true; + touchableRegionCrop = task.getRootTask().getSurfaceControl(); } } - if (!useSurfaceCrop) { - inputWindowHandle.setReplaceTouchableRegionWithCrop(false); - inputWindowHandle.setTouchableRegionCrop(null); + inputWindowHandle.setReplaceTouchableRegionWithCrop(useSurfaceBoundsAsTouchRegion); + inputWindowHandle.setTouchableRegionCrop(touchableRegionCrop); + + if (!useSurfaceBoundsAsTouchRegion) { + w.getSurfaceTouchableRegion(mTmpRegion, w.mAttrs); + inputWindowHandle.setTouchableRegion(mTmpRegion); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 2410d7ec13c2..955919a6fc46 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -51,7 +51,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND; import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; -import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; import static android.view.WindowManager.LayoutParams.FLAG_SCALED; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; @@ -2875,10 +2874,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } - int getSurfaceTouchableRegion(Region region, int flags) { - final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0; + void getSurfaceTouchableRegion(Region region, WindowManager.LayoutParams attrs) { + final boolean modal = attrs.isModal(); if (modal) { - flags |= FLAG_NOT_TOUCH_MODAL; if (mActivityRecord != null) { // Limit the outer touch to the activity root task region. updateRegionForModalActivityWindow(region); @@ -2910,8 +2908,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (mInvGlobalScale != 1.f) { region.scale(mInvGlobalScale); } - - return flags; } /** @@ -3759,10 +3755,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP * {@link WindowManager.LayoutParams#FLAG_NOT_TOUCH_MODAL touch modality.} */ void getEffectiveTouchableRegion(Region outRegion) { - final boolean modal = (mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0; final DisplayContent dc = getDisplayContent(); - if (modal && dc != null) { + if (mAttrs.isModal() && dc != null) { outRegion.set(dc.getBounds()); cropRegionToRootTaskBoundsIfNeeded(outRegion); subtractTouchExcludeRegionIfNeeded(outRegion); |
