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