Index: Source/core/html/HTMLDialogElement.cpp |
diff --git a/Source/core/html/HTMLDialogElement.cpp b/Source/core/html/HTMLDialogElement.cpp |
index 3f32fa3cd223537a4fc0b09ea5a6d3bf26b88f55..1fec67c24f106812aff4d35dabc69f58a73c9e2a 100644 |
--- a/Source/core/html/HTMLDialogElement.cpp |
+++ b/Source/core/html/HTMLDialogElement.cpp |
@@ -28,7 +28,10 @@ |
#include "HTMLDialogElement.h" |
#include "ExceptionCode.h" |
-#include "RenderDialog.h" |
+#include "FrameView.h" |
+#include "RenderBlock.h" |
+#include "RenderStyle.h" |
+#include "StyleResolver.h" |
namespace WebCore { |
@@ -36,8 +39,11 @@ using namespace HTMLNames; |
HTMLDialogElement::HTMLDialogElement(const QualifiedName& tagName, Document* document) |
: HTMLElement(tagName, document) |
+ , m_topIsValid(false) |
+ , m_top(0) |
{ |
ASSERT(hasTagName(dialogTag)); |
+ setHasCustomStyleCallbacks(); |
ScriptWrappable::init(this); |
} |
@@ -54,6 +60,50 @@ void HTMLDialogElement::close(ExceptionCode& ec) |
} |
setBooleanAttribute(openAttr, false); |
document()->removeFromTopLayer(this); |
+ m_topIsValid = false; |
+} |
+ |
+static bool needsCenteredPositioning(const RenderStyle* style) |
+{ |
+ return style->position() == AbsolutePosition && style->hasAutoTopAndBottom(); |
+} |
+ |
+PassRefPtr<RenderStyle> HTMLDialogElement::customStyleForRenderer() |
+{ |
+ RefPtr<RenderStyle> originalStyle = document()->styleResolver()->styleForElement(this); |
+ RefPtr<RenderStyle> style = RenderStyle::clone(originalStyle.get()); |
+ |
+ // Override top to remain centered after style recalcs. |
+ if (needsCenteredPositioning(style.get()) && m_topIsValid) |
+ style->setTop(Length(m_top.toInt(), WebCore::Fixed)); |
+ |
+ return style.release(); |
+} |
+ |
+void HTMLDialogElement::positionAndReattach() |
+{ |
+ // Layout because we need to know our ancestors' positions and our own height. |
+ document()->updateLayoutIgnorePendingStylesheets(); |
+ |
+ RenderBox* box = renderBox(); |
+ if (!box || !needsCenteredPositioning(box->style())) |
+ return; |
+ |
+ // Set up dialog's position to be safe-centered in the viewport. |
+ // FIXME: Figure out what to do in vertical writing mode. |
+ FrameView* frameView = document()->view(); |
+ int scrollTop = frameView->scrollOffset().height(); |
+ FloatPoint absolutePoint(0, scrollTop); |
+ int visibleHeight = frameView->visibleContentRect(ScrollableArea::IncludeScrollbars).height(); |
+ if (box->height() < visibleHeight) |
+ absolutePoint.move(0, (visibleHeight - box->height()) / 2); |
+ FloatPoint localPoint = box->containingBlock()->absoluteToLocal(absolutePoint); |
+ |
+ m_top = localPoint.y(); |
+ m_topIsValid = true; |
+ |
+ // FIXME: It's inefficient to reattach here. We could do better by mutating style directly and forcing another layout. |
+ reattach(); |
} |
void HTMLDialogElement::show() |
@@ -61,6 +111,7 @@ void HTMLDialogElement::show() |
if (fastHasAttribute(openAttr)) |
return; |
setBooleanAttribute(openAttr, true); |
+ positionAndReattach(); |
} |
void HTMLDialogElement::showModal(ExceptionCode& ec) |
@@ -69,8 +120,9 @@ void HTMLDialogElement::showModal(ExceptionCode& ec) |
ec = INVALID_STATE_ERR; |
return; |
} |
- setBooleanAttribute(openAttr, true); |
document()->addToTopLayer(this); |
+ setBooleanAttribute(openAttr, true); |
+ positionAndReattach(); |
} |
bool HTMLDialogElement::isPresentationAttribute(const QualifiedName& name) const |
@@ -83,11 +135,6 @@ bool HTMLDialogElement::isPresentationAttribute(const QualifiedName& name) const |
return HTMLElement::isPresentationAttribute(name); |
} |
-RenderObject* HTMLDialogElement::createRenderer(RenderArena* arena, RenderStyle*) |
-{ |
- return new (arena) RenderDialog(this); |
-} |
- |
} |
#endif |