Diff
Modified: trunk/LayoutTests/ChangeLog (88033 => 88034)
--- trunk/LayoutTests/ChangeLog 2011-06-03 18:43:15 UTC (rev 88033)
+++ trunk/LayoutTests/ChangeLog 2011-06-03 18:48:15 UTC (rev 88034)
@@ -1,3 +1,14 @@
+2011-06-01 Jer Noble <[email protected]>
+
+ Reviewed by Simon Fraser.
+
+ Flash of broken page when exiting full screen at jerryseinfeld.com
+ https://bugs.webkit.org/show_bug.cgi?id=61897
+ <rdar://problem/9522985>
+
+ * fullscreen/full-screen-placeholder-expected.txt: Added.
+ * fullscreen/full-screen-placeholder.html: Added.
+
2011-06-03 Robert Kroeger <[email protected]>
Reviewed by Adam Barth.
Added: trunk/LayoutTests/fullscreen/full-screen-placeholder-expected.txt (0 => 88034)
--- trunk/LayoutTests/fullscreen/full-screen-placeholder-expected.txt (rev 0)
+++ trunk/LayoutTests/fullscreen/full-screen-placeholder-expected.txt 2011-06-03 18:48:15 UTC (rev 88034)
@@ -0,0 +1,17 @@
+This layout test checks that the offset positions of the blue and green divs does not change when the red div enters full-screen mode. Press go full-screen to begin.
+One
+Two
+EVENT(webkitfullscreenchange)
+EXPECTED (document.webkitCurrentFullScreenElement == '[object HTMLDivElement]') OK
+EXPECTED (one.offsetLeft == '68') OK
+EXPECTED (one.offsetTop == '48') OK
+EXPECTED (two.offsetLeft == '8') OK
+EXPECTED (two.offsetTop == '108') OK
+EVENT(webkitfullscreenchange)
+EXPECTED (document.webkitCurrentFullScreenElement == 'null') OK
+EXPECTED (one.offsetLeft == '68') OK
+EXPECTED (one.offsetTop == '48') OK
+EXPECTED (two.offsetLeft == '8') OK
+EXPECTED (two.offsetTop == '108') OK
+END OF TEST
+
Added: trunk/LayoutTests/fullscreen/full-screen-placeholder.html (0 => 88034)
--- trunk/LayoutTests/fullscreen/full-screen-placeholder.html (rev 0)
+++ trunk/LayoutTests/fullscreen/full-screen-placeholder.html 2011-06-03 18:48:15 UTC (rev 88034)
@@ -0,0 +1,73 @@
+<script src=""
+<style>
+#float {
+ margin: 10px 0 0 10px;
+ height: 50px;
+ width: 50px;
+ float: left;
+ background-color: red;
+}
+#clear {
+ clear:left;
+}
+#one {
+ background-color: lightblue;
+ float: left;
+}
+#two {
+ background-color: lightgreen;
+}
+</style>
+<body>
+<div>This layout test checks that the offset positions of the blue and green divs does not change when the red div enters full-screen mode. Press <button _onclick_="document.getElementById('float').webkitRequestFullScreen()">go full-screen</a> to begin.</div>
+<div id="float"></div>
+<div id="one">One</div>
+<div id="clear" />
+<span id="two">Two</span>
+<script>
+ var _one_ = document.getElementById('one');
+ var two = document.getElementById('two');
+
+ // Bail out early if the full screen API is not enabled or is missing:
+ if (Element.prototype.webkitRequestFullScreen == undefined) {
+ logResult(false, "Element.prototype.webkitRequestFullScreen == undefined");
+ endTest();
+ } else {
+ var _oneState_ = {'offsetLeft': one.offsetLeft, 'offsetTop': one.offsetTop };
+ var twoState = {'offsetLeft': two.offsetLeft, 'offsetTop': two.offsetTop };
+
+
+ var callback;
+ var fullscreenChanged = function(event)
+ {
+ if (callback)
+ callback(event)
+ };
+ waitForEvent(document, 'webkitfullscreenchange', fullscreenChanged);
+
+ var div = document.getElementById('float');
+
+ var divEnteredFullScreen = function() {
+ testExpected("document.webkitCurrentFullScreenElement", div);
+ testExpected("one.offsetLeft", oneState.offsetLeft);
+ testExpected("one.offsetTop", oneState.offsetTop);
+ testExpected("two.offsetLeft", twoState.offsetLeft);
+ testExpected("two.offsetTop", twoState.offsetTop);
+ callback = cancelledFullScreen;
+ runWithKeyDown(function(){document.webkitCancelFullScreen()});
+ };
+
+ var cancelledFullScreen = function() {
+ testExpected("document.webkitCurrentFullScreenElement", null);
+ testExpected("one.offsetLeft", oneState.offsetLeft);
+ testExpected("one.offsetTop", oneState.offsetTop);
+ testExpected("two.offsetLeft", twoState.offsetLeft);
+ testExpected("two.offsetTop", twoState.offsetTop);
+ callback = null;
+ endTest();
+ };
+
+ callback = divEnteredFullScreen;
+ runWithKeyDown(function(){div.webkitRequestFullScreen()});
+ }
+</script>
Modified: trunk/Source/WebCore/ChangeLog (88033 => 88034)
--- trunk/Source/WebCore/ChangeLog 2011-06-03 18:43:15 UTC (rev 88033)
+++ trunk/Source/WebCore/ChangeLog 2011-06-03 18:48:15 UTC (rev 88034)
@@ -1,3 +1,33 @@
+2011-06-01 Jer Noble <[email protected]>
+
+ Reviewed by Simon Fraser.
+
+ Flash of broken page when exiting full screen at jerryseinfeld.com
+ https://bugs.webkit.org/show_bug.cgi?id=61897
+ <rdar://problem/9522985>
+
+ Test: fullscreen/full-screen-placeholder.html
+
+ Entering full-screen mode is causing the page layout to change because the full-screen
+ element is taken out of the normal flow. To counteract this effect, insert a placeholder
+ block as a parent of the full-screen renderer with the same size and style as the full-screen
+ element pre-full-screen.
+
+ Only create a placeholder for block-level elements; the technique required for inline elements
+ would be vastly more complicated.
+
+ * dom/Document.cpp:
+ (WebCore::Document::webkitWillEnterFullScreenForElement): Create a placeholder
+ based on the size and style of the full-screen element.
+ (WebCore::Document::setFullScreenRenderer): Persist the placeholder size and
+ style across new renderers.
+ * rendering/RenderFullScreen.cpp:
+ (RenderFullScreen::RenderFullScreen): Added ivar.
+ (RenderFullScreen::destroy): Make sure to safely destroy our placeholder.
+ (RenderFullScreen::createPlaceholder): Added.
+ * rendering/RenderFullScreen.h:
+ (WebCore::RenderFullScreen::placeholder): Ivar accessor.
+
2011-06-03 Levi Weintraub <[email protected]>
Reviewed by Eric Seidel.
Modified: trunk/Source/WebCore/dom/Document.cpp (88033 => 88034)
--- trunk/Source/WebCore/dom/Document.cpp 2011-06-03 18:43:15 UTC (rev 88033)
+++ trunk/Source/WebCore/dom/Document.cpp 2011-06-03 18:48:15 UTC (rev 88034)
@@ -4784,7 +4784,18 @@
ASSERT(page() && page()->settings()->fullScreenEnabled());
m_fullScreenElement = element;
-
+
+ // Create a placeholder block for a the full-screen element, to keep the page from reflowing
+ // when the element is removed from the normal flow. Only do this for a RenderBox, as only
+ // a box will have a frameRect. The placeholder will be created in setFullScreenRenderer()
+ // during layout.
+ RenderObject* renderer = m_fullScreenElement->renderer();
+ bool shouldCreatePlaceholder = m_fullScreenElement->renderer()->isBox();
+ if (shouldCreatePlaceholder) {
+ m_savedPlaceholderFrameRect = toRenderBox(renderer)->frameRect();
+ m_savedPlaceholderRenderStyle = RenderStyle::clone(renderer->style());
+ }
+
if (m_fullScreenElement != documentElement())
m_fullScreenElement->detach();
@@ -4861,6 +4872,13 @@
if (renderer == m_fullScreenRenderer)
return;
+ if (renderer && m_savedPlaceholderRenderStyle)
+ renderer->createPlaceholder(m_savedPlaceholderRenderStyle.release(), m_savedPlaceholderFrameRect);
+ else if (renderer && m_fullScreenRenderer && m_fullScreenRenderer->placeholder()) {
+ RenderBlock* placeholder = m_fullScreenRenderer->placeholder();
+ renderer->createPlaceholder(RenderStyle::clone(placeholder->style()), placeholder->frameRect());
+ }
+
if (m_fullScreenRenderer)
m_fullScreenRenderer->destroy();
ASSERT(!m_fullScreenRenderer);
Modified: trunk/Source/WebCore/dom/Document.h (88033 => 88034)
--- trunk/Source/WebCore/dom/Document.h 2011-06-03 18:43:15 UTC (rev 88033)
+++ trunk/Source/WebCore/dom/Document.h 2011-06-03 18:48:15 UTC (rev 88034)
@@ -34,6 +34,7 @@
#include "DOMTimeStamp.h"
#include "DocumentTiming.h"
#include "IconURL.h"
+#include "IntRect.h"
#include "PageVisibilityState.h"
#include "QualifiedName.h"
#include "ScriptExecutionContext.h"
@@ -1371,6 +1372,8 @@
Timer<Document> m_fullScreenChangeDelayTimer;
Deque<RefPtr<Element> > m_fullScreenChangeEventTargetQueue;
bool m_isAnimatingFullScreen;
+ IntRect m_savedPlaceholderFrameRect;
+ RefPtr<RenderStyle> m_savedPlaceholderRenderStyle;
#endif
int m_loadEventDelayCount;
Modified: trunk/Source/WebCore/dom/NodeRenderingContext.cpp (88033 => 88034)
--- trunk/Source/WebCore/dom/NodeRenderingContext.cpp 2011-06-03 18:43:15 UTC (rev 88033)
+++ trunk/Source/WebCore/dom/NodeRenderingContext.cpp 2011-06-03 18:48:15 UTC (rev 88034)
@@ -228,7 +228,7 @@
}
#if ENABLE(FULLSCREEN_API)
-static RenderFullScreen* wrapWithRenderFullScreen(RenderObject* object, Document* document)
+static RenderObject* wrapWithRenderFullScreen(RenderObject* object, Document* document)
{
RenderFullScreen* fullscreenRenderer = new (document->renderArena()) RenderFullScreen(document);
fullscreenRenderer->setStyle(RenderFullScreen::createFullScreenStyle());
@@ -237,6 +237,8 @@
if (object)
fullscreenRenderer->addChild(object);
document->setFullScreenRenderer(fullscreenRenderer);
+ if (fullscreenRenderer->placeholder())
+ return fullscreenRenderer->placeholder();
return fullscreenRenderer;
}
#endif
Modified: trunk/Source/WebCore/rendering/RenderFullScreen.cpp (88033 => 88034)
--- trunk/Source/WebCore/rendering/RenderFullScreen.cpp 2011-06-03 18:43:15 UTC (rev 88033)
+++ trunk/Source/WebCore/rendering/RenderFullScreen.cpp 2011-06-03 18:48:15 UTC (rev 88034)
@@ -36,8 +36,22 @@
using namespace WebCore;
+RenderFullScreen::RenderFullScreen(Node* node)
+ : RenderFlexibleBox(node)
+ , m_placeholder(0)
+{
+ setReplaced(false);
+}
+
void RenderFullScreen::destroy()
{
+ if (m_placeholder) {
+ remove();
+ if (!m_placeholder->beingDestroyed())
+ m_placeholder->destroy();
+ m_placeholder = 0;
+ }
+
// RenderObjects are unretained, so notify the document (which holds a pointer to a RenderFullScreen)
// if it's RenderFullScreen is destroyed.
if (document() && document()->fullScreenRenderer() == this)
@@ -72,4 +86,24 @@
return fullscreenStyle.release();
}
+void RenderFullScreen::createPlaceholder(PassRefPtr<RenderStyle> style, const IntRect& frameRect)
+{
+ if (style->width().isAuto())
+ style->setWidth(Length(frameRect.width(), Fixed));
+ if (style->height().isAuto())
+ style->setHeight(Length(frameRect.height(), Fixed));
+
+ if (!m_placeholder) {
+ m_placeholder = new (document()->renderArena()) RenderBlock(document());
+ m_placeholder->setStyle(style);
+ m_placeholder->setIsAnonymous(false);
+ if (parent()) {
+ parent()->addChild(m_placeholder, this);
+ remove();
+ }
+ m_placeholder->addChild(this);
+ } else
+ m_placeholder->setStyle(style);
+}
+
#endif
Modified: trunk/Source/WebCore/rendering/RenderFullScreen.h (88033 => 88034)
--- trunk/Source/WebCore/rendering/RenderFullScreen.h 2011-06-03 18:43:15 UTC (rev 88033)
+++ trunk/Source/WebCore/rendering/RenderFullScreen.h 2011-06-03 18:48:15 UTC (rev 88034)
@@ -33,15 +33,18 @@
class RenderFullScreen : public RenderFlexibleBox {
public:
- RenderFullScreen(Node* node) : RenderFlexibleBox(node) { setReplaced(false); }
+ RenderFullScreen(Node*);
virtual void destroy();
virtual bool isRenderFullScreen() const { return true; }
virtual const char* renderName() const { return "RenderFullScreen"; }
-
+
+ RenderBlock* placeholder() { return m_placeholder; }
+ void createPlaceholder(PassRefPtr<RenderStyle>, const IntRect& frameRect);
+
static PassRefPtr<RenderStyle> createFullScreenStyle();
protected:
- bool m_isAnimating;
+ RenderBlock* m_placeholder;
};
inline RenderFullScreen* toRenderFullScreen(RenderObject* object)