84993c0cc9b40fff644d48987c7bd50677ebc7ad
[WebKit-https.git] / Source / WebCore / rendering / RenderFullScreen.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * 
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  * 
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #if ENABLE(FULLSCREEN_API)
28
29 #include "RenderFullScreen.h"
30
31 #include "RenderBlockFlow.h"
32 #include "RenderLayer.h"
33 #include "RenderLayerCompositor.h"
34 #include "RenderTreeBuilder.h"
35 #include <wtf/IsoMallocInlines.h>
36
37 namespace WebCore {
38
39 WTF_MAKE_ISO_ALLOCATED_IMPL(RenderFullScreen);
40
41 class RenderFullScreenPlaceholder final : public RenderBlockFlow {
42     WTF_MAKE_ISO_ALLOCATED(RenderFullScreenPlaceholder);
43 public:
44     RenderFullScreenPlaceholder(Document& document, RenderStyle&& style)
45         : RenderBlockFlow(document, WTFMove(style))
46     {
47     }
48
49 private:
50     bool isRenderFullScreenPlaceholder() const override { return true; }
51 };
52
53 WTF_MAKE_ISO_ALLOCATED_IMPL(RenderFullScreenPlaceholder);
54
55 RenderFullScreen::RenderFullScreen(Document& document, RenderStyle&& style)
56     : RenderFlexibleBox(document, WTFMove(style))
57 {
58     setReplaced(false); 
59 }
60
61 void RenderFullScreen::willBeDestroyed(RenderTreeBuilder& builder)
62 {
63     if (m_placeholder) {
64         m_placeholder->removeFromParentAndDestroy(builder);
65         ASSERT(!m_placeholder);
66     }
67
68     RenderFlexibleBox::willBeDestroyed(builder);
69 }
70
71 static RenderStyle createFullScreenStyle()
72 {
73     auto fullscreenStyle = RenderStyle::create();
74
75     // Create a stacking context:
76     fullscreenStyle.setZIndex(INT_MAX);
77
78     fullscreenStyle.setFontDescription({ });
79     fullscreenStyle.fontCascade().update(nullptr);
80
81     fullscreenStyle.setDisplay(FLEX);
82     fullscreenStyle.setJustifyContentPosition(ContentPositionCenter);
83     fullscreenStyle.setAlignItemsPosition(ItemPositionCenter);
84     fullscreenStyle.setFlexDirection(FlowColumn);
85     
86     fullscreenStyle.setPosition(FixedPosition);
87     fullscreenStyle.setWidth(Length(100.0, Percent));
88     fullscreenStyle.setHeight(Length(100.0, Percent));
89     fullscreenStyle.setLeft(Length(0, WebCore::Fixed));
90     fullscreenStyle.setTop(Length(0, WebCore::Fixed));
91     
92     fullscreenStyle.setBackgroundColor(Color::black);
93
94     return fullscreenStyle;
95 }
96
97 RenderPtr<RenderFullScreen> RenderFullScreen::wrapNewRenderer(RenderTreeBuilder& builder, RenderPtr<RenderElement> renderer, RenderElement& parent, Document& document)
98 {
99     auto newFullscreenRenderer = createRenderer<RenderFullScreen>(document, createFullScreenStyle());
100     newFullscreenRenderer->initializeStyle();
101
102     auto& fullscreenRenderer = *newFullscreenRenderer;
103     if (!parent.isChildAllowed(fullscreenRenderer, fullscreenRenderer.style()))
104         return nullptr;
105
106     builder.insertChild(fullscreenRenderer, WTFMove(renderer));
107     fullscreenRenderer.setNeedsLayoutAndPrefWidthsRecalc();
108
109     document.setFullScreenRenderer(builder, &fullscreenRenderer);
110
111     return newFullscreenRenderer;
112 }
113
114 void RenderFullScreen::wrapExistingRenderer(RenderElement& renderer, Document& document)
115 {
116     // FIXME: This should be done by RenderTreeUpdater.
117     RenderTreeBuilder builder(*document.renderView());
118
119     auto newFullscreenRenderer = createRenderer<RenderFullScreen>(document, createFullScreenStyle());
120     newFullscreenRenderer->initializeStyle();
121
122     auto& fullscreenRenderer = *newFullscreenRenderer;
123     auto& parent = *renderer.parent();
124     if (!parent.isChildAllowed(fullscreenRenderer, fullscreenRenderer.style()))
125         return;
126
127     RenderBlock* containingBlock = renderer.containingBlock();
128     ASSERT(containingBlock);
129     // Since we are moving the |object| to a new parent |fullscreenRenderer|,
130     // the line box tree underneath our |containingBlock| is not longer valid.
131     containingBlock->deleteLines();
132
133     builder.insertChild(parent, WTFMove(newFullscreenRenderer), &renderer);
134
135     auto toMove = parent.takeChild(builder, renderer);
136
137     // Always just do a full layout to ensure that line boxes get deleted properly.
138     // Because objects moved from |parent| to |fullscreenRenderer|, we want to
139     // make new line boxes instead of leaving the old ones around.
140     parent.setNeedsLayoutAndPrefWidthsRecalc();
141     containingBlock->setNeedsLayoutAndPrefWidthsRecalc();
142
143     builder.insertChild(fullscreenRenderer, WTFMove(toMove));
144     fullscreenRenderer.setNeedsLayoutAndPrefWidthsRecalc();
145
146     document.setFullScreenRenderer(builder, &fullscreenRenderer);
147 }
148
149 void RenderFullScreen::unwrapRenderer(bool& requiresRenderTreeRebuild)
150 {
151     RenderTreeBuilder builder(view());
152
153     requiresRenderTreeRebuild = false;
154     if (parent()) {
155         auto* child = firstChild();
156         // Things can get very complicated with anonymous block generation.
157         // We can restore correctly without rebuild in simple cases only.
158         // FIXME: We should have a mechanism for removing a block without reconstructing the tree.
159         if (child != lastChild())
160             requiresRenderTreeRebuild = true;
161         else if (child && child->isAnonymousBlock()) {
162             auto& anonymousBlock = downcast<RenderBlock>(*child);
163             if (anonymousBlock.firstChild() != anonymousBlock.lastChild())
164                 requiresRenderTreeRebuild = true;
165         }
166
167         while ((child = firstChild())) {
168             if (child->isAnonymousBlock() && !requiresRenderTreeRebuild) {
169                 if (auto* nonAnonymousChild = downcast<RenderBlock>(*child).firstChild())
170                     child = nonAnonymousChild;
171                 else {
172                     child->removeFromParentAndDestroy(builder);
173                     continue;
174                 }
175             }
176             // We have to clear the override size, because as a flexbox, we
177             // may have set one on the child, and we don't want to leave that
178             // lying around on the child.
179             if (is<RenderBox>(*child))
180                 downcast<RenderBox>(*child).clearOverrideSize();
181             auto childToMove = child->parent()->takeChild(builder, *child);
182             builder.insertChild(*parent(), WTFMove(childToMove), this);
183             parent()->setNeedsLayoutAndPrefWidthsRecalc();
184         }
185     }
186     if (placeholder())
187         placeholder()->removeFromParentAndDestroy(builder);
188     ASSERT(!placeholder());
189
190     removeFromParentAndDestroy(builder);
191 }
192
193 void RenderFullScreen::createPlaceholder(std::unique_ptr<RenderStyle> style, const LayoutRect& frameRect)
194 {
195     if (style->width().isAuto())
196         style->setWidth(Length(frameRect.width(), Fixed));
197     if (style->height().isAuto())
198         style->setHeight(Length(frameRect.height(), Fixed));
199
200     if (m_placeholder) {
201         m_placeholder->setStyle(WTFMove(*style));
202         return;
203     }
204
205     if (!parent())
206         return;
207
208     auto newPlaceholder = createRenderer<RenderFullScreenPlaceholder>(document(), WTFMove(*style));
209     newPlaceholder->initializeStyle();
210
211     m_placeholder = makeWeakPtr(*newPlaceholder);
212
213     RenderTreeBuilder::current()->insertChild(*parent(), WTFMove(newPlaceholder), this);
214     parent()->setNeedsLayoutAndPrefWidthsRecalc();
215 }
216
217 }
218
219 #endif