| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 /* |  | 
| 2  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. |  | 
| 3  * |  | 
| 4  * Redistribution and use in source and binary forms, with or without |  | 
| 5  * modification, are permitted provided that the following conditions |  | 
| 6  * are met: |  | 
| 7  * 1. Redistributions of source code must retain the above copyright |  | 
| 8  *    notice, this list of conditions and the following disclaimer. |  | 
| 9  * 2. Redistributions in binary form must reproduce the above copyright |  | 
| 10  *    notice, this list of conditions and the following disclaimer in the |  | 
| 11  *    documentation and/or other materials provided with the distribution. |  | 
| 12  * |  | 
| 13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |  | 
| 14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |  | 
| 15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |  | 
| 16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR |  | 
| 17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |  | 
| 18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |  | 
| 19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |  | 
| 20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |  | 
| 21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | 
| 22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |  | 
| 23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | 
| 24  */ |  | 
| 25 |  | 
| 26 #include "config.h" |  | 
| 27 #include "platform/scroll/ScrollView.h" |  | 
| 28 |  | 
| 29 #include "platform/graphics/GraphicsContextStateSaver.h" |  | 
| 30 #include "platform/graphics/GraphicsLayer.h" |  | 
| 31 #include "platform/HostWindow.h" |  | 
| 32 #include "platform/scroll/ScrollbarTheme.h" |  | 
| 33 #include "wtf/StdLibExtras.h" |  | 
| 34 |  | 
| 35 namespace blink { |  | 
| 36 |  | 
| 37 ScrollView::ScrollView() |  | 
| 38     : m_horizontalScrollbarMode(ScrollbarAuto) |  | 
| 39     , m_verticalScrollbarMode(ScrollbarAuto) |  | 
| 40     , m_horizontalScrollbarLock(false) |  | 
| 41     , m_verticalScrollbarLock(false) |  | 
| 42     , m_scrollbarsAvoidingResizer(0) |  | 
| 43     , m_scrollbarsSuppressed(false) |  | 
| 44     , m_inUpdateScrollbars(false) |  | 
| 45     , m_drawPanScrollIcon(false) |  | 
| 46     , m_clipsRepaints(true) |  | 
| 47 { |  | 
| 48 } |  | 
| 49 |  | 
| 50 ScrollView::~ScrollView() |  | 
| 51 { |  | 
| 52 } |  | 
| 53 |  | 
| 54 void ScrollView::addChild(PassRefPtr<Widget> prpChild) |  | 
| 55 { |  | 
| 56     Widget* child = prpChild.get(); |  | 
| 57     ASSERT(child != this && !child->parent()); |  | 
| 58     child->setParent(this); |  | 
| 59     m_children.add(prpChild); |  | 
| 60 } |  | 
| 61 |  | 
| 62 void ScrollView::removeChild(Widget* child) |  | 
| 63 { |  | 
| 64     ASSERT(child->parent() == this); |  | 
| 65     child->setParent(0); |  | 
| 66     m_children.remove(child); |  | 
| 67 } |  | 
| 68 |  | 
| 69 void ScrollView::setHasHorizontalScrollbar(bool hasBar) |  | 
| 70 { |  | 
| 71     if (hasBar && !m_horizontalScrollbar) { |  | 
| 72         m_horizontalScrollbar = createScrollbar(HorizontalScrollbar); |  | 
| 73         addChild(m_horizontalScrollbar.get()); |  | 
| 74         didAddScrollbar(m_horizontalScrollbar.get(), HorizontalScrollbar); |  | 
| 75         m_horizontalScrollbar->styleChanged(); |  | 
| 76     } else if (!hasBar && m_horizontalScrollbar) { |  | 
| 77         willRemoveScrollbar(m_horizontalScrollbar.get(), HorizontalScrollbar); |  | 
| 78         // If the scrollbar has been marked as overlapping the window resizer, |  | 
| 79         // then its removal should reduce the count. |  | 
| 80         if (m_horizontalScrollbar->overlapsResizer()) |  | 
| 81             adjustScrollbarsAvoidingResizerCount(-1); |  | 
| 82         removeChild(m_horizontalScrollbar.get()); |  | 
| 83         m_horizontalScrollbar = nullptr; |  | 
| 84     } |  | 
| 85 } |  | 
| 86 |  | 
| 87 void ScrollView::setHasVerticalScrollbar(bool hasBar) |  | 
| 88 { |  | 
| 89     if (hasBar && !m_verticalScrollbar) { |  | 
| 90         m_verticalScrollbar = createScrollbar(VerticalScrollbar); |  | 
| 91         addChild(m_verticalScrollbar.get()); |  | 
| 92         didAddScrollbar(m_verticalScrollbar.get(), VerticalScrollbar); |  | 
| 93         m_verticalScrollbar->styleChanged(); |  | 
| 94     } else if (!hasBar && m_verticalScrollbar) { |  | 
| 95         willRemoveScrollbar(m_verticalScrollbar.get(), VerticalScrollbar); |  | 
| 96         // If the scrollbar has been marked as overlapping the window resizer, |  | 
| 97         // then its removal should reduce the count. |  | 
| 98         if (m_verticalScrollbar->overlapsResizer()) |  | 
| 99             adjustScrollbarsAvoidingResizerCount(-1); |  | 
| 100         removeChild(m_verticalScrollbar.get()); |  | 
| 101         m_verticalScrollbar = nullptr; |  | 
| 102     } |  | 
| 103 } |  | 
| 104 |  | 
| 105 PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientati
      on) |  | 
| 106 { |  | 
| 107     return Scrollbar::create(this, orientation, RegularScrollbar); |  | 
| 108 } |  | 
| 109 |  | 
| 110 void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode v
      erticalMode, |  | 
| 111                                    bool horizontalLock, bool verticalLock) |  | 
| 112 { |  | 
| 113     bool needsUpdate = false; |  | 
| 114 |  | 
| 115     if (horizontalMode != horizontalScrollbarMode() && !m_horizontalScrollbarLoc
      k) { |  | 
| 116         m_horizontalScrollbarMode = horizontalMode; |  | 
| 117         needsUpdate = true; |  | 
| 118     } |  | 
| 119 |  | 
| 120     if (verticalMode != verticalScrollbarMode() && !m_verticalScrollbarLock) { |  | 
| 121         m_verticalScrollbarMode = verticalMode; |  | 
| 122         needsUpdate = true; |  | 
| 123     } |  | 
| 124 |  | 
| 125     if (horizontalLock) |  | 
| 126         setHorizontalScrollbarLock(); |  | 
| 127 |  | 
| 128     if (verticalLock) |  | 
| 129         setVerticalScrollbarLock(); |  | 
| 130 |  | 
| 131     if (!needsUpdate) |  | 
| 132         return; |  | 
| 133 |  | 
| 134     updateScrollbars(scrollOffsetDouble()); |  | 
| 135 |  | 
| 136     if (!layerForScrolling()) |  | 
| 137         return; |  | 
| 138     blink::WebLayer* layer = layerForScrolling()->platformLayer(); |  | 
| 139     if (!layer) |  | 
| 140         return; |  | 
| 141     layer->setUserScrollable(userInputScrollable(HorizontalScrollbar), userInput
      Scrollable(VerticalScrollbar)); |  | 
| 142 } |  | 
| 143 |  | 
| 144 void ScrollView::scrollbarModes(ScrollbarMode& horizontalMode, ScrollbarMode& ve
      rticalMode) const |  | 
| 145 { |  | 
| 146     horizontalMode = m_horizontalScrollbarMode; |  | 
| 147     verticalMode = m_verticalScrollbarMode; |  | 
| 148 } |  | 
| 149 |  | 
| 150 void ScrollView::setCanHaveScrollbars(bool canScroll) |  | 
| 151 { |  | 
| 152     ScrollbarMode newHorizontalMode; |  | 
| 153     ScrollbarMode newVerticalMode; |  | 
| 154 |  | 
| 155     scrollbarModes(newHorizontalMode, newVerticalMode); |  | 
| 156 |  | 
| 157     if (canScroll && newVerticalMode == ScrollbarAlwaysOff) |  | 
| 158         newVerticalMode = ScrollbarAuto; |  | 
| 159     else if (!canScroll) |  | 
| 160         newVerticalMode = ScrollbarAlwaysOff; |  | 
| 161 |  | 
| 162     if (canScroll && newHorizontalMode == ScrollbarAlwaysOff) |  | 
| 163         newHorizontalMode = ScrollbarAuto; |  | 
| 164     else if (!canScroll) |  | 
| 165         newHorizontalMode = ScrollbarAlwaysOff; |  | 
| 166 |  | 
| 167     setScrollbarModes(newHorizontalMode, newVerticalMode); |  | 
| 168 } |  | 
| 169 |  | 
| 170 void ScrollView::setClipsRepaints(bool clipsRepaints) |  | 
| 171 { |  | 
| 172     m_clipsRepaints = clipsRepaints; |  | 
| 173 } |  | 
| 174 |  | 
| 175 IntSize ScrollView::unscaledVisibleContentSize(IncludeScrollbarsInRect scrollbar
      Inclusion) const |  | 
