2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "ScrollView.h"
29 #include "GraphicsContext.h"
30 #include "GraphicsLayer.h"
31 #include "HostWindow.h"
32 #include "PlatformMouseEvent.h"
33 #include "PlatformWheelEvent.h"
34 #include "ScrollAnimator.h"
35 #include "Scrollbar.h"
36 #include "ScrollbarTheme.h"
37 #include <wtf/StdLibExtras.h>
43 ScrollView::ScrollView()
44 : m_horizontalScrollbarMode(ScrollbarAuto)
45 , m_verticalScrollbarMode(ScrollbarAuto)
46 , m_horizontalScrollbarLock(false)
47 , m_verticalScrollbarLock(false)
48 , m_prohibitsScrolling(false)
49 , m_canBlitOnScroll(true)
50 , m_scrollbarsAvoidingResizer(0)
51 , m_scrollbarsSuppressed(false)
52 , m_inUpdateScrollbars(false)
53 , m_updateScrollbarsPass(0)
54 , m_drawPanScrollIcon(false)
55 , m_useFixedLayout(false)
56 , m_paintsEntireContents(false)
57 , m_clipsRepaints(true)
58 , m_delegatesScrolling(false)
62 ScrollView::~ScrollView()
66 void ScrollView::addChild(PassRefPtr<Widget> prpChild)
68 Widget* child = prpChild.get();
69 ASSERT(child != this && !child->parent());
70 child->setParent(this);
71 m_children.add(prpChild);
72 if (child->platformWidget())
73 platformAddChild(child);
76 void ScrollView::removeChild(Widget* child)
78 ASSERT(child->parent() == this);
80 m_children.remove(child);
81 if (child->platformWidget())
82 platformRemoveChild(child);
85 bool ScrollView::setHasHorizontalScrollbar(bool hasBar, bool* contentSizeAffected)
87 ASSERT(!hasBar || !avoidScrollbarCreation());
88 if (hasBar && !m_horizontalScrollbar) {
89 m_horizontalScrollbar = createScrollbar(HorizontalScrollbar);
90 addChild(m_horizontalScrollbar.get());
91 didAddScrollbar(m_horizontalScrollbar.get(), HorizontalScrollbar);
92 m_horizontalScrollbar->styleChanged();
93 if (contentSizeAffected)
94 *contentSizeAffected = !m_horizontalScrollbar->isOverlayScrollbar();
98 if (!hasBar && m_horizontalScrollbar) {
99 bool wasOverlayScrollbar = m_horizontalScrollbar->isOverlayScrollbar();
100 willRemoveScrollbar(m_horizontalScrollbar.get(), HorizontalScrollbar);
101 removeChild(m_horizontalScrollbar.get());
102 m_horizontalScrollbar = 0;
103 if (contentSizeAffected)
104 *contentSizeAffected = !wasOverlayScrollbar;
111 bool ScrollView::setHasVerticalScrollbar(bool hasBar, bool* contentSizeAffected)
113 ASSERT(!hasBar || !avoidScrollbarCreation());
114 if (hasBar && !m_verticalScrollbar) {
115 m_verticalScrollbar = createScrollbar(VerticalScrollbar);
116 addChild(m_verticalScrollbar.get());
117 didAddScrollbar(m_verticalScrollbar.get(), VerticalScrollbar);
118 m_verticalScrollbar->styleChanged();
119 if (contentSizeAffected)
120 *contentSizeAffected = !m_verticalScrollbar->isOverlayScrollbar();
124 if (!hasBar && m_verticalScrollbar) {
125 bool wasOverlayScrollbar = m_verticalScrollbar->isOverlayScrollbar();
126 willRemoveScrollbar(m_verticalScrollbar.get(), VerticalScrollbar);
127 removeChild(m_verticalScrollbar.get());
128 m_verticalScrollbar = 0;
129 if (contentSizeAffected)
130 *contentSizeAffected = !wasOverlayScrollbar;
138 PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientation)
140 return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
143 void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode,
144 bool horizontalLock, bool verticalLock)
146 bool needsUpdate = false;
148 if (horizontalMode != horizontalScrollbarMode() && !m_horizontalScrollbarLock) {
149 m_horizontalScrollbarMode = horizontalMode;
153 if (verticalMode != verticalScrollbarMode() && !m_verticalScrollbarLock) {
154 m_verticalScrollbarMode = verticalMode;
159 setHorizontalScrollbarLock();
162 setVerticalScrollbarLock();
167 if (platformWidget())
168 platformSetScrollbarModes();
170 updateScrollbars(scrollOffset());
174 void ScrollView::scrollbarModes(ScrollbarMode& horizontalMode, ScrollbarMode& verticalMode) const
176 if (platformWidget()) {
177 platformScrollbarModes(horizontalMode, verticalMode);
180 horizontalMode = m_horizontalScrollbarMode;
181 verticalMode = m_verticalScrollbarMode;
184 void ScrollView::setCanHaveScrollbars(bool canScroll)
186 ScrollbarMode newHorizontalMode;
187 ScrollbarMode newVerticalMode;
189 scrollbarModes(newHorizontalMode, newVerticalMode);
191 if (canScroll && newVerticalMode == ScrollbarAlwaysOff)
192 newVerticalMode = ScrollbarAuto;
194 newVerticalMode = ScrollbarAlwaysOff;
196 if (canScroll && newHorizontalMode == ScrollbarAlwaysOff)
197 newHorizontalMode = ScrollbarAuto;
199 newHorizontalMode = ScrollbarAlwaysOff;
201 setScrollbarModes(newHorizontalMode, newVerticalMode);
204 void ScrollView::setCanBlitOnScroll(bool b)
206 if (platformWidget()) {
207 platformSetCanBlitOnScroll(b);
211 m_canBlitOnScroll = b;
214 bool ScrollView::canBlitOnScroll() const
216 if (platformWidget())
217 return platformCanBlitOnScroll();
219 return m_canBlitOnScroll;
222 void ScrollView::setPaintsEntireContents(bool paintsEntireContents)
224 m_paintsEntireContents = paintsEntireContents;
227 void ScrollView::setClipsRepaints(bool clipsRepaints)
229 m_clipsRepaints = clipsRepaints;
232 void ScrollView::setDelegatesScrolling(bool delegatesScrolling)
234 if (m_delegatesScrolling == delegatesScrolling)
237 m_delegatesScrolling = delegatesScrolling;
238 delegatesScrollingDidChange();
241 IntSize ScrollView::unscaledVisibleContentSize(VisibleContentRectIncludesScrollbars scrollbarInclusion) const
243 if (platformWidget())
244 return platformVisibleContentSize(scrollbarInclusion == IncludeScrollbars);
246 if (!m_fixedVisibleContentRect.isEmpty())
247 return m_fixedVisibleContentRect.size();
249 int verticalScrollbarWidth = 0;
250 int horizontalScrollbarHeight = 0;
252 if (scrollbarInclusion == ExcludeScrollbars) {
253 if (Scrollbar* verticalBar = verticalScrollbar())
254 verticalScrollbarWidth = !verticalBar->isOverlayScrollbar() ? verticalBar->width() : 0;
255 if (Scrollbar* horizontalBar = horizontalScrollbar())
256 horizontalScrollbarHeight = !horizontalBar->isOverlayScrollbar() ? horizontalBar->height() : 0;
259 return IntSize(max(0, width() - verticalScrollbarWidth),
260 max(0, height() - horizontalScrollbarHeight));
264 IntRect ScrollView::visibleContentRect(VisibleContentRectIncludesScrollbars scollbarInclusion) const
266 if (platformWidget())
267 return platformVisibleContentRect(scollbarInclusion == IncludeScrollbars);
269 if (!m_fixedVisibleContentRect.isEmpty())
270 return m_fixedVisibleContentRect;
272 FloatSize visibleContentSize = unscaledVisibleContentSize(scollbarInclusion);
273 visibleContentSize.scale(1 / visibleContentScaleFactor());
274 return IntRect(IntPoint(m_scrollOffset), expandedIntSize(visibleContentSize));
278 IntSize ScrollView::layoutSize() const
280 return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? unscaledVisibleContentSize(ExcludeScrollbars) : m_fixedLayoutSize;
283 IntSize ScrollView::fixedLayoutSize() const
285 return m_fixedLayoutSize;
288 void ScrollView::setFixedLayoutSize(const IntSize& newSize)
290 if (fixedLayoutSize() == newSize)
292 m_fixedLayoutSize = newSize;
293 if (m_useFixedLayout)
294 fixedLayoutSizeChanged();
297 bool ScrollView::useFixedLayout() const
299 return m_useFixedLayout;
302 void ScrollView::setUseFixedLayout(bool enable)
304 if (useFixedLayout() == enable)
306 m_useFixedLayout = enable;
307 if (!m_fixedLayoutSize.isEmpty())
308 fixedLayoutSizeChanged();
311 void ScrollView::fixedLayoutSizeChanged()
313 updateScrollbars(scrollOffset());
317 IntSize ScrollView::contentsSize() const
319 return m_contentsSize;
322 void ScrollView::setContentsSize(const IntSize& newSize)
324 if (contentsSize() == newSize)
326 m_contentsSize = newSize;
327 if (platformWidget())
328 platformSetContentsSize();
330 updateScrollbars(scrollOffset());
331 updateOverhangAreas();
334 IntPoint ScrollView::maximumScrollPosition() const
336 IntPoint maximumOffset(contentsWidth() - visibleWidth() - scrollOrigin().x(), totalContentsSize().height() - visibleHeight() - scrollOrigin().y());
337 maximumOffset.clampNegativeToZero();
338 return maximumOffset;
341 IntPoint ScrollView::minimumScrollPosition() const
343 return IntPoint(-scrollOrigin().x(), -scrollOrigin().y());
346 IntPoint ScrollView::adjustScrollPositionWithinRange(const IntPoint& scrollPoint) const
348 if (!constrainsScrollingToContentEdge())
351 IntPoint newScrollPosition = scrollPoint.shrunkTo(maximumScrollPosition());
352 newScrollPosition = newScrollPosition.expandedTo(minimumScrollPosition());
353 return newScrollPosition;
356 IntSize ScrollView::scrollOffsetRelativeToDocument() const
358 IntSize scrollOffset = this->scrollOffset();
359 return IntSize(scrollOffset.width(), scrollOffset.height() - headerHeight());
362 IntPoint ScrollView::scrollPositionRelativeToDocument() const
364 IntPoint scrollPosition = this->scrollPosition();
365 return IntPoint(scrollPosition.x(), scrollPosition.y() - headerHeight());
368 int ScrollView::scrollSize(ScrollbarOrientation orientation) const
370 // If no scrollbars are present, it does not indicate content is not be scrollable.
371 if (!m_horizontalScrollbar && !m_verticalScrollbar && !prohibitsScrolling()) {
372 IntSize scrollSize = m_contentsSize - visibleContentRect().size();
373 scrollSize.clampNegativeToZero();
374 return orientation == HorizontalScrollbar ? scrollSize.width() : scrollSize.height();
377 Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_horizontalScrollbar : m_verticalScrollbar).get();
378 return scrollbar ? (scrollbar->totalSize() - scrollbar->visibleSize()) : 0;
381 void ScrollView::notifyPageThatContentAreaWillPaint() const
385 void ScrollView::setScrollOffset(const IntPoint& offset)
387 int horizontalOffset = offset.x();
388 int verticalOffset = offset.y();
389 if (constrainsScrollingToContentEdge()) {
390 horizontalOffset = max(min(horizontalOffset, contentsWidth() - visibleWidth()), 0);
391 verticalOffset = max(min(verticalOffset, totalContentsSize().height() - visibleHeight()), 0);
394 IntSize newOffset = m_scrollOffset;
395 newOffset.setWidth(horizontalOffset - scrollOrigin().x());
396 newOffset.setHeight(verticalOffset - scrollOrigin().y());
401 void ScrollView::scrollTo(const IntSize& newOffset)
403 IntSize scrollDelta = newOffset - m_scrollOffset;
404 if (scrollDelta == IntSize())
406 m_scrollOffset = newOffset;
408 if (scrollbarsSuppressed())
411 #if USE(TILED_BACKING_STORE)
412 if (delegatesScrolling()) {
413 hostWindow()->delegatedScrollRequested(IntPoint(newOffset));
417 repaintFixedElementsAfterScrolling();
418 scrollContents(scrollDelta);
419 updateFixedElementsAfterScrolling();
422 int ScrollView::scrollPosition(Scrollbar* scrollbar) const
424 if (scrollbar->orientation() == HorizontalScrollbar)
425 return scrollPosition().x() + scrollOrigin().x();
426 if (scrollbar->orientation() == VerticalScrollbar)
427 return scrollPosition().y() + scrollOrigin().y();
431 void ScrollView::setScrollPosition(const IntPoint& scrollPoint)
433 if (prohibitsScrolling())
436 if (platformWidget()) {
437 platformSetScrollPosition(scrollPoint);
441 #if USE(TILED_BACKING_STORE)
442 if (delegatesScrolling()) {
443 hostWindow()->delegatedScrollRequested(scrollPoint);
448 IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint);
450 if (newScrollPosition == scrollPosition())
453 if (requestScrollPositionUpdate(newScrollPosition))
456 updateScrollbars(IntSize(newScrollPosition.x(), newScrollPosition.y()));
459 bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity)
461 if (platformWidget())
462 return platformScroll(direction, granularity);
464 return ScrollableArea::scroll(direction, granularity);
467 bool ScrollView::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity)
469 return scroll(logicalToPhysical(direction, isVerticalDocument(), isFlippedDocument()), granularity);
472 IntSize ScrollView::overhangAmount() const
476 int physicalScrollY = scrollPosition().y() + scrollOrigin().y();
477 if (physicalScrollY < 0)
478 stretch.setHeight(physicalScrollY);
479 else if (totalContentsSize().height() && physicalScrollY > totalContentsSize().height() - visibleHeight())
480 stretch.setHeight(physicalScrollY - (totalContentsSize().height() - visibleHeight()));
482 int physicalScrollX = scrollPosition().x() + scrollOrigin().x();
483 if (physicalScrollX < 0)
484 stretch.setWidth(physicalScrollX);
485 else if (contentsWidth() && physicalScrollX > contentsWidth() - visibleWidth())
486 stretch.setWidth(physicalScrollX - (contentsWidth() - visibleWidth()));
491 void ScrollView::windowResizerRectChanged()
493 if (platformWidget())
496 updateScrollbars(scrollOffset());
499 static const unsigned cMaxUpdateScrollbarsPass = 2;
501 void ScrollView::updateScrollbars(const IntSize& desiredOffset)
503 if (m_inUpdateScrollbars || prohibitsScrolling() || platformWidget())
506 // If we came in here with the view already needing a layout, then go ahead and do that
507 // first. (This will be the common case, e.g., when the page changes due to window resizing for example).
508 // This layout will not re-enter updateScrollbars and does not count towards our max layout pass total.
509 if (!m_scrollbarsSuppressed) {
510 m_inUpdateScrollbars = true;
511 visibleContentsResized();
512 m_inUpdateScrollbars = false;
515 IntRect oldScrollCornerRect = scrollCornerRect();
517 bool hasHorizontalScrollbar = m_horizontalScrollbar;
518 bool hasVerticalScrollbar = m_verticalScrollbar;
520 bool newHasHorizontalScrollbar = hasHorizontalScrollbar;
521 bool newHasVerticalScrollbar = hasVerticalScrollbar;
523 ScrollbarMode hScroll = m_horizontalScrollbarMode;
524 ScrollbarMode vScroll = m_verticalScrollbarMode;
526 if (hScroll != ScrollbarAuto)
527 newHasHorizontalScrollbar = (hScroll == ScrollbarAlwaysOn);
528 if (vScroll != ScrollbarAuto)
529 newHasVerticalScrollbar = (vScroll == ScrollbarAlwaysOn);
531 bool scrollbarAddedOrRemoved = false;
533 if (m_scrollbarsSuppressed || (hScroll != ScrollbarAuto && vScroll != ScrollbarAuto)) {
534 if (hasHorizontalScrollbar != newHasHorizontalScrollbar && (hasHorizontalScrollbar || !avoidScrollbarCreation())) {
535 if (setHasHorizontalScrollbar(newHasHorizontalScrollbar))
536 scrollbarAddedOrRemoved = true;
539 if (hasVerticalScrollbar != newHasVerticalScrollbar && (hasVerticalScrollbar || !avoidScrollbarCreation())) {
540 if (setHasVerticalScrollbar(newHasVerticalScrollbar))
541 scrollbarAddedOrRemoved = true;
544 bool sendContentResizedNotification = false;
546 IntSize docSize = totalContentsSize();
547 IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size();
549 if (hScroll == ScrollbarAuto) {
550 newHasHorizontalScrollbar = docSize.width() > visibleWidth();
551 if (newHasHorizontalScrollbar && !m_updateScrollbarsPass && docSize.width() <= fullVisibleSize.width() && docSize.height() <= fullVisibleSize.height())
552 newHasHorizontalScrollbar = false;
554 if (vScroll == ScrollbarAuto) {
555 newHasVerticalScrollbar = docSize.height() > visibleHeight();
556 if (newHasVerticalScrollbar && !m_updateScrollbarsPass && docSize.width() <= fullVisibleSize.width() && docSize.height() <= fullVisibleSize.height())
557 newHasVerticalScrollbar = false;
560 // If we ever turn one scrollbar off, always turn the other one off too. Never ever
561 // try to both gain/lose a scrollbar in the same pass.
562 if (!newHasHorizontalScrollbar && hasHorizontalScrollbar && vScroll != ScrollbarAlwaysOn)
563 newHasVerticalScrollbar = false;
564 if (!newHasVerticalScrollbar && hasVerticalScrollbar && hScroll != ScrollbarAlwaysOn)
565 newHasHorizontalScrollbar = false;
567 if (hasHorizontalScrollbar != newHasHorizontalScrollbar && (hasHorizontalScrollbar || !avoidScrollbarCreation())) {
568 if (scrollOrigin().y() && !newHasHorizontalScrollbar)
569 ScrollableArea::setScrollOrigin(IntPoint(scrollOrigin().x(), scrollOrigin().y() - m_horizontalScrollbar->height()));
570 if (m_horizontalScrollbar)
571 m_horizontalScrollbar->invalidate();
573 bool changeAffectsContentSize = false;
574 if (setHasHorizontalScrollbar(newHasHorizontalScrollbar, &changeAffectsContentSize)) {
575 scrollbarAddedOrRemoved = true;
576 sendContentResizedNotification |= changeAffectsContentSize;
580 if (hasVerticalScrollbar != newHasVerticalScrollbar && (hasVerticalScrollbar || !avoidScrollbarCreation())) {
581 if (scrollOrigin().x() && !newHasVerticalScrollbar)
582 ScrollableArea::setScrollOrigin(IntPoint(scrollOrigin().x() - m_verticalScrollbar->width(), scrollOrigin().y()));
583 if (m_verticalScrollbar)
584 m_verticalScrollbar->invalidate();
586 bool changeAffectsContentSize = false;
587 if (setHasVerticalScrollbar(newHasVerticalScrollbar, &changeAffectsContentSize)) {
588 scrollbarAddedOrRemoved = true;
589 sendContentResizedNotification |= changeAffectsContentSize;
593 if (sendContentResizedNotification && m_updateScrollbarsPass < cMaxUpdateScrollbarsPass) {
594 m_updateScrollbarsPass++;
596 visibleContentsResized();
597 IntSize newDocSize = totalContentsSize();
598 if (newDocSize == docSize) {
599 // The layout with the new scroll state had no impact on
600 // the document's overall size, so updateScrollbars didn't get called.
602 updateScrollbars(desiredOffset);
604 m_updateScrollbarsPass--;
607 if (scrollbarAddedOrRemoved)
608 addedOrRemovedScrollbar();
611 // Set up the range (and page step/line step), but only do this if we're not in a nested call (to avoid
612 // doing it multiple times).
613 if (m_updateScrollbarsPass)
616 m_inUpdateScrollbars = true;
618 if (m_horizontalScrollbar) {
619 int clientWidth = visibleWidth();
620 int pageStep = max(max<int>(clientWidth * Scrollbar::minFractionToStepWhenPaging(), clientWidth - Scrollbar::maxOverlapBetweenPages()), 1);
621 IntRect oldRect(m_horizontalScrollbar->frameRect());
623 height() - m_horizontalScrollbar->height(),
624 width() - (m_verticalScrollbar ? m_verticalScrollbar->width() : 0),
625 m_horizontalScrollbar->height());
626 m_horizontalScrollbar->setFrameRect(hBarRect);
627 if (!m_scrollbarsSuppressed && oldRect != m_horizontalScrollbar->frameRect())
628 m_horizontalScrollbar->invalidate();
630 if (m_scrollbarsSuppressed)
631 m_horizontalScrollbar->setSuppressInvalidation(true);
632 m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth);
633 m_horizontalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
634 m_horizontalScrollbar->setProportion(clientWidth, contentsWidth());
635 if (m_scrollbarsSuppressed)
636 m_horizontalScrollbar->setSuppressInvalidation(false);
639 if (m_verticalScrollbar) {
640 int clientHeight = visibleHeight();
641 int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1);
642 IntRect oldRect(m_verticalScrollbar->frameRect());
643 IntRect vBarRect(width() - m_verticalScrollbar->width(),
645 m_verticalScrollbar->width(),
646 height() - (m_horizontalScrollbar ? m_horizontalScrollbar->height() : 0));
647 m_verticalScrollbar->setFrameRect(vBarRect);
648 if (!m_scrollbarsSuppressed && oldRect != m_verticalScrollbar->frameRect())
649 m_verticalScrollbar->invalidate();
651 if (m_scrollbarsSuppressed)
652 m_verticalScrollbar->setSuppressInvalidation(true);
653 m_verticalScrollbar->setEnabled(totalContentsSize().height() > clientHeight);
654 m_verticalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
655 m_verticalScrollbar->setProportion(clientHeight, totalContentsSize().height());
656 if (m_scrollbarsSuppressed)
657 m_verticalScrollbar->setSuppressInvalidation(false);
660 if (hasHorizontalScrollbar != newHasHorizontalScrollbar || hasVerticalScrollbar != newHasVerticalScrollbar) {
661 // FIXME: Is frameRectsChanged really necessary here? Have any frame rects changed?
663 positionScrollbarLayers();
664 updateScrollCorner();
665 if (!m_horizontalScrollbar && !m_verticalScrollbar)
666 invalidateScrollCornerRect(oldScrollCornerRect);
669 IntPoint adjustedScrollPosition = IntPoint(desiredOffset);
670 if (!isRubberBandInProgress())
671 adjustedScrollPosition = adjustScrollPositionWithinRange(adjustedScrollPosition);
673 if (adjustedScrollPosition != scrollPosition() || scrollOriginChanged()) {
674 ScrollableArea::scrollToOffsetWithoutAnimation(adjustedScrollPosition + toIntSize(scrollOrigin()));
675 resetScrollOriginChanged();
678 // Make sure the scrollbar offsets are up to date.
679 if (m_horizontalScrollbar)
680 m_horizontalScrollbar->offsetDidChange();
681 if (m_verticalScrollbar)
682 m_verticalScrollbar->offsetDidChange();
684 m_inUpdateScrollbars = false;
687 const int panIconSizeLength = 16;
689 IntRect ScrollView::rectToCopyOnScroll() const
691 IntRect scrollViewRect = convertToRootView(IntRect(0, 0, visibleWidth(), visibleHeight()));
692 if (hasOverlayScrollbars()) {
693 int verticalScrollbarWidth = (verticalScrollbar() && !hasLayerForVerticalScrollbar()) ? verticalScrollbar()->width() : 0;
694 int horizontalScrollbarHeight = (horizontalScrollbar() && !hasLayerForHorizontalScrollbar()) ? horizontalScrollbar()->height() : 0;
696 scrollViewRect.setWidth(scrollViewRect.width() - verticalScrollbarWidth);
697 scrollViewRect.setHeight(scrollViewRect.height() - horizontalScrollbarHeight);
699 return scrollViewRect;
702 void ScrollView::scrollContents(const IntSize& scrollDelta)
704 HostWindow* window = hostWindow();
708 // Since scrolling is double buffered, we will be blitting the scroll view's intersection
709 // with the clip rect every time to keep it smooth.
710 IntRect clipRect = windowClipRect();
711 IntRect scrollViewRect = rectToCopyOnScroll();
712 IntRect updateRect = clipRect;
713 updateRect.intersect(scrollViewRect);
715 // Invalidate the root view (not the backing store).
716 window->invalidateRootView(updateRect, false /*immediate*/);
718 if (m_drawPanScrollIcon) {
719 // FIXME: the pan icon is broken when accelerated compositing is on, since it will draw under the compositing layers.
720 // https://bugs.webkit.org/show_bug.cgi?id=47837
721 int panIconDirtySquareSizeLength = 2 * (panIconSizeLength + max(abs(scrollDelta.width()), abs(scrollDelta.height()))); // We only want to repaint what's necessary
722 IntPoint panIconDirtySquareLocation = IntPoint(m_panScrollIconPoint.x() - (panIconDirtySquareSizeLength / 2), m_panScrollIconPoint.y() - (panIconDirtySquareSizeLength / 2));
723 IntRect panScrollIconDirtyRect = IntRect(panIconDirtySquareLocation, IntSize(panIconDirtySquareSizeLength, panIconDirtySquareSizeLength));
724 panScrollIconDirtyRect.intersect(clipRect);
725 window->invalidateContentsAndRootView(panScrollIconDirtyRect, false /*immediate*/);
728 if (canBlitOnScroll()) { // The main frame can just blit the WebView window
729 // FIXME: Find a way to scroll subframes with this faster path
730 if (!scrollContentsFastPath(-scrollDelta, scrollViewRect, clipRect))
731 scrollContentsSlowPath(updateRect);
733 // We need to go ahead and repaint the entire backing store. Do it now before moving the
735 scrollContentsSlowPath(updateRect);
738 // Invalidate the overhang areas if they are visible.
739 updateOverhangAreas();
741 // This call will move children with native widgets (plugins) and invalidate them as well.
744 // Now blit the backingstore into the window which should be very fast.
745 window->invalidateRootView(IntRect(), true);
748 bool ScrollView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
750 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
754 void ScrollView::scrollContentsSlowPath(const IntRect& updateRect)
756 hostWindow()->invalidateContentsForSlowScroll(updateRect, false);
759 IntPoint ScrollView::rootViewToContents(const IntPoint& rootViewPoint) const
761 IntPoint viewPoint = convertFromRootView(rootViewPoint);
762 return viewPoint + scrollOffsetRelativeToDocument();
765 IntPoint ScrollView::contentsToRootView(const IntPoint& contentsPoint) const
767 IntPoint viewPoint = contentsPoint + IntSize(0, headerHeight()) - scrollOffset();
768 return convertToRootView(viewPoint);
771 IntRect ScrollView::rootViewToContents(const IntRect& rootViewRect) const
773 IntRect viewRect = convertFromRootView(rootViewRect);
774 viewRect.move(scrollOffsetRelativeToDocument());
778 IntRect ScrollView::contentsToRootView(const IntRect& contentsRect) const
780 IntRect viewRect = contentsRect;
781 viewRect.move(-scrollOffset() + IntSize(0, headerHeight()));
782 return convertToRootView(viewRect);
785 IntPoint ScrollView::rootViewToTotalContents(const IntPoint& rootViewPoint) const
787 IntPoint viewPoint = convertFromRootView(rootViewPoint);
788 return viewPoint + scrollOffset();
791 IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const
793 if (delegatesScrolling())
794 return convertFromContainingWindow(windowPoint);
796 IntPoint viewPoint = convertFromContainingWindow(windowPoint);
797 return viewPoint + scrollOffsetRelativeToDocument();
800 IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const
802 if (delegatesScrolling())
803 return convertToContainingWindow(contentsPoint);
805 IntPoint viewPoint = contentsPoint + IntSize(0, headerHeight()) - scrollOffset();
806 return convertToContainingWindow(viewPoint);
809 IntRect ScrollView::windowToContents(const IntRect& windowRect) const
811 if (delegatesScrolling())
812 return convertFromContainingWindow(windowRect);
814 IntRect viewRect = convertFromContainingWindow(windowRect);
815 viewRect.move(scrollOffsetRelativeToDocument());
819 IntRect ScrollView::contentsToWindow(const IntRect& contentsRect) const
821 if (delegatesScrolling())
822 return convertToContainingWindow(contentsRect);
824 IntRect viewRect = contentsRect;
825 viewRect.move(-scrollOffset() + IntSize(0, headerHeight()));
826 return convertToContainingWindow(viewRect);
829 IntRect ScrollView::contentsToScreen(const IntRect& rect) const
831 HostWindow* window = hostWindow();
832 if (platformWidget())
833 return platformContentsToScreen(rect);
836 return window->rootViewToScreen(contentsToRootView(rect));
839 IntPoint ScrollView::screenToContents(const IntPoint& point) const
841 HostWindow* window = hostWindow();
842 if (platformWidget())
843 return platformScreenToContents(point);
846 return rootViewToContents(window->screenToRootView(point));
849 bool ScrollView::containsScrollbarsAvoidingResizer() const
851 return !m_scrollbarsAvoidingResizer;
854 void ScrollView::adjustScrollbarsAvoidingResizerCount(int overlapDelta)
856 int oldCount = m_scrollbarsAvoidingResizer;
857 m_scrollbarsAvoidingResizer += overlapDelta;
859 parent()->adjustScrollbarsAvoidingResizerCount(overlapDelta);
860 else if (!scrollbarsSuppressed()) {
861 // If we went from n to 0 or from 0 to n and we're the outermost view,
862 // we need to invalidate the windowResizerRect(), since it will now need to paint
864 if ((oldCount > 0 && m_scrollbarsAvoidingResizer == 0) ||
865 (oldCount == 0 && m_scrollbarsAvoidingResizer > 0))
866 invalidateRect(windowResizerRect());
870 void ScrollView::setParent(ScrollView* parentView)
872 if (parentView == parent())
875 if (m_scrollbarsAvoidingResizer && parent())
876 parent()->adjustScrollbarsAvoidingResizerCount(-m_scrollbarsAvoidingResizer);
878 Widget::setParent(parentView);
880 if (m_scrollbarsAvoidingResizer && parent())
881 parent()->adjustScrollbarsAvoidingResizerCount(m_scrollbarsAvoidingResizer);
884 void ScrollView::setScrollbarsSuppressed(bool suppressed, bool repaintOnUnsuppress)
886 if (suppressed == m_scrollbarsSuppressed)
889 m_scrollbarsSuppressed = suppressed;
891 if (platformWidget())
892 platformSetScrollbarsSuppressed(repaintOnUnsuppress);
893 else if (repaintOnUnsuppress && !suppressed) {
894 if (m_horizontalScrollbar)
895 m_horizontalScrollbar->invalidate();
896 if (m_verticalScrollbar)
897 m_verticalScrollbar->invalidate();
899 // Invalidate the scroll corner too on unsuppress.
900 invalidateRect(scrollCornerRect());
904 Scrollbar* ScrollView::scrollbarAtPoint(const IntPoint& windowPoint)
906 if (platformWidget())
909 IntPoint viewPoint = convertFromContainingWindow(windowPoint);
910 if (m_horizontalScrollbar && m_horizontalScrollbar->shouldParticipateInHitTesting() && m_horizontalScrollbar->frameRect().contains(viewPoint))
911 return m_horizontalScrollbar.get();
912 if (m_verticalScrollbar && m_verticalScrollbar->shouldParticipateInHitTesting() && m_verticalScrollbar->frameRect().contains(viewPoint))
913 return m_verticalScrollbar.get();
917 void ScrollView::setScrollbarOverlayStyle(ScrollbarOverlayStyle overlayStyle)
919 ScrollableArea::setScrollbarOverlayStyle(overlayStyle);
920 platformSetScrollbarOverlayStyle(overlayStyle);
923 void ScrollView::setFrameRect(const IntRect& newRect)
925 IntRect oldRect = frameRect();
927 if (newRect == oldRect)
930 Widget::setFrameRect(newRect);
934 updateScrollbars(scrollOffset());
936 if (!m_useFixedLayout && oldRect.size() != newRect.size())
940 void ScrollView::frameRectsChanged()
942 if (platformWidget())
945 HashSet<RefPtr<Widget> >::const_iterator end = m_children.end();
946 for (HashSet<RefPtr<Widget> >::const_iterator current = m_children.begin(); current != end; ++current)
947 (*current)->frameRectsChanged();
950 void ScrollView::clipRectChanged()
952 HashSet<RefPtr<Widget> >::const_iterator end = m_children.end();
953 for (HashSet<RefPtr<Widget> >::const_iterator current = m_children.begin(); current != end; ++current)
954 (*current)->clipRectChanged();
957 #if USE(ACCELERATED_COMPOSITING)
958 static void positionScrollbarLayer(GraphicsLayer* graphicsLayer, Scrollbar* scrollbar)
960 if (!graphicsLayer || !scrollbar)
963 IntRect scrollbarRect = scrollbar->frameRect();
964 graphicsLayer->setPosition(scrollbarRect.location());
966 if (scrollbarRect.size() == graphicsLayer->size())
969 graphicsLayer->setSize(scrollbarRect.size());
971 if (graphicsLayer->hasContentsLayer()) {
972 graphicsLayer->setContentsRect(IntRect(0, 0, scrollbarRect.width(), scrollbarRect.height()));
976 graphicsLayer->setDrawsContent(true);
977 graphicsLayer->setNeedsDisplay();
980 static void positionScrollCornerLayer(GraphicsLayer* graphicsLayer, const IntRect& cornerRect)
984 graphicsLayer->setDrawsContent(!cornerRect.isEmpty());
985 graphicsLayer->setPosition(cornerRect.location());
986 if (cornerRect.size() != graphicsLayer->size())
987 graphicsLayer->setNeedsDisplay();
988 graphicsLayer->setSize(cornerRect.size());
993 void ScrollView::positionScrollbarLayers()
995 #if USE(ACCELERATED_COMPOSITING)
996 positionScrollbarLayer(layerForHorizontalScrollbar(), horizontalScrollbar());
997 positionScrollbarLayer(layerForVerticalScrollbar(), verticalScrollbar());
998 positionScrollCornerLayer(layerForScrollCorner(), scrollCornerRect());
1002 void ScrollView::repaintContentRectangle(const IntRect& rect, bool now)
1004 IntRect paintRect = rect;
1005 if (clipsRepaints() && !paintsEntireContents())
1006 paintRect.intersect(visibleContentRect());
1007 if (paintRect.isEmpty())
1010 if (platformWidget()) {
1011 notifyPageThatContentAreaWillPaint();
1012 platformRepaintContentRectangle(paintRect, now);
1016 if (HostWindow* window = hostWindow())
1017 window->invalidateContentsAndRootView(contentsToWindow(paintRect), now /*immediate*/);
1020 IntRect ScrollView::scrollCornerRect() const
1024 if (hasOverlayScrollbars())
1027 if (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0) {
1028 cornerRect.unite(IntRect(m_horizontalScrollbar->width(),
1029 height() - m_horizontalScrollbar->height(),
1030 width() - m_horizontalScrollbar->width(),
1031 m_horizontalScrollbar->height()));
1034 if (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0) {
1035 cornerRect.unite(IntRect(width() - m_verticalScrollbar->width(),
1036 m_verticalScrollbar->height(),
1037 m_verticalScrollbar->width(),
1038 height() - m_verticalScrollbar->height()));
1044 bool ScrollView::isScrollCornerVisible() const
1046 return !scrollCornerRect().isEmpty();
1049 void ScrollView::scrollbarStyleChanged(int, bool forceUpdate)
1055 updateScrollbars(scrollOffset());
1056 positionScrollbarLayers();
1059 void ScrollView::updateScrollCorner()
1063 void ScrollView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
1065 ScrollbarTheme::theme()->paintScrollCorner(this, context, cornerRect);
1068 void ScrollView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
1070 bar->paint(context, rect);
1073 void ScrollView::invalidateScrollCornerRect(const IntRect& rect)
1075 invalidateRect(rect);
1078 void ScrollView::paintScrollbars(GraphicsContext* context, const IntRect& rect)
1080 if (m_horizontalScrollbar
1081 #if USE(ACCELERATED_COMPOSITING)
1082 && !layerForHorizontalScrollbar()
1085 paintScrollbar(context, m_horizontalScrollbar.get(), rect);
1086 if (m_verticalScrollbar
1087 #if USE(ACCELERATED_COMPOSITING)
1088 && !layerForVerticalScrollbar()
1091 paintScrollbar(context, m_verticalScrollbar.get(), rect);
1093 #if USE(ACCELERATED_COMPOSITING)
1094 if (layerForScrollCorner())
1097 paintScrollCorner(context, scrollCornerRect());
1100 void ScrollView::paintPanScrollIcon(GraphicsContext* context)
1102 static Image* panScrollIcon = Image::loadPlatformResource("panIcon").leakRef();
1103 IntPoint iconGCPoint = m_panScrollIconPoint;
1105 iconGCPoint = parent()->windowToContents(iconGCPoint);
1106 context->drawImage(panScrollIcon, ColorSpaceDeviceRGB, iconGCPoint);
1109 void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
1111 if (platformWidget()) {
1112 Widget::paint(context, rect);
1116 if (context->paintingDisabled() && !context->updatingControlTints())
1119 notifyPageThatContentAreaWillPaint();
1121 IntRect documentDirtyRect = rect;
1122 if (!paintsEntireContents()) {
1123 IntRect visibleAreaWithoutScrollbars(location(), visibleContentRect().size());
1124 documentDirtyRect.intersect(visibleAreaWithoutScrollbars);
1127 if (!documentDirtyRect.isEmpty()) {
1128 GraphicsContextStateSaver stateSaver(*context);
1130 context->translate(x(), y());
1131 documentDirtyRect.moveBy(-location());
1133 if (!paintsEntireContents()) {
1134 context->translate(-scrollX(), -scrollY());
1135 documentDirtyRect.moveBy(scrollPosition());
1137 context->clip(visibleContentRect());
1140 paintContents(context, documentDirtyRect);
1143 #if USE(ACCELERATED_COMPOSITING) && ENABLE(RUBBER_BANDING)
1144 if (!layerForOverhangAreas())
1145 calculateAndPaintOverhangAreas(context, rect);
1147 calculateAndPaintOverhangAreas(context, rect);
1150 // Now paint the scrollbars.
1151 if (!m_scrollbarsSuppressed && (m_horizontalScrollbar || m_verticalScrollbar)) {
1152 GraphicsContextStateSaver stateSaver(*context);
1153 IntRect scrollViewDirtyRect = rect;
1154 IntRect visibleAreaWithScrollbars(location(), visibleContentRect(IncludeScrollbars).size());
1155 scrollViewDirtyRect.intersect(visibleAreaWithScrollbars);
1156 context->translate(x(), y());
1157 scrollViewDirtyRect.moveBy(-location());
1159 paintScrollbars(context, scrollViewDirtyRect);
1162 // Paint the panScroll Icon
1163 if (m_drawPanScrollIcon)
1164 paintPanScrollIcon(context);
1167 void ScrollView::calculateOverhangAreasForPainting(IntRect& horizontalOverhangRect, IntRect& verticalOverhangRect)
1169 int verticalScrollbarWidth = (verticalScrollbar() && !verticalScrollbar()->isOverlayScrollbar())
1170 ? verticalScrollbar()->width() : 0;
1171 int horizontalScrollbarHeight = (horizontalScrollbar() && !horizontalScrollbar()->isOverlayScrollbar())
1172 ? horizontalScrollbar()->height() : 0;
1174 int physicalScrollY = scrollPosition().y() + scrollOrigin().y();
1175 if (physicalScrollY < 0) {
1176 horizontalOverhangRect = frameRect();
1177 horizontalOverhangRect.setHeight(-physicalScrollY);
1178 horizontalOverhangRect.setWidth(horizontalOverhangRect.width() - verticalScrollbarWidth);
1179 } else if (totalContentsSize().height() && physicalScrollY > totalContentsSize().height() - visibleHeight()) {
1180 int height = physicalScrollY - (totalContentsSize().height() - visibleHeight());
1181 horizontalOverhangRect = frameRect();
1182 horizontalOverhangRect.setY(frameRect().maxY() - height - horizontalScrollbarHeight);
1183 horizontalOverhangRect.setHeight(height);
1184 horizontalOverhangRect.setWidth(horizontalOverhangRect.width() - verticalScrollbarWidth);
1187 int physicalScrollX = scrollPosition().x() + scrollOrigin().x();
1188 if (physicalScrollX < 0) {
1189 verticalOverhangRect.setWidth(-physicalScrollX);
1190 verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height() - horizontalScrollbarHeight);
1191 verticalOverhangRect.setX(frameRect().x());
1192 if (horizontalOverhangRect.y() == frameRect().y())
1193 verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.height());
1195 verticalOverhangRect.setY(frameRect().y());
1196 } else if (contentsWidth() && physicalScrollX > contentsWidth() - visibleWidth()) {
1197 int width = physicalScrollX - (contentsWidth() - visibleWidth());
1198 verticalOverhangRect.setWidth(width);
1199 verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height() - horizontalScrollbarHeight);
1200 verticalOverhangRect.setX(frameRect().maxX() - width - verticalScrollbarWidth);
1201 if (horizontalOverhangRect.y() == frameRect().y())
1202 verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.height());
1204 verticalOverhangRect.setY(frameRect().y());
1208 void ScrollView::updateOverhangAreas()
1210 HostWindow* window = hostWindow();
1214 IntRect horizontalOverhangRect;
1215 IntRect verticalOverhangRect;
1216 calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
1217 if (!horizontalOverhangRect.isEmpty())
1218 window->invalidateContentsAndRootView(horizontalOverhangRect, false /*immediate*/);
1219 if (!verticalOverhangRect.isEmpty())
1220 window->invalidateContentsAndRootView(verticalOverhangRect, false /*immediate*/);
1223 void ScrollView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
1225 ScrollbarTheme::theme()->paintOverhangAreas(this, context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
1228 void ScrollView::calculateAndPaintOverhangAreas(GraphicsContext* context, const IntRect& dirtyRect)
1230 IntRect horizontalOverhangRect;
1231 IntRect verticalOverhangRect;
1232 calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
1234 if (dirtyRect.intersects(horizontalOverhangRect) || dirtyRect.intersects(verticalOverhangRect))
1235 paintOverhangAreas(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
1238 bool ScrollView::isPointInScrollbarCorner(const IntPoint& windowPoint)
1240 if (!scrollbarCornerPresent())
1243 IntPoint viewPoint = convertFromContainingWindow(windowPoint);
1245 if (m_horizontalScrollbar) {
1246 int horizontalScrollbarYMin = m_horizontalScrollbar->frameRect().y();
1247 int horizontalScrollbarYMax = m_horizontalScrollbar->frameRect().y() + m_horizontalScrollbar->frameRect().height();
1248 int horizontalScrollbarXMin = m_horizontalScrollbar->frameRect().x() + m_horizontalScrollbar->frameRect().width();
1250 return viewPoint.y() > horizontalScrollbarYMin && viewPoint.y() < horizontalScrollbarYMax && viewPoint.x() > horizontalScrollbarXMin;
1253 int verticalScrollbarXMin = m_verticalScrollbar->frameRect().x();
1254 int verticalScrollbarXMax = m_verticalScrollbar->frameRect().x() + m_verticalScrollbar->frameRect().width();
1255 int verticalScrollbarYMin = m_verticalScrollbar->frameRect().y() + m_verticalScrollbar->frameRect().height();
1257 return viewPoint.x() > verticalScrollbarXMin && viewPoint.x() < verticalScrollbarXMax && viewPoint.y() > verticalScrollbarYMin;
1260 bool ScrollView::scrollbarCornerPresent() const
1262 return (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0)
1263 || (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0);
1266 IntRect ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& localRect) const
1268 // Scrollbars won't be transformed within us
1269 IntRect newRect = localRect;
1270 newRect.moveBy(scrollbar->location());
1274 IntRect ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
1276 IntRect newRect = parentRect;
1277 // Scrollbars won't be transformed within us
1278 newRect.moveBy(-scrollbar->location());
1282 // FIXME: test these on windows
1283 IntPoint ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& localPoint) const
1285 // Scrollbars won't be transformed within us
1286 IntPoint newPoint = localPoint;
1287 newPoint.moveBy(scrollbar->location());
1291 IntPoint ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
1293 IntPoint newPoint = parentPoint;
1294 // Scrollbars won't be transformed within us
1295 newPoint.moveBy(-scrollbar->location());
1299 void ScrollView::setParentVisible(bool visible)
1301 if (isParentVisible() == visible)
1304 Widget::setParentVisible(visible);
1306 if (!isSelfVisible())
1309 HashSet<RefPtr<Widget> >::iterator end = m_children.end();
1310 for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it)
1311 (*it)->setParentVisible(visible);
1314 void ScrollView::show()
1316 if (!isSelfVisible()) {
1317 setSelfVisible(true);
1318 if (isParentVisible()) {
1319 HashSet<RefPtr<Widget> >::iterator end = m_children.end();
1320 for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it)
1321 (*it)->setParentVisible(true);
1328 void ScrollView::hide()
1330 if (isSelfVisible()) {
1331 if (isParentVisible()) {
1332 HashSet<RefPtr<Widget> >::iterator end = m_children.end();
1333 for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it)
1334 (*it)->setParentVisible(false);
1336 setSelfVisible(false);
1342 bool ScrollView::isOffscreen() const
1344 if (platformWidget())
1345 return platformIsOffscreen();
1350 // FIXME: Add a HostWindow::isOffscreen method here. Since only Mac implements this method
1351 // currently, we can add the method when the other platforms decide to implement this concept.
1356 void ScrollView::addPanScrollIcon(const IntPoint& iconPosition)
1358 HostWindow* window = hostWindow();
1361 m_drawPanScrollIcon = true;
1362 m_panScrollIconPoint = IntPoint(iconPosition.x() - panIconSizeLength / 2 , iconPosition.y() - panIconSizeLength / 2) ;
1363 window->invalidateContentsAndRootView(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)), true /*immediate*/);
1366 void ScrollView::removePanScrollIcon()
1368 HostWindow* window = hostWindow();
1371 m_drawPanScrollIcon = false;
1372 window->invalidateContentsAndRootView(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)), true /*immediate*/);
1375 void ScrollView::setScrollOrigin(const IntPoint& origin, bool updatePositionAtAll, bool updatePositionSynchronously)
1377 if (scrollOrigin() == origin)
1380 ScrollableArea::setScrollOrigin(origin);
1382 if (platformWidget()) {
1383 platformSetScrollOrigin(origin, updatePositionAtAll, updatePositionSynchronously);
1387 // Update if the scroll origin changes, since our position will be different if the content size did not change.
1388 if (updatePositionAtAll && updatePositionSynchronously)
1389 updateScrollbars(scrollOffset());
1392 #if !PLATFORM(QT) && !PLATFORM(MAC)
1394 void ScrollView::platformAddChild(Widget*)
1398 void ScrollView::platformRemoveChild(Widget*)
1406 void ScrollView::platformSetScrollbarsSuppressed(bool)
1410 void ScrollView::platformSetScrollOrigin(const IntPoint&, bool, bool)
1414 void ScrollView::platformSetScrollbarOverlayStyle(ScrollbarOverlayStyle)
1422 void ScrollView::platformSetScrollbarModes()
1426 void ScrollView::platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode& vertical) const
1428 horizontal = ScrollbarAuto;
1429 vertical = ScrollbarAuto;
1432 void ScrollView::platformSetCanBlitOnScroll(bool)
1436 bool ScrollView::platformCanBlitOnScroll() const
1441 IntRect ScrollView::platformVisibleContentRect(bool) const
1446 IntSize ScrollView::platformVisibleContentSize(bool) const
1451 void ScrollView::platformSetContentsSize()
1455 IntRect ScrollView::platformContentsToScreen(const IntRect& rect) const
1460 IntPoint ScrollView::platformScreenToContents(const IntPoint& point) const
1465 void ScrollView::platformSetScrollPosition(const IntPoint&)
1469 bool ScrollView::platformScroll(ScrollDirection, ScrollGranularity)
1474 void ScrollView::platformRepaintContentRectangle(const IntRect&, bool /*now*/)
1478 bool ScrollView::platformIsOffscreen() const