mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 1586144 - Factor dynamic toolbar max height into layout metrics. r=emilio,botond
Now * nsPresContext::mVisibleArea is excluding the toolbar max height so that ICB is now static regardless of the dynamic toolbar transition * nsPresContext::mSizeForViewportUnits is introduced to resolve viewport units which is including the toolbar max height That means that with the dynamic toolbar max height; mVisibleArea < mSizeForViewportUnits See https://github.com/bokand/URLBarSizing for more detail backgrounds of this change. Depends on D50417 Differential Revision: https://phabricator.services.mozilla.com/D50418 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
2a51338a5a
commit
f5f6f60da5
@ -1482,6 +1482,24 @@ nsDOMWindowUtils::GetVisualViewportOffset(int32_t* aOffsetX,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SetDynamicToolbarMaxHeight(uint32_t aHeightInScreen) {
|
||||
if (aHeightInScreen > INT32_MAX) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
RefPtr<nsPresContext> presContext = GetPresContext();
|
||||
if (!presContext) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(presContext->IsRootContentDocumentCrossProcess());
|
||||
|
||||
presContext->SetDynamicToolbarMaxHeight(ScreenIntCoord(aHeightInScreen));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetScrollbarSize(bool aFlushLayout, int32_t* aWidth,
|
||||
int32_t* aHeight) {
|
||||
|
@ -867,6 +867,12 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
*/
|
||||
void getVisualViewportOffset(out long aOffsetX, out long aOffsetY);
|
||||
|
||||
/**
|
||||
* Sets the maximum height of the dynamic toolbar in Screen pixel units.
|
||||
*/
|
||||
[can_run_script]
|
||||
void setDynamicToolbarMaxHeight(in uint32_t aHeightInScreen);
|
||||
|
||||
const long FLUSH_NONE = -1;
|
||||
const long FLUSH_STYLE = 0;
|
||||
const long FLUSH_LAYOUT = 1;
|
||||
|
@ -286,6 +286,7 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
|
||||
const mozilla::Maybe<mozilla::gfx::Matrix4x4>& aMatrix,
|
||||
const mozilla::ScreenRect& aRemoteDocumentRect);
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
mozilla::ipc::IPCResult RecvDynamicToolbarMaxHeightChanged(
|
||||
const mozilla::ScreenIntCoord& aHeight);
|
||||
|
||||
|
@ -460,6 +460,9 @@ ScreenIntSize MobileViewportManager::GetCompositionSize(
|
||||
return ScreenIntSize();
|
||||
}
|
||||
|
||||
// FIXME: Bug 1586986 - To update VisualViewport in response to the dynamic
|
||||
// toolbar transition we probably need to include the dynamic toolbar
|
||||
// _current_ height.
|
||||
ScreenIntSize compositionSize(aDisplaySize);
|
||||
ScreenMargin scrollbars =
|
||||
mContext->ScrollbarAreaToExcludeFromCompositionBounds()
|
||||
|
@ -8424,6 +8424,19 @@ bool nsLayoutUtils::GetContentViewerSize(nsPresContext* aPresContext,
|
||||
|
||||
nsIntRect bounds;
|
||||
cv->GetBounds(bounds);
|
||||
|
||||
if (aPresContext->HasDynamicToolbar() && !bounds.IsEmpty()) {
|
||||
MOZ_ASSERT(aPresContext->IsRootContentDocumentCrossProcess());
|
||||
MOZ_ASSERT(bounds.height > aPresContext->GetDynamicToolbarMaxHeight());
|
||||
bounds.height -= aPresContext->GetDynamicToolbarMaxHeight();
|
||||
// Collapse the size in the case the dynamic toolbar max height is greater
|
||||
// than the content bound height so that hopefully embedders of GeckoView
|
||||
// may notice they set wrong dynamic toolbar max height.
|
||||
if (bounds.height < 0) {
|
||||
bounds.height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
aOutSize = LayoutDeviceIntRect::FromUnknownRect(bounds).Size();
|
||||
return true;
|
||||
}
|
||||
|
@ -87,6 +87,7 @@
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/dom/PerformanceTiming.h"
|
||||
#include "mozilla/layers/APZThreadUtils.h"
|
||||
#include "MobileViewportManager.h"
|
||||
|
||||
// Needed for Start/Stop of Image Animation
|
||||
#include "imgIContainer.h"
|
||||
@ -422,6 +423,12 @@ void nsPresContext::AppUnitsPerDevPixelChanged() {
|
||||
|
||||
mCurAppUnitsPerDevPixel = mDeviceContext->AppUnitsPerDevPixel();
|
||||
|
||||
// Recompute the size for vh units since it's changed by the dynamic toolbar
|
||||
// max height which is stored in screen coord.
|
||||
if (IsRootContentDocumentCrossProcess()) {
|
||||
AdjustSizeForViewportUnits();
|
||||
}
|
||||
|
||||
// nsSubDocumentFrame uses a AppUnitsPerDevPixel difference between parent and
|
||||
// child document to determine if it needs to build a nsDisplayZoom item. So
|
||||
// if we that changes then we need to invalidate the subdoc frame so that
|
||||
@ -2466,6 +2473,21 @@ void nsPresContext::FlushFontFeatureValues() {
|
||||
}
|
||||
}
|
||||
|
||||
void nsPresContext::SetVisibleArea(const nsRect& r) {
|
||||
if (!r.IsEqualEdges(mVisibleArea)) {
|
||||
mVisibleArea = r;
|
||||
mSizeForViewportUnits = mVisibleArea.Size();
|
||||
if (IsRootContentDocumentCrossProcess()) {
|
||||
AdjustSizeForViewportUnits();
|
||||
}
|
||||
// Visible area does not affect media queries when paginated.
|
||||
if (!IsPaginated()) {
|
||||
MediaFeatureValuesChanged(
|
||||
{mozilla::MediaFeatureChangeReason::ViewportChange});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsPresContext::SetDynamicToolbarMaxHeight(ScreenIntCoord aHeight) {
|
||||
MOZ_ASSERT(IsRootContentDocumentCrossProcess());
|
||||
|
||||
@ -2473,6 +2495,44 @@ void nsPresContext::SetDynamicToolbarMaxHeight(ScreenIntCoord aHeight) {
|
||||
return;
|
||||
}
|
||||
mDynamicToolbarMaxHeight = aHeight;
|
||||
|
||||
AdjustSizeForViewportUnits();
|
||||
|
||||
if (RefPtr<mozilla::PresShell> presShell = mPresShell) {
|
||||
// Changing the max height of the dynamic toolbar changes the ICB size, we
|
||||
// need to kick a reflow with the current window dimensions since the max
|
||||
// height change doesn't change the window dimensions but
|
||||
// PresShell::ResizeReflow ends up subtracting the new dynamic toolbar
|
||||
// height from the window dimensions and kick a reflow with the proper ICB
|
||||
// size.
|
||||
nscoord currentWidth, currentHeight;
|
||||
presShell->GetViewManager()->GetWindowDimensions(¤tWidth,
|
||||
¤tHeight);
|
||||
presShell->ResizeReflow(currentWidth, currentHeight,
|
||||
ResizeReflowOptions::NoOption);
|
||||
}
|
||||
}
|
||||
|
||||
void nsPresContext::AdjustSizeForViewportUnits() {
|
||||
MOZ_ASSERT(IsRootContentDocumentCrossProcess());
|
||||
if (mVisibleArea.height == NS_UNCONSTRAINEDSIZE) {
|
||||
// Ignore `NS_UNCONSTRAINEDSIZE` since it's a temporary state during a
|
||||
// reflow. We will end up calling this function again with a proper size in
|
||||
// the same reflow.
|
||||
return;
|
||||
}
|
||||
|
||||
if (MOZ_UNLIKELY(mVisibleArea.height +
|
||||
NSIntPixelsToAppUnits(mDynamicToolbarMaxHeight,
|
||||
mCurAppUnitsPerDevPixel) >
|
||||
nscoord_MAX)) {
|
||||
MOZ_ASSERT_UNREACHABLE("The dynamic toolbar max height is probably wrong");
|
||||
return;
|
||||
}
|
||||
|
||||
mSizeForViewportUnits.height =
|
||||
mVisibleArea.height +
|
||||
NSIntPixelsToAppUnits(mDynamicToolbarMaxHeight, mCurAppUnitsPerDevPixel);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -369,22 +369,27 @@ class nsPresContext : public nsISupports,
|
||||
* Set the currently visible area. The units for r are standard
|
||||
* nscoord units (as scaled by the device context).
|
||||
*/
|
||||
void SetVisibleArea(const nsRect& r) {
|
||||
if (!r.IsEqualEdges(mVisibleArea)) {
|
||||
mVisibleArea = r;
|
||||
// Visible area does not affect media queries when paginated.
|
||||
if (!IsPaginated()) {
|
||||
MediaFeatureValuesChanged(
|
||||
{mozilla::MediaFeatureChangeReason::ViewportChange});
|
||||
}
|
||||
}
|
||||
}
|
||||
void SetVisibleArea(const nsRect& r);
|
||||
|
||||
/**
|
||||
* Set the maximum height of the dynamic toolbar in nscoord units.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void SetDynamicToolbarMaxHeight(mozilla::ScreenIntCoord aHeight);
|
||||
|
||||
mozilla::ScreenIntCoord GetDynamicToolbarMaxHeight() const {
|
||||
MOZ_ASSERT(IsRootContentDocumentCrossProcess());
|
||||
return mDynamicToolbarMaxHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we are using the dynamic toolbar.
|
||||
*/
|
||||
bool HasDynamicToolbar() const {
|
||||
MOZ_ASSERT(IsRootContentDocumentCrossProcess());
|
||||
return mDynamicToolbarMaxHeight > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this presentation context is a paginated
|
||||
* context.
|
||||
@ -1114,6 +1119,10 @@ class nsPresContext : public nsISupports,
|
||||
};
|
||||
TransactionInvalidations* GetInvalidations(TransactionId aTransactionId);
|
||||
|
||||
// This should be called only when we update mVisibleArea or
|
||||
// mDynamicToolbarMaxHeight or `app units per device pixels` changes.
|
||||
void AdjustSizeForViewportUnits();
|
||||
|
||||
// IMPORTANT: The ownership implicit in the following member variables
|
||||
// has been explicitly checked. If you add any members to this class,
|
||||
// please make the ownership explicit (pinkerton, scc).
|
||||
@ -1173,6 +1182,10 @@ class nsPresContext : public nsISupports,
|
||||
mozilla::UniquePtr<gfxMissingFontRecorder> mMissingFonts;
|
||||
|
||||
nsRect mVisibleArea;
|
||||
// This value is used to resolve viewport units.
|
||||
// On mobile this size is including the dynamic toolbar maximum height below.
|
||||
// On desktops this size is pretty much the same as |mVisibleArea|.
|
||||
nsSize mSizeForViewportUnits;
|
||||
// The maximum height of the dynamic toolbar on mobile.
|
||||
mozilla::ScreenIntCoord mDynamicToolbarMaxHeight;
|
||||
nsSize mPageSize;
|
||||
|
59
layout/base/tests/file_dynamic_toolbar_max_height.html
Normal file
59
layout/base/tests/file_dynamic_toolbar_max_height.html
Normal file
@ -0,0 +1,59 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
|
||||
<title>Tests metrics with dynamic toolbar</title>
|
||||
<script>
|
||||
const ok = opener.ok.bind(opener);
|
||||
const is = opener.is.bind(opener);
|
||||
const original_finish = opener.SimpleTest.finish;
|
||||
const SimpleTest = opener.SimpleTest;
|
||||
const add_task = opener.add_task;
|
||||
SimpleTest.finish = function finish() {
|
||||
self.close();
|
||||
original_finish();
|
||||
}
|
||||
</script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
|
||||
<style>
|
||||
html {
|
||||
scrollbar-width: none;
|
||||
}
|
||||
#percent {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
}
|
||||
#vh {
|
||||
position: absolute;
|
||||
height: 100vh;
|
||||
}
|
||||
</style>
|
||||
<div id="percent"></div>
|
||||
<div id="vh"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
SpecialPowers.DOMWindowUtils.setDynamicToolbarMaxHeight(0);
|
||||
|
||||
let percentHeight = getComputedStyle(percent).height;
|
||||
let vhHeight = getComputedStyle(vh).height;
|
||||
is(percentHeight, vhHeight,
|
||||
"%-units and vh-units should be the same when the dynamic toolbar max " +
|
||||
"height is zero");
|
||||
|
||||
SpecialPowers.DOMWindowUtils.setDynamicToolbarMaxHeight(50);
|
||||
|
||||
percentHeight = getComputedStyle(percent).height;
|
||||
vhHeight = getComputedStyle(vh).height;
|
||||
is(parseInt(percentHeight) + 50, parseInt(vhHeight),
|
||||
"vh units should be 50px greater than %-units");
|
||||
is(document.documentElement.clientHeight, parseInt(percentHeight),
|
||||
"documentElement.clientHeight should equal to %-units");
|
||||
is(window.innerHeight, parseInt(percentHeight),
|
||||
"window.innerHeight should equal to %-units when the dynamic toolbar is " +
|
||||
"visible");
|
||||
ok(matchMedia(`(height: ${percentHeight})`).matches,
|
||||
"Media Queries' height is not including the dynamic toolbar max height");
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
</script>
|
@ -139,6 +139,8 @@ support-files = bug1226904.html
|
||||
support-files = bug1448730.html
|
||||
[test_bug1515822.html]
|
||||
[test_bug1550869_video.html]
|
||||
[test_dynamic_toolbar_max_height.html]
|
||||
support-files = file_dynamic_toolbar_max_height.html
|
||||
[test_emulateMedium.html]
|
||||
[test_emulate_color_scheme.html]
|
||||
[test_event_target_iframe_oop.html]
|
||||
|
23
layout/base/tests/test_dynamic_toolbar_max_height.html
Normal file
23
layout/base/tests/test_dynamic_toolbar_max_height.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{
|
||||
set: [
|
||||
["dom.meta-viewport.enabled", true],
|
||||
["apz.allow_zooming", true],
|
||||
],
|
||||
},
|
||||
function() {
|
||||
// We need to open a new window because the API to set the dynamic toolbar
|
||||
// max height works only in the top content document.
|
||||
window.open("file_dynamic_toolbar_max_height.html");
|
||||
}
|
||||
);
|
||||
</script>
|
||||
</html>
|
@ -237,7 +237,13 @@ impl Device {
|
||||
/// used for viewport unit resolution.
|
||||
pub fn au_viewport_size_for_viewport_unit_resolution(&self) -> Size2D<Au> {
|
||||
self.used_viewport_size.store(true, Ordering::Relaxed);
|
||||
self.au_viewport_size()
|
||||
|
||||
let pc = match self.pres_context() {
|
||||
Some(pc) => pc,
|
||||
None => return Size2D::new(Au(0), Au(0)),
|
||||
};
|
||||
let size = &pc.mSizeForViewportUnits;
|
||||
Size2D::new(Au(size.width), Au(size.height))
|
||||
}
|
||||
|
||||
/// Returns whether we ever looked up the viewport size of the Device.
|
||||
|
Loading…
Reference in New Issue
Block a user