| 176 { |  | 
| 177     return scrollbarInclusion == ExcludeScrollbars ? excludeScrollbars(frameRect
      ().size()) : frameRect().size(); |  | 
| 178 } |  | 
| 179 |  | 
| 180 IntSize ScrollView::excludeScrollbars(const IntSize& size) const |  | 
| 181 { |  | 
| 182     int verticalScrollbarWidth = 0; |  | 
| 183     int horizontalScrollbarHeight = 0; |  | 
| 184 |  | 
| 185     if (Scrollbar* verticalBar = verticalScrollbar()) |  | 
| 186         verticalScrollbarWidth = !verticalBar->isOverlayScrollbar() ? verticalBa
      r->width() : 0; |  | 
| 187     if (Scrollbar* horizontalBar = horizontalScrollbar()) |  | 
| 188         horizontalScrollbarHeight = !horizontalBar->isOverlayScrollbar() ? horiz
      ontalBar->height() : 0; |  | 
| 189 |  | 
| 190     return IntSize(std::max(0, size.width() - verticalScrollbarWidth), |  | 
| 191         std::max(0, size.height() - horizontalScrollbarHeight)); |  | 
| 192 |  | 
| 193 } |  | 
| 194 |  | 
| 195 IntRect ScrollView::visibleContentRect(IncludeScrollbarsInRect scollbarInclusion
      ) const |  | 
| 196 { |  | 
| 197     FloatSize visibleContentSize = unscaledVisibleContentSize(scollbarInclusion)
      ; |  | 
| 198     visibleContentSize.scale(1 / visibleContentScaleFactor()); |  | 
| 199     return IntRect(flooredIntPoint(m_scrollPosition), expandedIntSize(visibleCon
      tentSize)); |  | 
| 200 } |  | 
| 201 |  | 
| 202 IntSize ScrollView::contentsSize() const |  | 
| 203 { |  | 
| 204     return m_contentsSize; |  | 
| 205 } |  | 
| 206 |  | 
| 207 void ScrollView::setContentsSize(const IntSize& newSize) |  | 
| 208 { |  | 
| 209     if (contentsSize() == newSize) |  | 
| 210         return; |  | 
| 211     m_contentsSize = newSize; |  | 
| 212     updateScrollbars(scrollOffsetDouble()); |  | 
| 213     updateOverhangAreas(); |  | 
| 214 } |  | 
| 215 |  | 
| 216 IntPoint ScrollView::maximumScrollPosition() const |  | 
| 217 { |  | 
| 218     IntPoint maximumOffset(contentsWidth() - visibleWidth() - scrollOrigin().x()
      , contentsHeight() - visibleHeight() - scrollOrigin().y()); |  | 
| 219     maximumOffset.clampNegativeToZero(); |  | 
| 220     return maximumOffset; |  | 
| 221 } |  | 
| 222 |  | 
| 223 IntPoint ScrollView::minimumScrollPosition() const |  | 
| 224 { |  | 
| 225     return IntPoint(-scrollOrigin().x(), -scrollOrigin().y()); |  | 
| 226 } |  | 
| 227 |  | 
| 228 IntPoint ScrollView::adjustScrollPositionWithinRange(const IntPoint& scrollPoint
      ) const |  | 
| 229 { |  | 
| 230     if (!constrainsScrollingToContentEdge()) |  | 
| 231         return scrollPoint; |  | 
| 232 |  | 
| 233     IntPoint newScrollPosition = scrollPoint.shrunkTo(maximumScrollPosition()); |  | 
| 234     newScrollPosition = newScrollPosition.expandedTo(minimumScrollPosition()); |  | 
| 235     return newScrollPosition; |  | 
| 236 } |  | 
| 237 |  | 
| 238 DoublePoint ScrollView::adjustScrollPositionWithinRange(const DoublePoint& scrol
      lPoint) const |  | 
| 239 { |  | 
| 240     if (!constrainsScrollingToContentEdge()) |  | 
| 241         return scrollPoint; |  | 
| 242     DoublePoint newScrollPosition = scrollPoint.shrunkTo( |  | 
| 243         maximumScrollPosition().x(), maximumScrollPosition().y()); |  | 
| 244     newScrollPosition = newScrollPosition.expandedTo( |  | 
| 245         minimumScrollPosition().x(), minimumScrollPosition().y()); |  | 
| 246     return newScrollPosition; |  | 
| 247 } |  | 
| 248 |  | 
| 249 void ScrollView::adjustScrollbarOpacity() |  | 
| 250 { |  | 
| 251     if (m_horizontalScrollbar && layerForHorizontalScrollbar()) { |  | 
| 252         bool isOpaqueScrollbar = !m_horizontalScrollbar->isOverlayScrollbar(); |  | 
| 253         layerForHorizontalScrollbar()->setContentsOpaque(isOpaqueScrollbar); |  | 
| 254     } |  | 
| 255     if (m_verticalScrollbar && layerForVerticalScrollbar()) { |  | 
| 256         bool isOpaqueScrollbar = !m_verticalScrollbar->isOverlayScrollbar(); |  | 
| 257         layerForVerticalScrollbar()->setContentsOpaque(isOpaqueScrollbar); |  | 
| 258     } |  | 
| 259 } |  | 
| 260 |  | 
| 261 int ScrollView::scrollSize(ScrollbarOrientation orientation) const |  | 
| 262 { |  | 
| 263     Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_horizontalS
      crollbar : m_verticalScrollbar).get(); |  | 
| 264 |  | 
| 265     // If no scrollbars are present, the content may still be scrollable. |  | 
| 266     if (!scrollbar) { |  | 
| 267         IntSize scrollSize = m_contentsSize - visibleContentRect().size(); |  | 
| 268         scrollSize.clampNegativeToZero(); |  | 
| 269         return orientation == HorizontalScrollbar ? scrollSize.width() : scrollS
      ize.height(); |  | 
| 270     } |  | 
| 271 |  | 
| 272     return scrollbar->totalSize() - scrollbar->visibleSize(); |  | 
| 273 } |  | 
| 274 |  | 
| 275 void ScrollView::notifyPageThatContentAreaWillPaint() const |  | 
| 276 { |  | 
| 277 } |  | 
| 278 |  | 
| 279 void ScrollView::setScrollOffset(const IntPoint& offset) |  | 
| 280 { |  | 
| 281     scrollTo(DoublePoint(adjustScrollPositionWithinRange(offset))); |  | 
| 282 } |  | 
| 283 |  | 
| 284 void ScrollView::setScrollOffset(const DoublePoint& offset) |  | 
| 285 { |  | 
| 286     scrollTo(adjustScrollPositionWithinRange(offset)); |  | 
| 287 } |  | 
| 288 |  | 
| 289 void ScrollView::scrollTo(const DoublePoint& newPosition) |  | 
| 290 { |  | 
| 291     DoubleSize scrollDelta = newPosition - m_scrollPosition; |  | 
| 292     if (scrollDelta.isZero()) |  | 
| 293         return; |  | 
| 294     m_scrollPosition = newPosition; |  | 
| 295 |  | 
| 296     if (scrollbarsSuppressed()) |  | 
| 297         return; |  | 
| 298 |  | 
| 299     // FIXME: Change scrollContents() to take DoubleSize. crbug.com/414283. |  | 
| 300     if (isFrameView()) |  | 
| 301         m_pendingScrollDelta += scrollDelta; |  | 
| 302     else |  | 
| 303         scrollContents(flooredIntSize(scrollDelta)); |  | 
| 304 } |  | 
| 305 |  | 
| 306 void ScrollView::setScrollPosition(const DoublePoint& scrollPoint, ScrollBehavio
      r scrollBehavior) |  | 
| 307 { |  | 
| 308     DoublePoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint)
      ; |  | 
| 309 |  | 
| 310     if (newScrollPosition == scrollPositionDouble()) |  | 
| 311         return; |  | 
| 312 |  | 
| 313     if (scrollBehavior == ScrollBehaviorInstant) { |  | 
| 314         DoubleSize newOffset(newScrollPosition.x(), newScrollPosition.y()); |  | 
| 315         updateScrollbars(newOffset); |  | 
| 316     } else { |  | 
| 317         programmaticallyScrollSmoothlyToOffset(toFloatPoint(newScrollPosition)); |  | 
| 318     } |  | 
| 319 } |  | 
| 320 |  | 
| 321 bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity
      ) |  | 
