Changeset 42334 in webkit


Ignore:
Timestamp:
Apr 8, 2009 3:33:48 PM (15 years ago)
Author:
hyatt@apple.com
Message:

WebCore:

2009-04-08 David Hyatt <hyatt@apple.com>

Reviewed by Adam Roben and Darin Adler

Fix for https://bugs.webkit.org/show_bug.cgi?id=12440, repaints inconsistent for
fixed positioned elements.

Rewrite the updateScrollers method to be more correct in its results.

Test: fast/block/positioning/fixed-positioning-scrollbar-bug.html

  • dom/Document.cpp: (WebCore::Document::recalcStyle): (WebCore::Document::implicitClose):
  • page/FrameView.cpp: (WebCore::FrameView::createScrollbar): (WebCore::FrameView::layout): (WebCore::FrameView::adjustPageHeight):
  • page/FrameView.h:
  • page/win/FrameWin.cpp: (WebCore::computePageRectsForFrame):
  • platform/ScrollView.cpp: (WebCore::ScrollView::ScrollView): (WebCore::ScrollView::updateScrollbars):
  • platform/ScrollView.h:
  • rendering/RenderView.cpp: (WebCore::RenderView::layout): (WebCore::RenderView::docHeight): (WebCore::RenderView::docWidth):
  • rendering/RenderView.h:

WebKit/mac:

2009-04-08 David Hyatt <hyatt@apple.com>

Reviewed by Adam Roben and Darin Adler

Fix for https://bugs.webkit.org/show_bug.cgi?id=12440, fixed positioned elements end up in
inconsistent positions. Rewrite updateScrollers to improve the correctness.

  • WebView/WebDynamicScrollBarsView.h:
  • WebView/WebDynamicScrollBarsView.m: (-[WebDynamicScrollBarsView updateScrollers]):

LayoutTests:

2009-04-08 David Hyatt <hyatt@apple.com>

Reviewed by Adam Roben and Darin Adler

Updated results and new tests for https://bugs.webkit.org/show_bug.cgi?id=12440.

  • fast/block/positioning/fixed-positioning-scrollbar-bug.html: Added.
  • platform/mac/fast/block/positioning/fixed-positioning-scrollbar-bug-expected.checksum: Added.
  • platform/mac/fast/block/positioning/fixed-positioning-scrollbar-bug-expected.png: Added.
  • platform/mac/fast/block/positioning/fixed-positioning-scrollbar-bug-expected.txt: Added.
  • platform/mac/fast/flexbox/016-expected.checksum:
  • platform/mac/fast/flexbox/016-expected.png:
  • platform/mac/fast/flexbox/016-expected.txt:
  • platform/mac/fast/flexbox/flex-hang-expected.checksum:
  • platform/mac/fast/flexbox/flex-hang-expected.png:
  • platform/mac/fast/flexbox/flex-hang-expected.txt:
  • platform/mac/fast/lists/001-expected.checksum:
  • platform/mac/fast/lists/001-expected.png:
  • platform/mac/fast/lists/001-expected.txt:
