Changeset 135242 in webkit


Ignore:
Timestamp:
Nov 19, 2012 8:45:02 PM (11 years ago)
Author:
commit-queue@webkit.org
Message:

Implement the new stacking layer needed by the Fullscreen API and the new <dialog> element
https://bugs.webkit.org/show_bug.cgi?id=84796

Patch by Matt Falkenhagen <falken@chromium.org> on 2012-11-19
Reviewed by Julien Chaffraix.

Source/WebCore:

This adds the top layer element stack to Document. The Fullscreen
specification mandates that we track the ordering of the DOM nodes in
the top layer, not the renderers. That makes it hard to implement on
the rendering side only.

Elements in the top layer get a layer. Layers in the top layer are
added to the root layer's child list after normal layers and in the
order of the top layer stack. This way, the top layer appears above
all other stacking contexts and in the desired order.

In addition, top layer renderers are added as children of RenderView
in top layer order. This is to satisfy requirements such as the
containing block of an element in the top layer is the initial
containing block. It also allows RenderLayer to know the proper
stacking order of the layers without going directly from the top layer
elements to their layers.

So far, only modal dialog elements can be added to the top layer.
The plan is to make the Fullscreen API also use the top layer.

Tests: fast/dom/HTMLDialogElement/top-layer-containing-block.html

fast/dom/HTMLDialogElement/top-layer-display-none.html
fast/dom/HTMLDialogElement/top-layer-nesting.html
fast/dom/HTMLDialogElement/top-layer-stacking-dynamic.html
fast/dom/HTMLDialogElement/top-layer-stacking.html

  • WebCore.exp.in:
  • css/StyleResolver.cpp:

(WebCore::StyleResolver::adjustRenderStyle): Elements in the top layer have a stacking context.

  • dom/Document.cpp:

(WebCore):
(WebCore::Document::addToTopLayer):
(WebCore::Document::removeFromTopLayer):

  • dom/Document.h:

(Document):
(WebCore::Document::topLayerElements): Add the top layer element stack to Document.

  • dom/Element.cpp:

(WebCore::Element::removedFrom):
(WebCore):
(WebCore::Element::isInTopLayer):
(WebCore::Element::setIsInTopLayer):

  • dom/Element.h:
  • dom/ElementRareData.h:

(ElementRareData):

  • dom/Node.cpp:

(WebCore::Node::detach): Add an exception to the assert since top layer elements and their descendants are moved from their
regular position in the render tree.

  • dom/NodeRareData.h:

(WebCore::NodeRareData::NodeRareData):
(NodeRareData):
(WebCore::NodeRareData::isInTopLayer):
(WebCore::NodeRareData::setIsInTopLayer):

  • dom/NodeRenderingContext.cpp:

(WebCore):
(WebCore::adjustInsertionPointForTopLayerElement):
(WebCore::NodeRendererFactory::createRendererIfNeeded): Add renderers for top layer elements as children of RenderView, and
in top layer stacking order.

  • html/HTMLDialogElement.cpp:

(WebCore::HTMLDialogElement::close):
(WebCore::HTMLDialogElement::showModal):

  • rendering/RenderLayer.cpp:

(WebCore):
(WebCore::RenderLayer::isInTopLayer):
(WebCore::RenderLayer::isInTopLayerSubtree):
(WebCore::RenderLayer::rebuildZOrderLists): Add the top layer stack after normal layer collection.
(WebCore::RenderLayer::collectLayers): Avoid adding layers for top layer elements during normal layer collection.

  • rendering/RenderLayer.h:

(RenderLayer):

LayoutTests:

Add tests for top layer stacking and rendering.

  • fast/dom/HTMLDialogElement/top-layer-containing-block-expected.html: Added.
  • fast/dom/HTMLDialogElement/top-layer-containing-block.html: Added.
  • fast/dom/HTMLDialogElement/top-layer-display-none-expected.html: Added.
  • fast/dom/HTMLDialogElement/top-layer-display-none.html: Added.
  • fast/dom/HTMLDialogElement/top-layer-nesting-expected.html: Added.
  • fast/dom/HTMLDialogElement/top-layer-nesting.html: Added.
  • fast/dom/HTMLDialogElement/top-layer-stacking-dynamic-expected.html: Added.
  • fast/dom/HTMLDialogElement/top-layer-stacking-dynamic.html: Added.
  • fast/dom/HTMLDialogElement/top-layer-stacking-expected.html: Added.
  • fast/dom/HTMLDialogElement/top-layer-stacking.html: Added.