| 322 { |  | 
| 323     ScrollDirection physicalDirection = |  | 
| 324         toPhysicalDirection(direction, isVerticalDocument(), isFlippedDocument()
      ); |  | 
| 325 |  | 
| 326     return ScrollableArea::scroll(physicalDirection, granularity); |  | 
| 327 } |  | 
| 328 |  | 
| 329 IntSize ScrollView::overhangAmount() const |  | 
| 330 { |  | 
| 331     IntSize stretch; |  | 
| 332 |  | 
| 333     IntPoint currentScrollPosition = scrollPosition(); |  | 
| 334     IntPoint minScrollPosition = minimumScrollPosition(); |  | 
| 335     IntPoint maxScrollPosition = maximumScrollPosition(); |  | 
| 336 |  | 
| 337     if (currentScrollPosition.x() < minScrollPosition.x()) |  | 
| 338         stretch.setWidth(currentScrollPosition.x() - minScrollPosition.x()); |  | 
| 339     if (currentScrollPosition.x() > maxScrollPosition.x()) |  | 
| 340         stretch.setWidth(currentScrollPosition.x() - maxScrollPosition.x()); |  | 
| 341 |  | 
| 342     if (currentScrollPosition.y() < minScrollPosition.y()) |  | 
| 343         stretch.setHeight(currentScrollPosition.y() - minScrollPosition.y()); |  | 
| 344     if (currentScrollPosition.y() > maxScrollPosition.y()) |  | 
| 345         stretch.setHeight(currentScrollPosition.y() - maxScrollPosition.y()); |  | 
| 346 |  | 
| 347     return stretch; |  | 
| 348 } |  | 
| 349 |  | 
| 350 void ScrollView::windowResizerRectChanged() |  | 
| 351 { |  | 
| 352     updateScrollbars(scrollOffsetDouble()); |  | 
| 353 } |  | 
| 354 |  | 
| 355 static bool useOverlayScrollbars() |  | 
| 356 { |  | 
| 357     // FIXME: Need to detect the presence of CSS custom scrollbars, which are no
      n-overlay regardless the ScrollbarTheme. |  | 
| 358     return ScrollbarTheme::theme()->usesOverlayScrollbars(); |  | 
| 359 } |  | 
| 360 |  | 
| 361 void ScrollView::computeScrollbarExistence(bool& newHasHorizontalScrollbar, bool
      & newHasVerticalScrollbar, const IntSize& docSize, ComputeScrollbarExistenceOpti
      on option) const |  | 
| 362 { |  | 
| 363     bool hasHorizontalScrollbar = m_horizontalScrollbar; |  | 
| 364     bool hasVerticalScrollbar = m_verticalScrollbar; |  | 
| 365 |  | 
| 366     newHasHorizontalScrollbar = hasHorizontalScrollbar; |  | 
| 367     newHasVerticalScrollbar = hasVerticalScrollbar; |  | 
| 368 |  | 
| 369     ScrollbarMode hScroll = m_horizontalScrollbarMode; |  | 
| 370     ScrollbarMode vScroll = m_verticalScrollbarMode; |  | 
| 371 |  | 
| 372     if (hScroll != ScrollbarAuto) |  | 
| 373         newHasHorizontalScrollbar = (hScroll == ScrollbarAlwaysOn); |  | 
| 374     if (vScroll != ScrollbarAuto) |  | 
| 375         newHasVerticalScrollbar = (vScroll == ScrollbarAlwaysOn); |  | 
| 376 |  | 
| 377     if (m_scrollbarsSuppressed || (hScroll != ScrollbarAuto && vScroll != Scroll
      barAuto)) |  | 
| 378         return; |  | 
| 379 |  | 
| 380     if (hScroll == ScrollbarAuto) |  | 
| 381         newHasHorizontalScrollbar = docSize.width() > visibleWidth(); |  | 
| 382     if (vScroll == ScrollbarAuto) |  | 
| 383         newHasVerticalScrollbar = docSize.height() > visibleHeight(); |  | 
| 384 |  | 
| 385     if (useOverlayScrollbars()) |  | 
| 386         return; |  | 
| 387 |  | 
| 388     IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size(); |  | 
| 389 |  | 
| 390     bool attemptToRemoveScrollbars = (option == FirstPass |  | 
| 391         && docSize.width() <= fullVisibleSize.width() && docSize.height() <= ful
      lVisibleSize.height()); |  | 
| 392     if (attemptToRemoveScrollbars) { |  | 
| 393         if (hScroll == ScrollbarAuto) |  | 
| 394             newHasHorizontalScrollbar = false; |  | 
| 395         if (vScroll == ScrollbarAuto) |  | 
| 396             newHasVerticalScrollbar = false; |  | 
| 397     } |  | 
| 398 |  | 
| 399     // If we ever turn one scrollbar off, always turn the other one off too. |  | 
| 400     // Never ever try to both gain/lose a scrollbar in the same pass. |  | 
| 401     if (!newHasHorizontalScrollbar && hasHorizontalScrollbar && vScroll != Scrol
      lbarAlwaysOn) |  | 
| 402         newHasVerticalScrollbar = false; |  | 
| 403     if (!newHasVerticalScrollbar && hasVerticalScrollbar && hScroll != Scrollbar
      AlwaysOn) |  | 
| 404         newHasHorizontalScrollbar = false; |  | 
| 405 } |  | 
| 406 |  | 
| 407 void ScrollView::updateScrollbarGeometry() |  | 
| 408 { |  | 
| 409     if (m_horizontalScrollbar) { |  | 
| 410         int clientWidth = visibleWidth(); |  | 
| 411         IntRect oldRect(m_horizontalScrollbar->frameRect()); |  | 
| 412         IntRect hBarRect((shouldPlaceVerticalScrollbarOnLeft() && m_verticalScro
      llbar) ? m_verticalScrollbar->width() : 0, |  | 
| 413                         height() - m_horizontalScrollbar->height(), |  | 
| 414                         width() - (m_verticalScrollbar ? m_verticalScrollbar->wi
      dth() : 0), |  | 
| 415                         m_horizontalScrollbar->height()); |  | 
| 416         m_horizontalScrollbar->setFrameRect(adjustScrollbarRectForResizer(hBarRe
      ct, m_horizontalScrollbar.get())); |  | 
| 417         if (!m_scrollbarsSuppressed && oldRect != m_horizontalScrollbar->frameRe
      ct()) |  | 
| 418             m_horizontalScrollbar->invalidate(); |  | 
| 419 |  | 
| 420         if (m_scrollbarsSuppressed) |  | 
| 421             m_horizontalScrollbar->setSuppressInvalidation(true); |  | 
| 422         m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth); |  | 
| 423         m_horizontalScrollbar->setProportion(clientWidth, contentsWidth()); |  | 
| 424         m_horizontalScrollbar->offsetDidChange(); |  | 
| 425         if (m_scrollbarsSuppressed) |  | 
| 426             m_horizontalScrollbar->setSuppressInvalidation(false); |  | 
| 427     } |  | 
| 428 |  | 
| 429     if (m_verticalScrollbar) { |  | 
| 430         int clientHeight = visibleHeight(); |  | 
| 431         IntRect oldRect(m_verticalScrollbar->frameRect()); |  | 
| 432         IntRect vBarRect(shouldPlaceVerticalScrollbarOnLeft() ? 0 : (width() - m
      _verticalScrollbar->width()), |  | 
| 433                          0, |  | 
| 434                          m_verticalScrollbar->width(), |  | 
| 435                          height() - (m_horizontalScrollbar ? m_horizontalScrollb
      ar->height() : 0)); |  | 
| 436         m_verticalScrollbar->setFrameRect(adjustScrollbarRectForResizer(vBarRect
      , m_verticalScrollbar.get())); |  | 
| 437         if (!m_scrollbarsSuppressed && oldRect != m_verticalScrollbar->frameRect
      ()) |  | 
| 438             m_verticalScrollbar->invalidate(); |  | 
| 439 |  | 
| 440         if (m_scrollbarsSuppressed) |  | 
| 441             m_verticalScrollbar->setSuppressInvalidation(true); |  | 
| 442         m_verticalScrollbar->setEnabled(contentsHeight() > clientHeight); |  | 
| 443         m_verticalScrollbar->setProportion(clientHeight, contentsHeight()); |  | 
| 444         m_verticalScrollbar->offsetDidChange(); |  | 
| 445         if (m_scrollbarsSuppressed) |  | 
| 446             m_verticalScrollbar->setSuppressInvalidation(false); |  | 
| 447     } |  | 
| 448 } |  | 
| 449 |  | 
| 450 IntRect ScrollView::adjustScrollbarRectForResizer(const IntRect& rect, Scrollbar
      * scrollbar) |  | 
