⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 126774 in webkit


Ignore:
Timestamp:
Aug 27, 2012, 10:39:45 AM (14 years ago)
Author:
Simon Fraser
Message:

Implement sticky positioning
https://bugs.webkit.org/show_bug.cgi?id=90046

Reviewed by Ojan Vafai.

Source/WebCore:

Initial implementation of position: -webkit-sticky, which
constrains an element to be positioned inside the intersection
of its container box, and the viewport. Sticky elements create
stacking context.

A stickily positioned element behaves like position:relative
(space is reserved for it in-flow), but with an offset that is
determined by the sticky position. Changed isInFlowPositioned()
to cover relative and sticky.

Added a convenience isPositioned() to RenderObject(), which
is true for an object with any non-static position value.

Tests: fast/css/sticky/inflow-sticky.html

fast/css/sticky/inline-sticky-abspos-child.html
fast/css/sticky/inline-sticky.html
fast/css/sticky/replaced-sticky.html
fast/css/sticky/sticky-as-positioning-container.html
fast/css/sticky/sticky-left-percentage.html
fast/css/sticky/sticky-left.html
fast/css/sticky/sticky-margins.html
fast/css/sticky/sticky-side-margins.html
fast/css/sticky/sticky-stacking-context.html
fast/css/sticky/sticky-top-margins.html
fast/css/sticky/sticky-top.html
fast/css/sticky/sticky-writing-mode-horizontal-bt.html
fast/css/sticky/sticky-writing-mode-vertical-lr.html
fast/css/sticky/sticky-writing-mode-vertical-rl.html

  • css/StyleResolver.cpp:

(WebCore::StyleResolver::adjustRenderStyle): Have position:sticky
create stacking context from the get-go, to make scrolling optimizations easier later.

  • page/FrameView.cpp:

(WebCore::FrameView::scrollContentsFastPath): Use hasViewportConstrainedPosition().

  • page/FrameView.h: FrameView's "fixed" objects contains both fixed and sticky objects now.
  • rendering/RenderBlock.cpp: Use isPositioned().

(WebCore::RenderBlock::isSelectionRoot):
(WebCore::RenderBlock::renderName):

  • rendering/RenderBox.cpp:

(WebCore::RenderBox::styleWillChange): Need to look for both stick and fixed positioning to
determine whether to add something to FrameView's fixed object set.
(WebCore::RenderBox::computeRectForRepaint): Need to take the sticky offset into account
when computing repaint rects.

  • rendering/RenderBox.h: Implement frameRectForStickyPositioning() for boxes.
  • rendering/RenderBoxModelObject.cpp:

(WebCore::RenderBoxModelObject::updateBoxModelInfoFromStyle):
(WebCore::RenderBoxModelObject::adjustedPositionRelativeToOffsetParent):
(WebCore::RenderBoxModelObject::stickyPositionOffset): Compute the sticky position
offset by taking into account the viewport rect, and the conteriner's contentRect
inset by its margins.
(WebCore::RenderBoxModelObject::offsetForInFlowPosition): Convenience wrapper
for getting relative or sticky offset.

  • rendering/RenderBoxModelObject.h: Have requiresLayer() use isPositioned().

(WebCore::RenderBoxModelObject::stickyPositionLogicalOffset):

  • rendering/RenderInline.cpp:

(WebCore::RenderInline::styleWillChange): Need to implement this to
add/remove objects from FrameView's fixed object list, since, prior to sticky,
only boxes could be fixed.
(WebCore::RenderInline::renderName):
(WebCore::RenderInline::positionForPoint):
(WebCore::RenderInline::computeRectForRepaint):

  • rendering/RenderInline.h:
  • rendering/RenderLayer.cpp:

(WebCore::RenderLayer::updateLayerPositionsAfterScroll): Have to look for fixed or sticky.
(WebCore::RenderLayer::calculateClipRects): Use isPositioned().
(WebCore::RenderLayer::shouldBeNormalFlowOnly): Ditto.

  • rendering/RenderLayer.h:
  • rendering/RenderObject.cpp:

(WebCore::RenderObject::styleWillChange):
(WebCore::RenderObject::propagateStyleToAnonymousChildren): Should use isInFlowPositioned(),
not just isRelPositioned().
(WebCore::RenderObject::offsetParent): Use isPositioned().

  • rendering/RenderObject.h:

(WebCore::RenderObject::isInFlowPositioned):
(WebCore::RenderObject::isStickyPositioned):
(WebCore::RenderObject::setStickyPositioned):
(WebCore::RenderObject::RenderObjectBitfields::RenderObjectBitfields):
(RenderObjectBitfields):

  • rendering/RenderStyle.h: add hasViewportConstrainedPosition() for fixed or sticky position.

