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 "platform/scroll/ScrollView.h"
28
29 #include "platform/graphics/GraphicsContextStateSaver.h"
30 #include "platform/graphics/GraphicsLayer.h"
31 #include "platform/HostWindow.h"
32 #include "platform/scroll/ScrollbarTheme.h"
33 #include "wtf/StdLibExtras.h"
34
35 namespace blink {
36
ScrollView()37 ScrollView::ScrollView()
38 : m_horizontalScrollbarMode(ScrollbarAuto)
39 , m_verticalScrollbarMode(ScrollbarAuto)
40 , m_horizontalScrollbarLock(false)
41 , m_verticalScrollbarLock(false)
42 , m_scrollbarsAvoidingResizer(0)
43 , m_scrollbarsSuppressed(false)
44 , m_inUpdateScrollbars(false)
45 , m_drawPanScrollIcon(false)
46 , m_clipsRepaints(true)
47 {
48 }
49
~ScrollView()50 ScrollView::~ScrollView()
51 {
52 }
53
addChild(PassRefPtr<Widget> prpChild)54 void ScrollView::addChild(PassRefPtr<Widget> prpChild)
55 {
56 Widget* child = prpChild.get();
57 ASSERT(child != this && !child->parent());
58 child->setParent(this);
59 m_children.add(prpChild);
60 }
61
removeChild(Widget * child)62 void ScrollView::removeChild(Widget* child)
63 {
64 ASSERT(child->parent() == this);
65 child->setParent(0);
66 m_children.remove(child);
67 }
68
setHasHorizontalScrollbar(bool hasBar)69 void ScrollView::setHasHorizontalScrollbar(bool hasBar)
70 {
71 if (hasBar && !m_horizontalScrollbar) {
72 m_horizontalScrollbar = createScrollbar(HorizontalScrollbar);
73 addChild(m_horizontalScrollbar.get());
74 didAddScrollbar(m_horizontalScrollbar.get(), HorizontalScrollbar);
75 m_horizontalScrollbar->styleChanged();
76 } else if (!hasBar && m_horizontalScrollbar) {
77 willRemoveScrollbar(m_horizontalScrollbar.get(), HorizontalScrollbar);
78 removeChild(m_horizontalScrollbar.get());
79 m_horizontalScrollbar = nullptr;
80 }
81 }
82
setHasVerticalScrollbar(bool hasBar)83 void ScrollView::setHasVerticalScrollbar(bool hasBar)
84 {
85 if (hasBar && !m_verticalScrollbar) {
86 m_verticalScrollbar = createScrollbar(VerticalScrollbar);
87 addChild(m_verticalScrollbar.get());
88 didAddScrollbar(m_verticalScrollbar.get(), VerticalScrollbar);
89 m_verticalScrollbar->styleChanged();
90 } else if (!hasBar && m_verticalScrollbar) {
91 willRemoveScrollbar(m_verticalScrollbar.get(), VerticalScrollbar);
92 removeChild(m_verticalScrollbar.get());
93 m_verticalScrollbar = nullptr;
94 }
95 }
96
createScrollbar(ScrollbarOrientation orientation)97 PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientation)
98 {
99 return Scrollbar::create(this, orientation, RegularScrollbar);
100 }
101
setScrollbarModes(ScrollbarMode horizontalMode,ScrollbarMode verticalMode,bool horizontalLock,bool verticalLock)102 void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode,
103 bool horizontalLock, bool verticalLock)
104 {
105 bool needsUpdate = false;
106
107 if (horizontalMode != horizontalScrollbarMode() && !m_horizontalScrollbarLock) {
108 m_horizontalScrollbarMode = horizontalMode;
109 needsUpdate = true;
110 }
111
112 if (verticalMode != verticalScrollbarMode() && !m_verticalScrollbarLock) {
113 m_verticalScrollbarMode = verticalMode;
114 needsUpdate = true;
115 }
116
117 if (horizontalLock)
118 setHorizontalScrollbarLock();
119
120 if (verticalLock)
121 setVerticalScrollbarLock();
122
123 if (!needsUpdate)
124 return;
125
126 updateScrollbars(scrollOffset());
127
128 if (!layerForScrolling())
129 return;
130 blink::WebLayer* layer = layerForScrolling()->platformLayer();
131 if (!layer)
132 return;
133 layer->setUserScrollable(userInputScrollable(HorizontalScrollbar), userInputScrollable(VerticalScrollbar));
134 }
135
scrollbarModes(ScrollbarMode & horizontalMode,ScrollbarMode & verticalMode) const136 void ScrollView::scrollbarModes(ScrollbarMode& horizontalMode, ScrollbarMode& verticalMode) const
137 {
138 horizontalMode = m_horizontalScrollbarMode;
139 verticalMode = m_verticalScrollbarMode;
140 }
141
setCanHaveScrollbars(bool canScroll)142 void ScrollView::setCanHaveScrollbars(bool canScroll)
143 {
144 ScrollbarMode newHorizontalMode;
145 ScrollbarMode newVerticalMode;
146
147 scrollbarModes(newHorizontalMode, newVerticalMode);
148
149 if (canScroll && newVerticalMode == ScrollbarAlwaysOff)
150 newVerticalMode = ScrollbarAuto;
151 else if (!canScroll)
152 newVerticalMode = ScrollbarAlwaysOff;
153
154 if (canScroll && newHorizontalMode == ScrollbarAlwaysOff)
155 newHorizontalMode = ScrollbarAuto;
156 else if (!canScroll)
157 newHorizontalMode = ScrollbarAlwaysOff;
158
159 setScrollbarModes(newHorizontalMode, newVerticalMode);
160 }
161
setClipsRepaints(bool clipsRepaints)162 void ScrollView::setClipsRepaints(bool clipsRepaints)
163 {
164 m_clipsRepaints = clipsRepaints;
165 }
166
unscaledVisibleContentSize(IncludeScrollbarsInRect scrollbarInclusion) const167 IntSize ScrollView::unscaledVisibleContentSize(IncludeScrollbarsInRect scrollbarInclusion) const
168 {
169 return scrollbarInclusion == ExcludeScrollbars ? excludeScrollbars(frameRect().size()) : frameRect().size();
170 }
171
excludeScrollbars(const IntSize & size) const172 IntSize ScrollView::excludeScrollbars(const IntSize& size) const
173 {
174 int verticalScrollbarWidth = 0;
175 int horizontalScrollbarHeight = 0;
176
177 if (Scrollbar* verticalBar = verticalScrollbar())
178 verticalScrollbarWidth = !verticalBar->isOverlayScrollbar() ? verticalBar->width() : 0;
179 if (Scrollbar* horizontalBar = horizontalScrollbar())
180 horizontalScrollbarHeight = !horizontalBar->isOverlayScrollbar() ? horizontalBar->height() : 0;
181
182 return IntSize(std::max(0, size.width() - verticalScrollbarWidth),
183 std::max(0, size.height() - horizontalScrollbarHeight));
184
185 }
186
visibleContentRect(IncludeScrollbarsInRect scollbarInclusion) const187 IntRect ScrollView::visibleContentRect(IncludeScrollbarsInRect scollbarInclusion) const
188 {
189 FloatSize visibleContentSize = unscaledVisibleContentSize(scollbarInclusion);
190 visibleContentSize.scale(1 / visibleContentScaleFactor());
191 return IntRect(IntPoint(m_scrollOffset), expandedIntSize(visibleContentSize));
192 }
193
contentsSize() const194 IntSize ScrollView::contentsSize() const
195 {
196 return m_contentsSize;
197 }
198
setContentsSize(const IntSize & newSize)199 void ScrollView::setContentsSize(const IntSize& newSize)
200 {
201 if (contentsSize() == newSize)
202 return;
203 m_contentsSize = newSize;
204 updateScrollbars(scrollOffset());
205 updateOverhangAreas();
206 }
207
maximumScrollPosition() const208 IntPoint ScrollView::maximumScrollPosition() const
209 {
210 IntPoint maximumOffset(contentsWidth() - visibleWidth() - scrollOrigin().x(), contentsHeight() - visibleHeight() - scrollOrigin().y());
211 maximumOffset.clampNegativeToZero();
212 return maximumOffset;
213 }
214
minimumScrollPosition() const215 IntPoint ScrollView::minimumScrollPosition() const
216 {
217 return IntPoint(-scrollOrigin().x(), -scrollOrigin().y());
218 }
219
adjustScrollPositionWithinRange(const IntPoint & scrollPoint) const220 IntPoint ScrollView::adjustScrollPositionWithinRange(const IntPoint& scrollPoint) const
221 {
222 if (!constrainsScrollingToContentEdge())
223 return scrollPoint;
224
225 IntPoint newScrollPosition = scrollPoint.shrunkTo(maximumScrollPosition());
226 newScrollPosition = newScrollPosition.expandedTo(minimumScrollPosition());
227 return newScrollPosition;
228 }
229
adjustScrollbarOpacity()230 void ScrollView::adjustScrollbarOpacity()
231 {
232 if (m_horizontalScrollbar && layerForHorizontalScrollbar()) {
233 bool isOpaqueScrollbar = !m_horizontalScrollbar->isOverlayScrollbar();
234 layerForHorizontalScrollbar()->setContentsOpaque(isOpaqueScrollbar);
235 }
236 if (m_verticalScrollbar && layerForVerticalScrollbar()) {
237 bool isOpaqueScrollbar = !m_verticalScrollbar->isOverlayScrollbar();
238 layerForVerticalScrollbar()->setContentsOpaque(isOpaqueScrollbar);
239 }
240 }
241
scrollSize(ScrollbarOrientation orientation) const242 int ScrollView::scrollSize(ScrollbarOrientation orientation) const
243 {
244 Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_horizontalScrollbar : m_verticalScrollbar).get();
245
246 // If no scrollbars are present, the content may still be scrollable.
247 if (!scrollbar) {
248 IntSize scrollSize = m_contentsSize - visibleContentRect().size();
249 scrollSize.clampNegativeToZero();
250 return orientation == HorizontalScrollbar ? scrollSize.width() : scrollSize.height();
251 }
252
253 return scrollbar->totalSize() - scrollbar->visibleSize();
254 }
255
notifyPageThatContentAreaWillPaint() const256 void ScrollView::notifyPageThatContentAreaWillPaint() const
257 {
258 }
259
setScrollOffset(const IntPoint & offset)260 void ScrollView::setScrollOffset(const IntPoint& offset)
261 {
262 scrollTo(toIntSize(adjustScrollPositionWithinRange(offset)));
263 }
264
scrollTo(const IntSize & newOffset)265 void ScrollView::scrollTo(const IntSize& newOffset)
266 {
267 IntSize scrollDelta = newOffset - m_scrollOffset;
268 if (scrollDelta == IntSize())
269 return;
270 m_scrollOffset = newOffset;
271
272 if (scrollbarsSuppressed())
273 return;
274
275 if (isFrameView())
276 m_pendingScrollDelta += scrollDelta;
277 else
278 scrollContents(scrollDelta);
279 }
280
setScrollPosition(const IntPoint & scrollPoint,ScrollBehavior scrollBehavior)281 void ScrollView::setScrollPosition(const IntPoint& scrollPoint, ScrollBehavior scrollBehavior)
282 {
283 IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint);
284
285 if (newScrollPosition == scrollPosition())
286 return;
287
288 if (scrollBehavior == ScrollBehaviorInstant)
289 updateScrollbars(IntSize(newScrollPosition.x(), newScrollPosition.y()));
290 else
291 programmaticallyScrollSmoothlyToOffset(newScrollPosition);
292 }
293
scroll(ScrollDirection direction,ScrollGranularity granularity)294 bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity)
295 {
296 ScrollDirection physicalDirection =
297 toPhysicalDirection(direction, isVerticalDocument(), isFlippedDocument());
298
299 return ScrollableArea::scroll(physicalDirection, granularity);
300 }
301
overhangAmount() const302 IntSize ScrollView::overhangAmount() const
303 {
304 IntSize stretch;
305
306 IntPoint currentScrollPosition = scrollPosition();
307 IntPoint minScrollPosition = minimumScrollPosition();
308 IntPoint maxScrollPosition = maximumScrollPosition();
309
310 if (currentScrollPosition.x() < minScrollPosition.x())
311 stretch.setWidth(currentScrollPosition.x() - minScrollPosition.x());
312 if (currentScrollPosition.x() > maxScrollPosition.x())
313 stretch.setWidth(currentScrollPosition.x() - maxScrollPosition.x());
314
315 if (currentScrollPosition.y() < minScrollPosition.y())
316 stretch.setHeight(currentScrollPosition.y() - minScrollPosition.y());
317 if (currentScrollPosition.y() > maxScrollPosition.y())
318 stretch.setHeight(currentScrollPosition.y() - maxScrollPosition.y());
319
320 return stretch;
321 }
322
windowResizerRectChanged()323 void ScrollView::windowResizerRectChanged()
324 {
325 updateScrollbars(scrollOffset());
326 }
327
useOverlayScrollbars()328 static bool useOverlayScrollbars()
329 {
330 // FIXME: Need to detect the presence of CSS custom scrollbars, which are non-overlay regardless the ScrollbarTheme.
331 return ScrollbarTheme::theme()->usesOverlayScrollbars();
332 }
333
computeScrollbarExistence(bool & newHasHorizontalScrollbar,bool & newHasVerticalScrollbar,const IntSize & docSize,ComputeScrollbarExistenceOption option) const334 void ScrollView::computeScrollbarExistence(bool& newHasHorizontalScrollbar, bool& newHasVerticalScrollbar, const IntSize& docSize, ComputeScrollbarExistenceOption option) const
335 {
336 bool hasHorizontalScrollbar = m_horizontalScrollbar;
337 bool hasVerticalScrollbar = m_verticalScrollbar;
338
339 newHasHorizontalScrollbar = hasHorizontalScrollbar;
340 newHasVerticalScrollbar = hasVerticalScrollbar;
341
342 ScrollbarMode hScroll = m_horizontalScrollbarMode;
343 ScrollbarMode vScroll = m_verticalScrollbarMode;
344
345 if (hScroll != ScrollbarAuto)
346 newHasHorizontalScrollbar = (hScroll == ScrollbarAlwaysOn);
347 if (vScroll != ScrollbarAuto)
348 newHasVerticalScrollbar = (vScroll == ScrollbarAlwaysOn);
349
350 if (m_scrollbarsSuppressed || (hScroll != ScrollbarAuto && vScroll != ScrollbarAuto))
351 return;
352
353 if (hScroll == ScrollbarAuto)
354 newHasHorizontalScrollbar = docSize.width() > visibleWidth();
355 if (vScroll == ScrollbarAuto)
356 newHasVerticalScrollbar = docSize.height() > visibleHeight();
357
358 if (useOverlayScrollbars())
359 return;
360
361 IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size();
362
363 bool attemptToRemoveScrollbars = (option == FirstPass
364 && docSize.width() <= fullVisibleSize.width() && docSize.height() <= fullVisibleSize.height());
365 if (attemptToRemoveScrollbars) {
366 if (hScroll == ScrollbarAuto)
367 newHasHorizontalScrollbar = false;
368 if (vScroll == ScrollbarAuto)
369 newHasVerticalScrollbar = false;
370 }
371
372 // If we ever turn one scrollbar off, always turn the other one off too.
373 // Never ever try to both gain/lose a scrollbar in the same pass.
374 if (!newHasHorizontalScrollbar && hasHorizontalScrollbar && vScroll != ScrollbarAlwaysOn)
375 newHasVerticalScrollbar = false;
376 if (!newHasVerticalScrollbar && hasVerticalScrollbar && hScroll != ScrollbarAlwaysOn)
377 newHasHorizontalScrollbar = false;
378 }
379
updateScrollbarGeometry()380 void ScrollView::updateScrollbarGeometry()
381 {
382 if (m_horizontalScrollbar) {
383 int clientWidth = visibleWidth();
384 IntRect oldRect(m_horizontalScrollbar->frameRect());
385 IntRect hBarRect((shouldPlaceVerticalScrollbarOnLeft() && m_verticalScrollbar) ? m_verticalScrollbar->width() : 0,
386 height() - m_horizontalScrollbar->height(),
387 width() - (m_verticalScrollbar ? m_verticalScrollbar->width() : 0),
388 m_horizontalScrollbar->height());
389 m_horizontalScrollbar->setFrameRect(hBarRect);
390 if (!m_scrollbarsSuppressed && oldRect != m_horizontalScrollbar->frameRect())
391 m_horizontalScrollbar->invalidate();
392
393 if (m_scrollbarsSuppressed)
394 m_horizontalScrollbar->setSuppressInvalidation(true);
395 m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth);
396 m_horizontalScrollbar->setProportion(clientWidth, contentsWidth());
397 m_horizontalScrollbar->offsetDidChange();
398 if (m_scrollbarsSuppressed)
399 m_horizontalScrollbar->setSuppressInvalidation(false);
400 }
401
402 if (m_verticalScrollbar) {
403 int clientHeight = visibleHeight();
404 IntRect oldRect(m_verticalScrollbar->frameRect());
405 IntRect vBarRect(shouldPlaceVerticalScrollbarOnLeft() ? 0 : (width() - m_verticalScrollbar->width()),
406 0,
407 m_verticalScrollbar->width(),
408 height() - (m_horizontalScrollbar ? m_horizontalScrollbar->height() : 0));
409 m_verticalScrollbar->setFrameRect(vBarRect);
410 if (!m_scrollbarsSuppressed && oldRect != m_verticalScrollbar->frameRect())
411 m_verticalScrollbar->invalidate();
412
413 if (m_scrollbarsSuppressed)
414 m_verticalScrollbar->setSuppressInvalidation(true);
415 m_verticalScrollbar->setEnabled(contentsHeight() > clientHeight);
416 m_verticalScrollbar->setProportion(clientHeight, contentsHeight());
417 m_verticalScrollbar->offsetDidChange();
418 if (m_scrollbarsSuppressed)
419 m_verticalScrollbar->setSuppressInvalidation(false);
420 }
421 }
422
adjustScrollbarExistence(ComputeScrollbarExistenceOption option)423 bool ScrollView::adjustScrollbarExistence(ComputeScrollbarExistenceOption option)
424 {
425 ASSERT(m_inUpdateScrollbars);
426
427 // If we came in here with the view already needing a layout, then go ahead and do that
428 // first. (This will be the common case, e.g., when the page changes due to window resizing for example).
429 // This layout will not re-enter updateScrollbars and does not count towards our max layout pass total.
430 if (!m_scrollbarsSuppressed)
431 scrollbarExistenceDidChange();
432
433 bool hasHorizontalScrollbar = m_horizontalScrollbar;
434 bool hasVerticalScrollbar = m_verticalScrollbar;
435
436 bool newHasHorizontalScrollbar = false;
437 bool newHasVerticalScrollbar = false;
438 computeScrollbarExistence(newHasHorizontalScrollbar, newHasVerticalScrollbar, contentsSize(), option);
439
440 bool scrollbarExistenceChanged = hasHorizontalScrollbar != newHasHorizontalScrollbar || hasVerticalScrollbar != newHasVerticalScrollbar;
441 if (!scrollbarExistenceChanged)
442 return false;
443
444 setHasHorizontalScrollbar(newHasHorizontalScrollbar);
445 setHasVerticalScrollbar(newHasVerticalScrollbar);
446
447 if (m_scrollbarsSuppressed)
448 return true;
449
450 if (!useOverlayScrollbars())
451 contentsResized();
452 scrollbarExistenceDidChange();
453 return true;
454 }
455
updateScrollbars(const IntSize & desiredOffset)456 void ScrollView::updateScrollbars(const IntSize& desiredOffset)
457 {
458 if (scrollbarsDisabled()) {
459 setScrollOffsetFromUpdateScrollbars(desiredOffset);
460 return;
461 }
462
463 if (m_inUpdateScrollbars)
464 return;
465 InUpdateScrollbarsScope inUpdateScrollbarsScope(this);
466
467 IntSize oldVisibleSize = visibleSize();
468
469 bool scrollbarExistenceChanged = false;
470 int maxUpdateScrollbarsPass = useOverlayScrollbars() || m_scrollbarsSuppressed ? 1 : 3;
471 for (int updateScrollbarsPass = 0; updateScrollbarsPass < maxUpdateScrollbarsPass; updateScrollbarsPass++) {
472 if (!adjustScrollbarExistence(updateScrollbarsPass ? Incremental : FirstPass))
473 break;
474 scrollbarExistenceChanged = true;
475 }
476
477 updateScrollbarGeometry();
478
479 if (scrollbarExistenceChanged) {
480 // FIXME: Is frameRectsChanged really necessary here? Have any frame rects changed?
481 frameRectsChanged();
482 positionScrollbarLayers();
483 updateScrollCorner();
484 }
485
486 // FIXME: We don't need to do this if we are composited.
487 IntSize newVisibleSize = visibleSize();
488 if (newVisibleSize.width() > oldVisibleSize.width()) {
489 if (shouldPlaceVerticalScrollbarOnLeft())
490 invalidateRect(IntRect(0, 0, newVisibleSize.width() - oldVisibleSize.width(), newVisibleSize.height()));
491 else
492 invalidateRect(IntRect(oldVisibleSize.width(), 0, newVisibleSize.width() - oldVisibleSize.width(), newVisibleSize.height()));
493 }
494 if (newVisibleSize.height() > oldVisibleSize.height())
495 invalidateRect(IntRect(0, oldVisibleSize.height(), newVisibleSize.width(), newVisibleSize.height() - oldVisibleSize.height()));
496
497 setScrollOffsetFromUpdateScrollbars(desiredOffset);
498 }
499
setScrollOffsetFromUpdateScrollbars(const IntSize & offset)500 void ScrollView::setScrollOffsetFromUpdateScrollbars(const IntSize& offset)
501 {
502 IntPoint adjustedScrollPosition = IntPoint(offset);
503
504 if (!isRubberBandInProgress())
505 adjustedScrollPosition = adjustScrollPositionWithinRange(adjustedScrollPosition);
506
507 if (adjustedScrollPosition != scrollPosition() || scrollOriginChanged()) {
508 ScrollableArea::scrollToOffsetWithoutAnimation(adjustedScrollPosition);
509 resetScrollOriginChanged();
510 }
511 }
512
513 const int panIconSizeLength = 16;
514
rectToCopyOnScroll() const515 IntRect ScrollView::rectToCopyOnScroll() const
516 {
517 IntRect scrollViewRect = convertToContainingWindow(IntRect((shouldPlaceVerticalScrollbarOnLeft() && verticalScrollbar()) ? verticalScrollbar()->width() : 0, 0, visibleWidth(), visibleHeight()));
518 if (hasOverlayScrollbars()) {
519 int verticalScrollbarWidth = (verticalScrollbar() && !hasLayerForVerticalScrollbar()) ? verticalScrollbar()->width() : 0;
520 int horizontalScrollbarHeight = (horizontalScrollbar() && !hasLayerForHorizontalScrollbar()) ? horizontalScrollbar()->height() : 0;
521
522 scrollViewRect.setWidth(scrollViewRect.width() - verticalScrollbarWidth);
523 scrollViewRect.setHeight(scrollViewRect.height() - horizontalScrollbarHeight);
524 }
525 return scrollViewRect;
526 }
527
scrollContentsIfNeeded()528 void ScrollView::scrollContentsIfNeeded()
529 {
530 if (m_pendingScrollDelta.isZero())
531 return;
532 IntSize scrollDelta = m_pendingScrollDelta;
533 m_pendingScrollDelta = IntSize();
534 scrollContents(scrollDelta);
535 }
536
scrollContents(const IntSize & scrollDelta)537 void ScrollView::scrollContents(const IntSize& scrollDelta)
538 {
539 HostWindow* window = hostWindow();
540 if (!window)
541 return;
542
543 IntRect clipRect = windowClipRect();
544 IntRect updateRect = clipRect;
545 updateRect.intersect(rectToCopyOnScroll());
546
547 if (m_drawPanScrollIcon) {
548 // FIXME: the pan icon is broken when accelerated compositing is on, since it will draw under the compositing layers.
549 // https://bugs.webkit.org/show_bug.cgi?id=47837
550 int panIconDirtySquareSizeLength = 2 * (panIconSizeLength + std::max(abs(scrollDelta.width()), abs(scrollDelta.height()))); // We only want to repaint what's necessary
551 IntPoint panIconDirtySquareLocation = IntPoint(m_panScrollIconPoint.x() - (panIconDirtySquareSizeLength / 2), m_panScrollIconPoint.y() - (panIconDirtySquareSizeLength / 2));
552 IntRect panScrollIconDirtyRect = IntRect(panIconDirtySquareLocation, IntSize(panIconDirtySquareSizeLength, panIconDirtySquareSizeLength));
553 panScrollIconDirtyRect.intersect(clipRect);
554 window->invalidateContentsAndRootView(panScrollIconDirtyRect);
555 }
556
557 if (!scrollContentsFastPath(-scrollDelta))
558 scrollContentsSlowPath(updateRect);
559
560 // Invalidate the overhang areas if they are visible.
561 updateOverhangAreas();
562
563 // This call will move children with native widgets (plugins) and invalidate them as well.
564 frameRectsChanged();
565 }
566
scrollContentsSlowPath(const IntRect & updateRect)567 void ScrollView::scrollContentsSlowPath(const IntRect& updateRect)
568 {
569 hostWindow()->invalidateContentsForSlowScroll(updateRect);
570 }
571
rootViewToContents(const IntPoint & rootViewPoint) const572 IntPoint ScrollView::rootViewToContents(const IntPoint& rootViewPoint) const
573 {
574 IntPoint viewPoint = convertFromContainingWindow(rootViewPoint);
575 return viewPoint + scrollOffset();
576 }
577
contentsToRootView(const IntPoint & contentsPoint) const578 IntPoint ScrollView::contentsToRootView(const IntPoint& contentsPoint) const
579 {
580 IntPoint viewPoint = contentsPoint - scrollOffset();
581 return convertToContainingWindow(viewPoint);
582 }
583
rootViewToContents(const IntRect & rootViewRect) const584 IntRect ScrollView::rootViewToContents(const IntRect& rootViewRect) const
585 {
586 IntRect viewRect = convertFromContainingWindow(rootViewRect);
587 viewRect.move(scrollOffset());
588 return viewRect;
589 }
590
contentsToRootView(const IntRect & contentsRect) const591 IntRect ScrollView::contentsToRootView(const IntRect& contentsRect) const
592 {
593 IntRect viewRect = contentsRect;
594 viewRect.move(-scrollOffset());
595 return convertToContainingWindow(viewRect);
596 }
597
windowToContents(const IntPoint & windowPoint) const598 IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const
599 {
600 IntPoint viewPoint = convertFromContainingWindow(windowPoint);
601 return viewPoint + scrollOffset();
602 }
603
windowToContents(const FloatPoint & windowPoint) const604 FloatPoint ScrollView::windowToContents(const FloatPoint& windowPoint) const
605 {
606 FloatPoint viewPoint = convertFromContainingWindow(windowPoint);
607 return viewPoint + scrollOffset();
608 }
609
contentsToWindow(const IntPoint & contentsPoint) const610 IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const
611 {
612 IntPoint viewPoint = contentsPoint - scrollOffset();
613 return convertToContainingWindow(viewPoint);
614 }
615
windowToContents(const IntRect & windowRect) const616 IntRect ScrollView::windowToContents(const IntRect& windowRect) const
617 {
618 IntRect viewRect = convertFromContainingWindow(windowRect);
619 viewRect.move(scrollOffset());
620 return viewRect;
621 }
622
contentsToWindow(const IntRect & contentsRect) const623 IntRect ScrollView::contentsToWindow(const IntRect& contentsRect) const
624 {
625 IntRect viewRect = contentsRect;
626 viewRect.move(-scrollOffset());
627 return convertToContainingWindow(viewRect);
628 }
629
contentsToScreen(const IntRect & rect) const630 IntRect ScrollView::contentsToScreen(const IntRect& rect) const
631 {
632 HostWindow* window = hostWindow();
633 if (!window)
634 return IntRect();
635 return window->rootViewToScreen(contentsToRootView(rect));
636 }
637
containsScrollbarsAvoidingResizer() const638 bool ScrollView::containsScrollbarsAvoidingResizer() const
639 {
640 return !m_scrollbarsAvoidingResizer;
641 }
642
adjustScrollbarsAvoidingResizerCount(int overlapDelta)643 void ScrollView::adjustScrollbarsAvoidingResizerCount(int overlapDelta)
644 {
645 int oldCount = m_scrollbarsAvoidingResizer;
646 m_scrollbarsAvoidingResizer += overlapDelta;
647 if (parent())
648 toScrollView(parent())->adjustScrollbarsAvoidingResizerCount(overlapDelta);
649 else if (!scrollbarsSuppressed()) {
650 // If we went from n to 0 or from 0 to n and we're the outermost view,
651 // we need to invalidate the windowResizerRect(), since it will now need to paint
652 // differently.
653 if ((oldCount > 0 && m_scrollbarsAvoidingResizer == 0) ||
654 (oldCount == 0 && m_scrollbarsAvoidingResizer > 0))
655 invalidateRect(windowResizerRect());
656 }
657 }
658
setParent(Widget * parentView)659 void ScrollView::setParent(Widget* parentView)
660 {
661 if (parentView == parent())
662 return;
663
664 if (m_scrollbarsAvoidingResizer && parent())
665 toScrollView(parent())->adjustScrollbarsAvoidingResizerCount(-m_scrollbarsAvoidingResizer);
666
667 Widget::setParent(parentView);
668
669 if (m_scrollbarsAvoidingResizer && parent())
670 toScrollView(parent())->adjustScrollbarsAvoidingResizerCount(m_scrollbarsAvoidingResizer);
671 }
672
setScrollbarsSuppressed(bool suppressed,bool repaintOnUnsuppress)673 void ScrollView::setScrollbarsSuppressed(bool suppressed, bool repaintOnUnsuppress)
674 {
675 if (suppressed == m_scrollbarsSuppressed)
676 return;
677
678 m_scrollbarsSuppressed = suppressed;
679
680 if (repaintOnUnsuppress && !suppressed) {
681 if (m_horizontalScrollbar)
682 m_horizontalScrollbar->invalidate();
683 if (m_verticalScrollbar)
684 m_verticalScrollbar->invalidate();
685
686 // Invalidate the scroll corner too on unsuppress.
687 invalidateRect(scrollCornerRect());
688 }
689 }
690
scrollbarAtWindowPoint(const IntPoint & windowPoint)691 Scrollbar* ScrollView::scrollbarAtWindowPoint(const IntPoint& windowPoint)
692 {
693 IntPoint viewPoint = convertFromContainingWindow(windowPoint);
694 return scrollbarAtViewPoint(viewPoint);
695 }
696
scrollbarAtViewPoint(const IntPoint & viewPoint)697 Scrollbar* ScrollView::scrollbarAtViewPoint(const IntPoint& viewPoint)
698 {
699 if (m_horizontalScrollbar && m_horizontalScrollbar->shouldParticipateInHitTesting() && m_horizontalScrollbar->frameRect().contains(viewPoint))
700 return m_horizontalScrollbar.get();
701 if (m_verticalScrollbar && m_verticalScrollbar->shouldParticipateInHitTesting() && m_verticalScrollbar->frameRect().contains(viewPoint))
702 return m_verticalScrollbar.get();
703 return 0;
704 }
705
setFrameRect(const IntRect & newRect)706 void ScrollView::setFrameRect(const IntRect& newRect)
707 {
708 IntRect oldRect = frameRect();
709
710 if (newRect == oldRect)
711 return;
712
713 Widget::setFrameRect(newRect);
714
715 updateScrollbars(scrollOffset());
716
717 frameRectsChanged();
718 }
719
frameRectsChanged()720 void ScrollView::frameRectsChanged()
721 {
722 HashSet<RefPtr<Widget> >::const_iterator end = m_children.end();
723 for (HashSet<RefPtr<Widget> >::const_iterator current = m_children.begin(); current != end; ++current)
724 (*current)->frameRectsChanged();
725 }
726
positionScrollbarLayer(GraphicsLayer * graphicsLayer,Scrollbar * scrollbar)727 static void positionScrollbarLayer(GraphicsLayer* graphicsLayer, Scrollbar* scrollbar)
728 {
729 if (!graphicsLayer || !scrollbar)
730 return;
731
732 IntRect scrollbarRect = scrollbar->frameRect();
733 graphicsLayer->setPosition(scrollbarRect.location());
734
735 if (scrollbarRect.size() == graphicsLayer->size())
736 return;
737
738 graphicsLayer->setSize(scrollbarRect.size());
739
740 if (graphicsLayer->hasContentsLayer()) {
741 graphicsLayer->setContentsRect(IntRect(0, 0, scrollbarRect.width(), scrollbarRect.height()));
742 return;
743 }
744
745 graphicsLayer->setDrawsContent(true);
746 graphicsLayer->setNeedsDisplay();
747 }
748
positionScrollCornerLayer(GraphicsLayer * graphicsLayer,const IntRect & cornerRect)749 static void positionScrollCornerLayer(GraphicsLayer* graphicsLayer, const IntRect& cornerRect)
750 {
751 if (!graphicsLayer)
752 return;
753 graphicsLayer->setDrawsContent(!cornerRect.isEmpty());
754 graphicsLayer->setPosition(cornerRect.location());
755 if (cornerRect.size() != graphicsLayer->size())
756 graphicsLayer->setNeedsDisplay();
757 graphicsLayer->setSize(cornerRect.size());
758 }
759
positionScrollbarLayers()760 void ScrollView::positionScrollbarLayers()
761 {
762 positionScrollbarLayer(layerForHorizontalScrollbar(), horizontalScrollbar());
763 positionScrollbarLayer(layerForVerticalScrollbar(), verticalScrollbar());
764 positionScrollCornerLayer(layerForScrollCorner(), scrollCornerRect());
765 }
766
userInputScrollable(ScrollbarOrientation orientation) const767 bool ScrollView::userInputScrollable(ScrollbarOrientation orientation) const
768 {
769 ScrollbarMode mode = (orientation == HorizontalScrollbar) ?
770 m_horizontalScrollbarMode : m_verticalScrollbarMode;
771
772 return mode == ScrollbarAuto || mode == ScrollbarAlwaysOn;
773 }
774
shouldPlaceVerticalScrollbarOnLeft() const775 bool ScrollView::shouldPlaceVerticalScrollbarOnLeft() const
776 {
777 return false;
778 }
779
contentRectangleForPaintInvalidation(const IntRect & rect)780 void ScrollView::contentRectangleForPaintInvalidation(const IntRect& rect)
781 {
782 IntRect paintRect = rect;
783 if (clipsPaintInvalidations())
784 paintRect.intersect(visibleContentRect());
785 if (paintRect.isEmpty())
786 return;
787
788 if (HostWindow* window = hostWindow())
789 window->invalidateContentsAndRootView(contentsToWindow(paintRect));
790 }
791
scrollCornerRect() const792 IntRect ScrollView::scrollCornerRect() const
793 {
794 IntRect cornerRect;
795
796 if (hasOverlayScrollbars())
797 return cornerRect;
798
799 if (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0) {
800 cornerRect.unite(IntRect(shouldPlaceVerticalScrollbarOnLeft() ? 0 : m_horizontalScrollbar->width(),
801 height() - m_horizontalScrollbar->height(),
802 width() - m_horizontalScrollbar->width(),
803 m_horizontalScrollbar->height()));
804 }
805
806 if (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0) {
807 cornerRect.unite(IntRect(shouldPlaceVerticalScrollbarOnLeft() ? 0 : (width() - m_verticalScrollbar->width()),
808 m_verticalScrollbar->height(),
809 m_verticalScrollbar->width(),
810 height() - m_verticalScrollbar->height()));
811 }
812
813 return cornerRect;
814 }
815
isScrollCornerVisible() const816 bool ScrollView::isScrollCornerVisible() const
817 {
818 return !scrollCornerRect().isEmpty();
819 }
820
scrollbarStyleChanged()821 void ScrollView::scrollbarStyleChanged()
822 {
823 adjustScrollbarOpacity();
824 contentsResized();
825 updateScrollbars(scrollOffset());
826 positionScrollbarLayers();
827 }
828
updateScrollCorner()829 void ScrollView::updateScrollCorner()
830 {
831 }
832
paintScrollCorner(GraphicsContext * context,const IntRect & cornerRect)833 void ScrollView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
834 {
835 ScrollbarTheme::theme()->paintScrollCorner(context, cornerRect);
836 }
837
paintScrollbar(GraphicsContext * context,Scrollbar * bar,const IntRect & rect)838 void ScrollView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
839 {
840 bar->paint(context, rect);
841 }
842
invalidateScrollCornerRect(const IntRect & rect)843 void ScrollView::invalidateScrollCornerRect(const IntRect& rect)
844 {
845 invalidateRect(rect);
846 }
847
paintScrollbars(GraphicsContext * context,const IntRect & rect)848 void ScrollView::paintScrollbars(GraphicsContext* context, const IntRect& rect)
849 {
850 if (m_horizontalScrollbar && !layerForHorizontalScrollbar())
851 paintScrollbar(context, m_horizontalScrollbar.get(), rect);
852 if (m_verticalScrollbar && !layerForVerticalScrollbar())
853 paintScrollbar(context, m_verticalScrollbar.get(), rect);
854
855 if (layerForScrollCorner())
856 return;
857 paintScrollCorner(context, scrollCornerRect());
858 }
859
paintPanScrollIcon(GraphicsContext * context)860 void ScrollView::paintPanScrollIcon(GraphicsContext* context)
861 {
862 DEFINE_STATIC_REF(Image, panScrollIcon, (Image::loadPlatformResource("panIcon")));
863 IntPoint iconGCPoint = m_panScrollIconPoint;
864 if (parent())
865 iconGCPoint = toScrollView(parent())->windowToContents(iconGCPoint);
866 context->drawImage(panScrollIcon, iconGCPoint);
867 }
868
paint(GraphicsContext * context,const IntRect & rect)869 void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
870 {
871 notifyPageThatContentAreaWillPaint();
872
873 IntRect documentDirtyRect = rect;
874 IntRect visibleAreaWithoutScrollbars(location(), visibleContentRect().size());
875 documentDirtyRect.intersect(visibleAreaWithoutScrollbars);
876
877 if (!documentDirtyRect.isEmpty()) {
878 GraphicsContextStateSaver stateSaver(*context);
879
880 context->translate(x() - scrollX(), y() - scrollY());
881 context->clip(visibleContentRect());
882
883 documentDirtyRect.moveBy(-location() + scrollPosition());
884 paintContents(context, documentDirtyRect);
885 }
886
887 calculateAndPaintOverhangAreas(context, rect);
888
889 // Now paint the scrollbars.
890 if (!m_scrollbarsSuppressed && (m_horizontalScrollbar || m_verticalScrollbar)) {
891 GraphicsContextStateSaver stateSaver(*context);
892 IntRect scrollViewDirtyRect = rect;
893 IntRect visibleAreaWithScrollbars(location(), visibleContentRect(IncludeScrollbars).size());
894 scrollViewDirtyRect.intersect(visibleAreaWithScrollbars);
895 context->translate(x(), y());
896 scrollViewDirtyRect.moveBy(-location());
897 context->clip(IntRect(IntPoint(), visibleAreaWithScrollbars.size()));
898
899 paintScrollbars(context, scrollViewDirtyRect);
900 }
901
902 // Paint the panScroll Icon
903 if (m_drawPanScrollIcon)
904 paintPanScrollIcon(context);
905 }
906
calculateOverhangAreasForPainting(IntRect & horizontalOverhangRect,IntRect & verticalOverhangRect)907 void ScrollView::calculateOverhangAreasForPainting(IntRect& horizontalOverhangRect, IntRect& verticalOverhangRect)
908 {
909 int verticalScrollbarWidth = (verticalScrollbar() && !verticalScrollbar()->isOverlayScrollbar())
910 ? verticalScrollbar()->width() : 0;
911 int horizontalScrollbarHeight = (horizontalScrollbar() && !horizontalScrollbar()->isOverlayScrollbar())
912 ? horizontalScrollbar()->height() : 0;
913
914 int physicalScrollY = scrollPosition().y() + scrollOrigin().y();
915 if (physicalScrollY < 0) {
916 horizontalOverhangRect = frameRect();
917 horizontalOverhangRect.setHeight(-physicalScrollY);
918 horizontalOverhangRect.setWidth(horizontalOverhangRect.width() - verticalScrollbarWidth);
919 } else if (contentsHeight() && physicalScrollY > contentsHeight() - visibleHeight()) {
920 int height = physicalScrollY - (contentsHeight() - visibleHeight());
921 horizontalOverhangRect = frameRect();
922 horizontalOverhangRect.setY(frameRect().maxY() - height - horizontalScrollbarHeight);
923 horizontalOverhangRect.setHeight(height);
924 horizontalOverhangRect.setWidth(horizontalOverhangRect.width() - verticalScrollbarWidth);
925 }
926
927 int physicalScrollX = scrollPosition().x() + scrollOrigin().x();
928 if (physicalScrollX < 0) {
929 verticalOverhangRect.setWidth(-physicalScrollX);
930 verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height() - horizontalScrollbarHeight);
931 verticalOverhangRect.setX(frameRect().x());
932 if (horizontalOverhangRect.y() == frameRect().y())
933 verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.height());
934 else
935 verticalOverhangRect.setY(frameRect().y());
936 } else if (contentsWidth() && physicalScrollX > contentsWidth() - visibleWidth()) {
937 int width = physicalScrollX - (contentsWidth() - visibleWidth());
938 verticalOverhangRect.setWidth(width);
939 verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height() - horizontalScrollbarHeight);
940 verticalOverhangRect.setX(frameRect().maxX() - width - verticalScrollbarWidth);
941 if (horizontalOverhangRect.y() == frameRect().y())
942 verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.height());
943 else
944 verticalOverhangRect.setY(frameRect().y());
945 }
946 }
947
updateOverhangAreas()948 void ScrollView::updateOverhangAreas()
949 {
950 HostWindow* window = hostWindow();
951 if (!window)
952 return;
953
954 IntRect horizontalOverhangRect;
955 IntRect verticalOverhangRect;
956 calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
957 if (!horizontalOverhangRect.isEmpty())
958 window->invalidateContentsAndRootView(horizontalOverhangRect);
959 if (!verticalOverhangRect.isEmpty())
960 window->invalidateContentsAndRootView(verticalOverhangRect);
961 }
962
paintOverhangAreas(GraphicsContext * context,const IntRect & horizontalOverhangRect,const IntRect & verticalOverhangRect,const IntRect & dirtyRect)963 void ScrollView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
964 {
965 ScrollbarTheme::theme()->paintOverhangBackground(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
966 ScrollbarTheme::theme()->paintOverhangShadows(context, scrollOffset(), horizontalOverhangRect, verticalOverhangRect, dirtyRect);
967 }
968
calculateAndPaintOverhangAreas(GraphicsContext * context,const IntRect & dirtyRect)969 void ScrollView::calculateAndPaintOverhangAreas(GraphicsContext* context, const IntRect& dirtyRect)
970 {
971 IntRect horizontalOverhangRect;
972 IntRect verticalOverhangRect;
973 calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
974
975 if (dirtyRect.intersects(horizontalOverhangRect) || dirtyRect.intersects(verticalOverhangRect))
976 paintOverhangAreas(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
977 }
978
calculateAndPaintOverhangBackground(GraphicsContext * context,const IntRect & dirtyRect)979 void ScrollView::calculateAndPaintOverhangBackground(GraphicsContext* context, const IntRect& dirtyRect)
980 {
981 IntRect horizontalOverhangRect;
982 IntRect verticalOverhangRect;
983 calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
984
985 if (dirtyRect.intersects(horizontalOverhangRect) || dirtyRect.intersects(verticalOverhangRect))
986 ScrollbarTheme::theme()->paintOverhangBackground(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
987 }
988
isPointInScrollbarCorner(const IntPoint & windowPoint)989 bool ScrollView::isPointInScrollbarCorner(const IntPoint& windowPoint)
990 {
991 if (!scrollbarCornerPresent())
992 return false;
993
994 IntPoint viewPoint = convertFromContainingWindow(windowPoint);
995
996 if (m_horizontalScrollbar) {
997 int horizontalScrollbarYMin = m_horizontalScrollbar->frameRect().y();
998 int horizontalScrollbarYMax = m_horizontalScrollbar->frameRect().y() + m_horizontalScrollbar->frameRect().height();
999 int horizontalScrollbarXMin = m_horizontalScrollbar->frameRect().x() + m_horizontalScrollbar->frameRect().width();
1000
1001 return viewPoint.y() > horizontalScrollbarYMin && viewPoint.y() < horizontalScrollbarYMax && viewPoint.x() > horizontalScrollbarXMin;
1002 }
1003
1004 int verticalScrollbarXMin = m_verticalScrollbar->frameRect().x();
1005 int verticalScrollbarXMax = m_verticalScrollbar->frameRect().x() + m_verticalScrollbar->frameRect().width();
1006 int verticalScrollbarYMin = m_verticalScrollbar->frameRect().y() + m_verticalScrollbar->frameRect().height();
1007
1008 return viewPoint.x() > verticalScrollbarXMin && viewPoint.x() < verticalScrollbarXMax && viewPoint.y() > verticalScrollbarYMin;
1009 }
1010
scrollbarCornerPresent() const1011 bool ScrollView::scrollbarCornerPresent() const
1012 {
1013 return (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0)
1014 || (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0);
1015 }
1016
convertFromScrollbarToContainingView(const Scrollbar * scrollbar,const IntRect & localRect) const1017 IntRect ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& localRect) const
1018 {
1019 // Scrollbars won't be transformed within us
1020 IntRect newRect = localRect;
1021 newRect.moveBy(scrollbar->location());
1022 return newRect;
1023 }
1024
convertFromContainingViewToScrollbar(const Scrollbar * scrollbar,const IntRect & parentRect) const1025 IntRect ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
1026 {
1027 IntRect newRect = parentRect;
1028 // Scrollbars won't be transformed within us
1029 newRect.moveBy(-scrollbar->location());
1030 return newRect;
1031 }
1032
1033 // FIXME: test these on windows
convertFromScrollbarToContainingView(const Scrollbar * scrollbar,const IntPoint & localPoint) const1034 IntPoint ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& localPoint) const
1035 {
1036 // Scrollbars won't be transformed within us
1037 IntPoint newPoint = localPoint;
1038 newPoint.moveBy(scrollbar->location());
1039 return newPoint;
1040 }
1041
convertFromContainingViewToScrollbar(const Scrollbar * scrollbar,const IntPoint & parentPoint) const1042 IntPoint ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
1043 {
1044 IntPoint newPoint = parentPoint;
1045 // Scrollbars won't be transformed within us
1046 newPoint.moveBy(-scrollbar->location());
1047 return newPoint;
1048 }
1049
setParentVisible(bool visible)1050 void ScrollView::setParentVisible(bool visible)
1051 {
1052 if (isParentVisible() == visible)
1053 return;
1054
1055 Widget::setParentVisible(visible);
1056
1057 if (!isSelfVisible())
1058 return;
1059
1060 HashSet<RefPtr<Widget> >::iterator end = m_children.end();
1061 for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it)
1062 (*it)->setParentVisible(visible);
1063 }
1064
show()1065 void ScrollView::show()
1066 {
1067 if (!isSelfVisible()) {
1068 setSelfVisible(true);
1069 if (isParentVisible()) {
1070 HashSet<RefPtr<Widget> >::iterator end = m_children.end();
1071 for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it)
1072 (*it)->setParentVisible(true);
1073 }
1074 }
1075
1076 Widget::show();
1077 }
1078
hide()1079 void ScrollView::hide()
1080 {
1081 if (isSelfVisible()) {
1082 if (isParentVisible()) {
1083 HashSet<RefPtr<Widget> >::iterator end = m_children.end();
1084 for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it)
1085 (*it)->setParentVisible(false);
1086 }
1087 setSelfVisible(false);
1088 }
1089
1090 Widget::hide();
1091 }
1092
addPanScrollIcon(const IntPoint & iconPosition)1093 void ScrollView::addPanScrollIcon(const IntPoint& iconPosition)
1094 {
1095 HostWindow* window = hostWindow();
1096 if (!window)
1097 return;
1098 m_drawPanScrollIcon = true;
1099 m_panScrollIconPoint = IntPoint(iconPosition.x() - panIconSizeLength / 2 , iconPosition.y() - panIconSizeLength / 2) ;
1100 window->invalidateContentsAndRootView(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)));
1101 }
1102
removePanScrollIcon()1103 void ScrollView::removePanScrollIcon()
1104 {
1105 HostWindow* window = hostWindow();
1106 if (!window)
1107 return;
1108 m_drawPanScrollIcon = false;
1109 window->invalidateContentsAndRootView(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)));
1110 }
1111
setScrollOrigin(const IntPoint & origin,bool updatePositionAtAll,bool updatePositionSynchronously)1112 void ScrollView::setScrollOrigin(const IntPoint& origin, bool updatePositionAtAll, bool updatePositionSynchronously)
1113 {
1114 if (scrollOrigin() == origin)
1115 return;
1116
1117 ScrollableArea::setScrollOrigin(origin);
1118
1119 // Update if the scroll origin changes, since our position will be different if the content size did not change.
1120 if (updatePositionAtAll && updatePositionSynchronously)
1121 updateScrollbars(scrollOffset());
1122 }
1123
1124 } // namespace blink
1125