| 451 { |  | 
| 452     // Get our window resizer rect and see if we overlap. Adjust to avoid the ov
      erlap |  | 
| 453     // if necessary. |  | 
| 454     IntRect adjustedRect(rect); |  | 
| 455     bool overlapsResizer = false; |  | 
| 456     if (!rect.isEmpty() && !windowResizerRect().isEmpty()) { |  | 
| 457         IntRect resizerRect = convertFromContainingWindow(windowResizerRect()); |  | 
| 458         if (rect.intersects(resizerRect)) { |  | 
| 459             if (scrollbar->orientation() == HorizontalScrollbar) { |  | 
| 460                 int overlap = rect.maxX() - resizerRect.x(); |  | 
| 461                 if (overlap > 0 && resizerRect.maxX() >= rect.maxX()) { |  | 
| 462                     adjustedRect.setWidth(rect.width() - overlap); |  | 
| 463                     overlapsResizer = true; |  | 
| 464                 } |  | 
| 465             } else { |  | 
| 466                 int overlap = rect.maxY() - resizerRect.y(); |  | 
| 467                 if (overlap > 0 && resizerRect.maxY() >= rect.maxY()) { |  | 
| 468                     adjustedRect.setHeight(rect.height() - overlap); |  | 
| 469                     overlapsResizer = true; |  | 
| 470                 } |  | 
| 471             } |  | 
| 472         } |  | 
| 473     } |  | 
| 474     if (overlapsResizer != scrollbar->overlapsResizer()) { |  | 
| 475         scrollbar->setOverlapsResizer(overlapsResizer); |  | 
| 476         adjustScrollbarsAvoidingResizerCount(overlapsResizer ? 1 : -1); |  | 
| 477     } |  | 
| 478     return adjustedRect; |  | 
| 479 } |  | 
| 480 |  | 
| 481 bool ScrollView::adjustScrollbarExistence(ComputeScrollbarExistenceOption option
      ) |  | 
| 482 { |  | 
| 483     ASSERT(m_inUpdateScrollbars); |  | 
| 484 |  | 
| 485     // If we came in here with the view already needing a layout, then go ahead 
      and do that |  | 
| 486     // first.  (This will be the common case, e.g., when the page changes due to
       window resizing for example). |  | 
| 487     // This layout will not re-enter updateScrollbars and does not count towards
       our max layout pass total. |  | 
| 488     if (!m_scrollbarsSuppressed) |  | 
| 489         scrollbarExistenceDidChange(); |  | 
| 490 |  | 
| 491     bool hasHorizontalScrollbar = m_horizontalScrollbar; |  | 
| 492     bool hasVerticalScrollbar = m_verticalScrollbar; |  | 
| 493 |  | 
| 494     bool newHasHorizontalScrollbar = false; |  | 
| 495     bool newHasVerticalScrollbar = false; |  | 
| 496     computeScrollbarExistence(newHasHorizontalScrollbar, newHasVerticalScrollbar
      , contentsSize(), option); |  | 
| 497 |  | 
| 498     bool scrollbarExistenceChanged = hasHorizontalScrollbar != newHasHorizontalS
      crollbar || hasVerticalScrollbar != newHasVerticalScrollbar; |  | 
