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