OLD | NEW |
1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv
ed. | 3 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv
ed. |
3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 4 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) | 5 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) |
5 * | 6 * |
6 * Redistribution and use in source and binary forms, with or without | 7 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 8 * modification, are permitted provided that the following conditions |
8 * are met: | 9 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 11 * notice, this list of conditions and the following disclaimer. |
11 * 2. Redistributions in binary form must reproduce the above copyright | 12 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 12 matching lines...) Expand all Loading... |
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 */ | 27 */ |
27 | 28 |
28 #include "config.h" | 29 #include "config.h" |
29 #include "core/page/AutoscrollController.h" | 30 #include "core/page/AutoscrollController.h" |
30 | 31 |
31 #include "core/page/EventHandler.h" | 32 #include "core/page/EventHandler.h" |
32 #include "core/frame/Frame.h" | 33 #include "core/frame/Frame.h" |
33 #include "core/frame/FrameView.h" | 34 #include "core/frame/FrameView.h" |
| 35 #include "core/page/Chrome.h" |
34 #include "core/page/Page.h" | 36 #include "core/page/Page.h" |
35 #include "core/rendering/HitTestResult.h" | 37 #include "core/rendering/HitTestResult.h" |
36 #include "core/rendering/RenderBox.h" | 38 #include "core/rendering/RenderBox.h" |
37 #include "wtf/CurrentTime.h" | 39 #include "wtf/CurrentTime.h" |
38 | 40 |
39 namespace WebCore { | 41 namespace WebCore { |
40 | 42 |
41 // Delay time in second for start autoscroll if pointer is in border edge of scr
ollable element. | 43 // Delay time in second for start autoscroll if pointer is in border edge of scr
ollable element. |
42 static double autoscrollDelay = 0.2; | 44 static double autoscrollDelay = 0.2; |
43 | 45 |
44 // When the autoscroll or the panScroll is triggered when do the scroll every 0.
05s to make it smooth | 46 PassOwnPtr<AutoscrollController> AutoscrollController::create(Page& page) |
45 static const double autoscrollInterval = 0.05; | |
46 | |
47 PassOwnPtr<AutoscrollController> AutoscrollController::create() | |
48 { | 47 { |
49 return adoptPtr(new AutoscrollController()); | 48 return adoptPtr(new AutoscrollController(page)); |
50 } | 49 } |
51 | 50 |
52 AutoscrollController::AutoscrollController() | 51 AutoscrollController::AutoscrollController(Page& page) |
53 : m_autoscrollTimer(this, &AutoscrollController::autoscrollTimerFired) | 52 : m_page(page) |
54 , m_autoscrollRenderer(0) | 53 , m_autoscrollRenderer(0) |
55 , m_autoscrollType(NoAutoscroll) | 54 , m_autoscrollType(NoAutoscroll) |
56 , m_dragAndDropAutoscrollStartTime(0) | 55 , m_dragAndDropAutoscrollStartTime(0) |
57 { | 56 { |
58 } | 57 } |
59 | 58 |
60 bool AutoscrollController::autoscrollInProgress() const | 59 bool AutoscrollController::autoscrollInProgress() const |
61 { | 60 { |
62 return m_autoscrollType == AutoscrollForSelection; | 61 return m_autoscrollType == AutoscrollForSelection; |
63 } | 62 } |
64 | 63 |
65 bool AutoscrollController::autoscrollInProgress(const RenderBox* renderer) const | 64 bool AutoscrollController::autoscrollInProgress(const RenderBox* renderer) const |
66 { | 65 { |
67 return m_autoscrollRenderer == renderer; | 66 return m_autoscrollRenderer == renderer; |
68 } | 67 } |
69 | 68 |
70 void AutoscrollController::startAutoscrollForSelection(RenderObject* renderer) | 69 void AutoscrollController::startAutoscrollForSelection(RenderObject* renderer) |
71 { | 70 { |
72 // We don't want to trigger the autoscroll or the panScroll if it's already
active | 71 // We don't want to trigger the autoscroll or the panScroll if it's already
active |
73 if (m_autoscrollTimer.isActive()) | 72 if (m_autoscrollType != NoAutoscroll) |
74 return; | 73 return; |
75 RenderBox* scrollable = RenderBox::findAutoscrollable(renderer); | 74 RenderBox* scrollable = RenderBox::findAutoscrollable(renderer); |
76 if (!scrollable) | 75 if (!scrollable) |
77 return; | 76 return; |
78 m_autoscrollType = AutoscrollForSelection; | 77 m_autoscrollType = AutoscrollForSelection; |
79 m_autoscrollRenderer = scrollable; | 78 m_autoscrollRenderer = scrollable; |
80 startAutoscrollTimer(); | 79 startAutoscroll(); |
81 } | 80 } |
82 | 81 |
83 void AutoscrollController::stopAutoscrollTimer() | 82 void AutoscrollController::stopAutoscroll() |
84 { | 83 { |
85 RenderBox* scrollable = m_autoscrollRenderer; | 84 RenderBox* scrollable = m_autoscrollRenderer; |
86 m_autoscrollTimer.stop(); | |
87 m_autoscrollRenderer = 0; | 85 m_autoscrollRenderer = 0; |
88 | 86 |
89 if (!scrollable) | 87 if (!scrollable) |
90 return; | 88 return; |
91 | 89 |
92 scrollable->stopAutoscroll(); | 90 scrollable->stopAutoscroll(); |
93 #if OS(WIN) | 91 #if OS(WIN) |
94 if (panScrollInProgress()) { | 92 if (panScrollInProgress()) { |
95 if (FrameView* view = scrollable->frame()->view()) { | 93 if (FrameView* view = scrollable->frame()->view()) { |
96 view->removePanScrollIcon(); | 94 view->removePanScrollIcon(); |
97 view->setCursor(pointerCursor()); | 95 view->setCursor(pointerCursor()); |
98 } | 96 } |
99 } | 97 } |
100 #endif | 98 #endif |
101 | 99 |
102 m_autoscrollType = NoAutoscroll; | 100 m_autoscrollType = NoAutoscroll; |
103 } | 101 } |
104 | 102 |
105 void AutoscrollController::stopAutoscrollIfNeeded(RenderObject* renderer) | 103 void AutoscrollController::stopAutoscrollIfNeeded(RenderObject* renderer) |
106 { | 104 { |
107 if (m_autoscrollRenderer != renderer) | 105 if (m_autoscrollRenderer != renderer) |
108 return; | 106 return; |
109 m_autoscrollRenderer = 0; | 107 m_autoscrollRenderer = 0; |
110 m_autoscrollType = NoAutoscroll; | 108 m_autoscrollType = NoAutoscroll; |
111 m_autoscrollTimer.stop(); | |
112 } | 109 } |
113 | 110 |
114 void AutoscrollController::updateAutoscrollRenderer() | 111 void AutoscrollController::updateAutoscrollRenderer() |
115 { | 112 { |
116 if (!m_autoscrollRenderer) | 113 if (!m_autoscrollRenderer) |
117 return; | 114 return; |
118 | 115 |
119 RenderObject* renderer = m_autoscrollRenderer; | 116 RenderObject* renderer = m_autoscrollRenderer; |
120 | 117 |
121 #if OS(WIN) | 118 #if OS(WIN) |
122 HitTestResult hitTest = renderer->frame()->eventHandler().hitTestResultAtPoi
nt(m_panScrollStartPos, HitTestRequest::ReadOnly | HitTestRequest::Active | HitT
estRequest::DisallowShadowContent); | 119 HitTestResult hitTest = renderer->frame()->eventHandler().hitTestResultAtPoi
nt(m_panScrollStartPos, HitTestRequest::ReadOnly | HitTestRequest::Active | HitT
estRequest::DisallowShadowContent); |
123 | 120 |
124 if (Node* nodeAtPoint = hitTest.innerNode()) | 121 if (Node* nodeAtPoint = hitTest.innerNode()) |
125 renderer = nodeAtPoint->renderer(); | 122 renderer = nodeAtPoint->renderer(); |
126 #endif | 123 #endif |
127 | 124 |
128 while (renderer && !(renderer->isBox() && toRenderBox(renderer)->canAutoscro
ll())) | 125 while (renderer && !(renderer->isBox() && toRenderBox(renderer)->canAutoscro
ll())) |
129 renderer = renderer->parent(); | 126 renderer = renderer->parent(); |
130 m_autoscrollRenderer = renderer && renderer->isBox() ? toRenderBox(renderer)
: 0; | 127 m_autoscrollRenderer = renderer && renderer->isBox() ? toRenderBox(renderer)
: 0; |
131 } | 128 } |
132 | 129 |
133 void AutoscrollController::updateDragAndDrop(Node* dropTargetNode, const IntPoin
t& eventPosition, double eventTime) | 130 void AutoscrollController::updateDragAndDrop(Node* dropTargetNode, const IntPoin
t& eventPosition, double eventTime) |
134 { | 131 { |
135 if (!dropTargetNode || !dropTargetNode->renderer()) { | 132 if (!dropTargetNode || !dropTargetNode->renderer()) { |
136 stopAutoscrollTimer(); | 133 stopAutoscroll(); |
137 return; | 134 return; |
138 } | 135 } |
139 | 136 |
140 if (m_autoscrollRenderer && m_autoscrollRenderer->frame() != dropTargetNode-
>renderer()->frame()) | 137 if (m_autoscrollRenderer && m_autoscrollRenderer->frame() != dropTargetNode-
>renderer()->frame()) |
141 return; | 138 return; |
142 | 139 |
143 RenderBox* scrollable = RenderBox::findAutoscrollable(dropTargetNode->render
er()); | 140 RenderBox* scrollable = RenderBox::findAutoscrollable(dropTargetNode->render
er()); |
144 if (!scrollable) { | 141 if (!scrollable) { |
145 stopAutoscrollTimer(); | 142 stopAutoscroll(); |
146 return; | 143 return; |
147 } | 144 } |
148 | 145 |
149 Page* page = scrollable->frame() ? scrollable->frame()->page() : 0; | 146 Page* page = scrollable->frame() ? scrollable->frame()->page() : 0; |
150 if (!page) { | 147 if (!page) { |
151 stopAutoscrollTimer(); | 148 stopAutoscroll(); |
152 return; | 149 return; |
153 } | 150 } |
154 | 151 |
155 IntSize offset = scrollable->calculateAutoscrollDirection(eventPosition); | 152 IntSize offset = scrollable->calculateAutoscrollDirection(eventPosition); |
156 if (offset.isZero()) { | 153 if (offset.isZero()) { |
157 stopAutoscrollTimer(); | 154 stopAutoscroll(); |
158 return; | 155 return; |
159 } | 156 } |
160 | 157 |
161 m_dragAndDropAutoscrollReferencePosition = eventPosition + offset; | 158 m_dragAndDropAutoscrollReferencePosition = eventPosition + offset; |
162 | 159 |
163 if (m_autoscrollType == NoAutoscroll) { | 160 if (m_autoscrollType == NoAutoscroll) { |
164 m_autoscrollType = AutoscrollForDragAndDrop; | 161 m_autoscrollType = AutoscrollForDragAndDrop; |
165 m_autoscrollRenderer = scrollable; | 162 m_autoscrollRenderer = scrollable; |
166 m_dragAndDropAutoscrollStartTime = eventTime; | 163 m_dragAndDropAutoscrollStartTime = eventTime; |
167 startAutoscrollTimer(); | 164 startAutoscroll(); |
168 } else if (m_autoscrollRenderer != scrollable) { | 165 } else if (m_autoscrollRenderer != scrollable) { |
169 m_dragAndDropAutoscrollStartTime = eventTime; | 166 m_dragAndDropAutoscrollStartTime = eventTime; |
170 m_autoscrollRenderer = scrollable; | 167 m_autoscrollRenderer = scrollable; |
171 } | 168 } |
172 } | 169 } |
173 | 170 |
174 #if OS(WIN) | 171 #if OS(WIN) |
175 void AutoscrollController::handleMouseReleaseForPanScrolling(Frame* frame, const
PlatformMouseEvent& mouseEvent) | 172 void AutoscrollController::handleMouseReleaseForPanScrolling(Frame* frame, const
PlatformMouseEvent& mouseEvent) |
176 { | 173 { |
177 Page* page = frame->page(); | 174 Page* page = frame->page(); |
178 if (!page || page->mainFrame() != frame) | 175 if (!page || page->mainFrame() != frame) |
179 return; | 176 return; |
180 switch (m_autoscrollType) { | 177 switch (m_autoscrollType) { |
181 case AutoscrollForPan: | 178 case AutoscrollForPan: |
182 if (mouseEvent.button() == MiddleButton) | 179 if (mouseEvent.button() == MiddleButton) |
183 m_autoscrollType = AutoscrollForPanCanStop; | 180 m_autoscrollType = AutoscrollForPanCanStop; |
184 break; | 181 break; |
185 case AutoscrollForPanCanStop: | 182 case AutoscrollForPanCanStop: |
186 stopAutoscrollTimer(); | 183 stopAutoscroll(); |
187 break; | 184 break; |
188 } | 185 } |
189 } | 186 } |
190 | 187 |
191 bool AutoscrollController::panScrollInProgress() const | 188 bool AutoscrollController::panScrollInProgress() const |
192 { | 189 { |
193 return m_autoscrollType == AutoscrollForPanCanStop || m_autoscrollType == Au
toscrollForPan; | 190 return m_autoscrollType == AutoscrollForPanCanStop || m_autoscrollType == Au
toscrollForPan; |
194 } | 191 } |
195 | 192 |
196 void AutoscrollController::startPanScrolling(RenderBox* scrollable, const IntPoi
nt& lastKnownMousePosition) | 193 void AutoscrollController::startPanScrolling(RenderBox* scrollable, const IntPoi
nt& lastKnownMousePosition) |
197 { | 194 { |
198 // We don't want to trigger the autoscroll or the panScroll if it's already
active | 195 // We don't want to trigger the autoscroll or the panScroll if it's already
active |
199 if (m_autoscrollTimer.isActive()) | 196 if (m_autoscrollType != NoAutoscroll) |
200 return; | 197 return; |
201 | 198 |
202 m_autoscrollType = AutoscrollForPan; | 199 m_autoscrollType = AutoscrollForPan; |
203 m_autoscrollRenderer = scrollable; | 200 m_autoscrollRenderer = scrollable; |
204 m_panScrollStartPos = lastKnownMousePosition; | 201 m_panScrollStartPos = lastKnownMousePosition; |
205 | 202 |
206 if (FrameView* view = scrollable->frame()->view()) | 203 if (FrameView* view = scrollable->frame()->view()) |
207 view->addPanScrollIcon(lastKnownMousePosition); | 204 view->addPanScrollIcon(lastKnownMousePosition); |
208 startAutoscrollTimer(); | 205 startAutoscroll(); |
209 } | 206 } |
210 #else | 207 #else |
211 bool AutoscrollController::panScrollInProgress() const | 208 bool AutoscrollController::panScrollInProgress() const |
212 { | 209 { |
213 return false; | 210 return false; |
214 } | 211 } |
215 #endif | 212 #endif |
216 | 213 |
217 void AutoscrollController::autoscrollTimerFired(Timer<AutoscrollController>*) | 214 // FIXME: This would get get better animation fidelity if it used the monotonicF
rameBeginTime instead |
| 215 // of WTF::currentTime(). |
| 216 void AutoscrollController::animate(double) |
218 { | 217 { |
219 if (!m_autoscrollRenderer) { | 218 if (!m_autoscrollRenderer) { |
220 stopAutoscrollTimer(); | 219 stopAutoscroll(); |
221 return; | 220 return; |
222 } | 221 } |
223 | 222 |
224 EventHandler& eventHandler = m_autoscrollRenderer->frame()->eventHandler(); | 223 EventHandler& eventHandler = m_autoscrollRenderer->frame()->eventHandler(); |
225 switch (m_autoscrollType) { | 224 switch (m_autoscrollType) { |
226 case AutoscrollForDragAndDrop: | 225 case AutoscrollForDragAndDrop: |
227 if (WTF::currentTime() - m_dragAndDropAutoscrollStartTime > autoscrollDe
lay) | 226 if (WTF::currentTime() - m_dragAndDropAutoscrollStartTime > autoscrollDe
lay) |
228 m_autoscrollRenderer->autoscroll(m_dragAndDropAutoscrollReferencePos
ition); | 227 m_autoscrollRenderer->autoscroll(m_dragAndDropAutoscrollReferencePos
ition); |
229 break; | 228 break; |
230 case AutoscrollForSelection: | 229 case AutoscrollForSelection: |
231 if (!eventHandler.mousePressed()) { | 230 if (!eventHandler.mousePressed()) { |
232 stopAutoscrollTimer(); | 231 stopAutoscroll(); |
233 return; | 232 return; |
234 } | 233 } |
235 eventHandler.updateSelectionForMouseDrag(); | 234 eventHandler.updateSelectionForMouseDrag(); |
236 m_autoscrollRenderer->autoscroll(eventHandler.lastKnownMousePosition()); | 235 m_autoscrollRenderer->autoscroll(eventHandler.lastKnownMousePosition()); |
237 break; | 236 break; |
238 case NoAutoscroll: | 237 case NoAutoscroll: |
239 break; | 238 break; |
240 #if OS(WIN) | 239 #if OS(WIN) |
241 case AutoscrollForPanCanStop: | 240 case AutoscrollForPanCanStop: |
242 case AutoscrollForPan: | 241 case AutoscrollForPan: |
243 if (!panScrollInProgress()) { | 242 if (!panScrollInProgress()) { |
244 stopAutoscrollTimer(); | 243 stopAutoscroll(); |
245 return; | 244 return; |
246 } | 245 } |
247 if (FrameView* view = m_autoscrollRenderer->frame()->view()) | 246 if (FrameView* view = m_autoscrollRenderer->frame()->view()) |
248 updatePanScrollState(view, eventHandler.lastKnownMousePosition()); | 247 updatePanScrollState(view, eventHandler.lastKnownMousePosition()); |
249 m_autoscrollRenderer->panScroll(m_panScrollStartPos); | 248 m_autoscrollRenderer->panScroll(m_panScrollStartPos); |
250 break; | 249 break; |
251 #endif | 250 #endif |
252 } | 251 } |
| 252 if (m_autoscrollType != NoAutoscroll) |
| 253 m_page.chrome().scheduleAnimation(); |
253 } | 254 } |
254 | 255 |
255 void AutoscrollController::startAutoscrollTimer() | 256 void AutoscrollController::startAutoscroll() |
256 { | 257 { |
257 m_autoscrollTimer.startRepeating(autoscrollInterval); | 258 m_page.chrome().scheduleAnimation(); |
258 } | 259 } |
259 | 260 |
260 #if OS(WIN) | 261 #if OS(WIN) |
261 void AutoscrollController::updatePanScrollState(FrameView* view, const IntPoint&
lastKnownMousePosition) | 262 void AutoscrollController::updatePanScrollState(FrameView* view, const IntPoint&
lastKnownMousePosition) |
262 { | 263 { |
263 // At the original click location we draw a 4 arrowed icon. Over this icon t
here won't be any scroll | 264 // At the original click location we draw a 4 arrowed icon. Over this icon t
here won't be any scroll |
264 // So we don't want to change the cursor over this area | 265 // So we don't want to change the cursor over this area |
265 bool east = m_panScrollStartPos.x() < (lastKnownMousePosition.x() - ScrollVi
ew::noPanScrollRadius); | 266 bool east = m_panScrollStartPos.x() < (lastKnownMousePosition.x() - ScrollVi
ew::noPanScrollRadius); |
266 bool west = m_panScrollStartPos.x() > (lastKnownMousePosition.x() + ScrollVi
ew::noPanScrollRadius); | 267 bool west = m_panScrollStartPos.x() > (lastKnownMousePosition.x() + ScrollVi
ew::noPanScrollRadius); |
267 bool north = m_panScrollStartPos.y() > (lastKnownMousePosition.y() + ScrollV
iew::noPanScrollRadius); | 268 bool north = m_panScrollStartPos.y() > (lastKnownMousePosition.y() + ScrollV
iew::noPanScrollRadius); |
(...skipping 19 matching lines...) Expand all Loading... |
287 } else if (east) | 288 } else if (east) |
288 view->setCursor(eastPanningCursor()); | 289 view->setCursor(eastPanningCursor()); |
289 else if (west) | 290 else if (west) |
290 view->setCursor(westPanningCursor()); | 291 view->setCursor(westPanningCursor()); |
291 else | 292 else |
292 view->setCursor(middlePanningCursor()); | 293 view->setCursor(middlePanningCursor()); |
293 } | 294 } |
294 #endif | 295 #endif |
295 | 296 |
296 } // namespace WebCore | 297 } // namespace WebCore |
OLD | NEW |