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 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 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>
41 ScrollView::ScrollView()
42 : m_horizontalScrollbarMode(ScrollbarAuto)
43 , m_verticalScrollbarMode(ScrollbarAuto)
44 , m_horizontalScrollbarLock(false)
45 , m_verticalScrollbarLock(false)
46 , m_prohibitsScrolling(false)
47 , m_canBlitOnScroll(true)
48 , m_scrollbarsAvoidingResizer(0)
49 , m_scrollbarsSuppressed(false)
50 , m_inUpdateScrollbars(false)
51 , m_updateScrollbarsPass(0)
52 , m_drawPanScrollIcon(false)
53 , m_useFixedLayout(false)
54 , m_paintsEntireContents(false)
55 , m_clipsRepaints(true)
56 , m_delegatesScrolling(false)
60 ScrollView::~ScrollView()
64 void ScrollView::addChild(PassRefPtr<Widget> prpChild)
66 Widget* child = prpChild.get();
67 ASSERT(child != this && !child->parent());
68 child->setParent(this);
69 m_children.add(prpChild);
70 if (child->platformWidget())
71 platformAddChild(child);
74 void ScrollView::removeChild(Widget* child)
76 ASSERT(child->parent() == this);
78 m_children.remove(child);
79 if (child->platformWidget())
80 platformRemoveChild(child);
83 bool ScrollView::setHasHorizontalScrollbar(bool hasBar, bool* contentSizeAffected)
85 ASSERT(!hasBar || !avoidScrollbarCreation());
86 if (hasBar && !m_horizontalScrollbar) {
87 m_horizontalScrollbar = createScrollbar(HorizontalScrollbar);
88 addChild(m_horizontalScrollbar.get());
89 didAddScrollbar(m_horizontalScrollbar.get(), HorizontalScrollbar);
90 m_horizontalScrollbar->styleChanged();
91 if (contentSizeAffected)
92 *contentSizeAffected = !m_horizontalScrollbar->isOverlayScrollbar();
96 if (!hasBar && m_horizontalScrollbar) {
97 bool wasOverlayScrollbar = m_horizontalScrollbar->isOverlayScrollbar();
98 willRemoveScrollbar(m_horizontalScrollbar.get(), HorizontalScrollbar);
99 removeChild(m_horizontalScrollbar.get());
100 m_horizontalScrollbar = 0;
101 if (contentSizeAffected)
102 *contentSizeAffected = !wasOverlayScrollbar;
109 bool ScrollView::setHasVerticalScrollbar(bool hasBar, bool* contentSizeAffected)
111 ASSERT(!hasBar || !avoidScrollbarCreation());
112 if (hasBar && !m_verticalScrollbar) {
113 m_verticalScrollbar = createScrollbar(VerticalScrollbar);
114 addChild(m_verticalScrollbar.get());
115 didAddScrollbar(m_verticalScrollbar.get(), VerticalScrollbar);
116 m_verticalScrollbar->styleChanged();
117 if (contentSizeAffected)
118 *contentSizeAffected = !m_verticalScrollbar->isOverlayScrollbar();
122 if (!hasBar && m_verticalScrollbar) {
123 bool wasOverlayScrollbar = m_verticalScrollbar->isOverlayScrollbar();
124 willRemoveScrollbar(m_verticalScrollbar.get(), VerticalScrollbar);
125 removeChild(m_verticalScrollbar.get());
126 m_verticalScrollbar = 0;
127 if (contentSizeAffected)
128 *contentSizeAffected = !wasOverlayScrollbar;
136 PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientation)
138 return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
141 void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode,
142 bool horizontalLock, bool verticalLock)
144 bool needsUpdate = false;
146 if (horizontalMode != horizontalScrollbarMode() && !m_horizontalScrollbarLock) {
147 m_horizontalScrollbarMode = horizontalMode;
151 if (verticalMode != verticalScrollbarMode() && !m_verticalScrollbarLock) {
152 m_verticalScrollbarMode = verticalMode;
157 setHorizontalScrollbarLock();
160 setVerticalScrollbarLock();
165 if (platformWidget())
166 platformSetScrollbarModes();
168 updateScrollbars(scrollOffset());
172 void ScrollView::scrollbarModes(ScrollbarMode& horizontalMode, ScrollbarMode& verticalMode) const
174 if (platformWidget()) {
175 platformScrollbarModes(horizontalMode, verticalMode);
178 horizontalMode = m_horizontalScrollbarMode;
179 verticalMode = m_verticalScrollbarMode;
182 void ScrollView::setCanHaveScrollbars(bool canScroll)
184 ScrollbarMode newHorizontalMode;
185 ScrollbarMode newVerticalMode;
187 scrollbarModes(newHorizontalMode, newVerticalMode);
189 if (canScroll && newVerticalMode == ScrollbarAlwaysOff)
190 newVerticalMode = ScrollbarAuto;
192 newVerticalMode = ScrollbarAlwaysOff;
194 if (canScroll && newHorizontalMode == ScrollbarAlwaysOff)
195 newHorizontalMode = ScrollbarAuto;
197 newHorizontalMode = ScrollbarAlwaysOff;
199 setScrollbarModes(newHorizontalMode, newVerticalMode);
202 void ScrollView::setCanBlitOnScroll(bool b)
204 if (platformWidget()) {
205 platformSetCanBlitOnScroll(b);
209 m_canBlitOnScroll = b;
212 bool ScrollView::canBlitOnScroll() const
214 if (platformWidget())
215 return platformCanBlitOnScroll();
217 return m_canBlitOnScroll;
220 void ScrollView::setPaintsEntireContents(bool paintsEntireContents)
222 m_paintsEntireContents = paintsEntireContents;
225 void ScrollView::setClipsRepaints(bool clipsRepaints)
227 m_clipsRepaints = clipsRepaints;
230 void ScrollView::setDelegatesScrolling(bool delegatesScrolling)
232 if (m_delegatesScrolling == delegatesScrolling)
235 m_delegatesScrolling = delegatesScrolling;
236 delegatesScrollingDidChange();
240 IntRect ScrollView::unobscuredContentRect(VisibleContentRectIncludesScrollbars scrollbarInclusion) const
242 FloatSize visibleContentSize = unscaledUnobscuredVisibleContentSize(scrollbarInclusion);
243 visibleContentSize.scale(1 / visibleContentScaleFactor());
244 return IntRect(IntPoint(m_scrollOffset), expandedIntSize(visibleContentSize));
248 IntSize ScrollView::unscaledTotalVisibleContentSize(VisibleContentRectIncludesScrollbars scrollbarInclusion) const
250 if (platformWidget())
251 return platformVisibleContentSize(scrollbarInclusion == IncludeScrollbars);
253 #if USE(TILED_BACKING_STORE)
254 if (!m_fixedVisibleContentRect.isEmpty())
255 return m_fixedVisibleContentRect.size();
258 int verticalScrollbarWidth = 0;
259 int horizontalScrollbarHeight = 0;
261 if (scrollbarInclusion == ExcludeScrollbars) {
262 if (Scrollbar* verticalBar = verticalScrollbar())
263 verticalScrollbarWidth = !verticalBar->isOverlayScrollbar() ? verticalBar->width() : 0;
264 if (Scrollbar* horizontalBar = horizontalScrollbar())
265 horizontalScrollbarHeight = !horizontalBar->isOverlayScrollbar() ? horizontalBar->height() : 0;
268 return IntSize(width() - verticalScrollbarWidth, height() - horizontalScrollbarHeight).expandedTo(IntSize());
271 IntSize ScrollView::unscaledUnobscuredVisibleContentSize(VisibleContentRectIncludesScrollbars scrollbarInclusion) const
273 IntSize visibleContentSize = unscaledTotalVisibleContentSize(scrollbarInclusion);
275 if (platformWidget())
276 return visibleContentSize;
278 #if USE(TILED_BACKING_STORE)
279 if (!m_fixedVisibleContentRect.isEmpty())
280 return visibleContentSize;
283 visibleContentSize.setHeight(visibleContentSize.height() - topContentInset());
284 return visibleContentSize;
288 IntRect ScrollView::visibleContentRectInternal(VisibleContentRectIncludesScrollbars scrollbarInclusion, VisibleContentRectBehavior visibleContentRectBehavior) const
291 if (visibleContentRectBehavior == LegacyIOSDocumentViewRect) {
292 if (platformWidget())
293 return platformVisibleContentRect(true /* include scrollbars */);
296 if (platformWidget())
297 return unobscuredContentRect();
299 UNUSED_PARAM(visibleContentRectBehavior);
302 if (platformWidget())
303 return platformVisibleContentRect(scrollbarInclusion == IncludeScrollbars);
305 #if USE(TILED_BACKING_STORE)
306 if (!m_fixedVisibleContentRect.isEmpty())
307 return m_fixedVisibleContentRect;
310 return unobscuredContentRect();
314 IntSize ScrollView::layoutSize() const
316 return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? unscaledUnobscuredVisibleContentSize(ExcludeScrollbars) : m_fixedLayoutSize;
319 IntSize ScrollView::fixedLayoutSize() const
321 return m_fixedLayoutSize;
324 void ScrollView::setFixedLayoutSize(const IntSize& newSize)
326 if (fixedLayoutSize() == newSize)
328 m_fixedLayoutSize = newSize;
329 if (m_useFixedLayout)
330 fixedLayoutSizeChanged();
333 bool ScrollView::useFixedLayout() const
335 return m_useFixedLayout;
338 void ScrollView::setUseFixedLayout(bool enable)
340 if (useFixedLayout() == enable)
342 m_useFixedLayout = enable;
343 if (!m_fixedLayoutSize.isEmpty())
344 fixedLayoutSizeChanged();
347 void ScrollView::fixedLayoutSizeChanged()
349 updateScrollbars(scrollOffset());
353 IntSize ScrollView::contentsSize() const
355 return m_contentsSize;
358 void ScrollView::setContentsSize(const IntSize& newSize)
360 if (contentsSize() == newSize)
362 m_contentsSize = newSize;
363 if (platformWidget())
364 platformSetContentsSize();
366 updateScrollbars(scrollOffset());
367 updateOverhangAreas();
370 IntPoint ScrollView::maximumScrollPosition() const
372 IntPoint maximumOffset(contentsWidth() - visibleWidth() - scrollOrigin().x(), totalContentsSize().height() - visibleHeight() - scrollOrigin().y());
373 maximumOffset.clampNegativeToZero();
374 return maximumOffset;
377 IntPoint ScrollView::minimumScrollPosition() const
379 return IntPoint(-scrollOrigin().x(), -scrollOrigin().y());
382 IntPoint ScrollView::adjustScrollPositionWithinRange(const IntPoint& scrollPoint) const
384 if (!constrainsScrollingToContentEdge())
387 IntPoint newScrollPosition = scrollPoint.shrunkTo(maximumScrollPosition());
388 newScrollPosition = newScrollPosition.expandedTo(minimumScrollPosition());
389 return newScrollPosition;
392 IntSize ScrollView::scrollOffsetRelativeToDocument() const
394 IntSize scrollOffset = this->scrollOffset();
395 return IntSize(scrollOffset.width(), scrollOffset.height() - headerHeight() - topContentInset());
398 IntPoint ScrollView::scrollPositionRelativeToDocument() const
400 IntPoint scrollPosition = this->scrollPosition();
401 return IntPoint(scrollPosition.x(), scrollPosition.y() - headerHeight() - topContentInset());
404 int ScrollView::scrollSize(ScrollbarOrientation orientation) const
406 // If no scrollbars are present, it does not indicate content is not be scrollable.
407 if (!m_horizontalScrollbar && !m_verticalScrollbar && !prohibitsScrolling()) {
408 IntSize scrollSize = m_contentsSize - visibleContentRect(LegacyIOSDocumentVisibleRect).size();
409 scrollSize.clampNegativeToZero();
410 return orientation == HorizontalScrollbar ? scrollSize.width() : scrollSize.height();
413 Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_horizontalScrollbar : m_verticalScrollbar).get();
414 return scrollbar ? (scrollbar->totalSize() - scrollbar->visibleSize()) : 0;
417 void ScrollView::notifyPageThatContentAreaWillPaint() const
421 void ScrollView::setScrollOffset(const IntPoint& offset)
423 int horizontalOffset = offset.x();
424 int verticalOffset = offset.y();
425 if (constrainsScrollingToContentEdge()) {
426 horizontalOffset = std::max(std::min(horizontalOffset, contentsWidth() - visibleWidth()), 0);
427 verticalOffset = std::max(std::min(verticalOffset, totalContentsSize().height() - visibleHeight()), 0);
430 IntSize newOffset = m_scrollOffset;
431 newOffset.setWidth(horizontalOffset - scrollOrigin().x());
432 newOffset.setHeight(verticalOffset - scrollOrigin().y());
437 void ScrollView::scrollTo(const IntSize& newOffset)
439 IntSize scrollDelta = newOffset - m_scrollOffset;
440 if (scrollDelta == IntSize())
442 m_scrollOffset = newOffset;
444 if (scrollbarsSuppressed())
447 #if USE(TILED_BACKING_STORE)
448 if (delegatesScrolling()) {
449 hostWindow()->delegatedScrollRequested(IntPoint(newOffset));
453 updateLayerPositionsAfterScrolling();
454 scrollContents(scrollDelta);
455 updateCompositingLayersAfterScrolling();
458 int ScrollView::scrollPosition(Scrollbar* scrollbar) const
460 if (scrollbar->orientation() == HorizontalScrollbar)
461 return scrollPosition().x() + scrollOrigin().x();
462 if (scrollbar->orientation() == VerticalScrollbar)
463 return scrollPosition().y() + scrollOrigin().y();
467 void ScrollView::setScrollPosition(const IntPoint& scrollPoint)
469 if (prohibitsScrolling())
472 if (platformWidget()) {
473 platformSetScrollPosition(scrollPoint);
477 #if USE(TILED_BACKING_STORE)
478 if (delegatesScrolling()) {
479 hostWindow()->delegatedScrollRequested(scrollPoint);
484 IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint);
486 if (newScrollPosition == scrollPosition())
489 if (requestScrollPositionUpdate(newScrollPosition))
492 updateScrollbars(IntSize(newScrollPosition.x(), newScrollPosition.y()));
495 bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity)
497 if (platformWidget())
498 return platformScroll(direction, granularity);
500 return ScrollableArea::scroll(direction, granularity);
503 bool ScrollView::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity)
505 return scroll(logicalToPhysical(direction, isVerticalDocument(), isFlippedDocument()), granularity);
508 IntSize ScrollView::overhangAmount() const
512 int physicalScrollY = scrollPosition().y() + scrollOrigin().y();
513 if (physicalScrollY < 0)
514 stretch.setHeight(physicalScrollY);
515 else if (totalContentsSize().height() && physicalScrollY > totalContentsSize().height() - visibleHeight())
516 stretch.setHeight(physicalScrollY - (totalContentsSize().height() - visibleHeight()));
518 int physicalScrollX = scrollPosition().x() + scrollOrigin().x();
519 if (physicalScrollX < 0)
520 stretch.setWidth(physicalScrollX);
521 else if (contentsWidth() && physicalScrollX > contentsWidth() - visibleWidth())
522 stretch.setWidth(physicalScrollX - (contentsWidth() - visibleWidth()));
527 void ScrollView::windowResizerRectChanged()
529 if (platformWidget())
532 updateScrollbars(scrollOffset());
535 static const unsigned cMaxUpdateScrollbarsPass = 2;
537 void ScrollView::updateScrollbars(const IntSize& desiredOffset)
539 if (m_inUpdateScrollbars || prohibitsScrolling() || platformWidget())
542 bool hasOverlayScrollbars = (!m_horizontalScrollbar || m_horizontalScrollbar->isOverlayScrollbar()) && (!m_verticalScrollbar || m_verticalScrollbar->isOverlayScrollbar());
544 // If we came in here with the view already needing a layout, then go ahead and do that
545 // first. (This will be the common case, e.g., when the page changes due to window resizing for example).
546 // This layout will not re-enter updateScrollbars and does not count towards our max layout pass total.
547 if (!m_scrollbarsSuppressed && !hasOverlayScrollbars) {
548 m_inUpdateScrollbars = true;
549 visibleContentsResized();
550 m_inUpdateScrollbars = false;
553 IntRect oldScrollCornerRect = scrollCornerRect();
555 bool hasHorizontalScrollbar = m_horizontalScrollbar;
556 bool hasVerticalScrollbar = m_verticalScrollbar;
558 bool newHasHorizontalScrollbar = hasHorizontalScrollbar;
559 bool newHasVerticalScrollbar = hasVerticalScrollbar;
561 ScrollbarMode hScroll = m_horizontalScrollbarMode;
562 ScrollbarMode vScroll = m_verticalScrollbarMode;
564 if (hScroll != ScrollbarAuto)
565 newHasHorizontalScrollbar = (hScroll == ScrollbarAlwaysOn);
566 if (vScroll != ScrollbarAuto)
567 newHasVerticalScrollbar = (vScroll == ScrollbarAlwaysOn);
569 bool scrollbarAddedOrRemoved = false;
571 if (m_scrollbarsSuppressed || (hScroll != ScrollbarAuto && vScroll != ScrollbarAuto)) {
572 if (hasHorizontalScrollbar != newHasHorizontalScrollbar && (hasHorizontalScrollbar || !avoidScrollbarCreation())) {
573 if (setHasHorizontalScrollbar(newHasHorizontalScrollbar))
574 scrollbarAddedOrRemoved = true;
577 if (hasVerticalScrollbar != newHasVerticalScrollbar && (hasVerticalScrollbar || !avoidScrollbarCreation())) {
578 if (setHasVerticalScrollbar(newHasVerticalScrollbar))
579 scrollbarAddedOrRemoved = true;
582 bool sendContentResizedNotification = false;
584 IntSize docSize = totalContentsSize();
585 IntSize fullVisibleSize = unobscuredContentRectIncludingScrollbars().size();
587 if (hScroll == ScrollbarAuto)
588 newHasHorizontalScrollbar = docSize.width() > visibleWidth();
589 if (vScroll == ScrollbarAuto)
590 newHasVerticalScrollbar = docSize.height() > visibleHeight();
592 bool needAnotherPass = false;
593 if (!hasOverlayScrollbars) {
594 // If we ever turn one scrollbar off, always turn the other one off too. Never ever
595 // try to both gain/lose a scrollbar in the same pass.
596 if (!m_updateScrollbarsPass && docSize.width() <= fullVisibleSize.width() && docSize.height() <= fullVisibleSize.height()) {
597 if (hScroll == ScrollbarAuto)
598 newHasHorizontalScrollbar = false;
599 if (vScroll == ScrollbarAuto)
600 newHasVerticalScrollbar = false;
602 if (!newHasHorizontalScrollbar && hasHorizontalScrollbar && vScroll != ScrollbarAlwaysOn) {
603 newHasVerticalScrollbar = false;
604 needAnotherPass = true;
606 if (!newHasVerticalScrollbar && hasVerticalScrollbar && hScroll != ScrollbarAlwaysOn) {
607 newHasHorizontalScrollbar = false;
608 needAnotherPass = true;
612 if (hasHorizontalScrollbar != newHasHorizontalScrollbar && (hasHorizontalScrollbar || !avoidScrollbarCreation())) {
613 if (scrollOrigin().y() && !newHasHorizontalScrollbar)
614 ScrollableArea::setScrollOrigin(IntPoint(scrollOrigin().x(), scrollOrigin().y() - m_horizontalScrollbar->height()));
615 if (m_horizontalScrollbar)
616 m_horizontalScrollbar->invalidate();
618 bool changeAffectsContentSize = false;
619 if (setHasHorizontalScrollbar(newHasHorizontalScrollbar, &changeAffectsContentSize)) {
620 scrollbarAddedOrRemoved = true;
621 sendContentResizedNotification |= changeAffectsContentSize;
625 if (hasVerticalScrollbar != newHasVerticalScrollbar && (hasVerticalScrollbar || !avoidScrollbarCreation())) {
626 if (scrollOrigin().x() && !newHasVerticalScrollbar)
627 ScrollableArea::setScrollOrigin(IntPoint(scrollOrigin().x() - m_verticalScrollbar->width(), scrollOrigin().y()));
628 if (m_verticalScrollbar)
629 m_verticalScrollbar->invalidate();
631 bool changeAffectsContentSize = false;
632 if (setHasVerticalScrollbar(newHasVerticalScrollbar, &changeAffectsContentSize)) {
633 scrollbarAddedOrRemoved = true;
634 sendContentResizedNotification |= changeAffectsContentSize;
638 if ((sendContentResizedNotification || needAnotherPass) && m_updateScrollbarsPass < cMaxUpdateScrollbarsPass) {
639 m_updateScrollbarsPass++;
641 visibleContentsResized();
642 IntSize newDocSize = totalContentsSize();
643 if (newDocSize == docSize) {
644 // The layout with the new scroll state had no impact on
645 // the document's overall size, so updateScrollbars didn't get called.
647 updateScrollbars(desiredOffset);
649 m_updateScrollbarsPass--;
653 if (scrollbarAddedOrRemoved)
654 addedOrRemovedScrollbar();
656 // Set up the range (and page step/line step), but only do this if we're not in a nested call (to avoid
657 // doing it multiple times).
658 if (m_updateScrollbarsPass)
661 m_inUpdateScrollbars = true;
663 if (m_horizontalScrollbar) {
664 int clientWidth = visibleWidth();
665 int pageStep = std::max(std::max<int>(clientWidth * Scrollbar::minFractionToStepWhenPaging(), clientWidth - Scrollbar::maxOverlapBetweenPages()), 1);
666 IntRect oldRect(m_horizontalScrollbar->frameRect());
668 height() - m_horizontalScrollbar->height(),
669 width() - (m_verticalScrollbar ? m_verticalScrollbar->width() : 0),
670 m_horizontalScrollbar->height());
671 m_horizontalScrollbar->setFrameRect(hBarRect);
672 if (!m_scrollbarsSuppressed && oldRect != m_horizontalScrollbar->frameRect())
673 m_horizontalScrollbar->invalidate();
675 if (m_scrollbarsSuppressed)
676 m_horizontalScrollbar->setSuppressInvalidation(true);
677 m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth);
678 m_horizontalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
679 m_horizontalScrollbar->setProportion(clientWidth, contentsWidth());
680 if (m_scrollbarsSuppressed)
681 m_horizontalScrollbar->setSuppressInvalidation(false);
684 if (m_verticalScrollbar) {
685 int clientHeight = visibleHeight();
686 int pageStep = std::max(std::max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1);
687 IntRect oldRect(m_verticalScrollbar->frameRect());
688 IntRect vBarRect(width() - m_verticalScrollbar->width(),
690 m_verticalScrollbar->width(),
691 height() - topContentInset() - (m_horizontalScrollbar ? m_horizontalScrollbar->height() : 0));
692 m_verticalScrollbar->setFrameRect(vBarRect);
693 if (!m_scrollbarsSuppressed && oldRect != m_verticalScrollbar->frameRect())
694 m_verticalScrollbar->invalidate();
696 if (m_scrollbarsSuppressed)
697 m_verticalScrollbar->setSuppressInvalidation(true);
698 m_verticalScrollbar->setEnabled(totalContentsSize().height() > clientHeight);
699 m_verticalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
700 m_verticalScrollbar->setProportion(clientHeight, totalContentsSize().height());
701 if (m_scrollbarsSuppressed)
702 m_verticalScrollbar->setSuppressInvalidation(false);
705 if (hasHorizontalScrollbar != newHasHorizontalScrollbar || hasVerticalScrollbar != newHasVerticalScrollbar) {
706 // FIXME: Is frameRectsChanged really necessary here? Have any frame rects changed?
708 positionScrollbarLayers();
709 updateScrollCorner();
710 if (!m_horizontalScrollbar && !m_verticalScrollbar)
711 invalidateScrollCornerRect(oldScrollCornerRect);
714 IntPoint adjustedScrollPosition = IntPoint(desiredOffset);
715 if (!isRubberBandInProgress())
716 adjustedScrollPosition = adjustScrollPositionWithinRange(adjustedScrollPosition);
718 if (adjustedScrollPosition != scrollPosition() || scrollOriginChanged()) {
719 ScrollableArea::scrollToOffsetWithoutAnimation(adjustedScrollPosition + toIntSize(scrollOrigin()));
720 resetScrollOriginChanged();
723 // Make sure the scrollbar offsets are up to date.
724 if (m_horizontalScrollbar)
725 m_horizontalScrollbar->offsetDidChange();
726 if (m_verticalScrollbar)
727 m_verticalScrollbar->offsetDidChange();
729 m_inUpdateScrollbars = false;
732 const int panIconSizeLength = 16;
734 IntRect ScrollView::rectToCopyOnScroll() const
736 IntRect scrollViewRect = convertToRootView(IntRect(0, 0, visibleWidth(), visibleHeight()));
737 if (hasOverlayScrollbars()) {
738 int verticalScrollbarWidth = (verticalScrollbar() && !hasLayerForVerticalScrollbar()) ? verticalScrollbar()->width() : 0;
739 int horizontalScrollbarHeight = (horizontalScrollbar() && !hasLayerForHorizontalScrollbar()) ? horizontalScrollbar()->height() : 0;
741 scrollViewRect.setWidth(scrollViewRect.width() - verticalScrollbarWidth);
742 scrollViewRect.setHeight(scrollViewRect.height() - horizontalScrollbarHeight);
744 return scrollViewRect;
747 void ScrollView::scrollContents(const IntSize& scrollDelta)
749 HostWindow* window = hostWindow();
753 // Since scrolling is double buffered, we will be blitting the scroll view's intersection
754 // with the clip rect every time to keep it smooth.
755 IntRect clipRect = windowClipRect();
756 IntRect scrollViewRect = rectToCopyOnScroll();
757 IntRect updateRect = clipRect;
758 updateRect.intersect(scrollViewRect);
760 // Invalidate the root view (not the backing store).
761 window->invalidateRootView(updateRect);
763 if (m_drawPanScrollIcon) {
764 // FIXME: the pan icon is broken when accelerated compositing is on, since it will draw under the compositing layers.
765 // https://bugs.webkit.org/show_bug.cgi?id=47837
766 int panIconDirtySquareSizeLength = 2 * (panIconSizeLength + std::max(abs(scrollDelta.width()), abs(scrollDelta.height()))); // We only want to repaint what's necessary
767 IntPoint panIconDirtySquareLocation = IntPoint(m_panScrollIconPoint.x() - (panIconDirtySquareSizeLength / 2), m_panScrollIconPoint.y() - (panIconDirtySquareSizeLength / 2));
768 IntRect panScrollIconDirtyRect = IntRect(panIconDirtySquareLocation, IntSize(panIconDirtySquareSizeLength, panIconDirtySquareSizeLength));
769 panScrollIconDirtyRect.intersect(clipRect);
770 window->invalidateContentsAndRootView(panScrollIconDirtyRect);
773 if (canBlitOnScroll()) { // The main frame can just blit the WebView window
774 // FIXME: Find a way to scroll subframes with this faster path
775 if (!scrollContentsFastPath(-scrollDelta, scrollViewRect, clipRect))
776 scrollContentsSlowPath(updateRect);
778 // We need to go ahead and repaint the entire backing store. Do it now before moving the
780 scrollContentsSlowPath(updateRect);
783 // Invalidate the overhang areas if they are visible.
784 updateOverhangAreas();
786 // This call will move children with native widgets (plugins) and invalidate them as well.
789 // Now blit the backingstore into the window which should be very fast.
790 window->invalidateRootView(IntRect());
793 bool ScrollView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
795 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
799 void ScrollView::scrollContentsSlowPath(const IntRect& updateRect)
801 hostWindow()->invalidateContentsForSlowScroll(updateRect);
804 IntPoint ScrollView::rootViewToContents(const IntPoint& rootViewPoint) const
806 if (delegatesScrolling())
807 return convertFromRootView(rootViewPoint);
809 IntPoint viewPoint = convertFromRootView(rootViewPoint);
810 return viewPoint + scrollOffsetRelativeToDocument();
813 IntPoint ScrollView::contentsToRootView(const IntPoint& contentsPoint) const
815 if (delegatesScrolling())
816 return convertToRootView(contentsPoint);
818 IntPoint viewPoint = contentsPoint + IntSize(0, headerHeight() + topContentInset()) - scrollOffset();
819 return convertToRootView(viewPoint);
822 IntRect ScrollView::rootViewToContents(const IntRect& rootViewRect) const
824 if (delegatesScrolling())
825 return convertFromRootView(rootViewRect);
827 IntRect viewRect = convertFromRootView(rootViewRect);
828 viewRect.move(scrollOffsetRelativeToDocument());
832 IntRect ScrollView::contentsToRootView(const IntRect& contentsRect) const
834 if (delegatesScrolling())
835 return convertToRootView(contentsRect);
837 IntRect viewRect = contentsRect;
838 viewRect.move(-scrollOffset() + IntSize(0, headerHeight() + topContentInset()));
839 return convertToRootView(viewRect);
842 IntPoint ScrollView::rootViewToTotalContents(const IntPoint& rootViewPoint) const
844 if (delegatesScrolling())
845 return convertFromRootView(rootViewPoint);
847 IntPoint viewPoint = convertFromRootView(rootViewPoint);
848 return viewPoint + scrollOffset();
851 IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const
853 if (delegatesScrolling())
854 return convertFromContainingWindow(windowPoint);
856 IntPoint viewPoint = convertFromContainingWindow(windowPoint);
857 return viewPoint + scrollOffsetRelativeToDocument();
860 IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const
862 if (delegatesScrolling())
863 return convertToContainingWindow(contentsPoint);
865 IntPoint viewPoint = contentsPoint + IntSize(0, headerHeight() + topContentInset()) - scrollOffset();
866 return convertToContainingWindow(viewPoint);
869 IntRect ScrollView::windowToContents(const IntRect& windowRect) const
871 if (delegatesScrolling())
872 return convertFromContainingWindow(windowRect);
874 IntRect viewRect = convertFromContainingWindow(windowRect);
875 viewRect.move(scrollOffsetRelativeToDocument());
879 IntRect ScrollView::contentsToWindow(const IntRect& contentsRect) const
881 if (delegatesScrolling())
882 return convertToContainingWindow(contentsRect);
884 IntRect viewRect = contentsRect;
885 viewRect.move(-scrollOffset() + IntSize(0, headerHeight() + topContentInset()));
886 return convertToContainingWindow(viewRect);
889 IntRect ScrollView::contentsToScreen(const IntRect& rect) const
891 HostWindow* window = hostWindow();
892 if (platformWidget())
893 return platformContentsToScreen(rect);
896 return window->rootViewToScreen(contentsToRootView(rect));
899 IntPoint ScrollView::screenToContents(const IntPoint& point) const
901 HostWindow* window = hostWindow();
902 if (platformWidget())
903 return platformScreenToContents(point);
906 return rootViewToContents(window->screenToRootView(point));
909 bool ScrollView::containsScrollbarsAvoidingResizer() const
911 return !m_scrollbarsAvoidingResizer;
914 void ScrollView::adjustScrollbarsAvoidingResizerCount(int overlapDelta)
916 int oldCount = m_scrollbarsAvoidingResizer;
917 m_scrollbarsAvoidingResizer += overlapDelta;
919 parent()->adjustScrollbarsAvoidingResizerCount(overlapDelta);
920 else if (!scrollbarsSuppressed()) {
921 // If we went from n to 0 or from 0 to n and we're the outermost view,
922 // we need to invalidate the windowResizerRect(), since it will now need to paint
924 if ((oldCount > 0 && m_scrollbarsAvoidingResizer == 0) ||
925 (oldCount == 0 && m_scrollbarsAvoidingResizer > 0))
926 invalidateRect(windowResizerRect());
930 void ScrollView::setParent(ScrollView* parentView)
932 if (parentView == parent())
935 if (m_scrollbarsAvoidingResizer && parent())
936 parent()->adjustScrollbarsAvoidingResizerCount(-m_scrollbarsAvoidingResizer);
938 Widget::setParent(parentView);
940 if (m_scrollbarsAvoidingResizer && parent())
941 parent()->adjustScrollbarsAvoidingResizerCount(m_scrollbarsAvoidingResizer);
944 void ScrollView::setScrollbarsSuppressed(bool suppressed, bool repaintOnUnsuppress)
946 if (suppressed == m_scrollbarsSuppressed)
949 m_scrollbarsSuppressed = suppressed;
951 if (platformWidget())
952 platformSetScrollbarsSuppressed(repaintOnUnsuppress);
953 else if (repaintOnUnsuppress && !suppressed) {
954 if (m_horizontalScrollbar)
955 m_horizontalScrollbar->invalidate();
956 if (m_verticalScrollbar)
957 m_verticalScrollbar->invalidate();
959 // Invalidate the scroll corner too on unsuppress.
960 invalidateRect(scrollCornerRect());
964 Scrollbar* ScrollView::scrollbarAtPoint(const IntPoint& windowPoint)
966 if (platformWidget())
969 IntPoint viewPoint = convertFromContainingWindow(windowPoint);
970 if (m_horizontalScrollbar && m_horizontalScrollbar->shouldParticipateInHitTesting() && m_horizontalScrollbar->frameRect().contains(viewPoint))
971 return m_horizontalScrollbar.get();
972 if (m_verticalScrollbar && m_verticalScrollbar->shouldParticipateInHitTesting() && m_verticalScrollbar->frameRect().contains(viewPoint))
973 return m_verticalScrollbar.get();
977 void ScrollView::setScrollbarOverlayStyle(ScrollbarOverlayStyle overlayStyle)
979 ScrollableArea::setScrollbarOverlayStyle(overlayStyle);
980 platformSetScrollbarOverlayStyle(overlayStyle);
983 void ScrollView::setFrameRect(const IntRect& newRect)
985 IntRect oldRect = frameRect();
987 if (newRect == oldRect)
990 Widget::setFrameRect(newRect);
994 updateScrollbars(scrollOffset());
996 if (!m_useFixedLayout && oldRect.size() != newRect.size())
1000 void ScrollView::frameRectsChanged()
1002 if (platformWidget())
1005 HashSet<RefPtr<Widget>>::const_iterator end = m_children.end();
1006 for (HashSet<RefPtr<Widget>>::const_iterator current = m_children.begin(); current != end; ++current)
1007 (*current)->frameRectsChanged();
1010 void ScrollView::clipRectChanged()
1012 HashSet<RefPtr<Widget>>::const_iterator end = m_children.end();
1013 for (HashSet<RefPtr<Widget>>::const_iterator current = m_children.begin(); current != end; ++current)
1014 (*current)->clipRectChanged();
1017 static void positionScrollbarLayer(GraphicsLayer* graphicsLayer, Scrollbar* scrollbar)
1019 if (!graphicsLayer || !scrollbar)
1022 IntRect scrollbarRect = scrollbar->frameRect();
1023 graphicsLayer->setPosition(scrollbarRect.location());
1025 if (scrollbarRect.size() == graphicsLayer->size())
1028 graphicsLayer->setSize(scrollbarRect.size());
1030 if (graphicsLayer->hasContentsLayer()) {
1031 graphicsLayer->setContentsRect(IntRect(0, 0, scrollbarRect.width(), scrollbarRect.height()));
1035 graphicsLayer->setDrawsContent(true);
1036 graphicsLayer->setNeedsDisplay();
1039 static void positionScrollCornerLayer(GraphicsLayer* graphicsLayer, const IntRect& cornerRect)
1043 graphicsLayer->setDrawsContent(!cornerRect.isEmpty());
1044 graphicsLayer->setPosition(cornerRect.location());
1045 if (cornerRect.size() != graphicsLayer->size())
1046 graphicsLayer->setNeedsDisplay();
1047 graphicsLayer->setSize(cornerRect.size());
1050 void ScrollView::positionScrollbarLayers()
1052 positionScrollbarLayer(layerForHorizontalScrollbar(), horizontalScrollbar());
1053 positionScrollbarLayer(layerForVerticalScrollbar(), verticalScrollbar());
1054 positionScrollCornerLayer(layerForScrollCorner(), scrollCornerRect());
1057 void ScrollView::repaintContentRectangle(const IntRect& rect)
1059 IntRect paintRect = rect;
1060 if (clipsRepaints() && !paintsEntireContents())
1061 paintRect.intersect(visibleContentRect(LegacyIOSDocumentVisibleRect));
1062 if (paintRect.isEmpty())
1065 if (platformWidget()) {
1066 notifyPageThatContentAreaWillPaint();
1067 platformRepaintContentRectangle(paintRect);
1071 if (HostWindow* window = hostWindow())
1072 window->invalidateContentsAndRootView(contentsToWindow(paintRect));
1075 IntRect ScrollView::scrollCornerRect() const
1079 if (hasOverlayScrollbars())
1082 int heightTrackedByScrollbar = height() - topContentInset();
1084 if (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0) {
1085 cornerRect.unite(IntRect(m_horizontalScrollbar->width(),
1086 height() - m_horizontalScrollbar->height(),
1087 width() - m_horizontalScrollbar->width(),
1088 m_horizontalScrollbar->height()));
1091 if (m_verticalScrollbar && heightTrackedByScrollbar - m_verticalScrollbar->height() > 0) {
1092 cornerRect.unite(IntRect(width() - m_verticalScrollbar->width(),
1093 m_verticalScrollbar->height() + topContentInset(),
1094 m_verticalScrollbar->width(),
1095 heightTrackedByScrollbar - m_verticalScrollbar->height()));
1101 bool ScrollView::isScrollCornerVisible() const
1103 return !scrollCornerRect().isEmpty();
1106 void ScrollView::scrollbarStyleChanged(int, bool forceUpdate)
1112 updateScrollbars(scrollOffset());
1113 positionScrollbarLayers();
1116 void ScrollView::updateScrollCorner()
1120 void ScrollView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
1122 ScrollbarTheme::theme()->paintScrollCorner(this, context, cornerRect);
1125 void ScrollView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
1127 bar->paint(context, rect);
1130 void ScrollView::invalidateScrollCornerRect(const IntRect& rect)
1132 invalidateRect(rect);
1135 void ScrollView::paintScrollbars(GraphicsContext* context, const IntRect& rect)
1137 if (m_horizontalScrollbar && !layerForHorizontalScrollbar())
1138 paintScrollbar(context, m_horizontalScrollbar.get(), rect);
1139 if (m_verticalScrollbar && !layerForVerticalScrollbar())
1140 paintScrollbar(context, m_verticalScrollbar.get(), rect);
1142 if (layerForScrollCorner())
1145 paintScrollCorner(context, scrollCornerRect());
1148 void ScrollView::paintPanScrollIcon(GraphicsContext* context)
1150 static Image* panScrollIcon = Image::loadPlatformResource("panIcon").leakRef();
1151 IntPoint iconGCPoint = m_panScrollIconPoint;
1153 iconGCPoint = parent()->windowToContents(iconGCPoint);
1154 context->drawImage(panScrollIcon, ColorSpaceDeviceRGB, iconGCPoint);
1157 void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
1159 if (platformWidget()) {
1160 Widget::paint(context, rect);
1164 if (context->paintingDisabled() && !context->updatingControlTints())
1167 notifyPageThatContentAreaWillPaint();
1169 IntRect documentDirtyRect = rect;
1170 if (!paintsEntireContents()) {
1171 IntRect visibleAreaWithoutScrollbars(location(), visibleContentRect(LegacyIOSDocumentVisibleRect).size());
1172 documentDirtyRect.intersect(visibleAreaWithoutScrollbars);
1175 if (!documentDirtyRect.isEmpty()) {
1176 GraphicsContextStateSaver stateSaver(*context);
1178 context->translate(x(), y());
1179 documentDirtyRect.moveBy(-location());
1181 if (!paintsEntireContents()) {
1182 context->translate(-scrollX(), -scrollY());
1183 documentDirtyRect.moveBy(scrollPosition());
1185 context->clip(visibleContentRect(LegacyIOSDocumentVisibleRect));
1188 paintContents(context, documentDirtyRect);
1191 #if ENABLE(RUBBER_BANDING)
1192 if (!layerForOverhangAreas())
1193 calculateAndPaintOverhangAreas(context, rect);
1195 calculateAndPaintOverhangAreas(context, rect);
1198 // Now paint the scrollbars.
1199 if (!m_scrollbarsSuppressed && (m_horizontalScrollbar || m_verticalScrollbar)) {
1200 GraphicsContextStateSaver stateSaver(*context);
1201 IntRect scrollViewDirtyRect = rect;
1202 IntRect visibleAreaWithScrollbars(location(), unobscuredContentRectIncludingScrollbars().size());
1203 scrollViewDirtyRect.intersect(visibleAreaWithScrollbars);
1204 context->translate(x(), y());
1205 scrollViewDirtyRect.moveBy(-location());
1207 paintScrollbars(context, scrollViewDirtyRect);
1210 // Paint the panScroll Icon
1211 if (m_drawPanScrollIcon)
1212 paintPanScrollIcon(context);
1215 void ScrollView::calculateOverhangAreasForPainting(IntRect& horizontalOverhangRect, IntRect& verticalOverhangRect)
1217 int verticalScrollbarWidth = (verticalScrollbar() && !verticalScrollbar()->isOverlayScrollbar())
1218 ? verticalScrollbar()->width() : 0;
1219 int horizontalScrollbarHeight = (horizontalScrollbar() && !horizontalScrollbar()->isOverlayScrollbar())
1220 ? horizontalScrollbar()->height() : 0;
1222 int physicalScrollY = scrollPosition().y() + scrollOrigin().y();
1223 if (physicalScrollY < 0) {
1224 horizontalOverhangRect = frameRect();
1225 horizontalOverhangRect.setHeight(-physicalScrollY);
1226 horizontalOverhangRect.setWidth(horizontalOverhangRect.width() - verticalScrollbarWidth);
1227 } else if (totalContentsSize().height() && physicalScrollY > totalContentsSize().height() - visibleHeight()) {
1228 int height = physicalScrollY - (totalContentsSize().height() - visibleHeight());
1229 horizontalOverhangRect = frameRect();
1230 horizontalOverhangRect.setY(frameRect().maxY() - height - horizontalScrollbarHeight);
1231 horizontalOverhangRect.setHeight(height);
1232 horizontalOverhangRect.setWidth(horizontalOverhangRect.width() - verticalScrollbarWidth);
1235 int physicalScrollX = scrollPosition().x() + scrollOrigin().x();
1236 if (physicalScrollX < 0) {
1237 verticalOverhangRect.setWidth(-physicalScrollX);
1238 verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height() - horizontalScrollbarHeight);
1239 verticalOverhangRect.setX(frameRect().x());
1240 if (horizontalOverhangRect.y() == frameRect().y())
1241 verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.height());
1243 verticalOverhangRect.setY(frameRect().y());
1244 } else if (contentsWidth() && physicalScrollX > contentsWidth() - visibleWidth()) {
1245 int width = physicalScrollX - (contentsWidth() - visibleWidth());
1246 verticalOverhangRect.setWidth(width);
1247 verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height() - horizontalScrollbarHeight);
1248 verticalOverhangRect.setX(frameRect().maxX() - width - verticalScrollbarWidth);
1249 if (horizontalOverhangRect.y() == frameRect().y())
1250 verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.height());
1252 verticalOverhangRect.setY(frameRect().y());
1256 void ScrollView::updateOverhangAreas()
1258 HostWindow* window = hostWindow();
1262 IntRect horizontalOverhangRect;
1263 IntRect verticalOverhangRect;
1264 calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
1265 if (!horizontalOverhangRect.isEmpty())
1266 window->invalidateContentsAndRootView(horizontalOverhangRect);
1267 if (!verticalOverhangRect.isEmpty())
1268 window->invalidateContentsAndRootView(verticalOverhangRect);
1271 void ScrollView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
1273 ScrollbarTheme::theme()->paintOverhangAreas(this, context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
1276 void ScrollView::calculateAndPaintOverhangAreas(GraphicsContext* context, const IntRect& dirtyRect)
1278 IntRect horizontalOverhangRect;
1279 IntRect verticalOverhangRect;
1280 calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
1282 if (dirtyRect.intersects(horizontalOverhangRect) || dirtyRect.intersects(verticalOverhangRect))
1283 paintOverhangAreas(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
1286 bool ScrollView::isPointInScrollbarCorner(const IntPoint& windowPoint)
1288 if (!scrollbarCornerPresent())
1291 IntPoint viewPoint = convertFromContainingWindow(windowPoint);
1293 if (m_horizontalScrollbar) {
1294 int horizontalScrollbarYMin = m_horizontalScrollbar->frameRect().y();
1295 int horizontalScrollbarYMax = m_horizontalScrollbar->frameRect().y() + m_horizontalScrollbar->frameRect().height();
1296 int horizontalScrollbarXMin = m_horizontalScrollbar->frameRect().x() + m_horizontalScrollbar->frameRect().width();
1298 return viewPoint.y() > horizontalScrollbarYMin && viewPoint.y() < horizontalScrollbarYMax && viewPoint.x() > horizontalScrollbarXMin;
1301 int verticalScrollbarXMin = m_verticalScrollbar->frameRect().x();
1302 int verticalScrollbarXMax = m_verticalScrollbar->frameRect().x() + m_verticalScrollbar->frameRect().width();
1303 int verticalScrollbarYMin = m_verticalScrollbar->frameRect().y() + m_verticalScrollbar->frameRect().height();
1305 return viewPoint.x() > verticalScrollbarXMin && viewPoint.x() < verticalScrollbarXMax && viewPoint.y() > verticalScrollbarYMin;
1308 bool ScrollView::scrollbarCornerPresent() const
1310 return (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0)
1311 || (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0);
1314 IntRect ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& localRect) const
1316 // Scrollbars won't be transformed within us
1317 IntRect newRect = localRect;
1318 newRect.moveBy(scrollbar->location());
1322 IntRect ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
1324 IntRect newRect = parentRect;
1325 // Scrollbars won't be transformed within us
1326 newRect.moveBy(-scrollbar->location());
1330 // FIXME: test these on windows
1331 IntPoint ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& localPoint) const
1333 // Scrollbars won't be transformed within us
1334 IntPoint newPoint = localPoint;
1335 newPoint.moveBy(scrollbar->location());
1339 IntPoint ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
1341 IntPoint newPoint = parentPoint;
1342 // Scrollbars won't be transformed within us
1343 newPoint.moveBy(-scrollbar->location());
1347 void ScrollView::setParentVisible(bool visible)
1349 if (isParentVisible() == visible)
1352 Widget::setParentVisible(visible);
1354 if (!isSelfVisible())
1357 HashSet<RefPtr<Widget>>::iterator end = m_children.end();
1358 for (HashSet<RefPtr<Widget>>::iterator it = m_children.begin(); it != end; ++it)
1359 (*it)->setParentVisible(visible);
1362 void ScrollView::show()
1364 if (!isSelfVisible()) {
1365 setSelfVisible(true);
1366 if (isParentVisible()) {
1367 HashSet<RefPtr<Widget>>::iterator end = m_children.end();
1368 for (HashSet<RefPtr<Widget>>::iterator it = m_children.begin(); it != end; ++it)
1369 (*it)->setParentVisible(true);
1376 void ScrollView::hide()
1378 if (isSelfVisible()) {
1379 if (isParentVisible()) {
1380 HashSet<RefPtr<Widget>>::iterator end = m_children.end();
1381 for (HashSet<RefPtr<Widget>>::iterator it = m_children.begin(); it != end; ++it)
1382 (*it)->setParentVisible(false);
1384 setSelfVisible(false);
1390 bool ScrollView::isOffscreen() const
1392 if (platformWidget())
1393 return platformIsOffscreen();
1398 // FIXME: Add a HostWindow::isOffscreen method here. Since only Mac implements this method
1399 // currently, we can add the method when the other platforms decide to implement this concept.
1404 void ScrollView::addPanScrollIcon(const IntPoint& iconPosition)
1406 HostWindow* window = hostWindow();
1409 m_drawPanScrollIcon = true;
1410 m_panScrollIconPoint = IntPoint(iconPosition.x() - panIconSizeLength / 2 , iconPosition.y() - panIconSizeLength / 2) ;
1411 window->invalidateContentsAndRootView(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)));
1414 void ScrollView::removePanScrollIcon()
1416 HostWindow* window = hostWindow();
1419 m_drawPanScrollIcon = false;
1420 window->invalidateContentsAndRootView(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)));
1423 void ScrollView::setScrollOrigin(const IntPoint& origin, bool updatePositionAtAll, bool updatePositionSynchronously)
1425 if (scrollOrigin() == origin)
1428 ScrollableArea::setScrollOrigin(origin);
1430 if (platformWidget()) {
1431 platformSetScrollOrigin(origin, updatePositionAtAll, updatePositionSynchronously);
1435 // Update if the scroll origin changes, since our position will be different if the content size did not change.
1436 if (updatePositionAtAll && updatePositionSynchronously)
1437 updateScrollbars(scrollOffset());
1440 #if !PLATFORM(COCOA)
1442 void ScrollView::platformAddChild(Widget*)
1446 void ScrollView::platformRemoveChild(Widget*)
1452 #if !PLATFORM(COCOA)
1454 void ScrollView::platformSetScrollbarsSuppressed(bool)
1458 void ScrollView::platformSetScrollOrigin(const IntPoint&, bool, bool)
1462 void ScrollView::platformSetScrollbarOverlayStyle(ScrollbarOverlayStyle)
1468 #if !PLATFORM(COCOA)
1470 void ScrollView::platformSetScrollbarModes()
1474 void ScrollView::platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode& vertical) const
1476 horizontal = ScrollbarAuto;
1477 vertical = ScrollbarAuto;
1480 void ScrollView::platformSetCanBlitOnScroll(bool)
1484 bool ScrollView::platformCanBlitOnScroll() const
1489 IntRect ScrollView::platformVisibleContentRect(bool) const
1494 IntSize ScrollView::platformVisibleContentSize(bool) const
1499 void ScrollView::platformSetContentsSize()
1503 IntRect ScrollView::platformContentsToScreen(const IntRect& rect) const
1508 IntPoint ScrollView::platformScreenToContents(const IntPoint& point) const
1513 void ScrollView::platformSetScrollPosition(const IntPoint&)
1517 bool ScrollView::platformScroll(ScrollDirection, ScrollGranularity)
1522 void ScrollView::platformRepaintContentRectangle(const IntRect&)
1526 bool ScrollView::platformIsOffscreen() const