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