mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Bug 1688004 - Build top layer items for XUL documents that don't have scrollframes. r=miko
This will allow the browser chrome to use `<dialog>` etc, see bug 1685313. Tweak the check to support scrolling="false" on reftests, so that we can test this. Differential Revision: https://phabricator.services.mozilla.com/D102623
This commit is contained in:
parent
bc32435029
commit
6a72aab71b
@ -2565,7 +2565,7 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock(
|
||||
isScrollable = presContext->HasPaginatedScrolling();
|
||||
} else if (isXUL) {
|
||||
isScrollable = false;
|
||||
} else if (nsContentUtils::IsInChromeDocshell(aDocElement->OwnerDoc()) &&
|
||||
} else if (aDocElement->OwnerDoc()->AllowXULXBL() &&
|
||||
aDocElement->AsElement()->AttrValueIs(
|
||||
kNameSpaceID_None, nsGkAtoms::scrolling, nsGkAtoms::_false,
|
||||
eCaseMatters)) {
|
||||
|
@ -16,9 +16,10 @@
|
||||
#include "mozilla/RestyleManager.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
#include "nsCanvasFrame.h"
|
||||
#include "nsAbsoluteContainingBlock.h"
|
||||
#include "nsCanvasFrame.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "nsIMozBrowserFrame.h"
|
||||
#include "nsPlaceholderFrame.h"
|
||||
@ -56,12 +57,27 @@ void ViewportFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
AUTO_PROFILER_LABEL("ViewportFrame::BuildDisplayList",
|
||||
GRAPHICS_DisplayListBuilding);
|
||||
|
||||
if (nsIFrame* kid = mFrames.FirstChild()) {
|
||||
// make the kid's BorderBackground our own. This ensures that the canvas
|
||||
// frame's background becomes our own background and therefore appears
|
||||
// below negative z-index elements.
|
||||
BuildDisplayListForChild(aBuilder, kid, aLists);
|
||||
nsIFrame* kid = mFrames.FirstChild();
|
||||
if (!kid) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsDisplayListCollection set(aBuilder);
|
||||
BuildDisplayListForChild(aBuilder, kid, set);
|
||||
|
||||
// If we have a scrollframe then it takes care of creating the display list
|
||||
// for the top layer, but otherwise we need to do it here.
|
||||
if (!kid->IsScrollFrame()) {
|
||||
bool isOpaque = false;
|
||||
if (auto* list = BuildDisplayListForTopLayer(aBuilder, &isOpaque)) {
|
||||
if (isOpaque) {
|
||||
set.DeleteAll(aBuilder);
|
||||
}
|
||||
set.PositionedDescendants()->AppendToTop(list);
|
||||
}
|
||||
}
|
||||
|
||||
set.MoveTo(aLists);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -150,51 +166,54 @@ static bool BackdropListIsOpaque(ViewportFrame* aFrame,
|
||||
return opaque.Contains(aFrame->GetRect());
|
||||
}
|
||||
|
||||
void ViewportFrame::BuildDisplayListForTopLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aList,
|
||||
bool* aIsOpaque) {
|
||||
nsDisplayWrapList* ViewportFrame::BuildDisplayListForTopLayer(
|
||||
nsDisplayListBuilder* aBuilder, bool* aIsOpaque) {
|
||||
nsDisplayList topLayerList;
|
||||
|
||||
nsTArray<dom::Element*> topLayer = PresContext()->Document()->GetTopLayer();
|
||||
for (dom::Element* elem : topLayer) {
|
||||
if (nsIFrame* frame = elem->GetPrimaryFrame()) {
|
||||
// There are two cases where an element in fullscreen is not in
|
||||
// the top layer:
|
||||
// 1. When building display list for purpose other than painting,
|
||||
// it is possible that there is inconsistency between the style
|
||||
// info and the content tree.
|
||||
// 2. This is an element which we are not going to put in the top
|
||||
// layer for fullscreen. See ShouldInTopLayerForFullscreen().
|
||||
// In both cases, we want to skip the frame here and paint it in
|
||||
// the normal path.
|
||||
if (frame->StyleDisplay()->mTopLayer == StyleTopLayer::None) {
|
||||
MOZ_ASSERT(!aBuilder->IsForPainting() ||
|
||||
!ShouldInTopLayerForFullscreen(elem));
|
||||
continue;
|
||||
}
|
||||
MOZ_ASSERT(ShouldInTopLayerForFullscreen(elem));
|
||||
// Inner SVG, MathML elements, as well as children of some XUL
|
||||
// elements are not allowed to be out-of-flow. They should not
|
||||
// be handled as top layer element here.
|
||||
if (!frame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
|
||||
MOZ_ASSERT(!elem->GetParent()->IsHTMLElement(),
|
||||
"HTML element should always be out-of-flow if in the top "
|
||||
"layer");
|
||||
continue;
|
||||
}
|
||||
if (nsIFrame* backdropPh =
|
||||
frame->GetChildList(kBackdropList).FirstChild()) {
|
||||
MOZ_ASSERT(!backdropPh->GetNextSibling(), "more than one ::backdrop?");
|
||||
MOZ_ASSERT(backdropPh->HasAnyStateBits(NS_FRAME_FIRST_REFLOW),
|
||||
"did you intend to reflow ::backdrop placeholders?");
|
||||
nsIFrame* backdropFrame =
|
||||
nsPlaceholderFrame::GetRealFrameForPlaceholder(backdropPh);
|
||||
BuildDisplayListForTopLayerFrame(aBuilder, backdropFrame, aList);
|
||||
|
||||
if (aIsOpaque) {
|
||||
*aIsOpaque = BackdropListIsOpaque(this, aBuilder, aList);
|
||||
}
|
||||
}
|
||||
BuildDisplayListForTopLayerFrame(aBuilder, frame, aList);
|
||||
nsIFrame* frame = elem->GetPrimaryFrame();
|
||||
if (!frame) {
|
||||
continue;
|
||||
}
|
||||
// There are two cases where an element in fullscreen is not in
|
||||
// the top layer:
|
||||
// 1. When building display list for purpose other than painting,
|
||||
// it is possible that there is inconsistency between the style
|
||||
// info and the content tree.
|
||||
// 2. This is an element which we are not going to put in the top
|
||||
// layer for fullscreen. See ShouldInTopLayerForFullscreen().
|
||||
// In both cases, we want to skip the frame here and paint it in
|
||||
// the normal path.
|
||||
if (frame->StyleDisplay()->mTopLayer == StyleTopLayer::None) {
|
||||
MOZ_ASSERT(!aBuilder->IsForPainting() ||
|
||||
!ShouldInTopLayerForFullscreen(elem));
|
||||
continue;
|
||||
}
|
||||
MOZ_ASSERT(ShouldInTopLayerForFullscreen(elem));
|
||||
// Inner SVG, MathML elements, as well as children of some XUL
|
||||
// elements are not allowed to be out-of-flow. They should not
|
||||
// be handled as top layer element here.
|
||||
if (!frame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
|
||||
MOZ_ASSERT(!elem->GetParent()->IsHTMLElement(),
|
||||
"HTML element should always be out-of-flow if in the top "
|
||||
"layer");
|
||||
continue;
|
||||
}
|
||||
if (nsIFrame* backdropPh =
|
||||
frame->GetChildList(kBackdropList).FirstChild()) {
|
||||
MOZ_ASSERT(!backdropPh->GetNextSibling(), "more than one ::backdrop?");
|
||||
MOZ_ASSERT(backdropPh->HasAnyStateBits(NS_FRAME_FIRST_REFLOW),
|
||||
"did you intend to reflow ::backdrop placeholders?");
|
||||
nsIFrame* backdropFrame =
|
||||
nsPlaceholderFrame::GetRealFrameForPlaceholder(backdropPh);
|
||||
BuildDisplayListForTopLayerFrame(aBuilder, backdropFrame, &topLayerList);
|
||||
|
||||
if (aIsOpaque) {
|
||||
*aIsOpaque = BackdropListIsOpaque(this, aBuilder, &topLayerList);
|
||||
}
|
||||
}
|
||||
BuildDisplayListForTopLayerFrame(aBuilder, frame, &topLayerList);
|
||||
}
|
||||
|
||||
if (nsCanvasFrame* canvasFrame = PresShell()->GetCanvasFrame()) {
|
||||
@ -203,10 +222,26 @@ void ViewportFrame::BuildDisplayListForTopLayer(nsDisplayListBuilder* aBuilder,
|
||||
MOZ_ASSERT(frame->StyleDisplay()->mTopLayer != StyleTopLayer::None,
|
||||
"ua.css should ensure this");
|
||||
MOZ_ASSERT(frame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW));
|
||||
BuildDisplayListForTopLayerFrame(aBuilder, frame, aList);
|
||||
BuildDisplayListForTopLayerFrame(aBuilder, frame, &topLayerList);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (topLayerList.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
nsDisplayListBuilder::AutoBuildingDisplayList buildingDisplayList(aBuilder,
|
||||
this);
|
||||
// Wrap the whole top layer in a single item with maximum z-index,
|
||||
// and append it at the very end, so that it stays at the topmost.
|
||||
nsDisplayWrapList* wrapList = MakeDisplayItemWithIndex<nsDisplayWrapList>(
|
||||
aBuilder, this, 2, &topLayerList, aBuilder->CurrentActiveScrolledRoot(),
|
||||
false);
|
||||
if (!wrapList) {
|
||||
return nullptr;
|
||||
}
|
||||
wrapList->SetOverrideZIndex(
|
||||
std::numeric_limits<decltype(wrapList->ZIndex())>::max());
|
||||
return wrapList;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsContainerFrame.h"
|
||||
|
||||
class nsDisplayWrapList;
|
||||
class nsPresContext;
|
||||
|
||||
namespace mozilla {
|
||||
@ -51,9 +52,8 @@ class ViewportFrame : public nsContainerFrame {
|
||||
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists) override;
|
||||
|
||||
void BuildDisplayListForTopLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aList,
|
||||
bool* aIsOpaque = nullptr);
|
||||
nsDisplayWrapList* BuildDisplayListForTopLayer(nsDisplayListBuilder* aBuilder,
|
||||
bool* aIsOpaque = nullptr);
|
||||
|
||||
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
|
||||
virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
|
||||
|
@ -4117,30 +4117,16 @@ void ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
nsDisplayWrapList* ScrollFrameHelper::MaybeCreateTopLayerItems(
|
||||
nsDisplayListBuilder* aBuilder, bool* aIsOpaque) {
|
||||
if (mIsRoot) {
|
||||
if (ViewportFrame* viewportFrame = do_QueryFrame(mOuter->GetParent())) {
|
||||
nsDisplayList topLayerList;
|
||||
viewportFrame->BuildDisplayListForTopLayer(aBuilder, &topLayerList,
|
||||
aIsOpaque);
|
||||
if (!topLayerList.IsEmpty()) {
|
||||
nsDisplayListBuilder::AutoBuildingDisplayList buildingDisplayList(
|
||||
aBuilder, viewportFrame);
|
||||
|
||||
// Wrap the whole top layer in a single item with maximum z-index,
|
||||
// and append it at the very end, so that it stays at the topmost.
|
||||
nsDisplayWrapList* wrapList =
|
||||
MakeDisplayItemWithIndex<nsDisplayWrapList>(
|
||||
aBuilder, viewportFrame, 2, &topLayerList,
|
||||
aBuilder->CurrentActiveScrolledRoot(), false);
|
||||
if (wrapList) {
|
||||
wrapList->SetOverrideZIndex(
|
||||
std::numeric_limits<decltype(wrapList->ZIndex())>::max());
|
||||
return wrapList;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!mIsRoot) {
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
ViewportFrame* viewport = do_QueryFrame(mOuter->GetParent());
|
||||
if (!viewport) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return viewport->BuildDisplayListForTopLayer(aBuilder, aIsOpaque);
|
||||
}
|
||||
|
||||
nsRect ScrollFrameHelper::RestrictToRootDisplayPort(
|
||||
|
9
layout/reftests/bugs/1688004.xhtml
Normal file
9
layout/reftests/bugs/1688004.xhtml
Normal file
@ -0,0 +1,9 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" scrolling="false" class="reftest-wait">
|
||||
<body>
|
||||
<dialog>ABC</dialog>
|
||||
<script><![CDATA[
|
||||
document.querySelector("dialog").showModal();
|
||||
document.documentElement.className = "";
|
||||
]]></script>
|
||||
</body>
|
||||
</html>
|
@ -2111,3 +2111,4 @@ fuzzy(0-2,0-96600) == 1648282-1a.html 1648282-1-ref.html
|
||||
fuzzy(0-2,0-96600) == 1648282-1b.html 1648282-1-ref.html
|
||||
!= 1672137-1.html 1672137-1-notref.html
|
||||
== 1686729-1.html 1686729-1-ref.html
|
||||
!= chrome://reftest/content/bugs/1688004.xhtml about:blank
|
||||
|
Loading…
Reference in New Issue
Block a user