From b106379310783dac036088c6ef052d3ceb0754fa Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Fri, 28 Jun 2019 12:10:51 +0200 Subject: [PATCH] GestureNav: Fix broken exclusion rect calculation for modal windows Fixes an issue with non-fullscreen modal windows (such as dialogs), where the touch exclusion of the window behind was still being applied, even though the window behind did not actually receive the touches in the exclusion, because they would go to the modal window in front. Bug: 135522625 Test: atest testCalculateSystemGestureExclusion_modal Change-Id: Ia99f4f601e780715abaf966f6f297fd9d555fd0b --- .../com/android/server/wm/DisplayContent.java | 6 ++--- .../com/android/server/wm/WindowState.java | 19 +++++++++++++++ .../server/wm/DisplayContentTests.java | 24 +++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index c069b2e8da5c2..675483442300f 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -5142,7 +5142,7 @@ class DisplayContent extends WindowContainer { if (w.cantReceiveTouchInput() || !w.isVisible() @@ -5150,12 +5150,10 @@ class DisplayContent extends WindowContainer implements WindowManagerP subtractTouchExcludeRegionIfNeeded(outRegion); } + /** + * Get the effective touchable region in global coordinates. + * + * In contrast to {@link #getTouchableRegion}, this takes into account + * {@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) { + outRegion.set(dc.getBounds()); + cropRegionToStackBoundsIfNeeded(outRegion); + subtractTouchExcludeRegionIfNeeded(outRegion); + } else { + getTouchableRegion(outRegion); + } + } + private void setTouchableRegionCropIfNeeded(InputWindowHandle handle) { final Task task = getTask(); if (task == null || !task.cropWindowsToStackBounds()) { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index f2e7dc6fecae0..7cd097ebdc2b2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -793,6 +793,30 @@ public class DisplayContentTests extends WindowTestsBase { assertEquals(expected, dc.calculateSystemGestureExclusion()); } + @Test + public void testCalculateSystemGestureExclusion_modal() throws Exception { + final DisplayContent dc = createNewDisplay(); + final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "base"); + win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR; + win.setSystemGestureExclusion(Collections.singletonList(new Rect(0, 0, 1000, 1000))); + + final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "modal"); + win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR; + win2.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION; + win2.getAttrs().width = 10; + win2.getAttrs().height = 10; + win2.setSystemGestureExclusion(Collections.emptyList()); + + dc.setLayoutNeeded(); + dc.performLayout(true /* initial */, false /* updateImeWindows */); + + win.setHasSurface(true); + win2.setHasSurface(true); + + final Region expected = Region.obtain(); + assertEquals(expected, dc.calculateSystemGestureExclusion()); + } + @Test public void testCalculateSystemGestureExclusion_immersiveStickyLegacyWindow() throws Exception { synchronized (mWm.mGlobalLock) {