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