Remove ScrollView::platformInit() and ScrollView::platformDestroy()
[WebKit-https.git] / Source / WebCore / platform / ScrollView.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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. 
24  */
25
26 #include "config.h"
27 #include "ScrollView.h"
28
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>
38
39 using namespace std;
40
41 namespace WebCore {
42
43 ScrollView::ScrollView()
44     : m_horizontalScrollbarMode(ScrollbarAuto)
45     , m_verticalScrollbarMode(ScrollbarAuto)
46     , m_horizontalScrollbarLock(false)
47     , m_verticalScrollbarLock(false)
48     , m_prohibitsScrolling(false)
49     , m_canBlitOnScroll(true)
50     , m_scrollbarsAvoidingResizer(0)
51     , m_scrollbarsSuppressed(false)
52     , m_inUpdateScrollbars(false)
53     , m_updateScrollbarsPass(0)
54     , m_drawPanScrollIcon(false)
55     , m_useFixedLayout(false)
56     , m_paintsEntireContents(false)
57     , m_clipsRepaints(true)
58     , m_delegatesScrolling(false)
59 {
60 }
61
62 ScrollView::~ScrollView()
63 {
64 }
65
66 void ScrollView::addChild(PassRefPtr<Widget> prpChild) 
67 {
68     Widget* child = prpChild.get();
69     ASSERT(child != this && !child->parent());
70     child->setParent(this);
71     m_children.add(prpChild);
72     if (child->platformWidget())
73         platformAddChild(child);
74 }
75
76 void ScrollView::removeChild(Widget* child)
77 {
78     ASSERT(child->parent() == this);
79     child->setParent(0);
80     m_children.remove(child);
81     if (child->platformWidget())
82         platformRemoveChild(child);
83 }
84
85 bool ScrollView::setHasHorizontalScrollbar(bool hasBar, bool* contentSizeAffected)
86 {
87     ASSERT(!hasBar || !avoidScrollbarCreation());
88     if (hasBar && !m_horizontalScrollbar) {
89         m_horizontalScrollbar = createScrollbar(HorizontalScrollbar);
90         addChild(m_horizontalScrollbar.get());
91         didAddScrollbar(m_horizontalScrollbar.get(), HorizontalScrollbar);
92         m_horizontalScrollbar->styleChanged();
93         if (contentSizeAffected)
94             *contentSizeAffected = !m_horizontalScrollbar->isOverlayScrollbar();
95         return true;
96     }
97     
98     if (!hasBar && m_horizontalScrollbar) {
99         bool wasOverlayScrollbar = m_horizontalScrollbar->isOverlayScrollbar();
100         willRemoveScrollbar(m_horizontalScrollbar.get(), HorizontalScrollbar);
101         removeChild(m_horizontalScrollbar.get());
102         m_horizontalScrollbar = 0;
103         if (contentSizeAffected)
104             *contentSizeAffected = !wasOverlayScrollbar;
105         return true;
106     }
107
108     return false;
109 }
110
111 bool ScrollView::setHasVerticalScrollbar(bool hasBar, bool* contentSizeAffected)
112 {
113     ASSERT(!hasBar || !avoidScrollbarCreation());
114     if (hasBar && !m_verticalScrollbar) {
115         m_verticalScrollbar = createScrollbar(VerticalScrollbar);
116         addChild(m_verticalScrollbar.get());
117         didAddScrollbar(m_verticalScrollbar.get(), VerticalScrollbar);
118         m_verticalScrollbar->styleChanged();
119         if (contentSizeAffected)
120             *contentSizeAffected = !m_verticalScrollbar->isOverlayScrollbar();
121         return true;
122     }
123     
124     if (!hasBar && m_verticalScrollbar) {
125         bool wasOverlayScrollbar = m_verticalScrollbar->isOverlayScrollbar();
126         willRemoveScrollbar(m_verticalScrollbar.get(), VerticalScrollbar);
127         removeChild(m_verticalScrollbar.get());
128         m_verticalScrollbar = 0;
129         if (contentSizeAffected)
130             *contentSizeAffected = !wasOverlayScrollbar;
131         return true;
132     }
133
134     return false;
135 }
136
137 #if !PLATFORM(GTK)
138 PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientation)
139 {
140     return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
141 }
142
143 void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode,
144                                    bool horizontalLock, bool verticalLock)
145 {
146     bool needsUpdate = false;
147
148     if (horizontalMode != horizontalScrollbarMode() && !m_horizontalScrollbarLock) {
149         m_horizontalScrollbarMode = horizontalMode;
150         needsUpdate = true;
151     }
152
153     if (verticalMode != verticalScrollbarMode() && !m_verticalScrollbarLock) {
154         m_verticalScrollbarMode = verticalMode;
155         needsUpdate = true;
156     }
157
158     if (horizontalLock)
159         setHorizontalScrollbarLock();
160
161     if (verticalLock)
162         setVerticalScrollbarLock();
163
164     if (!needsUpdate)
165         return;
166
167     if (platformWidget())
168         platformSetScrollbarModes();
169     else
170         updateScrollbars(scrollOffset());
171 }
172 #endif
173
174 void ScrollView::scrollbarModes(ScrollbarMode& horizontalMode, ScrollbarMode& verticalMode) const
175 {
176     if (platformWidget()) {
177         platformScrollbarModes(horizontalMode, verticalMode);
178         return;
179     }
180     horizontalMode = m_horizontalScrollbarMode;
181     verticalMode = m_verticalScrollbarMode;
182 }
183
184 void ScrollView::setCanHaveScrollbars(bool canScroll)
185 {
186     ScrollbarMode newHorizontalMode;
187     ScrollbarMode newVerticalMode;
188     
189     scrollbarModes(newHorizontalMode, newVerticalMode);
190     
191     if (canScroll && newVerticalMode == ScrollbarAlwaysOff)
192         newVerticalMode = ScrollbarAuto;
193     else if (!canScroll)
194         newVerticalMode = ScrollbarAlwaysOff;
195     
196     if (canScroll && newHorizontalMode == ScrollbarAlwaysOff)
197         newHorizontalMode = ScrollbarAuto;
198     else if (!canScroll)
199         newHorizontalMode = ScrollbarAlwaysOff;
200     
201     setScrollbarModes(newHorizontalMode, newVerticalMode);
202 }
203
204 void ScrollView::setCanBlitOnScroll(bool b)
205 {
206     if (platformWidget()) {
207         platformSetCanBlitOnScroll(b);
208         return;
209     }
210
211     m_canBlitOnScroll = b;
212 }
213
214 bool ScrollView::canBlitOnScroll() const
215 {
216     if (platformWidget())
217         return platformCanBlitOnScroll();
218
219     return m_canBlitOnScroll;
220 }
221
222 void ScrollView::setPaintsEntireContents(bool paintsEntireContents)
223 {
224     m_paintsEntireContents = paintsEntireContents;
225 }
226
227 void ScrollView::setClipsRepaints(bool clipsRepaints)
228 {
229     m_clipsRepaints = clipsRepaints;
230 }
231
232 void ScrollView::setDelegatesScrolling(bool delegatesScrolling)
233 {
234     if (m_delegatesScrolling == delegatesScrolling)
235         return;
236
237     m_delegatesScrolling = delegatesScrolling;
238     delegatesScrollingDidChange();
239 }
240
241 IntSize ScrollView::unscaledVisibleContentSize(VisibleContentRectIncludesScrollbars scrollbarInclusion) const
242 {
243     if (platformWidget())
244         return platformVisibleContentSize(scrollbarInclusion == IncludeScrollbars);
245
246     if (!m_fixedVisibleContentRect.isEmpty())
247         return m_fixedVisibleContentRect.size();
248
249     int verticalScrollbarWidth = 0;
250     int horizontalScrollbarHeight = 0;
251
252     if (scrollbarInclusion == ExcludeScrollbars) {
253         if (Scrollbar* verticalBar = verticalScrollbar())
254             verticalScrollbarWidth = !verticalBar->isOverlayScrollbar() ? verticalBar->width() : 0;
255         if (Scrollbar* horizontalBar = horizontalScrollbar())
256             horizontalScrollbarHeight = !horizontalBar->isOverlayScrollbar() ? horizontalBar->height() : 0;
257     }
258
259     return IntSize(max(0, width() - verticalScrollbarWidth),
260                    max(0, height() - horizontalScrollbarHeight));
261 }
262
263 #if !PLATFORM(GTK)
264 IntRect ScrollView::visibleContentRect(VisibleContentRectIncludesScrollbars scollbarInclusion) const
265 {
266     if (platformWidget())
267         return platformVisibleContentRect(scollbarInclusion == IncludeScrollbars);
268
269     if (!m_fixedVisibleContentRect.isEmpty())
270         return m_fixedVisibleContentRect;
271
272     FloatSize visibleContentSize = unscaledVisibleContentSize(scollbarInclusion);
273     visibleContentSize.scale(1 / visibleContentScaleFactor());
274     return IntRect(IntPoint(m_scrollOffset), expandedIntSize(visibleContentSize));
275 }
276 #endif
277
278 IntSize ScrollView::layoutSize() const
279 {
280     return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? unscaledVisibleContentSize(ExcludeScrollbars) : m_fixedLayoutSize;
281 }
282
283 IntSize ScrollView::fixedLayoutSize() const
284 {
285     return m_fixedLayoutSize;
286 }
287
288 void ScrollView::setFixedLayoutSize(const IntSize& newSize)
289 {
290     if (fixedLayoutSize() == newSize)
291         return;
292     m_fixedLayoutSize = newSize;
293     if (m_useFixedLayout)
294         fixedLayoutSizeChanged();
295 }
296
297 bool ScrollView::useFixedLayout() const
298 {
299     return m_useFixedLayout;
300 }
301
302 void ScrollView::setUseFixedLayout(bool enable)
303 {
304     if (useFixedLayout() == enable)
305         return;
306     m_useFixedLayout = enable;
307     if (!m_fixedLayoutSize.isEmpty())
308         fixedLayoutSizeChanged();
309 }
310
311 void ScrollView::fixedLayoutSizeChanged()
312 {
313     updateScrollbars(scrollOffset());
314     contentsResized();
315 }
316
317 IntSize ScrollView::contentsSize() const
318 {
319     return m_contentsSize;
320 }
321
322 void ScrollView::setContentsSize(const IntSize& newSize)
323 {
324     if (contentsSize() == newSize)
325         return;
326     m_contentsSize = newSize;
327     if (platformWidget())
328         platformSetContentsSize();
329     else
330         updateScrollbars(scrollOffset());
331     updateOverhangAreas();
332 }
333
334 IntPoint ScrollView::maximumScrollPosition() const
335 {
336     IntPoint maximumOffset(contentsWidth() - visibleWidth() - scrollOrigin().x(), totalContentsSize().height() - visibleHeight() - scrollOrigin().y());
337     maximumOffset.clampNegativeToZero();
338     return maximumOffset;
339 }
340
341 IntPoint ScrollView::minimumScrollPosition() const
342 {
343     return IntPoint(-scrollOrigin().x(), -scrollOrigin().y());
344 }
345
346 IntPoint ScrollView::adjustScrollPositionWithinRange(const IntPoint& scrollPoint) const
347 {
348     if (!constrainsScrollingToContentEdge())
349         return scrollPoint;
350
351     IntPoint newScrollPosition = scrollPoint.shrunkTo(maximumScrollPosition());
352     newScrollPosition = newScrollPosition.expandedTo(minimumScrollPosition());
353     return newScrollPosition;
354 }
355
356 IntSize ScrollView::scrollOffsetRelativeToDocument() const
357 {
358     IntSize scrollOffset = this->scrollOffset();
359     return IntSize(scrollOffset.width(), scrollOffset.height() - headerHeight());
360 }
361
362 IntPoint ScrollView::scrollPositionRelativeToDocument() const
363 {
364     IntPoint scrollPosition = this->scrollPosition();
365     return IntPoint(scrollPosition.x(), scrollPosition.y() - headerHeight());
366 }
367
368 int ScrollView::scrollSize(ScrollbarOrientation orientation) const
369 {
370     // If no scrollbars are present, it does not indicate content is not be scrollable.
371     if (!m_horizontalScrollbar && !m_verticalScrollbar && !prohibitsScrolling()) {
372         IntSize scrollSize = m_contentsSize - visibleContentRect().size();
373         scrollSize.clampNegativeToZero();
374         return orientation == HorizontalScrollbar ? scrollSize.width() : scrollSize.height();
375     }
376
377     Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_horizontalScrollbar : m_verticalScrollbar).get();
378     return scrollbar ? (scrollbar->totalSize() - scrollbar->visibleSize()) : 0;
379 }
380
381 void ScrollView::notifyPageThatContentAreaWillPaint() const
382 {
383 }
384
385 void ScrollView::setScrollOffset(const IntPoint& offset)
386 {
387     int horizontalOffset = offset.x();
388     int verticalOffset = offset.y();
389     if (constrainsScrollingToContentEdge()) {
390         horizontalOffset = max(min(horizontalOffset, contentsWidth() - visibleWidth()), 0);
391         verticalOffset = max(min(verticalOffset, totalContentsSize().height() - visibleHeight()), 0);
392     }
393
394     IntSize newOffset = m_scrollOffset;
395     newOffset.setWidth(horizontalOffset - scrollOrigin().x());
396     newOffset.setHeight(verticalOffset - scrollOrigin().y());
397
398     scrollTo(newOffset);
399 }
400
401 void ScrollView::scrollTo(const IntSize& newOffset)
402 {
403     IntSize scrollDelta = newOffset - m_scrollOffset;
404     if (scrollDelta == IntSize())
405         return;
406     m_scrollOffset = newOffset;
407
408     if (scrollbarsSuppressed())
409         return;
410
411 #if USE(TILED_BACKING_STORE)
412     if (delegatesScrolling()) {
413         hostWindow()->delegatedScrollRequested(IntPoint(newOffset));
414         return;
415     }
416 #endif
417     repaintFixedElementsAfterScrolling();
418     scrollContents(scrollDelta);
419     updateFixedElementsAfterScrolling();
420 }
421
422 int ScrollView::scrollPosition(Scrollbar* scrollbar) const
423 {
424     if (scrollbar->orientation() == HorizontalScrollbar)
425         return scrollPosition().x() + scrollOrigin().x();
426     if (scrollbar->orientation() == VerticalScrollbar)
427         return scrollPosition().y() + scrollOrigin().y();
428     return 0;
429 }
430
431 void ScrollView::setScrollPosition(const IntPoint& scrollPoint)
432 {
433     if (prohibitsScrolling())
434         return;
435
436     if (platformWidget()) {
437         platformSetScrollPosition(scrollPoint);
438         return;
439     }
440
441 #if USE(TILED_BACKING_STORE)
442     if (delegatesScrolling()) {
443         hostWindow()->delegatedScrollRequested(scrollPoint);
444         return;
445     }
446 #endif
447
448     IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint);
449
450     if (newScrollPosition == scrollPosition())
451         return;
452
453     if (requestScrollPositionUpdate(newScrollPosition))
454         return;
455
456     updateScrollbars(IntSize(newScrollPosition.x(), newScrollPosition.y()));
457 }
458
459 bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity)
460 {
461     if (platformWidget())
462         return platformScroll(direction, granularity);
463
464     return ScrollableArea::scroll(direction, granularity);
465 }
466
467 bool ScrollView::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity)
468 {
469     return scroll(logicalToPhysical(direction, isVerticalDocument(), isFlippedDocument()), granularity);
470 }
471
472 IntSize ScrollView::overhangAmount() const
473 {
474     IntSize stretch;
475
476     int physicalScrollY = scrollPosition().y() + scrollOrigin().y();
477     if (physicalScrollY < 0)
478         stretch.setHeight(physicalScrollY);
479     else if (totalContentsSize().height() && physicalScrollY > totalContentsSize().height() - visibleHeight())
480         stretch.setHeight(physicalScrollY - (totalContentsSize().height() - visibleHeight()));
481
482     int physicalScrollX = scrollPosition().x() + scrollOrigin().x();
483     if (physicalScrollX < 0)
484         stretch.setWidth(physicalScrollX);
485     else if (contentsWidth() && physicalScrollX > contentsWidth() - visibleWidth())
486         stretch.setWidth(physicalScrollX - (contentsWidth() - visibleWidth()));
487
488     return stretch;
489 }
490
491 void ScrollView::windowResizerRectChanged()
492 {
493     if (platformWidget())
494         return;
495
496     updateScrollbars(scrollOffset());
497 }
498
499 static const unsigned cMaxUpdateScrollbarsPass = 2;
500
501 void ScrollView::updateScrollbars(const IntSize& desiredOffset)
502 {
503     if (m_inUpdateScrollbars || prohibitsScrolling() || platformWidget())
504         return;
505
506     // If we came in here with the view already needing a layout, then go ahead and do that
507     // first.  (This will be the common case, e.g., when the page changes due to window resizing for example).
508     // This layout will not re-enter updateScrollbars and does not count towards our max layout pass total.
509     if (!m_scrollbarsSuppressed) {
510         m_inUpdateScrollbars = true;
511         visibleContentsResized();
512         m_inUpdateScrollbars = false;
513     }
514
515     IntRect oldScrollCornerRect = scrollCornerRect();
516
517     bool hasHorizontalScrollbar = m_horizontalScrollbar;
518     bool hasVerticalScrollbar = m_verticalScrollbar;
519     
520     bool newHasHorizontalScrollbar = hasHorizontalScrollbar;
521     bool newHasVerticalScrollbar = hasVerticalScrollbar;
522    
523     ScrollbarMode hScroll = m_horizontalScrollbarMode;
524     ScrollbarMode vScroll = m_verticalScrollbarMode;
525
526     if (hScroll != ScrollbarAuto)
527         newHasHorizontalScrollbar = (hScroll == ScrollbarAlwaysOn);
528     if (vScroll != ScrollbarAuto)
529         newHasVerticalScrollbar = (vScroll == ScrollbarAlwaysOn);
530
531     bool scrollbarAddedOrRemoved = false;
532
533     if (m_scrollbarsSuppressed || (hScroll != ScrollbarAuto && vScroll != ScrollbarAuto)) {
534         if (hasHorizontalScrollbar != newHasHorizontalScrollbar && (hasHorizontalScrollbar || !avoidScrollbarCreation())) {
535             if (setHasHorizontalScrollbar(newHasHorizontalScrollbar))
536                 scrollbarAddedOrRemoved = true;
537         }
538
539         if (hasVerticalScrollbar != newHasVerticalScrollbar && (hasVerticalScrollbar || !avoidScrollbarCreation())) {
540             if (setHasVerticalScrollbar(newHasVerticalScrollbar))
541                 scrollbarAddedOrRemoved = true;
542         }
543     } else {
544         bool sendContentResizedNotification = false;
545         
546         IntSize docSize = totalContentsSize();
547         IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size();
548
549         if (hScroll == ScrollbarAuto) {
550             newHasHorizontalScrollbar = docSize.width() > visibleWidth();
551             if (newHasHorizontalScrollbar && !m_updateScrollbarsPass && docSize.width() <= fullVisibleSize.width() && docSize.height() <= fullVisibleSize.height())
552                 newHasHorizontalScrollbar = false;
553         }
554         if (vScroll == ScrollbarAuto) {
555             newHasVerticalScrollbar = docSize.height() > visibleHeight();
556             if (newHasVerticalScrollbar && !m_updateScrollbarsPass && docSize.width() <= fullVisibleSize.width() && docSize.height() <= fullVisibleSize.height())
557                 newHasVerticalScrollbar = false;
558         }
559
560         // If we ever turn one scrollbar off, always turn the other one off too.  Never ever
561         // try to both gain/lose a scrollbar in the same pass.
562         if (!newHasHorizontalScrollbar && hasHorizontalScrollbar && vScroll != ScrollbarAlwaysOn)
563             newHasVerticalScrollbar = false;
564         if (!newHasVerticalScrollbar && hasVerticalScrollbar && hScroll != ScrollbarAlwaysOn)
565             newHasHorizontalScrollbar = false;
566
567         if (hasHorizontalScrollbar != newHasHorizontalScrollbar && (hasHorizontalScrollbar || !avoidScrollbarCreation())) {
568             if (scrollOrigin().y() && !newHasHorizontalScrollbar)
569                 ScrollableArea::setScrollOrigin(IntPoint(scrollOrigin().x(), scrollOrigin().y() - m_horizontalScrollbar->height()));
570             if (m_horizontalScrollbar)
571                 m_horizontalScrollbar->invalidate();
572
573             bool changeAffectsContentSize = false;
574             if (setHasHorizontalScrollbar(newHasHorizontalScrollbar, &changeAffectsContentSize)) {
575                 scrollbarAddedOrRemoved = true;
576                 sendContentResizedNotification |= changeAffectsContentSize;
577             }
578         }
579
580         if (hasVerticalScrollbar != newHasVerticalScrollbar && (hasVerticalScrollbar || !avoidScrollbarCreation())) {
581             if (scrollOrigin().x() && !newHasVerticalScrollbar)
582                 ScrollableArea::setScrollOrigin(IntPoint(scrollOrigin().x() - m_verticalScrollbar->width(), scrollOrigin().y()));
583             if (m_verticalScrollbar)
584                 m_verticalScrollbar->invalidate();
585
586             bool changeAffectsContentSize = false;
587             if (setHasVerticalScrollbar(newHasVerticalScrollbar, &changeAffectsContentSize)) {
588                 scrollbarAddedOrRemoved = true;
589                 sendContentResizedNotification |= changeAffectsContentSize;
590             }
591         }
592
593         if (sendContentResizedNotification && m_updateScrollbarsPass < cMaxUpdateScrollbarsPass) {
594             m_updateScrollbarsPass++;
595             contentsResized();
596             visibleContentsResized();
597             IntSize newDocSize = totalContentsSize();
598             if (newDocSize == docSize) {
599                 // The layout with the new scroll state had no impact on
600                 // the document's overall size, so updateScrollbars didn't get called.
601                 // Recur manually.
602                 updateScrollbars(desiredOffset);
603             }
604             m_updateScrollbarsPass--;
605         }
606
607         if (scrollbarAddedOrRemoved)
608             addedOrRemovedScrollbar();
609     }
610     
611     // Set up the range (and page step/line step), but only do this if we're not in a nested call (to avoid
612     // doing it multiple times).
613     if (m_updateScrollbarsPass)
614         return;
615
616     m_inUpdateScrollbars = true;
617
618     if (m_horizontalScrollbar) {
619         int clientWidth = visibleWidth();
620         int pageStep = max(max<int>(clientWidth * Scrollbar::minFractionToStepWhenPaging(), clientWidth - Scrollbar::maxOverlapBetweenPages()), 1);
621         IntRect oldRect(m_horizontalScrollbar->frameRect());
622         IntRect hBarRect(0,
623                         height() - m_horizontalScrollbar->height(),
624                         width() - (m_verticalScrollbar ? m_verticalScrollbar->width() : 0),
625                         m_horizontalScrollbar->height());
626         m_horizontalScrollbar->setFrameRect(hBarRect);
627         if (!m_scrollbarsSuppressed && oldRect != m_horizontalScrollbar->frameRect())
628             m_horizontalScrollbar->invalidate();
629
630         if (m_scrollbarsSuppressed)
631             m_horizontalScrollbar->setSuppressInvalidation(true);
632         m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth);
633         m_horizontalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
634         m_horizontalScrollbar->setProportion(clientWidth, contentsWidth());
635         if (m_scrollbarsSuppressed)
636             m_horizontalScrollbar->setSuppressInvalidation(false); 
637     } 
638
639     if (m_verticalScrollbar) {
640         int clientHeight = visibleHeight();
641         int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1);
642         IntRect oldRect(m_verticalScrollbar->frameRect());
643         IntRect vBarRect(width() - m_verticalScrollbar->width(), 
644                          0,
645                          m_verticalScrollbar->width(),
646                          height() - (m_horizontalScrollbar ? m_horizontalScrollbar->height() : 0));
647         m_verticalScrollbar->setFrameRect(vBarRect);
648         if (!m_scrollbarsSuppressed && oldRect != m_verticalScrollbar->frameRect())
649             m_verticalScrollbar->invalidate();
650
651         if (m_scrollbarsSuppressed)
652             m_verticalScrollbar->setSuppressInvalidation(true);
653         m_verticalScrollbar->setEnabled(totalContentsSize().height() > clientHeight);
654         m_verticalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
655         m_verticalScrollbar->setProportion(clientHeight, totalContentsSize().height());
656         if (m_scrollbarsSuppressed)
657             m_verticalScrollbar->setSuppressInvalidation(false);
658     }
659
660     if (hasHorizontalScrollbar != newHasHorizontalScrollbar || hasVerticalScrollbar != newHasVerticalScrollbar) {
661         // FIXME: Is frameRectsChanged really necessary here? Have any frame rects changed?
662         frameRectsChanged();
663         positionScrollbarLayers();
664         updateScrollCorner();
665         if (!m_horizontalScrollbar && !m_verticalScrollbar)
666             invalidateScrollCornerRect(oldScrollCornerRect);
667     }
668
669     IntPoint adjustedScrollPosition = IntPoint(desiredOffset);
670     if (!isRubberBandInProgress())
671         adjustedScrollPosition = adjustScrollPositionWithinRange(adjustedScrollPosition);
672
673     if (adjustedScrollPosition != scrollPosition() || scrollOriginChanged()) {
674         ScrollableArea::scrollToOffsetWithoutAnimation(adjustedScrollPosition + toIntSize(scrollOrigin()));
675         resetScrollOriginChanged();
676     }
677
678     // Make sure the scrollbar offsets are up to date.
679     if (m_horizontalScrollbar)
680         m_horizontalScrollbar->offsetDidChange();
681     if (m_verticalScrollbar)
682         m_verticalScrollbar->offsetDidChange();
683
684     m_inUpdateScrollbars = false;
685 }
686
687 const int panIconSizeLength = 16;
688
689 IntRect ScrollView::rectToCopyOnScroll() const
690 {
691     IntRect scrollViewRect = convertToRootView(IntRect(0, 0, visibleWidth(), visibleHeight()));
692     if (hasOverlayScrollbars()) {
693         int verticalScrollbarWidth = (verticalScrollbar() && !hasLayerForVerticalScrollbar()) ? verticalScrollbar()->width() : 0;
694         int horizontalScrollbarHeight = (horizontalScrollbar() && !hasLayerForHorizontalScrollbar()) ? horizontalScrollbar()->height() : 0;
695         
696         scrollViewRect.setWidth(scrollViewRect.width() - verticalScrollbarWidth);
697         scrollViewRect.setHeight(scrollViewRect.height() - horizontalScrollbarHeight);
698     }
699     return scrollViewRect;
700 }
701
702 void ScrollView::scrollContents(const IntSize& scrollDelta)
703 {
704     HostWindow* window = hostWindow();
705     if (!window)
706         return;
707
708     // Since scrolling is double buffered, we will be blitting the scroll view's intersection
709     // with the clip rect every time to keep it smooth.
710     IntRect clipRect = windowClipRect();
711     IntRect scrollViewRect = rectToCopyOnScroll();    
712     IntRect updateRect = clipRect;
713     updateRect.intersect(scrollViewRect);
714
715     // Invalidate the root view (not the backing store).
716     window->invalidateRootView(updateRect, false /*immediate*/);
717
718     if (m_drawPanScrollIcon) {
719         // FIXME: the pan icon is broken when accelerated compositing is on, since it will draw under the compositing layers.
720         // https://bugs.webkit.org/show_bug.cgi?id=47837
721         int panIconDirtySquareSizeLength = 2 * (panIconSizeLength + max(abs(scrollDelta.width()), abs(scrollDelta.height()))); // We only want to repaint what's necessary
722         IntPoint panIconDirtySquareLocation = IntPoint(m_panScrollIconPoint.x() - (panIconDirtySquareSizeLength / 2), m_panScrollIconPoint.y() - (panIconDirtySquareSizeLength / 2));
723         IntRect panScrollIconDirtyRect = IntRect(panIconDirtySquareLocation, IntSize(panIconDirtySquareSizeLength, panIconDirtySquareSizeLength));
724         panScrollIconDirtyRect.intersect(clipRect);
725         window->invalidateContentsAndRootView(panScrollIconDirtyRect, false /*immediate*/);
726     }
727
728     if (canBlitOnScroll()) { // The main frame can just blit the WebView window
729         // FIXME: Find a way to scroll subframes with this faster path
730         if (!scrollContentsFastPath(-scrollDelta, scrollViewRect, clipRect))
731             scrollContentsSlowPath(updateRect);
732     } else { 
733        // We need to go ahead and repaint the entire backing store.  Do it now before moving the
734        // windowed plugins.
735        scrollContentsSlowPath(updateRect);
736     }
737
738     // Invalidate the overhang areas if they are visible.
739     updateOverhangAreas();
740
741     // This call will move children with native widgets (plugins) and invalidate them as well.
742     frameRectsChanged();
743
744     // Now blit the backingstore into the window which should be very fast.
745     window->invalidateRootView(IntRect(), true);
746 }
747
748 bool ScrollView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
749 {
750     hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
751     return true;
752 }
753
754 void ScrollView::scrollContentsSlowPath(const IntRect& updateRect)
755 {
756     hostWindow()->invalidateContentsForSlowScroll(updateRect, false);
757 }
758
759 IntPoint ScrollView::rootViewToContents(const IntPoint& rootViewPoint) const
760 {
761     IntPoint viewPoint = convertFromRootView(rootViewPoint);
762     return viewPoint + scrollOffsetRelativeToDocument();
763 }
764
765 IntPoint ScrollView::contentsToRootView(const IntPoint& contentsPoint) const
766 {
767     IntPoint viewPoint = contentsPoint + IntSize(0, headerHeight()) - scrollOffset();
768     return convertToRootView(viewPoint);  
769 }
770
771 IntRect ScrollView::rootViewToContents(const IntRect& rootViewRect) const
772 {
773     IntRect viewRect = convertFromRootView(rootViewRect);
774     viewRect.move(scrollOffsetRelativeToDocument());
775     return viewRect;
776 }
777
778 IntRect ScrollView::contentsToRootView(const IntRect& contentsRect) const
779 {
780     IntRect viewRect = contentsRect;
781     viewRect.move(-scrollOffset() + IntSize(0, headerHeight()));
782     return convertToRootView(viewRect);
783 }
784
785 IntPoint ScrollView::rootViewToTotalContents(const IntPoint& rootViewPoint) const
786 {
787     IntPoint viewPoint = convertFromRootView(rootViewPoint);
788     return viewPoint + scrollOffset();
789 }
790
791 IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const
792 {
793     if (delegatesScrolling())
794         return convertFromContainingWindow(windowPoint);
795
796     IntPoint viewPoint = convertFromContainingWindow(windowPoint);
797     return viewPoint + scrollOffsetRelativeToDocument();
798 }
799
800 IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const
801 {
802     if (delegatesScrolling())
803         return convertToContainingWindow(contentsPoint);
804
805     IntPoint viewPoint = contentsPoint + IntSize(0, headerHeight()) - scrollOffset();
806     return convertToContainingWindow(viewPoint);  
807 }
808
809 IntRect ScrollView::windowToContents(const IntRect& windowRect) const
810 {
811     if (delegatesScrolling())
812         return convertFromContainingWindow(windowRect);
813
814     IntRect viewRect = convertFromContainingWindow(windowRect);
815     viewRect.move(scrollOffsetRelativeToDocument());
816     return viewRect;
817 }
818
819 IntRect ScrollView::contentsToWindow(const IntRect& contentsRect) const
820 {
821     if (delegatesScrolling())
822         return convertToContainingWindow(contentsRect);
823
824     IntRect viewRect = contentsRect;
825     viewRect.move(-scrollOffset() + IntSize(0, headerHeight()));
826     return convertToContainingWindow(viewRect);
827 }
828
829 IntRect ScrollView::contentsToScreen(const IntRect& rect) const
830 {
831     HostWindow* window = hostWindow();
832     if (platformWidget())
833         return platformContentsToScreen(rect);
834     if (!window)
835         return IntRect();
836     return window->rootViewToScreen(contentsToRootView(rect));
837 }
838
839 IntPoint ScrollView::screenToContents(const IntPoint& point) const
840 {
841     HostWindow* window = hostWindow();
842     if (platformWidget())
843         return platformScreenToContents(point);
844     if (!window)
845         return IntPoint();
846     return rootViewToContents(window->screenToRootView(point));
847 }
848
849 bool ScrollView::containsScrollbarsAvoidingResizer() const
850 {
851     return !m_scrollbarsAvoidingResizer;
852 }
853
854 void ScrollView::adjustScrollbarsAvoidingResizerCount(int overlapDelta)
855 {
856     int oldCount = m_scrollbarsAvoidingResizer;
857     m_scrollbarsAvoidingResizer += overlapDelta;
858     if (parent())
859         parent()->adjustScrollbarsAvoidingResizerCount(overlapDelta);
860     else if (!scrollbarsSuppressed()) {
861         // If we went from n to 0 or from 0 to n and we're the outermost view,
862         // we need to invalidate the windowResizerRect(), since it will now need to paint
863         // differently.
864         if ((oldCount > 0 && m_scrollbarsAvoidingResizer == 0) ||
865             (oldCount == 0 && m_scrollbarsAvoidingResizer > 0))
866             invalidateRect(windowResizerRect());
867     }
868 }
869
870 void ScrollView::setParent(ScrollView* parentView)
871 {
872     if (parentView == parent())
873         return;
874
875     if (m_scrollbarsAvoidingResizer && parent())
876         parent()->adjustScrollbarsAvoidingResizerCount(-m_scrollbarsAvoidingResizer);
877
878     Widget::setParent(parentView);
879
880     if (m_scrollbarsAvoidingResizer && parent())
881         parent()->adjustScrollbarsAvoidingResizerCount(m_scrollbarsAvoidingResizer);
882 }
883
884 void ScrollView::setScrollbarsSuppressed(bool suppressed, bool repaintOnUnsuppress)
885 {
886     if (suppressed == m_scrollbarsSuppressed)
887         return;
888
889     m_scrollbarsSuppressed = suppressed;
890
891     if (platformWidget())
892         platformSetScrollbarsSuppressed(repaintOnUnsuppress);
893     else if (repaintOnUnsuppress && !suppressed) {
894         if (m_horizontalScrollbar)
895             m_horizontalScrollbar->invalidate();
896         if (m_verticalScrollbar)
897             m_verticalScrollbar->invalidate();
898
899         // Invalidate the scroll corner too on unsuppress.
900         invalidateRect(scrollCornerRect());
901     }
902 }
903
904 Scrollbar* ScrollView::scrollbarAtPoint(const IntPoint& windowPoint)
905 {
906     if (platformWidget())
907         return 0;
908
909     IntPoint viewPoint = convertFromContainingWindow(windowPoint);
910     if (m_horizontalScrollbar && m_horizontalScrollbar->shouldParticipateInHitTesting() && m_horizontalScrollbar->frameRect().contains(viewPoint))
911         return m_horizontalScrollbar.get();
912     if (m_verticalScrollbar && m_verticalScrollbar->shouldParticipateInHitTesting() && m_verticalScrollbar->frameRect().contains(viewPoint))
913         return m_verticalScrollbar.get();
914     return 0;
915 }
916
917 void ScrollView::setScrollbarOverlayStyle(ScrollbarOverlayStyle overlayStyle)
918 {
919     ScrollableArea::setScrollbarOverlayStyle(overlayStyle);
920     platformSetScrollbarOverlayStyle(overlayStyle);
921 }
922
923 void ScrollView::setFrameRect(const IntRect& newRect)
924 {
925     IntRect oldRect = frameRect();
926     
927     if (newRect == oldRect)
928         return;
929
930     Widget::setFrameRect(newRect);
931
932     frameRectsChanged();
933
934     updateScrollbars(scrollOffset());
935
936     if (!m_useFixedLayout && oldRect.size() != newRect.size())
937         contentsResized();
938 }
939
940 void ScrollView::frameRectsChanged()
941 {
942     if (platformWidget())
943         return;
944
945     HashSet<RefPtr<Widget> >::const_iterator end = m_children.end();
946     for (HashSet<RefPtr<Widget> >::const_iterator current = m_children.begin(); current != end; ++current)
947         (*current)->frameRectsChanged();
948 }
949
950 void ScrollView::clipRectChanged()
951 {
952     HashSet<RefPtr<Widget> >::const_iterator end = m_children.end();
953     for (HashSet<RefPtr<Widget> >::const_iterator current = m_children.begin(); current != end; ++current)
954         (*current)->clipRectChanged();
955 }
956
957 #if USE(ACCELERATED_COMPOSITING)
958 static void positionScrollbarLayer(GraphicsLayer* graphicsLayer, Scrollbar* scrollbar)
959 {
960     if (!graphicsLayer || !scrollbar)
961         return;
962
963     IntRect scrollbarRect = scrollbar->frameRect();
964     graphicsLayer->setPosition(scrollbarRect.location());
965
966     if (scrollbarRect.size() == graphicsLayer->size())
967         return;
968
969     graphicsLayer->setSize(scrollbarRect.size());
970
971     if (graphicsLayer->hasContentsLayer()) {
972         graphicsLayer->setContentsRect(IntRect(0, 0, scrollbarRect.width(), scrollbarRect.height()));
973         return;
974     }
975
976     graphicsLayer->setDrawsContent(true);
977     graphicsLayer->setNeedsDisplay();
978 }
979
980 static void positionScrollCornerLayer(GraphicsLayer* graphicsLayer, const IntRect& cornerRect)
981 {
982     if (!graphicsLayer)
983         return;
984     graphicsLayer->setDrawsContent(!cornerRect.isEmpty());
985     graphicsLayer->setPosition(cornerRect.location());
986     if (cornerRect.size() != graphicsLayer->size())
987         graphicsLayer->setNeedsDisplay();
988     graphicsLayer->setSize(cornerRect.size());
989 }
990 #endif
991
992
993 void ScrollView::positionScrollbarLayers()
994 {
995 #if USE(ACCELERATED_COMPOSITING)
996     positionScrollbarLayer(layerForHorizontalScrollbar(), horizontalScrollbar());
997     positionScrollbarLayer(layerForVerticalScrollbar(), verticalScrollbar());
998     positionScrollCornerLayer(layerForScrollCorner(), scrollCornerRect());
999 #endif
1000 }
1001
1002 void ScrollView::repaintContentRectangle(const IntRect& rect, bool now)
1003 {
1004     IntRect paintRect = rect;
1005     if (clipsRepaints() && !paintsEntireContents())
1006         paintRect.intersect(visibleContentRect());
1007     if (paintRect.isEmpty())
1008         return;
1009
1010     if (platformWidget()) {
1011         notifyPageThatContentAreaWillPaint();
1012         platformRepaintContentRectangle(paintRect, now);
1013         return;
1014     }
1015
1016     if (HostWindow* window = hostWindow())
1017         window->invalidateContentsAndRootView(contentsToWindow(paintRect), now /*immediate*/);
1018 }
1019
1020 IntRect ScrollView::scrollCornerRect() const
1021 {
1022     IntRect cornerRect;
1023
1024     if (hasOverlayScrollbars())
1025         return cornerRect;
1026
1027     if (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0) {
1028         cornerRect.unite(IntRect(m_horizontalScrollbar->width(),
1029                                  height() - m_horizontalScrollbar->height(),
1030                                  width() - m_horizontalScrollbar->width(),
1031                                  m_horizontalScrollbar->height()));
1032     }
1033
1034     if (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0) {
1035         cornerRect.unite(IntRect(width() - m_verticalScrollbar->width(),
1036                                  m_verticalScrollbar->height(),
1037                                  m_verticalScrollbar->width(),
1038                                  height() - m_verticalScrollbar->height()));
1039     }
1040     
1041     return cornerRect;
1042 }
1043
1044 bool ScrollView::isScrollCornerVisible() const
1045 {
1046     return !scrollCornerRect().isEmpty();
1047 }
1048
1049 void ScrollView::scrollbarStyleChanged(int, bool forceUpdate)
1050 {
1051     if (!forceUpdate)
1052         return;
1053
1054     contentsResized();
1055     updateScrollbars(scrollOffset());
1056     positionScrollbarLayers();
1057 }
1058
1059 void ScrollView::updateScrollCorner()
1060 {
1061 }
1062
1063 void ScrollView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
1064 {
1065     ScrollbarTheme::theme()->paintScrollCorner(this, context, cornerRect);
1066 }
1067
1068 void ScrollView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
1069 {
1070     bar->paint(context, rect);
1071 }
1072
1073 void ScrollView::invalidateScrollCornerRect(const IntRect& rect)
1074 {
1075     invalidateRect(rect);
1076 }
1077
1078 void ScrollView::paintScrollbars(GraphicsContext* context, const IntRect& rect)
1079 {
1080     if (m_horizontalScrollbar
1081 #if USE(ACCELERATED_COMPOSITING)
1082         && !layerForHorizontalScrollbar()
1083 #endif
1084                                       )
1085         paintScrollbar(context, m_horizontalScrollbar.get(), rect);
1086     if (m_verticalScrollbar
1087 #if USE(ACCELERATED_COMPOSITING)
1088         && !layerForVerticalScrollbar()
1089 #endif
1090                                     )
1091         paintScrollbar(context, m_verticalScrollbar.get(), rect);
1092
1093 #if USE(ACCELERATED_COMPOSITING)
1094     if (layerForScrollCorner())
1095         return;
1096 #endif
1097     paintScrollCorner(context, scrollCornerRect());
1098 }
1099
1100 void ScrollView::paintPanScrollIcon(GraphicsContext* context)
1101 {
1102     static Image* panScrollIcon = Image::loadPlatformResource("panIcon").leakRef();
1103     IntPoint iconGCPoint = m_panScrollIconPoint;
1104     if (parent())
1105         iconGCPoint = parent()->windowToContents(iconGCPoint);
1106     context->drawImage(panScrollIcon, ColorSpaceDeviceRGB, iconGCPoint);
1107 }
1108
1109 void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
1110 {
1111     if (platformWidget()) {
1112         Widget::paint(context, rect);
1113         return;
1114     }
1115
1116     if (context->paintingDisabled() && !context->updatingControlTints())
1117         return;
1118
1119     notifyPageThatContentAreaWillPaint();
1120
1121     IntRect documentDirtyRect = rect;
1122     if (!paintsEntireContents()) {
1123         IntRect visibleAreaWithoutScrollbars(location(), visibleContentRect().size());
1124         documentDirtyRect.intersect(visibleAreaWithoutScrollbars);
1125     }
1126
1127     if (!documentDirtyRect.isEmpty()) {
1128         GraphicsContextStateSaver stateSaver(*context);
1129
1130         context->translate(x(), y());
1131         documentDirtyRect.moveBy(-location());
1132
1133         if (!paintsEntireContents()) {
1134             context->translate(-scrollX(), -scrollY());
1135             documentDirtyRect.moveBy(scrollPosition());
1136
1137             context->clip(visibleContentRect());
1138         }
1139
1140         paintContents(context, documentDirtyRect);
1141     }
1142
1143 #if USE(ACCELERATED_COMPOSITING) && ENABLE(RUBBER_BANDING)
1144     if (!layerForOverhangAreas())
1145         calculateAndPaintOverhangAreas(context, rect);
1146 #else
1147     calculateAndPaintOverhangAreas(context, rect);
1148 #endif
1149
1150     // Now paint the scrollbars.
1151     if (!m_scrollbarsSuppressed && (m_horizontalScrollbar || m_verticalScrollbar)) {
1152         GraphicsContextStateSaver stateSaver(*context);
1153         IntRect scrollViewDirtyRect = rect;
1154         IntRect visibleAreaWithScrollbars(location(), visibleContentRect(IncludeScrollbars).size());
1155         scrollViewDirtyRect.intersect(visibleAreaWithScrollbars);
1156         context->translate(x(), y());
1157         scrollViewDirtyRect.moveBy(-location());
1158
1159         paintScrollbars(context, scrollViewDirtyRect);
1160     }
1161
1162     // Paint the panScroll Icon
1163     if (m_drawPanScrollIcon)
1164         paintPanScrollIcon(context);
1165 }
1166
1167 void ScrollView::calculateOverhangAreasForPainting(IntRect& horizontalOverhangRect, IntRect& verticalOverhangRect)
1168 {
1169     int verticalScrollbarWidth = (verticalScrollbar() && !verticalScrollbar()->isOverlayScrollbar())
1170         ? verticalScrollbar()->width() : 0;
1171     int horizontalScrollbarHeight = (horizontalScrollbar() && !horizontalScrollbar()->isOverlayScrollbar())
1172         ? horizontalScrollbar()->height() : 0;
1173
1174     int physicalScrollY = scrollPosition().y() + scrollOrigin().y();
1175     if (physicalScrollY < 0) {
1176         horizontalOverhangRect = frameRect();
1177         horizontalOverhangRect.setHeight(-physicalScrollY);
1178         horizontalOverhangRect.setWidth(horizontalOverhangRect.width() - verticalScrollbarWidth);
1179     } else if (totalContentsSize().height() && physicalScrollY > totalContentsSize().height() - visibleHeight()) {
1180         int height = physicalScrollY - (totalContentsSize().height() - visibleHeight());
1181         horizontalOverhangRect = frameRect();
1182         horizontalOverhangRect.setY(frameRect().maxY() - height - horizontalScrollbarHeight);
1183         horizontalOverhangRect.setHeight(height);
1184         horizontalOverhangRect.setWidth(horizontalOverhangRect.width() - verticalScrollbarWidth);
1185     }
1186
1187     int physicalScrollX = scrollPosition().x() + scrollOrigin().x();
1188     if (physicalScrollX < 0) {
1189         verticalOverhangRect.setWidth(-physicalScrollX);
1190         verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height() - horizontalScrollbarHeight);
1191         verticalOverhangRect.setX(frameRect().x());
1192         if (horizontalOverhangRect.y() == frameRect().y())
1193             verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.height());
1194         else
1195             verticalOverhangRect.setY(frameRect().y());
1196     } else if (contentsWidth() && physicalScrollX > contentsWidth() - visibleWidth()) {
1197         int width = physicalScrollX - (contentsWidth() - visibleWidth());
1198         verticalOverhangRect.setWidth(width);
1199         verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height() - horizontalScrollbarHeight);
1200         verticalOverhangRect.setX(frameRect().maxX() - width - verticalScrollbarWidth);
1201         if (horizontalOverhangRect.y() == frameRect().y())
1202             verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.height());
1203         else
1204             verticalOverhangRect.setY(frameRect().y());
1205     }
1206 }
1207
1208 void ScrollView::updateOverhangAreas()
1209 {
1210     HostWindow* window = hostWindow();
1211     if (!window)
1212         return;
1213
1214     IntRect horizontalOverhangRect;
1215     IntRect verticalOverhangRect;
1216     calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
1217     if (!horizontalOverhangRect.isEmpty())
1218         window->invalidateContentsAndRootView(horizontalOverhangRect, false /*immediate*/);
1219     if (!verticalOverhangRect.isEmpty())
1220         window->invalidateContentsAndRootView(verticalOverhangRect, false /*immediate*/);
1221 }
1222
1223 void ScrollView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
1224 {
1225     ScrollbarTheme::theme()->paintOverhangAreas(this, context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
1226 }
1227
1228 void ScrollView::calculateAndPaintOverhangAreas(GraphicsContext* context, const IntRect& dirtyRect)
1229 {
1230     IntRect horizontalOverhangRect;
1231     IntRect verticalOverhangRect;
1232     calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
1233
1234     if (dirtyRect.intersects(horizontalOverhangRect) || dirtyRect.intersects(verticalOverhangRect))
1235         paintOverhangAreas(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
1236 }
1237
1238 bool ScrollView::isPointInScrollbarCorner(const IntPoint& windowPoint)
1239 {
1240     if (!scrollbarCornerPresent())
1241         return false;
1242
1243     IntPoint viewPoint = convertFromContainingWindow(windowPoint);
1244
1245     if (m_horizontalScrollbar) {
1246         int horizontalScrollbarYMin = m_horizontalScrollbar->frameRect().y();
1247         int horizontalScrollbarYMax = m_horizontalScrollbar->frameRect().y() + m_horizontalScrollbar->frameRect().height();
1248         int horizontalScrollbarXMin = m_horizontalScrollbar->frameRect().x() + m_horizontalScrollbar->frameRect().width();
1249
1250         return viewPoint.y() > horizontalScrollbarYMin && viewPoint.y() < horizontalScrollbarYMax && viewPoint.x() > horizontalScrollbarXMin;
1251     }
1252
1253     int verticalScrollbarXMin = m_verticalScrollbar->frameRect().x();
1254     int verticalScrollbarXMax = m_verticalScrollbar->frameRect().x() + m_verticalScrollbar->frameRect().width();
1255     int verticalScrollbarYMin = m_verticalScrollbar->frameRect().y() + m_verticalScrollbar->frameRect().height();
1256     
1257     return viewPoint.x() > verticalScrollbarXMin && viewPoint.x() < verticalScrollbarXMax && viewPoint.y() > verticalScrollbarYMin;
1258 }
1259
1260 bool ScrollView::scrollbarCornerPresent() const
1261 {
1262     return (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0)
1263         || (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0);
1264 }
1265
1266 IntRect ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& localRect) const
1267 {
1268     // Scrollbars won't be transformed within us
1269     IntRect newRect = localRect;
1270     newRect.moveBy(scrollbar->location());
1271     return newRect;
1272 }
1273
1274 IntRect ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
1275 {
1276     IntRect newRect = parentRect;
1277     // Scrollbars won't be transformed within us
1278     newRect.moveBy(-scrollbar->location());
1279     return newRect;
1280 }
1281
1282 // FIXME: test these on windows
1283 IntPoint ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& localPoint) const
1284 {
1285     // Scrollbars won't be transformed within us
1286     IntPoint newPoint = localPoint;
1287     newPoint.moveBy(scrollbar->location());
1288     return newPoint;
1289 }
1290
1291 IntPoint ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
1292 {
1293     IntPoint newPoint = parentPoint;
1294     // Scrollbars won't be transformed within us
1295     newPoint.moveBy(-scrollbar->location());
1296     return newPoint;
1297 }
1298
1299 void ScrollView::setParentVisible(bool visible)
1300 {
1301     if (isParentVisible() == visible)
1302         return;
1303     
1304     Widget::setParentVisible(visible);
1305
1306     if (!isSelfVisible())
1307         return;
1308         
1309     HashSet<RefPtr<Widget> >::iterator end = m_children.end();
1310     for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it)
1311         (*it)->setParentVisible(visible);
1312 }
1313
1314 void ScrollView::show()
1315 {
1316     if (!isSelfVisible()) {
1317         setSelfVisible(true);
1318         if (isParentVisible()) {
1319             HashSet<RefPtr<Widget> >::iterator end = m_children.end();
1320             for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it)
1321                 (*it)->setParentVisible(true);
1322         }
1323     }
1324
1325     Widget::show();
1326 }
1327
1328 void ScrollView::hide()
1329 {
1330     if (isSelfVisible()) {
1331         if (isParentVisible()) {
1332             HashSet<RefPtr<Widget> >::iterator end = m_children.end();
1333             for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it)
1334                 (*it)->setParentVisible(false);
1335         }
1336         setSelfVisible(false);
1337     }
1338
1339     Widget::hide();
1340 }
1341
1342 bool ScrollView::isOffscreen() const
1343 {
1344     if (platformWidget())
1345         return platformIsOffscreen();
1346     
1347     if (!isVisible())
1348         return true;
1349     
1350     // FIXME: Add a HostWindow::isOffscreen method here.  Since only Mac implements this method
1351     // currently, we can add the method when the other platforms decide to implement this concept.
1352     return false;
1353 }
1354
1355
1356 void ScrollView::addPanScrollIcon(const IntPoint& iconPosition)
1357 {
1358     HostWindow* window = hostWindow();
1359     if (!window)
1360         return;
1361     m_drawPanScrollIcon = true;    
1362     m_panScrollIconPoint = IntPoint(iconPosition.x() - panIconSizeLength / 2 , iconPosition.y() - panIconSizeLength / 2) ;
1363     window->invalidateContentsAndRootView(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)), true /*immediate*/);
1364 }
1365
1366 void ScrollView::removePanScrollIcon()
1367 {
1368     HostWindow* window = hostWindow();
1369     if (!window)
1370         return;
1371     m_drawPanScrollIcon = false; 
1372     window->invalidateContentsAndRootView(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)), true /*immediate*/);
1373 }
1374
1375 void ScrollView::setScrollOrigin(const IntPoint& origin, bool updatePositionAtAll, bool updatePositionSynchronously)
1376 {
1377     if (scrollOrigin() == origin)
1378         return;
1379
1380     ScrollableArea::setScrollOrigin(origin);
1381
1382     if (platformWidget()) {
1383         platformSetScrollOrigin(origin, updatePositionAtAll, updatePositionSynchronously);
1384         return;
1385     }
1386     
1387     // Update if the scroll origin changes, since our position will be different if the content size did not change.
1388     if (updatePositionAtAll && updatePositionSynchronously)
1389         updateScrollbars(scrollOffset());
1390 }
1391
1392 #if !PLATFORM(QT) && !PLATFORM(MAC)
1393
1394 void ScrollView::platformAddChild(Widget*)
1395 {
1396 }
1397
1398 void ScrollView::platformRemoveChild(Widget*)
1399 {
1400 }
1401
1402 #endif
1403
1404 #if !PLATFORM(MAC)
1405
1406 void ScrollView::platformSetScrollbarsSuppressed(bool)
1407 {
1408 }
1409
1410 void ScrollView::platformSetScrollOrigin(const IntPoint&, bool, bool)
1411 {
1412 }
1413
1414 void ScrollView::platformSetScrollbarOverlayStyle(ScrollbarOverlayStyle)
1415 {
1416 }
1417
1418 #endif
1419
1420 #if !PLATFORM(MAC)
1421
1422 void ScrollView::platformSetScrollbarModes()
1423 {
1424 }
1425
1426 void ScrollView::platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode& vertical) const
1427 {
1428     horizontal = ScrollbarAuto;
1429     vertical = ScrollbarAuto;
1430 }
1431
1432 void ScrollView::platformSetCanBlitOnScroll(bool)
1433 {
1434 }
1435
1436 bool ScrollView::platformCanBlitOnScroll() const
1437 {
1438     return false;
1439 }
1440
1441 IntRect ScrollView::platformVisibleContentRect(bool) const
1442 {
1443     return IntRect();
1444 }
1445
1446 IntSize ScrollView::platformVisibleContentSize(bool) const
1447 {
1448     return IntSize();
1449 }
1450
1451 void ScrollView::platformSetContentsSize()
1452 {
1453 }
1454
1455 IntRect ScrollView::platformContentsToScreen(const IntRect& rect) const
1456 {
1457     return rect;
1458 }
1459
1460 IntPoint ScrollView::platformScreenToContents(const IntPoint& point) const
1461 {
1462     return point;
1463 }
1464
1465 void ScrollView::platformSetScrollPosition(const IntPoint&)
1466 {
1467 }
1468
1469 bool ScrollView::platformScroll(ScrollDirection, ScrollGranularity)
1470 {
1471     return true;
1472 }
1473
1474 void ScrollView::platformRepaintContentRectangle(const IntRect&, bool /*now*/)
1475 {
1476 }
1477
1478 bool ScrollView::platformIsOffscreen() const
1479 {
1480     return false;
1481 }
1482
1483 #endif
1484
1485 }