Bug 1126230 part 8 - Implement painting part for the top layer. r=roc

--HG--
extra : source : 4a61841b92db5baf999a9aee02a9aba4799e3d1b
This commit is contained in:
Xidorn Quan 2015-10-07 14:04:32 +11:00
Родитель c2d718f5cb
Коммит 7773a3e41c
4 изменённых файлов: 102 добавлений и 9 удалений

Просмотреть файл

@ -2314,9 +2314,12 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
// dirty rect in child-relative coordinates
nsRect dirty = aDirtyRect - child->GetOffsetTo(this);
const nsStyleDisplay* disp;
nsIAtom* childType = child->GetType();
nsDisplayListBuilder::OutOfFlowDisplayData* savedOutOfFlowData = nullptr;
if (childType == nsGkAtoms::placeholderFrame) {
if (childType != nsGkAtoms::placeholderFrame) {
disp = child->StyleDisplay();
} else {
nsPlaceholderFrame* placeholder = static_cast<nsPlaceholderFrame*>(child);
child = placeholder->GetOutOfFlowFrame();
NS_ASSERTION(child, "No out of flow frame?");
@ -2326,6 +2329,16 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
if (!child || nsLayoutUtils::IsPopup(child) ||
(child->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT))
return;
MOZ_ASSERT(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW);
disp = child->StyleDisplay();
// If the out-of-flow frame is in the top layer, the viewport frame
// will paint it. Skip it here. Note that, only out-of-flow frames
// with this property should be skipped, because non-HTML elements
// may stop their children from being out-of-flow. Those frames
// should still be handled in the normal in-flow path.
if (disp->mTopLayer != NS_STYLE_TOP_LAYER_NONE) {
return;
}
// Make sure that any attempt to use childType below is disappointed. We
// could call GetType again but since we don't currently need it, let's
// avoid the virtual call.
@ -2403,7 +2416,6 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
// Child is composited if it's transformed, partially transparent, or has
// SVG effects or a blend mode..
const nsStyleDisplay* disp = child->StyleDisplay();
const nsStylePosition* pos = child->StylePosition();
bool isVisuallyAtomic = child->HasOpacity()
|| child->IsTransformed()

Просмотреть файл

@ -14,6 +14,7 @@
#include "nsSubDocumentFrame.h"
#include "nsAbsoluteContainingBlock.h"
#include "GeckoProfiler.h"
#include "nsIMozBrowserFrame.h"
using namespace mozilla;
@ -51,14 +52,89 @@ ViewportFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
PROFILER_LABEL("ViewportFrame", "BuildDisplayList",
js::ProfileEntry::Category::GRAPHICS);
nsIFrame* kid = mFrames.FirstChild();
if (!kid)
return;
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, aDirtyRect, aLists);
}
// 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, aDirtyRect, aLists);
nsDisplayList topLayerList;
BuildDisplayListForTopLayer(aBuilder, &topLayerList);
if (!topLayerList.IsEmpty()) {
// 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 =
new (aBuilder) nsDisplayWrapList(aBuilder, this, &topLayerList);
wrapList->SetOverrideZIndex(
std::numeric_limits<decltype(wrapList->ZIndex())>::max());
aLists.PositionedDescendants()->AppendNewToTop(wrapList);
}
}
#ifdef DEBUG
/**
* Returns whether we are going to put an element in the top layer for
* fullscreen. This function should matches the CSS rule in ua.css.
*/
static bool
ShouldInTopLayerForFullscreen(Element* aElement)
{
if (!aElement->GetParent()) {
return false;
}
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(aElement);
if (browserFrame && browserFrame->GetReallyIsBrowserOrApp()) {
return false;
}
return true;
}
#endif // DEBUG
void
ViewportFrame::BuildDisplayListForTopLayer(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList)
{
nsIDocument* doc = PresContext()->Document();
nsTArray<Element*> fullscreenStack = doc->GetFullscreenStack();
for (Element* elem : fullscreenStack) {
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 == NS_STYLE_TOP_LAYER_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->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
MOZ_ASSERT(!elem->GetParent()->IsHTMLElement(), "HTML element "
"should always be out-of-flow if in the top layer");
continue;
}
MOZ_ASSERT(frame->GetParent() == this);
nsRect dirty;
nsDisplayListBuilder::OutOfFlowDisplayData*
savedOutOfFlowData = nsDisplayListBuilder::GetOutOfFlowData(frame);
if (savedOutOfFlowData) {
dirty = savedOutOfFlowData->mDirtyRect;
}
nsDisplayList list;
frame->BuildDisplayListForStackingContext(aBuilder, dirty, &list);
aList->AppendToTop(&list);
}
}
}
#ifdef DEBUG

Просмотреть файл

@ -63,6 +63,9 @@ public:
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
void BuildDisplayListForTopLayer(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList);
virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
virtual void Reflow(nsPresContext* aPresContext,

Просмотреть файл

@ -280,6 +280,8 @@
box-sizing: border-box !important;
}
/* Selectors here should match the check in
* nsViewportFrame.cpp:ShouldInTopLayerForFullscreen() */
*|*:-moz-full-screen:not(:root):not(:-moz-browser-frame) {
-moz-top-layer: top !important;
}