451d5fa32f0c9c96dcd779c693e3601b08173308
[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 <wtf/IsoMallocInlines.h>
35
36 namespace WebCore {
37
38 WTF_MAKE_ISO_ALLOCATED_IMPL(RenderFullScreen);
39
40 class RenderFullScreenPlaceholder final : public RenderBlockFlow {
41     WTF_MAKE_ISO_ALLOCATED(RenderFullScreenPlaceholder);
42 public:
43     RenderFullScreenPlaceholder(Document& document, RenderStyle&& style)
44         : RenderBlockFlow(document, WTFMove(style))
45     {
46     }
47
48 private:
49     bool isRenderFullScreenPlaceholder() const override { return true; }
50 };
51
52 WTF_MAKE_ISO_ALLOCATED_IMPL(RenderFullScreenPlaceholder);
53
54 RenderFullScreen::RenderFullScreen(Document& document, RenderStyle&& style)
55     : RenderFlexibleBox(document, WTFMove(style))
56 {
57     setReplaced(false); 
58 }
59
60 void RenderFullScreen::willBeDestroyed()
61 {
62     if (m_placeholder) {
63         m_placeholder->removeFromParentAndDestroy();
64         ASSERT(!m_placeholder);
65     }
66
67     RenderFlexibleBox::willBeDestroyed();
68 }
69
70 static RenderStyle createFullScreenStyle()
71 {
72     auto fullscreenStyle = RenderStyle::create();
73
74     // Create a stacking context:
75     fullscreenStyle.setZIndex(INT_MAX);
76
77     fullscreenStyle.setFontDescription({ });
78     fullscreenStyle.fontCascade().update(nullptr);
79
80     fullscreenStyle.setDisplay(FLEX);
81     fullscreenStyle.setJustifyContentPosition(ContentPositionCenter);
82     fullscreenStyle.setAlignItemsPosition(ItemPositionCenter);
83     fullscreenStyle.setFlexDirection(FlowColumn);
84     
85     fullscreenStyle.setPosition(FixedPosition);
86     fullscreenStyle.setWidth(Length(100.0, Percent));
87     fullscreenStyle.setHeight(Length(100.0, Percent));
88     fullscreenStyle.setLeft(Length(0, WebCore::Fixed));
89     fullscreenStyle.setTop(Length(0, WebCore::Fixed));
90     
91     fullscreenStyle.setBackgroundColor(Color::black);
92
93     return fullscreenStyle;
94 }
95
96 RenderPtr<RenderFullScreen> RenderFullScreen::wrapNewRenderer(RenderPtr<RenderElement> renderer, RenderElement& parent, Document& document)
97 {
98     auto newFullscreenRenderer = createRenderer<RenderFullScreen>(document, createFullScreenStyle());
99     newFullscreenRenderer->initializeStyle();
100
101     auto& fullscreenRenderer = *newFullscreenRenderer;
102     if (!parent.isChildAllowed(fullscreenRenderer, fullscreenRenderer.style()))
103         return nullptr;
104
105     fullscreenRenderer.addChild(WTFMove(renderer));
106     fullscreenRenderer.setNeedsLayoutAndPrefWidthsRecalc();
107
108     document.setFullScreenRenderer(&fullscreenRenderer);
109
110     return newFullscreenRenderer;
111 }
112
113 void RenderFullScreen::wrapExistingRenderer(RenderElement& renderer, Document& document)
114 {
115     auto newFullscreenRenderer = createRenderer<RenderFullScreen>(document, createFullScreenStyle());
116     newFullscreenRenderer->initializeStyle();
117
118     auto& fullscreenRenderer = *newFullscreenRenderer;
119     auto& parent = *renderer.parent();
120     if (!parent.isChildAllowed(fullscreenRenderer, fullscreenRenderer.style()))
121         return;
122
123     RenderBlock* containingBlock = renderer.containingBlock();
124     ASSERT(containingBlock);
125     // Since we are moving the |object| to a new parent |fullscreenRenderer|,
126     // the line box tree underneath our |containingBlock| is not longer valid.
127     containingBlock->deleteLines();
128
129     parent.addChild(WTFMove(newFullscreenRenderer), &renderer);
130
131     auto toMove = parent.takeChild(renderer);
132
133     // Always just do a full layout to ensure that line boxes get deleted properly.
134     // Because objects moved from |parent| to |fullscreenRenderer|, we want to
135     // make new line boxes instead of leaving the old ones around.
136     parent.setNeedsLayoutAndPrefWidthsRecalc();
137     containingBlock->setNeedsLayoutAndPrefWidthsRecalc();
138
139     fullscreenRenderer.addChild(WTFMove(toMove));
140     fullscreenRenderer.setNeedsLayoutAndPrefWidthsRecalc();
141
142     document.setFullScreenRenderer(&fullscreenRenderer);
143 }
144
145 void RenderFullScreen::unwrapRenderer(bool& requiresRenderTreeRebuild)
146 {
147     requiresRenderTreeRebuild = false;
148     if (parent()) {
149         auto* child = firstChild();
150         // Things can get very complicated with anonymous block generation.
151         // We can restore correctly without rebuild in simple cases only.
152         // FIXME: We should have a mechanism for removing a block without reconstructing the tree.
153         if (child != lastChild())
154             requiresRenderTreeRebuild = true;
155         else if (child && child->isAnonymousBlock()) {
156             auto& anonymousBlock = downcast<RenderBlock>(*child);
157             if (anonymousBlock.firstChild() != anonymousBlock.lastChild())
158                 requiresRenderTreeRebuild = true;
159         }
160
161         while ((child = firstChild())) {
162             if (child->isAnonymousBlock() && !requiresRenderTreeRebuild) {
163                 if (auto* nonAnonymousChild = downcast<RenderBlock>(*child).firstChild())
164                     child = nonAnonymousChild;
165                 else {
166                     child->removeFromParentAndDestroy();
167                     continue;
168                 }
169             }
170             // We have to clear the override size, because as a flexbox, we
171             // may have set one on the child, and we don't want to leave that
172             // lying around on the child.
173             if (is<RenderBox>(*child))
174                 downcast<RenderBox>(*child).clearOverrideSize();
175             auto childToMove = child->parent()->takeChild(*child);
176             parent()->addChild(WTFMove(childToMove), this);
177             parent()->setNeedsLayoutAndPrefWidthsRecalc();
178         }
179     }
180     if (placeholder())
181         placeholder()->removeFromParentAndDestroy();
182     ASSERT(!placeholder());
183
184     removeFromParentAndDestroy();
185 }
186
187 void RenderFullScreen::createPlaceholder(std::unique_ptr<RenderStyle> style, const LayoutRect& frameRect)
188 {
189     if (style->width().isAuto())
190         style->setWidth(Length(frameRect.width(), Fixed));
191     if (style->height().isAuto())
192         style->setHeight(Length(frameRect.height(), Fixed));
193
194     if (m_placeholder) {
195         m_placeholder->setStyle(WTFMove(*style));
196         return;
197     }
198
199     if (!parent())
200         return;
201
202     auto newPlaceholder = createRenderer<RenderFullScreenPlaceholder>(document(), WTFMove(*style));
203     newPlaceholder->initializeStyle();
204
205     m_placeholder = makeWeakPtr(*newPlaceholder);
206
207     parent()->addChild(WTFMove(newPlaceholder), this);
208     parent()->setNeedsLayoutAndPrefWidthsRecalc();
209 }
210
211 }
212
213 #endif