Home | History | Annotate | Download | only in scroll
      1 /*
      2  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "platform/scroll/ScrollView.h"
     28 
     29 #include "platform/graphics/GraphicsContextStateSaver.h"
     30 #include "platform/graphics/GraphicsLayer.h"
     31 #include "platform/HostWindow.h"
     32 #include "platform/scroll/ScrollbarTheme.h"
     33 #include "wtf/StdLibExtras.h"
     34 
     35 using namespace std;
     36 
     37 namespace WebCore {
     38 
     39 ScrollView::ScrollView()
     40     : m_horizontalScrollbarMode(ScrollbarAuto)
     41     , m_verticalScrollbarMode(ScrollbarAuto)
     42     , m_horizontalScrollbarLock(false)
     43     , m_verticalScrollbarLock(false)
     44     , m_canBlitOnScroll(true)
     45     , m_scrollbarsAvoidingResizer(0)
     46     , m_scrollbarsSuppressed(false)
     47     , m_inUpdateScrollbars(false)
     48     , m_updateScrollbarsPass(0)
     49     , m_drawPanScrollIcon(false)
     50     , m_paintsEntireContents(false)
     51     , m_clipsRepaints(true)
     52 {
     53 }
     54 
     55 ScrollView::~ScrollView()
     56 {
     57 }
     58 
     59 void ScrollView::addChild(PassRefPtr<Widget> prpChild)
     60 {
     61     Widget* child = prpChild.get();
     62     ASSERT(child != this && !child->parent());
     63     child->setParent(this);
     64     m_children.add(prpChild);
     65 }
     66 
     67 void ScrollView::removeChild(Widget* child)
     68 {
     69     ASSERT(child->parent() == this);
     70     child->setParent(0);
     71     m_children.remove(child);
     72 }
     73 
     74 void ScrollView::setHasHorizontalScrollbar(bool hasBar)
     75 {
     76     if (hasBar && !m_horizontalScrollbar) {
     77         m_horizontalScrollbar = createScrollbar(HorizontalScrollbar);
     78         addChild(m_horizontalScrollbar.get());
     79         didAddScrollbar(m_horizontalScrollbar.get(), HorizontalScrollbar);
     80         m_horizontalScrollbar->styleChanged();
     81     } else if (!hasBar && m_horizontalScrollbar) {
     82         willRemoveScrollbar(m_horizontalScrollbar.get(), HorizontalScrollbar);
     83         removeChild(m_horizontalScrollbar.get());
     84         m_horizontalScrollbar = 0;
     85     }
     86 }
     87 
     88 void ScrollView::setHasVerticalScrollbar(bool hasBar)
     89 {
     90     if (hasBar && !m_verticalScrollbar) {
     91         m_verticalScrollbar = createScrollbar(VerticalScrollbar);
     92         addChild(m_verticalScrollbar.get());
     93         didAddScrollbar(m_verticalScrollbar.get(), VerticalScrollbar);
     94         m_verticalScrollbar->styleChanged();
     95     } else if (!hasBar && m_verticalScrollbar) {
     96         willRemoveScrollbar(m_verticalScrollbar.get(), VerticalScrollbar);
     97         removeChild(m_verticalScrollbar.get());
     98         m_verticalScrollbar = 0;
     99     }
    100 }
    101 
    102 PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientation)
    103 {
    104     return Scrollbar::create(this, orientation, RegularScrollbar);
    105 }
    106 
    107 void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode,
    108                                    bool horizontalLock, bool verticalLock)
    109 {
    110     bool needsUpdate = false;
    111 
    112     if (horizontalMode != horizontalScrollbarMode() && !m_horizontalScrollbarLock) {
    113         m_horizontalScrollbarMode = horizontalMode;
    114         needsUpdate = true;
    115     }
    116 
    117     if (verticalMode != verticalScrollbarMode() && !m_verticalScrollbarLock) {
    118         m_verticalScrollbarMode = verticalMode;
    119         needsUpdate = true;
    120     }
    121 
    122     if (horizontalLock)
    123         setHorizontalScrollbarLock();
    124 
    125     if (verticalLock)
    126         setVerticalScrollbarLock();
    127 
    128     if (!needsUpdate)
    129         return;
    130 
    131     updateScrollbars(scrollOffset());
    132 
    133     if (!layerForScrolling())
    134         return;
    135     blink::WebLayer* layer = layerForScrolling()->platformLayer();
    136     if (!layer)
    137         return;
    138     layer->setUserScrollable(userInputScrollable(HorizontalScrollbar), userInputScrollable(VerticalScrollbar));
    139 }
    140 
    141 void ScrollView::scrollbarModes(ScrollbarMode& horizontalMode, ScrollbarMode& verticalMode) const
    142 {
    143     horizontalMode = m_horizontalScrollbarMode;
    144     verticalMode = m_verticalScrollbarMode;
    145 }
    146 
    147 void ScrollView::setCanHaveScrollbars(bool canScroll)
    148 {
    149     ScrollbarMode newHorizontalMode;
    150     ScrollbarMode newVerticalMode;
    151 
    152     scrollbarModes(newHorizontalMode, newVerticalMode);
    153 
    154     if (canScroll && newVerticalMode == ScrollbarAlwaysOff)
    155         newVerticalMode = ScrollbarAuto;
    156     else if (!canScroll)
    157         newVerticalMode = ScrollbarAlwaysOff;
    158 
    159     if (canScroll && newHorizontalMode == ScrollbarAlwaysOff)
    160         newHorizontalMode = ScrollbarAuto;
    161     else if (!canScroll)
    162         newHorizontalMode = ScrollbarAlwaysOff;
    163 
    164     setScrollbarModes(newHorizontalMode, newVerticalMode);
    165 }
    166 
    167 void ScrollView::setCanBlitOnScroll(bool b)
    168 {
    169     m_canBlitOnScroll = b;
    170 }
    171 
    172 bool ScrollView::canBlitOnScroll() const
    173 {
    174     return m_canBlitOnScroll;
    175 }
    176 
    177 void ScrollView::setPaintsEntireContents(bool paintsEntireContents)
    178 {
    179     m_paintsEntireContents = paintsEntireContents;
    180 }
    181 
    182 void ScrollView::setClipsRepaints(bool clipsRepaints)
    183 {
    184     m_clipsRepaints = clipsRepaints;
    185 }
    186 
    187 IntSize ScrollView::unscaledVisibleContentSize(IncludeScrollbarsInRect scrollbarInclusion) const
    188 {
    189     return scrollbarInclusion == ExcludeScrollbars ? excludeScrollbars(frameRect().size()) : frameRect().size();
    190 }
    191 
    192 IntSize ScrollView::excludeScrollbars(const IntSize& size) const
    193 {
    194     int verticalScrollbarWidth = 0;
    195     int horizontalScrollbarHeight = 0;
    196 
    197     if (Scrollbar* verticalBar = verticalScrollbar())
    198         verticalScrollbarWidth = !verticalBar->isOverlayScrollbar() ? verticalBar->width() : 0;
    199     if (Scrollbar* horizontalBar = horizontalScrollbar())
    200         horizontalScrollbarHeight = !horizontalBar->isOverlayScrollbar() ? horizontalBar->height() : 0;
    201 
    202     return IntSize(max(0, size.width() - verticalScrollbarWidth),
    203         max(0, size.height() - horizontalScrollbarHeight));
    204 
    205 }
    206 
    207 IntRect ScrollView::visibleContentRect(IncludeScrollbarsInRect scollbarInclusion) const
    208 {
    209     FloatSize visibleContentSize = unscaledVisibleContentSize(scollbarInclusion);
    210     visibleContentSize.scale(1 / visibleContentScaleFactor());
    211     return IntRect(IntPoint(m_scrollOffset), expandedIntSize(visibleContentSize));
    212 }
    213 
    214 IntSize ScrollView::contentsSize() const
    215 {
    216     return m_contentsSize;
    217 }
    218 
    219 void ScrollView::setContentsSize(const IntSize& newSize)
    220 {
    221     if (contentsSize() == newSize)
    222         return;
    223     m_contentsSize = newSize;
    224     updateScrollbars(scrollOffset());
    225     updateOverhangAreas();
    226 }
    227 
    228 IntPoint ScrollView::maximumScrollPosition() const
    229 {
    230     IntPoint maximumOffset(contentsWidth() - visibleWidth() - scrollOrigin().x(), contentsHeight() - visibleHeight() - scrollOrigin().y());
    231     maximumOffset.clampNegativeToZero();
    232     return maximumOffset;
    233 }
    234 
    235 IntPoint ScrollView::minimumScrollPosition() const
    236 {
    237     return IntPoint(-scrollOrigin().x(), -scrollOrigin().y());
    238 }
    239 
    240 IntPoint ScrollView::adjustScrollPositionWithinRange(const IntPoint& scrollPoint) const
    241 {
    242     if (!constrainsScrollingToContentEdge())
    243         return scrollPoint;
    244 
    245     IntPoint newScrollPosition = scrollPoint.shrunkTo(maximumScrollPosition());
    246     newScrollPosition = newScrollPosition.expandedTo(minimumScrollPosition());
    247     return newScrollPosition;
    248 }
    249 
    250 int ScrollView::scrollSize(ScrollbarOrientation orientation) const
    251 {
    252     Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_horizontalScrollbar : m_verticalScrollbar).get();
    253 
    254     // If no scrollbars are present, the content may still be scrollable.
    255     if (!scrollbar) {
    256         IntSize scrollSize = m_contentsSize - visibleContentRect().size();
    257         scrollSize.clampNegativeToZero();
    258         return orientation == HorizontalScrollbar ? scrollSize.width() : scrollSize.height();
    259     }
    260 
    261     return scrollbar->totalSize() - scrollbar->visibleSize();
    262 }
    263 
    264 void ScrollView::notifyPageThatContentAreaWillPaint() const
    265 {
    266 }
    267 
    268 void ScrollView::setScrollOffset(const IntPoint& offset)
    269 {
    270     scrollTo(toIntSize(adjustScrollPositionWithinRange(offset)));
    271 }
    272 
    273 void ScrollView::scrollTo(const IntSize& newOffset)
    274 {
    275     IntSize scrollDelta = newOffset - m_scrollOffset;
    276     if (scrollDelta == IntSize())
    277         return;
    278     m_scrollOffset = newOffset;
    279 
    280     if (scrollbarsSuppressed())
    281         return;
    282 
    283     repaintFixedElementsAfterScrolling();
    284     scrollContents(scrollDelta);
    285     updateFixedElementsAfterScrolling();
    286 }
    287 
    288 void ScrollView::setScrollPosition(const IntPoint& scrollPoint)
    289 {
    290     IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint);
    291 
    292     if (newScrollPosition == scrollPosition())
    293         return;
    294 
    295     updateScrollbars(IntSize(newScrollPosition.x(), newScrollPosition.y()));
    296 }
    297 
    298 bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity)
    299 {
    300     ScrollDirection physicalDirection =
    301         toPhysicalDirection(direction, isVerticalDocument(), isFlippedDocument());
    302 
    303     return ScrollableArea::scroll(physicalDirection, granularity);
    304 }
    305 
    306 IntSize ScrollView::overhangAmount() const
    307 {
    308     IntSize stretch;
    309 
    310     IntPoint currentScrollPosition = scrollPosition();
    311     IntPoint minScrollPosition = minimumScrollPosition();
    312     IntPoint maxScrollPosition = maximumScrollPosition();
    313 
    314     if (currentScrollPosition.x() < minScrollPosition.x())
    315         stretch.setWidth(currentScrollPosition.x() - minScrollPosition.x());
    316     if (currentScrollPosition.x() > maxScrollPosition.x())
    317         stretch.setWidth(currentScrollPosition.x() - maxScrollPosition.x());
    318 
    319     if (currentScrollPosition.y() < minScrollPosition.y())
    320         stretch.setHeight(currentScrollPosition.y() - minScrollPosition.y());
    321     if (currentScrollPosition.y() > maxScrollPosition.y())
    322         stretch.setHeight(currentScrollPosition.y() - maxScrollPosition.y());
    323 
    324     return stretch;
    325 }
    326 
    327 void ScrollView::windowResizerRectChanged()
    328 {
    329     updateScrollbars(scrollOffset());
    330 }
    331 
    332 static const unsigned cMaxUpdateScrollbarsPass = 2;
    333 
    334 void ScrollView::updateScrollbars(const IntSize& desiredOffset)
    335 {
    336     if (m_inUpdateScrollbars)
    337         return;
    338 
    339     // If we came in here with the view already needing a layout, then go ahead and do that
    340     // first.  (This will be the common case, e.g., when the page changes due to window resizing for example).
    341     // This layout will not re-enter updateScrollbars and does not count towards our max layout pass total.
    342     if (!m_scrollbarsSuppressed) {
    343         m_inUpdateScrollbars = true;
    344         scrollbarExistenceDidChange();
    345         m_inUpdateScrollbars = false;
    346     }
    347 
    348     IntRect oldScrollCornerRect = scrollCornerRect();
    349 
    350     bool hasHorizontalScrollbar = m_horizontalScrollbar;
    351     bool hasVerticalScrollbar = m_verticalScrollbar;
    352 
    353     bool newHasHorizontalScrollbar = hasHorizontalScrollbar;
    354     bool newHasVerticalScrollbar = hasVerticalScrollbar;
    355 
    356     ScrollbarMode hScroll = m_horizontalScrollbarMode;
    357     ScrollbarMode vScroll = m_verticalScrollbarMode;
    358 
    359     if (hScroll != ScrollbarAuto)
    360         newHasHorizontalScrollbar = (hScroll == ScrollbarAlwaysOn);
    361     if (vScroll != ScrollbarAuto)
    362         newHasVerticalScrollbar = (vScroll == ScrollbarAlwaysOn);
    363 
    364     if (m_scrollbarsSuppressed || (hScroll != ScrollbarAuto && vScroll != ScrollbarAuto)) {
    365         if (hasHorizontalScrollbar != newHasHorizontalScrollbar)
    366             setHasHorizontalScrollbar(newHasHorizontalScrollbar);
    367         if (hasVerticalScrollbar != newHasVerticalScrollbar)
    368             setHasVerticalScrollbar(newHasVerticalScrollbar);
    369     } else {
    370         bool scrollbarExistenceChanged = false;
    371 
    372         IntSize docSize = contentsSize();
    373         IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size();
    374 
    375         bool scrollbarsAreOverlay = ScrollbarTheme::theme()->usesOverlayScrollbars();
    376 
    377         if (hScroll == ScrollbarAuto) {
    378             newHasHorizontalScrollbar = docSize.width() > visibleWidth();
    379             if (!scrollbarsAreOverlay && newHasHorizontalScrollbar && !m_updateScrollbarsPass && docSize.width() <= fullVisibleSize.width() && docSize.height() <= fullVisibleSize.height())
    380                 newHasHorizontalScrollbar = false;
    381         }
    382         if (vScroll == ScrollbarAuto) {
    383             newHasVerticalScrollbar = docSize.height() > visibleHeight();
    384             if (!scrollbarsAreOverlay && newHasVerticalScrollbar && !m_updateScrollbarsPass && docSize.width() <= fullVisibleSize.width() && docSize.height() <= fullVisibleSize.height())
    385                 newHasVerticalScrollbar = false;
    386         }
    387 
    388         if (!scrollbarsAreOverlay) {
    389             // If we ever turn one scrollbar off, always turn the other one off too.  Never ever
    390             // try to both gain/lose a scrollbar in the same pass.
    391             if (!newHasHorizontalScrollbar && hasHorizontalScrollbar && vScroll != ScrollbarAlwaysOn)
    392                 newHasVerticalScrollbar = false;
    393             if (!newHasVerticalScrollbar && hasVerticalScrollbar && hScroll != ScrollbarAlwaysOn)
    394                 newHasHorizontalScrollbar = false;
    395         }
    396 
    397         if (hasHorizontalScrollbar != newHasHorizontalScrollbar) {
    398             scrollbarExistenceChanged = true;
    399             if (scrollOrigin().y() && !newHasHorizontalScrollbar && !scrollbarsAreOverlay)
    400                 ScrollableArea::setScrollOrigin(IntPoint(scrollOrigin().x(), scrollOrigin().y() - m_horizontalScrollbar->height()));
    401             if (hasHorizontalScrollbar)
    402                 m_horizontalScrollbar->invalidate();
    403             setHasHorizontalScrollbar(newHasHorizontalScrollbar);
    404         }
    405 
    406         if (hasVerticalScrollbar != newHasVerticalScrollbar) {
    407             scrollbarExistenceChanged = true;
    408             if (scrollOrigin().x() && !newHasVerticalScrollbar && !scrollbarsAreOverlay)
    409                 ScrollableArea::setScrollOrigin(IntPoint(scrollOrigin().x() - m_verticalScrollbar->width(), scrollOrigin().y()));
    410             if (hasVerticalScrollbar)
    411                 m_verticalScrollbar->invalidate();
    412             setHasVerticalScrollbar(newHasVerticalScrollbar);
    413         }
    414 
    415         if (scrollbarExistenceChanged) {
    416             if (scrollbarsAreOverlay) {
    417                 // Synchronize status of scrollbar layers if necessary.
    418                 m_inUpdateScrollbars = true;
    419                 scrollbarExistenceDidChange();
    420                 m_inUpdateScrollbars = false;
    421             } else if (m_updateScrollbarsPass < cMaxUpdateScrollbarsPass) {
    422                 m_updateScrollbarsPass++;
    423                 contentsResized();
    424                 scrollbarExistenceDidChange();
    425                 IntSize newDocSize = contentsSize();
    426                 if (newDocSize == docSize) {
    427                     // The layout with the new scroll state had no impact on
    428                     // the document's overall size, so updateScrollbars didn't get called.
    429                     // Recur manually.
    430                     updateScrollbars(desiredOffset);
    431                 }
    432                 m_updateScrollbarsPass--;
    433             }
    434         }
    435     }
    436 
    437     // Set up the range, but only do this if we're not in a nested call (to avoid
    438     // doing it multiple times).
    439     if (m_updateScrollbarsPass)
    440         return;
    441 
    442     m_inUpdateScrollbars = true;
    443 
    444     if (m_horizontalScrollbar) {
    445         int clientWidth = visibleWidth();
    446         IntRect oldRect(m_horizontalScrollbar->frameRect());
    447         IntRect hBarRect((shouldPlaceVerticalScrollbarOnLeft() && m_verticalScrollbar) ? m_verticalScrollbar->width() : 0,
    448                         height() - m_horizontalScrollbar->height(),
    449                         width() - (m_verticalScrollbar ? m_verticalScrollbar->width() : 0),
    450                         m_horizontalScrollbar->height());
    451         m_horizontalScrollbar->setFrameRect(hBarRect);
    452         if (!m_scrollbarsSuppressed && oldRect != m_horizontalScrollbar->frameRect())
    453             m_horizontalScrollbar->invalidate();
    454 
    455         if (m_scrollbarsSuppressed)
    456             m_horizontalScrollbar->setSuppressInvalidation(true);
    457         m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth);
    458         m_horizontalScrollbar->setProportion(clientWidth, contentsWidth());
    459         if (m_scrollbarsSuppressed)
    460             m_horizontalScrollbar->setSuppressInvalidation(false);
    461     }
    462 
    463     if (m_verticalScrollbar) {
    464         int clientHeight = visibleHeight();
    465         IntRect oldRect(m_verticalScrollbar->frameRect());
    466         IntRect vBarRect(shouldPlaceVerticalScrollbarOnLeft() ? 0 : (width() - m_verticalScrollbar->width()),
    467                          0,
    468                          m_verticalScrollbar->width(),
    469                          height() - (m_horizontalScrollbar ? m_horizontalScrollbar->height() : 0));
    470         m_verticalScrollbar->setFrameRect(vBarRect);
    471         if (!m_scrollbarsSuppressed && oldRect != m_verticalScrollbar->frameRect())
    472             m_verticalScrollbar->invalidate();
    473 
    474         if (m_scrollbarsSuppressed)
    475             m_verticalScrollbar->setSuppressInvalidation(true);
    476         m_verticalScrollbar->setEnabled(contentsHeight() > clientHeight);
    477         m_verticalScrollbar->setProportion(clientHeight, contentsHeight());
    478         if (m_scrollbarsSuppressed)
    479             m_verticalScrollbar->setSuppressInvalidation(false);
    480     }
    481 
    482     if (hasHorizontalScrollbar != newHasHorizontalScrollbar || hasVerticalScrollbar != newHasVerticalScrollbar) {
    483         // FIXME: Is frameRectsChanged really necessary here? Have any frame rects changed?
    484         frameRectsChanged();
    485         positionScrollbarLayers();
    486         updateScrollCorner();
    487         if (!m_horizontalScrollbar && !m_verticalScrollbar)
    488             invalidateScrollCornerRect(oldScrollCornerRect);
    489     }
    490 
    491     IntPoint adjustedScrollPosition = IntPoint(desiredOffset);
    492     if (!isRubberBandInProgress())
    493         adjustedScrollPosition = adjustScrollPositionWithinRange(adjustedScrollPosition);
    494 
    495     if (adjustedScrollPosition != scrollPosition() || scrollOriginChanged()) {
    496         ScrollableArea::scrollToOffsetWithoutAnimation(adjustedScrollPosition);
    497         resetScrollOriginChanged();
    498     }
    499 
    500     // Make sure the scrollbar offsets are up to date.
    501     if (m_horizontalScrollbar)
    502         m_horizontalScrollbar->offsetDidChange();
    503     if (m_verticalScrollbar)
    504         m_verticalScrollbar->offsetDidChange();
    505 
    506     m_inUpdateScrollbars = false;
    507 }
    508 
    509 const int panIconSizeLength = 16;
    510 
    511 IntRect ScrollView::rectToCopyOnScroll() const
    512 {
    513     IntRect scrollViewRect = convertToRootView(IntRect((shouldPlaceVerticalScrollbarOnLeft() && verticalScrollbar()) ? verticalScrollbar()->width() : 0, 0, visibleWidth(), visibleHeight()));
    514     if (hasOverlayScrollbars()) {
    515         int verticalScrollbarWidth = (verticalScrollbar() && !hasLayerForVerticalScrollbar()) ? verticalScrollbar()->width() : 0;
    516         int horizontalScrollbarHeight = (horizontalScrollbar() && !hasLayerForHorizontalScrollbar()) ? horizontalScrollbar()->height() : 0;
    517 
    518         scrollViewRect.setWidth(scrollViewRect.width() - verticalScrollbarWidth);
    519         scrollViewRect.setHeight(scrollViewRect.height() - horizontalScrollbarHeight);
    520     }
    521     return scrollViewRect;
    522 }
    523 
    524 void ScrollView::scrollContents(const IntSize& scrollDelta)
    525 {
    526     HostWindow* window = hostWindow();
    527     if (!window)
    528         return;
    529 
    530     // Since scrolling is double buffered, we will be blitting the scroll view's intersection
    531     // with the clip rect every time to keep it smooth.
    532     IntRect clipRect = windowClipRect();
    533     IntRect scrollViewRect = rectToCopyOnScroll();
    534     IntRect updateRect = clipRect;
    535     updateRect.intersect(scrollViewRect);
    536 
    537     if (m_drawPanScrollIcon) {
    538         // FIXME: the pan icon is broken when accelerated compositing is on, since it will draw under the compositing layers.
    539         // https://bugs.webkit.org/show_bug.cgi?id=47837
    540         int panIconDirtySquareSizeLength = 2 * (panIconSizeLength + max(abs(scrollDelta.width()), abs(scrollDelta.height()))); // We only want to repaint what's necessary
    541         IntPoint panIconDirtySquareLocation = IntPoint(m_panScrollIconPoint.x() - (panIconDirtySquareSizeLength / 2), m_panScrollIconPoint.y() - (panIconDirtySquareSizeLength / 2));
    542         IntRect panScrollIconDirtyRect = IntRect(panIconDirtySquareLocation, IntSize(panIconDirtySquareSizeLength, panIconDirtySquareSizeLength));
    543         panScrollIconDirtyRect.intersect(clipRect);
    544         window->invalidateContentsAndRootView(panScrollIconDirtyRect);
    545     }
    546 
    547     if (canBlitOnScroll()) { // The main frame can just blit the WebView window
    548         // FIXME: Find a way to scroll subframes with this faster path
    549         if (!scrollContentsFastPath(-scrollDelta, scrollViewRect, clipRect))
    550             scrollContentsSlowPath(updateRect);
    551     } else {
    552        // We need to go ahead and repaint the entire backing store.  Do it now before moving the
    553        // windowed plugins.
    554        scrollContentsSlowPath(updateRect);
    555     }
    556 
    557     // Invalidate the overhang areas if they are visible.
    558     updateOverhangAreas();
    559 
    560     // This call will move children with native widgets (plugins) and invalidate them as well.
    561     frameRectsChanged();
    562 }
    563 
    564 bool ScrollView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
    565 {
    566     hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
    567     return true;
    568 }
    569 
    570 void ScrollView::scrollContentsSlowPath(const IntRect& updateRect)
    571 {
    572     hostWindow()->invalidateContentsForSlowScroll(updateRect);
    573 }
    574 
    575 IntPoint ScrollView::rootViewToContents(const IntPoint& rootViewPoint) const
    576 {
    577     IntPoint viewPoint = convertFromRootView(rootViewPoint);
    578     return viewPoint + scrollOffset();
    579 }
    580 
    581 IntPoint ScrollView::contentsToRootView(const IntPoint& contentsPoint) const
    582 {
    583     IntPoint viewPoint = contentsPoint - scrollOffset();
    584     return convertToRootView(viewPoint);
    585 }
    586 
    587 IntRect ScrollView::rootViewToContents(const IntRect& rootViewRect) const
    588 {
    589     IntRect viewRect = convertFromRootView(rootViewRect);
    590     viewRect.move(scrollOffset());
    591     return viewRect;
    592 }
    593 
    594 IntRect ScrollView::contentsToRootView(const IntRect& contentsRect) const
    595 {
    596     IntRect viewRect = contentsRect;
    597     viewRect.move(-scrollOffset());
    598     return convertToRootView(viewRect);
    599 }
    600 
    601 IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const
    602 {
    603     IntPoint viewPoint = convertFromContainingWindow(windowPoint);
    604     return viewPoint + scrollOffset();
    605 }
    606 
    607 IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const
    608 {
    609     IntPoint viewPoint = contentsPoint - scrollOffset();
    610     return convertToContainingWindow(viewPoint);
    611 }
    612 
    613 IntRect ScrollView::windowToContents(const IntRect& windowRect) const
    614 {
    615     IntRect viewRect = convertFromContainingWindow(windowRect);
    616     viewRect.move(scrollOffset());
    617     return viewRect;
    618 }
    619 
    620 IntRect ScrollView::contentsToWindow(const IntRect& contentsRect) const
    621 {
    622     IntRect viewRect = contentsRect;
    623     viewRect.move(-scrollOffset());
    624     return convertToContainingWindow(viewRect);
    625 }
    626 
    627 IntRect ScrollView::contentsToScreen(const IntRect& rect) const
    628 {
    629     HostWindow* window = hostWindow();
    630     if (!window)
    631         return IntRect();
    632     return window->rootViewToScreen(contentsToRootView(rect));
    633 }
    634 
    635 IntPoint ScrollView::screenToContents(const IntPoint& point) const
    636 {
    637     HostWindow* window = hostWindow();
    638     if (!window)
    639         return IntPoint();
    640     return rootViewToContents(window->screenToRootView(point));
    641 }
    642 
    643 bool ScrollView::containsScrollbarsAvoidingResizer() const
    644 {
    645     return !m_scrollbarsAvoidingResizer;
    646 }
    647 
    648 void ScrollView::adjustScrollbarsAvoidingResizerCount(int overlapDelta)
    649 {
    650     int oldCount = m_scrollbarsAvoidingResizer;
    651     m_scrollbarsAvoidingResizer += overlapDelta;
    652     if (parent())
    653         toScrollView(parent())->adjustScrollbarsAvoidingResizerCount(overlapDelta);
    654     else if (!scrollbarsSuppressed()) {
    655         // If we went from n to 0 or from 0 to n and we're the outermost view,
    656         // we need to invalidate the windowResizerRect(), since it will now need to paint
    657         // differently.
    658         if ((oldCount > 0 && m_scrollbarsAvoidingResizer == 0) ||
    659             (oldCount == 0 && m_scrollbarsAvoidingResizer > 0))
    660             invalidateRect(windowResizerRect());
    661     }
    662 }
    663 
    664 void ScrollView::setParent(Widget* parentView)
    665 {
    666     if (parentView == parent())
    667         return;
    668 
    669     if (m_scrollbarsAvoidingResizer && parent())
    670         toScrollView(parent())->adjustScrollbarsAvoidingResizerCount(-m_scrollbarsAvoidingResizer);
    671 
    672     Widget::setParent(parentView);
    673 
    674     if (m_scrollbarsAvoidingResizer && parent())
    675         toScrollView(parent())->adjustScrollbarsAvoidingResizerCount(m_scrollbarsAvoidingResizer);
    676 }
    677 
    678 void ScrollView::setScrollbarsSuppressed(bool suppressed, bool repaintOnUnsuppress)
    679 {
    680     if (suppressed == m_scrollbarsSuppressed)
    681         return;
    682 
    683     m_scrollbarsSuppressed = suppressed;
    684 
    685     if (repaintOnUnsuppress && !suppressed) {
    686         if (m_horizontalScrollbar)
    687             m_horizontalScrollbar->invalidate();
    688         if (m_verticalScrollbar)
    689             m_verticalScrollbar->invalidate();
    690 
    691         // Invalidate the scroll corner too on unsuppress.
    692         invalidateRect(scrollCornerRect());
    693     }
    694 }
    695 
    696 Scrollbar* ScrollView::scrollbarAtPoint(const IntPoint& windowPoint)
    697 {
    698     IntPoint viewPoint = convertFromContainingWindow(windowPoint);
    699     if (m_horizontalScrollbar && m_horizontalScrollbar->shouldParticipateInHitTesting() && m_horizontalScrollbar->frameRect().contains(viewPoint))
    700         return m_horizontalScrollbar.get();
    701     if (m_verticalScrollbar && m_verticalScrollbar->shouldParticipateInHitTesting() && m_verticalScrollbar->frameRect().contains(viewPoint))
    702         return m_verticalScrollbar.get();
    703     return 0;
    704 }
    705 
    706 void ScrollView::setFrameRect(const IntRect& newRect)
    707 {
    708     IntRect oldRect = frameRect();
    709 
    710     if (newRect == oldRect)
    711         return;
    712 
    713     Widget::setFrameRect(newRect);
    714 
    715     updateScrollbars(scrollOffset());
    716 
    717     frameRectsChanged();
    718 }
    719 
    720 void ScrollView::frameRectsChanged()
    721 {
    722     HashSet<RefPtr<Widget> >::const_iterator end = m_children.end();
    723     for (HashSet<RefPtr<Widget> >::const_iterator current = m_children.begin(); current != end; ++current)
    724         (*current)->frameRectsChanged();
    725 }
    726 
    727 void ScrollView::clipRectChanged()
    728 {
    729     HashSet<RefPtr<Widget> >::const_iterator end = m_children.end();
    730     for (HashSet<RefPtr<Widget> >::const_iterator current = m_children.begin(); current != end; ++current)
    731         (*current)->clipRectChanged();
    732 }
    733 
    734 static void positionScrollbarLayer(GraphicsLayer* graphicsLayer, Scrollbar* scrollbar)
    735 {
    736     if (!graphicsLayer || !scrollbar)
    737         return;
    738 
    739     IntRect scrollbarRect = scrollbar->frameRect();
    740     graphicsLayer->setPosition(scrollbarRect.location());
    741 
    742     if (scrollbarRect.size() == graphicsLayer->size())
    743         return;
    744 
    745     graphicsLayer->setSize(scrollbarRect.size());
    746 
    747     if (graphicsLayer->hasContentsLayer()) {
    748         graphicsLayer->setContentsRect(IntRect(0, 0, scrollbarRect.width(), scrollbarRect.height()));
    749         return;
    750     }
    751 
    752     graphicsLayer->setDrawsContent(true);
    753     graphicsLayer->setNeedsDisplay();
    754 }
    755 
    756 static void positionScrollCornerLayer(GraphicsLayer* graphicsLayer, const IntRect& cornerRect)
    757 {
    758     if (!graphicsLayer)
    759         return;
    760     graphicsLayer->setDrawsContent(!cornerRect.isEmpty());
    761     graphicsLayer->setPosition(cornerRect.location());
    762     if (cornerRect.size() != graphicsLayer->size())
    763         graphicsLayer->setNeedsDisplay();
    764     graphicsLayer->setSize(cornerRect.size());
    765 }
    766 
    767 void ScrollView::positionScrollbarLayers()
    768 {
    769     positionScrollbarLayer(layerForHorizontalScrollbar(), horizontalScrollbar());
    770     positionScrollbarLayer(layerForVerticalScrollbar(), verticalScrollbar());
    771     positionScrollCornerLayer(layerForScrollCorner(), scrollCornerRect());
    772 }
    773 
    774 bool ScrollView::userInputScrollable(ScrollbarOrientation orientation) const
    775 {
    776     ScrollbarMode mode = (orientation == HorizontalScrollbar) ?
    777         m_horizontalScrollbarMode : m_verticalScrollbarMode;
    778 
    779     return mode == ScrollbarAuto || mode == ScrollbarAlwaysOn;
    780 }
    781 
    782 bool ScrollView::shouldPlaceVerticalScrollbarOnLeft() const
    783 {
    784     return false;
    785 }
    786 
    787 void ScrollView::repaintContentRectangle(const IntRect& rect)
    788 {
    789     IntRect paintRect = rect;
    790     if (clipsRepaints() && !paintsEntireContents())
    791         paintRect.intersect(visibleContentRect());
    792     if (paintRect.isEmpty())
    793         return;
    794 
    795     if (HostWindow* window = hostWindow())
    796         window->invalidateContentsAndRootView(contentsToWindow(paintRect));
    797 }
    798 
    799 IntRect ScrollView::scrollCornerRect() const
    800 {
    801     IntRect cornerRect;
    802 
    803     if (hasOverlayScrollbars())
    804         return cornerRect;
    805 
    806     if (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0) {
    807         cornerRect.unite(IntRect(shouldPlaceVerticalScrollbarOnLeft() ? 0 : m_horizontalScrollbar->width(),
    808                                  height() - m_horizontalScrollbar->height(),
    809                                  width() - m_horizontalScrollbar->width(),
    810                                  m_horizontalScrollbar->height()));
    811     }
    812 
    813     if (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0) {
    814         cornerRect.unite(IntRect(shouldPlaceVerticalScrollbarOnLeft() ? 0 : (width() - m_verticalScrollbar->width()),
    815                                  m_verticalScrollbar->height(),
    816                                  m_verticalScrollbar->width(),
    817                                  height() - m_verticalScrollbar->height()));
    818     }
    819 
    820     return cornerRect;
    821 }
    822 
    823 bool ScrollView::isScrollCornerVisible() const
    824 {
    825     return !scrollCornerRect().isEmpty();
    826 }
    827 
    828 void ScrollView::scrollbarStyleChanged(int, bool forceUpdate)
    829 {
    830     if (!forceUpdate)
    831         return;
    832 
    833     contentsResized();
    834     updateScrollbars(scrollOffset());
    835     positionScrollbarLayers();
    836 }
    837 
    838 void ScrollView::updateScrollCorner()
    839 {
    840 }
    841 
    842 void ScrollView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
    843 {
    844     ScrollbarTheme::theme()->paintScrollCorner(context, cornerRect);
    845 }
    846 
    847 void ScrollView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
    848 {
    849     bar->paint(context, rect);
    850 }
    851 
    852 void ScrollView::invalidateScrollCornerRect(const IntRect& rect)
    853 {
    854     invalidateRect(rect);
    855 }
    856 
    857 void ScrollView::paintScrollbars(GraphicsContext* context, const IntRect& rect)
    858 {
    859     if (m_horizontalScrollbar && !layerForHorizontalScrollbar())
    860         paintScrollbar(context, m_horizontalScrollbar.get(), rect);
    861     if (m_verticalScrollbar && !layerForVerticalScrollbar())
    862         paintScrollbar(context, m_verticalScrollbar.get(), rect);
    863 
    864     if (layerForScrollCorner())
    865         return;
    866     paintScrollCorner(context, scrollCornerRect());
    867 }
    868 
    869 void ScrollView::paintPanScrollIcon(GraphicsContext* context)
    870 {
    871     DEFINE_STATIC_REF(Image, panScrollIcon, (Image::loadPlatformResource("panIcon")));
    872     IntPoint iconGCPoint = m_panScrollIconPoint;
    873     if (parent())
    874         iconGCPoint = toScrollView(parent())->windowToContents(iconGCPoint);
    875     context->drawImage(panScrollIcon, iconGCPoint);
    876 }
    877 
    878 void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
    879 {
    880     if (context->paintingDisabled() && !context->updatingControlTints())
    881         return;
    882 
    883     notifyPageThatContentAreaWillPaint();
    884 
    885     IntRect documentDirtyRect = rect;
    886     if (!paintsEntireContents()) {
    887         IntRect visibleAreaWithoutScrollbars(location(), visibleContentRect().size());
    888         documentDirtyRect.intersect(visibleAreaWithoutScrollbars);
    889     }
    890 
    891     if (!documentDirtyRect.isEmpty()) {
    892         GraphicsContextStateSaver stateSaver(*context);
    893 
    894         context->translate(x(), y());
    895         documentDirtyRect.moveBy(-location());
    896 
    897         if (!paintsEntireContents()) {
    898             context->translate(-scrollX(), -scrollY());
    899             documentDirtyRect.moveBy(scrollPosition());
    900 
    901             context->clip(visibleContentRect());
    902         }
    903 
    904         paintContents(context, documentDirtyRect);
    905     }
    906 
    907     calculateAndPaintOverhangAreas(context, rect);
    908 
    909     // Now paint the scrollbars.
    910     if (!m_scrollbarsSuppressed && (m_horizontalScrollbar || m_verticalScrollbar)) {
    911         GraphicsContextStateSaver stateSaver(*context);
    912         IntRect scrollViewDirtyRect = rect;
    913         IntRect visibleAreaWithScrollbars(location(), visibleContentRect(IncludeScrollbars).size());
    914         scrollViewDirtyRect.intersect(visibleAreaWithScrollbars);
    915         context->translate(x(), y());
    916         scrollViewDirtyRect.moveBy(-location());
    917 
    918         paintScrollbars(context, scrollViewDirtyRect);
    919     }
    920 
    921     // Paint the panScroll Icon
    922     if (m_drawPanScrollIcon)
    923         paintPanScrollIcon(context);
    924 }
    925 
    926 void ScrollView::calculateOverhangAreasForPainting(IntRect& horizontalOverhangRect, IntRect& verticalOverhangRect)
    927 {
    928     int verticalScrollbarWidth = (verticalScrollbar() && !verticalScrollbar()->isOverlayScrollbar())
    929         ? verticalScrollbar()->width() : 0;
    930     int horizontalScrollbarHeight = (horizontalScrollbar() && !horizontalScrollbar()->isOverlayScrollbar())
    931         ? horizontalScrollbar()->height() : 0;
    932 
    933     int physicalScrollY = scrollPosition().y() + scrollOrigin().y();
    934     if (physicalScrollY < 0) {
    935         horizontalOverhangRect = frameRect();
    936         horizontalOverhangRect.setHeight(-physicalScrollY);
    937         horizontalOverhangRect.setWidth(horizontalOverhangRect.width() - verticalScrollbarWidth);
    938     } else if (contentsHeight() && physicalScrollY > contentsHeight() - visibleHeight()) {
    939         int height = physicalScrollY - (contentsHeight() - visibleHeight());
    940         horizontalOverhangRect = frameRect();
    941         horizontalOverhangRect.setY(frameRect().maxY() - height - horizontalScrollbarHeight);
    942         horizontalOverhangRect.setHeight(height);
    943         horizontalOverhangRect.setWidth(horizontalOverhangRect.width() - verticalScrollbarWidth);
    944     }
    945 
    946     int physicalScrollX = scrollPosition().x() + scrollOrigin().x();
    947     if (physicalScrollX < 0) {
    948         verticalOverhangRect.setWidth(-physicalScrollX);
    949         verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height() - horizontalScrollbarHeight);
    950         verticalOverhangRect.setX(frameRect().x());
    951         if (horizontalOverhangRect.y() == frameRect().y())
    952             verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.height());
    953         else
    954             verticalOverhangRect.setY(frameRect().y());
    955     } else if (contentsWidth() && physicalScrollX > contentsWidth() - visibleWidth()) {
    956         int width = physicalScrollX - (contentsWidth() - visibleWidth());
    957         verticalOverhangRect.setWidth(width);
    958         verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height() - horizontalScrollbarHeight);
    959         verticalOverhangRect.setX(frameRect().maxX() - width - verticalScrollbarWidth);
    960         if (horizontalOverhangRect.y() == frameRect().y())
    961             verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.height());
    962         else
    963             verticalOverhangRect.setY(frameRect().y());
    964     }
    965 }
    966 
    967 void ScrollView::updateOverhangAreas()
    968 {
    969     HostWindow* window = hostWindow();
    970     if (!window)
    971         return;
    972 
    973     IntRect horizontalOverhangRect;
    974     IntRect verticalOverhangRect;
    975     calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
    976     if (!horizontalOverhangRect.isEmpty())
    977         window->invalidateContentsAndRootView(horizontalOverhangRect);
    978     if (!verticalOverhangRect.isEmpty())
    979         window->invalidateContentsAndRootView(verticalOverhangRect);
    980 }
    981 
    982 void ScrollView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
    983 {
    984     ScrollbarTheme::theme()->paintOverhangBackground(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
    985     ScrollbarTheme::theme()->paintOverhangShadows(context, scrollOffset(), horizontalOverhangRect, verticalOverhangRect, dirtyRect);
    986 }
    987 
    988 void ScrollView::calculateAndPaintOverhangAreas(GraphicsContext* context, const IntRect& dirtyRect)
    989 {
    990     IntRect horizontalOverhangRect;
    991     IntRect verticalOverhangRect;
    992     calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
    993 
    994     if (dirtyRect.intersects(horizontalOverhangRect) || dirtyRect.intersects(verticalOverhangRect))
    995         paintOverhangAreas(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
    996 }
    997 
    998 void ScrollView::calculateAndPaintOverhangBackground(GraphicsContext* context, const IntRect& dirtyRect)
    999 {
   1000     IntRect horizontalOverhangRect;
   1001     IntRect verticalOverhangRect;
   1002     calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
   1003 
   1004     if (dirtyRect.intersects(horizontalOverhangRect) || dirtyRect.intersects(verticalOverhangRect))
   1005         ScrollbarTheme::theme()->paintOverhangBackground(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
   1006 }
   1007 
   1008 bool ScrollView::isPointInScrollbarCorner(const IntPoint& windowPoint)
   1009 {
   1010     if (!scrollbarCornerPresent())
   1011         return false;
   1012 
   1013     IntPoint viewPoint = convertFromContainingWindow(windowPoint);
   1014 
   1015     if (m_horizontalScrollbar) {
   1016         int horizontalScrollbarYMin = m_horizontalScrollbar->frameRect().y();
   1017         int horizontalScrollbarYMax = m_horizontalScrollbar->frameRect().y() + m_horizontalScrollbar->frameRect().height();
   1018         int horizontalScrollbarXMin = m_horizontalScrollbar->frameRect().x() + m_horizontalScrollbar->frameRect().width();
   1019 
   1020         return viewPoint.y() > horizontalScrollbarYMin && viewPoint.y() < horizontalScrollbarYMax && viewPoint.x() > horizontalScrollbarXMin;
   1021     }
   1022 
   1023     int verticalScrollbarXMin = m_verticalScrollbar->frameRect().x();
   1024     int verticalScrollbarXMax = m_verticalScrollbar->frameRect().x() + m_verticalScrollbar->frameRect().width();
   1025     int verticalScrollbarYMin = m_verticalScrollbar->frameRect().y() + m_verticalScrollbar->frameRect().height();
   1026 
   1027     return viewPoint.x() > verticalScrollbarXMin && viewPoint.x() < verticalScrollbarXMax && viewPoint.y() > verticalScrollbarYMin;
   1028 }
   1029 
   1030 bool ScrollView::scrollbarCornerPresent() const
   1031 {
   1032     return (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0)
   1033         || (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0);
   1034 }
   1035 
   1036 IntRect ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& localRect) const
   1037 {
   1038     // Scrollbars won't be transformed within us
   1039     IntRect newRect = localRect;
   1040     newRect.moveBy(scrollbar->location());
   1041     return newRect;
   1042 }
   1043 
   1044 IntRect ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
   1045 {
   1046     IntRect newRect = parentRect;
   1047     // Scrollbars won't be transformed within us
   1048     newRect.moveBy(-scrollbar->location());
   1049     return newRect;
   1050 }
   1051 
   1052 // FIXME: test these on windows
   1053 IntPoint ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& localPoint) const
   1054 {
   1055     // Scrollbars won't be transformed within us
   1056     IntPoint newPoint = localPoint;
   1057     newPoint.moveBy(scrollbar->location());
   1058     return newPoint;
   1059 }
   1060 
   1061 IntPoint ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
   1062 {
   1063     IntPoint newPoint = parentPoint;
   1064     // Scrollbars won't be transformed within us
   1065     newPoint.moveBy(-scrollbar->location());
   1066     return newPoint;
   1067 }
   1068 
   1069 void ScrollView::setParentVisible(bool visible)
   1070 {
   1071     if (isParentVisible() == visible)
   1072         return;
   1073 
   1074     Widget::setParentVisible(visible);
   1075 
   1076     if (!isSelfVisible())
   1077         return;
   1078 
   1079     HashSet<RefPtr<Widget> >::iterator end = m_children.end();
   1080     for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it)
   1081         (*it)->setParentVisible(visible);
   1082 }
   1083 
   1084 void ScrollView::show()
   1085 {
   1086     if (!isSelfVisible()) {
   1087         setSelfVisible(true);
   1088         if (isParentVisible()) {
   1089             HashSet<RefPtr<Widget> >::iterator end = m_children.end();
   1090             for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it)
   1091                 (*it)->setParentVisible(true);
   1092         }
   1093     }
   1094 
   1095     Widget::show();
   1096 }
   1097 
   1098 void ScrollView::hide()
   1099 {
   1100     if (isSelfVisible()) {
   1101         if (isParentVisible()) {
   1102             HashSet<RefPtr<Widget> >::iterator end = m_children.end();
   1103             for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it)
   1104                 (*it)->setParentVisible(false);
   1105         }
   1106         setSelfVisible(false);
   1107     }
   1108 
   1109     Widget::hide();
   1110 }
   1111 
   1112 bool ScrollView::isOffscreen() const
   1113 {
   1114     return !isVisible();
   1115 }
   1116 
   1117 
   1118 void ScrollView::addPanScrollIcon(const IntPoint& iconPosition)
   1119 {
   1120     HostWindow* window = hostWindow();
   1121     if (!window)
   1122         return;
   1123     m_drawPanScrollIcon = true;
   1124     m_panScrollIconPoint = IntPoint(iconPosition.x() - panIconSizeLength / 2 , iconPosition.y() - panIconSizeLength / 2) ;
   1125     window->invalidateContentsAndRootView(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)));
   1126 }
   1127 
   1128 void ScrollView::removePanScrollIcon()
   1129 {
   1130     HostWindow* window = hostWindow();
   1131     if (!window)
   1132         return;
   1133     m_drawPanScrollIcon = false;
   1134     window->invalidateContentsAndRootView(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)));
   1135 }
   1136 
   1137 void ScrollView::setScrollOrigin(const IntPoint& origin, bool updatePositionAtAll, bool updatePositionSynchronously)
   1138 {
   1139     if (scrollOrigin() == origin)
   1140         return;
   1141 
   1142     ScrollableArea::setScrollOrigin(origin);
   1143 
   1144     // Update if the scroll origin changes, since our position will be different if the content size did not change.
   1145     if (updatePositionAtAll && updatePositionSynchronously)
   1146         updateScrollbars(scrollOffset());
   1147 }
   1148 
   1149 int ScrollView::pageStep(ScrollbarOrientation orientation) const
   1150 {
   1151     int length = (orientation == HorizontalScrollbar) ? visibleWidth() : visibleHeight();
   1152     int minPageStep = static_cast<float>(length) * minFractionToStepWhenPaging();
   1153     int pageStep = std::max(minPageStep, length - maxOverlapBetweenPages());
   1154 
   1155     return std::max(pageStep, 1);
   1156 }
   1157 
   1158 } // namespace WebCore
   1159