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"
30 #include "ChromeClient.h"
31 #include "FloatRect.h"
33 #include "FrameView.h"
34 #include "GraphicsContext.h"
36 #include "NotImplemented.h"
38 #include "PlatformScrollBar.h"
39 #include "PlatformMouseEvent.h"
40 #include "PlatformWheelEvent.h"
41 #include "RenderTheme.h"
42 #include "ScrollBar.h"
46 #include <wtf/Assertions.h>
47 #include <wtf/HashSet.h>
53 class ScrollView::ScrollViewPrivate : public ScrollbarClient {
55 ScrollViewPrivate(ScrollView* view)
57 , m_hasStaticBackground(false)
58 , m_scrollbarsSuppressed(false)
59 , m_inUpdateScrollbars(false)
60 , m_scrollbarsAvoidingResizer(0)
61 , m_vScrollbarMode(ScrollbarAuto)
62 , m_hScrollbarMode(ScrollbarAuto)
64 , m_attachedToWindow(false)
70 setHasHorizontalScrollbar(false);
71 setHasVerticalScrollbar(false);
74 void setHasHorizontalScrollbar(bool hasBar);
75 void setHasVerticalScrollbar(bool hasBar);
77 virtual void valueChanged(Scrollbar*);
78 virtual IntRect windowClipRect() const;
80 void scrollBackingStore(const IntSize& scrollDelta);
82 void setAllowsScrolling(bool);
83 bool allowsScrolling() const;
86 IntSize m_scrollOffset;
87 IntSize m_contentsSize;
88 bool m_hasStaticBackground;
89 bool m_scrollbarsSuppressed;
90 bool m_inUpdateScrollbars;
91 int m_scrollbarsAvoidingResizer;
92 ScrollbarMode m_vScrollbarMode;
93 ScrollbarMode m_hScrollbarMode;
94 RefPtr<PlatformScrollbar> m_vBar;
95 RefPtr<PlatformScrollbar> m_hBar;
97 HashSet<Widget*> m_children;
99 bool m_attachedToWindow;
102 void ScrollView::ScrollViewPrivate::setHasHorizontalScrollbar(bool hasBar)
104 if (Scrollbar::hasPlatformScrollbars()) {
105 if (hasBar && !m_hBar) {
106 m_hBar = new PlatformScrollbar(this, HorizontalScrollbar, RegularScrollbar);
107 m_view->addChild(m_hBar.get());
108 } else if (!hasBar && m_hBar) {
109 m_view->removeChild(m_hBar.get());
115 void ScrollView::ScrollViewPrivate::setHasVerticalScrollbar(bool hasBar)
117 if (Scrollbar::hasPlatformScrollbars()) {
118 if (hasBar && !m_vBar) {
119 m_vBar = new PlatformScrollbar(this, VerticalScrollbar, RegularScrollbar);
120 m_view->addChild(m_vBar.get());
121 } else if (!hasBar && m_vBar) {
122 m_view->removeChild(m_vBar.get());
128 void ScrollView::ScrollViewPrivate::valueChanged(Scrollbar* bar)
130 // Figure out if we really moved.
131 IntSize newOffset = m_scrollOffset;
134 newOffset.setWidth(bar->value());
135 else if (bar == m_vBar)
136 newOffset.setHeight(bar->value());
138 IntSize scrollDelta = newOffset - m_scrollOffset;
139 if (scrollDelta == IntSize())
141 m_scrollOffset = newOffset;
143 if (m_scrollbarsSuppressed)
146 scrollBackingStore(scrollDelta);
147 static_cast<FrameView*>(m_view)->frame()->sendScrollEvent();
150 void ScrollView::ScrollViewPrivate::scrollBackingStore(const IntSize& scrollDelta)
152 // Since scrolling is double buffered, we will be blitting the scroll view's intersection
153 // with the clip rect every time to keep it smooth.
154 HWND containingWindowHandle = m_view->containingWindow();
155 IntRect clipRect = m_view->windowClipRect();
156 IntRect scrollViewRect = m_view->convertToContainingWindow(IntRect(0, 0, m_view->visibleWidth(), m_view->visibleHeight()));
157 IntRect updateRect = clipRect;
158 updateRect.intersect(scrollViewRect);
160 ::InvalidateRect(containingWindowHandle, &r, false);
162 if (!m_hasStaticBackground) // The main frame can just blit the WebView window
163 // FIXME: Find a way to blit subframes without blitting overlapping content
164 m_view->scrollBackingStore(-scrollDelta.width(), -scrollDelta.height(), scrollViewRect, clipRect);
166 // We need to go ahead and repaint the entire backing store. Do it now before moving the
168 m_view->addToDirtyRegion(updateRect);
169 m_view->updateBackingStore();
172 // This call will move child HWNDs (plugins) and invalidate them as well.
173 m_view->geometryChanged();
175 // Now update the window (which should do nothing but a blit of the backing store's updateRect and so should
177 ::UpdateWindow(containingWindowHandle);
180 void ScrollView::ScrollViewPrivate::setAllowsScrolling(bool flag)
182 if (flag && m_vScrollbarMode == ScrollbarAlwaysOff)
183 m_vScrollbarMode = ScrollbarAuto;
185 m_vScrollbarMode = ScrollbarAlwaysOff;
187 if (flag && m_hScrollbarMode == ScrollbarAlwaysOff)
188 m_hScrollbarMode = ScrollbarAuto;
190 m_hScrollbarMode = ScrollbarAlwaysOff;
192 m_view->updateScrollbars(m_scrollOffset);
195 bool ScrollView::ScrollViewPrivate::allowsScrolling() const
197 // Return YES if either horizontal or vertical scrolling is allowed.
198 return m_hScrollbarMode != ScrollbarAlwaysOff || m_vScrollbarMode != ScrollbarAlwaysOff;
201 IntRect ScrollView::ScrollViewPrivate::windowClipRect() const
203 return static_cast<const FrameView*>(m_view)->windowClipRect(false);
206 ScrollView::ScrollView()
207 : m_data(new ScrollViewPrivate(this))
211 ScrollView::~ScrollView()
216 void ScrollView::updateContents(const IntRect& rect, bool now)
221 IntPoint windowPoint = contentsToWindow(rect.location());
222 IntRect containingWindowRect = rect;
223 containingWindowRect.setLocation(windowPoint);
225 RECT containingWindowRectWin = containingWindowRect;
226 HWND containingWindowHandle = containingWindow();
228 ::InvalidateRect(containingWindowHandle, &containingWindowRectWin, false);
230 // Cache the dirty spot.
231 addToDirtyRegion(containingWindowRect);
234 ::UpdateWindow(containingWindowHandle);
237 void ScrollView::update()
239 ::UpdateWindow(containingWindow());
242 int ScrollView::visibleWidth() const
244 return max(0, width() - (m_data->m_vBar ? m_data->m_vBar->width() : 0));
247 int ScrollView::visibleHeight() const
249 return max(0, height() - (m_data->m_hBar ? m_data->m_hBar->height() : 0));
252 FloatRect ScrollView::visibleContentRect() const
254 return FloatRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
257 FloatRect ScrollView::visibleContentRectConsideringExternalScrollers() const
259 // external scrollers not supported for now
260 return visibleContentRect();
263 void ScrollView::setContentsPos(int newX, int newY)
265 int dx = newX - contentsX();
266 int dy = newY - contentsY();
270 void ScrollView::resizeContents(int w, int h)
272 IntSize newContentsSize(w, h);
273 if (m_data->m_contentsSize != newContentsSize) {
274 m_data->m_contentsSize = newContentsSize;
275 updateScrollbars(m_data->m_scrollOffset);
279 void ScrollView::setFrameGeometry(const IntRect& newGeometry)
281 IntRect oldGeometry = frameGeometry();
282 Widget::setFrameGeometry(newGeometry);
284 if (newGeometry == oldGeometry)
287 if (newGeometry.width() != oldGeometry.width() || newGeometry.height() != oldGeometry.height()) {
288 updateScrollbars(m_data->m_scrollOffset);
289 static_cast<FrameView*>(this)->setNeedsLayout();
295 int ScrollView::contentsX() const
297 return scrollOffset().width();
300 int ScrollView::contentsY() const
302 return scrollOffset().height();
305 int ScrollView::contentsWidth() const
307 return m_data->m_contentsSize.width();
310 int ScrollView::contentsHeight() const
312 return m_data->m_contentsSize.height();
315 IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const
317 IntPoint viewPoint = convertFromContainingWindow(windowPoint);
318 return viewPoint + scrollOffset();
321 IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const
323 IntPoint viewPoint = contentsPoint - scrollOffset();
324 return convertToContainingWindow(viewPoint);
327 IntPoint ScrollView::convertChildToSelf(const Widget* child, const IntPoint& point) const
329 IntPoint newPoint = point;
330 if (child != m_data->m_hBar && child != m_data->m_vBar)
331 newPoint = point - scrollOffset();
332 return Widget::convertChildToSelf(child, newPoint);
335 IntPoint ScrollView::convertSelfToChild(const Widget* child, const IntPoint& point) const
337 IntPoint newPoint = point;
338 if (child != m_data->m_hBar && child != m_data->m_vBar)
339 newPoint = point + scrollOffset();
340 return Widget::convertSelfToChild(child, newPoint);
343 IntSize ScrollView::scrollOffset() const
345 return m_data->m_scrollOffset;
348 IntSize ScrollView::maximumScroll() const
350 IntSize delta = (m_data->m_contentsSize - IntSize(visibleWidth(), visibleHeight())) - scrollOffset();
351 delta.clampNegativeToZero();
355 void ScrollView::scrollBy(int dx, int dy)
357 IntSize scrollOffset = m_data->m_scrollOffset;
358 IntSize newScrollOffset = scrollOffset + IntSize(dx, dy).shrunkTo(maximumScroll());
359 newScrollOffset.clampNegativeToZero();
361 if (newScrollOffset == scrollOffset)
364 updateScrollbars(newScrollOffset);
367 void ScrollView::scrollRectIntoViewRecursively(const IntRect& r)
369 IntPoint p(max(0, r.x()), max(0, r.y()));
370 ScrollView* view = this;
372 view->setContentsPos(p.x(), p.y());
373 p.move(view->x() - view->scrollOffset().width(), view->y() - view->scrollOffset().height());
374 view = static_cast<ScrollView*>(view->parent());
378 WebCore::ScrollbarMode ScrollView::hScrollbarMode() const
380 return m_data->m_hScrollbarMode;
383 WebCore::ScrollbarMode ScrollView::vScrollbarMode() const
385 return m_data->m_vScrollbarMode;
388 void ScrollView::suppressScrollbars(bool suppressed, bool repaintOnSuppress)
390 m_data->m_scrollbarsSuppressed = suppressed;
391 if (repaintOnSuppress && !suppressed) {
393 m_data->m_hBar->invalidate();
395 m_data->m_vBar->invalidate();
397 // Invalidate the scroll corner too on unsuppress.
399 if (m_data->m_hBar && width() - m_data->m_hBar->width() > 0) {
400 hCorner = IntRect(m_data->m_hBar->width(),
401 height() - m_data->m_hBar->height(),
402 width() - m_data->m_hBar->width(),
403 m_data->m_hBar->height());
404 invalidateRect(hCorner);
407 if (m_data->m_vBar && height() - m_data->m_vBar->height() > 0) {
408 IntRect vCorner(width() - m_data->m_vBar->width(),
409 m_data->m_vBar->height(),
410 m_data->m_vBar->width(),
411 height() - m_data->m_vBar->height());
412 if (vCorner != hCorner)
413 invalidateRect(vCorner);
418 void ScrollView::setHScrollbarMode(ScrollbarMode newMode)
420 if (m_data->m_hScrollbarMode != newMode) {
421 m_data->m_hScrollbarMode = newMode;
422 updateScrollbars(m_data->m_scrollOffset);
426 void ScrollView::setVScrollbarMode(ScrollbarMode newMode)
428 if (m_data->m_vScrollbarMode != newMode) {
429 m_data->m_vScrollbarMode = newMode;
430 updateScrollbars(m_data->m_scrollOffset);
434 void ScrollView::setScrollbarsMode(ScrollbarMode newMode)
436 if (m_data->m_hScrollbarMode != newMode ||
437 m_data->m_vScrollbarMode != newMode) {
438 m_data->m_hScrollbarMode = m_data->m_vScrollbarMode = newMode;
439 updateScrollbars(m_data->m_scrollOffset);
443 void ScrollView::setStaticBackground(bool flag)
445 m_data->m_hasStaticBackground = flag;
448 void ScrollView::updateScrollbars(const IntSize& desiredOffset)
450 // Don't allow re-entrancy into this function.
451 if (m_data->m_inUpdateScrollbars)
454 // FIXME: This code is here so we don't have to fork FrameView.h/.cpp.
455 // In the end, FrameView should just merge with ScrollView.
456 if (static_cast<const FrameView*>(this)->frame()->prohibitsScrolling())
459 m_data->m_inUpdateScrollbars = true;
461 bool hasVerticalScrollbar = m_data->m_vBar;
462 bool hasHorizontalScrollbar = m_data->m_hBar;
463 bool oldHasVertical = hasVerticalScrollbar;
464 bool oldHasHorizontal = hasHorizontalScrollbar;
465 ScrollbarMode hScroll = m_data->m_hScrollbarMode;
466 ScrollbarMode vScroll = m_data->m_vScrollbarMode;
468 const int cVerticalWidth = PlatformScrollbar::verticalScrollbarWidth();
469 const int cHorizontalHeight = PlatformScrollbar::horizontalScrollbarHeight();
471 for (int pass = 0; pass < 2; pass++) {
472 bool scrollsVertically;
473 bool scrollsHorizontally;
475 if (!m_data->m_scrollbarsSuppressed && (hScroll == ScrollbarAuto || vScroll == ScrollbarAuto)) {
476 // Do a layout if pending before checking if scrollbars are needed.
477 if (hasVerticalScrollbar != oldHasVertical || hasHorizontalScrollbar != oldHasHorizontal)
478 static_cast<FrameView*>(this)->layout();
480 scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() > height());
481 if (scrollsVertically)
482 scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() + cVerticalWidth > width());
484 scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() > width());
485 if (scrollsHorizontally)
486 scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() + cHorizontalHeight > height());
490 scrollsHorizontally = (hScroll == ScrollbarAuto) ? hasHorizontalScrollbar : (hScroll == ScrollbarAlwaysOn);
491 scrollsVertically = (vScroll == ScrollbarAuto) ? hasVerticalScrollbar : (vScroll == ScrollbarAlwaysOn);
494 if (hasVerticalScrollbar != scrollsVertically) {
495 m_data->setHasVerticalScrollbar(scrollsVertically);
496 hasVerticalScrollbar = scrollsVertically;
499 if (hasHorizontalScrollbar != scrollsHorizontally) {
500 m_data->setHasHorizontalScrollbar(scrollsHorizontally);
501 hasHorizontalScrollbar = scrollsHorizontally;
505 // Set up the range (and page step/line step).
506 IntSize maxScrollPosition(contentsWidth() - visibleWidth(), contentsHeight() - visibleHeight());
507 IntSize scroll = desiredOffset.shrunkTo(maxScrollPosition);
508 scroll.clampNegativeToZero();
510 if (m_data->m_hBar) {
511 int clientWidth = visibleWidth();
512 m_data->m_hBar->setEnabled(contentsWidth() > clientWidth);
513 int pageStep = (clientWidth - PAGE_KEEP);
514 if (pageStep < 0) pageStep = clientWidth;
515 IntRect oldRect(m_data->m_hBar->frameGeometry());
516 IntRect hBarRect = IntRect(0,
517 height() - m_data->m_hBar->height(),
518 width() - (m_data->m_vBar ? m_data->m_vBar->width() : 0),
519 m_data->m_hBar->height());
520 m_data->m_hBar->setRect(hBarRect);
521 if (!m_data->m_scrollbarsSuppressed && oldRect != m_data->m_hBar->frameGeometry())
522 m_data->m_hBar->invalidate();
524 if (m_data->m_scrollbarsSuppressed)
525 m_data->m_hBar->setSuppressInvalidation(true);
526 m_data->m_hBar->setSteps(LINE_STEP, pageStep);
527 m_data->m_hBar->setProportion(clientWidth, contentsWidth());
528 m_data->m_hBar->setValue(scroll.width());
529 if (m_data->m_scrollbarsSuppressed)
530 m_data->m_hBar->setSuppressInvalidation(false);
533 if (m_data->m_vBar) {
534 int clientHeight = visibleHeight();
535 m_data->m_vBar->setEnabled(contentsHeight() > clientHeight);
536 int pageStep = (clientHeight - PAGE_KEEP);
537 if (pageStep < 0) pageStep = clientHeight;
538 IntRect oldRect(m_data->m_vBar->frameGeometry());
539 IntRect vBarRect = IntRect(width() - m_data->m_vBar->width(),
541 m_data->m_vBar->width(),
542 height() - (m_data->m_hBar ? m_data->m_hBar->height() : 0));
543 m_data->m_vBar->setRect(vBarRect);
544 if (!m_data->m_scrollbarsSuppressed && oldRect != m_data->m_vBar->frameGeometry())
545 m_data->m_vBar->invalidate();
547 if (m_data->m_scrollbarsSuppressed)
548 m_data->m_vBar->setSuppressInvalidation(true);
549 m_data->m_vBar->setSteps(LINE_STEP, pageStep);
550 m_data->m_vBar->setProportion(clientHeight, contentsHeight());
551 m_data->m_vBar->setValue(scroll.height());
552 if (m_data->m_scrollbarsSuppressed)
553 m_data->m_vBar->setSuppressInvalidation(false);
556 if (oldHasVertical != (m_data->m_vBar != 0) || oldHasHorizontal != (m_data->m_hBar != 0))
559 // See if our offset has changed in a situation where we might not have scrollbars.
560 // This can happen when editing a body with overflow:hidden and scrolling to reveal selection.
561 // It can also happen when maximizing a window that has scrollbars (but the new maximized result
563 IntSize scrollDelta = scroll - m_data->m_scrollOffset;
564 if (scrollDelta != IntSize()) {
565 m_data->m_scrollOffset = scroll;
566 m_data->scrollBackingStore(scrollDelta);
569 m_data->m_inUpdateScrollbars = false;
572 PlatformScrollbar* ScrollView::scrollbarUnderMouse(const PlatformMouseEvent& mouseEvent)
574 IntPoint viewPoint = convertFromContainingWindow(mouseEvent.pos());
575 if (m_data->m_hBar && m_data->m_hBar->frameGeometry().contains(viewPoint))
576 return m_data->m_hBar.get();
577 if (m_data->m_vBar && m_data->m_vBar->frameGeometry().contains(viewPoint))
578 return m_data->m_vBar.get();
582 void ScrollView::addChild(Widget* child)
584 child->setParent(this);
585 child->setContainingWindow(containingWindow());
586 m_data->m_children.add(child);
589 void ScrollView::removeChild(Widget* child)
592 m_data->m_children.remove(child);
595 void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
597 // FIXME: This code is here so we don't have to fork FrameView.h/.cpp.
598 // In the end, FrameView should just merge with ScrollView.
599 ASSERT(isFrameView());
601 if (context->paintingDisabled())
604 IntRect documentDirtyRect = rect;
605 documentDirtyRect.intersect(frameGeometry());
609 context->translate(x(), y());
610 documentDirtyRect.move(-x(), -y());
612 context->translate(-contentsX(), -contentsY());
613 documentDirtyRect.move(contentsX(), contentsY());
615 context->clip(enclosingIntRect(visibleContentRect()));
617 static_cast<const FrameView*>(this)->frame()->paint(context, documentDirtyRect);
621 // Now paint the scrollbars.
622 if (!m_data->m_scrollbarsSuppressed && (m_data->m_hBar || m_data->m_vBar)) {
624 IntRect scrollViewDirtyRect = rect;
625 scrollViewDirtyRect.intersect(frameGeometry());
626 context->translate(x(), y());
627 scrollViewDirtyRect.move(-x(), -y());
629 m_data->m_hBar->paint(context, scrollViewDirtyRect);
631 m_data->m_vBar->paint(context, scrollViewDirtyRect);
633 // Fill the scroll corner with white.
635 if (m_data->m_hBar && width() - m_data->m_hBar->width() > 0) {
636 hCorner = IntRect(m_data->m_hBar->width(),
637 height() - m_data->m_hBar->height(),
638 width() - m_data->m_hBar->width(),
639 m_data->m_hBar->height());
640 if (hCorner.intersects(scrollViewDirtyRect))
641 context->fillRect(hCorner, Color::white);
644 if (m_data->m_vBar && height() - m_data->m_vBar->height() > 0) {
645 IntRect vCorner(width() - m_data->m_vBar->width(),
646 m_data->m_vBar->height(),
647 m_data->m_vBar->width(),
648 height() - m_data->m_vBar->height());
649 if (vCorner != hCorner && vCorner.intersects(scrollViewDirtyRect))
650 context->fillRect(vCorner, Color::white);
657 void ScrollView::themeChanged()
659 PlatformScrollbar::themeChanged();
660 theme()->themeChanged();
664 void ScrollView::wheelEvent(PlatformWheelEvent& e)
666 if (!m_data->allowsScrolling())
669 // Determine how much we want to scroll. If we can move at all, we will accept the event.
670 IntSize maxScrollDelta = maximumScroll();
671 if ((e.deltaX() < 0 && maxScrollDelta.width() > 0) ||
672 (e.deltaX() > 0 && scrollOffset().width() > 0) ||
673 (e.deltaY() < 0 && maxScrollDelta.height() > 0) ||
674 (e.deltaY() > 0 && scrollOffset().height() > 0)) {
676 scrollBy(-e.deltaX() * LINE_STEP, -e.deltaY() * LINE_STEP);
680 HashSet<Widget*>* ScrollView::children()
682 return &(m_data->m_children);
685 void ScrollView::geometryChanged() const
687 HashSet<Widget*>::const_iterator end = m_data->m_children.end();
688 for (HashSet<Widget*>::const_iterator current = m_data->m_children.begin(); current != end; ++current)
689 (*current)->geometryChanged();
692 bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity)
694 if ((direction == ScrollUp || direction == ScrollDown) && m_data->m_vBar)
695 return m_data->m_vBar->scroll(direction, granularity);
696 else if (m_data->m_hBar)
697 return m_data->m_hBar->scroll(direction, granularity);
700 IntRect ScrollView::windowResizerRect()
702 ASSERT(isFrameView());
703 const FrameView* frameView = static_cast<const FrameView*>(this);
704 Page* page = frameView->frame() ? frameView->frame()->page() : 0;
707 return page->chrome()->windowResizerRect();
710 bool ScrollView::resizerOverlapsContent() const
712 return !m_data->m_scrollbarsAvoidingResizer;
715 void ScrollView::adjustOverlappingScrollbarCount(int overlapDelta)
717 int oldCount = m_data->m_scrollbarsAvoidingResizer;
718 m_data->m_scrollbarsAvoidingResizer += overlapDelta;
719 if (parent() && parent()->isFrameView())
720 static_cast<FrameView*>(parent())->adjustOverlappingScrollbarCount(overlapDelta);
721 else if (!m_data->m_scrollbarsSuppressed) {
722 // If we went from n to 0 or from 0 to n and we're the outermost view,
723 // we need to invalidate the windowResizerRect(), since it will now need to paint
725 if (oldCount > 0 && m_data->m_scrollbarsAvoidingResizer == 0 ||
726 oldCount == 0 && m_data->m_scrollbarsAvoidingResizer > 0)
727 invalidateRect(windowResizerRect());
731 void ScrollView::setParent(ScrollView* parentView)
733 if (!parentView && m_data->m_scrollbarsAvoidingResizer && parent() && parent()->isFrameView())
734 static_cast<FrameView*>(parent())->adjustOverlappingScrollbarCount(false);
735 Widget::setParent(parentView);
738 void ScrollView::attachToWindow()
740 if (m_data->m_attachedToWindow)
743 m_data->m_attachedToWindow = true;
745 if (m_data->m_visible) {
746 HashSet<Widget*>::iterator end = m_data->m_children.end();
747 for (HashSet<Widget*>::iterator it = m_data->m_children.begin(); it != end; ++it)
748 (*it)->attachToWindow();
752 void ScrollView::detachFromWindow()
754 if (!m_data->m_attachedToWindow)
757 if (m_data->m_visible) {
758 HashSet<Widget*>::iterator end = m_data->m_children.end();
759 for (HashSet<Widget*>::iterator it = m_data->m_children.begin(); it != end; ++it)
760 (*it)->detachFromWindow();
763 m_data->m_attachedToWindow = false;
766 void ScrollView::show()
768 if (!m_data->m_visible) {
769 m_data->m_visible = true;
770 if (isAttachedToWindow()) {
771 HashSet<Widget*>::iterator end = m_data->m_children.end();
772 for (HashSet<Widget*>::iterator it = m_data->m_children.begin(); it != end; ++it)
773 (*it)->attachToWindow();
780 void ScrollView::hide()
782 if (m_data->m_visible) {
783 if (isAttachedToWindow()) {
784 HashSet<Widget*>::iterator end = m_data->m_children.end();
785 for (HashSet<Widget*>::iterator it = m_data->m_children.begin(); it != end; ++it)
786 (*it)->detachFromWindow();
788 m_data->m_visible = false;
794 bool ScrollView::isAttachedToWindow() const
796 return m_data->m_attachedToWindow;
799 void ScrollView::addToDirtyRegion(const IntRect& containingWindowRect)
801 ASSERT(isFrameView());
802 const FrameView* frameView = static_cast<const FrameView*>(this);
803 Page* page = frameView->frame() ? frameView->frame()->page() : 0;
806 page->chrome()->addToDirtyRegion(containingWindowRect);
809 void ScrollView::scrollBackingStore(int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect)
811 ASSERT(isFrameView());
812 const FrameView* frameView = static_cast<const FrameView*>(this);
813 Page* page = frameView->frame() ? frameView->frame()->page() : 0;
816 page->chrome()->scrollBackingStore(dx, dy, scrollViewRect, clipRect);
819 void ScrollView::updateBackingStore()
821 ASSERT(isFrameView());
822 const FrameView* frameView = static_cast<const FrameView*>(this);
823 Page* page = frameView->frame() ? frameView->frame()->page() : 0;
826 page->chrome()->updateBackingStore();
829 void ScrollView::setAllowsScrolling(bool flag)
831 m_data->setAllowsScrolling(flag);
834 bool ScrollView::allowsScrolling() const
836 return m_data->allowsScrolling();
839 bool ScrollView::inWindow() const
841 // Needed for back/forward cache.
846 } // namespace WebCore