2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "ScrollView.h"
29 #include "GraphicsContext.h"
30 #include "HostWindow.h"
31 #include "PlatformMouseEvent.h"
32 #include "PlatformWheelEvent.h"
33 #include "Scrollbar.h"
34 #include "ScrollbarTheme.h"
35 #include <wtf/StdLibExtras.h>
41 ScrollView::ScrollView()
42 : m_horizontalScrollbarMode(ScrollbarAuto)
43 , m_verticalScrollbarMode(ScrollbarAuto)
44 , m_prohibitsScrolling(false)
45 , m_canBlitOnScroll(true)
46 , m_scrollbarsAvoidingResizer(0)
47 , m_scrollbarsSuppressed(false)
48 , m_inUpdateScrollbars(false)
49 , m_drawPanScrollIcon(false)
50 , m_useFixedLayout(false)
55 ScrollView::~ScrollView()
60 void ScrollView::addChild(Widget* child)
62 ASSERT(child != this && !child->parent());
63 child->setParent(this);
64 m_children.add(child);
65 if (child->platformWidget())
66 platformAddChild(child);
69 void ScrollView::removeChild(Widget* child)
71 ASSERT(child->parent() == this);
73 m_children.remove(child);
74 if (child->platformWidget())
75 platformRemoveChild(child);
78 void ScrollView::setHasHorizontalScrollbar(bool hasBar)
80 if (hasBar && !m_horizontalScrollbar && !platformHasHorizontalAdjustment()) {
81 m_horizontalScrollbar = createScrollbar(HorizontalScrollbar);
82 addChild(m_horizontalScrollbar.get());
83 } else if (!hasBar && m_horizontalScrollbar) {
84 removeChild(m_horizontalScrollbar.get());
85 m_horizontalScrollbar = 0;
89 void ScrollView::setHasVerticalScrollbar(bool hasBar)
91 if (hasBar && !m_verticalScrollbar && !platformHasVerticalAdjustment()) {
92 m_verticalScrollbar = createScrollbar(VerticalScrollbar);
93 addChild(m_verticalScrollbar.get());
94 } else if (!hasBar && m_verticalScrollbar) {
95 removeChild(m_verticalScrollbar.get());
96 m_verticalScrollbar = 0;
100 PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientation)
102 return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
105 void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode)
107 if (horizontalMode == horizontalScrollbarMode() && verticalMode == verticalScrollbarMode())
109 m_horizontalScrollbarMode = horizontalMode;
110 m_verticalScrollbarMode = verticalMode;
111 if (platformWidget())
112 platformSetScrollbarModes();
114 updateScrollbars(scrollOffset());
117 void ScrollView::scrollbarModes(ScrollbarMode& horizontalMode, ScrollbarMode& verticalMode) const
119 if (platformWidget()) {
120 platformScrollbarModes(horizontalMode, verticalMode);
123 horizontalMode = m_horizontalScrollbarMode;
124 verticalMode = m_verticalScrollbarMode;
127 void ScrollView::setCanHaveScrollbars(bool canScroll)
129 ScrollbarMode newHorizontalMode;
130 ScrollbarMode newVerticalMode;
132 scrollbarModes(newHorizontalMode, newVerticalMode);
134 if (canScroll && newVerticalMode == ScrollbarAlwaysOff)
135 newVerticalMode = ScrollbarAuto;
137 newVerticalMode = ScrollbarAlwaysOff;
139 if (canScroll && newHorizontalMode == ScrollbarAlwaysOff)
140 newHorizontalMode = ScrollbarAuto;
142 newHorizontalMode = ScrollbarAlwaysOff;
144 setScrollbarModes(newHorizontalMode, newVerticalMode);
147 void ScrollView::setCanBlitOnScroll(bool b)
149 if (platformWidget()) {
150 platformSetCanBlitOnScroll(b);
154 m_canBlitOnScroll = b;
157 bool ScrollView::canBlitOnScroll() const
159 if (platformWidget())
160 return platformCanBlitOnScroll();
162 return m_canBlitOnScroll;
165 IntRect ScrollView::visibleContentRect(bool includeScrollbars) const
167 if (platformWidget())
168 return platformVisibleContentRect(includeScrollbars);
169 return IntRect(IntPoint(m_scrollOffset.width(), m_scrollOffset.height()),
170 IntSize(max(0, width() - (verticalScrollbar() && !includeScrollbars ? verticalScrollbar()->width() : 0)),
171 max(0, height() - (horizontalScrollbar() && !includeScrollbars ? horizontalScrollbar()->height() : 0))));
174 int ScrollView::layoutWidth() const
176 return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? visibleWidth() : m_fixedLayoutSize.width();
179 int ScrollView::layoutHeight() const
181 return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? visibleHeight() : m_fixedLayoutSize.height();
184 IntSize ScrollView::fixedLayoutSize() const
186 return m_fixedLayoutSize;
189 void ScrollView::setFixedLayoutSize(const IntSize& newSize)
191 if (fixedLayoutSize() == newSize)
193 m_fixedLayoutSize = newSize;
194 updateScrollbars(scrollOffset());
197 bool ScrollView::useFixedLayout() const
199 return m_useFixedLayout;
202 void ScrollView::setUseFixedLayout(bool enable)
204 if (useFixedLayout() == enable)
206 m_useFixedLayout = enable;
207 updateScrollbars(scrollOffset());
210 IntSize ScrollView::contentsSize() const
212 if (platformWidget())
213 return platformContentsSize();
214 return m_contentsSize;
217 void ScrollView::setContentsSize(const IntSize& newSize)
219 if (contentsSize() == newSize)
221 m_contentsSize = newSize;
222 if (platformWidget())
223 platformSetContentsSize();
225 updateScrollbars(scrollOffset());
228 IntPoint ScrollView::maximumScrollPosition() const
230 IntSize maximumOffset = contentsSize() - visibleContentRect().size();
231 maximumOffset.clampNegativeToZero();
232 return IntPoint(maximumOffset.width(), maximumOffset.height());
235 void ScrollView::valueChanged(Scrollbar* scrollbar)
237 // Figure out if we really moved.
238 IntSize newOffset = m_scrollOffset;
240 if (scrollbar == m_horizontalScrollbar)
241 newOffset.setWidth(scrollbar->value());
242 else if (scrollbar == m_verticalScrollbar)
243 newOffset.setHeight(scrollbar->value());
246 IntSize scrollDelta = newOffset - m_scrollOffset;
247 if (scrollDelta == IntSize())
249 m_scrollOffset = newOffset;
251 if (scrollbarsSuppressed())
254 scrollContents(scrollDelta);
257 void ScrollView::scrollRectIntoViewRecursively(const IntRect& r)
259 // FIXME: This method is not transform-aware. It should just be moved to FrameView so that an accurate
260 // position for the child view can be determined.
262 ScrollView* view = this;
264 if (view->prohibitsScrolling()) // Allow the views to scroll into view recursively until we hit one that prohibits scrolling.
266 view->setScrollPosition(rect.location());
267 rect.move(view->x() - view->scrollOffset().width(), view->y() - view->scrollOffset().height());
269 rect.intersect(view->frameRect());
270 view = view->parent();
273 // We may be embedded inside some containing platform scroll view that we don't manage. This is the case
274 // in Mail.app on OS X, for example, where the WebKit view for message bodies is inside a Cocoa NSScrollView
275 // that contains both it and message headers. Let the HostWindow know about this scroll so that it can pass the message
276 // on up the view chain.
277 // This rect is not clamped, since Mail actually relies on receiving an unclamped rect with negative coordinates in order to
278 // expose the headers.
279 hostWindow()->scrollRectIntoView(rect, this);
282 void ScrollView::setScrollPosition(const IntPoint& scrollPoint)
284 if (prohibitsScrolling())
287 if (platformWidget()) {
288 platformSetScrollPosition(scrollPoint);
292 IntPoint newScrollPosition = scrollPoint.shrunkTo(maximumScrollPosition());
293 newScrollPosition.clampNegativeToZero();
295 if (newScrollPosition == scrollPosition())
298 updateScrollbars(IntSize(newScrollPosition.x(), newScrollPosition.y()));
301 bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity)
303 if (platformWidget())
304 return platformScroll(direction, granularity);
306 if (direction == ScrollUp || direction == ScrollDown) {
307 if (m_verticalScrollbar)
308 return m_verticalScrollbar->scroll(direction, granularity);
310 if (m_horizontalScrollbar)
311 return m_horizontalScrollbar->scroll(direction, granularity);
316 void ScrollView::updateScrollbars(const IntSize& desiredOffset)
318 // Don't allow re-entrancy into this function.
319 if (m_inUpdateScrollbars || prohibitsScrolling() || platformWidget())
322 m_inUpdateScrollbars = true;
324 bool hasVerticalScrollbar = m_verticalScrollbar;
325 bool hasHorizontalScrollbar = m_horizontalScrollbar;
326 bool oldHasVertical = hasVerticalScrollbar;
327 bool oldHasHorizontal = hasHorizontalScrollbar;
328 ScrollbarMode hScroll = m_horizontalScrollbarMode;
329 ScrollbarMode vScroll = m_verticalScrollbarMode;
331 const int scrollbarThickness = ScrollbarTheme::nativeTheme()->scrollbarThickness();
333 for (int pass = 0; pass < 2; pass++) {
334 bool scrollsVertically;
335 bool scrollsHorizontally;
337 if (!m_scrollbarsSuppressed && (hScroll == ScrollbarAuto || vScroll == ScrollbarAuto)) {
338 // Do a layout if pending before checking if scrollbars are needed.
339 if (hasVerticalScrollbar != oldHasVertical || hasHorizontalScrollbar != oldHasHorizontal)
340 visibleContentsResized();
342 scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() > height());
343 if (scrollsVertically)
344 scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() + scrollbarThickness > width());
346 scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() > width());
347 if (scrollsHorizontally)
348 scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() + scrollbarThickness > height());
351 scrollsHorizontally = (hScroll == ScrollbarAuto) ? hasHorizontalScrollbar : (hScroll == ScrollbarAlwaysOn);
352 scrollsVertically = (vScroll == ScrollbarAuto) ? hasVerticalScrollbar : (vScroll == ScrollbarAlwaysOn);
355 if (hasVerticalScrollbar != scrollsVertically) {
356 setHasVerticalScrollbar(scrollsVertically);
357 hasVerticalScrollbar = scrollsVertically;
360 if (hasHorizontalScrollbar != scrollsHorizontally) {
361 setHasHorizontalScrollbar(scrollsHorizontally);
362 hasHorizontalScrollbar = scrollsHorizontally;
366 // Set up the range (and page step/line step).
367 IntSize maxScrollPosition(contentsWidth() - visibleWidth(), contentsHeight() - visibleHeight());
368 IntSize scroll = desiredOffset.shrunkTo(maxScrollPosition);
369 scroll.clampNegativeToZero();
371 if (!platformHandleHorizontalAdjustment(scroll) && m_horizontalScrollbar) {
372 int clientWidth = visibleWidth();
373 m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth);
374 int pageStep = (clientWidth - cAmountToKeepWhenPaging);
376 pageStep = clientWidth;
377 IntRect oldRect(m_horizontalScrollbar->frameRect());
378 IntRect hBarRect = IntRect(0,
379 height() - m_horizontalScrollbar->height(),
380 width() - (m_verticalScrollbar ? m_verticalScrollbar->width() : 0),
381 m_horizontalScrollbar->height());
382 m_horizontalScrollbar->setFrameRect(hBarRect);
383 if (!m_scrollbarsSuppressed && oldRect != m_horizontalScrollbar->frameRect())
384 m_horizontalScrollbar->invalidate();
386 if (m_scrollbarsSuppressed)
387 m_horizontalScrollbar->setSuppressInvalidation(true);
388 m_horizontalScrollbar->setSteps(cScrollbarPixelsPerLineStep, pageStep);
389 m_horizontalScrollbar->setProportion(clientWidth, contentsWidth());
390 m_horizontalScrollbar->setValue(scroll.width());
391 if (m_scrollbarsSuppressed)
392 m_horizontalScrollbar->setSuppressInvalidation(false);
395 if (!platformHandleVerticalAdjustment(scroll) && m_verticalScrollbar) {
396 int clientHeight = visibleHeight();
397 m_verticalScrollbar->setEnabled(contentsHeight() > clientHeight);
398 int pageStep = (clientHeight - cAmountToKeepWhenPaging);
400 pageStep = clientHeight;
401 IntRect oldRect(m_verticalScrollbar->frameRect());
402 IntRect vBarRect = IntRect(width() - m_verticalScrollbar->width(),
404 m_verticalScrollbar->width(),
405 height() - (m_horizontalScrollbar ? m_horizontalScrollbar->height() : 0));
406 m_verticalScrollbar->setFrameRect(vBarRect);
407 if (!m_scrollbarsSuppressed && oldRect != m_verticalScrollbar->frameRect())
408 m_verticalScrollbar->invalidate();
410 if (m_scrollbarsSuppressed)
411 m_verticalScrollbar->setSuppressInvalidation(true);
412 m_verticalScrollbar->setSteps(cScrollbarPixelsPerLineStep, pageStep);
413 m_verticalScrollbar->setProportion(clientHeight, contentsHeight());
414 m_verticalScrollbar->setValue(scroll.height());
415 if (m_scrollbarsSuppressed)
416 m_verticalScrollbar->setSuppressInvalidation(false);
419 if (oldHasVertical != (m_verticalScrollbar != 0) || oldHasHorizontal != (m_horizontalScrollbar != 0))
422 // See if our offset has changed in a situation where we might not have scrollbars.
423 // This can happen when editing a body with overflow:hidden and scrolling to reveal selection.
424 // It can also happen when maximizing a window that has scrollbars (but the new maximized result
426 IntSize scrollDelta = scroll - m_scrollOffset;
427 if (scrollDelta != IntSize()) {
428 m_scrollOffset = scroll;
429 scrollContents(scrollDelta);
432 m_inUpdateScrollbars = false;
435 const int panIconSizeLength = 20;
437 void ScrollView::scrollContents(const IntSize& scrollDelta)
442 // Since scrolling is double buffered, we will be blitting the scroll view's intersection
443 // with the clip rect every time to keep it smooth.
444 IntRect clipRect = windowClipRect();
445 IntRect scrollViewRect = convertToContainingWindow(IntRect(0, 0, visibleWidth(), visibleHeight()));
446 IntRect updateRect = clipRect;
447 updateRect.intersect(scrollViewRect);
449 // Invalidate the window (not the backing store).
450 hostWindow()->repaint(updateRect, false);
452 if (m_drawPanScrollIcon) {
453 int panIconDirtySquareSizeLength = 2 * (panIconSizeLength + max(abs(scrollDelta.width()), abs(scrollDelta.height()))); // We only want to repaint what's necessary
454 IntPoint panIconDirtySquareLocation = IntPoint(m_panScrollIconPoint.x() - (panIconDirtySquareSizeLength / 2), m_panScrollIconPoint.y() - (panIconDirtySquareSizeLength / 2));
455 IntRect panScrollIconDirtyRect = IntRect(panIconDirtySquareLocation , IntSize(panIconDirtySquareSizeLength, panIconDirtySquareSizeLength));
456 panScrollIconDirtyRect.intersect(clipRect);
457 hostWindow()->repaint(panScrollIconDirtyRect, true);
460 if (canBlitOnScroll() && !rootPreventsBlitting()) { // The main frame can just blit the WebView window
461 // FIXME: Find a way to blit subframes without blitting overlapping content
462 hostWindow()->scroll(-scrollDelta, scrollViewRect, clipRect);
464 // We need to go ahead and repaint the entire backing store. Do it now before moving the
466 hostWindow()->repaint(updateRect, true, false, true); // Invalidate the backing store and repaint it synchronously
469 // This call will move children with native widgets (plugins) and invalidate them as well.
472 // Now update the window (which should do nothing but a blit of the backing store's updateRect and so should
474 hostWindow()->paint();
477 IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const
479 IntPoint viewPoint = convertFromContainingWindow(windowPoint);
480 return viewPoint + scrollOffset();
483 IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const
485 IntPoint viewPoint = contentsPoint - scrollOffset();
486 return convertToContainingWindow(viewPoint);
489 IntRect ScrollView::windowToContents(const IntRect& windowRect) const
491 IntRect viewRect = convertFromContainingWindow(windowRect);
492 viewRect.move(scrollOffset());
496 IntRect ScrollView::contentsToWindow(const IntRect& contentsRect) const
498 IntRect viewRect = contentsRect;
499 viewRect.move(-scrollOffset());
500 return convertToContainingWindow(viewRect);
503 IntRect ScrollView::contentsToScreen(const IntRect& rect) const
505 if (platformWidget())
506 return platformContentsToScreen(rect);
507 return hostWindow()->windowToScreen(contentsToWindow(rect));
510 IntPoint ScrollView::screenToContents(const IntPoint& point) const
512 if (platformWidget())
513 return platformScreenToContents(point);
514 return windowToContents(hostWindow()->screenToWindow(point));
517 bool ScrollView::containsScrollbarsAvoidingResizer() const
519 return !m_scrollbarsAvoidingResizer;
522 void ScrollView::adjustScrollbarsAvoidingResizerCount(int overlapDelta)
524 int oldCount = m_scrollbarsAvoidingResizer;
525 m_scrollbarsAvoidingResizer += overlapDelta;
527 parent()->adjustScrollbarsAvoidingResizerCount(overlapDelta);
528 else if (!scrollbarsSuppressed()) {
529 // If we went from n to 0 or from 0 to n and we're the outermost view,
530 // we need to invalidate the windowResizerRect(), since it will now need to paint
532 if (oldCount > 0 && m_scrollbarsAvoidingResizer == 0 ||
533 oldCount == 0 && m_scrollbarsAvoidingResizer > 0)
534 invalidateRect(windowResizerRect());
538 void ScrollView::setParent(ScrollView* parentView)
540 if (parentView == parent())
543 if (m_scrollbarsAvoidingResizer && parent())
544 parent()->adjustScrollbarsAvoidingResizerCount(-m_scrollbarsAvoidingResizer);
546 Widget::setParent(parentView);
548 if (m_scrollbarsAvoidingResizer && parent())
549 parent()->adjustScrollbarsAvoidingResizerCount(m_scrollbarsAvoidingResizer);
552 void ScrollView::setScrollbarsSuppressed(bool suppressed, bool repaintOnUnsuppress)
554 if (suppressed == m_scrollbarsSuppressed)
557 m_scrollbarsSuppressed = suppressed;
559 if (platformWidget())
560 platformSetScrollbarsSuppressed(repaintOnUnsuppress);
561 else if (repaintOnUnsuppress && !suppressed) {
562 if (m_horizontalScrollbar)
563 m_horizontalScrollbar->invalidate();
564 if (m_verticalScrollbar)
565 m_verticalScrollbar->invalidate();
567 // Invalidate the scroll corner too on unsuppress.
569 if (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0) {
570 hCorner = IntRect(m_horizontalScrollbar->width(),
571 height() - m_horizontalScrollbar->height(),
572 width() - m_horizontalScrollbar->width(),
573 m_horizontalScrollbar->height());
574 invalidateRect(hCorner);
577 if (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0) {
578 IntRect vCorner(width() - m_verticalScrollbar->width(),
579 m_verticalScrollbar->height(),
580 m_verticalScrollbar->width(),
581 height() - m_verticalScrollbar->height());
582 if (vCorner != hCorner)
583 invalidateRect(vCorner);
588 Scrollbar* ScrollView::scrollbarUnderMouse(const PlatformMouseEvent& mouseEvent)
590 if (platformWidget())
593 IntPoint viewPoint = convertFromContainingWindow(mouseEvent.pos());
594 if (m_horizontalScrollbar && m_horizontalScrollbar->frameRect().contains(viewPoint))
595 return m_horizontalScrollbar.get();
596 if (m_verticalScrollbar && m_verticalScrollbar->frameRect().contains(viewPoint))
597 return m_verticalScrollbar.get();
601 void ScrollView::wheelEvent(PlatformWheelEvent& e)
603 // We don't allow mouse wheeling to happen in a ScrollView that has had its scrollbars explicitly disabled.
604 if (!canHaveScrollbars() || platformWidget())
607 // Determine how much we want to scroll. If we can move at all, we will accept the event.
608 IntSize maxScrollDelta = maximumScrollPosition() - scrollPosition();
609 if ((e.deltaX() < 0 && maxScrollDelta.width() > 0) ||
610 (e.deltaX() > 0 && scrollOffset().width() > 0) ||
611 (e.deltaY() < 0 && maxScrollDelta.height() > 0) ||
612 (e.deltaY() > 0 && scrollOffset().height() > 0)) {
614 float deltaX = e.deltaX();
615 float deltaY = e.deltaY();
616 if (e.granularity() == ScrollByLineWheelEvent) {
617 deltaX *= cMouseWheelPixelsPerLineStep;
618 deltaY *= cMouseWheelPixelsPerLineStep;
619 } else if (e.granularity() == ScrollByPageWheelEvent) {
621 bool negative = deltaY < 0;
622 deltaY = max(0, visibleHeight() - cAmountToKeepWhenPaging);
626 scrollBy(IntSize(-deltaX, -deltaY));
630 void ScrollView::setFrameRect(const IntRect& newRect)
632 IntRect oldRect = frameRect();
634 if (newRect == oldRect)
637 Widget::setFrameRect(newRect);
639 if (platformWidget())
642 if (newRect.width() != oldRect.width() || newRect.height() != oldRect.height()) {
643 updateScrollbars(m_scrollOffset);
650 void ScrollView::frameRectsChanged()
652 if (platformWidget())
655 HashSet<Widget*>::const_iterator end = m_children.end();
656 for (HashSet<Widget*>::const_iterator current = m_children.begin(); current != end; ++current)
657 (*current)->frameRectsChanged();
660 void ScrollView::repaintContentRectangle(const IntRect& rect, bool now)
665 if (platformWidget()) {
666 platformRepaintContentRectangle(rect, now);
670 hostWindow()->repaint(contentsToWindow(rect), true, now);
673 void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
675 if (platformWidget()) {
676 Widget::paint(context, rect);
680 if (context->paintingDisabled() && !context->updatingControlTints())
683 IntRect documentDirtyRect = rect;
684 documentDirtyRect.intersect(frameRect());
688 context->translate(x(), y());
689 documentDirtyRect.move(-x(), -y());
691 context->translate(-scrollX(), -scrollY());
692 documentDirtyRect.move(scrollX(), scrollY());
694 context->clip(visibleContentRect());
696 paintContents(context, documentDirtyRect);
700 // Now paint the scrollbars.
701 if (!m_scrollbarsSuppressed && (m_horizontalScrollbar || m_verticalScrollbar)) {
703 IntRect scrollViewDirtyRect = rect;
704 scrollViewDirtyRect.intersect(frameRect());
705 context->translate(x(), y());
706 scrollViewDirtyRect.move(-x(), -y());
707 if (m_horizontalScrollbar)
708 m_horizontalScrollbar->paint(context, scrollViewDirtyRect);
709 if (m_verticalScrollbar)
710 m_verticalScrollbar->paint(context, scrollViewDirtyRect);
713 if (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0) {
714 hCorner = IntRect(m_horizontalScrollbar->width(),
715 height() - m_horizontalScrollbar->height(),
716 width() - m_horizontalScrollbar->width(),
717 m_horizontalScrollbar->height());
718 if (hCorner.intersects(scrollViewDirtyRect))
719 ScrollbarTheme::nativeTheme()->paintScrollCorner(this, context, hCorner);
722 if (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0) {
723 IntRect vCorner(width() - m_verticalScrollbar->width(),
724 m_verticalScrollbar->height(),
725 m_verticalScrollbar->width(),
726 height() - m_verticalScrollbar->height());
727 if (vCorner != hCorner && vCorner.intersects(scrollViewDirtyRect))
728 ScrollbarTheme::nativeTheme()->paintScrollCorner(this, context, vCorner);
734 // Paint the panScroll Icon
735 if (m_drawPanScrollIcon) {
736 DEFINE_STATIC_LOCAL(RefPtr<Image>, panScrollIcon, (Image::loadPlatformResource("panIcon")));
737 context->drawImage(panScrollIcon.get(), m_panScrollIconPoint);
741 bool ScrollView::scrollbarCornerPresent() const
743 return (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0) ||
744 (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0);
747 void ScrollView::setParentVisible(bool visible)
749 if (isParentVisible() == visible)
752 Widget::setParentVisible(visible);
754 if (!isSelfVisible())
757 HashSet<Widget*>::iterator end = m_children.end();
758 for (HashSet<Widget*>::iterator it = m_children.begin(); it != end; ++it)
759 (*it)->setParentVisible(visible);
762 void ScrollView::show()
764 if (!isSelfVisible()) {
765 setSelfVisible(true);
766 if (isParentVisible()) {
767 HashSet<Widget*>::iterator end = m_children.end();
768 for (HashSet<Widget*>::iterator it = m_children.begin(); it != end; ++it)
769 (*it)->setParentVisible(true);
776 void ScrollView::hide()
778 if (isSelfVisible()) {
779 if (isParentVisible()) {
780 HashSet<Widget*>::iterator end = m_children.end();
781 for (HashSet<Widget*>::iterator it = m_children.begin(); it != end; ++it)
782 (*it)->setParentVisible(false);
784 setSelfVisible(false);
790 bool ScrollView::isOffscreen() const
792 if (platformWidget())
793 return platformIsOffscreen();
798 // FIXME: Add a HostWindow::isOffscreen method here. Since only Mac implements this method
799 // currently, we can add the method when the other platforms decide to implement this concept.
804 void ScrollView::addPanScrollIcon(const IntPoint& iconPosition)
806 m_drawPanScrollIcon = true;
807 m_panScrollIconPoint = IntPoint(iconPosition.x() - panIconSizeLength / 2 , iconPosition.y() - panIconSizeLength / 2) ;
808 hostWindow()->repaint(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength,panIconSizeLength)), true, true);
811 void ScrollView::removePanScrollIcon()
813 m_drawPanScrollIcon = false;
814 hostWindow()->repaint(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)), true, true);
817 #if !PLATFORM(WX) && !PLATFORM(GTK) && !PLATFORM(QT)
818 void ScrollView::platformInit()
822 void ScrollView::platformDestroy()
827 #if !PLATFORM(WX) && !PLATFORM(GTK) && !PLATFORM(QT) && !PLATFORM(MAC)
828 void ScrollView::platformAddChild(Widget*)
832 void ScrollView::platformRemoveChild(Widget*)
838 void ScrollView::platformSetScrollbarsSuppressed(bool repaintOnUnsuppress)
843 #if !PLATFORM(MAC) && !PLATFORM(WX)
844 void ScrollView::platformSetScrollbarModes()
848 void ScrollView::platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode& vertical) const
852 void ScrollView::platformSetCanBlitOnScroll(bool)
856 bool ScrollView::platformCanBlitOnScroll() const
861 IntRect ScrollView::platformVisibleContentRect(bool) const
866 IntSize ScrollView::platformContentsSize() const
871 void ScrollView::platformSetContentsSize()
875 IntRect ScrollView::platformContentsToScreen(const IntRect& rect) const
880 IntPoint ScrollView::platformScreenToContents(const IntPoint& point) const
885 void ScrollView::platformSetScrollPosition(const IntPoint&)
889 bool ScrollView::platformScroll(ScrollDirection, ScrollGranularity)
894 void ScrollView::platformRepaintContentRectangle(const IntRect&, bool now)
898 bool ScrollView::platformIsOffscreen() const
905 bool ScrollView::platformHandleHorizontalAdjustment(const IntSize&)
910 bool ScrollView::platformHandleVerticalAdjustment(const IntSize&)
915 bool ScrollView::platformHasHorizontalAdjustment() const
920 bool ScrollView::platformHasVerticalAdjustment() const