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
This commit is contained in:
@@ -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()) {
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user