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