Location:
trunk
Files:
4 added
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r42333 r42334  
     12009-04-08  David Hyatt  <hyatt@apple.com>
     2
     3        Reviewed by Adam Roben and Darin Adler
     4
     5        Updated results and new tests for https://bugs.webkit.org/show_bug.cgi?id=12440.
     6
     7        * fast/block/positioning/fixed-positioning-scrollbar-bug.html: Added.
     8        * platform/mac/fast/block/positioning/fixed-positioning-scrollbar-bug-expected.checksum: Added.
     9        * platform/mac/fast/block/positioning/fixed-positioning-scrollbar-bug-expected.png: Added.
     10        * platform/mac/fast/block/positioning/fixed-positioning-scrollbar-bug-expected.txt: Added.
     11        * platform/mac/fast/flexbox/016-expected.checksum:
     12        * platform/mac/fast/flexbox/016-expected.png:
     13        * platform/mac/fast/flexbox/016-expected.txt:
     14        * platform/mac/fast/flexbox/flex-hang-expected.checksum:
     15        * platform/mac/fast/flexbox/flex-hang-expected.png:
     16        * platform/mac/fast/flexbox/flex-hang-expected.txt:
     17        * platform/mac/fast/lists/001-expected.checksum:
     18        * platform/mac/fast/lists/001-expected.png:
     19        * platform/mac/fast/lists/001-expected.txt:
     20
    1212009-04-08  Sam Weinig  <sam@webkit.org>
    222
  • trunk/LayoutTests/platform/mac/fast/flexbox/016-expected.checksum

    r38121 r42334  
    1 e28a973da4ebd916c5493205e0cf7866
     1770ce5977c24643477c634416f5c0b82
  • trunk/LayoutTests/platform/mac/fast/flexbox/016-expected.txt

    r30431 r42334  
    1 layer at (0,0) size 812x600
    2   RenderView at (0,0) size 800x600
    3 layer at (0,0) size 812x600
    4   RenderBlock {HTML} at (0,0) size 800x600 [bgcolor=#FFFFFF]
    5     RenderBody {BODY} at (0,0) size 800x600
    6       RenderFlexibleBox {DIV} at (0,0) size 800x600
     1layer at (0,0) size 812x585
     2  RenderView at (0,0) size 800x585
     3layer at (0,0) size 812x585
     4  RenderBlock {HTML} at (0,0) size 800x585 [bgcolor=#FFFFFF]
     5    RenderBody {BODY} at (0,0) size 800x585
     6      RenderFlexibleBox {DIV} at (0,0) size 800x585
    77        RenderBlock {DIV} at (0,0) size 800x54
    88          RenderText {#text} at (0,0) size 800x54
     
    1313            text run at (254,18) width 499: "It should start beneath the header, end above the footer, and fill the width of the"
    1414            text run at (0,36) width 111: "browser window."
    15         RenderPartObject {IFRAME} at (0,54) size 812x528 [bgcolor=#008000] [border: (10px solid #808000)]
    16           layer at (0,0) size 792x508
    17             RenderView at (0,0) size 792x508
    18           layer at (0,0) size 792x508
    19             RenderBlock {HTML} at (0,0) size 792x508
    20               RenderBody {BODY} at (8,8) size 776x492
    21         RenderBlock {DIV} at (0,582) size 800x18
     15        RenderPartObject {IFRAME} at (0,54) size 812x513 [bgcolor=#008000] [border: (10px solid #808000)]
     16          layer at (0,0) size 792x493
     17            RenderView at (0,0) size 792x493
     18          layer at (0,0) size 792x493
     19            RenderBlock {HTML} at (0,0) size 792x493
     20              RenderBody {BODY} at (8,8) size 776x477
     21        RenderBlock {DIV} at (0,567) size 800x18
    2222          RenderText {#text} at (0,0) size 664x18
    2323            text run at (0,0) width 407: "This footer should remain at the bottom of the browser window. "
  • trunk/LayoutTests/platform/mac/fast/flexbox/flex-hang-expected.checksum

    r38121 r42334  
    1 6dc980c12ad5492084a0afeb8c0ca53c
     11f38bab3a53ab10e50eedeb03b796747
  • trunk/LayoutTests/platform/mac/fast/flexbox/flex-hang-expected.txt

    r30635 r42334  
    55    RenderBody {BODY} at (0,0) size 785x587
    66      RenderFlexibleBox {DIV} at (0,0) size 787x587 [border: (1px solid #000000)]
    7         RenderFlexibleBox {DIV} at (1,1) size 785x380 [border: (1px solid #000000)]
    8           RenderFlexibleBox {DIV} at (1,1) size 510x378 [border: (1px solid #000000)]
    9           RenderFlexibleBox {DIV} at (511,1) size 276x378 [border: (1px solid #000000)]
    10         RenderFlexibleBox {DIV} at (1,381) size 785x205 [border: (1px solid #000000)]
    11           RenderFlexibleBox {DIV} at (1,1) size 510x203 [border: (1px solid #000000)]
    12           RenderFlexibleBox {DIV} at (511,1) size 276x203 [border: (1px solid #000000)]
     7        RenderFlexibleBox {DIV} at (1,1) size 785x379 [border: (1px solid #000000)]
     8          RenderFlexibleBox {DIV} at (1,1) size 510x377 [border: (1px solid #000000)]
     9          RenderFlexibleBox {DIV} at (511,1) size 276x377 [border: (1px solid #000000)]
     10        RenderFlexibleBox {DIV} at (1,380) size 785x206 [border: (1px solid #000000)]
     11          RenderFlexibleBox {DIV} at (1,1) size 510x204 [border: (1px solid #000000)]
     12          RenderFlexibleBox {DIV} at (511,1) size 276x204 [border: (1px solid #000000)]
  • trunk/LayoutTests/platform/mac/fast/lists/001-expected.checksum

    r38121 r42334  
    1 4db83380f83e249fa123502288c8037f
     1fa6148a3e615abad86aea15059ac7bd5
  • trunk/LayoutTests/platform/mac/fast/lists/001-expected.txt

    r25970 r42334  
    1 layer at (0,0) size 809x600
    2   RenderView at (0,0) size 800x600
    3 layer at (0,0) size 809x600
    4   RenderBlock {HTML} at (0,0) size 800x600
    5     RenderBody {BODY} at (8,8) size 784x576
     1layer at (0,0) size 809x585
     2  RenderView at (0,0) size 800x585
     3layer at (0,0) size 809x585
     4  RenderBlock {HTML} at (0,0) size 800x585
     5    RenderBody {BODY} at (8,8) size 784x561
    66      RenderBlock {DIV} at (0,0) size 784x106 [border: (3px solid #FFA500)]
    77        RenderBlock (floating) {DIV} at (11,11) size 122x122 [bgcolor=#FFA500] [border: (3px solid #FFA500)]
  • trunk/WebCore/ChangeLog

    r42333 r42334  
     12009-04-08  David Hyatt  <hyatt@apple.com>
     2
     3        Reviewed by Adam Roben and Darin Adler
     4
     5        Fix for https://bugs.webkit.org/show_bug.cgi?id=12440, repaints inconsistent for
     6        fixed positioned elements.
     7
     8        Rewrite the updateScrollers method to be more correct in its results.
     9
     10        Test: fast/block/positioning/fixed-positioning-scrollbar-bug.html
     11
     12        * dom/Document.cpp:
     13        (WebCore::Document::recalcStyle):
     14        (WebCore::Document::implicitClose):
     15        * page/FrameView.cpp:
     16        (WebCore::FrameView::createScrollbar):
     17        (WebCore::FrameView::layout):
     18        (WebCore::FrameView::adjustPageHeight):
     19        * page/FrameView.h:
     20        * page/win/FrameWin.cpp:
     21        (WebCore::computePageRectsForFrame):
     22        * platform/ScrollView.cpp:
     23        (WebCore::ScrollView::ScrollView):
     24        (WebCore::ScrollView::updateScrollbars):
     25        * platform/ScrollView.h:
     26        * rendering/RenderView.cpp:
     27        (WebCore::RenderView::layout):
     28        (WebCore::RenderView::docHeight):
     29        (WebCore::RenderView::docWidth):
     30        * rendering/RenderView.h:
     31
    1322009-04-08  Sam Weinig  <sam@webkit.org>
    233
  • trunk/WebCore/dom/Document.cpp

    r42333 r42334  
    11561156            n->recalcStyle(change);
    11571157
     1158#if USE(ACCELERATED_COMPOSITING)
    11581159    if (view()) {
    1159         if (changed())
    1160             view()->layout();
    1161 #if USE(ACCELERATED_COMPOSITING)
    1162         else {
    1163             bool layoutPending = view()->layoutPending() || renderer()->needsLayout();
    1164             // If we didn't update compositing layers because of layout(), we need to do so here.
    1165             if (!layoutPending)
    1166                 view()->updateCompositingLayers();
    1167         }
    1168 #endif
    1169     }
     1160        bool layoutPending = view()->layoutPending() || renderer()->needsLayout();
     1161        // If we didn't update compositing layers because of layout(), we need to do so here.
     1162        if (!layoutPending)
     1163            view()->updateCompositingLayers();
     1164    }
     1165#endif
    11701166
    11711167bail_out:
     
    16141610    frame()->loader()->checkCallImplicitClose();
    16151611
    1616     // Now do our painting/layout, but only if we aren't in a subframe or if we're in a subframe
    1617     // that has been sized already.  Otherwise, our view size would be incorrect, so doing any
    1618     // layout/painting now would be pointless.
     1612    // We used to force a synchronous display and flush here.  This really isn't
     1613    // necessary and can in fact be actively harmful if pages are loading at a rate of > 60fps
     1614    // (if your platform is syncing flushes and limiting them to 60fps).
     1615    m_overMinimumLayoutThreshold = true;
    16191616    if (!ownerElement() || (ownerElement()->renderer() && !ownerElement()->renderer()->needsLayout())) {
    16201617        updateRendering();
     
    16231620        if (view() && renderer() && (!renderer()->firstChild() || renderer()->needsLayout()))
    16241621            view()->layout();
    1625            
    1626         // Paint immediately after the document is ready.  We do this to ensure that any timers set by the
    1627         // onload don't have a chance to fire before we would have painted.  To avoid over-flushing we only
    1628         // worry about this for the top-level document.  For platforms that use native widgets for ScrollViews, this
    1629         // call does nothing (Mac, wx).
    1630         // FIXME: This causes a timing issue with the dispatchDidFinishLoad delegate callback on Mac, so think
    1631         // before enabling it, even if Mac becomes viewless later.
    1632         // See <rdar://problem/5092361>
    1633         if (view() && !ownerElement())
    1634             view()->hostWindow()->paint();
    16351622    }
    16361623
  • trunk/WebCore/page/FrameView.cpp

    r42297 r42334  
    316316
    317317    // Try the <body> element first as a scrollbar source.
    318     Element* body = doc->body();
     318    Element* body = doc ? doc->body() : 0;
    319319    if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
    320320        return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderBox());
    321321   
    322322    // If the <body> didn't have a custom style, then the root element might.
    323     Element* docElement = doc->documentElement();
     323    Element* docElement = doc ? doc->documentElement() : 0;
    324324    if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
    325325        return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox());
     
    14401440        GraphicsContext context((PlatformGraphicsContext*)0);
    14411441        root->setTruncatedAt((int)floorf(oldBottom));
    1442         IntRect dirtyRect(0, (int)floorf(oldTop), root->docWidth(), (int)ceilf(oldBottom - oldTop));
     1442        IntRect dirtyRect(0, (int)floorf(oldTop), root->overflowWidth(), (int)ceilf(oldBottom - oldTop));
    14431443        root->layer()->paint(&context, dirtyRect);
    14441444        *newBottom = root->bestTruncatedAt();
     
    14491449}
    14501450
    1451 IntSize FrameView::minimumContentsSize() const
    1452 {
    1453     RenderView* root = m_frame->contentRenderer();
    1454     if (!root)
    1455         return ScrollView::minimumContentsSize();
    1456     return IntSize(root->docWidth(), root->docHeight());
    1457 }
    1458 
    14591451} // namespace WebCore
  • trunk/WebCore/page/FrameView.h

    r42297 r42334  
    7474    void setMarginHeight(int);
    7575
    76     virtual IntSize minimumContentsSize() const;
    77 
    7876    virtual void setCanHaveScrollbars(bool);
    7977
  • trunk/WebCore/page/win/FrameWin.cpp

    r40478 r42334  
    6262    float ratio = static_cast<float>(printRect.height()) / static_cast<float>(printRect.width());
    6363 
    64     float pageWidth  = static_cast<float>(root->docWidth());
     64    float pageWidth  = static_cast<float>(root->overflowWidth());
    6565    float pageHeight = pageWidth * ratio;
    6666    outPageHeight = static_cast<int>(pageHeight);   // this is the height of the page adjusted by margins
  • trunk/WebCore/platform/ScrollView.cpp

    r42297 r42334  
    4646    , m_scrollbarsAvoidingResizer(0)
    4747    , m_scrollbarsSuppressed(false)
    48     , m_inUpdateScrollbars(false)
     48    , m_updatingScrollbarAttributes(false)
     49    , m_updateScrollbarsPass(0)
    4950    , m_drawPanScrollIcon(false)
    5051    , m_useFixedLayout(false)
     
    314315}
    315316
     317static const unsigned cMaxUpdateScrollbarsPass = 2;
     318
    316319void ScrollView::updateScrollbars(const IntSize& desiredOffset)
    317320{
    318     // Don't allow re-entrancy into this function.
    319     if (m_inUpdateScrollbars || prohibitsScrolling() || platformWidget())
    320         return;
    321 
    322     m_inUpdateScrollbars = true;
    323 
     321    if (m_updatingScrollbarAttributes || prohibitsScrolling() || platformWidget())
     322        return;
     323
     324    bool hasHorizontalScrollbar = m_horizontalScrollbar;
    324325    bool hasVerticalScrollbar = m_verticalScrollbar;
    325     bool hasHorizontalScrollbar = m_horizontalScrollbar;
    326     bool oldHasVertical = hasVerticalScrollbar;
    327     bool oldHasHorizontal = hasHorizontalScrollbar;
     326   
     327    bool newHasHorizontalScrollbar = hasHorizontalScrollbar;
     328    bool newHasVerticalScrollbar = hasVerticalScrollbar;
     329   
    328330    ScrollbarMode hScroll = m_horizontalScrollbarMode;
    329331    ScrollbarMode vScroll = m_verticalScrollbarMode;
    330332
    331     const int scrollbarThickness = ScrollbarTheme::nativeTheme()->scrollbarThickness();
    332 
    333     for (int pass = 0; pass < 2; pass++) {
    334         bool scrollsVertically;
    335         bool scrollsHorizontally;
    336 
    337         if (!m_scrollbarsSuppressed && (hScroll == ScrollbarAuto || vScroll == ScrollbarAuto)) {
    338             // Do a layout if pending before checking if scrollbars are needed.
    339             if (hasVerticalScrollbar != oldHasVertical || hasHorizontalScrollbar != oldHasHorizontal)
    340                 visibleContentsResized();
    341 
    342             IntSize docSize = minimumContentsSize();
    343 
    344             scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && docSize.height() > height());
    345             if (scrollsVertically)
    346                 scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && docSize.width() + scrollbarThickness > width());
    347             else {
    348                 scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && docSize.width() > width());
    349                 if (scrollsHorizontally)
    350                     scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && docSize.height() + scrollbarThickness > height());
     333    if (m_scrollbarsSuppressed || (hScroll != ScrollbarAuto && vScroll != ScrollbarAuto)) {
     334        if (hScroll != ScrollbarAuto)
     335            newHasHorizontalScrollbar = (hScroll == ScrollbarAlwaysOn);
     336        if (vScroll != ScrollbarAuto)
     337            newHasVerticalScrollbar = (vScroll == ScrollbarAlwaysOn);
     338        if (hasHorizontalScrollbar != newHasHorizontalScrollbar)
     339            setHasHorizontalScrollbar(newHasHorizontalScrollbar);
     340        if (hasVerticalScrollbar != newHasVerticalScrollbar)
     341            setHasVerticalScrollbar(newHasVerticalScrollbar);
     342    } else {
     343        bool sendContentResizedNotification = false;
     344       
     345        IntSize docSize = contentsSize();
     346       
     347        if (hScroll == ScrollbarAuto)
     348            newHasHorizontalScrollbar = docSize.width() > visibleWidth();
     349        if (vScroll == ScrollbarAuto)
     350            newHasVerticalScrollbar = docSize.height() > visibleHeight();
     351       
     352        // If we ever turn one scrollbar off, always turn the other one off too.  Never ever
     353        // try to both gain/lose a scrollbar in the same pass.
     354        if (!newHasHorizontalScrollbar && hasHorizontalScrollbar)
     355            newHasVerticalScrollbar = false;
     356        if (!newHasVerticalScrollbar && hasVerticalScrollbar)
     357            newHasHorizontalScrollbar = false;
     358
     359        if (hasHorizontalScrollbar != newHasHorizontalScrollbar) {
     360            setHasHorizontalScrollbar(newHasHorizontalScrollbar);
     361            sendContentResizedNotification = true;
     362        }
     363 
     364        if (hasVerticalScrollbar != newHasVerticalScrollbar) {
     365            setHasVerticalScrollbar(newHasVerticalScrollbar);
     366            sendContentResizedNotification = true;
     367        }
     368
     369        if (sendContentResizedNotification && m_updateScrollbarsPass < cMaxUpdateScrollbarsPass) {
     370            m_updateScrollbarsPass++;
     371            visibleContentsResized();
     372            IntSize newDocSize = contentsSize();
     373            if (newDocSize != docSize) {
     374                // The layout with the new scroll state had no impact on
     375                // the document's overall size, so updateScrollbars didn't get called.
     376                // Recur manually.
     377                updateScrollbars(desiredOffset);
    351378            }
    352         } else {
    353             scrollsHorizontally = (hScroll == ScrollbarAuto) ? hasHorizontalScrollbar : (hScroll == ScrollbarAlwaysOn);
    354             scrollsVertically = (vScroll == ScrollbarAuto) ? hasVerticalScrollbar : (vScroll == ScrollbarAlwaysOn);
     379            m_updateScrollbarsPass--;
    355380        }
    356        
    357         if (hasVerticalScrollbar != scrollsVertically) {
    358             setHasVerticalScrollbar(scrollsVertically);
    359             hasVerticalScrollbar = scrollsVertically;
    360         }
    361 
    362         if (hasHorizontalScrollbar != scrollsHorizontally) {
    363             setHasHorizontalScrollbar(scrollsHorizontally);
    364             hasHorizontalScrollbar = scrollsHorizontally;
    365         }
    366     }
    367    
    368     // Set up the range (and page step/line step).
     381    }
     382   
     383    // Set up the range (and page step/line step), but only do this if we're not in a nested call (to avoid
     384    // doing it multiple times).
     385    if (m_updateScrollbarsPass)
     386        return;
     387
     388    m_updatingScrollbarAttributes = true;
    369389    IntSize maxScrollPosition(contentsWidth() - visibleWidth(), contentsHeight() - visibleHeight());
    370390    IntSize scroll = desiredOffset.shrunkTo(maxScrollPosition);
     
    419439    }
    420440
    421     if (oldHasVertical != (m_verticalScrollbar != 0) || oldHasHorizontal != (m_horizontalScrollbar != 0))
     441    if (hasHorizontalScrollbar != (m_horizontalScrollbar != 0) || hasVerticalScrollbar != (m_verticalScrollbar != 0))
    422442        frameRectsChanged();
    423443
     
    432452    }
    433453
    434     m_inUpdateScrollbars = false;
     454    m_updatingScrollbarAttributes = false;
    435455}
    436456
  • trunk/WebCore/platform/ScrollView.h

    r42297 r42334  
    127127    // values).
    128128    IntSize contentsSize() const; // Always at least as big as the visibleWidth()/visibleHeight().
    129     virtual IntSize minimumContentsSize() const { return contentsSize(); } // Allows a subclass to indicate a smaller size than the viewport (used for scrollbar checking).
    130129    int contentsWidth() const { return contentsSize().width(); }
    131130    int contentsHeight() const { return contentsSize().height(); }
     
    255254    bool m_scrollbarsSuppressed;
    256255
    257     bool m_inUpdateScrollbars;
     256    bool m_updatingScrollbarAttributes;
     257    unsigned m_updateScrollbarsPass;
    258258
    259259    IntPoint m_panScrollIconPoint;
  • trunk/WebCore/rendering/RenderView.cpp

    r42297 r42334  
    122122        RenderBlock::layout();
    123123
    124     m_docWidth = calcDocWidth();
    125     m_docHeight = calcDocHeight();
    126 
    127     setOverflowWidth(max(width(), m_docWidth));
    128     setOverflowHeight(max(height(), m_docHeight));
     124    // Reset overflowWidth and overflowHeight, since they act as a lower bound for docWidth() and docHeight().
     125    setOverflowWidth(width());
     126    setOverflowHeight(height());
     127   
     128    setOverflowWidth(docWidth());
     129    setOverflowHeight(docHeight());
    129130
    130131    ASSERT(layoutDelta() == IntSize());
     
    550551}
    551552
    552 int RenderView::calcDocHeight() const
    553 {
    554     // Exclude our own height, since it always matches the viewport height.  We want to know the height
    555     // of the document if it is potentially smaller than the viewport (this value will be used when trying
    556     // to figure out if scrollbars are needed).
    557     int h = max(0, lowestPosition(true, false));
     553int RenderView::docHeight() const
     554{
     555    int h = lowestPosition();
    558556
    559557    // FIXME: This doesn't do any margin collapsing.
     
    570568}
    571569
    572 int RenderView::calcDocWidth() const
    573 {
    574     // Exclude our own width, since it always matches the viewport width.  We want to know the width
    575     // of the document if it is potentially smaller than the viewport (this value will be used when trying
    576     // to figure out if scrollbars are needed).
    577     int w = max(0, rightmostPosition(true, false));
     570int RenderView::docWidth() const
     571{
     572    int w = rightmostPosition();
    578573
    579574    for (RenderBox* c = firstChildBox(); c; c = c->nextSiblingBox()) {
  • trunk/WebCore/rendering/RenderView.h

    r42297 r42334  
    5555    int viewHeight() const;
    5656    int viewWidth() const;
    57    
    58     int docWidth() const { return m_docWidth; }
    59     int docHeight() const { return m_docHeight; }
    6057
    6158    float zoomFactor() const;
     
    173170    bool shouldRepaint(const IntRect& r) const;
    174171       
    175     int calcDocHeight() const;
    176     int calcDocWidth() const;
     172    int docHeight() const;
     173    int docWidth() const;
    177174
    178175protected:
     
    196193
    197194private:
    198     int m_docWidth;
    199     int m_docHeight;
    200 
    201195    int m_bestTruncatedAt;
    202196    int m_truncatorWidth;
  • trunk/WebKit/mac/ChangeLog

    r42324 r42334  
     12009-04-08  David Hyatt  <hyatt@apple.com>
     2
     3        Reviewed by Adam Roben and Darin Adler
     4
     5        Fix for https://bugs.webkit.org/show_bug.cgi?id=12440, fixed positioned elements end up in
     6        inconsistent positions.  Rewrite updateScrollers to improve the correctness.
     7
     8        * WebView/WebDynamicScrollBarsView.h:
     9        * WebView/WebDynamicScrollBarsView.m:
     10        (-[WebDynamicScrollBarsView updateScrollers]):
     11
    1122009-04-07  Anders Carlsson  <andersca@apple.com>
    213
  • trunk/WebKit/mac/WebView/WebDynamicScrollBarsView.h

    r36982 r42334  
    4444    BOOL suppressScrollers;
    4545    BOOL inUpdateScrollers;
     46    unsigned inUpdateScrollersLayoutPass;
    4647}
    4748- (void)setAllowsHorizontalScrolling:(BOOL)flag; // This method is used by Safari, so it cannot be removed.
  • trunk/WebKit/mac/WebView/WebDynamicScrollBarsView.m

    r42297 r42334  
    8686}
    8787
     88static const unsigned cMaxUpdateScrollbarsPass = 2;
     89
    8890- (void)updateScrollers
    8991{
    90     // We need to do the work below twice in the case where a scroll bar disappears,
    91     // making the second layout have a wider width than the first. Doing it more than
    92     // twice would indicate some kind of infinite loop, so we do it at most twice.
    93     // It's quite efficient to do this work twice in the normal case, so we don't bother
    94     // trying to figure out of the second pass is needed or not.
    95     if (inUpdateScrollers)
    96         return;
    97    
    98     inUpdateScrollers = true;
    99 
    100     int pass;
    10192    BOOL hasVerticalScroller = [self hasVerticalScroller];
    10293    BOOL hasHorizontalScroller = [self hasHorizontalScroller];
    103     BOOL oldHasVertical = hasVerticalScroller;
    104     BOOL oldHasHorizontal = hasHorizontalScroller;
    105 
    106     for (pass = 0; pass < 2; pass++) {
    107         BOOL scrollsVertically;
    108         BOOL scrollsHorizontally;
    109 
    110         if (!suppressLayout && !suppressScrollers && (hScroll == ScrollbarAuto || vScroll == ScrollbarAuto)) {
    111             // Do a layout if pending, before checking if scrollbars are needed.
    112             // This fixes 2969367, although may introduce a slowdown in live resize performance.
    113             NSView *documentView = [self documentView];
    114             if (!documentView) {
    115                 scrollsHorizontally = NO;
    116                 scrollsVertically = NO;
    117             } else {
    118                 if ((hasVerticalScroller != oldHasVertical ||
    119                     hasHorizontalScroller != oldHasHorizontal || [documentView inLiveResize]) && [documentView conformsToProtocol:@protocol(WebDocumentView)]) {
    120                     [(id <WebDocumentView>)documentView setNeedsLayout: YES];
    121                     [(id <WebDocumentView>)documentView layout];
    122                 }
    123 
    124                 NSSize documentSize = [documentView frame].size;
    125                 if ([documentView isKindOfClass:[WebHTMLView class]]) {
    126                     WebHTMLView *htmlView = (WebHTMLView*)documentView;
    127                     if (Frame* coreFrame = core([htmlView _frame])) {
    128                         if (FrameView* coreView = coreFrame->view())
    129                             documentSize = coreView->minimumContentsSize();
    130                     }
    131                 }
    132 
    133                 NSSize frameSize = [self frame].size;
    134 
    135                 scrollsVertically = (vScroll == ScrollbarAlwaysOn) ||
    136                     (vScroll == ScrollbarAuto && documentSize.height > frameSize.height);
    137                 if (scrollsVertically)
    138                     scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) ||
    139                         (hScroll == ScrollbarAuto && documentSize.width + [NSScroller scrollerWidth] > frameSize.width);
    140                 else {
    141                     scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) ||
    142                         (hScroll == ScrollbarAuto && documentSize.width > frameSize.width);
    143                     if (scrollsHorizontally)
    144                         scrollsVertically = (vScroll == ScrollbarAlwaysOn) ||
    145                             (vScroll == ScrollbarAuto && documentSize.height + [NSScroller scrollerWidth] > frameSize.height);
    146                 }
    147             }
    148         } else {
    149             scrollsHorizontally = (hScroll == ScrollbarAuto) ? hasHorizontalScroller : (hScroll == ScrollbarAlwaysOn);
    150             scrollsVertically = (vScroll == ScrollbarAuto) ? hasVerticalScroller : (vScroll == ScrollbarAlwaysOn);
     94   
     95    BOOL newHasHorizontalScroller = hasHorizontalScroller;
     96    BOOL newHasVerticalScroller = hasVerticalScroller;
     97   
     98    BOOL needsLayout = NO;
     99
     100    NSView *documentView = [self documentView];
     101    if (!documentView) {
     102        newHasHorizontalScroller = NO;
     103        newHasVerticalScroller = NO;
     104    }
     105   
     106    if (!documentView || suppressLayout || suppressScrollers || (hScroll != ScrollbarAuto && vScroll != ScrollbarAuto)) {
     107        inUpdateScrollers = YES;
     108        if (hScroll != ScrollbarAuto)
     109            newHasHorizontalScroller = (hScroll == ScrollbarAlwaysOn);
     110        if (vScroll != ScrollbarAuto)
     111            newHasVerticalScroller = (vScroll == ScrollbarAlwaysOn);
     112        if (hasHorizontalScroller != newHasHorizontalScroller)
     113            [self setHasHorizontalScroller:newHasHorizontalScroller];
     114        if (hasVerticalScroller != newHasVerticalScroller)
     115            [self setHasVerticalScroller:newHasVerticalScroller];
     116        if (suppressScrollers) {
     117            [[self verticalScroller] setNeedsDisplay:NO];
     118            [[self horizontalScroller] setNeedsDisplay:NO];
    151119        }
    152 
    153         if (hasVerticalScroller != scrollsVertically) {
    154             [self setHasVerticalScroller:scrollsVertically];
    155             hasVerticalScroller = scrollsVertically;
     120        inUpdateScrollers = NO;
     121        return;
     122    }
     123
     124    needsLayout = NO;
     125
     126    NSSize documentSize = [documentView frame].size;
     127    NSSize visibleSize = [self documentVisibleRect].size;
     128   
     129    if (hScroll == ScrollbarAuto)
     130        newHasHorizontalScroller = documentSize.width > visibleSize.width;
     131    if (vScroll == ScrollbarAuto)
     132        newHasVerticalScroller = documentSize.height > visibleSize.height;
     133   
     134    // If we ever turn one scrollbar off, always turn the other one off too.  Never ever
     135    // try to both gain/lose a scrollbar in the same pass.
     136    if (!newHasHorizontalScroller && hasHorizontalScroller)
     137        newHasVerticalScroller = NO;
     138    if (!newHasVerticalScroller && hasVerticalScroller)
     139        newHasHorizontalScroller = NO;
     140
     141    if (hasHorizontalScroller != newHasHorizontalScroller) {
     142        inUpdateScrollers = YES;
     143        [self setHasHorizontalScroller:newHasHorizontalScroller];
     144        inUpdateScrollers = NO;
     145        needsLayout = YES;
     146    }
     147
     148    if (hasVerticalScroller != newHasVerticalScroller) {
     149        inUpdateScrollers = YES;
     150        [self setHasVerticalScroller:newHasVerticalScroller];
     151        inUpdateScrollers = NO;
     152        needsLayout = YES;
     153    }
     154
     155    if (needsLayout && inUpdateScrollersLayoutPass < cMaxUpdateScrollbarsPass &&
     156        [documentView conformsToProtocol:@protocol(WebDocumentView)]) {
     157        inUpdateScrollersLayoutPass++;
     158        [(id <WebDocumentView>)documentView setNeedsLayout: YES];
     159        [(id <WebDocumentView>)documentView layout];
     160        NSSize newDocumentSize = [documentView frame].size;
     161        if (NSEqualSizes(documentSize, newDocumentSize)) {
     162            // The layout with the new scroll state had no impact on
     163            // the document's overall size, so updateScrollers didn't get called.
     164            // Recur manually.
     165            [self updateScrollers];
    156166        }
    157 
    158         if (hasHorizontalScroller != scrollsHorizontally) {
    159             [self setHasHorizontalScroller:scrollsHorizontally];
    160             hasHorizontalScroller = scrollsHorizontally;
    161         }
    162     }
    163 
    164     if (suppressScrollers) {
    165         [[self verticalScroller] setNeedsDisplay: NO];
    166         [[self horizontalScroller] setNeedsDisplay: NO];
    167     }
    168 
    169     inUpdateScrollers = false;
     167        inUpdateScrollersLayoutPass--;
     168    }
    170169}
    171170
Note: See TracChangeset for help on using the changeset viewer.