| 499     if (!scrollbarExistenceChanged) |  | 
| 500         return false; |  | 
| 501 |  | 
| 502     setHasHorizontalScrollbar(newHasHorizontalScrollbar); |  | 
| 503     setHasVerticalScrollbar(newHasVerticalScrollbar); |  | 
| 504 |  | 
| 505     if (m_scrollbarsSuppressed) |  | 
| 506         return true; |  | 
| 507 |  | 
| 508     if (!useOverlayScrollbars()) |  | 
| 509         contentsResized(); |  | 
| 510     scrollbarExistenceDidChange(); |  | 
| 511     return true; |  | 
| 512 } |  | 
| 513 |  | 
| 514 void ScrollView::updateScrollbars(const DoubleSize& desiredOffset) |  | 
| 515 { |  | 
| 516     if (scrollbarsDisabled()) { |  | 
| 517         setScrollOffsetFromUpdateScrollbars(desiredOffset); |  | 
| 518         return; |  | 
| 519     } |  | 
| 520 |  | 
| 521     if (m_inUpdateScrollbars) |  | 
| 522         return; |  | 
| 523     InUpdateScrollbarsScope inUpdateScrollbarsScope(this); |  | 
| 524 |  | 
| 525     IntSize oldVisibleSize = visibleSize(); |  | 
| 526 |  | 
| 527     bool scrollbarExistenceChanged = false; |  | 
| 528     int maxUpdateScrollbarsPass = useOverlayScrollbars() || m_scrollbarsSuppress
      ed ? 1 : 3; |  | 
| 529     for (int updateScrollbarsPass = 0; updateScrollbarsPass < maxUpdateScrollbar
      sPass; updateScrollbarsPass++) { |  | 
| 530         if (!adjustScrollbarExistence(updateScrollbarsPass ? Incremental : First
      Pass)) |  | 
| 531             break; |  | 
| 532         scrollbarExistenceChanged = true; |  | 
| 533     } |  | 
| 534 |  | 
| 535     updateScrollbarGeometry(); |  | 
| 536 |  | 
| 537     if (scrollbarExistenceChanged) { |  | 
| 538         // FIXME: Is frameRectsChanged really necessary here? Have any frame rec
      ts changed? |  | 
| 539         frameRectsChanged(); |  | 
| 540         positionScrollbarLayers(); |  | 
| 541         updateScrollCorner(); |  | 
| 542     } |  | 
| 543 |  | 
| 544     // FIXME: We don't need to do this if we are composited. |  | 
| 545     IntSize newVisibleSize = visibleSize(); |  | 
| 546     if (newVisibleSize.width() > oldVisibleSize.width()) { |  | 
| 547         if (shouldPlaceVerticalScrollbarOnLeft()) |  | 
| 548             invalidateRect(IntRect(0, 0, newVisibleSize.width() - oldVisibleSize
      .width(), newVisibleSize.height())); |  | 
| 549         else |  | 
| 550             invalidateRect(IntRect(oldVisibleSize.width(), 0, newVisibleSize.wid
      th() - oldVisibleSize.width(), newVisibleSize.height())); |  | 
| 551     } |  | 
| 552     if (newVisibleSize.height() > oldVisibleSize.height()) |  | 
| 553         invalidateRect(IntRect(0, oldVisibleSize.height(), newVisibleSize.width(
      ), newVisibleSize.height() - oldVisibleSize.height())); |  | 
| 554 |  | 
| 555     setScrollOffsetFromUpdateScrollbars(desiredOffset); |  | 
| 556 } |  | 
| 557 |  | 
| 558 void ScrollView::setScrollOffsetFromUpdateScrollbars(const DoubleSize& offset) |  | 
| 559 { |  | 
| 560     DoublePoint adjustedScrollPosition = DoublePoint(offset); |  | 
| 561 |  | 
| 562     if (!isRubberBandInProgress()) |  | 
| 563         adjustedScrollPosition = adjustScrollPositionWithinRange(adjustedScrollP
      osition); |  | 
| 564 |  | 
| 565     if (adjustedScrollPosition != scrollPositionDouble() || scrollOriginChanged(
      )) { |  | 
| 566         ScrollableArea::scrollToOffsetWithoutAnimation(toFloatPoint(adjustedScro
      llPosition)); |  | 
| 567         resetScrollOriginChanged(); |  | 
| 568     } |  | 
| 569 } |  | 
| 570 |  | 
| 571 const int panIconSizeLength = 16; |  | 
| 572 |  | 
| 573 IntRect ScrollView::rectToCopyOnScroll() const |  | 
| 574 { |  | 
| 575     IntRect scrollViewRect = convertToContainingWindow(IntRect((shouldPlaceVerti
      calScrollbarOnLeft() && verticalScrollbar()) ? verticalScrollbar()->width() : 0,
       0, visibleWidth(), visibleHeight())); |  | 
| 576     if (hasOverlayScrollbars()) { |  | 
| 577         int verticalScrollbarWidth = (verticalScrollbar() && !hasLayerForVertica
      lScrollbar()) ? verticalScrollbar()->width() : 0; |  | 
| 578         int horizontalScrollbarHeight = (horizontalScrollbar() && !hasLayerForHo
      rizontalScrollbar()) ? horizontalScrollbar()->height() : 0; |  | 
| 579 |  | 
| 580         scrollViewRect.setWidth(scrollViewRect.width() - verticalScrollbarWidth)
      ; |  | 
| 581         scrollViewRect.setHeight(scrollViewRect.height() - horizontalScrollbarHe
      ight); |  | 
| 582     } |  | 
| 583     return scrollViewRect; |  | 
| 584 } |  | 
| 585 |  | 
| 586 void ScrollView::scrollContentsIfNeeded() |  | 
| 587 { |  | 
| 588     if (m_pendingScrollDelta.isZero()) |  | 
| 589         return; |  | 
| 590     DoubleSize scrollDelta = m_pendingScrollDelta; |  | 
| 591     m_pendingScrollDelta = DoubleSize(); |  | 
| 592     // FIXME: Change scrollContents() to take DoubleSize. crbug.com/414283. |  | 
| 593     scrollContents(flooredIntSize(scrollDelta)); |  | 
| 594 } |  | 
| 595 |  | 
| 596 void ScrollView::scrollContents(const IntSize& scrollDelta) |  | 
| 597 { |  | 
| 598     HostWindow* window = hostWindow(); |  | 
| 599     if (!window) |  | 
| 600         return; |  | 
| 601 |  | 
| 602     IntRect clipRect = windowClipRect(); |  | 
| 603     IntRect updateRect = clipRect; |  | 
| 604     updateRect.intersect(rectToCopyOnScroll()); |  | 
| 605 |  | 
| 606     if (m_drawPanScrollIcon) { |  | 
| 607         // FIXME: the pan icon is broken when accelerated compositing is on, sin
      ce it will draw under the compositing layers. |  | 
| 608         // https://bugs.webkit.org/show_bug.cgi?id=47837 |  | 
| 609         int panIconDirtySquareSizeLength = 2 * (panIconSizeLength + std::max(abs
      (scrollDelta.width()), abs(scrollDelta.height()))); // We only want to repaint w
      hat's necessary |  | 
| 610         IntPoint panIconDirtySquareLocation = IntPoint(m_panScrollIconPoint.x() 
      - (panIconDirtySquareSizeLength / 2), m_panScrollIconPoint.y() - (panIconDirtySq
      uareSizeLength / 2)); |  | 
| 611         IntRect panScrollIconDirtyRect = IntRect(panIconDirtySquareLocation, Int
      Size(panIconDirtySquareSizeLength, panIconDirtySquareSizeLength)); |  | 
| 612         panScrollIconDirtyRect.intersect(clipRect); |  | 
| 613         window->invalidateContentsAndRootView(panScrollIconDirtyRect); |  | 
| 614     } |  | 
| 615 |  | 
| 616     if (!scrollContentsFastPath(-scrollDelta)) |  | 
| 617         scrollContentsSlowPath(updateRect); |  | 
| 618 |  | 
| 619     // Invalidate the overhang areas if they are visible. |  | 
| 620     updateOverhangAreas(); |  | 
| 621 |  | 
| 622     // This call will move children with native widgets (plugins) and invalidate
       them as well. |  | 
| 623     frameRectsChanged(); |  | 
| 624 } |  | 
| 625 |  | 
| 626 void ScrollView::scrollContentsSlowPath(const IntRect& updateRect) |  | 
| 627 { |  | 
| 628     hostWindow()->invalidateContentsForSlowScroll(updateRect); |  | 
| 629 } |  | 
| 630 |  | 
| 631 IntPoint ScrollView::rootViewToContents(const IntPoint& rootViewPoint) const |  | 
| 632 { |  | 
| 633     IntPoint viewPoint = convertFromContainingWindow(rootViewPoint); |  | 
| 634     return viewPoint + scrollOffset(); |  | 
| 635 } |  | 
| 636 |  | 
| 637 IntPoint ScrollView::contentsToRootView(const IntPoint& contentsPoint) const |  | 
| 638 { |  | 
| 639     IntPoint viewPoint = contentsPoint - scrollOffset(); |  | 
| 640     return convertToContainingWindow(viewPoint); |  | 
| 641 } |  | 
| 642 |  | 
| 643 IntRect ScrollView::rootViewToContents(const IntRect& rootViewRect) const |  | 
| 644 { |  | 
| 645     IntRect viewRect = convertFromContainingWindow(rootViewRect); |  | 
| 646     viewRect.move(scrollOffset()); |  | 
| 647     return viewRect; |  | 
| 648 } |  | 
| 649 |  | 
| 650 IntRect ScrollView::contentsToRootView(const IntRect& contentsRect) const |  | 
| 651 { |  | 
| 652     IntRect viewRect = contentsRect; |  | 
| 653     viewRect.move(-scrollOffset()); |  | 
| 654     return convertToContainingWindow(viewRect); |  | 
| 655 } |  | 
| 656 |  | 
| 657 IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const |  | 
| 658 { |  | 
| 659     IntPoint viewPoint = convertFromContainingWindow(windowPoint); |  | 
| 660     return viewPoint + scrollOffset(); |  | 
| 661 } |  | 
| 662 |  | 
| 663 FloatPoint ScrollView::windowToContents(const FloatPoint& windowPoint) const |  | 
| 664 { |  | 
| 665     FloatPoint viewPoint = convertFromContainingWindow(windowPoint); |  | 
| 666     return viewPoint + scrollOffset(); |  | 
| 667 } |  | 
| 668 |  | 
| 669 IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const |  | 
| 670 { |  | 
| 671     IntPoint viewPoint = contentsPoint - scrollOffset(); |  | 
| 672     return convertToContainingWindow(viewPoint); |  | 
| 673 } |  | 
| 674 |  | 
| 675 IntRect ScrollView::windowToContents(const IntRect& windowRect) const |  | 
| 676 { |  | 
| 677     IntRect viewRect = convertFromContainingWindow(windowRect); |  | 
| 678     viewRect.move(scrollOffset()); |  | 
| 679     return viewRect; |  | 
| 680 } |  | 
| 681 |  | 
| 682 IntRect ScrollView::contentsToWindow(const IntRect& contentsRect) const |  | 
| 683 { |  | 
| 684     IntRect viewRect = contentsRect; |  | 
| 685     viewRect.move(-scrollOffset()); |  | 
| 686     return convertToContainingWindow(viewRect); |  | 
| 687 } |  | 
| 688 |  | 
| 689 IntRect ScrollView::contentsToScreen(const IntRect& rect) const |  | 
| 690 { |  | 
| 691     HostWindow* window = hostWindow(); |  | 
| 692     if (!window) |  | 
| 693         return IntRect(); |  | 
| 694     return window->rootViewToScreen(contentsToRootView(rect)); |  | 
| 695 } |  | 
| 696 |  | 
| 697 bool ScrollView::containsScrollbarsAvoidingResizer() const |  | 
| 698 { |  | 
| 699     return !m_scrollbarsAvoidingResizer; |  | 
| 700 } |  | 
| 701 |  | 
| 702 void ScrollView::adjustScrollbarsAvoidingResizerCount(int overlapDelta) |  | 
| 703 { |  | 
| 704     int oldCount = m_scrollbarsAvoidingResizer; |  | 
| 705     m_scrollbarsAvoidingResizer += overlapDelta; |  | 
| 706     if (parent()) |  | 
| 707         toScrollView(parent())->adjustScrollbarsAvoidingResizerCount(overlapDelt
      a); |  | 
| 708     else if (!scrollbarsSuppressed()) { |  | 
| 709         // If we went from n to 0 or from 0 to n and we're the outermost view, |  | 
| 710         // we need to invalidate the windowResizerRect(), since it will now need
       to paint |  | 
| 711         // differently. |  | 
| 712         if ((oldCount > 0 && m_scrollbarsAvoidingResizer == 0) || |  | 
| 713             (oldCount == 0 && m_scrollbarsAvoidingResizer > 0)) |  | 
| 714             invalidateRect(windowResizerRect()); |  | 
| 715     } |  | 
| 716 } |  | 
| 717 |  | 
| 718 void ScrollView::setParent(Widget* parentView) |  | 
| 719 { |  | 
| 720     if (parentView == parent()) |  | 
| 721         return; |  | 
| 722 |  | 
| 723     if (m_scrollbarsAvoidingResizer && parent()) |  | 
| 724         toScrollView(parent())->adjustScrollbarsAvoidingResizerCount(-m_scrollba
      rsAvoidingResizer); |  | 
| 725 |  | 
| 726     Widget::setParent(parentView); |  | 
| 727 |  | 
| 728     if (m_scrollbarsAvoidingResizer && parent()) |  | 
| 729         toScrollView(parent())->adjustScrollbarsAvoidingResizerCount(m_scrollbar
      sAvoidingResizer); |  | 
| 730 } |  | 
| 731 |  | 
| 732 void ScrollView::setScrollbarsSuppressed(bool suppressed, bool repaintOnUnsuppre
      ss) |  | 