LayoutTests:

Various ref tests for sticky positioning.

  • fast/css/sticky/inflow-sticky-expected.html: Added.
  • fast/css/sticky/inflow-sticky.html: Added.
  • fast/css/sticky/inline-sticky-abspos-child-expected.html: Added.
  • fast/css/sticky/inline-sticky-abspos-child.html: Added.
  • fast/css/sticky/inline-sticky-expected.html: Added.
  • fast/css/sticky/inline-sticky.html: Added.
  • fast/css/sticky/replaced-sticky-expected.html: Added.
  • fast/css/sticky/replaced-sticky.html: Added.
  • fast/css/sticky/sticky-as-positioning-container-expected.html: Added.
  • fast/css/sticky/sticky-as-positioning-container.html: Added.
  • fast/css/sticky/sticky-left-expected.html: Added.
  • fast/css/sticky/sticky-left-percentage-expected.html: Added.
  • fast/css/sticky/sticky-left-percentage.html: Added.
  • fast/css/sticky/sticky-left.html: Added.
  • fast/css/sticky/sticky-margins-expected.html: Added.
  • fast/css/sticky/sticky-margins.html: Added.
  • fast/css/sticky/sticky-side-margins-expected.html: Added.
  • fast/css/sticky/sticky-side-margins.html: Added.
  • fast/css/sticky/sticky-stacking-context-expected.html: Added.
  • fast/css/sticky/sticky-stacking-context.html: Added.
  • fast/css/sticky/sticky-top-expected.html: Added.
  • fast/css/sticky/sticky-top-margins-expected.html: Added.
  • fast/css/sticky/sticky-top-margins.html: Added.
  • fast/css/sticky/sticky-top.html: Added.
  • fast/css/sticky/sticky-writing-mode-horizontal-bt-expected.html: Added.
  • fast/css/sticky/sticky-writing-mode-horizontal-bt.html: Added.
  • fast/css/sticky/sticky-writing-mode-vertical-lr-expected.html: Added.
  • fast/css/sticky/sticky-writing-mode-vertical-lr.html: Added.
  • fast/css/sticky/sticky-writing-mode-vertical-rl-expected.html: Added.
  • fast/css/sticky/sticky-writing-mode-vertical-rl.html: Added.
