| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.server.wm; |
| |
| import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; |
| import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; |
| import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; |
| import static android.view.DisplayCutout.BOUNDS_POSITION_TOP; |
| import static android.view.DisplayCutout.fromBoundingRect; |
| import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; |
| |
| import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; |
| import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; |
| import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; |
| |
| import static org.junit.Assert.assertEquals; |
| |
| import android.content.res.Configuration; |
| import android.graphics.Rect; |
| import android.platform.test.annotations.Presubmit; |
| import android.view.DisplayInfo; |
| import android.view.Gravity; |
| import android.view.WindowManager; |
| |
| import androidx.test.filters.FlakyTest; |
| import androidx.test.filters.SmallTest; |
| |
| import com.android.server.wm.utils.WmDisplayCutout; |
| |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.mockito.Mockito; |
| |
| /** |
| * Tests for the {@link WindowState#computeFrameLw} method and other window frame machinery. |
| * |
| * Build/Install/Run: |
| * atest WmTests:WindowFrameTests |
| */ |
| @SmallTest |
| @Presubmit |
| @RunWith(WindowTestRunner.class) |
| public class WindowFrameTests extends WindowTestsBase { |
| |
| private final Rect mEmptyRect = new Rect(); |
| private DisplayContent mTestDisplayContent; |
| |
| @Before |
| public void setUp() throws Exception { |
| DisplayInfo testDisplayInfo = new DisplayInfo(mDisplayInfo); |
| testDisplayInfo.displayCutout = null; |
| mTestDisplayContent = createNewDisplay(testDisplayInfo); |
| } |
| |
| // Do not use this function directly in the tests below. Instead, use more explicit function |
| // such as assertFlame(). |
| private void assertRect(Rect rect, int left, int top, int right, int bottom) { |
| assertEquals(left, rect.left); |
| assertEquals(top, rect.top); |
| assertEquals(right, rect.right); |
| assertEquals(bottom, rect.bottom); |
| } |
| |
| private void assertContentInset(WindowState w, int left, int top, int right, int bottom) { |
| assertRect(w.getContentInsets(), left, top, right, bottom); |
| } |
| |
| private void assertVisibleInset(WindowState w, int left, int top, int right, int bottom) { |
| assertRect(w.getVisibleInsets(), left, top, right, bottom); |
| } |
| |
| private void assertStableInset(WindowState w, int left, int top, int right, int bottom) { |
| assertRect(w.getStableInsets(), left, top, right, bottom); |
| } |
| |
| private void assertFrame(WindowState w, Rect frame) { |
| assertEquals(w.getFrameLw(), frame); |
| } |
| |
| private void assertFrame(WindowState w, int left, int top, int right, int bottom) { |
| assertRect(w.getFrameLw(), left, top, right, bottom); |
| } |
| |
| private void assertRelFrame(WindowState w, int left, int top, int right, int bottom) { |
| assertRect(w.getRelativeFrameLw(), left, top, right, bottom); |
| } |
| |
| private void assertContentFrame(WindowState w, Rect expectedRect) { |
| assertRect(w.getContentFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right, |
| expectedRect.bottom); |
| } |
| |
| private void assertVisibleFrame(WindowState w, Rect expectedRect) { |
| assertRect(w.getVisibleFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right, |
| expectedRect.bottom); |
| } |
| |
| private void assertStableFrame(WindowState w, Rect expectedRect) { |
| assertRect(w.getStableFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right, |
| expectedRect.bottom); |
| } |
| |
| private void assertPolicyCrop(WindowState w, int left, int top, int right, int bottom) { |
| Rect policyCrop = new Rect(); |
| w.calculatePolicyCrop(policyCrop); |
| assertRect(policyCrop, left, top, right, bottom); |
| } |
| |
| @Test |
| public void testLayoutInFullscreenTaskInsets() { |
| // fullscreen task doesn't use bounds for computeFrame |
| WindowState w = createWindow(); |
| w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; |
| |
| final int bottomContentInset = 100; |
| final int topContentInset = 50; |
| final int bottomVisibleInset = 30; |
| final int topVisibleInset = 70; |
| final int leftStableInset = 20; |
| final int rightStableInset = 90; |
| |
| // With no insets or system decor all the frames incoming from PhoneWindowManager |
| // are identical. |
| final Rect pf = new Rect(0, 0, 1000, 1000); |
| final Rect df = pf; |
| final Rect of = df; |
| final Rect cf = new Rect(pf); |
| // Produce some insets |
| cf.top += 50; |
| cf.bottom -= 100; |
| final Rect vf = new Rect(pf); |
| vf.top += topVisibleInset; |
| vf.bottom -= bottomVisibleInset; |
| final Rect sf = new Rect(pf); |
| sf.left += leftStableInset; |
| sf.right -= rightStableInset; |
| |
| final Rect dcf = pf; |
| // When mFrame extends past cf, the content insets are |
| // the difference between mFrame and ContentFrame. Visible |
| // and stable frames work the same way. |
| w.getWindowFrames().setFrames(pf, df, cf, vf, dcf, sf); |
| w.computeFrameLw(); |
| assertFrame(w, 0, 0, 1000, 1000); |
| assertRelFrame(w, 0, 0, 1000, 1000); |
| assertContentInset(w, 0, topContentInset, 0, bottomContentInset); |
| assertVisibleInset(w, 0, topVisibleInset, 0, bottomVisibleInset); |
| assertStableInset(w, leftStableInset, 0, rightStableInset, 0); |
| assertContentFrame(w, cf); |
| assertVisibleFrame(w, vf); |
| assertStableFrame(w, sf); |
| // On the other hand getFrame() doesn't extend past cf we won't get any insets |
| w.mAttrs.x = 100; |
| w.mAttrs.y = 100; |
| w.mAttrs.width = 100; w.mAttrs.height = 100; //have to clear MATCH_PARENT |
| w.mRequestedWidth = 100; |
| w.mRequestedHeight = 100; |
| w.computeFrameLw(); |
| assertFrame(w, 100, 100, 200, 200); |
| assertRelFrame(w, 100, 100, 200, 200); |
| assertContentInset(w, 0, 0, 0, 0); |
| // In this case the frames are shrunk to the window frame. |
| assertContentFrame(w, w.getFrameLw()); |
| assertVisibleFrame(w, w.getFrameLw()); |
| assertStableFrame(w, w.getFrameLw()); |
| } |
| |
| @Test |
| public void testLayoutInFullscreenTaskNoInsets() { |
| // fullscreen task doesn't use bounds for computeFrame |
| WindowState w = createWindow(); |
| w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; |
| |
| // With no insets or system decor all the frames incoming from PhoneWindowManager |
| // are identical. |
| final Rect pf = new Rect(0, 0, 1000, 1000); |
| |
| // Here the window has FILL_PARENT, FILL_PARENT |
| // so we expect it to fill the entire available frame. |
| w.getWindowFrames().setFrames(pf, pf, pf, pf, pf, pf); |
| w.computeFrameLw(); |
| assertFrame(w, 0, 0, 1000, 1000); |
| assertRelFrame(w, 0, 0, 1000, 1000); |
| |
| // It can select various widths and heights within the bounds. |
| // Strangely the window attribute width is ignored for normal windows |
| // and we use mRequestedWidth/mRequestedHeight |
| w.mAttrs.width = 300; |
| w.mAttrs.height = 300; |
| w.computeFrameLw(); |
| // Explicit width and height without requested width/height |
| // gets us nothing. |
| assertFrame(w, 0, 0, 0, 0); |
| |
| w.mRequestedWidth = 300; |
| w.mRequestedHeight = 300; |
| w.computeFrameLw(); |
| // With requestedWidth/Height we can freely choose our size within the |
| // parent bounds. |
| assertFrame(w, 0, 0, 300, 300); |
| |
| // With FLAG_SCALED though, requestedWidth/height is used to control |
| // the unscaled surface size, and mAttrs.width/height becomes the |
| // layout controller. |
| w.mAttrs.flags = WindowManager.LayoutParams.FLAG_SCALED; |
| w.mRequestedHeight = -1; |
| w.mRequestedWidth = -1; |
| w.mAttrs.width = 100; |
| w.mAttrs.height = 100; |
| w.computeFrameLw(); |
| assertFrame(w, 0, 0, 100, 100); |
| w.mAttrs.flags = 0; |
| |
| // But sizes too large will be clipped to the containing frame |
| w.mRequestedWidth = 1200; |
| w.mRequestedHeight = 1200; |
| w.computeFrameLw(); |
| assertFrame(w, 0, 0, 1000, 1000); |
| |
| // Before they are clipped though windows will be shifted |
| w.mAttrs.x = 300; |
| w.mAttrs.y = 300; |
| w.mRequestedWidth = 1000; |
| w.mRequestedHeight = 1000; |
| w.computeFrameLw(); |
| assertFrame(w, 0, 0, 1000, 1000); |
| |
| // If there is room to move around in the parent frame the window will be shifted according |
| // to gravity. |
| w.mAttrs.x = 0; |
| w.mAttrs.y = 0; |
| w.mRequestedWidth = 300; |
| w.mRequestedHeight = 300; |
| w.mAttrs.gravity = Gravity.RIGHT | Gravity.TOP; |
| w.computeFrameLw(); |
| assertFrame(w, 700, 0, 1000, 300); |
| assertRelFrame(w, 700, 0, 1000, 300); |
| w.mAttrs.gravity = Gravity.RIGHT | Gravity.BOTTOM; |
| w.computeFrameLw(); |
| assertFrame(w, 700, 700, 1000, 1000); |
| assertRelFrame(w, 700, 700, 1000, 1000); |
| // Window specified x and y are interpreted as offsets in the opposite |
| // direction of gravity |
| w.mAttrs.x = 100; |
| w.mAttrs.y = 100; |
| w.computeFrameLw(); |
| assertFrame(w, 600, 600, 900, 900); |
| assertRelFrame(w, 600, 600, 900, 900); |
| } |
| |
| @Test |
| public void testLayoutNonfullscreenTask() { |
| removeGlobalMinSizeRestriction(); |
| final DisplayInfo displayInfo = mWm.getDefaultDisplayContentLocked().getDisplayInfo(); |
| final int logicalWidth = displayInfo.logicalWidth; |
| final int logicalHeight = displayInfo.logicalHeight; |
| |
| final Rect taskBounds = new Rect( |
| logicalWidth / 4, logicalHeight / 4, logicalWidth / 4 * 3, logicalHeight / 4 * 3); |
| WindowState w = createWindow(); |
| final Task task = w.getTask(); |
| // Use split-screen because it is non-fullscreen, but also not floating |
| task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); |
| task.setBounds(taskBounds); |
| // The bounds we are requesting might be different from what the system resolved based on |
| // other factors. |
| final Rect resolvedTaskBounds = task.getBounds(); |
| w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; |
| |
| final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight); |
| final WindowFrames windowFrames = w.getWindowFrames(); |
| windowFrames.setFrames(pf, pf, pf, pf, pf, pf); |
| w.computeFrameLw(); |
| // For non fullscreen tasks the containing frame is based off the |
| // task bounds not the parent frame. |
| assertEquals(resolvedTaskBounds, w.getFrameLw()); |
| assertEquals(0, w.getRelativeFrameLw().left); |
| assertEquals(0, w.getRelativeFrameLw().top); |
| assertContentFrame(w, resolvedTaskBounds); |
| assertContentInset(w, 0, 0, 0, 0); |
| |
| pf.set(0, 0, logicalWidth, logicalHeight); |
| // We still produce insets against the containing frame the same way. |
| final int cfRight = logicalWidth / 2; |
| final int cfBottom = logicalHeight / 2; |
| final Rect cf = new Rect(0, 0, cfRight, cfBottom); |
| windowFrames.setFrames(pf, pf, cf, cf, pf, cf); |
| w.computeFrameLw(); |
| assertEquals(resolvedTaskBounds, w.getFrameLw()); |
| assertEquals(0, w.getRelativeFrameLw().left); |
| assertEquals(0, w.getRelativeFrameLw().top); |
| int contentInsetRight = resolvedTaskBounds.right - cfRight; |
| int contentInsetBottom = resolvedTaskBounds.bottom - cfBottom; |
| assertContentInset(w, 0, 0, contentInsetRight, contentInsetBottom); |
| assertContentFrame(w, new Rect(resolvedTaskBounds.left, resolvedTaskBounds.top, |
| resolvedTaskBounds.right - contentInsetRight, |
| resolvedTaskBounds.bottom - contentInsetBottom)); |
| |
| pf.set(0, 0, logicalWidth, logicalHeight); |
| // If we set displayed bounds, the insets will be computed with the main task bounds |
| // but the frame will be positioned according to the displayed bounds. |
| final int insetLeft = logicalWidth / 5; |
| final int insetTop = logicalHeight / 5; |
| final int insetRight = insetLeft + (resolvedTaskBounds.right - resolvedTaskBounds.left); |
| final int insetBottom = insetTop + (resolvedTaskBounds.bottom - resolvedTaskBounds.top); |
| task.setOverrideDisplayedBounds(resolvedTaskBounds); |
| task.setBounds(insetLeft, insetTop, insetRight, insetBottom); |
| windowFrames.setFrames(pf, pf, cf, cf, pf, cf); |
| w.computeFrameLw(); |
| assertEquals(resolvedTaskBounds, w.getFrameLw()); |
| assertEquals(0, w.getRelativeFrameLw().left); |
| assertEquals(0, w.getRelativeFrameLw().top); |
| contentInsetRight = insetRight - cfRight; |
| contentInsetBottom = insetBottom - cfBottom; |
| assertContentInset(w, 0, 0, contentInsetRight, contentInsetBottom); |
| assertContentFrame(w, new Rect(resolvedTaskBounds.left, resolvedTaskBounds.top, |
| resolvedTaskBounds.right - contentInsetRight, |
| resolvedTaskBounds.bottom - contentInsetBottom)); |
| } |
| |
| @Test |
| @FlakyTest(bugId = 130388666) |
| public void testCalculatePolicyCrop() { |
| final WindowState w = createWindow(); |
| w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; |
| |
| final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo(); |
| final int logicalWidth = displayInfo.logicalWidth; |
| final int logicalHeight = displayInfo.logicalHeight; |
| final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight); |
| final Rect df = pf; |
| final Rect cf = new Rect(pf); |
| // Produce some insets |
| cf.top += displayInfo.logicalWidth / 10; |
| cf.bottom -= displayInfo.logicalWidth / 5; |
| final Rect vf = cf; |
| final Rect sf = vf; |
| // We use a decor content frame with insets to produce cropping. |
| Rect dcf = new Rect(cf); |
| |
| final WindowFrames windowFrames = w.getWindowFrames(); |
| windowFrames.setFrames(pf, df, cf, vf, dcf, sf); |
| w.computeFrameLw(); |
| assertPolicyCrop(w, 0, cf.top, logicalWidth, cf.bottom); |
| |
| windowFrames.mDecorFrame.setEmpty(); |
| // Likewise with no decor frame we would get no crop |
| w.computeFrameLw(); |
| assertPolicyCrop(w, 0, 0, logicalWidth, logicalHeight); |
| |
| // Now we set up a window which doesn't fill the entire decor frame. |
| // Normally it would be cropped to it's frame but in the case of docked resizing |
| // we need to account for the fact the windows surface will be made |
| // fullscreen and thus also make the crop fullscreen. |
| |
| windowFrames.setFrames(pf, pf, pf, pf, pf, pf); |
| w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; |
| w.mAttrs.width = logicalWidth / 2; |
| w.mAttrs.height = logicalHeight / 2; |
| w.mRequestedWidth = logicalWidth / 2; |
| w.mRequestedHeight = logicalHeight / 2; |
| w.computeFrameLw(); |
| |
| // Normally the crop is shrunk from the decor frame |
| // to the computed window frame. |
| assertPolicyCrop(w, 0, 0, logicalWidth / 2, logicalHeight / 2); |
| |
| doReturn(true).when(w).isDockedResizing(); |
| // But if we are docked resizing it won't be, however we will still be |
| // shrunk to the decor frame and the display. |
| assertPolicyCrop(w, 0, 0, |
| Math.min(pf.width(), displayInfo.logicalWidth), |
| Math.min(pf.height(), displayInfo.logicalHeight)); |
| } |
| |
| @Test |
| @FlakyTest(bugId = 137879065) |
| public void testLayoutLetterboxedWindow() { |
| // First verify task behavior in multi-window mode. |
| final DisplayInfo displayInfo = mTestDisplayContent.getDisplayInfo(); |
| final int logicalWidth = displayInfo.logicalWidth; |
| final int logicalHeight = displayInfo.logicalHeight; |
| |
| final int taskLeft = logicalWidth / 5; |
| final int taskTop = logicalHeight / 5; |
| final int taskRight = logicalWidth / 4 * 3; |
| final int taskBottom = logicalHeight / 4 * 3; |
| final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom); |
| WindowState w = createWindow(); |
| final Task task = w.getTask(); |
| // Use split-screen because it is non-fullscreen, but also not floating |
| task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); |
| task.setBounds(taskBounds); |
| w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; |
| |
| final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight); |
| final WindowFrames windowFrames = w.getWindowFrames(); |
| windowFrames.setFrames(pf, pf, pf, pf, pf, pf); |
| w.computeFrameLw(); |
| // For non fullscreen tasks the containing frame is based off the |
| // task bounds not the parent frame. |
| assertFrame(w, taskLeft, taskTop, taskRight, taskBottom); |
| assertContentFrame(w, taskBounds); |
| assertContentInset(w, 0, 0, 0, 0); |
| |
| // Now simulate switch to fullscreen for letterboxed app. |
| final int xInset = logicalWidth / 10; |
| final Rect cf = new Rect(xInset, 0, logicalWidth - xInset, logicalHeight); |
| Configuration config = new Configuration(w.mActivityRecord.getRequestedOverrideConfiguration()); |
| config.windowConfiguration.setBounds(cf); |
| config.windowConfiguration.setAppBounds(cf); |
| w.mActivityRecord.onRequestedOverrideConfigurationChanged(config); |
| pf.set(0, 0, logicalWidth, logicalHeight); |
| task.setWindowingMode(WINDOWING_MODE_FULLSCREEN); |
| task.setBounds(null); |
| windowFrames.setFrames(pf, pf, cf, cf, pf, cf); |
| w.computeFrameLw(); |
| assertFrame(w, cf); |
| assertContentFrame(w, cf); |
| assertContentInset(w, 0, 0, 0, 0); |
| } |
| |
| @Test |
| @FlakyTest(bugId = 130388666) |
| public void testDisplayCutout() { |
| // Regular fullscreen task and window |
| WindowState w = createWindow(); |
| w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; |
| |
| final Rect pf = new Rect(0, 0, 1000, 2000); |
| // Create a display cutout of size 50x50, aligned top-center |
| final WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets( |
| fromBoundingRect(500, 0, 550, 50, BOUNDS_POSITION_TOP), |
| pf.width(), pf.height()); |
| |
| final WindowFrames windowFrames = w.getWindowFrames(); |
| windowFrames.setFrames(pf, pf, pf, pf, pf, pf); |
| windowFrames.setDisplayCutout(cutout); |
| w.computeFrameLw(); |
| |
| assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetTop(), 50); |
| assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetBottom(), 0); |
| assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetLeft(), 0); |
| assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetRight(), 0); |
| } |
| |
| @Test |
| @FlakyTest(bugId = 130388666) |
| public void testDisplayCutout_tempDisplayedBounds() { |
| // Regular fullscreen task and window |
| WindowState w = createWindow(); |
| final Task task = w.getTask(); |
| task.setBounds(new Rect(0, 0, 1000, 2000)); |
| task.setOverrideDisplayedBounds(new Rect(0, -500, 1000, 1500)); |
| w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; |
| |
| final Rect pf = new Rect(0, -500, 1000, 1500); |
| // Create a display cutout of size 50x50, aligned top-center |
| final WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets( |
| fromBoundingRect(500, 0, 550, 50, BOUNDS_POSITION_TOP), |
| pf.width(), pf.height()); |
| |
| final WindowFrames windowFrames = w.getWindowFrames(); |
| windowFrames.setFrames(pf, pf, pf, pf, pf, pf); |
| windowFrames.setDisplayCutout(cutout); |
| w.computeFrameLw(); |
| |
| assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetTop(), 50); |
| assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetBottom(), 0); |
| assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetLeft(), 0); |
| assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetRight(), 0); |
| } |
| |
| @Test |
| public void testFreeformContentInsets() { |
| removeGlobalMinSizeRestriction(); |
| // fullscreen task doesn't use bounds for computeFrame |
| WindowState w = createWindow(); |
| final Task task = w.getTask(); |
| w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; |
| task.setWindowingMode(WINDOWING_MODE_FREEFORM); |
| |
| DisplayContent dc = mTestDisplayContent; |
| dc.mInputMethodTarget = w; |
| WindowState mockIme = mock(WindowState.class); |
| Mockito.doReturn(true).when(mockIme).isVisibleNow(); |
| dc.mInputMethodWindow = mockIme; |
| |
| // With no insets or system decor all the frames incoming from PhoneWindowManager |
| // are identical. |
| final Rect pf = new Rect(0, 0, 1000, 800); |
| final Rect df = pf; |
| final Rect of = df; |
| final Rect cf = new Rect(pf); |
| cf.bottom -= 400; |
| final Rect vf = new Rect(cf); |
| final Rect sf = new Rect(pf); |
| final Rect dcf = pf; |
| |
| // First check that it only gets moved up enough to show window. |
| final Rect winRect = new Rect(200, 200, 300, 500); |
| |
| task.setBounds(winRect); |
| w.getWindowFrames().setFrames(pf, df, cf, vf, dcf, sf); |
| w.computeFrameLw(); |
| |
| final Rect expected = new Rect(winRect.left, cf.bottom - winRect.height(), |
| winRect.right, cf.bottom); |
| assertEquals(expected, w.getFrameLw()); |
| assertEquals(expected, w.getContentFrameLw()); |
| assertEquals(expected, w.getVisibleFrameLw()); |
| |
| // Now check that it won't get moved beyond the top and then has appropriate insets |
| winRect.bottom = 600; |
| task.setBounds(winRect); |
| w.setBounds(winRect); |
| w.getWindowFrames().setFrames(pf, df, cf, vf, dcf, sf); |
| w.computeFrameLw(); |
| |
| assertFrame(w, winRect.left, 0, winRect.right, winRect.height()); |
| expected.top = 0; |
| expected.bottom = cf.bottom; |
| assertContentFrame(w, expected); |
| assertVisibleFrame(w, expected); |
| |
| // Check that it's moved back without ime insets |
| w.getWindowFrames().setFrames(pf, df, pf, pf, dcf, sf); |
| w.computeFrameLw(); |
| assertEquals(winRect, w.getFrameLw()); |
| } |
| |
| private WindowState createWindow() { |
| final WindowState ws = createWindow(null, TYPE_APPLICATION, mTestDisplayContent, "WindowFrameTests"); |
| spyOn(ws); |
| return ws; |
| } |
| } |