| 733 { |  | 
| 734     if (suppressed == m_scrollbarsSuppressed) |  | 
| 735         return; |  | 
| 736 |  | 
| 737     m_scrollbarsSuppressed = suppressed; |  | 
| 738 |  | 
| 739     if (repaintOnUnsuppress && !suppressed) { |  | 
| 740         if (m_horizontalScrollbar) |  | 
| 741             m_horizontalScrollbar->invalidate(); |  | 
| 742         if (m_verticalScrollbar) |  | 
| 743             m_verticalScrollbar->invalidate(); |  | 
| 744 |  | 
| 745         // Invalidate the scroll corner too on unsuppress. |  | 
| 746         invalidateRect(scrollCornerRect()); |  | 
| 747     } |  | 
| 748 } |  | 
| 749 |  | 
| 750 Scrollbar* ScrollView::scrollbarAtWindowPoint(const IntPoint& windowPoint) |  | 
| 751 { |  | 
| 752     IntPoint viewPoint = convertFromContainingWindow(windowPoint); |  | 
| 753     return scrollbarAtViewPoint(viewPoint); |  | 
| 754 } |  | 
| 755 |  | 
| 756 Scrollbar* ScrollView::scrollbarAtViewPoint(const IntPoint& viewPoint) |  | 
| 757 { |  | 
| 758     if (m_horizontalScrollbar && m_horizontalScrollbar->shouldParticipateInHitTe
      sting() && m_horizontalScrollbar->frameRect().contains(viewPoint)) |  | 
| 759         return m_horizontalScrollbar.get(); |  | 
| 760     if (m_verticalScrollbar && m_verticalScrollbar->shouldParticipateInHitTestin
      g() && m_verticalScrollbar->frameRect().contains(viewPoint)) |  | 
| 761         return m_verticalScrollbar.get(); |  | 
| 762     return 0; |  | 
| 763 } |  | 
| 764 |  | 
| 765 void ScrollView::setFrameRect(const IntRect& newRect) |  | 
| 766 { |  | 
| 767     IntRect oldRect = frameRect(); |  | 
| 768 |  | 
| 769     if (newRect == oldRect) |  | 
| 770         return; |  | 
| 771 |  | 
| 772     Widget::setFrameRect(newRect); |  | 
| 773 |  | 
| 774     updateScrollbars(scrollOffsetDouble()); |  | 
| 775 |  | 
| 776     frameRectsChanged(); |  | 
| 777 } |  | 
| 778 |  | 
| 779 void ScrollView::frameRectsChanged() |  | 
| 780 { |  | 
| 781     HashSet<RefPtr<Widget> >::const_iterator end = m_children.end(); |  | 
| 782     for (HashSet<RefPtr<Widget> >::const_iterator current = m_children.begin(); 
      current != end; ++current) |  | 
| 783         (*current)->frameRectsChanged(); |  | 
| 784 } |  | 
| 785 |  | 
| 786 static void positionScrollbarLayer(GraphicsLayer* graphicsLayer, Scrollbar* scro
      llbar) |  | 
| 787 { |  | 
| 788     if (!graphicsLayer || !scrollbar) |  | 
| 789         return; |  | 
| 790 |  | 
| 791     IntRect scrollbarRect = scrollbar->frameRect(); |  | 
| 792     graphicsLayer->setPosition(scrollbarRect.location()); |  | 
| 793 |  | 
| 794     if (scrollbarRect.size() == graphicsLayer->size()) |  | 
| 795         return; |  | 
| 796 |  | 
| 797     graphicsLayer->setSize(scrollbarRect.size()); |  | 
| 798 |  | 
| 799     if (graphicsLayer->hasContentsLayer()) { |  | 
| 800         graphicsLayer->setContentsRect(IntRect(0, 0, scrollbarRect.width(), scro
      llbarRect.height())); |  | 
| 801         return; |  | 
| 802     } |  | 
| 803 |  | 
| 804     graphicsLayer->setDrawsContent(true); |  | 
| 805     graphicsLayer->setNeedsDisplay(); |  | 
| 806 } |  | 
| 807 |  | 
| 808 static void positionScrollCornerLayer(GraphicsLayer* graphicsLayer, const IntRec
      t& cornerRect) |  | 
| 809 { |  | 
| 810     if (!graphicsLayer) |  | 
| 811         return; |  | 
| 812     graphicsLayer->setDrawsContent(!cornerRect.isEmpty()); |  | 
| 813     graphicsLayer->setPosition(cornerRect.location()); |  | 
| 814     if (cornerRect.size() != graphicsLayer->size()) |  | 
| 815         graphicsLayer->setNeedsDisplay(); |  | 
| 816     graphicsLayer->setSize(cornerRect.size()); |  | 
| 817 } |  | 
| 818 |  | 
| 819 void ScrollView::positionScrollbarLayers() |  | 
| 820 { |  | 
| 821     positionScrollbarLayer(layerForHorizontalScrollbar(), horizontalScrollbar())
      ; |  | 
| 822     positionScrollbarLayer(layerForVerticalScrollbar(), verticalScrollbar()); |  | 
| 823     positionScrollCornerLayer(layerForScrollCorner(), scrollCornerRect()); |  | 
| 824 } |  | 
| 825 |  | 
| 826 bool ScrollView::userInputScrollable(ScrollbarOrientation orientation) const |  | 
| 827 { |  | 
| 828     ScrollbarMode mode = (orientation == HorizontalScrollbar) ? |  | 
| 829         m_horizontalScrollbarMode : m_verticalScrollbarMode; |  | 
| 830 |  | 
| 831     return mode == ScrollbarAuto || mode == ScrollbarAlwaysOn; |  | 
| 832 } |  | 
| 833 |  | 
| 834 bool ScrollView::shouldPlaceVerticalScrollbarOnLeft() const |  | 
| 835 { |  | 
| 836     return false; |  | 
| 837 } |  | 
| 838 |  | 
| 839 void ScrollView::contentRectangleForPaintInvalidation(const IntRect& rect) |  | 
| 840 { |  | 
| 841     IntRect paintRect = rect; |  | 
| 842     if (clipsPaintInvalidations()) |  | 
| 843         paintRect.intersect(visibleContentRect()); |  | 
| 844     if (paintRect.isEmpty()) |  | 
| 845         return; |  | 
| 846 |  | 
| 847     if (HostWindow* window = hostWindow()) |  | 
| 848         window->invalidateContentsAndRootView(contentsToWindow(paintRect)); |  | 
| 849 } |  | 
| 850 |  | 
| 851 IntRect ScrollView::scrollCornerRect() const |  | 
| 852 { |  | 
| 853     IntRect cornerRect; |  | 
| 854 |  | 
| 855     if (hasOverlayScrollbars()) |  | 
| 856         return cornerRect; |  | 
| 857 |  | 
| 858     if (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0) { |  | 
| 859         cornerRect.unite(IntRect(shouldPlaceVerticalScrollbarOnLeft() ? 0 : m_ho
      rizontalScrollbar->width(), |  | 
| 860                                  height() - m_horizontalScrollbar->height(), |  | 
| 861                                  width() - m_horizontalScrollbar->width(), |  | 
| 862                                  m_horizontalScrollbar->height())); |  | 
| 863     } |  | 
| 864 |  | 
| 865     if (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0) { |  | 
| 866         cornerRect.unite(IntRect(shouldPlaceVerticalScrollbarOnLeft() ? 0 : (wid
      th() - m_verticalScrollbar->width()), |  | 
| 867                                  m_verticalScrollbar->height(), |  | 
| 868                                  m_verticalScrollbar->width(), |  | 
| 869                                  height() - m_verticalScrollbar->height())); |  | 
| 870     } |  | 
| 871 |  | 
| 872     return cornerRect; |  | 
| 873 } |  | 
| 874 |  | 
| 875 bool ScrollView::isScrollCornerVisible() const |  | 
| 876 { |  | 
| 877     return !scrollCornerRect().isEmpty(); |  | 
| 878 } |  | 
| 879 |  | 
| 880 void ScrollView::scrollbarStyleChanged() |  | 
| 881 { |  | 
| 882     adjustScrollbarOpacity(); |  | 
| 883     contentsResized(); |  | 
| 884     updateScrollbars(scrollOffsetDouble()); |  | 
| 885     positionScrollbarLayers(); |  | 
| 886 } |  | 
| 887 |  | 
| 888 void ScrollView::updateScrollCorner() |  | 
| 889 { |  | 
| 890 } |  | 
| 891 |  | 
| 892 void ScrollView::paintScrollCorner(GraphicsContext* context, const IntRect& corn
      erRect) |  | 
| 893 { |  | 
| 894     ScrollbarTheme::theme()->paintScrollCorner(context, cornerRect); |  | 
| 895 } |  | 
| 896 |  | 
| 897 void ScrollView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const 
      IntRect& rect) |  | 
