summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Roos <roosa@google.com>2019-06-28 12:10:51 +0200
committerAdrian Roos <roosa@google.com>2019-07-04 17:44:07 +0200
commitb106379310783dac036088c6ef052d3ceb0754fa (patch)
tree04aa3d4443a1c046637fbc8660e4e90575c5e8cc
parent8ef731c2329badb9555782c47885d9c262d6df9c (diff)
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
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java19
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java24
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 c069b2e8da5c..675483442300 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<DisplayContent.DisplayChildWindowCo
final int[] remainingLeftRight =
{mSystemGestureExclusionLimit, mSystemGestureExclusionLimit};
- // Traverse all windows bottom up to assemble the gesture exclusion rects.
+ // Traverse all windows top down to assemble the gesture exclusion rects.
// For each window, we only take the rects that fall within its touchable region.
forAllWindows(w -> {
if (w.cantReceiveTouchInput() || !w.isVisible()
@@ -5150,12 +5150,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|| unhandled.isEmpty()) {
return;
}
- final boolean modal =
- (w.mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
// Get the touchable region of the window, and intersect with where the screen is still
// touchable, i.e. touchable regions on top are not covering it yet.
- w.getTouchableRegion(touchableRegion);
+ w.getEffectiveTouchableRegion(touchableRegion);
touchableRegion.op(unhandled, Op.INTERSECT);
if (w.isImplicitlyExcludingAllSystemGestures()) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index b5586bf28751..43ad091b08c0 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3011,6 +3011,25 @@ class WindowState extends WindowContainer<WindowState> 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 f2e7dc6fecae..7cd097ebdc2b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -794,6 +794,30 @@ public class DisplayContentTests extends WindowTestsBase {
}
@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) {
mWm.mSystemGestureExcludedByPreQStickyImmersive = true;