2 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
3 * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
4 * Copyright (C) 2006 Zack Rusin <zack@kde.org>
5 * Copyright (C) 2006 George Staikos <staikos@kde.org>
6 * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
27 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "ScrollView.h"
34 #include "FrameView.h"
35 #include "FloatRect.h"
37 #include "PlatformMouseEvent.h"
38 #include "PlatformWheelEvent.h"
39 #include "NotImplemented.h"
42 #include "GraphicsContext.h"
43 #include "PlatformScrollBar.h"
49 #include "qwebframe.h"
52 // #define DEBUG_SCROLLVIEW
56 class ScrollView::ScrollViewPrivate : public ScrollbarClient
59 ScrollViewPrivate(ScrollView* view)
61 , m_hasStaticBackground(false)
62 , m_scrollbarsSuppressed(false)
63 , m_inUpdateScrollbars(false)
64 , m_scrollbarsAvoidingResizer(0)
65 , m_vScrollbarMode(ScrollbarAuto)
66 , m_hScrollbarMode(ScrollbarAuto)
68 setHasHorizontalScrollbar(true);
69 setHasVerticalScrollbar(true);
74 setHasHorizontalScrollbar(false);
75 setHasVerticalScrollbar(false);
78 void setHasHorizontalScrollbar(bool hasBar);
79 void setHasVerticalScrollbar(bool hasBar);
81 virtual void valueChanged(Scrollbar*);
82 virtual IntRect windowClipRect() const;
84 void scrollBackingStore(const IntSize& scrollDelta);
87 IntSize m_scrollOffset;
88 IntSize m_contentsSize;
89 bool m_hasStaticBackground;
90 bool m_scrollbarsSuppressed;
91 bool m_inUpdateScrollbars;
92 int m_scrollbarsAvoidingResizer;
93 ScrollbarMode m_vScrollbarMode;
94 ScrollbarMode m_hScrollbarMode;
95 RefPtr<PlatformScrollbar> m_vBar;
96 RefPtr<PlatformScrollbar> m_hBar;
97 QRegion m_dirtyRegion;
98 HashSet<Widget*> m_children;
101 void ScrollView::ScrollViewPrivate::setHasHorizontalScrollbar(bool hasBar)
103 if (Scrollbar::hasPlatformScrollbars()) {
104 if (hasBar && !m_hBar) {
105 m_hBar = new PlatformScrollbar(this, HorizontalScrollbar, RegularScrollbar);
106 m_view->addChild(m_hBar.get());
107 } else if (!hasBar && m_hBar) {
108 m_view->removeChild(m_hBar.get());;
114 void ScrollView::ScrollViewPrivate::setHasVerticalScrollbar(bool hasBar)
116 if (Scrollbar::hasPlatformScrollbars()) {
117 if (hasBar && !m_vBar) {
118 m_vBar = new PlatformScrollbar(this, VerticalScrollbar, RegularScrollbar);
119 m_view->addChild(m_vBar.get());
120 } else if (!hasBar && m_vBar) {
121 m_view->removeChild(m_vBar.get());
127 void ScrollView::ScrollViewPrivate::valueChanged(Scrollbar* bar)
129 // Figure out if we really moved.
130 IntSize newOffset = m_scrollOffset;
133 newOffset.setWidth(bar->value());
134 else if (bar == m_vBar)
135 newOffset.setHeight(bar->value());
137 IntSize scrollDelta = newOffset - m_scrollOffset;
138 if (scrollDelta == IntSize())
140 m_scrollOffset = newOffset;
142 if (m_scrollbarsSuppressed)
145 scrollBackingStore(scrollDelta);
146 static_cast<FrameView*>(m_view)->frame()->sendScrollEvent();
149 void ScrollView::ScrollViewPrivate::scrollBackingStore(const IntSize& scrollDelta)
151 // Since scrolling is double buffered, we will be blitting the scroll view's intersection
152 // with the clip rect every time to keep it smooth.
153 IntRect clipRect = m_view->windowClipRect();
154 IntRect scrollViewRect = m_view->convertToContainingWindow(IntRect(0, 0, m_view->visibleWidth(), m_view->visibleHeight()));
156 IntRect updateRect = clipRect;
157 updateRect.intersect(scrollViewRect);
159 if (!m_hasStaticBackground) {
160 m_view->scrollBackingStore(-scrollDelta.width(), -scrollDelta.height(),
161 scrollViewRect, clipRect);
163 // We need to go ahead and repaint the entire backing store.
167 m_view->geometryChanged();
170 IntRect ScrollView::ScrollViewPrivate::windowClipRect() const
172 return static_cast<const FrameView*>(m_view)->windowClipRect(false);
175 ScrollView::ScrollView()
176 : m_data(new ScrollViewPrivate(this))
180 ScrollView::~ScrollView()
185 PlatformScrollbar *ScrollView::horizontalScrollBar() const
187 return m_data->m_hBar.get();
190 PlatformScrollbar *ScrollView::verticalScrollBar() const
192 return m_data->m_vBar.get();
195 void ScrollView::updateContents(const IntRect& rect, bool now)
200 IntPoint windowPoint = contentsToWindow(rect.location());
201 IntRect containingWindowRect = rect;
202 containingWindowRect.setLocation(windowPoint);
204 //In QWebPage::paintEvent we paint the ev->region().rects()
205 //individually. Unfortunately, webkit expects we'll draw the
206 //boundingrect of all update rects instead. This is unfortunate,
207 //because if we want to draw the scrollbar rects along with the update
208 //rects this results in redrawing the entire page for a 1px scroll.
209 //In light of this we cache the update rects that webkit sends us here
210 //and send the bound along to QWebPage. The cache is cleared everytime
211 //an actual paint occurs in ScrollView::paint...
213 QRect r(containingWindowRect);
214 QWebPage* page = qwebframe()->page();
215 r = r.intersect(QRect(QPoint(0, 0), page->viewportSize()));
218 // Cache the dirty spot.
219 if (!m_data->m_dirtyRegion.isEmpty())
220 m_data->m_dirtyRegion = m_data->m_dirtyRegion.united(QRegion(r));
222 m_data->m_dirtyRegion = QRegion(r);
226 bool painting = containingWindow()->testAttribute(Qt::WA_WState_InPaintEvent);
227 if (painting && now) {
228 QWebPage *page = qobject_cast<QWebPage*>(containingWindow());
230 page->mainFrame()->render(&p, m_data->m_dirtyRegion.boundingRect());
232 containingWindow()->repaint(m_data->m_dirtyRegion.boundingRect());
234 containingWindow()->update(m_data->m_dirtyRegion.boundingRect());
239 void ScrollView::update()
241 QWidget* window = containingWindow();
243 window->update(frameGeometry());
246 int ScrollView::visibleWidth() const
248 return width() - (m_data->m_vBar ? m_data->m_vBar->width() : 0);
251 int ScrollView::visibleHeight() const
253 return height() - (m_data->m_hBar ? m_data->m_hBar->height() : 0);
256 FloatRect ScrollView::visibleContentRect() const
258 return FloatRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
261 FloatRect ScrollView::visibleContentRectConsideringExternalScrollers() const
263 // external scrollers not supported for now
264 return visibleContentRect();
267 void ScrollView::setContentsPos(int newX, int newY)
269 int dx = newX - contentsX();
270 int dy = newY - contentsY();
274 void ScrollView::resizeContents(int w, int h)
276 IntSize newContentsSize(w, h);
277 if (m_data->m_contentsSize != newContentsSize) {
278 m_data->m_contentsSize = newContentsSize;
279 updateScrollbars(m_data->m_scrollOffset);
283 void ScrollView::setFrameGeometry(const IntRect& newGeometry)
285 IntRect oldGeometry = frameGeometry();
286 Widget::setFrameGeometry(newGeometry);
288 if (newGeometry == oldGeometry)
291 if (newGeometry.width() != oldGeometry.width() || newGeometry.height() != oldGeometry.height()) {
292 updateScrollbars(m_data->m_scrollOffset);
293 static_cast<FrameView*>(this)->setNeedsLayout();
299 HashSet<Widget*>* ScrollView::children()
301 return &(m_data->m_children);
304 void ScrollView::geometryChanged() const
306 HashSet<Widget*>::const_iterator end = m_data->m_children.end();
307 for (HashSet<Widget*>::const_iterator current = m_data->m_children.begin(); current != end; ++current)
308 (*current)->geometryChanged();
312 int ScrollView::contentsX() const
314 return scrollOffset().width();
317 int ScrollView::contentsY() const
319 return scrollOffset().height();
322 int ScrollView::contentsWidth() const
324 return m_data->m_contentsSize.width();
327 int ScrollView::contentsHeight() const
329 return m_data->m_contentsSize.height();
332 IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const
334 IntPoint viewPoint = convertFromContainingWindow(windowPoint);
335 return viewPoint + scrollOffset();
338 IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const
340 IntPoint viewPoint = contentsPoint - scrollOffset();
341 return convertToContainingWindow(viewPoint);
344 IntPoint ScrollView::convertChildToSelf(const Widget* child, const IntPoint& point) const
346 IntPoint newPoint = point;
347 if (child != m_data->m_hBar && child != m_data->m_vBar)
348 newPoint = point - scrollOffset();
349 return Widget::convertChildToSelf(child, newPoint);
352 IntPoint ScrollView::convertSelfToChild(const Widget* child, const IntPoint& point) const
354 IntPoint newPoint = point;
355 if (child != m_data->m_hBar && child != m_data->m_vBar)
356 newPoint = point + scrollOffset();
357 return Widget::convertSelfToChild(child, newPoint);
360 IntSize ScrollView::scrollOffset() const
362 return m_data->m_scrollOffset;
365 IntSize ScrollView::maximumScroll() const
367 IntSize delta = (m_data->m_contentsSize - IntSize(visibleWidth(), visibleHeight())) - scrollOffset();
368 delta.clampNegativeToZero();
372 void ScrollView::scrollBy(int dx, int dy)
374 IntSize scrollOffset = m_data->m_scrollOffset;
375 IntSize newScrollOffset = scrollOffset + IntSize(dx, dy).shrunkTo(maximumScroll());
376 newScrollOffset.clampNegativeToZero();
378 if (newScrollOffset == scrollOffset)
381 updateScrollbars(newScrollOffset);
384 void ScrollView::scrollRectIntoViewRecursively(const IntRect& r)
386 IntPoint p(max(0, r.x()), max(0, r.y()));
387 ScrollView* view = this;
388 ScrollView* oldView = view;
390 view->setContentsPos(p.x(), p.y());
391 p.move(view->x() - view->scrollOffset().width(), view->y() - view->scrollOffset().height());
392 view = static_cast<ScrollView*>(parent());
396 WebCore::ScrollbarMode ScrollView::hScrollbarMode() const
398 return m_data->m_hScrollbarMode;
401 WebCore::ScrollbarMode ScrollView::vScrollbarMode() const
403 return m_data->m_vScrollbarMode;
406 void ScrollView::suppressScrollbars(bool suppressed, bool repaintOnSuppress)
408 m_data->m_scrollbarsSuppressed = suppressed;
409 if (repaintOnSuppress && !suppressed) {
411 m_data->m_hBar->invalidate();
413 m_data->m_vBar->invalidate();
415 // Invalidate the scroll corner too on unsuppress.
417 if (m_data->m_hBar && width() - m_data->m_hBar->width() > 0) {
418 hCorner = IntRect(m_data->m_hBar->width(),
419 height() - m_data->m_hBar->height(),
420 width() - m_data->m_hBar->width(),
421 m_data->m_hBar->height());
422 invalidateRect(hCorner);
425 if (m_data->m_vBar && height() - m_data->m_vBar->height() > 0) {
426 IntRect vCorner(width() - m_data->m_vBar->width(),
427 m_data->m_vBar->height(),
428 m_data->m_vBar->width(),
429 height() - m_data->m_vBar->height());
430 if (vCorner != hCorner)
431 invalidateRect(vCorner);
436 void ScrollView::setHScrollbarMode(ScrollbarMode newMode)
438 if (m_data->m_hScrollbarMode != newMode) {
439 m_data->m_hScrollbarMode = newMode;
440 updateScrollbars(m_data->m_scrollOffset);
444 void ScrollView::setVScrollbarMode(ScrollbarMode newMode)
446 if (m_data->m_vScrollbarMode != newMode) {
447 m_data->m_vScrollbarMode = newMode;
448 updateScrollbars(m_data->m_scrollOffset);
452 void ScrollView::setScrollbarsMode(ScrollbarMode newMode)
454 if (m_data->m_hScrollbarMode != newMode ||
455 m_data->m_vScrollbarMode != newMode) {
456 m_data->m_hScrollbarMode = m_data->m_vScrollbarMode = newMode;
457 updateScrollbars(m_data->m_scrollOffset);
461 void ScrollView::setStaticBackground(bool flag)
463 m_data->m_hasStaticBackground = flag;
466 bool ScrollView::inWindow() const
471 void ScrollView::updateScrollbars(const IntSize& desiredOffset)
473 // Don't allow re-entrancy into this function.
474 if (m_data->m_inUpdateScrollbars)
477 // FIXME: This code is here so we don't have to fork FrameView.h/.cpp.
478 // In the end, FrameView should just merge with ScrollView.
479 if (static_cast<const FrameView*>(this)->frame()->prohibitsScrolling())
482 m_data->m_inUpdateScrollbars = true;
484 bool hasVerticalScrollbar = m_data->m_vBar;
485 bool hasHorizontalScrollbar = m_data->m_hBar;
486 bool oldHasVertical = hasVerticalScrollbar;
487 bool oldHasHorizontal = hasHorizontalScrollbar;
488 ScrollbarMode hScroll = m_data->m_hScrollbarMode;
489 ScrollbarMode vScroll = m_data->m_vScrollbarMode;
491 const int cVerticalWidth = PlatformScrollbar::verticalScrollbarWidth();
492 const int cHorizontalHeight = PlatformScrollbar::horizontalScrollbarHeight();
494 for (int pass = 0; pass < 2; pass++) {
495 bool scrollsVertically;
496 bool scrollsHorizontally;
498 if (!m_data->m_scrollbarsSuppressed && (hScroll == ScrollbarAuto || vScroll == ScrollbarAuto)) {
499 // Do a layout if pending before checking if scrollbars are needed.
500 if (hasVerticalScrollbar != oldHasVertical || hasHorizontalScrollbar != oldHasHorizontal)
501 static_cast<FrameView*>(this)->layout();
503 scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() > height());
504 if (scrollsVertically)
505 scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() + cVerticalWidth > width());
507 scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() > width());
508 if (scrollsHorizontally)
509 scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() + cHorizontalHeight > height());
513 scrollsHorizontally = (hScroll == ScrollbarAuto) ? hasHorizontalScrollbar : (hScroll == ScrollbarAlwaysOn);
514 scrollsVertically = (vScroll == ScrollbarAuto) ? hasVerticalScrollbar : (vScroll == ScrollbarAlwaysOn);
517 if (hasVerticalScrollbar != scrollsVertically) {
518 m_data->setHasVerticalScrollbar(scrollsVertically);
519 hasVerticalScrollbar = scrollsVertically;
522 if (hasHorizontalScrollbar != scrollsHorizontally) {
523 m_data->setHasHorizontalScrollbar(scrollsHorizontally);
524 hasHorizontalScrollbar = scrollsHorizontally;
528 // Set up the range (and page step/line step).
529 IntSize maxScrollPosition(contentsWidth() - visibleWidth(), contentsHeight() - visibleHeight());
530 IntSize scroll = desiredOffset.shrunkTo(maxScrollPosition);
531 scroll.clampNegativeToZero();
533 if (m_data->m_hBar) {
534 int clientWidth = visibleWidth();
535 m_data->m_hBar->setEnabled(contentsWidth() > clientWidth);
536 int pageStep = (clientWidth - PAGE_KEEP);
537 if (pageStep < 0) pageStep = clientWidth;
538 IntRect oldRect(m_data->m_hBar->frameGeometry());
539 IntRect hBarRect = IntRect(0,
540 height() - m_data->m_hBar->height(),
541 width() - (m_data->m_vBar ? m_data->m_vBar->width() : 0),
542 m_data->m_hBar->height());
543 m_data->m_hBar->setRect(hBarRect);
544 if (!m_data->m_scrollbarsSuppressed && oldRect != m_data->m_hBar->frameGeometry())
545 m_data->m_hBar->invalidate();
547 m_data->m_hBar->setSteps(LINE_STEP, pageStep);
548 m_data->m_hBar->setProportion(clientWidth, contentsWidth());
549 m_data->m_hBar->setValue(scroll.width());
552 if (m_data->m_vBar) {
553 int clientHeight = visibleHeight();
554 m_data->m_vBar->setEnabled(contentsHeight() > clientHeight);
555 int pageStep = (clientHeight - PAGE_KEEP);
556 if (pageStep < 0) pageStep = clientHeight;
557 IntRect oldRect(m_data->m_vBar->frameGeometry());
558 IntRect vBarRect = IntRect(width() - m_data->m_vBar->width(),
560 m_data->m_vBar->width(),
561 height() - (m_data->m_hBar ? m_data->m_hBar->height() : 0));
562 m_data->m_vBar->setRect(vBarRect);
563 if (!m_data->m_scrollbarsSuppressed && oldRect != m_data->m_vBar->frameGeometry())
564 m_data->m_vBar->invalidate();
566 m_data->m_vBar->setSteps(LINE_STEP, pageStep);
567 m_data->m_vBar->setProportion(clientHeight, contentsHeight());
568 m_data->m_vBar->setValue(scroll.height());
571 if (oldHasVertical != (m_data->m_vBar != 0) || oldHasHorizontal != (m_data->m_hBar != 0))
574 // See if our offset has changed in a situation where we might not have scrollbars.
575 // This can happen when editing a body with overflow:hidden and scrolling to reveal selection.
576 // It can also happen when maximizing a window that has scrollbars (but the new maximized result
578 IntSize scrollDelta = scroll - m_data->m_scrollOffset;
579 if (scrollDelta != IntSize()) {
580 m_data->m_scrollOffset = scroll;
581 m_data->scrollBackingStore(scrollDelta);
584 m_data->m_inUpdateScrollbars = false;
587 PlatformScrollbar* ScrollView::scrollbarUnderMouse(const PlatformMouseEvent& mouseEvent)
589 IntPoint viewPoint = convertFromContainingWindow(mouseEvent.pos());
590 if (m_data->m_hBar && m_data->m_hBar->frameGeometry().contains(viewPoint))
591 return m_data->m_hBar.get();
592 if (m_data->m_vBar && m_data->m_vBar->frameGeometry().contains(viewPoint))
593 return m_data->m_vBar.get();
597 void ScrollView::addChild(Widget* child)
599 QWidget* w = child->qwidget();
601 m_data->m_children.add(child);
603 child->setParent(this);
606 void ScrollView::removeChild(Widget* child)
610 QWidget* w = child->qwidget();
612 m_data->m_children.remove(child);
615 void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
617 Q_ASSERT(isFrameView());
619 m_data->m_dirtyRegion = QRegion(); //clear the cache...
621 if (context->paintingDisabled())
624 IntRect documentDirtyRect = rect;
626 QPainter *p = context->platformContext();
630 QRect canvasRect = frameGeometry();
631 documentDirtyRect.intersect(canvasRect);
632 context->translate(canvasRect.x(), canvasRect.y());
633 documentDirtyRect.move(-canvasRect.x(), -canvasRect.y());
635 context->translate(-contentsX(), -contentsY());
636 documentDirtyRect.move(contentsX(), contentsY());
638 IntRect clipRect = enclosingIntRect(visibleContentRect());
640 context->clip(clipRect);
642 #ifdef DEBUG_SCROLLVIEW
643 qDebug() << "ScrollView::paint --> "
644 << "isSubframe" << (qwebframe() != qwebframe()->page()->mainFrame() ? "true" : "false")
646 << "canvasRect" << canvasRect
647 << "clipRect" << clipRect
648 << "documentDirtyRect" << documentDirtyRect
652 static_cast<const FrameView*>(this)->frame()->paint(context, documentDirtyRect);
656 // Now paint the scrollbars.
657 if (!m_data->m_scrollbarsSuppressed && (m_data->m_hBar || m_data->m_vBar)) {
660 IntRect scrollViewDirtyRect = rect;
661 scrollViewDirtyRect.intersect(canvasRect);
663 context->translate(canvasRect.x(), canvasRect.y());
664 scrollViewDirtyRect.move(-canvasRect.x(), -canvasRect.y());
667 m_data->m_hBar->paint(context, scrollViewDirtyRect);
669 m_data->m_vBar->paint(context, scrollViewDirtyRect);
671 // Fill the scroll corner with white.
673 if (m_data->m_hBar && width() - m_data->m_hBar->width() > 0) {
674 hCorner = IntRect(m_data->m_hBar->width(),
675 height() - m_data->m_hBar->height(),
676 width() - m_data->m_hBar->width(),
677 m_data->m_hBar->height());
678 if (hCorner.intersects(scrollViewDirtyRect))
679 context->fillRect(hCorner, Color::white);
682 if (m_data->m_vBar && height() - m_data->m_vBar->height() > 0) {
683 IntRect vCorner(width() - m_data->m_vBar->width(),
684 m_data->m_vBar->height(),
685 m_data->m_vBar->width(),
686 height() - m_data->m_vBar->height());
687 if (vCorner != hCorner && vCorner.intersects(scrollViewDirtyRect))
688 context->fillRect(vCorner, Color::white);
695 void ScrollView::wheelEvent(PlatformWheelEvent& e)
697 // Determine how much we want to scroll. If we can move at all, we will accept the event.
698 IntSize maxScrollDelta = maximumScroll();
699 if ((e.deltaX() < 0 && maxScrollDelta.width() > 0) ||
700 (e.deltaX() > 0 && scrollOffset().width() > 0) ||
701 (e.deltaY() < 0 && maxScrollDelta.height() > 0) ||
702 (e.deltaY() > 0 && scrollOffset().height() > 0))
705 scrollBy(-e.deltaX() * LINE_STEP, -e.deltaY() * LINE_STEP);
708 bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity)
710 if (direction == ScrollUp || direction == ScrollDown) {
712 return m_data->m_vBar->scroll(direction, granularity);
715 return m_data->m_hBar->scroll(direction, granularity);
720 IntRect ScrollView::windowResizerRect()
722 ASSERT(isFrameView());
723 const FrameView* frameView = static_cast<const FrameView*>(this);
724 Page* page = frameView->frame() ? frameView->frame()->page() : 0;
727 return page->chrome()->windowResizerRect();
730 bool ScrollView::resizerOverlapsContent() const
732 return !m_data->m_scrollbarsAvoidingResizer;
735 void ScrollView::adjustOverlappingScrollbarCount(int overlapDelta)
737 int oldCount = m_data->m_scrollbarsAvoidingResizer;
738 m_data->m_scrollbarsAvoidingResizer += overlapDelta;
739 if (parent() && parent()->isFrameView())
740 static_cast<FrameView*>(parent())->adjustOverlappingScrollbarCount(overlapDelta);
741 else if (!m_data->m_scrollbarsSuppressed) {
742 // If we went from n to 0 or from 0 to n and we're the outermost view,
743 // we need to invalidate the windowResizerRect(), since it will now need to paint
745 if (oldCount > 0 && m_data->m_scrollbarsAvoidingResizer == 0 ||
746 oldCount == 0 && m_data->m_scrollbarsAvoidingResizer > 0)
747 invalidateRect(windowResizerRect());
751 void ScrollView::setParent(ScrollView* parentView)
753 if (!parentView && m_data->m_scrollbarsAvoidingResizer && parent() && parent()->isFrameView())
754 static_cast<FrameView*>(parent())->adjustOverlappingScrollbarCount(false);
755 Widget::setParent(parentView);
758 void ScrollView::addToDirtyRegion(const IntRect& containingWindowRect)
760 ASSERT(isFrameView());
761 const FrameView* frameView = static_cast<const FrameView*>(this);
762 Page* page = frameView->frame() ? frameView->frame()->page() : 0;
765 page->chrome()->addToDirtyRegion(containingWindowRect);
768 void ScrollView::scrollBackingStore(int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect)
770 ASSERT(isFrameView());
771 const FrameView* frameView = static_cast<const FrameView*>(this);
772 Page* page = frameView->frame() ? frameView->frame()->page() : 0;
775 page->chrome()->scrollBackingStore(dx, dy, scrollViewRect, clipRect);
778 void ScrollView::updateBackingStore()
780 ASSERT(isFrameView());
781 const FrameView* frameView = static_cast<const FrameView*>(this);
782 Page* page = frameView->frame() ? frameView->frame()->page() : 0;
785 page->chrome()->updateBackingStore();