1 /*
2 * Copyright (c) 2010, Google Inc. All rights reserved.
3 * Copyright (C) 2008, 2011 Apple Inc. All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "config.h"
33 #include "ScrollableArea.h"
34
35 #include "GraphicsContext.h"
36 #include "GraphicsLayer.h"
37 #include "FloatPoint.h"
38 #include "PlatformWheelEvent.h"
39 #include "ScrollAnimator.h"
40 #include "ScrollbarTheme.h"
41 #include <wtf/PassOwnPtr.h>
42
43 namespace WebCore {
44
ScrollableArea()45 ScrollableArea::ScrollableArea()
46 : m_scrollAnimator(ScrollAnimator::create(this))
47 , m_constrainsScrollingToContentEdge(true)
48 , m_inLiveResize(false)
49 , m_verticalScrollElasticity(ScrollElasticityNone)
50 , m_horizontalScrollElasticity(ScrollElasticityNone)
51 {
52 }
53
~ScrollableArea()54 ScrollableArea::~ScrollableArea()
55 {
56 }
57
scroll(ScrollDirection direction,ScrollGranularity granularity,float multiplier)58 bool ScrollableArea::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
59 {
60 ScrollbarOrientation orientation;
61 Scrollbar* scrollbar;
62 if (direction == ScrollUp || direction == ScrollDown) {
63 orientation = VerticalScrollbar;
64 scrollbar = verticalScrollbar();
65 } else {
66 orientation = HorizontalScrollbar;
67 scrollbar = horizontalScrollbar();
68 }
69
70 if (!scrollbar)
71 return false;
72
73 float step = 0;
74 switch (granularity) {
75 case ScrollByLine:
76 step = scrollbar->lineStep();
77 break;
78 case ScrollByPage:
79 step = scrollbar->pageStep();
80 break;
81 case ScrollByDocument:
82 step = scrollbar->totalSize();
83 break;
84 case ScrollByPixel:
85 step = scrollbar->pixelStep();
86 break;
87 }
88
89 if (direction == ScrollUp || direction == ScrollLeft)
90 multiplier = -multiplier;
91
92 return m_scrollAnimator->scroll(orientation, granularity, step, multiplier);
93 }
94
scrollToOffsetWithoutAnimation(const FloatPoint & offset)95 void ScrollableArea::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
96 {
97 m_scrollAnimator->scrollToOffsetWithoutAnimation(offset);
98 }
99
scrollToOffsetWithoutAnimation(ScrollbarOrientation orientation,float offset)100 void ScrollableArea::scrollToOffsetWithoutAnimation(ScrollbarOrientation orientation, float offset)
101 {
102 if (orientation == HorizontalScrollbar)
103 scrollToXOffsetWithoutAnimation(offset);
104 else
105 scrollToYOffsetWithoutAnimation(offset);
106 }
107
scrollToXOffsetWithoutAnimation(float x)108 void ScrollableArea::scrollToXOffsetWithoutAnimation(float x)
109 {
110 scrollToOffsetWithoutAnimation(FloatPoint(x, m_scrollAnimator->currentPosition().y()));
111 }
112
scrollToYOffsetWithoutAnimation(float y)113 void ScrollableArea::scrollToYOffsetWithoutAnimation(float y)
114 {
115 scrollToOffsetWithoutAnimation(FloatPoint(m_scrollAnimator->currentPosition().x(), y));
116 }
117
handleWheelEvent(PlatformWheelEvent & wheelEvent)118 void ScrollableArea::handleWheelEvent(PlatformWheelEvent& wheelEvent)
119 {
120 m_scrollAnimator->handleWheelEvent(wheelEvent);
121 }
122
123 #if ENABLE(GESTURE_EVENTS)
handleGestureEvent(const PlatformGestureEvent & gestureEvent)124 void ScrollableArea::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
125 {
126 m_scrollAnimator->handleGestureEvent(gestureEvent);
127 }
128 #endif
129
setScrollOffsetFromAnimation(const IntPoint & offset)130 void ScrollableArea::setScrollOffsetFromAnimation(const IntPoint& offset)
131 {
132 // Tell the derived class to scroll its contents.
133 setScrollOffset(offset);
134
135 Scrollbar* verticalScrollbar = this->verticalScrollbar();
136
137 // Tell the scrollbars to update their thumb postions.
138 if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) {
139 horizontalScrollbar->offsetDidChange();
140 if (horizontalScrollbar->isOverlayScrollbar()) {
141 if (!verticalScrollbar)
142 horizontalScrollbar->invalidate();
143 else {
144 // If there is both a horizontalScrollbar and a verticalScrollbar,
145 // then we must also invalidate the corner between them.
146 IntRect boundsAndCorner = horizontalScrollbar->boundsRect();
147 boundsAndCorner.setWidth(boundsAndCorner.width() + verticalScrollbar->width());
148 horizontalScrollbar->invalidateRect(boundsAndCorner);
149 }
150 }
151 }
152 if (verticalScrollbar) {
153 verticalScrollbar->offsetDidChange();
154 if (verticalScrollbar->isOverlayScrollbar())
155 verticalScrollbar->invalidate();
156 }
157 }
158
willStartLiveResize()159 void ScrollableArea::willStartLiveResize()
160 {
161 if (m_inLiveResize)
162 return;
163 m_inLiveResize = true;
164 scrollAnimator()->willStartLiveResize();
165 }
166
willEndLiveResize()167 void ScrollableArea::willEndLiveResize()
168 {
169 if (!m_inLiveResize)
170 return;
171 m_inLiveResize = false;
172 scrollAnimator()->willEndLiveResize();
173 }
174
didAddVerticalScrollbar(Scrollbar * scrollbar)175 void ScrollableArea::didAddVerticalScrollbar(Scrollbar* scrollbar)
176 {
177 scrollAnimator()->didAddVerticalScrollbar(scrollbar);
178 }
179
willRemoveVerticalScrollbar(Scrollbar * scrollbar)180 void ScrollableArea::willRemoveVerticalScrollbar(Scrollbar* scrollbar)
181 {
182 scrollAnimator()->willRemoveVerticalScrollbar(scrollbar);
183 }
184
didAddHorizontalScrollbar(Scrollbar * scrollbar)185 void ScrollableArea::didAddHorizontalScrollbar(Scrollbar* scrollbar)
186 {
187 scrollAnimator()->didAddHorizontalScrollbar(scrollbar);
188 }
189
willRemoveHorizontalScrollbar(Scrollbar * scrollbar)190 void ScrollableArea::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
191 {
192 scrollAnimator()->willRemoveHorizontalScrollbar(scrollbar);
193 }
194
hasOverlayScrollbars() const195 bool ScrollableArea::hasOverlayScrollbars() const
196 {
197 return (verticalScrollbar() && verticalScrollbar()->isOverlayScrollbar())
198 || (horizontalScrollbar() && horizontalScrollbar()->isOverlayScrollbar());
199 }
200
invalidateScrollbar(Scrollbar * scrollbar,const IntRect & rect)201 void ScrollableArea::invalidateScrollbar(Scrollbar* scrollbar, const IntRect& rect)
202 {
203 #if USE(ACCELERATED_COMPOSITING)
204 if (scrollbar == horizontalScrollbar()) {
205 if (GraphicsLayer* graphicsLayer = layerForHorizontalScrollbar()) {
206 graphicsLayer->setNeedsDisplay();
207 return;
208 }
209 } else if (scrollbar == verticalScrollbar()) {
210 if (GraphicsLayer* graphicsLayer = layerForVerticalScrollbar()) {
211 graphicsLayer->setNeedsDisplay();
212 return;
213 }
214 }
215 #endif
216 invalidateScrollbarRect(scrollbar, rect);
217 }
218
invalidateScrollCorner()219 void ScrollableArea::invalidateScrollCorner()
220 {
221 #if USE(ACCELERATED_COMPOSITING)
222 if (GraphicsLayer* graphicsLayer = layerForScrollCorner()) {
223 graphicsLayer->setNeedsDisplay();
224 return;
225 }
226 #endif
227 invalidateScrollCornerRect(scrollCornerRect());
228 }
229
230 } // namespace WebCore
231