[Offline indicator v2] Fix blink layout height and fullscreen
Today, most parts of the code assume the browser controls min-height is 0. This causes issues with the layout size and the fullscreen mode. The most obvious issues currently are: - If a min-height is set, ChromeFullscreenManager#controlsResizeView() always returns true since the controls aren't completely hidden. - Similarly if a min-height is set, position: fixed elements are sized as if the controls are fully showing. This CL changes the "browser controls resize/shrink blink" logic to try and fix the issues listed above. With the changes in this CL, the controlsResizeView bit will be false if the controls are at the min-height. Bug: 1049301 Change-Id: Ieb95e92c983b56b42a640f726c60c2eec9964064 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2048276 Commit-Queue: Sinan Sahin <sinansahin@google.com> Reviewed-by: Theresa <twellington@chromium.org> Reviewed-by: Matthew Jones <mdjones@chromium.org> Reviewed-by: David Bokan <bokan@chromium.org> Cr-Commit-Position: refs/heads/master@{#750260}
This commit is contained in:
cc/trees
chrome/android
chrome_junit_test_java_sources.gni
java
src
org
chromium
chrome
browser
junit
src
org
chromium
chrome
browser
fullscreen
third_party/blink/renderer/core
@ -43,11 +43,11 @@ struct ApplyViewportChangesArgs {
|
||||
bool is_pinch_gesture_active;
|
||||
|
||||
// How much the top controls have been shown or hidden. The ratio runs
|
||||
// between 0 (hidden) and 1 (full-shown). This is additive.
|
||||
// between a set min-height (default 0) and 1 (full-shown). This is additive.
|
||||
float top_controls_delta;
|
||||
|
||||
// How much the bottom controls have been shown or hidden. The ratio runs
|
||||
// between 0 (hidden) and 1 (full-shown). This is additive.
|
||||
// between a set min-height (default 0) and 1 (full-shown). This is additive.
|
||||
float bottom_controls_delta;
|
||||
|
||||
// Whether the browser controls have been locked to fully hidden or shown or
|
||||
|
@ -369,21 +369,22 @@ void LayerTreeImpl::UpdateViewportContainerSizes() {
|
||||
ViewportAnchor anchor(InnerViewportScrollNode(), OuterViewportScrollNode(),
|
||||
this);
|
||||
|
||||
// Top/bottom controls always share the same shown ratio.
|
||||
float top_controls_shown_ratio =
|
||||
top_controls_shown_ratio_->Current(IsActiveTree());
|
||||
float bottom_controls_shown_ratio =
|
||||
bottom_controls_shown_ratio_->Current(IsActiveTree());
|
||||
float top_controls_layout_height =
|
||||
browser_controls_shrink_blink_size() ? top_controls_height() : 0.f;
|
||||
float top_controls_layout_height = browser_controls_shrink_blink_size()
|
||||
? top_controls_height()
|
||||
: top_controls_min_height();
|
||||
float top_content_offset =
|
||||
top_controls_height() > 0
|
||||
? top_controls_height() * top_controls_shown_ratio
|
||||
: 0.f;
|
||||
float delta_from_top_controls =
|
||||
top_controls_layout_height - top_content_offset;
|
||||
float bottom_controls_layout_height =
|
||||
browser_controls_shrink_blink_size() ? bottom_controls_height() : 0.f;
|
||||
float bottom_controls_layout_height = browser_controls_shrink_blink_size()
|
||||
? bottom_controls_height()
|
||||
: bottom_controls_min_height();
|
||||
float bottom_content_offset =
|
||||
bottom_controls_height() > 0
|
||||
? bottom_controls_height() * bottom_controls_shown_ratio
|
||||
|
@ -79,6 +79,7 @@ chrome_junit_test_java_sources = [
|
||||
"junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java",
|
||||
"junit/src/org/chromium/chrome/browser/firstrun/ToSAckedReceiverTest.java",
|
||||
"junit/src/org/chromium/chrome/browser/fullscreen/BrowserStateBrowserControlsVisibilityDelegateTest.java",
|
||||
"junit/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerUnitTest.java",
|
||||
"junit/src/org/chromium/chrome/browser/gcore/GoogleApiClientHelperTest.java",
|
||||
"junit/src/org/chromium/chrome/browser/gsa/GSAStateUnitTest.java",
|
||||
"junit/src/org/chromium/chrome/browser/history/HistoryAdapterAccessibilityTest.java",
|
||||
|
@ -575,6 +575,9 @@ public class CompositorViewHolder extends FrameLayout
|
||||
for (TouchEventObserver o : mTouchEventObservers) {
|
||||
if (o.shouldInterceptTouchEvent(e)) return true;
|
||||
}
|
||||
|
||||
if (mFullscreenManager != null) mFullscreenManager.onMotionEvent(e);
|
||||
|
||||
if (mLayoutManager == null) return false;
|
||||
|
||||
mEventOffsetHandler.onInterceptTouchEvent(e);
|
||||
@ -708,9 +711,13 @@ public class CompositorViewHolder extends FrameLayout
|
||||
// The view size takes into account of the browser controls whose height
|
||||
// should be subtracted from the view if they are visible, therefore shrink
|
||||
// Blink-side view size.
|
||||
final int totalMinHeight = mFullscreenManager != null
|
||||
? mFullscreenManager.getTopControlsMinHeight()
|
||||
+ mFullscreenManager.getBottomControlsMinHeight()
|
||||
: 0;
|
||||
int controlsHeight = controlsResizeView()
|
||||
? getTopControlsHeightPixels() + getBottomControlsHeightPixels()
|
||||
: 0;
|
||||
: totalMinHeight;
|
||||
|
||||
if (isAttachedToWindow(view)) {
|
||||
webContents.setSize(w, h - controlsHeight);
|
||||
@ -989,7 +996,7 @@ public class CompositorViewHolder extends FrameLayout
|
||||
* @return {@code true} if browser controls shrink Blink view's size.
|
||||
*/
|
||||
public boolean controlsResizeView() {
|
||||
return mFullscreenManager != null ? mFullscreenManager.controlsResizeView() : false;
|
||||
return mFullscreenManager != null && mFullscreenManager.controlsResizeView();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -17,6 +17,7 @@ import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import org.chromium.base.ActivityState;
|
||||
import org.chromium.base.ApplicationStatus;
|
||||
@ -471,7 +472,7 @@ public class ChromeFullscreenManager extends FullscreenManager
|
||||
@Override
|
||||
public void onEnterFullscreen(FullscreenOptions options) {
|
||||
Tab tab = getTab();
|
||||
if (areBrowserControlsOffScreen()) {
|
||||
if (areBrowserControlsAtMinHeight()) {
|
||||
// The browser controls are currently hidden.
|
||||
getHtmlApiHandler().enterFullscreen(tab, options);
|
||||
} else {
|
||||
@ -518,6 +519,15 @@ public class ChromeFullscreenManager extends FullscreenManager
|
||||
return getBrowserControlHiddenRatio() == 1.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if the browser controls are showing as much as the min height. Note that this is
|
||||
* the same as {@link #areBrowserControlsOffScreen()} when both min-heights are 0.
|
||||
*/
|
||||
public boolean areBrowserControlsAtMinHeight() {
|
||||
return getContentOffset() == getTopControlsMinHeight()
|
||||
&& getBottomContentOffset() == getBottomControlsMinHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if the browser controls are currently completely visible.
|
||||
*/
|
||||
@ -617,6 +627,14 @@ public class ChromeFullscreenManager extends FullscreenManager
|
||||
return mRendererTopControlsMinHeightOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The content offset from the bottom of the screen, or the visible height of the bottom
|
||||
* controls, in px.
|
||||
*/
|
||||
public int getBottomContentOffset() {
|
||||
return getBottomControlsHeight() - getBottomControlOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBottomControlOffset() {
|
||||
// If the height is currently 0, the offset generated by the bottom controls should be too.
|
||||
@ -678,19 +696,25 @@ public class ChromeFullscreenManager extends FullscreenManager
|
||||
public void updateViewportSize() {
|
||||
if (mInGesture || mContentViewScrolling) return;
|
||||
|
||||
// Update content viewport size only when the browser controls are not animating.
|
||||
int topContentOffset = mRendererTopContentOffset;
|
||||
int bottomControlOffset = mRendererBottomControlOffset;
|
||||
if ((topContentOffset != 0 && topContentOffset != getTopControlsHeight())
|
||||
&& bottomControlOffset != 0 && bottomControlOffset != getBottomControlsHeight()) {
|
||||
return;
|
||||
}
|
||||
boolean controlsResizeView =
|
||||
topContentOffset > 0 || bottomControlOffset < getBottomControlsHeight();
|
||||
mControlsResizeView = controlsResizeView;
|
||||
// Update content viewport size only if the browser controls are not moving, i.e. not
|
||||
// scrolling or animating.
|
||||
if (!areBrowserControlsIdle()) return;
|
||||
|
||||
mControlsResizeView = getContentOffset() > getTopControlsMinHeight()
|
||||
|| getBottomContentOffset() > getBottomControlsMinHeight();
|
||||
for (FullscreenListener listener : mListeners) listener.onUpdateViewportSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether browser controls are currently idle, i.e. not scrolling or animating.
|
||||
*/
|
||||
private boolean areBrowserControlsIdle() {
|
||||
return (getContentOffset() == getTopControlsMinHeight()
|
||||
|| getContentOffset() == getTopControlsHeight())
|
||||
&& (getBottomContentOffset() == getBottomControlsMinHeight()
|
||||
|| getBottomContentOffset() == getBottomControlsHeight());
|
||||
}
|
||||
|
||||
// View.OnHierarchyChangeListener implementation
|
||||
|
||||
@Override
|
||||
@ -709,7 +733,7 @@ public class ChromeFullscreenManager extends FullscreenManager
|
||||
if (view == null) return;
|
||||
|
||||
float topViewsTranslation = getTopVisibleContentOffset();
|
||||
float bottomMargin = getBottomControlsHeight() - getBottomControlOffset();
|
||||
float bottomMargin = getBottomContentOffset();
|
||||
applyTranslationToTopChildViews(view, topViewsTranslation);
|
||||
applyMarginToFullChildViews(view, topViewsTranslation, bottomMargin);
|
||||
updateViewportSize();
|
||||
@ -757,7 +781,7 @@ public class ChromeFullscreenManager extends FullscreenManager
|
||||
}
|
||||
|
||||
final Tab tab = getTab();
|
||||
if (tab != null && areBrowserControlsOffScreen() && mIsEnteringPersistentModeState) {
|
||||
if (tab != null && areBrowserControlsAtMinHeight() && mIsEnteringPersistentModeState) {
|
||||
getHtmlApiHandler().enterFullscreen(tab, mPendingFullscreenOptions);
|
||||
mIsEnteringPersistentModeState = false;
|
||||
mPendingFullscreenOptions = null;
|
||||
@ -1136,4 +1160,9 @@ public class ChromeFullscreenManager extends FullscreenManager
|
||||
}
|
||||
VrModuleProvider.unregisterVrModeObserver(this);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
TabModelSelectorTabObserver getTabFullscreenObserverForTesting() {
|
||||
return mTabFullscreenObserver;
|
||||
}
|
||||
}
|
||||
|
269
chrome/android/junit/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerUnitTest.java
Normal file
269
chrome/android/junit/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerUnitTest.java
Normal file
@ -0,0 +1,269 @@
|
||||
// Copyright 2020 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package org.chromium.chrome.browser.fullscreen;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.View;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import org.chromium.base.ActivityState;
|
||||
import org.chromium.base.ApplicationStatus;
|
||||
import org.chromium.base.UserDataHost;
|
||||
import org.chromium.base.test.BaseRobolectricTestRunner;
|
||||
import org.chromium.chrome.R;
|
||||
import org.chromium.chrome.browser.tab.Tab;
|
||||
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
|
||||
import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
|
||||
import org.chromium.chrome.browser.toolbar.ControlContainer;
|
||||
import org.chromium.chrome.test.util.browser.Features;
|
||||
import org.chromium.components.embedder_support.view.ContentView;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ChromeFullscreenManager}.
|
||||
*/
|
||||
@RunWith(BaseRobolectricTestRunner.class)
|
||||
public class FullscreenManagerUnitTest {
|
||||
@Rule
|
||||
public TestRule mProcessor = new Features.JUnitProcessor();
|
||||
|
||||
// Since these tests don't depend on the heights being pixels, we can use these as dpi directly.
|
||||
private static final int TOOLBAR_HEIGHT = 56;
|
||||
private static final int EXTRA_TOP_CONTROL_HEIGHT = 20;
|
||||
|
||||
@Mock
|
||||
private Activity mActivity;
|
||||
@Mock
|
||||
private ControlContainer mControlContainer;
|
||||
@Mock
|
||||
private View mContainerView;
|
||||
@Mock
|
||||
private TabModelSelector mTabModelSelector;
|
||||
@Mock
|
||||
private android.content.res.Resources mResources;
|
||||
@Mock
|
||||
private ChromeFullscreenManager.FullscreenListener mFullscreenListener;
|
||||
@Mock
|
||||
private Tab mTab;
|
||||
@Mock
|
||||
private ContentView mContentView;
|
||||
|
||||
private UserDataHost mUserDataHost = new UserDataHost();
|
||||
private ChromeFullscreenManager mFullscreenManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.CREATED);
|
||||
when(mActivity.getResources()).thenReturn(mResources);
|
||||
when(mResources.getDimensionPixelSize(R.dimen.control_container_height))
|
||||
.thenReturn(TOOLBAR_HEIGHT);
|
||||
when(mControlContainer.getView()).thenReturn(mContainerView);
|
||||
when(mContainerView.getVisibility()).thenReturn(View.VISIBLE);
|
||||
when(mTab.isUserInteractable()).thenReturn(true);
|
||||
when(mTab.isInitialized()).thenReturn(true);
|
||||
when(mTab.getUserDataHost()).thenReturn(mUserDataHost);
|
||||
when(mTab.getContentView()).thenReturn(mContentView);
|
||||
doNothing().when(mContentView).removeOnHierarchyChangeListener(any());
|
||||
doNothing().when(mContentView).removeOnSystemUiVisibilityChangeListener(any());
|
||||
doNothing().when(mContentView).addOnHierarchyChangeListener(any());
|
||||
doNothing().when(mContentView).addOnSystemUiVisibilityChangeListener(any());
|
||||
|
||||
ChromeFullscreenManager fullscreenManager = new ChromeFullscreenManager(
|
||||
mActivity, ChromeFullscreenManager.ControlsPosition.TOP);
|
||||
mFullscreenManager = spy(fullscreenManager);
|
||||
mFullscreenManager.initialize(
|
||||
mControlContainer, mTabModelSelector, R.dimen.control_container_height);
|
||||
mFullscreenManager.addListener(mFullscreenListener);
|
||||
when(mFullscreenManager.getTab()).thenReturn(mTab);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitialTopControlsHeight() {
|
||||
assertEquals("Wrong initial top controls height.", TOOLBAR_HEIGHT,
|
||||
mFullscreenManager.getTopControlsHeight());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListenersNotifiedOfTopControlsHeightChange() {
|
||||
final int topControlsHeight = TOOLBAR_HEIGHT + EXTRA_TOP_CONTROL_HEIGHT;
|
||||
final int topControlsMinHeight = EXTRA_TOP_CONTROL_HEIGHT;
|
||||
mFullscreenManager.setTopControlsHeight(topControlsHeight, topControlsMinHeight);
|
||||
verify(mFullscreenListener)
|
||||
.onTopControlsHeightChanged(topControlsHeight, topControlsMinHeight);
|
||||
}
|
||||
|
||||
// controlsResizeView tests ---
|
||||
// For these tests, we will simulate the scrolls assuming we either completely show or hide (or
|
||||
// scroll until the min-height) the controls and don't leave at in-between positions. The reason
|
||||
// is that ChromeFullscreenManager only flips the mControlsResizeView bit if the controls are
|
||||
// idle, meaning they're at the min-height or fully shown. Making sure the controls snap to
|
||||
// these two positions is not CFM's responsibility as it's handled in native code by compositor
|
||||
// or blink.
|
||||
|
||||
@Test
|
||||
public void testControlsResizeViewChanges() {
|
||||
// Let's use simpler numbers for this test.
|
||||
final int topHeight = 100;
|
||||
final int topMinHeight = 0;
|
||||
|
||||
TabModelSelectorTabObserver tabFullscreenObserver =
|
||||
mFullscreenManager.getTabFullscreenObserverForTesting();
|
||||
|
||||
mFullscreenManager.setTopControlsHeight(topHeight, topMinHeight);
|
||||
|
||||
// Send initial offsets.
|
||||
tabFullscreenObserver.onBrowserControlsOffsetChanged(mTab, /*topControlsOffsetY*/ 0,
|
||||
/*bottomControlsOffsetY*/ 0, /*contentOffsetY*/ 100,
|
||||
/*topControlsMinHeightOffsetY*/ 0, /*bottomControlsMinHeightOffsetY*/ 0);
|
||||
// Initially, the controls should be fully visible.
|
||||
assertTrue("Browser controls aren't fully visible.",
|
||||
mFullscreenManager.areBrowserControlsFullyVisible());
|
||||
assertTrue("ControlsResizeView is false,"
|
||||
+ " but it should be true when the controls are fully visible.",
|
||||
mFullscreenManager.controlsResizeView());
|
||||
|
||||
// Scroll to fully hidden.
|
||||
tabFullscreenObserver.onBrowserControlsOffsetChanged(mTab, /*topControlsOffsetY*/ -100,
|
||||
/*bottomControlsOffsetY*/ 0, /*contentOffsetY*/ 0,
|
||||
/*topControlsMinHeightOffsetY*/ 0, /*bottomControlsMinHeightOffsetY*/ 0);
|
||||
assertTrue("Browser controls aren't at min-height.",
|
||||
mFullscreenManager.areBrowserControlsAtMinHeight());
|
||||
assertFalse("ControlsResizeView is true,"
|
||||
+ " but it should be false when the controls are hidden.",
|
||||
mFullscreenManager.controlsResizeView());
|
||||
|
||||
// Now, scroll back to fully visible.
|
||||
tabFullscreenObserver.onBrowserControlsOffsetChanged(mTab, /*topControlsOffsetY*/ 0,
|
||||
/*bottomControlsOffsetY*/ 0, /*contentOffsetY*/ 100,
|
||||
/*topControlsMinHeightOffsetY*/ 0, /*bottomControlsMinHeightOffsetY*/ 0);
|
||||
assertFalse("Browser controls are hidden when they should be fully visible.",
|
||||
mFullscreenManager.areBrowserControlsAtMinHeight());
|
||||
assertTrue("Browser controls aren't fully visible.",
|
||||
mFullscreenManager.areBrowserControlsFullyVisible());
|
||||
// #controlsResizeView should be flipped back to true.
|
||||
assertTrue("ControlsResizeView is false,"
|
||||
+ " but it should be true when the controls are fully visible.",
|
||||
mFullscreenManager.controlsResizeView());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testControlsResizeViewChangesWithMinHeight() {
|
||||
// Let's use simpler numbers for this test. We'll simulate the scrolling logic in the
|
||||
// compositor. Which means the top and bottom controls will have the same normalized ratio.
|
||||
// E.g. if the top content offset is 25 (at min-height so the normalized ratio is 0), the
|
||||
// bottom content offset will be 0 (min-height-0 + normalized-ratio-0 * rest-of-height-60).
|
||||
final int topHeight = 100;
|
||||
final int topMinHeight = 25;
|
||||
final int bottomHeight = 60;
|
||||
final int bottomMinHeight = 0;
|
||||
|
||||
TabModelSelectorTabObserver tabFullscreenObserver =
|
||||
mFullscreenManager.getTabFullscreenObserverForTesting();
|
||||
|
||||
mFullscreenManager.setTopControlsHeight(topHeight, topMinHeight);
|
||||
mFullscreenManager.setBottomControlsHeight(bottomHeight, bottomMinHeight);
|
||||
|
||||
// Send initial offsets.
|
||||
tabFullscreenObserver.onBrowserControlsOffsetChanged(mTab, /*topControlsOffsetY*/ 0,
|
||||
/*bottomControlsOffsetY*/ 0, /*contentOffsetY*/ 100,
|
||||
/*topControlsMinHeightOffsetY*/ 25, /*bottomControlsMinHeightOffsetY*/ 0);
|
||||
// Initially, the controls should be fully visible.
|
||||
assertTrue("Browser controls aren't fully visible.",
|
||||
mFullscreenManager.areBrowserControlsFullyVisible());
|
||||
assertTrue("ControlsResizeView is false,"
|
||||
+ " but it should be true when the controls are fully visible.",
|
||||
mFullscreenManager.controlsResizeView());
|
||||
|
||||
// Scroll all the way to the min-height.
|
||||
tabFullscreenObserver.onBrowserControlsOffsetChanged(mTab, /*topControlsOffsetY*/ -75,
|
||||
/*bottomControlsOffsetY*/ 60, /*contentOffsetY*/ 25,
|
||||
/*topControlsMinHeightOffsetY*/ 25, /*bottomControlsMinHeightOffsetY*/ 0);
|
||||
assertTrue("Browser controls aren't at min-height.",
|
||||
mFullscreenManager.areBrowserControlsAtMinHeight());
|
||||
assertFalse("ControlsResizeView is true,"
|
||||
+ " but it should be false when the controls are at min-height.",
|
||||
mFullscreenManager.controlsResizeView());
|
||||
|
||||
// Now, scroll back to fully visible.
|
||||
tabFullscreenObserver.onBrowserControlsOffsetChanged(mTab, /*topControlsOffsetY*/ 0,
|
||||
/*bottomControlsOffsetY*/ 0, /*contentOffsetY*/ 100,
|
||||
/*topControlsMinHeightOffsetY*/ 25, /*bottomControlsMinHeightOffsetY*/ 0);
|
||||
assertFalse("Browser controls are at min-height when they should be fully visible.",
|
||||
mFullscreenManager.areBrowserControlsAtMinHeight());
|
||||
assertTrue("Browser controls aren't fully visible.",
|
||||
mFullscreenManager.areBrowserControlsFullyVisible());
|
||||
// #controlsResizeView should be flipped back to true.
|
||||
assertTrue("ControlsResizeView is false,"
|
||||
+ " but it should be true when the controls are fully visible.",
|
||||
mFullscreenManager.controlsResizeView());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testControlsResizeViewWhenControlsAreNotIdle() {
|
||||
// Let's use simpler numbers for this test. We'll simulate the scrolling logic in the
|
||||
// compositor. Which means the top and bottom controls will have the same normalized ratio.
|
||||
// E.g. if the top content offset is 25 (at min-height so the normalized ratio is 0), the
|
||||
// bottom content offset will be 0 (min-height-0 + normalized-ratio-0 * rest-of-height-60).
|
||||
final int topHeight = 100;
|
||||
final int topMinHeight = 25;
|
||||
final int bottomHeight = 60;
|
||||
final int bottomMinHeight = 0;
|
||||
|
||||
TabModelSelectorTabObserver tabFullscreenObserver =
|
||||
mFullscreenManager.getTabFullscreenObserverForTesting();
|
||||
|
||||
mFullscreenManager.setTopControlsHeight(topHeight, topMinHeight);
|
||||
mFullscreenManager.setBottomControlsHeight(bottomHeight, bottomMinHeight);
|
||||
|
||||
// Send initial offsets.
|
||||
tabFullscreenObserver.onBrowserControlsOffsetChanged(mTab, /*topControlsOffsetY*/ 0,
|
||||
/*bottomControlsOffsetY*/ 0, /*contentOffsetY*/ 100,
|
||||
/*topControlsMinHeightOffsetY*/ 25, /*bottomControlsMinHeightOffsetY*/ 0);
|
||||
assertTrue("ControlsResizeView is false,"
|
||||
+ " but it should be true when the controls are fully visible.",
|
||||
mFullscreenManager.controlsResizeView());
|
||||
|
||||
// Scroll a little hide the controls partially.
|
||||
tabFullscreenObserver.onBrowserControlsOffsetChanged(mTab, /*topControlsOffsetY*/ -25,
|
||||
/*bottomControlsOffsetY*/ 20, /*contentOffsetY*/ 75,
|
||||
/*topControlsMinHeightOffsetY*/ 25, /*bottomControlsMinHeightOffsetY*/ 0);
|
||||
assertTrue("ControlsResizeView is false, but it should still be true.",
|
||||
mFullscreenManager.controlsResizeView());
|
||||
|
||||
// Scroll controls all the way to the min-height.
|
||||
tabFullscreenObserver.onBrowserControlsOffsetChanged(mTab, /*topControlsOffsetY*/ -75,
|
||||
/*bottomControlsOffsetY*/ 60, /*contentOffsetY*/ 25,
|
||||
/*topControlsMinHeightOffsetY*/ 25, /*bottomControlsMinHeightOffsetY*/ 0);
|
||||
assertFalse("ControlsResizeView is true,"
|
||||
+ " but it should've flipped to false since the controls are idle now.",
|
||||
mFullscreenManager.controlsResizeView());
|
||||
|
||||
// Scroll controls to show a little more.
|
||||
tabFullscreenObserver.onBrowserControlsOffsetChanged(mTab, /*topControlsOffsetY*/ -50,
|
||||
/*bottomControlsOffsetY*/ 40, /*contentOffsetY*/ 50,
|
||||
/*topControlsMinHeightOffsetY*/ 25, /*bottomControlsMinHeightOffsetY*/ 0);
|
||||
assertFalse("ControlsResizeView is true, but it should still be false.",
|
||||
mFullscreenManager.controlsResizeView());
|
||||
}
|
||||
|
||||
// --- controlsResizeView tests
|
||||
}
|
@ -1267,7 +1267,8 @@ void WebViewImpl::UpdateICBAndResizeViewport(
|
||||
if (GetBrowserControls().PermittedState() ==
|
||||
cc::BrowserControlsState::kBoth &&
|
||||
!GetBrowserControls().ShrinkViewport()) {
|
||||
icb_size.Expand(0, -GetBrowserControls().TotalHeight());
|
||||
icb_size.Expand(0, -(GetBrowserControls().TotalHeight() -
|
||||
GetBrowserControls().TotalMinHeight()));
|
||||
}
|
||||
|
||||
GetPageScaleConstraintsSet().DidChangeInitialContainingBlockSize(icb_size);
|
||||
|
@ -41,6 +41,7 @@ class CORE_EXPORT BrowserControls final
|
||||
float BottomHeight() const { return params_.bottom_controls_height; }
|
||||
float BottomMinHeight() const { return params_.bottom_controls_min_height; }
|
||||
float TotalHeight() const { return TopHeight() + BottomHeight(); }
|
||||
float TotalMinHeight() const { return TopMinHeight() + BottomMinHeight(); }
|
||||
bool ShrinkViewport() const {
|
||||
return params_.browser_controls_shrink_blink_size;
|
||||
}
|
||||
|
@ -1135,6 +1135,140 @@ TEST_F(BrowserControlsTest, MAYBE(DontAffectVHUnitsUseLayoutSize)) {
|
||||
EXPECT_EQ(800, GetFrame()->View()->ViewportSizeForViewportUnits().Height());
|
||||
}
|
||||
|
||||
// Ensure that vh units are correctly calculated when a top controls min-height
|
||||
// is set.
|
||||
TEST_F(BrowserControlsTest, MAYBE(VHUnitsWithTopMinHeight)) {
|
||||
// Initialize with the browser controls showing.
|
||||
// Top controls height: 100, top controls min-height: 20.
|
||||
WebViewImpl* web_view = Initialize("vh-height.html");
|
||||
web_view->ResizeWithBrowserControls(WebSize(400, 300), WebSize(400, 300),
|
||||
{100, 20, 0, 0, false, true});
|
||||
web_view->GetBrowserControls().UpdateConstraintsAndState(
|
||||
cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kShown);
|
||||
web_view->GetBrowserControls().SetShownRatio(1, 1);
|
||||
UpdateAllLifecyclePhases();
|
||||
|
||||
ASSERT_EQ(100.f, web_view->GetBrowserControls().ContentOffset());
|
||||
|
||||
// 'vh' units should be based on the viewport when the browser controls are
|
||||
// hidden. However, the viewport height will be limited by the min-height
|
||||
// since the top controls can't completely hide.
|
||||
Element* abs_pos = GetElementById(WebString::FromUTF8("abs"));
|
||||
Element* fixed_pos = GetElementById(WebString::FromUTF8("fixed"));
|
||||
float div_height = 0.5f * (300 + (100 - 20));
|
||||
EXPECT_FLOAT_EQ(div_height, abs_pos->getBoundingClientRect()->height());
|
||||
EXPECT_FLOAT_EQ(div_height, fixed_pos->getBoundingClientRect()->height());
|
||||
|
||||
// The size used for viewport units should be reduced by the top controls
|
||||
// min-height.
|
||||
EXPECT_EQ(380, GetFrame()->View()->ViewportSizeForViewportUnits().Height());
|
||||
|
||||
// Scroll the top controls to hide. They won't scroll past the min-height.
|
||||
VerticalScroll(-100.f);
|
||||
web_view->ResizeWithBrowserControls(WebSize(400, 380), WebSize(400, 380),
|
||||
{100, 20, 0, 0, false, false});
|
||||
UpdateAllLifecyclePhases();
|
||||
|
||||
ASSERT_EQ(20.f, web_view->GetBrowserControls().ContentOffset());
|
||||
|
||||
// vh units should be static with respect to the browser controls so neither
|
||||
// <div> should change size are a result of the browser controls hiding.
|
||||
EXPECT_FLOAT_EQ(190.f, abs_pos->getBoundingClientRect()->height());
|
||||
EXPECT_FLOAT_EQ(190.f, fixed_pos->getBoundingClientRect()->height());
|
||||
|
||||
// The viewport size used for vh units should not change as a result of top
|
||||
// controls hiding.
|
||||
ASSERT_EQ(380, GetFrame()->View()->ViewportSizeForViewportUnits().Height());
|
||||
}
|
||||
|
||||
// Ensure that vh units are correctly calculated when a bottom controls
|
||||
// min-height is set.
|
||||
TEST_F(BrowserControlsTest, MAYBE(VHUnitsWithBottomMinHeight)) {
|
||||
// Initialize with the browser controls showing.
|
||||
// Top controls height: 100, top controls min-height: 20.
|
||||
// Bottom controls height: 50, bottom controls min-height: 10.
|
||||
WebViewImpl* web_view = Initialize("vh-height.html");
|
||||
web_view->ResizeWithBrowserControls(WebSize(400, 250), WebSize(400, 250),
|
||||
{100, 20, 50, 10, false, true});
|
||||
web_view->GetBrowserControls().UpdateConstraintsAndState(
|
||||
cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kShown);
|
||||
web_view->GetBrowserControls().SetShownRatio(1, 1);
|
||||
UpdateAllLifecyclePhases();
|
||||
|
||||
EXPECT_FLOAT_EQ(100.f, web_view->GetBrowserControls().ContentOffset());
|
||||
|
||||
// 'vh' units should be based on the viewport when the browser controls are
|
||||
// hidden. However, the viewport height will be limited by the min-height
|
||||
// since the top and bottom controls can't completely hide.
|
||||
Element* abs_pos = GetElementById(WebString::FromUTF8("abs"));
|
||||
Element* fixed_pos = GetElementById(WebString::FromUTF8("fixed"));
|
||||
float div_height = 0.5f * (250 + (100 - 20) + (50 - 10));
|
||||
EXPECT_FLOAT_EQ(div_height, abs_pos->getBoundingClientRect()->height());
|
||||
EXPECT_FLOAT_EQ(div_height, fixed_pos->getBoundingClientRect()->height());
|
||||
|
||||
// The size used for viewport units should be reduced by the top/bottom
|
||||
// controls min-height.
|
||||
EXPECT_EQ(370, GetFrame()->View()->ViewportSizeForViewportUnits().Height());
|
||||
|
||||
// Scroll the controls to hide. They won't scroll past the min-height.
|
||||
VerticalScroll(-100.f);
|
||||
web_view->ResizeWithBrowserControls(WebSize(400, 370), WebSize(400, 370),
|
||||
{100, 20, 50, 10, false, false});
|
||||
UpdateAllLifecyclePhases();
|
||||
|
||||
EXPECT_FLOAT_EQ(20.f, web_view->GetBrowserControls().ContentOffset());
|
||||
EXPECT_FLOAT_EQ(10.f, web_view->GetBrowserControls().BottomContentOffset());
|
||||
|
||||
// vh units should be static with respect to the browser controls so neither
|
||||
// <div> should change size are a result of the browser controls hiding.
|
||||
EXPECT_FLOAT_EQ(185.f, abs_pos->getBoundingClientRect()->height());
|
||||
EXPECT_FLOAT_EQ(185.f, fixed_pos->getBoundingClientRect()->height());
|
||||
|
||||
// The viewport size used for vh units should not change as a result of the
|
||||
// controls hiding.
|
||||
ASSERT_EQ(370, GetFrame()->View()->ViewportSizeForViewportUnits().Height());
|
||||
}
|
||||
|
||||
// Ensure that vh units are correctly calculated with changing min-heights.
|
||||
TEST_F(BrowserControlsTest, MAYBE(VHUnitsWithMinHeightsChanging)) {
|
||||
// Initialize with the browser controls showing.
|
||||
// Top controls height: 100, top controls min-height: 20.
|
||||
// Bottom controls height: 50, bottom controls min-height: 10.
|
||||
WebViewImpl* web_view = Initialize("vh-height.html");
|
||||
web_view->ResizeWithBrowserControls(WebSize(400, 250), WebSize(400, 250),
|
||||
{100, 20, 50, 10, false, true});
|
||||
web_view->GetBrowserControls().UpdateConstraintsAndState(
|
||||
cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kShown);
|
||||
web_view->GetBrowserControls().SetShownRatio(1, 1);
|
||||
UpdateAllLifecyclePhases();
|
||||
|
||||
EXPECT_FLOAT_EQ(100.f, web_view->GetBrowserControls().ContentOffset());
|
||||
|
||||
// 'vh' units should be based on the viewport when the browser controls are
|
||||
// hidden. However, the viewport height will be limited by the min-height
|
||||
// since the top and bottom controls can't completely hide.
|
||||
Element* abs_pos = GetElementById(WebString::FromUTF8("abs"));
|
||||
Element* fixed_pos = GetElementById(WebString::FromUTF8("fixed"));
|
||||
float div_height = 0.5f * (250 + (100 - 20) + (50 - 10));
|
||||
EXPECT_FLOAT_EQ(div_height, abs_pos->getBoundingClientRect()->height());
|
||||
EXPECT_FLOAT_EQ(div_height, fixed_pos->getBoundingClientRect()->height());
|
||||
|
||||
// The size used for viewport units should be reduced by the top/bottom
|
||||
// controls min-height.
|
||||
EXPECT_EQ(370, GetFrame()->View()->ViewportSizeForViewportUnits().Height());
|
||||
|
||||
// Make the min-heights 0.
|
||||
web_view->ResizeWithBrowserControls(WebSize(400, 250), WebSize(400, 250),
|
||||
{100, 0, 50, 0, false, true});
|
||||
UpdateAllLifecyclePhases();
|
||||
|
||||
// The viewport size used for vh units should be updated to reflect the change
|
||||
// to the min-heights.
|
||||
float height = 250 + (100 - 0) + (50 - 0);
|
||||
ASSERT_EQ(height,
|
||||
GetFrame()->View()->ViewportSizeForViewportUnits().Height());
|
||||
}
|
||||
|
||||
// This tests that the viewport remains anchored when browser controls are
|
||||
// brought in while the document is fully scrolled. This normally causes
|
||||
// clamping of the visual viewport to keep it bounded by the layout viewport
|
||||
|
@ -1024,8 +1024,9 @@ FloatSize LocalFrameView::ViewportSizeForViewportUnits() const {
|
||||
// zoom factor when use-zoom-for-dsf is enabled on Android. Confirm this
|
||||
// works correctly when that's turned on. https://crbug.com/737777.
|
||||
float page_scale_at_layout_width = viewport_width / layout_size.Width();
|
||||
layout_size.Expand(
|
||||
0, browser_controls.TotalHeight() / page_scale_at_layout_width);
|
||||
layout_size.Expand(0, (browser_controls.TotalHeight() -
|
||||
browser_controls.TotalMinHeight()) /
|
||||
page_scale_at_layout_width);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user