Location:
trunk
Files:
10 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r135241 r135242  
     12012-11-19  Matt Falkenhagen  <falken@chromium.org>
     2
     3        Implement the new stacking layer needed by the Fullscreen API and the new <dialog> element
     4        https://bugs.webkit.org/show_bug.cgi?id=84796
     5
     6        Reviewed by Julien Chaffraix.
     7
     8        Add tests for top layer stacking and rendering.
     9
     10        * fast/dom/HTMLDialogElement/top-layer-containing-block-expected.html: Added.
     11        * fast/dom/HTMLDialogElement/top-layer-containing-block.html: Added.
     12        * fast/dom/HTMLDialogElement/top-layer-display-none-expected.html: Added.
     13        * fast/dom/HTMLDialogElement/top-layer-display-none.html: Added.
     14        * fast/dom/HTMLDialogElement/top-layer-nesting-expected.html: Added.
     15        * fast/dom/HTMLDialogElement/top-layer-nesting.html: Added.
     16        * fast/dom/HTMLDialogElement/top-layer-stacking-dynamic-expected.html: Added.
     17        * fast/dom/HTMLDialogElement/top-layer-stacking-dynamic.html: Added.
     18        * fast/dom/HTMLDialogElement/top-layer-stacking-expected.html: Added.
     19        * fast/dom/HTMLDialogElement/top-layer-stacking.html: Added.
     20
    1212012-11-19  Yury Semikhatsky  <yurys@chromium.org>
    222
  • trunk/Source/WebCore/ChangeLog

    r135240 r135242  
     12012-11-19  Matt Falkenhagen  <falken@chromium.org>
     2
     3        Implement the new stacking layer needed by the Fullscreen API and the new <dialog> element
     4        https://bugs.webkit.org/show_bug.cgi?id=84796
     5
     6        Reviewed by Julien Chaffraix.
     7
     8        This adds the top layer element stack to Document. The Fullscreen
     9        specification mandates that we track the ordering of the DOM nodes in
     10        the top layer, not the renderers. That makes it hard to implement on
     11        the rendering side only.
     12
     13        Elements in the top layer get a layer. Layers in the top layer are
     14        added to the root layer's child list after normal layers and in the
     15        order of the top layer stack. This way, the top layer appears above
     16        all other stacking contexts and in the desired order.
     17
     18        In addition, top layer renderers are added as children of RenderView
     19        in top layer order. This is to satisfy requirements such as the
     20        containing block of an element in the top layer is the initial
     21        containing block. It also allows RenderLayer to know the proper
     22        stacking order of the layers without going directly from the top layer
     23        elements to their layers.
     24
     25        So far, only modal dialog elements can be added to the top layer.
     26        The plan is to make the Fullscreen API also use the top layer.
     27
     28        Tests: fast/dom/HTMLDialogElement/top-layer-containing-block.html
     29               fast/dom/HTMLDialogElement/top-layer-display-none.html
     30               fast/dom/HTMLDialogElement/top-layer-nesting.html
     31               fast/dom/HTMLDialogElement/top-layer-stacking-dynamic.html
     32               fast/dom/HTMLDialogElement/top-layer-stacking.html
     33
     34        * WebCore.exp.in:
     35        * css/StyleResolver.cpp:
     36        (WebCore::StyleResolver::adjustRenderStyle): Elements in the top layer have a stacking context.
     37        * dom/Document.cpp:
     38        (WebCore):
     39        (WebCore::Document::addToTopLayer):
     40        (WebCore::Document::removeFromTopLayer):
     41        * dom/Document.h:
     42        (Document):
     43        (WebCore::Document::topLayerElements): Add the top layer element stack to Document.
     44        * dom/Element.cpp:
     45        (WebCore::Element::removedFrom):
     46        (WebCore):
     47        (WebCore::Element::isInTopLayer):
     48        (WebCore::Element::setIsInTopLayer):
     49        * dom/Element.h:
     50        * dom/ElementRareData.h:
     51        (ElementRareData):
     52        * dom/Node.cpp:
     53        (WebCore::Node::detach): Add an exception to the assert since top layer elements and their descendants are moved from their
     54        regular position in the render tree.
     55        * dom/NodeRareData.h:
     56        (WebCore::NodeRareData::NodeRareData):
     57        (NodeRareData):
     58        (WebCore::NodeRareData::isInTopLayer):
     59        (WebCore::NodeRareData::setIsInTopLayer):
     60        * dom/NodeRenderingContext.cpp:
     61        (WebCore):
     62        (WebCore::adjustInsertionPointForTopLayerElement):
     63        (WebCore::NodeRendererFactory::createRendererIfNeeded): Add renderers for top layer elements as children of RenderView, and
     64        in top layer stacking order.
     65        * html/HTMLDialogElement.cpp:
     66        (WebCore::HTMLDialogElement::close):
     67        (WebCore::HTMLDialogElement::showModal):
     68        * rendering/RenderLayer.cpp:
     69        (WebCore):
     70        (WebCore::RenderLayer::isInTopLayer):
     71        (WebCore::RenderLayer::isInTopLayerSubtree):
     72        (WebCore::RenderLayer::rebuildZOrderLists): Add the top layer stack after normal layer collection.
     73        (WebCore::RenderLayer::collectLayers): Avoid adding layers for top layer elements during normal layer collection.
     74        * rendering/RenderLayer.h:
     75        (RenderLayer):
     76
    1772012-11-19  Kentaro Hara  <haraken@chromium.org>
    278
  • trunk/Source/WebCore/WebCore.exp.in

    r135189 r135242  
    22162216#endif
    22172217
     2218#if ENABLE(DIALOG_ELEMENT)
     2219__ZNK7WebCore11RenderLayer12isInTopLayerEv
     2220#endif
     2221
    22182222#if ENABLE(DRAG_SUPPORT)
    22192223__ZN7WebCore12EventHandler17dragSourceEndedAtERKNS_18PlatformMouseEventENS_13DragOperationE
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r135164 r135242  
    19841984        || ((style->overflowX() != OHIDDEN || style->overflowY() != OHIDDEN) && style->useTouchOverflowScrolling())
    19851985#endif
     1986#if ENABLE(DIALOG_ELEMENT)
     1987        || (e && e->isInTopLayer())
     1988#endif
    19861989        ))
    19871990        style->setZIndex(0);
  • trunk/Source/WebCore/dom/Document.cpp

    r135189 r135242  
    54895489#endif
    54905490
     5491#if ENABLE(DIALOG_ELEMENT)
     5492void Document::addToTopLayer(Element* element)
     5493{
     5494    ASSERT(!m_topLayerElements.contains(element));
     5495    m_topLayerElements.append(element);
     5496}
     5497
     5498void Document::removeFromTopLayer(Element* element)
     5499{
     5500    size_t position = m_topLayerElements.find(element);
     5501    ASSERT(position != notFound);
     5502    m_topLayerElements.remove(position);
     5503}
     5504#endif
     5505
    54915506#if ENABLE(POINTER_LOCK)
    54925507void Document::webkitExitPointerLock()
  • trunk/Source/WebCore/dom/Document.h

    r135163 r135242  
    11691169    Locale& getCachedLocale(const AtomicString& locale = nullAtom);
    11701170
     1171#if ENABLE(DIALOG_ELEMENT)
     1172    void addToTopLayer(Element*);
     1173    void removeFromTopLayer(Element*);
     1174    const Vector<RefPtr<Element> >& topLayerElements() const { return m_topLayerElements; }
     1175#endif
     1176
    11711177protected:
    11721178    Document(Frame*, const KURL&, bool isXHTML, bool isHTML);
     
    14691475#endif
    14701476
     1477#if ENABLE(DIALOG_ELEMENT)
     1478    Vector<RefPtr<Element> > m_topLayerElements;
     1479#endif
     1480
    14711481    int m_loadEventDelayCount;
    14721482    Timer<Document> m_loadEventDelayTimer;
  • trunk/Source/WebCore/dom/Element.cpp

    r135174 r135242  
    11521152void Element::removedFrom(ContainerNode* insertionPoint)
    11531153{
     1154#if ENABLE(DIALOG_ELEMENT)
     1155    setIsInTopLayer(false);
     1156#endif
    11541157#if ENABLE(FULLSCREEN_API)
    11551158    if (containsFullScreenElement())
     
    21782181#endif   
    21792182
     2183#if ENABLE(DIALOG_ELEMENT)
     2184bool Element::isInTopLayer() const
     2185{
     2186    return hasRareData() && elementRareData()->isInTopLayer();
     2187}
     2188
     2189void Element::setIsInTopLayer(bool inTopLayer)
     2190{
     2191    // To avoid an extra call to elementRareData(), don't use Element::isInTopLayer().
     2192    ElementRareData* rareData = hasRareData() ? elementRareData() : 0;
     2193    if (rareData) {
     2194        if (rareData->isInTopLayer() == inTopLayer)
     2195            return;
     2196    } else {
     2197        if (!inTopLayer)
     2198            return;
     2199        rareData = ensureElementRareData();
     2200    }
     2201    rareData->setIsInTopLayer(inTopLayer);
     2202
     2203    if (inTopLayer)
     2204        document()->addToTopLayer(this);
     2205    else
     2206        document()->removeFromTopLayer(this);
     2207    setNeedsStyleRecalc(SyntheticStyleChange);
     2208}
     2209#endif
     2210
    21802211#if ENABLE(POINTER_LOCK)
    21812212void Element::webkitRequestPointerLock()
  • trunk/Source/WebCore/dom/Element.h

    r135174 r135242  
    414414#endif
    415415
     416#if ENABLE(DIALOG_ELEMENT)
     417    virtual bool isInTopLayer() const;
     418    virtual void setIsInTopLayer(bool);
     419#endif
     420
    416421#if ENABLE(POINTER_LOCK)
    417422    void webkitRequestPointerLock();
  • trunk/Source/WebCore/dom/ElementRareData.h

    r133848 r135242  
    5353    using NodeRareData::containsFullScreenElement;
    5454    using NodeRareData::setContainsFullScreenElement;
     55#endif
     56#if ENABLE(DIALOG_ELEMENT)
     57    using NodeRareData::isInTopLayer;
     58    using NodeRareData::setIsInTopLayer;
    5559#endif
    5660
  • trunk/Source/WebCore/dom/Node.cpp

    r135030 r135242  
    113113#include <wtf/text/StringBuilder.h>
    114114
     115#ifndef NDEBUG
     116#include "RenderLayer.h"
     117#endif
     118
    115119#if ENABLE(GESTURE_EVENTS)
    116120#include "GestureEvent.h"
     
    13071311        for (Node* node = this; node; node = node->traverseNextNode(this)) {
    13081312            RenderObject* renderer = node->renderer();
    1309             // RenderFlowThread removes some elements from the regular tree
     1313            // RenderFlowThread and the top layer remove elements from the regular tree
    13101314            // hierarchy. They will be cleaned up when we call detach on them.
     1315#if ENABLE(DIALOG_ELEMENT)
     1316            ASSERT(!renderer || renderer->inRenderFlowThread() || (renderer->enclosingLayer()->isInTopLayerSubtree()));
     1317#else
    13111318            ASSERT(!renderer || renderer->inRenderFlowThread());
     1319#endif
    13121320        }
    13131321#endif
  • trunk/Source/WebCore/dom/NodeRareData.h

    r135030 r135242  
    194194        , m_containsFullScreenElement(false)
    195195#endif
     196#if ENABLE(DIALOG_ELEMENT)
     197        , m_isInTopLayer(false)
     198#endif
    196199    {
    197200    }
     
    311314    bool containsFullScreenElement() { return m_containsFullScreenElement; }
    312315    void setContainsFullScreenElement(bool value) { m_containsFullScreenElement = value; }
     316#endif
     317#if ENABLE(DIALOG_ELEMENT)
     318    bool isInTopLayer() const { return m_isInTopLayer; }
     319    void setIsInTopLayer(bool value) { m_isInTopLayer = value; }
    313320#endif
    314321
     
    326333    bool m_containsFullScreenElement : 1;
    327334#endif
     335#if ENABLE(DIALOG_ELEMENT)
     336    bool m_isInTopLayer : 1;
     337#endif
    328338
    329339#if ENABLE(MUTATION_OBSERVERS)
  • trunk/Source/WebCore/dom/NodeRenderingContext.cpp

    r135237 r135242  
    213213}
    214214
     215#if ENABLE(DIALOG_ELEMENT)
     216static void adjustInsertionPointForTopLayerElement(Element* element, RenderObject*& parentRenderer, RenderObject*& nextRenderer)
     217{
     218    parentRenderer = parentRenderer->view();
     219    nextRenderer = 0;
     220    const Vector<RefPtr<Element> >& topLayerElements = element->document()->topLayerElements();
     221    size_t topLayerPosition = topLayerElements.find(element);
     222    ASSERT(topLayerPosition != notFound);
     223    // Find the next top layer renderer that's stacked above this element. Note that the immediate next element in the top layer
     224    // stack might not have a renderer (due to display: none, or possibly it is not attached yet).
     225    for (size_t i = topLayerPosition + 1; i < topLayerElements.size(); ++i) {
     226        nextRenderer = topLayerElements[i]->renderer();
     227        if (nextRenderer) {
     228            ASSERT(nextRenderer->parent() == parentRenderer);
     229            break;
     230        }
     231    }
     232}
     233#endif
     234
    215235void NodeRendererFactory::createRendererIfNeeded()
    216236{
     
    242262    // the renderer added to its parent already.
    243263    RenderObject* nextRenderer = m_context.hasFlowThreadParent() ? m_context.parentFlowRenderer()->nextRendererForNode(node) : m_context.nextRenderer();
     264
     265#if ENABLE(DIALOG_ELEMENT)
     266    if (element && element->isInTopLayer())
     267        adjustInsertionPointForTopLayerElement(element, parentRenderer, nextRenderer);
     268#endif
     269
    244270    RenderObject* newRenderer = createRenderer();
    245271
  • trunk/Source/WebCore/html/HTMLDialogElement.cpp

    r129330 r135242  
    5454    }
    5555    setBooleanAttribute(openAttr, false);
     56    setIsInTopLayer(false);
    5657}
    5758
     
    7071    }
    7172    setBooleanAttribute(openAttr, true);
     73    setIsInTopLayer(true);
    7274}
    7375
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r135080 r135242  
    36683668}
    36693669
     3670#if ENABLE(DIALOG_ELEMENT)
     3671bool RenderLayer::isInTopLayer() const
     3672{
     3673    Node* node = renderer()->node();
     3674    return node && node->isElementNode() && toElement(node)->isInTopLayer();
     3675}
     3676
     3677bool RenderLayer::isInTopLayerSubtree() const
     3678{
     3679    for (const RenderLayer* layer = this; layer; layer = layer->parent()) {
     3680        if (layer->isInTopLayer())
     3681            return true;
     3682    }
     3683    return false;
     3684}
     3685#endif
     3686
    36703687// Compute the z-offset of the point in the transformState.
    36713688// This is effectively projecting a ray normal to the plane of ancestor, finding where that
     
    47874804        std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex);
    47884805
     4806#if ENABLE(DIALOG_ELEMENT)
     4807    // Append layers for top layer elements after normal layer collection, to ensure they are on top regardless of z-indexes.
     4808    // The renderers of top layer elements are children of the view, sorted in top layer stacking order.
     4809    if (isRootLayer()) {
     4810        RenderObject* view = renderer()->view();
     4811        for (RenderObject* child = view->firstChild(); child; child = child->nextSibling()) {
     4812            Element* childElement = child->node()->isElementNode() ? toElement(child->node()) : 0;
     4813            if (childElement && childElement->isInTopLayer()) {
     4814                RenderLayer* layer = toRenderLayerModelObject(child)->layer();
     4815                m_posZOrderList->append(layer);
     4816            }
     4817        }
     4818    }
     4819#endif
     4820
    47894821    m_zOrderListsDirty = false;
    47904822}
     
    48114843void RenderLayer::collectLayers(bool includeHiddenLayers, Vector<RenderLayer*>*& posBuffer, Vector<RenderLayer*>*& negBuffer)
    48124844{
     4845#if ENABLE(DIALOG_ELEMENT)
     4846    if (isInTopLayer())
     4847        return;
     4848#endif
     4849
    48134850    updateDescendantDependentFlags();
    48144851
  • trunk/Source/WebCore/rendering/RenderLayer.h

    r135064 r135242  
    703703    Node* enclosingElement() const;
    704704
     705#if ENABLE(DIALOG_ELEMENT)
     706    bool isInTopLayer() const;
     707    bool isInTopLayerSubtree() const;
     708#endif
     709
    705710private:
    706711    void updateZOrderLists();
Note: See TracChangeset for help on using the changeset viewer.