| 898 { |  | 
| 899     bar->paint(context, rect); |  | 
| 900 } |  | 
| 901 |  | 
| 902 void ScrollView::invalidateScrollCornerRect(const IntRect& rect) |  | 
| 903 { |  | 
| 904     invalidateRect(rect); |  | 
| 905 } |  | 
| 906 |  | 
| 907 void ScrollView::paintScrollbars(GraphicsContext* context, const IntRect& rect) |  | 
| 908 { |  | 
| 909     if (m_horizontalScrollbar && !layerForHorizontalScrollbar()) |  | 
| 910         paintScrollbar(context, m_horizontalScrollbar.get(), rect); |  | 
| 911     if (m_verticalScrollbar && !layerForVerticalScrollbar()) |  | 
| 912         paintScrollbar(context, m_verticalScrollbar.get(), rect); |  | 
| 913 |  | 
| 914     if (layerForScrollCorner()) |  | 
| 915         return; |  | 
| 916     paintScrollCorner(context, scrollCornerRect()); |  | 
| 917 } |  | 
| 918 |  | 
| 919 void ScrollView::paintPanScrollIcon(GraphicsContext* context) |  | 
| 920 { |  | 
| 921     DEFINE_STATIC_REF(Image, panScrollIcon, (Image::loadPlatformResource("panIco
      n"))); |  | 
| 922     IntPoint iconGCPoint = m_panScrollIconPoint; |  | 
| 923     if (parent()) |  | 
| 924         iconGCPoint = toScrollView(parent())->windowToContents(iconGCPoint); |  | 
| 925     context->drawImage(panScrollIcon, iconGCPoint); |  | 
| 926 } |  | 
| 927 |  | 
| 928 void ScrollView::paint(GraphicsContext* context, const IntRect& rect) |  | 
| 929 { |  | 
| 930     notifyPageThatContentAreaWillPaint(); |  | 
| 931 |  | 
| 932     IntRect documentDirtyRect = rect; |  | 
| 933     IntRect visibleAreaWithoutScrollbars(location(), visibleContentRect().size()
      ); |  | 
| 934     documentDirtyRect.intersect(visibleAreaWithoutScrollbars); |  | 
| 935 |  | 
| 936     if (!documentDirtyRect.isEmpty()) { |  | 
| 937         GraphicsContextStateSaver stateSaver(*context); |  | 
| 938 |  | 
| 939         context->translate(x() - scrollX(), y() - scrollY()); |  | 
| 940         context->clip(visibleContentRect()); |  | 
| 941 |  | 
| 942         documentDirtyRect.moveBy(-location() + scrollPosition()); |  | 
| 943         paintContents(context, documentDirtyRect); |  | 
| 944     } |  | 
| 945 |  | 
| 946     calculateAndPaintOverhangAreas(context, rect); |  | 
| 947 |  | 
| 948     // Now paint the scrollbars. |  | 
| 949     if (!m_scrollbarsSuppressed && (m_horizontalScrollbar || m_verticalScrollbar
      )) { |  | 
| 950         GraphicsContextStateSaver stateSaver(*context); |  | 
| 951         IntRect scrollViewDirtyRect = rect; |  | 
| 952         IntRect visibleAreaWithScrollbars(location(), visibleContentRect(Include
      Scrollbars).size()); |  | 
| 953         scrollViewDirtyRect.intersect(visibleAreaWithScrollbars); |  | 
| 954         context->translate(x(), y()); |  | 
| 955         scrollViewDirtyRect.moveBy(-location()); |  | 
| 956         context->clip(IntRect(IntPoint(), visibleAreaWithScrollbars.size())); |  | 
| 957 |  | 
| 958         paintScrollbars(context, scrollViewDirtyRect); |  | 
| 959     } |  | 
| 960 |  | 
| 961     // Paint the panScroll Icon |  | 
| 962     if (m_drawPanScrollIcon) |  | 
| 963         paintPanScrollIcon(context); |  | 
| 964 } |  | 
| 965 |  | 
| 966 void ScrollView::calculateOverhangAreasForPainting(IntRect& horizontalOverhangRe
      ct, IntRect& verticalOverhangRect) |  | 
| 967 { |  | 
| 968     int verticalScrollbarWidth = (verticalScrollbar() && !verticalScrollbar()->i
      sOverlayScrollbar()) |  | 
| 969         ? verticalScrollbar()->width() : 0; |  | 
| 970     int horizontalScrollbarHeight = (horizontalScrollbar() && !horizontalScrollb
      ar()->isOverlayScrollbar()) |  | 
| 971         ? horizontalScrollbar()->height() : 0; |  | 
| 972 |  | 
| 973     int physicalScrollY = scrollPosition().y() + scrollOrigin().y(); |  | 
| 974     if (physicalScrollY < 0) { |  | 
| 975         horizontalOverhangRect = frameRect(); |  | 
| 976         horizontalOverhangRect.setHeight(-physicalScrollY); |  | 
| 977         horizontalOverhangRect.setWidth(horizontalOverhangRect.width() - vertica
      lScrollbarWidth); |  | 
| 978     } else if (contentsHeight() && physicalScrollY > contentsHeight() - visibleH
      eight()) { |  | 
| 979         int height = physicalScrollY - (contentsHeight() - visibleHeight()); |  | 
| 980         horizontalOverhangRect = frameRect(); |  | 
| 981         horizontalOverhangRect.setY(frameRect().maxY() - height - horizontalScro
      llbarHeight); |  | 
| 982         horizontalOverhangRect.setHeight(height); |  | 
| 983         horizontalOverhangRect.setWidth(horizontalOverhangRect.width() - vertica
      lScrollbarWidth); |  | 
| 984     } |  | 
| 985 |  | 
| 986     int physicalScrollX = scrollPosition().x() + scrollOrigin().x(); |  | 
| 987     if (physicalScrollX < 0) { |  | 
| 988         verticalOverhangRect.setWidth(-physicalScrollX); |  | 
| 989         verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhang
      Rect.height() - horizontalScrollbarHeight); |  | 
| 990         verticalOverhangRect.setX(frameRect().x()); |  | 
| 991         if (horizontalOverhangRect.y() == frameRect().y()) |  | 
| 992             verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.h
      eight()); |  | 
| 993         else |  | 
| 994             verticalOverhangRect.setY(frameRect().y()); |  | 
| 995     } else if (contentsWidth() && physicalScrollX > contentsWidth() - visibleWid
      th()) { |  | 
| 996         int width = physicalScrollX - (contentsWidth() - visibleWidth()); |  | 
| 997         verticalOverhangRect.setWidth(width); |  | 
| 998         verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhang
      Rect.height() - horizontalScrollbarHeight); |  | 
| 999         verticalOverhangRect.setX(frameRect().maxX() - width - verticalScrollbar
      Width); |  | 
| 1000         if (horizontalOverhangRect.y() == frameRect().y()) |  | 
| 1001             verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.h
      eight()); |  | 
| 1002         else |  | 
| 1003             verticalOverhangRect.setY(frameRect().y()); |  | 
| 1004     } |  | 
| 1005 } |  | 
| 1006 |  | 
| 1007 void ScrollView::updateOverhangAreas() |  | 
| 1008 { |  | 
| 1009     HostWindow* window = hostWindow(); |  | 
| 1010     if (!window) |  | 
| 1011         return; |  | 
| 1012 |  | 
| 1013     IntRect horizontalOverhangRect; |  | 
| 1014     IntRect verticalOverhangRect; |  | 
| 1015     calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRe
      ct); |  | 
| 1016     if (!horizontalOverhangRect.isEmpty()) |  | 
| 1017         window->invalidateContentsAndRootView(horizontalOverhangRect); |  | 
| 1018     if (!verticalOverhangRect.isEmpty()) |  | 
| 1019         window->invalidateContentsAndRootView(verticalOverhangRect); |  | 
| 1020 } |  | 
| 1021 |  | 
| 1022 void ScrollView::paintOverhangAreas(GraphicsContext* context, const IntRect& hor
      izontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRe
      ct) |  | 
| 1023 { |  | 
| 1024     ScrollbarTheme::theme()->paintOverhangBackground(context, horizontalOverhang
      Rect, verticalOverhangRect, dirtyRect); |  | 
| 1025     ScrollbarTheme::theme()->paintOverhangShadows(context, scrollOffset(), horiz
      ontalOverhangRect, verticalOverhangRect, dirtyRect); |  | 
| 1026 } |  | 
| 1027 |  | 
| 1028 void ScrollView::calculateAndPaintOverhangAreas(GraphicsContext* context, const 
      IntRect& dirtyRect) |  | 
| 1029 { |  | 
| 1030     IntRect horizontalOverhangRect; |  | 
| 1031     IntRect verticalOverhangRect; |  | 
| 1032     calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRe
      ct); |  | 
