| 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 |