Location:
trunk
Files:
30 added
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r126764 r126774  
     12012-08-24  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Implement sticky positioning
     4        https://bugs.webkit.org/show_bug.cgi?id=90046
     5
     6        Reviewed by Ojan Vafai.
     7
     8        Various ref tests for sticky positioning.
     9
     10        * fast/css/sticky/inflow-sticky-expected.html: Added.
     11        * fast/css/sticky/inflow-sticky.html: Added.
     12        * fast/css/sticky/inline-sticky-abspos-child-expected.html: Added.
     13        * fast/css/sticky/inline-sticky-abspos-child.html: Added.
     14        * fast/css/sticky/inline-sticky-expected.html: Added.
     15        * fast/css/sticky/inline-sticky.html: Added.
     16        * fast/css/sticky/replaced-sticky-expected.html: Added.
     17        * fast/css/sticky/replaced-sticky.html: Added.
     18        * fast/css/sticky/sticky-as-positioning-container-expected.html: Added.
     19        * fast/css/sticky/sticky-as-positioning-container.html: Added.
     20        * fast/css/sticky/sticky-left-expected.html: Added.
     21        * fast/css/sticky/sticky-left-percentage-expected.html: Added.
     22        * fast/css/sticky/sticky-left-percentage.html: Added.
     23        * fast/css/sticky/sticky-left.html: Added.
     24        * fast/css/sticky/sticky-margins-expected.html: Added.
     25        * fast/css/sticky/sticky-margins.html: Added.
     26        * fast/css/sticky/sticky-side-margins-expected.html: Added.
     27        * fast/css/sticky/sticky-side-margins.html: Added.
     28        * fast/css/sticky/sticky-stacking-context-expected.html: Added.
     29        * fast/css/sticky/sticky-stacking-context.html: Added.
     30        * fast/css/sticky/sticky-top-expected.html: Added.
     31        * fast/css/sticky/sticky-top-margins-expected.html: Added.
     32        * fast/css/sticky/sticky-top-margins.html: Added.
     33        * fast/css/sticky/sticky-top.html: Added.
     34        * fast/css/sticky/sticky-writing-mode-horizontal-bt-expected.html: Added.
     35        * fast/css/sticky/sticky-writing-mode-horizontal-bt.html: Added.
     36        * fast/css/sticky/sticky-writing-mode-vertical-lr-expected.html: Added.
     37        * fast/css/sticky/sticky-writing-mode-vertical-lr.html: Added.
     38        * fast/css/sticky/sticky-writing-mode-vertical-rl-expected.html: Added.
     39        * fast/css/sticky/sticky-writing-mode-vertical-rl.html: Added.
     40
    1412012-08-27  Vsevolod Vlasov  <vsevik@chromium.org>
    242
  • trunk/Source/WebCore/ChangeLog

    r126770 r126774  
     12012-08-24  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Implement sticky positioning
     4        https://bugs.webkit.org/show_bug.cgi?id=90046
     5
     6        Reviewed by Ojan Vafai.
     7
     8        Initial implementation of position: -webkit-sticky, which
     9        constrains an element to be positioned inside the intersection
     10        of its container box, and the viewport. Sticky elements create
     11        stacking context.
     12       
     13        A stickily positioned element behaves like position:relative
     14        (space is reserved for it in-flow), but with an offset that is
     15        determined by the sticky position. Changed isInFlowPositioned()
     16        to cover relative and sticky.
     17       
     18        Added a convenience isPositioned() to RenderObject(), which
     19        is true for an object with any non-static position value.
     20       
     21        Tests: fast/css/sticky/inflow-sticky.html
     22               fast/css/sticky/inline-sticky-abspos-child.html
     23               fast/css/sticky/inline-sticky.html
     24               fast/css/sticky/replaced-sticky.html
     25               fast/css/sticky/sticky-as-positioning-container.html
     26               fast/css/sticky/sticky-left-percentage.html
     27               fast/css/sticky/sticky-left.html
     28               fast/css/sticky/sticky-margins.html
     29               fast/css/sticky/sticky-side-margins.html
     30               fast/css/sticky/sticky-stacking-context.html
     31               fast/css/sticky/sticky-top-margins.html
     32               fast/css/sticky/sticky-top.html
     33               fast/css/sticky/sticky-writing-mode-horizontal-bt.html
     34               fast/css/sticky/sticky-writing-mode-vertical-lr.html
     35               fast/css/sticky/sticky-writing-mode-vertical-rl.html
     36
     37        * css/StyleResolver.cpp:
     38        (WebCore::StyleResolver::adjustRenderStyle): Have position:sticky
     39        create stacking context from the get-go, to make scrolling optimizations easier later.
     40        * page/FrameView.cpp:
     41        (WebCore::FrameView::scrollContentsFastPath): Use hasViewportConstrainedPosition().
     42        * page/FrameView.h: FrameView's "fixed" objects contains both fixed and sticky objects now.
     43        * rendering/RenderBlock.cpp: Use isPositioned().
     44        (WebCore::RenderBlock::isSelectionRoot):
     45        (WebCore::RenderBlock::renderName):
     46        * rendering/RenderBox.cpp:
     47        (WebCore::RenderBox::styleWillChange): Need to look for both stick and fixed positioning to
     48        determine whether to add something to FrameView's fixed object set.
     49        (WebCore::RenderBox::computeRectForRepaint): Need to take the sticky offset into account
     50        when computing repaint rects.
     51        * rendering/RenderBox.h: Implement frameRectForStickyPositioning() for boxes.
     52        * rendering/RenderBoxModelObject.cpp:
     53        (WebCore::RenderBoxModelObject::updateBoxModelInfoFromStyle):
     54        (WebCore::RenderBoxModelObject::adjustedPositionRelativeToOffsetParent):
     55        (WebCore::RenderBoxModelObject::stickyPositionOffset): Compute the sticky position
     56        offset by taking into account the viewport rect, and the conteriner's contentRect
     57        inset by its margins.
     58        (WebCore::RenderBoxModelObject::offsetForInFlowPosition): Convenience wrapper
     59        for getting relative or sticky offset.
     60        * rendering/RenderBoxModelObject.h: Have requiresLayer() use isPositioned().
     61        (WebCore::RenderBoxModelObject::stickyPositionLogicalOffset):
     62        * rendering/RenderInline.cpp:
     63        (WebCore::RenderInline::styleWillChange): Need to implement this to
     64        add/remove objects from FrameView's fixed object list, since, prior to sticky,
     65        only boxes could be fixed.
     66        (WebCore::RenderInline::renderName):
     67        (WebCore::RenderInline::positionForPoint):
     68        (WebCore::RenderInline::computeRectForRepaint):
     69        * rendering/RenderInline.h:
     70        * rendering/RenderLayer.cpp:
     71        (WebCore::RenderLayer::updateLayerPositionsAfterScroll): Have to look for fixed or sticky.
     72        (WebCore::RenderLayer::calculateClipRects): Use isPositioned().
     73        (WebCore::RenderLayer::shouldBeNormalFlowOnly): Ditto.
     74        * rendering/RenderLayer.h:
     75        * rendering/RenderObject.cpp:
     76        (WebCore::RenderObject::styleWillChange):
     77        (WebCore::RenderObject::propagateStyleToAnonymousChildren): Should use isInFlowPositioned(),
     78        not just isRelPositioned().
     79        (WebCore::RenderObject::offsetParent): Use isPositioned().
     80        * rendering/RenderObject.h:
     81        (WebCore::RenderObject::isInFlowPositioned):
     82        (WebCore::RenderObject::isStickyPositioned):
     83        (WebCore::RenderObject::setStickyPositioned):
     84        (WebCore::RenderObject::RenderObjectBitfields::RenderObjectBitfields):
     85        (RenderObjectBitfields):
     86        * rendering/RenderStyle.h: add hasViewportConstrainedPosition() for fixed or sticky position.
     87
    1882012-08-27  Julien Chaffraix  <jchaffraix@webkit.org>
    289
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r126520 r126774  
    21972197        || style->boxReflect()
    21982198        || style->hasFilter()
     2199        || style->position() == StickyPosition
    21992200#ifdef FIXED_POSITION_CREATES_STACKING_CONTEXT
    22002201        || style->position() == FixedPosition
  • trunk/Source/WebCore/page/FrameView.cpp

    r126754 r126774  
    15031503    for (FixedObjectSet::const_iterator it = m_fixedObjects->begin(); it != end; ++it) {
    15041504        RenderObject* renderer = *it;
    1505         if (renderer->style()->position() != FixedPosition)
     1505        if (!renderer->style()->hasViewportConstrainedPosition())
    15061506            continue;
    15071507#if USE(ACCELERATED_COMPOSITING)
  • trunk/Source/WebCore/page/FrameView.h

    r126444 r126774  
    198198    bool hasSlowRepaintObjects() const { return m_slowRepaintObjectCount; }
    199199
     200    // This includes position:fixed and sticky objects.
    200201    typedef HashSet<RenderObject*> FixedObjectSet;
    201202    void addFixedObject(RenderObject*);
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r126605 r126774  
    32113211       
    32123212    if (isBody() || isRoot() || hasOverflowClip()
    3213         || isInFlowPositioned() || isFloatingOrOutOfFlowPositioned()
     3213        || isPositioned() || isFloating()
    32143214        || isTableCell() || isInlineBlockOrInlineTable()
    32153215        || hasTransform() || hasReflection() || hasMask() || isWritingModeRoot())
     
    73637363    if (isRelPositioned())
    73647364        return "RenderBlock (relative positioned)";
     7365    if (isStickyPositioned())
     7366        return "RenderBlock (sticky positioned)";
    73657367    if (isRunIn())
    73667368        return "RenderBlock (run-in)";
  • trunk/Source/WebCore/rendering/RenderBox.cpp

    r126520 r126774  
    207207
    208208    if (FrameView *frameView = view()->frameView()) {
    209         bool newStyleIsFixed = newStyle && newStyle->position() == FixedPosition;
    210         bool oldStyleIsFixed = oldStyle && oldStyle->position() == FixedPosition;
    211         if (newStyleIsFixed != oldStyleIsFixed) {
    212             if (newStyleIsFixed)
     209        bool newStyleIsViewportConstained = newStyle && newStyle->hasViewportConstrainedPosition();
     210        bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition();
     211        if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) {
     212            if (newStyleIsViewportConstained)
    213213                frameView->addFixedObject(this);
    214214            else
     
    15781578    if (position == AbsolutePosition && o->isInFlowPositioned() && o->isRenderInline())
    15791579        topLeft += toRenderInline(o)->offsetForInFlowPositionedInline(this);
    1580     else if ((position == RelativePosition) && layer()) {
     1580    else if ((position == RelativePosition || position == StickyPosition) && layer()) {
    15811581        // Apply the relative position offset when invalidating a rectangle.  The layer
    15821582        // is translated, but the render box isn't, so we need to do this to get the
  • trunk/Source/WebCore/rendering/RenderBox.h

    r126520 r126774  
    4545    // hasAutoZIndex only returns true if the element is positioned or a flex-item since
    4646    // position:static elements that are not flex-items get their z-index coerced to auto.
    47     virtual bool requiresLayer() const OVERRIDE { return isRoot() || isOutOfFlowPositioned() || isInFlowPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasHiddenBackface() || hasMask() || hasReflection() || hasFilter() || style()->specifiesColumns() || !style()->hasAutoZIndex(); }
     47    virtual bool requiresLayer() const OVERRIDE { return isRoot() || isPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasHiddenBackface() || hasMask() || hasReflection() || hasFilter() || style()->specifiesColumns() || !style()->hasAutoZIndex(); }
    4848
    4949    // Use this with caution! No type checking is done!
     
    580580    virtual void computePreferredLogicalWidths() { setPreferredLogicalWidthsDirty(false); }
    581581
     582    virtual LayoutRect frameRectForStickyPositioning() const OVERRIDE { return frameRect(); }
     583
    582584private:
    583585    // The width/height of the contents + borders + padding.  The x/y location is relative to our container (which is not always our parent).
  • trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp

    r126520 r126774  
    457457    setInline(styleToUse->isDisplayInlineType());
    458458    setRelPositioned(styleToUse->position() == RelativePosition);
     459    setStickyPositioned(styleToUse->position() == StickyPosition);
    459460    setHorizontalWritingMode(styleToUse->isHorizontalWritingMode());
    460461}
     
    535536            if (isRelPositioned())
    536537                referencePoint.move(relativePositionOffset());
     538            else if (isStickyPositioned())
     539                referencePoint.move(stickyPositionOffset());
    537540            const RenderObject* curr = parent();
    538541            while (curr != offsetParent) {
     
    543546                curr = curr->parent();
    544547            }
    545             if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent->isRelPositioned() && !offsetParent->isOutOfFlowPositioned())
     548            if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent->isPositioned())
    546549                referencePoint.moveBy(toRenderBox(offsetParent)->topLeftLocation());
    547550        }
     
    549552
    550553    return referencePoint;
     554}
     555
     556LayoutSize RenderBoxModelObject::stickyPositionOffset() const
     557{
     558    RenderBlock* containingBlock = this->containingBlock();
     559
     560    LayoutRect viewportRect = view()->frameView()->visibleContentRect();
     561    LayoutRect containerContentRect = containingBlock->contentBoxRect();
     562
     563    LayoutUnit minLeftMargin = minimumValueForLength(style()->marginLeft(), containingBlock->availableLogicalWidth(), view());
     564    LayoutUnit minTopMargin = minimumValueForLength(style()->marginTop(), containingBlock->availableLogicalWidth(), view());
     565    LayoutUnit minRightMargin = minimumValueForLength(style()->marginRight(), containingBlock->availableLogicalWidth(), view());
     566    LayoutUnit minBottomMargin = minimumValueForLength(style()->marginBottom(), containingBlock->availableLogicalWidth(), view());
     567
     568    // Compute the container-relative area within which the sticky element is allowed to move.
     569    containerContentRect.move(minLeftMargin, minTopMargin);
     570    containerContentRect.contract(minLeftMargin + minRightMargin, minTopMargin + minBottomMargin);
     571    FloatRect absContainerContentRect = containingBlock->localToAbsoluteQuad(FloatRect(containerContentRect)).boundingBox();
     572
     573    LayoutRect stickyBoxRect = frameRectForStickyPositioning();
     574    LayoutRect flippedStickyBoxRect = stickyBoxRect;
     575    containingBlock->flipForWritingMode(flippedStickyBoxRect);
     576    LayoutPoint stickyLocation = flippedStickyBoxRect.location();
     577
     578    // FIXME: sucks to call localToAbsolute again, but we can't just offset from the previously computed rect if there are transforms.
     579    FloatRect absContainerFrame = containingBlock->localToAbsoluteQuad(FloatRect(FloatPoint(), containingBlock->size())).boundingBox();
     580    // We can't call localToAbsolute on |this| because that will recur. FIXME: For now, assume that |this| is not transformed.
     581    FloatRect absoluteStickyBoxRect(absContainerFrame.location() + stickyLocation, flippedStickyBoxRect.size());
     582
     583    FloatPoint originalLocation = absoluteStickyBoxRect.location();
     584
     585    // Horizontal position.
     586    // FIXME: if left and right are specified, allow right to override left.
     587    if (!style()->left().isAuto()) {
     588        LayoutUnit leftLimit = viewportRect.x() + valueForLength(style()->left(), viewportRect.width(), view());
     589        if (absoluteStickyBoxRect.x() < leftLimit)
     590            absoluteStickyBoxRect.setX(leftLimit);
     591
     592        if (absoluteStickyBoxRect.maxX() > absContainerContentRect.maxX())
     593            absoluteStickyBoxRect.setX(absContainerContentRect.maxX() - absoluteStickyBoxRect.width());
     594    }
     595   
     596    if (!style()->right().isAuto()) {
     597        LayoutUnit rightLimit = viewportRect.maxX() - valueForLength(style()->right(), viewportRect.width(), view());
     598        if (absoluteStickyBoxRect.maxX() > rightLimit)
     599            absoluteStickyBoxRect.setX(rightLimit - absoluteStickyBoxRect.width());
     600           
     601        if (absoluteStickyBoxRect.x() < absContainerContentRect.x())
     602            absoluteStickyBoxRect.setX(absContainerContentRect.x());
     603    }
     604
     605    // Vertical position.
     606    // FIXME: if top and bottom are specified, allow bottom to override top.
     607    if (!style()->top().isAuto()) {
     608        LayoutUnit topLimit = viewportRect.y() + valueForLength(style()->top(), viewportRect.height(), view());
     609        if (absoluteStickyBoxRect.y() < topLimit)
     610            absoluteStickyBoxRect.setY(topLimit);
     611
     612        if (absoluteStickyBoxRect.maxY() > absContainerContentRect.maxY())
     613            absoluteStickyBoxRect.setY(absContainerContentRect.maxY() - absoluteStickyBoxRect.height());
     614    }
     615   
     616    if (!style()->bottom().isAuto()) {
     617        LayoutUnit bottomLimit = viewportRect.maxY() - valueForLength(style()->bottom(), viewportRect.height(), view());
     618        if (absoluteStickyBoxRect.maxY() > bottomLimit)
     619            absoluteStickyBoxRect.setY(bottomLimit - absoluteStickyBoxRect.height());
     620           
     621        if (absoluteStickyBoxRect.y() < absContainerContentRect.y())
     622            absoluteStickyBoxRect.setY(absContainerContentRect.y());
     623    }
     624
     625    // The sticky offset is physical, so we can just return the delta computed in absolute coords (though it may be wrong with transforms).
     626    return roundedLayoutSize(absoluteStickyBoxRect.location() - originalLocation);
    551627}
    552628
     
    555631    if (isRelPositioned())
    556632        return relativePositionOffset();
     633
     634    if (isStickyPositioned())
     635        return stickyPositionOffset();
    557636
    558637    return LayoutSize();
  • trunk/Source/WebCore/rendering/RenderBoxModelObject.h

    r126520 r126774  
    6363    LayoutSize relativePositionLogicalOffset() const { return style()->isHorizontalWritingMode() ? relativePositionOffset() : relativePositionOffset().transposedSize(); }
    6464
     65    LayoutSize stickyPositionOffset() const;
     66    LayoutSize stickyPositionLogicalOffset() const { return style()->isHorizontalWritingMode() ? stickyPositionOffset() : stickyPositionOffset().transposedSize(); }
     67
    6568    LayoutSize offsetForInFlowPosition() const;
    6669
     
    8386    bool hasSelfPaintingLayer() const;
    8487    RenderLayer* layer() const { return m_layer; }
    85     virtual bool requiresLayer() const { return isRoot() || isOutOfFlowPositioned() || isInFlowPositioned() || isTransparent() || hasTransform() || hasHiddenBackface() || hasMask() || hasReflection() || hasFilter() || style()->specifiesColumns(); }
     88    virtual bool requiresLayer() const { return isRoot() || isPositioned() || isTransparent() || hasTransform() || hasHiddenBackface() || hasMask() || hasReflection() || hasFilter() || style()->specifiesColumns(); }
    8689
    8790    // This will work on inlines to return the bounding box of all of the lines' border boxes.
     
    276279private:
    277280    virtual bool isBoxModelObject() const { return true; }
     281   
     282    virtual LayoutRect frameRectForStickyPositioning() const = 0;
    278283
    279284    IntSize calculateFillTileSize(const FillLayer*, const IntSize& scaledPositioningAreaSize) const;
  • trunk/Source/WebCore/rendering/RenderInline.cpp

    r126520 r126774  
    154154        block->setStyle(blockStyle);
    155155    }
     156}
     157
     158void RenderInline::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
     159{
     160    if (FrameView *frameView = view()->frameView()) {
     161        RenderStyle* oldStyle = style();
     162        bool newStyleIsSticky = newStyle && newStyle->position() == StickyPosition;
     163        bool oldStyleIsSticky = oldStyle && oldStyle->position() == StickyPosition;
     164        if (newStyleIsSticky != oldStyleIsSticky) {
     165            if (newStyleIsSticky)
     166                frameView->addFixedObject(this);
     167            else
     168                frameView->removeFixedObject(this);
     169        }
     170    }
     171
     172    RenderBoxModelObject::styleWillChange(diff, newStyle);
    156173}
    157174
     
    751768    if (isRelPositioned())
    752769        return "RenderInline (relative positioned)";
     770    if (isStickyPositioned())
     771        return "RenderInline (sticky positioned)";
    753772    if (isAnonymous())
    754773        return "RenderInline (generated)";
     
    766785VisiblePosition RenderInline::positionForPoint(const LayoutPoint& point)
    767786{
    768     // FIXME: Does not deal with relative positioned inlines (should it?)
     787    // FIXME: Does not deal with relative or sticky positioned inlines (should it?)
    769788    RenderBlock* cb = containingBlock();
    770789    if (firstLineBox()) {
     
    10651084        // Apply the in-flow position offset when invalidating a rectangle. The layer
    10661085        // is translated, but the render box isn't, so we need to do this to get the
    1067         // right dirty rect. Since this is called from RenderObject::setStyle, the relative position
     1086        // right dirty rect. Since this is called from RenderObject::setStyle, the relative or sticky position
    10681087        // flag on the RenderObject has been cleared, so use the one on the style().
    10691088        topLeft += layer()->offsetForInFlowPosition();
  • trunk/Source/WebCore/rendering/RenderInline.h

    r126520 r126774  
    9090    virtual void willBeDestroyed();
    9191
    92     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
     92    virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle) OVERRIDE;
     93    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
    9394
    9495private:
     
    141142    virtual VisiblePosition positionForPoint(const LayoutPoint&);
    142143
     144    virtual LayoutRect frameRectForStickyPositioning() const OVERRIDE { return linesBoundingBox(); }
     145
    143146    virtual IntRect borderBoundingBox() const
    144147    {
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r126663 r126774  
    520520    updateLayerPosition();
    521521
    522     if ((flags & HasSeenFixedPositionedAncestor) || renderer()->style()->position() == FixedPosition) {
     522    if ((flags & HasSeenViewportConstrainedAncestor) || renderer()->style()->hasViewportConstrainedPosition()) {
    523523        // FIXME: Is it worth passing the offsetFromRoot around like in updateLayerPositions?
    524524        computeRepaintRects();
    525         flags |= HasSeenFixedPositionedAncestor;
     525        flags |= HasSeenViewportConstrainedAncestor;
    526526    } else if ((flags & HasSeenAncestorWithOverflowClip) && !m_canSkipRepaintRectsUpdateOnScroll) {
    527527        // If we have seen an overflow clip, we should update our repaint rects as clippedOverflowRectForRepaint
     
    934934{
    935935    RenderBoxModelObject* layerRenderer = layer->renderer();
    936     return layer->isRootLayer() || layerRenderer->isOutOfFlowPositioned() || layerRenderer->isInFlowPositioned() || layer->hasTransform();
     936    return layer->isRootLayer() || layerRenderer->isPositioned() || layer->hasTransform();
    937937}
    938938
     
    39973997                newOverflowClip.setHasRadius(true);
    39983998            clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
    3999             if (renderer()->isOutOfFlowPositioned() || renderer()->isInFlowPositioned())
     3999            if (renderer()->isPositioned())
    40004000                clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
    40014001        }
     
    48024802                || renderer()->isRenderIFrame()
    48034803                || (renderer()->style()->specifiesColumns() && !isRootLayer()))
    4804             && !renderer()->isOutOfFlowPositioned()
    4805             && !renderer()->isInFlowPositioned()
     4804            && !renderer()->isPositioned()
    48064805            && !renderer()->hasTransform()
    48074806#if ENABLE(CSS_FILTERS)
  • trunk/Source/WebCore/rendering/RenderLayer.h

    r126766 r126774  
    576576    enum UpdateLayerPositionsAfterScrollFlag {
    577577        NoFlag = 0,
    578         HasSeenFixedPositionedAncestor = 1 << 0,
     578        HasSeenViewportConstrainedAncestor = 1 << 0,
    579579        HasSeenAncestorWithOverflowClip = 1 << 1
    580580    };
  • trunk/Source/WebCore/rendering/RenderObject.cpp

    r126520 r126774  
    18541854
    18551855        s_affectsParentBlock = isFloatingOrOutOfFlowPositioned()
    1856             && (!newStyle->isFloating() && newStyle->position() != AbsolutePosition && newStyle->position() != FixedPosition)
     1856            && (!newStyle->isFloating() && !newStyle->hasOutOfFlowPosition())
    18571857            && parent() && (parent()->isBlockFlow() || parent()->isRenderInline());
    18581858
     
    18621862            setPositioned(false);
    18631863            setRelPositioned(false);
     1864            setStickyPositioned(false);
    18641865        }
    18651866        setHorizontalWritingMode(true);
     
    19671968        }
    19681969
    1969         // Preserve the position style of anonymous block continuations as they can have relative position when
    1970         // they contain block descendants of relative positioned inlines.
    1971         if (child->isRelPositioned() && toRenderBlock(child)->isAnonymousBlockContinuation())
     1970        // Preserve the position style of anonymous block continuations as they can have relative or sticky position when
     1971        // they contain block descendants of relative or sticky positioned inlines.
     1972        if (child->isInFlowPositioned() && toRenderBlock(child)->isAnonymousBlockContinuation())
    19721973            newStyle->setPosition(child->style()->position());
    19731974
     
    28992900    //     * Our own extension: if there is a difference in the effective zoom
    29002901
    2901     bool skipTables = isOutOfFlowPositioned() || isRelPositioned();
     2902    bool skipTables = isPositioned();
    29022903    float currZoom = style()->effectiveZoom();
    29032904    RenderObject* curr = parent();
    2904     while (curr && (!curr->node() || (!curr->isOutOfFlowPositioned() && !curr->isRelPositioned() && !curr->isBody()))) {
     2905    while (curr && (!curr->node() || (!curr->isPositioned() && !curr->isBody()))) {
    29052906        Node* element = curr->node();
    29062907        if (!skipTables && element && (element->hasTagName(tableTag) || element->hasTagName(tdTag) || element->hasTagName(thTag)))
  • trunk/Source/WebCore/rendering/RenderObject.h

    r126520 r126774  
    514514
    515515    bool isOutOfFlowPositioned() const { return m_bitfields.positioned(); } // absolute or fixed positioning
    516     bool isInFlowPositioned() const { return m_bitfields.relPositioned(); } // relative positioning
     516    bool isInFlowPositioned() const { return m_bitfields.relPositioned() || m_bitfields.stickyPositioned(); } // relative or sticky positioning
    517517    bool isRelPositioned() const { return m_bitfields.relPositioned(); } // relative positioning
     518    bool isStickyPositioned() const { return m_bitfields.stickyPositioned(); }
     519    bool isPositioned() const { return m_bitfields.positioned() || m_bitfields.relPositioned() || m_bitfields.stickyPositioned(); }
    518520
    519521    bool isText() const  { return m_bitfields.isText(); }
     
    622624    void setPositioned(bool b = true)  { m_bitfields.setPositioned(b);  }
    623625    void setRelPositioned(bool b = true) { m_bitfields.setRelPositioned(b); }
     626    void setStickyPositioned(bool b = true) { m_bitfields.setStickyPositioned(b); }
    624627    void setFloating(bool b = true) { m_bitfields.setFloating(b); }
    625628    void setInline(bool b = true) { m_bitfields.setIsInline(b); }
     
    991994            , m_positioned(false)
    992995            , m_relPositioned(false)
     996            , m_stickyPositioned(false)
    993997            , m_paintBackground(false)
    994998            , m_isAnonymous(node == node->document())
     
    10251029        ADD_BOOLEAN_BITFIELD(positioned, Positioned);
    10261030        ADD_BOOLEAN_BITFIELD(relPositioned, RelPositioned);
     1031        ADD_BOOLEAN_BITFIELD(stickyPositioned, StickyPositioned);
    10271032        ADD_BOOLEAN_BITFIELD(paintBackground, PaintBackground); // if the box has something to paint in the
    10281033        // background painting phase (background, border, etc)
  • trunk/Source/WebCore/rendering/style/RenderStyle.h

    r126520 r126774  
    512512    bool hasOutOfFlowPosition() const { return position() == AbsolutePosition || position() == FixedPosition; }
    513513    bool hasInFlowPosition() const { return position() == RelativePosition || position() == StickyPosition; }
     514    bool hasViewportConstrainedPosition() const { return position() == FixedPosition || position() == StickyPosition; }
    514515    EFloat floating() const { return static_cast<EFloat>(noninherited_flags._floating); }
    515516
Note: See TracChangeset for help on using the changeset viewer.