| 1033 |  | 
| 1034     if (dirtyRect.intersects(horizontalOverhangRect) || dirtyRect.intersects(ver
      ticalOverhangRect)) |  | 
| 1035         paintOverhangAreas(context, horizontalOverhangRect, verticalOverhangRect
      , dirtyRect); |  | 
| 1036 } |  | 
| 1037 |  | 
| 1038 void ScrollView::calculateAndPaintOverhangBackground(GraphicsContext* context, c
      onst IntRect& dirtyRect) |  | 
| 1039 { |  | 
| 1040     IntRect horizontalOverhangRect; |  | 
| 1041     IntRect verticalOverhangRect; |  | 
| 1042     calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRe
      ct); |  | 
| 1043 |  | 
| 1044     if (dirtyRect.intersects(horizontalOverhangRect) || dirtyRect.intersects(ver
      ticalOverhangRect)) |  | 
| 1045         ScrollbarTheme::theme()->paintOverhangBackground(context, horizontalOver
      hangRect, verticalOverhangRect, dirtyRect); |  | 
| 1046 } |  | 
| 1047 |  | 
| 1048 bool ScrollView::isPointInScrollbarCorner(const IntPoint& windowPoint) |  | 
| 1049 { |  | 
| 1050     if (!scrollbarCornerPresent()) |  | 
| 1051         return false; |  | 
| 1052 |  | 
| 1053     IntPoint viewPoint = convertFromContainingWindow(windowPoint); |  | 
| 1054 |  | 
| 1055     if (m_horizontalScrollbar) { |  | 
| 1056         int horizontalScrollbarYMin = m_horizontalScrollbar->frameRect().y(); |  | 
| 1057         int horizontalScrollbarYMax = m_horizontalScrollbar->frameRect().y() + m
      _horizontalScrollbar->frameRect().height(); |  | 
| 1058         int horizontalScrollbarXMin = m_horizontalScrollbar->frameRect().x() + m
      _horizontalScrollbar->frameRect().width(); |  | 
| 1059 |  | 
| 1060         return viewPoint.y() > horizontalScrollbarYMin && viewPoint.y() < horizo
      ntalScrollbarYMax && viewPoint.x() > horizontalScrollbarXMin; |  | 
| 1061     } |  | 
| 1062 |  | 
| 1063     int verticalScrollbarXMin = m_verticalScrollbar->frameRect().x(); |  | 
| 1064     int verticalScrollbarXMax = m_verticalScrollbar->frameRect().x() + m_vertica
      lScrollbar->frameRect().width(); |  | 
| 1065     int verticalScrollbarYMin = m_verticalScrollbar->frameRect().y() + m_vertica
      lScrollbar->frameRect().height(); |  | 
| 1066 |  | 
| 1067     return viewPoint.x() > verticalScrollbarXMin && viewPoint.x() < verticalScro
      llbarXMax && viewPoint.y() > verticalScrollbarYMin; |  | 
| 1068 } |  | 
| 1069 |  | 
| 1070 bool ScrollView::scrollbarCornerPresent() const |  | 
| 1071 { |  | 
| 1072     return (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 
      0) |  | 
| 1073         || (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0)
      ; |  | 
| 1074 } |  | 
| 1075 |  | 
| 1076 IntRect ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scroll
      bar, const IntRect& localRect) const |  | 
| 1077 { |  | 
| 1078     // Scrollbars won't be transformed within us |  | 
| 1079     IntRect newRect = localRect; |  | 
| 1080     newRect.moveBy(scrollbar->location()); |  | 
| 1081     return newRect; |  | 
| 1082 } |  | 
| 1083 |  | 
| 1084 IntRect ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scroll
      bar, const IntRect& parentRect) const |  | 
| 1085 { |  | 
| 1086     IntRect newRect = parentRect; |  | 
| 1087     // Scrollbars won't be transformed within us |  | 
| 1088     newRect.moveBy(-scrollbar->location()); |  | 
| 1089     return newRect; |  | 
| 1090 } |  | 
| 1091 |  | 
| 1092 // FIXME: test these on windows |  | 
| 1093 IntPoint ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrol
      lbar, const IntPoint& localPoint) const |  | 
| 1094 { |  | 
| 1095     // Scrollbars won't be transformed within us |  | 
| 1096     IntPoint newPoint = localPoint; |  | 
| 1097     newPoint.moveBy(scrollbar->location()); |  | 
| 1098     return newPoint; |  | 
| 1099 } |  | 
| 1100 |  | 
| 1101 IntPoint ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrol
      lbar, const IntPoint& parentPoint) const |  | 
| 1102 { |  | 
| 1103     IntPoint newPoint = parentPoint; |  | 
| 1104     // Scrollbars won't be transformed within us |  | 
| 1105     newPoint.moveBy(-scrollbar->location()); |  | 
| 1106     return newPoint; |  | 
| 1107 } |  | 
| 1108 |  | 
| 1109 void ScrollView::setParentVisible(bool visible) |  | 
| 1110 { |  | 
| 1111     if (isParentVisible() == visible) |  | 
| 1112         return; |  | 
| 1113 |  | 
| 1114     Widget::setParentVisible(visible); |  | 
| 1115 |  | 
| 1116     if (!isSelfVisible()) |  | 
| 1117         return; |  | 
| 1118 |  | 
| 1119     HashSet<RefPtr<Widget> >::iterator end = m_children.end(); |  | 
| 1120     for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; 
      ++it) |  | 
| 1121         (*it)->setParentVisible(visible); |  | 
| 1122 } |  | 
| 1123 |  | 
| 1124 void ScrollView::show() |  | 
| 1125 { |  | 
| 1126     if (!isSelfVisible()) { |  | 
| 1127         setSelfVisible(true); |  | 
| 1128         if (isParentVisible()) { |  | 
| 1129             HashSet<RefPtr<Widget> >::iterator end = m_children.end(); |  | 
| 1130             for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it 
      != end; ++it) |  | 
| 1131                 (*it)->setParentVisible(true); |  | 
| 1132         } |  | 
| 1133     } |  | 
| 1134 |  | 
| 1135     Widget::show(); |  | 
| 1136 } |  | 
| 1137 |  | 
| 1138 void ScrollView::hide() |  | 
| 1139 { |  | 
| 1140     if (isSelfVisible()) { |  | 
| 1141         if (isParentVisible()) { |  | 
| 1142             HashSet<RefPtr<Widget> >::iterator end = m_children.end(); |  | 
| 1143             for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it 
      != end; ++it) |  | 
| 1144                 (*it)->setParentVisible(false); |  | 
| 1145         } |  | 
| 1146         setSelfVisible(false); |  | 
| 1147     } |  | 
| 1148 |  | 
| 1149     Widget::hide(); |  | 
| 1150 } |  | 
| 1151 |  | 
| 1152 void ScrollView::addPanScrollIcon(const IntPoint& iconPosition) |  | 
| 1153 { |  | 
| 1154     HostWindow* window = hostWindow(); |  | 
| 1155     if (!window) |  | 
| 1156         return; |  | 
| 1157     m_drawPanScrollIcon = true; |  | 
| 1158     m_panScrollIconPoint = IntPoint(iconPosition.x() - panIconSizeLength / 2 , i
      conPosition.y() - panIconSizeLength / 2) ; |  | 
| 1159     window->invalidateContentsAndRootView(IntRect(m_panScrollIconPoint, IntSize(
      panIconSizeLength, panIconSizeLength))); |  | 
| 1160 } |  | 
| 1161 |  | 
| 1162 void ScrollView::removePanScrollIcon() |  | 
| 1163 { |  | 
| 1164     HostWindow* window = hostWindow(); |  | 
| 1165     if (!window) |  | 
| 1166         return; |  | 
| 1167     m_drawPanScrollIcon = false; |  | 
| 1168     window->invalidateContentsAndRootView(IntRect(m_panScrollIconPoint, IntSize(
      panIconSizeLength, panIconSizeLength))); |  | 
| 1169 } |  | 
| 1170 |  | 
| 1171 void ScrollView::setScrollOrigin(const IntPoint& origin, bool updatePositionAtAl
      l, bool updatePositionSynchronously) |  | 
| 1172 { |  | 
| 1173     if (scrollOrigin() == origin) |  | 
| 1174         return; |  | 
| 1175 |  | 
| 1176     ScrollableArea::setScrollOrigin(origin); |  | 
| 1177 |  | 
| 1178     // Update if the scroll origin changes, since our position will be different
       if the content size did not change. |  | 
| 1179     if (updatePositionAtAll && updatePositionSynchronously) |  | 
| 1180         updateScrollbars(scrollOffsetDouble()); |  | 
| 1181 } |  | 
| 1182 |  | 
| 1183 } // namespace blink |  | 
| OLD | NEW | 
|---|