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