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