| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv
ed. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv
ed. |
| 3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
| 4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) | 4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 8 * are met: | 8 * are met: |
| 9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 #include "sky/engine/core/dom/NodeRenderingTraversal.h" | 36 #include "sky/engine/core/dom/NodeRenderingTraversal.h" |
| 37 #include "sky/engine/core/dom/TouchList.h" | 37 #include "sky/engine/core/dom/TouchList.h" |
| 38 #include "sky/engine/core/dom/shadow/ShadowRoot.h" | 38 #include "sky/engine/core/dom/shadow/ShadowRoot.h" |
| 39 #include "sky/engine/core/editing/Editor.h" | 39 #include "sky/engine/core/editing/Editor.h" |
| 40 #include "sky/engine/core/editing/FrameSelection.h" | 40 #include "sky/engine/core/editing/FrameSelection.h" |
| 41 #include "sky/engine/core/editing/TextIterator.h" | 41 #include "sky/engine/core/editing/TextIterator.h" |
| 42 #include "sky/engine/core/editing/htmlediting.h" | 42 #include "sky/engine/core/editing/htmlediting.h" |
| 43 #include "sky/engine/core/events/DOMWindowEventQueue.h" | 43 #include "sky/engine/core/events/DOMWindowEventQueue.h" |
| 44 #include "sky/engine/core/events/EventPath.h" | 44 #include "sky/engine/core/events/EventPath.h" |
| 45 #include "sky/engine/core/events/KeyboardEvent.h" | 45 #include "sky/engine/core/events/KeyboardEvent.h" |
| 46 #include "sky/engine/core/events/MouseEvent.h" | |
| 47 #include "sky/engine/core/events/TextEvent.h" | 46 #include "sky/engine/core/events/TextEvent.h" |
| 48 #include "sky/engine/core/events/TouchEvent.h" | 47 #include "sky/engine/core/events/TouchEvent.h" |
| 49 #include "sky/engine/core/events/WheelEvent.h" | |
| 50 #include "sky/engine/core/fetch/ImageResource.h" | 48 #include "sky/engine/core/fetch/ImageResource.h" |
| 51 #include "sky/engine/core/frame/FrameView.h" | 49 #include "sky/engine/core/frame/FrameView.h" |
| 52 #include "sky/engine/core/frame/LocalFrame.h" | 50 #include "sky/engine/core/frame/LocalFrame.h" |
| 53 #include "sky/engine/core/frame/Settings.h" | 51 #include "sky/engine/core/frame/Settings.h" |
| 54 #include "sky/engine/core/loader/FrameLoaderClient.h" | 52 #include "sky/engine/core/loader/FrameLoaderClient.h" |
| 55 #include "sky/engine/core/page/AutoscrollController.h" | 53 #include "sky/engine/core/page/AutoscrollController.h" |
| 56 #include "sky/engine/core/page/Chrome.h" | 54 #include "sky/engine/core/page/Chrome.h" |
| 57 #include "sky/engine/core/page/ChromeClient.h" | 55 #include "sky/engine/core/page/ChromeClient.h" |
| 58 #include "sky/engine/core/page/EditorClient.h" | 56 #include "sky/engine/core/page/EditorClient.h" |
| 59 #include "sky/engine/core/page/EventWithHitTestResults.h" | 57 #include "sky/engine/core/page/EventWithHitTestResults.h" |
| 60 #include "sky/engine/core/page/FocusController.h" | 58 #include "sky/engine/core/page/FocusController.h" |
| 61 #include "sky/engine/core/page/Page.h" | 59 #include "sky/engine/core/page/Page.h" |
| 62 #include "sky/engine/core/rendering/HitTestRequest.h" | 60 #include "sky/engine/core/rendering/HitTestRequest.h" |
| 63 #include "sky/engine/core/rendering/HitTestResult.h" | 61 #include "sky/engine/core/rendering/HitTestResult.h" |
| 64 #include "sky/engine/core/rendering/RenderLayer.h" | 62 #include "sky/engine/core/rendering/RenderLayer.h" |
| 65 #include "sky/engine/core/rendering/RenderView.h" | 63 #include "sky/engine/core/rendering/RenderView.h" |
| 66 #include "sky/engine/core/rendering/style/RenderStyle.h" | 64 #include "sky/engine/core/rendering/style/RenderStyle.h" |
| 67 #include "sky/engine/platform/PlatformGestureEvent.h" | 65 #include "sky/engine/platform/PlatformGestureEvent.h" |
| 68 #include "sky/engine/platform/PlatformKeyboardEvent.h" | 66 #include "sky/engine/platform/PlatformKeyboardEvent.h" |
| 69 #include "sky/engine/platform/PlatformTouchEvent.h" | 67 #include "sky/engine/platform/PlatformTouchEvent.h" |
| 70 #include "sky/engine/platform/PlatformWheelEvent.h" | |
| 71 #include "sky/engine/platform/TraceEvent.h" | 68 #include "sky/engine/platform/TraceEvent.h" |
| 72 #include "sky/engine/platform/WindowsKeyboardCodes.h" | 69 #include "sky/engine/platform/WindowsKeyboardCodes.h" |
| 73 #include "sky/engine/platform/geometry/FloatPoint.h" | 70 #include "sky/engine/platform/geometry/FloatPoint.h" |
| 74 #include "sky/engine/platform/graphics/Image.h" | 71 #include "sky/engine/platform/graphics/Image.h" |
| 75 #include "sky/engine/platform/heap/Handle.h" | 72 #include "sky/engine/platform/heap/Handle.h" |
| 76 #include "sky/engine/platform/scroll/ScrollAnimator.h" | 73 #include "sky/engine/platform/scroll/ScrollAnimator.h" |
| 77 #include "sky/engine/platform/scroll/Scrollbar.h" | 74 #include "sky/engine/platform/scroll/Scrollbar.h" |
| 78 #include "sky/engine/wtf/Assertions.h" | 75 #include "sky/engine/wtf/Assertions.h" |
| 79 #include "sky/engine/wtf/CurrentTime.h" | 76 #include "sky/engine/wtf/CurrentTime.h" |
| 80 #include "sky/engine/wtf/StdLibExtras.h" | 77 #include "sky/engine/wtf/StdLibExtras.h" |
| 81 #include "sky/engine/wtf/TemporaryChange.h" | 78 #include "sky/engine/wtf/TemporaryChange.h" |
| 82 | 79 |
| 83 namespace blink { | 80 namespace blink { |
| 84 | 81 |
| 85 // The amount of time to wait before sending a fake mouse event, triggered | |
| 86 // during a scroll. The short interval is used if the content responds to the mo
use events quickly enough, | |
| 87 // otherwise the long interval is used. | |
| 88 static const double fakeMouseMoveShortInterval = 0.1; | |
| 89 static const double fakeMouseMoveLongInterval = 0.250; | |
| 90 | |
| 91 // The amount of time to wait for a cursor update on style and layout changes | 82 // The amount of time to wait for a cursor update on style and layout changes |
| 92 // Set to 50Hz, no need to be faster than common screen refresh rate | 83 // Set to 50Hz, no need to be faster than common screen refresh rate |
| 93 static const double cursorUpdateInterval = 0.02; | 84 static const double cursorUpdateInterval = 0.02; |
| 94 | 85 |
| 95 static const int maximumCursorSize = 128; | 86 static const int maximumCursorSize = 128; |
| 96 | 87 |
| 97 // It's pretty unlikely that a scale of less than one would ever be used. But al
l we really | 88 // It's pretty unlikely that a scale of less than one would ever be used. But al
l we really |
| 98 // need to ensure here is that the scale isn't so small that integer overflow ca
n occur when | 89 // need to ensure here is that the scale isn't so small that integer overflow ca
n occur when |
| 99 // dividing cursor sizes (limited above) by the scale. | 90 // dividing cursor sizes (limited above) by the scale. |
| 100 static const double minimumCursorScale = 0.001; | 91 static const double minimumCursorScale = 0.001; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 129 ~MaximumDurationTracker() | 120 ~MaximumDurationTracker() |
| 130 { | 121 { |
| 131 *m_maxDuration = max(*m_maxDuration, monotonicallyIncreasingTime() - m_s
tart); | 122 *m_maxDuration = max(*m_maxDuration, monotonicallyIncreasingTime() - m_s
tart); |
| 132 } | 123 } |
| 133 | 124 |
| 134 private: | 125 private: |
| 135 double* m_maxDuration; | 126 double* m_maxDuration; |
| 136 double m_start; | 127 double m_start; |
| 137 }; | 128 }; |
| 138 | 129 |
| 139 static inline ScrollGranularity wheelGranularityToScrollGranularity(unsigned del
taMode) | |
| 140 { | |
| 141 switch (deltaMode) { | |
| 142 case WheelEvent::DOM_DELTA_PAGE: | |
| 143 return ScrollByPage; | |
| 144 case WheelEvent::DOM_DELTA_LINE: | |
| 145 return ScrollByLine; | |
| 146 case WheelEvent::DOM_DELTA_PIXEL: | |
| 147 return ScrollByPixel; | |
| 148 default: | |
| 149 return ScrollByPixel; | |
| 150 } | |
| 151 } | |
| 152 | |
| 153 EventHandler::EventHandler(LocalFrame* frame) | 130 EventHandler::EventHandler(LocalFrame* frame) |
| 154 : m_frame(frame) | 131 : m_frame(frame) |
| 155 , m_mousePressed(false) | 132 , m_mousePressed(false) |
| 156 , m_capturesDragging(false) | 133 , m_capturesDragging(false) |
| 157 , m_mouseDownMayStartSelect(false) | 134 , m_mouseDownMayStartSelect(false) |
| 158 , m_mouseDownMayStartDrag(false) | 135 , m_mouseDownMayStartDrag(false) |
| 159 , m_mouseDownWasSingleClickInSelection(false) | |
| 160 , m_selectionInitiationState(HaveNotStartedSelection) | 136 , m_selectionInitiationState(HaveNotStartedSelection) |
| 161 , m_hoverTimer(this, &EventHandler::hoverTimerFired) | 137 , m_hoverTimer(this, &EventHandler::hoverTimerFired) |
| 162 , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired) | 138 , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired) |
| 163 , m_mouseDownMayStartAutoscroll(false) | 139 , m_mouseDownMayStartAutoscroll(false) |
| 164 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFire
d) | |
| 165 , m_eventHandlerWillResetCapturingMouseEventsNode(0) | |
| 166 , m_clickCount(0) | 140 , m_clickCount(0) |
| 167 , m_shouldOnlyFireDragOverEvent(false) | 141 , m_shouldOnlyFireDragOverEvent(false) |
| 168 , m_mousePositionIsUnknown(true) | 142 , m_mousePositionIsUnknown(true) |
| 169 , m_mouseDownTimestamp(0) | |
| 170 , m_widgetIsLatched(false) | |
| 171 , m_touchPressed(false) | 143 , m_touchPressed(false) |
| 172 , m_scrollGestureHandlingNode(nullptr) | 144 , m_scrollGestureHandlingNode(nullptr) |
| 173 , m_lastGestureScrollOverWidget(false) | 145 , m_lastGestureScrollOverWidget(false) |
| 174 , m_maxMouseMovedDuration(0) | 146 , m_maxMouseMovedDuration(0) |
| 175 , m_didStartDrag(false) | 147 , m_didStartDrag(false) |
| 176 , m_activeIntervalTimer(this, &EventHandler::activeIntervalTimerFired) | 148 , m_activeIntervalTimer(this, &EventHandler::activeIntervalTimerFired) |
| 177 , m_lastShowPressTimestamp(0) | 149 , m_lastShowPressTimestamp(0) |
| 178 { | 150 { |
| 179 } | 151 } |
| 180 | 152 |
| 181 EventHandler::~EventHandler() | 153 EventHandler::~EventHandler() |
| 182 { | 154 { |
| 183 ASSERT(!m_fakeMouseMoveEventTimer.isActive()); | |
| 184 } | 155 } |
| 185 | 156 |
| 186 void EventHandler::clear() | 157 void EventHandler::clear() |
| 187 { | 158 { |
| 188 m_hoverTimer.stop(); | 159 m_hoverTimer.stop(); |
| 189 m_cursorUpdateTimer.stop(); | 160 m_cursorUpdateTimer.stop(); |
| 190 m_fakeMouseMoveEventTimer.stop(); | |
| 191 m_activeIntervalTimer.stop(); | 161 m_activeIntervalTimer.stop(); |
| 192 m_nodeUnderMouse = nullptr; | 162 m_nodeUnderMouse = nullptr; |
| 193 m_lastNodeUnderMouse = nullptr; | 163 m_lastNodeUnderMouse = nullptr; |
| 194 m_lastScrollbarUnderMouse = nullptr; | 164 m_lastScrollbarUnderMouse = nullptr; |
| 195 m_clickCount = 0; | 165 m_clickCount = 0; |
| 196 m_clickNode = nullptr; | 166 m_clickNode = nullptr; |
| 197 m_dragTarget = nullptr; | 167 m_dragTarget = nullptr; |
| 198 m_shouldOnlyFireDragOverEvent = false; | 168 m_shouldOnlyFireDragOverEvent = false; |
| 199 m_mousePositionIsUnknown = true; | 169 m_mousePositionIsUnknown = true; |
| 200 m_lastKnownMousePosition = IntPoint(); | 170 m_lastKnownMousePosition = IntPoint(); |
| 201 m_lastKnownMouseGlobalPosition = IntPoint(); | 171 m_lastKnownMouseGlobalPosition = IntPoint(); |
| 202 m_mousePressNode = nullptr; | 172 m_mousePressNode = nullptr; |
| 203 m_mousePressed = false; | 173 m_mousePressed = false; |
| 204 m_capturesDragging = false; | 174 m_capturesDragging = false; |
| 205 m_capturingMouseEventsNode = nullptr; | |
| 206 m_latchedWheelEventNode = nullptr; | |
| 207 m_previousWheelScrolledNode = nullptr; | 175 m_previousWheelScrolledNode = nullptr; |
| 208 m_targetForTouchID.clear(); | 176 m_targetForTouchID.clear(); |
| 209 m_touchSequenceDocument.clear(); | 177 m_touchSequenceDocument.clear(); |
| 210 m_scrollGestureHandlingNode = nullptr; | 178 m_scrollGestureHandlingNode = nullptr; |
| 211 m_lastGestureScrollOverWidget = false; | 179 m_lastGestureScrollOverWidget = false; |
| 212 m_previousGestureScrolledNode = nullptr; | 180 m_previousGestureScrolledNode = nullptr; |
| 213 m_scrollbarHandlingScrollGesture = nullptr; | 181 m_scrollbarHandlingScrollGesture = nullptr; |
| 214 m_maxMouseMovedDuration = 0; | 182 m_maxMouseMovedDuration = 0; |
| 215 m_didStartDrag = false; | 183 m_didStartDrag = false; |
| 216 m_touchPressed = false; | 184 m_touchPressed = false; |
| 217 m_mouseDownMayStartSelect = false; | 185 m_mouseDownMayStartSelect = false; |
| 218 m_mouseDownMayStartDrag = false; | 186 m_mouseDownMayStartDrag = false; |
| 219 m_lastShowPressTimestamp = 0; | 187 m_lastShowPressTimestamp = 0; |
| 220 m_lastDeferredTapElement = nullptr; | 188 m_lastDeferredTapElement = nullptr; |
| 221 } | 189 } |
| 222 | 190 |
| 223 void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved) | 191 void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved) |
| 224 { | 192 { |
| 225 if (!nodeToBeRemoved.containsIncludingShadowDOM(m_clickNode.get())) | 193 if (!nodeToBeRemoved.containsIncludingShadowDOM(m_clickNode.get())) |
| 226 return; | 194 return; |
| 227 if (nodeToBeRemoved.isInShadowTree()) { | 195 if (nodeToBeRemoved.isInShadowTree()) { |
| 228 m_clickNode = nodeToBeRemoved.parentOrShadowHostNode(); | 196 m_clickNode = nodeToBeRemoved.parentOrShadowHostNode(); |
| 229 } else { | 197 } else { |
| 230 // We don't dispatch click events if the mousedown node is removed | 198 // We don't dispatch click events if the mousedown node is removed |
| 231 // before a mouseup event. It is compatible with IE and Firefox. | 199 // before a mouseup event. It is compatible with IE and Firefox. |
| 232 m_clickNode = nullptr; | 200 m_clickNode = nullptr; |
| 233 } | 201 } |
| 234 } | 202 } |
| 235 | 203 |
| 236 static void setSelectionIfNeeded(FrameSelection& selection, const VisibleSelecti
on& newSelection) | |
| 237 { | |
| 238 if (selection.selection() != newSelection) | |
| 239 selection.setSelection(newSelection); | |
| 240 } | |
| 241 | |
| 242 static inline bool dispatchSelectStart(Node* node) | 204 static inline bool dispatchSelectStart(Node* node) |
| 243 { | 205 { |
| 244 if (!node || !node->renderer()) | 206 if (!node || !node->renderer()) |
| 245 return true; | 207 return true; |
| 246 | 208 |
| 247 return node->dispatchEvent(Event::createCancelableBubble(EventTypeNames::sel
ectstart)); | 209 return node->dispatchEvent(Event::createCancelableBubble(EventTypeNames::sel
ectstart)); |
| 248 } | 210 } |
| 249 | 211 |
| 250 static VisibleSelection expandSelectionToRespectUserSelectAll(Node* targetNode,
const VisibleSelection& selection) | 212 static VisibleSelection expandSelectionToRespectUserSelectAll(Node* targetNode,
const VisibleSelection& selection) |
| 251 { | 213 { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 } | 279 } |
| 318 } | 280 } |
| 319 | 281 |
| 320 if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSel
ection.isRange()) | 282 if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSel
ection.isRange()) |
| 321 newSelection.appendTrailingWhitespace(); | 283 newSelection.appendTrailingWhitespace(); |
| 322 | 284 |
| 323 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec
tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | 285 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec
tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); |
| 324 } | 286 } |
| 325 } | 287 } |
| 326 | 288 |
| 327 void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestRe
sults& result) | |
| 328 { | |
| 329 if (m_mouseDownMayStartSelect) { | |
| 330 selectClosestWordFromHitTestResult(result.hitTestResult(), DontAppendTra
ilingWhitespace); | |
| 331 } | |
| 332 } | |
| 333 | |
| 334 void EventHandler::selectClosestMisspellingFromMouseEvent(const MouseEventWithHi
tTestResults& result) | |
| 335 { | |
| 336 if (m_mouseDownMayStartSelect) { | |
| 337 selectClosestMisspellingFromHitTestResult(result.hitTestResult(), DontAp
pendTrailingWhitespace); | |
| 338 } | |
| 339 } | |
| 340 | |
| 341 void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHit
TestResults& result) | |
| 342 { | |
| 343 if (!result.hitTestResult().isLiveLink()) | |
| 344 return selectClosestWordFromMouseEvent(result); | |
| 345 | |
| 346 Node* innerNode = result.targetNode(); | |
| 347 | |
| 348 if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) { | |
| 349 VisibleSelection newSelection; | |
| 350 Element* URLElement = result.hitTestResult().URLElement(); | |
| 351 VisiblePosition pos(innerNode->renderer()->positionForPoint(result.local
Point())); | |
| 352 if (pos.isNotNull() && pos.deepEquivalent().deprecatedNode()->isDescenda
ntOf(URLElement)) | |
| 353 newSelection = VisibleSelection::selectionFromContentsOfNode(URLElem
ent); | |
| 354 | |
| 355 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec
tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | |
| 356 } | |
| 357 } | |
| 358 | |
| 359 bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestR
esults& event) | |
| 360 { | |
| 361 TRACE_EVENT0("blink", "EventHandler::handleMousePressEventDoubleClick"); | |
| 362 | |
| 363 if (event.event().button() != LeftButton) | |
| 364 return false; | |
| 365 | |
| 366 if (m_frame->selection().isRange()) { | |
| 367 // A double-click when range is already selected | |
| 368 // should not change the selection. So, do not call | |
| 369 // selectClosestWordFromMouseEvent, but do set | |
| 370 // m_beganSelectingText to prevent handleMouseReleaseEvent | |
| 371 // from setting caret selection. | |
| 372 m_selectionInitiationState = ExtendedSelection; | |
| 373 } else { | |
| 374 selectClosestWordFromMouseEvent(event); | |
| 375 } | |
| 376 return true; | |
| 377 } | |
| 378 | |
| 379 bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestR
esults& event) | |
| 380 { | |
| 381 TRACE_EVENT0("blink", "EventHandler::handleMousePressEventTripleClick"); | |
| 382 | |
| 383 if (event.event().button() != LeftButton) | |
| 384 return false; | |
| 385 | |
| 386 Node* innerNode = event.targetNode(); | |
| 387 if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect)) | |
| 388 return false; | |
| 389 | |
| 390 VisibleSelection newSelection; | |
| 391 VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint
())); | |
| 392 if (pos.isNotNull()) { | |
| 393 newSelection = VisibleSelection(pos); | |
| 394 newSelection.expandUsingGranularity(ParagraphGranularity); | |
| 395 } | |
| 396 | |
| 397 return updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSe
lectionToRespectUserSelectAll(innerNode, newSelection), ParagraphGranularity); | |
| 398 } | |
| 399 | |
| 400 static int textDistance(const Position& start, const Position& end) | |
| 401 { | |
| 402 RefPtr<Range> range = Range::create(*start.document(), start, end); | |
| 403 return TextIterator::rangeLength(range.get(), true); | |
| 404 } | |
| 405 | |
| 406 bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR
esults& event) | |
| 407 { | |
| 408 TRACE_EVENT0("blink", "EventHandler::handleMousePressEventSingleClick"); | |
| 409 | |
| 410 m_frame->document()->updateLayout(); | |
| 411 Node* innerNode = event.targetNode(); | |
| 412 if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect)) | |
| 413 return false; | |
| 414 | |
| 415 // Extend the selection if the Shift key is down, unless the click is in a l
ink. | |
| 416 bool extendSelection = event.event().shiftKey() && !event.isOverLink(); | |
| 417 | |
| 418 // Don't restart the selection when the mouse is pressed on an | |
| 419 // existing selection so we can allow for text dragging. | |
| 420 LayoutPoint vPoint = event.event().position(); | |
| 421 if (!extendSelection && m_frame->selection().contains(vPoint)) { | |
| 422 m_mouseDownWasSingleClickInSelection = true; | |
| 423 return false; | |
| 424 } | |
| 425 | |
| 426 VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(event.loc
alPoint())); | |
| 427 if (visiblePos.isNull()) | |
| 428 visiblePos = VisiblePosition(firstPositionInOrBeforeNode(innerNode), DOW
NSTREAM); | |
| 429 Position pos = visiblePos.deepEquivalent(); | |
| 430 | |
| 431 VisibleSelection newSelection = m_frame->selection().selection(); | |
| 432 TextGranularity granularity = CharacterGranularity; | |
| 433 | |
| 434 if (extendSelection && newSelection.isCaretOrRange()) { | |
| 435 VisibleSelection selectionInUserSelectAll(expandSelectionToRespectUserSe
lectAll(innerNode, VisibleSelection(VisiblePosition(pos)))); | |
| 436 if (selectionInUserSelectAll.isRange()) { | |
| 437 if (comparePositions(selectionInUserSelectAll.start(), newSelection.
start()) < 0) | |
| 438 pos = selectionInUserSelectAll.start(); | |
| 439 else if (comparePositions(newSelection.end(), selectionInUserSelectA
ll.end()) < 0) | |
| 440 pos = selectionInUserSelectAll.end(); | |
| 441 } | |
| 442 | |
| 443 if (!m_frame->editor().behavior().shouldConsiderSelectionAsDirectional()
) { | |
| 444 if (pos.isNotNull()) { | |
| 445 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click d
eselects when selection | |
| 446 // was created right-to-left | |
| 447 Position start = newSelection.start(); | |
| 448 Position end = newSelection.end(); | |
| 449 int distanceToStart = textDistance(start, pos); | |
| 450 int distanceToEnd = textDistance(pos, end); | |
| 451 if (distanceToStart <= distanceToEnd) | |
| 452 newSelection = VisibleSelection(end, pos); | |
| 453 else | |
| 454 newSelection = VisibleSelection(start, pos); | |
| 455 } | |
| 456 } else | |
| 457 newSelection.setExtent(pos); | |
| 458 | |
| 459 if (m_frame->selection().granularity() != CharacterGranularity) { | |
| 460 granularity = m_frame->selection().granularity(); | |
| 461 newSelection.expandUsingGranularity(m_frame->selection().granularity
()); | |
| 462 } | |
| 463 } else { | |
| 464 newSelection = expandSelectionToRespectUserSelectAll(innerNode, VisibleS
election(visiblePos)); | |
| 465 } | |
| 466 | |
| 467 // Updating the selection is considered side-effect of the event and so it d
oesn't impact the handled state. | |
| 468 updateSelectionForMouseDownDispatchingSelectStart(innerNode, newSelection, g
ranularity); | |
| 469 return false; | |
| 470 } | |
| 471 | |
| 472 static inline bool canMouseDownStartSelect(Node* node) | |
| 473 { | |
| 474 if (!node || !node->renderer()) | |
| 475 return true; | |
| 476 | |
| 477 if (!node->canStartSelection()) | |
| 478 return false; | |
| 479 | |
| 480 return true; | |
| 481 } | |
| 482 | |
| 483 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
nt) | |
| 484 { | |
| 485 TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent"); | |
| 486 | |
| 487 cancelFakeMouseMoveEvent(); | |
| 488 | |
| 489 m_frame->document()->updateLayout(); | |
| 490 | |
| 491 bool singleClick = event.event().clickCount() <= 1; | |
| 492 | |
| 493 // If we got the event back, that must mean it wasn't prevented, | |
| 494 // so it's allowed to start a drag or selection if it wasn't in a scrollbar. | |
| 495 m_mouseDownMayStartSelect = canMouseDownStartSelect(event.targetNode()) && !
event.scrollbar(); | |
| 496 | |
| 497 m_mouseDownMayStartDrag = singleClick; | |
| 498 | |
| 499 m_mouseDownWasSingleClickInSelection = false; | |
| 500 | |
| 501 m_mouseDown = event.event(); | |
| 502 | |
| 503 if (event.isOverWidget() && passWidgetMouseDownEventToWidget(event)) | |
| 504 return true; | |
| 505 | |
| 506 // We don't do this at the start of mouse down handling, | |
| 507 // because we don't want to do it until we know we didn't hit a widget. | |
| 508 if (singleClick) | |
| 509 focusDocumentView(); | |
| 510 | |
| 511 Node* innerNode = event.targetNode(); | |
| 512 | |
| 513 m_mousePressNode = innerNode; | |
| 514 m_dragStartPos = event.event().position(); | |
| 515 | |
| 516 bool swallowEvent = false; | |
| 517 m_mousePressed = true; | |
| 518 m_selectionInitiationState = HaveNotStartedSelection; | |
| 519 | |
| 520 if (event.event().clickCount() == 2) | |
| 521 swallowEvent = handleMousePressEventDoubleClick(event); | |
| 522 else if (event.event().clickCount() >= 3) | |
| 523 swallowEvent = handleMousePressEventTripleClick(event); | |
| 524 else | |
| 525 swallowEvent = handleMousePressEventSingleClick(event); | |
| 526 | |
| 527 m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect | |
| 528 || (m_mousePressNode && m_mousePressNode->renderBox() && m_mousePressNod
e->renderBox()->canBeProgramaticallyScrolled()); | |
| 529 | |
| 530 return swallowEvent; | |
| 531 } | |
| 532 | |
| 533 bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e
vent) | |
| 534 { | |
| 535 TRACE_EVENT0("blink", "EventHandler::handleMouseDraggedEvent"); | |
| 536 | |
| 537 if (!m_mousePressed) | |
| 538 return false; | |
| 539 | |
| 540 Node* targetNode = event.targetNode(); | |
| 541 if (event.event().button() != LeftButton || !targetNode) | |
| 542 return false; | |
| 543 | |
| 544 RenderObject* renderer = targetNode->renderer(); | |
| 545 if (!renderer) { | |
| 546 Node* parent = NodeRenderingTraversal::parent(targetNode); | |
| 547 if (!parent) | |
| 548 return false; | |
| 549 | |
| 550 renderer = parent->renderer(); | |
| 551 if (!renderer) | |
| 552 return false; | |
| 553 } | |
| 554 | |
| 555 m_mouseDownMayStartDrag = false; | |
| 556 | |
| 557 if (m_mouseDownMayStartAutoscroll) { | |
| 558 if (AutoscrollController* controller = autoscrollController()) { | |
| 559 controller->startAutoscrollForSelection(renderer); | |
| 560 m_mouseDownMayStartAutoscroll = false; | |
| 561 } | |
| 562 } | |
| 563 | |
| 564 if (m_selectionInitiationState != ExtendedSelection) { | |
| 565 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active
); | |
| 566 HitTestResult result(m_mouseDownPos); | |
| 567 m_frame->document()->renderView()->hitTest(request, result); | |
| 568 | |
| 569 updateSelectionForMouseDrag(result); | |
| 570 } | |
| 571 updateSelectionForMouseDrag(event.hitTestResult()); | |
| 572 return true; | |
| 573 } | |
| 574 | |
| 575 void EventHandler::updateSelectionForMouseDrag() | 289 void EventHandler::updateSelectionForMouseDrag() |
| 576 { | 290 { |
| 577 FrameView* view = m_frame->view(); | 291 FrameView* view = m_frame->view(); |
| 578 if (!view) | 292 if (!view) |
| 579 return; | 293 return; |
| 580 RenderView* renderer = m_frame->contentRenderer(); | 294 RenderView* renderer = m_frame->contentRenderer(); |
| 581 if (!renderer) | 295 if (!renderer) |
| 582 return; | 296 return; |
| 583 | 297 |
| 584 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | H
itTestRequest::Move); | 298 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | H
itTestRequest::Move); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 newSelection.setExtent(targetPosition); | 350 newSelection.setExtent(targetPosition); |
| 637 } | 351 } |
| 638 | 352 |
| 639 if (m_frame->selection().granularity() != CharacterGranularity) | 353 if (m_frame->selection().granularity() != CharacterGranularity) |
| 640 newSelection.expandUsingGranularity(m_frame->selection().granularity()); | 354 newSelection.expandUsingGranularity(m_frame->selection().granularity()); |
| 641 | 355 |
| 642 m_frame->selection().setNonDirectionalSelectionIfNeeded(newSelection, m_fram
e->selection().granularity(), | 356 m_frame->selection().setNonDirectionalSelectionIfNeeded(newSelection, m_fram
e->selection().granularity(), |
| 643 FrameSelection::AdjustEndpointsAtBidiBoundary); | 357 FrameSelection::AdjustEndpointsAtBidiBoundary); |
| 644 } | 358 } |
| 645 | 359 |
| 646 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e
vent) | |
| 647 { | |
| 648 AutoscrollController* controller = autoscrollController(); | |
| 649 if (controller && controller->autoscrollInProgress()) | |
| 650 stopAutoscroll(); | |
| 651 | |
| 652 // Used to prevent mouseMoveEvent from initiating a drag before | |
| 653 // the mouse is pressed again. | |
| 654 m_mousePressed = false; | |
| 655 m_capturesDragging = false; | |
| 656 m_mouseDownMayStartDrag = false; | |
| 657 m_mouseDownMayStartSelect = false; | |
| 658 m_mouseDownMayStartAutoscroll = false; | |
| 659 | |
| 660 bool handled = false; | |
| 661 | |
| 662 // Clear the selection if the mouse didn't move after the last mouse | |
| 663 // press and it's not a context menu click. We do this so when clicking | |
| 664 // on the selection, the selection goes away. However, if we are | |
| 665 // editing, place the caret. | |
| 666 if (m_mouseDownWasSingleClickInSelection && m_selectionInitiationState != Ex
tendedSelection | |
| 667 && m_dragStartPos == event.event().position() | |
| 668 && m_frame->selection().isRange() | |
| 669 && event.event().button() != RightButton) { | |
| 670 VisibleSelection newSelection; | |
| 671 Node* node = event.targetNode(); | |
| 672 if (node && node->renderer() && node->hasEditableStyle()) { | |
| 673 VisiblePosition pos = VisiblePosition(node->renderer()->positionForP
oint(event.localPoint())); | |
| 674 newSelection = VisibleSelection(pos); | |
| 675 } | |
| 676 | |
| 677 setSelectionIfNeeded(m_frame->selection(), newSelection); | |
| 678 | |
| 679 handled = true; | |
| 680 } | |
| 681 | |
| 682 m_frame->selection().notifyRendererOfSelectionChange(UserTriggered); | |
| 683 | |
| 684 m_frame->selection().selectFrameElementInParentIfFullySelected(); | |
| 685 | |
| 686 if (event.event().button() == MiddleButton && !event.isOverLink()) { | |
| 687 // Ignore handled, since we want to paste to where the caret was placed
anyway. | |
| 688 handled = handlePasteGlobalSelection(event.event()) || handled; | |
| 689 } | |
| 690 | |
| 691 return handled; | |
| 692 } | |
| 693 | |
| 694 AutoscrollController* EventHandler::autoscrollController() const | 360 AutoscrollController* EventHandler::autoscrollController() const |
| 695 { | 361 { |
| 696 if (Page* page = m_frame->page()) | 362 if (Page* page = m_frame->page()) |
| 697 return &page->autoscrollController(); | 363 return &page->autoscrollController(); |
| 698 return 0; | 364 return 0; |
| 699 } | 365 } |
| 700 | 366 |
| 701 HitTestResult EventHandler::hitTestResultAtPoint(const LayoutPoint& point, HitTe
stRequest::HitTestRequestType hitType, const LayoutSize& padding) | 367 HitTestResult EventHandler::hitTestResultAtPoint(const LayoutPoint& point, HitTe
stRequest::HitTestRequestType hitType, const LayoutSize& padding) |
| 702 { | 368 { |
| 703 TRACE_EVENT0("blink", "EventHandler::hitTestResultAtPoint"); | 369 TRACE_EVENT0("blink", "EventHandler::hitTestResultAtPoint"); |
| 704 | 370 |
| 705 HitTestResult result(point, padding.height(), padding.width(), padding.heigh
t(), padding.width()); | 371 HitTestResult result(point, padding.height(), padding.width(), padding.heigh
t(), padding.width()); |
| 706 | 372 |
| 707 // RenderView::hitTest causes a layout, and we don't want to hit that until
the first | 373 // RenderView::hitTest causes a layout, and we don't want to hit that until
the first |
| 708 // layout because until then, there is nothing shown on the screen - the use
r can't | 374 // layout because until then, there is nothing shown on the screen - the use
r can't |
| 709 // have intentionally clicked on something belonging to this page. Furthermo
re, | 375 // have intentionally clicked on something belonging to this page. Furthermo
re, |
| 710 // mousemove events before the first layout should not lead to a premature l
ayout() | 376 // mousemove events before the first layout should not lead to a premature l
ayout() |
| 711 // happening, which could show a flash of white. | 377 // happening, which could show a flash of white. |
| 712 // See also the similar code in Document::prepareMouseEvent. | 378 // See also the similar code in Document::prepareMouseEvent. |
| 713 if (!m_frame->contentRenderer() || !m_frame->view() || !m_frame->view()->did
FirstLayout()) | 379 if (!m_frame->contentRenderer() || !m_frame->view() || !m_frame->view()->did
FirstLayout()) |
| 714 return result; | 380 return result; |
| 715 | 381 |
| 716 // hitTestResultAtPoint is specifically used to hitTest into all frames, thu
s it always allows child frame content. | 382 // hitTestResultAtPoint is specifically used to hitTest into all frames, thu
s it always allows child frame content. |
| 717 HitTestRequest request(hitType); | 383 HitTestRequest request(hitType); |
| 718 m_frame->contentRenderer()->hitTest(request, result); | 384 m_frame->contentRenderer()->hitTest(request, result); |
| 719 if (!request.readOnly()) | |
| 720 m_frame->document()->updateHoverActiveState(request, result.innerElement
()); | |
| 721 | 385 |
| 722 return result; | 386 return result; |
| 723 } | 387 } |
| 724 | 388 |
| 725 void EventHandler::stopAutoscroll() | 389 void EventHandler::stopAutoscroll() |
| 726 { | 390 { |
| 727 if (AutoscrollController* controller = autoscrollController()) | 391 if (AutoscrollController* controller = autoscrollController()) |
| 728 controller->stopAutoscroll(); | 392 controller->stopAutoscroll(); |
| 729 } | 393 } |
| 730 | 394 |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 963 { | 627 { |
| 964 bool editable = (node && node->hasEditableStyle()); | 628 bool editable = (node && node->hasEditableStyle()); |
| 965 | 629 |
| 966 if (useHandCursor(node, result.isOverLink())) | 630 if (useHandCursor(node, result.isOverLink())) |
| 967 return handCursor(); | 631 return handCursor(); |
| 968 | 632 |
| 969 // During selection, use an I-beam no matter what we're over. | 633 // During selection, use an I-beam no matter what we're over. |
| 970 // If a drag may be starting or we're capturing mouse events for a particula
r node, don't treat this as a selection. | 634 // If a drag may be starting or we're capturing mouse events for a particula
r node, don't treat this as a selection. |
| 971 if (m_mousePressed && m_mouseDownMayStartSelect | 635 if (m_mousePressed && m_mouseDownMayStartSelect |
| 972 && !m_mouseDownMayStartDrag | 636 && !m_mouseDownMayStartDrag |
| 973 && m_frame->selection().isCaretOrRange() | 637 && m_frame->selection().isCaretOrRange()) { |
| 974 && !m_capturingMouseEventsNode) { | |
| 975 return iBeam; | 638 return iBeam; |
| 976 } | 639 } |
| 977 | 640 |
| 978 RenderObject* renderer = node ? node->renderer() : 0; | 641 RenderObject* renderer = node ? node->renderer() : 0; |
| 979 if ((editable || (renderer && renderer->isText() && node->canStartSelection(
))) && !result.scrollbar()) | 642 if ((editable || (renderer && renderer->isText() && node->canStartSelection(
))) && !result.scrollbar()) |
| 980 return iBeam; | 643 return iBeam; |
| 981 return pointerCursor(); | 644 return pointerCursor(); |
| 982 } | 645 } |
| 983 | 646 |
| 984 static LayoutPoint documentPointForWindowPoint(LocalFrame* frame, const IntPoint
& windowPoint) | |
| 985 { | |
| 986 // FIXME(sky): remove | |
| 987 return windowPoint; | |
| 988 } | |
| 989 | |
| 990 bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) | |
| 991 { | |
| 992 TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent"); | |
| 993 | |
| 994 RefPtr<FrameView> protector(m_frame->view()); | |
| 995 | |
| 996 cancelFakeMouseMoveEvent(); | |
| 997 if (m_eventHandlerWillResetCapturingMouseEventsNode) | |
| 998 m_capturingMouseEventsNode = nullptr; | |
| 999 m_mousePressed = true; | |
| 1000 m_capturesDragging = true; | |
| 1001 setLastKnownMousePosition(mouseEvent); | |
| 1002 m_mouseDownTimestamp = mouseEvent.timestamp(); | |
| 1003 m_mouseDownMayStartDrag = false; | |
| 1004 m_mouseDownMayStartSelect = false; | |
| 1005 m_mouseDownMayStartAutoscroll = false; | |
| 1006 if (m_frame->view()) | |
| 1007 m_mouseDownPos = mouseEvent.position(); | |
| 1008 else { | |
| 1009 // FIXME(sky): Why do we have this else block at all? | |
| 1010 invalidateClick(); | |
| 1011 return false; | |
| 1012 } | |
| 1013 | |
| 1014 // Mouse events simulated from touch should not hit-test again. | |
| 1015 ASSERT(!mouseEvent.fromTouch()); | |
| 1016 | |
| 1017 HitTestRequest request(HitTestRequest::Active); | |
| 1018 // Save the document point we generate in case the window coordinate is inva
lidated by what happens | |
| 1019 // when we dispatch the event. | |
| 1020 LayoutPoint documentPoint = documentPointForWindowPoint(m_frame, mouseEvent.
position()); | |
| 1021 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(re
quest, documentPoint, mouseEvent); | |
| 1022 | |
| 1023 if (!mev.targetNode()) { | |
| 1024 invalidateClick(); | |
| 1025 return false; | |
| 1026 } | |
| 1027 | |
| 1028 m_mousePressNode = mev.targetNode(); | |
| 1029 | |
| 1030 m_clickCount = mouseEvent.clickCount(); | |
| 1031 m_clickNode = mev.targetNode()->isTextNode() ? NodeRenderingTraversal::pare
nt(mev.targetNode()) : mev.targetNode(); | |
| 1032 | |
| 1033 m_frame->selection().setCaretBlinkingSuspended(true); | |
| 1034 | |
| 1035 bool swallowEvent = !dispatchMouseEvent(EventTypeNames::mousedown, mev.targe
tNode(), m_clickCount, mouseEvent, true); | |
| 1036 swallowEvent = swallowEvent || handleMouseFocus(mouseEvent); | |
| 1037 m_capturesDragging = !swallowEvent || mev.scrollbar(); | |
| 1038 | |
| 1039 // If the hit testing originally determined the event was in a scrollbar, re
fetch the MouseEventWithHitTestResults | |
| 1040 // in case the scrollbar widget was destroyed when the mouse event was handl
ed. | |
| 1041 if (mev.scrollbar()) { | |
| 1042 const bool wasLastScrollBar = mev.scrollbar() == m_lastScrollbarUnderMou
se.get(); | |
| 1043 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active
); | |
| 1044 mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mou
seEvent); | |
| 1045 if (wasLastScrollBar && mev.scrollbar() != m_lastScrollbarUnderMouse.get
()) | |
| 1046 m_lastScrollbarUnderMouse = nullptr; | |
| 1047 } | |
| 1048 | |
| 1049 if (swallowEvent) { | |
| 1050 // scrollbars should get events anyway, even disabled controls might be
scrollable | |
| 1051 passMousePressEventToScrollbar(mev); | |
| 1052 } else { | |
| 1053 if (passMousePressEventToScrollbar(mev)) | |
| 1054 swallowEvent = true; | |
| 1055 else | |
| 1056 swallowEvent = handleMousePressEvent(mev); | |
| 1057 } | |
| 1058 | |
| 1059 return swallowEvent; | |
| 1060 } | |
| 1061 | |
| 1062 static RenderLayer* layerForNode(Node* node) | |
| 1063 { | |
| 1064 if (!node) | |
| 1065 return 0; | |
| 1066 | |
| 1067 RenderObject* renderer = node->renderer(); | |
| 1068 if (!renderer) | |
| 1069 return 0; | |
| 1070 | |
| 1071 RenderLayer* layer = renderer->enclosingLayer(); | |
| 1072 if (!layer) | |
| 1073 return 0; | |
| 1074 | |
| 1075 return layer; | |
| 1076 } | |
| 1077 | |
| 1078 ScrollableArea* EventHandler::associatedScrollableArea(const RenderLayer* layer)
const | 647 ScrollableArea* EventHandler::associatedScrollableArea(const RenderLayer* layer)
const |
| 1079 { | 648 { |
| 1080 if (RenderLayerScrollableArea* scrollableArea = layer->scrollableArea()) { | 649 if (RenderLayerScrollableArea* scrollableArea = layer->scrollableArea()) { |
| 1081 if (scrollableArea->scrollsOverflow()) | 650 if (scrollableArea->scrollsOverflow()) |
| 1082 return scrollableArea; | 651 return scrollableArea; |
| 1083 } | 652 } |
| 1084 | 653 |
| 1085 return 0; | 654 return 0; |
| 1086 } | 655 } |
| 1087 | 656 |
| 1088 bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& event) | |
| 1089 { | |
| 1090 TRACE_EVENT0("blink", "EventHandler::handleMouseMoveEvent"); | |
| 1091 | |
| 1092 RefPtr<FrameView> protector(m_frame->view()); | |
| 1093 MaximumDurationTracker maxDurationTracker(&m_maxMouseMovedDuration); | |
| 1094 | |
| 1095 HitTestResult hoveredNode = HitTestResult(LayoutPoint()); | |
| 1096 bool result = handleMouseMoveOrLeaveEvent(event, &hoveredNode); | |
| 1097 | |
| 1098 Page* page = m_frame->page(); | |
| 1099 if (!page) | |
| 1100 return result; | |
| 1101 | |
| 1102 if (RenderLayer* layer = layerForNode(hoveredNode.innerNode())) { | |
| 1103 if (ScrollableArea* layerScrollableArea = associatedScrollableArea(layer
)) | |
| 1104 layerScrollableArea->mouseMovedInContentArea(); | |
| 1105 } | |
| 1106 | |
| 1107 page->chrome().mouseDidMoveOverElement(hoveredNode, event.modifierFlags()); | |
| 1108 | |
| 1109 return result; | |
| 1110 } | |
| 1111 | |
| 1112 void EventHandler::handleMouseLeaveEvent(const PlatformMouseEvent& event) | |
| 1113 { | |
| 1114 TRACE_EVENT0("blink", "EventHandler::handleMouseLeaveEvent"); | |
| 1115 | |
| 1116 RefPtr<FrameView> protector(m_frame->view()); | |
| 1117 handleMouseMoveOrLeaveEvent(event); | |
| 1118 } | |
| 1119 | |
| 1120 bool EventHandler::handleMouseMoveOrLeaveEvent(const PlatformMouseEvent& mouseEv
ent, HitTestResult* hoveredNode, bool onlyUpdateScrollbars) | |
| 1121 { | |
| 1122 ASSERT(m_frame); | |
| 1123 ASSERT(m_frame->view()); | |
| 1124 | |
| 1125 setLastKnownMousePosition(mouseEvent); | |
| 1126 | |
| 1127 if (m_hoverTimer.isActive()) | |
| 1128 m_hoverTimer.stop(); | |
| 1129 | |
| 1130 m_cursorUpdateTimer.stop(); | |
| 1131 | |
| 1132 cancelFakeMouseMoveEvent(); | |
| 1133 | |
| 1134 // Send events right to a scrollbar if the mouse is pressed. | |
| 1135 if (m_lastScrollbarUnderMouse && m_mousePressed) { | |
| 1136 m_lastScrollbarUnderMouse->mouseMoved(mouseEvent); | |
| 1137 return true; | |
| 1138 } | |
| 1139 | |
| 1140 // Mouse events simulated from touch should not hit-test again. | |
| 1141 ASSERT(!mouseEvent.fromTouch()); | |
| 1142 | |
| 1143 HitTestRequest::HitTestRequestType hitType = HitTestRequest::Move; | |
| 1144 if (m_mousePressed) | |
| 1145 hitType |= HitTestRequest::Active; | |
| 1146 else if (onlyUpdateScrollbars) { | |
| 1147 // Mouse events should be treated as "read-only" if we're updating only
scrollbars. This | |
| 1148 // means that :hover and :active freeze in the state they were in, rathe
r than updating | |
| 1149 // for nodes the mouse moves while the window is not key (which will be
the case if | |
| 1150 // onlyUpdateScrollbars is true). | |
| 1151 hitType |= HitTestRequest::ReadOnly; | |
| 1152 } | |
| 1153 | |
| 1154 // Treat any mouse move events as readonly if the user is currently touching
the screen. | |
| 1155 if (m_touchPressed) | |
| 1156 hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly; | |
| 1157 HitTestRequest request(hitType); | |
| 1158 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent); | |
| 1159 if (hoveredNode) | |
| 1160 *hoveredNode = mev.hitTestResult(); | |
| 1161 | |
| 1162 Scrollbar* scrollbar = mev.scrollbar(); | |
| 1163 updateLastScrollbarUnderMouse(scrollbar, !m_mousePressed); | |
| 1164 if (onlyUpdateScrollbars) | |
| 1165 return true; | |
| 1166 | |
| 1167 bool swallowEvent = false; | |
| 1168 | |
| 1169 if (scrollbar && !m_mousePressed) | |
| 1170 scrollbar->mouseMoved(mouseEvent); // Handle hover effects on platforms
that support visual feedback on scrollbar hovering. | |
| 1171 if (FrameView* view = m_frame->view()) { | |
| 1172 OptionalCursor optionalCursor = selectCursor(mev.hitTestResult()); | |
| 1173 if (optionalCursor.isCursorChange()) { | |
| 1174 m_currentMouseCursor = optionalCursor.cursor(); | |
| 1175 view->setCursor(m_currentMouseCursor); | |
| 1176 } | |
| 1177 } | |
| 1178 | |
| 1179 if (swallowEvent) | |
| 1180 return true; | |
| 1181 | |
| 1182 swallowEvent = !dispatchMouseEvent(EventTypeNames::mousemove, mev.targetNode
(), 0, mouseEvent, true); | |
| 1183 if (!swallowEvent) | |
| 1184 swallowEvent = handleMouseDraggedEvent(mev); | |
| 1185 | |
| 1186 return swallowEvent; | |
| 1187 } | |
| 1188 | |
| 1189 void EventHandler::invalidateClick() | 657 void EventHandler::invalidateClick() |
| 1190 { | 658 { |
| 1191 m_clickCount = 0; | 659 m_clickCount = 0; |
| 1192 m_clickNode = nullptr; | 660 m_clickNode = nullptr; |
| 1193 } | 661 } |
| 1194 | 662 |
| 1195 bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) | |
| 1196 { | |
| 1197 TRACE_EVENT0("blink", "EventHandler::handleMouseReleaseEvent"); | |
| 1198 | |
| 1199 RefPtr<FrameView> protector(m_frame->view()); | |
| 1200 | |
| 1201 m_frame->selection().setCaretBlinkingSuspended(false); | |
| 1202 | |
| 1203 m_mousePressed = false; | |
| 1204 setLastKnownMousePosition(mouseEvent); | |
| 1205 | |
| 1206 if (m_lastScrollbarUnderMouse) { | |
| 1207 invalidateClick(); | |
| 1208 m_lastScrollbarUnderMouse->mouseUp(mouseEvent); | |
| 1209 bool setUnder = false; | |
| 1210 return !dispatchMouseEvent(EventTypeNames::mouseup, m_lastNodeUnderMouse
.get(), m_clickCount, mouseEvent, setUnder); | |
| 1211 } | |
| 1212 | |
| 1213 // Mouse events simulated from touch should not hit-test again. | |
| 1214 ASSERT(!mouseEvent.fromTouch()); | |
| 1215 | |
| 1216 HitTestRequest::HitTestRequestType hitType = HitTestRequest::Release; | |
| 1217 HitTestRequest request(hitType); | |
| 1218 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent); | |
| 1219 if (m_eventHandlerWillResetCapturingMouseEventsNode) | |
| 1220 m_capturingMouseEventsNode = nullptr; | |
| 1221 | |
| 1222 bool swallowMouseUpEvent = !dispatchMouseEvent(EventTypeNames::mouseup, mev.
targetNode(), m_clickCount, mouseEvent, false); | |
| 1223 | |
| 1224 bool swallowClickEvent = false; | |
| 1225 if (m_clickCount > 0 && mev.targetNode() && m_clickNode) { | |
| 1226 if (Node* clickTargetNode = NodeRenderingTraversal::commonAncestor(*mev.
targetNode(), *m_clickNode)) | |
| 1227 swallowClickEvent = !dispatchMouseEvent(EventTypeNames::click, click
TargetNode, m_clickCount, mouseEvent, true); | |
| 1228 } | |
| 1229 | |
| 1230 bool swallowMouseReleaseEvent = false; | |
| 1231 if (!swallowMouseUpEvent) | |
| 1232 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev); | |
| 1233 | |
| 1234 invalidateClick(); | |
| 1235 | |
| 1236 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; | |
| 1237 } | |
| 1238 | |
| 1239 bool EventHandler::handlePasteGlobalSelection(const PlatformMouseEvent& mouseEve
nt) | |
| 1240 { | |
| 1241 // If the event was a middle click, attempt to copy global selection in afte
r | |
| 1242 // the newly set caret position. | |
| 1243 // | |
| 1244 // This code is called from either the mouse up or mouse down handling. Ther
e | |
| 1245 // is some debate about when the global selection is pasted: | |
| 1246 // xterm: pastes on up. | |
| 1247 // GTK: pastes on down. | |
| 1248 // Qt: pastes on up. | |
| 1249 // Firefox: pastes on up. | |
| 1250 // Chromium: pastes on up. | |
| 1251 // | |
| 1252 // There is something of a webcompat angle to this well, as highlighted by | |
| 1253 // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on | |
| 1254 // down then the text is pasted just before the onclick handler runs and | |
| 1255 // clears the text box. So it's important this happens after the event | |
| 1256 // handlers have been fired. | |
| 1257 if (mouseEvent.type() != PlatformEvent::MouseReleased) | |
| 1258 return false; | |
| 1259 | |
| 1260 if (!m_frame->page()) | |
| 1261 return false; | |
| 1262 LocalFrame* focusFrame = m_frame->page()->focusController().focusedOrMainFra
me(); | |
| 1263 // Do not paste here if the focus was moved somewhere else. | |
| 1264 if (m_frame == focusFrame && m_frame->editor().behavior().supportsGlobalSele
ction()) | |
| 1265 return m_frame->editor().command("PasteGlobalSelection").execute(); | |
| 1266 | |
| 1267 return false; | |
| 1268 } | |
| 1269 | |
| 1270 void EventHandler::setCapturingMouseEventsNode(PassRefPtr<Node> n) | |
| 1271 { | |
| 1272 m_capturingMouseEventsNode = n; | |
| 1273 m_eventHandlerWillResetCapturingMouseEventsNode = false; | |
| 1274 } | |
| 1275 | |
| 1276 MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestReques
t& request, const PlatformMouseEvent& mev) | |
| 1277 { | |
| 1278 ASSERT(m_frame); | |
| 1279 ASSERT(m_frame->document()); | |
| 1280 | |
| 1281 return m_frame->document()->prepareMouseEvent(request, documentPointForWindo
wPoint(m_frame, mev.position()), mev); | |
| 1282 } | |
| 1283 | |
| 1284 void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo
useEvent& mouseEvent, bool fireMouseOverOut) | |
| 1285 { | |
| 1286 Node* result = targetNode; | |
| 1287 | |
| 1288 // If we're capturing, we always go right to that node. | |
| 1289 if (m_capturingMouseEventsNode) | |
| 1290 result = m_capturingMouseEventsNode.get(); | |
| 1291 else { | |
| 1292 // If the target node is a text node, dispatch on the parent node - rdar
://4196646 | |
| 1293 if (result && result->isTextNode()) | |
| 1294 result = NodeRenderingTraversal::parent(result); | |
| 1295 } | |
| 1296 m_nodeUnderMouse = result; | |
| 1297 | |
| 1298 // Fire mouseout/mouseover if the mouse has shifted to a different node. | |
| 1299 if (fireMouseOverOut) { | |
| 1300 RenderLayer* layerForLastNode = layerForNode(m_lastNodeUnderMouse.get())
; | |
| 1301 RenderLayer* layerForNodeUnderMouse = layerForNode(m_nodeUnderMouse.get(
)); | |
| 1302 Page* page = m_frame->page(); | |
| 1303 | |
| 1304 if (page && (layerForLastNode && (!layerForNodeUnderMouse || layerForNod
eUnderMouse != layerForLastNode))) { | |
| 1305 // The mouse has moved between layers. | |
| 1306 if (ScrollableArea* scrollableAreaForLastNode = associatedScrollable
Area(layerForLastNode)) | |
| 1307 scrollableAreaForLastNode->mouseExitedContentArea(); | |
| 1308 } | |
| 1309 | |
| 1310 if (page && (layerForNodeUnderMouse && (!layerForLastNode || layerForNod
eUnderMouse != layerForLastNode))) { | |
| 1311 // The mouse has moved between layers. | |
| 1312 if (ScrollableArea* scrollableAreaForNodeUnderMouse = associatedScro
llableArea(layerForNodeUnderMouse)) | |
| 1313 scrollableAreaForNodeUnderMouse->mouseEnteredContentArea(); | |
| 1314 } | |
| 1315 | |
| 1316 if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame-
>document()) { | |
| 1317 m_lastNodeUnderMouse = nullptr; | |
| 1318 m_lastScrollbarUnderMouse = nullptr; | |
| 1319 } | |
| 1320 | |
| 1321 if (m_lastNodeUnderMouse != m_nodeUnderMouse) { | |
| 1322 // send mouseout event to the old node | |
| 1323 if (m_lastNodeUnderMouse) | |
| 1324 m_lastNodeUnderMouse->dispatchMouseEvent(mouseEvent, EventTypeNa
mes::mouseout, 0, m_nodeUnderMouse.get()); | |
| 1325 // send mouseover event to the new node | |
| 1326 if (m_nodeUnderMouse) | |
| 1327 m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, EventTypeNames:
:mouseover, 0, m_lastNodeUnderMouse.get()); | |
| 1328 } | |
| 1329 m_lastNodeUnderMouse = m_nodeUnderMouse; | |
| 1330 } | |
| 1331 } | |
| 1332 | |
| 1333 // The return value means 'continue default handling.' | |
| 1334 bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe
tNode, int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder) | |
| 1335 { | |
| 1336 updateMouseEventTargetNode(targetNode, mouseEvent, setUnder); | |
| 1337 return !m_nodeUnderMouse || m_nodeUnderMouse->dispatchMouseEvent(mouseEvent,
eventType, clickCount); | |
| 1338 } | |
| 1339 | |
| 1340 // The return value means 'swallow event' (was handled), as for other handle* fu
nctions. | |
| 1341 bool EventHandler::handleMouseFocus(const PlatformMouseEvent& mouseEvent) | |
| 1342 { | |
| 1343 // The layout needs to be up to date to determine if an element is focusable
. | |
| 1344 m_frame->document()->updateLayout(); | |
| 1345 | |
| 1346 Element* element = 0; | |
| 1347 if (m_nodeUnderMouse) | |
| 1348 element = m_nodeUnderMouse->isElementNode() ? toElement(m_nodeUnderMouse
) : m_nodeUnderMouse->parentOrShadowHostElement(); | |
| 1349 for (; element; element = element->parentOrShadowHostElement()) { | |
| 1350 if (element->isFocusable() && element->focused()) | |
| 1351 return false; | |
| 1352 if (element->isMouseFocusable()) | |
| 1353 break; | |
| 1354 } | |
| 1355 ASSERT(!element || element->isMouseFocusable()); | |
| 1356 | |
| 1357 // To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus | |
| 1358 // a node on mouse down if it's selected and inside a focused node. It will | |
| 1359 // be focused if the user does a mouseup over it, however, because the | |
| 1360 // mouseup will set a selection inside it, which will call | |
| 1361 // FrameSelection::setFocusedNodeIfNeeded. | |
| 1362 if (element | |
| 1363 && m_frame->selection().isRange() | |
| 1364 && m_frame->selection().toNormalizedRange()->compareNode(element, IGNORE
_EXCEPTION) == Range::NODE_INSIDE | |
| 1365 && element->isDescendantOf(m_frame->document()->focusedElement())) | |
| 1366 return false; | |
| 1367 | |
| 1368 // Only change the focus when clicking scrollbars if it can transfered to a | |
| 1369 // mouse focusable node. | |
| 1370 if (!element && isInsideScrollbar(mouseEvent.position())) | |
| 1371 return true; | |
| 1372 | |
| 1373 if (Page* page = m_frame->page()) { | |
| 1374 // If focus shift is blocked, we eat the event. Note we should never | |
| 1375 // clear swallowEvent if the page already set it (e.g., by canceling | |
| 1376 // default behavior). | |
| 1377 if (element) { | |
| 1378 if (!page->focusController().setFocusedElement(element, m_frame, Foc
usTypeMouse)) | |
| 1379 return true; | |
| 1380 } else { | |
| 1381 // We call setFocusedElement even with !element in order to blur | |
| 1382 // current focus element when a link is clicked; this is expected by | |
| 1383 // some sites that rely on onChange handlers running from form | |
| 1384 // fields before the button click is processed. | |
| 1385 if (!page->focusController().setFocusedElement(0, m_frame)) | |
| 1386 return true; | |
| 1387 } | |
| 1388 } | |
| 1389 | |
| 1390 return false; | |
| 1391 } | |
| 1392 | |
| 1393 bool EventHandler::isInsideScrollbar(const IntPoint& windowPoint) const | 663 bool EventHandler::isInsideScrollbar(const IntPoint& windowPoint) const |
| 1394 { | 664 { |
| 1395 if (RenderView* renderView = m_frame->contentRenderer()) { | 665 if (RenderView* renderView = m_frame->contentRenderer()) { |
| 1396 HitTestRequest request(HitTestRequest::ReadOnly); | 666 HitTestRequest request(HitTestRequest::ReadOnly); |
| 1397 HitTestResult result(windowPoint); | 667 HitTestResult result(windowPoint); |
| 1398 renderView->hitTest(request, result); | 668 renderView->hitTest(request, result); |
| 1399 return result.scrollbar(); | 669 return result.scrollbar(); |
| 1400 } | 670 } |
| 1401 | 671 |
| 1402 return false; | 672 return false; |
| 1403 } | 673 } |
| 1404 | 674 |
| 1405 bool EventHandler::handleWheelEvent(const PlatformWheelEvent& event) | |
| 1406 { | |
| 1407 Document* doc = m_frame->document(); | |
| 1408 | |
| 1409 if (!doc->renderView()) | |
| 1410 return false; | |
| 1411 | |
| 1412 RefPtr<FrameView> protector(m_frame->view()); | |
| 1413 | |
| 1414 FrameView* view = m_frame->view(); | |
| 1415 if (!view) | |
| 1416 return false; | |
| 1417 | |
| 1418 LayoutPoint vPoint = event.position(); | |
| 1419 | |
| 1420 HitTestRequest request(HitTestRequest::ReadOnly); | |
| 1421 HitTestResult result(vPoint); | |
| 1422 doc->renderView()->hitTest(request, result); | |
| 1423 | |
| 1424 Node* node = result.innerNode(); | |
| 1425 // Wheel events should not dispatch to text nodes. | |
| 1426 if (node && node->isTextNode()) | |
| 1427 node = NodeRenderingTraversal::parent(node); | |
| 1428 | |
| 1429 bool isOverWidget; | |
| 1430 if (event.useLatchedEventNode()) { | |
| 1431 if (!m_latchedWheelEventNode) { | |
| 1432 m_latchedWheelEventNode = node; | |
| 1433 m_widgetIsLatched = result.isOverWidget(); | |
| 1434 } else | |
| 1435 node = m_latchedWheelEventNode.get(); | |
| 1436 | |
| 1437 isOverWidget = m_widgetIsLatched; | |
| 1438 } else { | |
| 1439 if (m_latchedWheelEventNode) | |
| 1440 m_latchedWheelEventNode = nullptr; | |
| 1441 if (m_previousWheelScrolledNode) | |
| 1442 m_previousWheelScrolledNode = nullptr; | |
| 1443 | |
| 1444 isOverWidget = result.isOverWidget(); | |
| 1445 } | |
| 1446 | |
| 1447 if (node) { | |
| 1448 if (node && !node->dispatchWheelEvent(event)) | |
| 1449 return true; | |
| 1450 } | |
| 1451 | |
| 1452 // We do another check on the frame view because the event handler can run J
S which results in the frame getting destroyed. | |
| 1453 view = m_frame->view(); | |
| 1454 if (!view || !view->wheelEvent(event)) | |
| 1455 return false; | |
| 1456 | |
| 1457 return true; | |
| 1458 } | |
| 1459 | |
| 1460 void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEv
ent) | |
| 1461 { | |
| 1462 if (!startNode || !wheelEvent) | |
| 1463 return; | |
| 1464 | |
| 1465 // Ctrl + scrollwheel is reserved for triggering zoom in/out actions in Chro
mium. | |
| 1466 if (wheelEvent->ctrlKey()) | |
| 1467 return; | |
| 1468 | |
| 1469 Node* stopNode = m_previousWheelScrolledNode.get(); | |
| 1470 ScrollGranularity granularity = wheelGranularityToScrollGranularity(wheelEve
nt->deltaMode()); | |
| 1471 | |
| 1472 // Break up into two scrolls if we need to. Diagonal movement on | |
| 1473 // a MacBook pro is an example of a 2-dimensional mouse wheel event (where b
oth deltaX and deltaY can be set). | |
| 1474 if (scroll(ScrollRight, granularity, startNode, &stopNode, wheelEvent->delta
X(), roundedIntPoint(wheelEvent->absoluteLocation()))) | |
| 1475 wheelEvent->setDefaultHandled(); | |
| 1476 | |
| 1477 if (scroll(ScrollDown, granularity, startNode, &stopNode, wheelEvent->deltaY
(), roundedIntPoint(wheelEvent->absoluteLocation()))) | |
| 1478 wheelEvent->setDefaultHandled(); | |
| 1479 | |
| 1480 if (!m_latchedWheelEventNode) | |
| 1481 m_previousWheelScrolledNode = stopNode; | |
| 1482 } | |
| 1483 | |
| 1484 bool EventHandler::handleGestureShowPress() | 675 bool EventHandler::handleGestureShowPress() |
| 1485 { | 676 { |
| 1486 m_lastShowPressTimestamp = WTF::currentTime(); | 677 m_lastShowPressTimestamp = WTF::currentTime(); |
| 1487 | 678 |
| 1488 FrameView* view = m_frame->view(); | 679 FrameView* view = m_frame->view(); |
| 1489 if (!view) | 680 if (!view) |
| 1490 return false; | 681 return false; |
| 1491 const FrameView::ScrollableAreaSet* areas = view->scrollableAreas(); | 682 const FrameView::ScrollableAreaSet* areas = view->scrollableAreas(); |
| 1492 if (!areas) | 683 if (!areas) |
| 1493 return false; | 684 return false; |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1625 case PlatformEvent::GesturePinchUpdate: | 816 case PlatformEvent::GesturePinchUpdate: |
| 1626 return false; | 817 return false; |
| 1627 default: | 818 default: |
| 1628 ASSERT_NOT_REACHED(); | 819 ASSERT_NOT_REACHED(); |
| 1629 return false; | 820 return false; |
| 1630 } | 821 } |
| 1631 } | 822 } |
| 1632 | 823 |
| 1633 bool EventHandler::handleGestureTap(const GestureEventWithHitTestResults& target
edEvent) | 824 bool EventHandler::handleGestureTap(const GestureEventWithHitTestResults& target
edEvent) |
| 1634 { | 825 { |
| 1635 RefPtr<FrameView> protector(m_frame->view()); | 826 return false; |
| 1636 const PlatformGestureEvent& gestureEvent = targetedEvent.event(); | |
| 1637 | |
| 1638 unsigned modifierFlags = 0; | |
| 1639 if (gestureEvent.altKey()) | |
| 1640 modifierFlags |= PlatformEvent::AltKey; | |
| 1641 if (gestureEvent.ctrlKey()) | |
| 1642 modifierFlags |= PlatformEvent::CtrlKey; | |
| 1643 if (gestureEvent.metaKey()) | |
| 1644 modifierFlags |= PlatformEvent::MetaKey; | |
| 1645 if (gestureEvent.shiftKey()) | |
| 1646 modifierFlags |= PlatformEvent::ShiftKey; | |
| 1647 PlatformEvent::Modifiers modifiers = static_cast<PlatformEvent::Modifiers>(m
odifierFlags); | |
| 1648 | |
| 1649 HitTestResult currentHitTest = targetedEvent.hitTestResult(); | |
| 1650 | |
| 1651 // We use the adjusted position so the application isn't surprised to see a
event with | |
| 1652 // co-ordinates outside the target's bounds. | |
| 1653 IntPoint adjustedPoint = gestureEvent.position(); | |
| 1654 | |
| 1655 PlatformMouseEvent fakeMouseMove(adjustedPoint, gestureEvent.globalPosition(
), | |
| 1656 NoButton, PlatformEvent::MouseMoved, /* clickCount */ 0, | |
| 1657 modifiers, PlatformMouseEvent::FromTouch, gestureEvent.timestamp()); | |
| 1658 dispatchMouseEvent(EventTypeNames::mousemove, currentHitTest.innerNode(), 0,
fakeMouseMove, true); | |
| 1659 | |
| 1660 // Do a new hit-test in case the mousemove event changed the DOM. | |
| 1661 // Note that if the original hit test wasn't over an element (eg. was over a
scrollbar) we | |
| 1662 // don't want to re-hit-test because it may be in the wrong frame (and there
's no way the page | |
| 1663 // could have seen the event anyway). | |
| 1664 // FIXME: Use a hit-test cache to avoid unnecessary hit tests. http://crbug.
com/398920 | |
| 1665 if (currentHitTest.innerNode()) | |
| 1666 currentHitTest = hitTestResultInFrame(m_frame, adjustedPoint, HitTestReq
uest::ReadOnly); | |
| 1667 m_clickNode = currentHitTest.innerNode(); | |
| 1668 if (m_clickNode && m_clickNode->isTextNode()) | |
| 1669 m_clickNode = NodeRenderingTraversal::parent(m_clickNode.get()); | |
| 1670 | |
| 1671 PlatformMouseEvent fakeMouseDown(adjustedPoint, gestureEvent.globalPosition(
), | |
| 1672 LeftButton, PlatformEvent::MousePressed, gestureEvent.tapCount(), | |
| 1673 modifiers, PlatformMouseEvent::FromTouch, gestureEvent.timestamp()); | |
| 1674 bool swallowMouseDownEvent = !dispatchMouseEvent(EventTypeNames::mousedown,
currentHitTest.innerNode(), gestureEvent.tapCount(), fakeMouseDown, true); | |
| 1675 if (!swallowMouseDownEvent) | |
| 1676 swallowMouseDownEvent = handleMouseFocus(fakeMouseDown); | |
| 1677 if (!swallowMouseDownEvent) | |
| 1678 swallowMouseDownEvent = handleMousePressEvent(MouseEventWithHitTestResul
ts(fakeMouseDown, currentHitTest)); | |
| 1679 | |
| 1680 // FIXME: Use a hit-test cache to avoid unnecessary hit tests. http://crbug.
com/398920 | |
| 1681 if (currentHitTest.innerNode()) | |
| 1682 currentHitTest = hitTestResultInFrame(m_frame, adjustedPoint, HitTestReq
uest::ReadOnly); | |
| 1683 PlatformMouseEvent fakeMouseUp(adjustedPoint, gestureEvent.globalPosition(), | |
| 1684 LeftButton, PlatformEvent::MouseReleased, gestureEvent.tapCount(), | |
| 1685 modifiers, PlatformMouseEvent::FromTouch, gestureEvent.timestamp()); | |
| 1686 bool swallowMouseUpEvent = !dispatchMouseEvent(EventTypeNames::mouseup, curr
entHitTest.innerNode(), gestureEvent.tapCount(), fakeMouseUp, false); | |
| 1687 | |
| 1688 bool swallowClickEvent = false; | |
| 1689 if (m_clickNode) { | |
| 1690 if (currentHitTest.innerNode()) { | |
| 1691 Node* clickTargetNode = NodeRenderingTraversal::commonAncestor(*curr
entHitTest.innerNode(), *m_clickNode); | |
| 1692 swallowClickEvent = !dispatchMouseEvent(EventTypeNames::click, click
TargetNode, gestureEvent.tapCount(), fakeMouseUp, true); | |
| 1693 } | |
| 1694 m_clickNode = nullptr; | |
| 1695 } | |
| 1696 | |
| 1697 if (!swallowMouseUpEvent) | |
| 1698 swallowMouseUpEvent = handleMouseReleaseEvent(MouseEventWithHitTestResul
ts(fakeMouseUp, currentHitTest)); | |
| 1699 | |
| 1700 return swallowMouseDownEvent | swallowMouseUpEvent | swallowClickEvent; | |
| 1701 } | 827 } |
| 1702 | 828 |
| 1703 bool EventHandler::handleGestureLongPress(const GestureEventWithHitTestResults&
targetedEvent) | 829 bool EventHandler::handleGestureLongPress(const GestureEventWithHitTestResults&
targetedEvent) |
| 1704 { | 830 { |
| 1705 const PlatformGestureEvent& gestureEvent = targetedEvent.event(); | 831 const PlatformGestureEvent& gestureEvent = targetedEvent.event(); |
| 1706 | 832 |
| 1707 // FIXME: Ideally we should try to remove the extra mouse-specific hit-tests
here (re-using the | 833 // FIXME: Ideally we should try to remove the extra mouse-specific hit-tests
here (re-using the |
| 1708 // supplied HitTestResult), but that will require some overhaul of the touch
drag-and-drop code | 834 // supplied HitTestResult), but that will require some overhaul of the touch
drag-and-drop code |
| 1709 // and LongPress is such a special scenario that it's unlikely to matter muc
h in practice. | 835 // and LongPress is such a special scenario that it's unlikely to matter muc
h in practice. |
| 1710 | 836 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1816 if (horizontalScroll || verticalScroll) { | 942 if (horizontalScroll || verticalScroll) { |
| 1817 return true; | 943 return true; |
| 1818 } | 944 } |
| 1819 | 945 |
| 1820 // Otherwise try to scroll the view. | 946 // Otherwise try to scroll the view. |
| 1821 return sendScrollEventToView(gestureEvent, delta); | 947 return sendScrollEventToView(gestureEvent, delta); |
| 1822 } | 948 } |
| 1823 | 949 |
| 1824 bool EventHandler::sendScrollEventToView(const PlatformGestureEvent& gestureEven
t, const FloatSize& scaledDelta) | 950 bool EventHandler::sendScrollEventToView(const PlatformGestureEvent& gestureEven
t, const FloatSize& scaledDelta) |
| 1825 { | 951 { |
| 1826 FrameView* view = m_frame->view(); | 952 return false; |
| 1827 if (!view) | |
| 1828 return false; | |
| 1829 | |
| 1830 const float tickDivisor = static_cast<float>(WheelEvent::TickMultiplier); | |
| 1831 IntPoint point(gestureEvent.position().x(), gestureEvent.position().y()); | |
| 1832 IntPoint globalPoint(gestureEvent.globalPosition().x(), gestureEvent.globalP
osition().y()); | |
| 1833 PlatformWheelEvent syntheticWheelEvent(point, globalPoint, | |
| 1834 scaledDelta.width(), scaledDelta.height(), | |
| 1835 scaledDelta.width() / tickDivisor, scaledDelta.height() / tickDivisor, | |
| 1836 ScrollByPixelWheelEvent, | |
| 1837 gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(),
gestureEvent.metaKey()); | |
| 1838 syntheticWheelEvent.setHasPreciseScrollingDeltas(true); | |
| 1839 | |
| 1840 bool scrolledFrame = view->wheelEvent(syntheticWheelEvent); | |
| 1841 return scrolledFrame; | |
| 1842 } | 953 } |
| 1843 | 954 |
| 1844 void EventHandler::clearGestureScrollNodes() | 955 void EventHandler::clearGestureScrollNodes() |
| 1845 { | 956 { |
| 1846 m_scrollGestureHandlingNode = nullptr; | 957 m_scrollGestureHandlingNode = nullptr; |
| 1847 m_previousGestureScrolledNode = nullptr; | 958 m_previousGestureScrolledNode = nullptr; |
| 1848 } | 959 } |
| 1849 | 960 |
| 1850 bool EventHandler::isScrollbarHandlingGestures() const | 961 bool EventHandler::isScrollbarHandlingGestures() const |
| 1851 { | 962 { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1878 IntPoint hitTestPoint = gestureEvent.position(); | 989 IntPoint hitTestPoint = gestureEvent.position(); |
| 1879 IntSize touchRadius = gestureEvent.area(); | 990 IntSize touchRadius = gestureEvent.area(); |
| 1880 touchRadius.scale(1.f / 2); | 991 touchRadius.scale(1.f / 2); |
| 1881 // FIXME: We should not do a rect-based hit-test if touch adjustment is disa
bled. | 992 // FIXME: We should not do a rect-based hit-test if touch adjustment is disa
bled. |
| 1882 HitTestResult hitTestResult = hitTestResultAtPoint(hitTestPoint, hitType | H
itTestRequest::ReadOnly, touchRadius); | 993 HitTestResult hitTestResult = hitTestResultAtPoint(hitTestPoint, hitType | H
itTestRequest::ReadOnly, touchRadius); |
| 1883 | 994 |
| 1884 // Now apply hover/active state to the final target. | 995 // Now apply hover/active state to the final target. |
| 1885 // FIXME: This is supposed to send mouseenter/mouseleave events, but doesn't
because we | 996 // FIXME: This is supposed to send mouseenter/mouseleave events, but doesn't
because we |
| 1886 // aren't passing a PlatformMouseEvent. | 997 // aren't passing a PlatformMouseEvent. |
| 1887 HitTestRequest request(hitType); | 998 HitTestRequest request(hitType); |
| 1888 if (!request.readOnly()) | |
| 1889 m_frame->document()->updateHoverActiveState(request, hitTestResult.inner
Element()); | |
| 1890 | 999 |
| 1891 if (shouldKeepActiveForMinInterval) { | 1000 if (shouldKeepActiveForMinInterval) { |
| 1892 m_lastDeferredTapElement = hitTestResult.innerElement(); | 1001 m_lastDeferredTapElement = hitTestResult.innerElement(); |
| 1893 m_activeIntervalTimer.startOneShot(minimumActiveInterval - activeInterva
l, FROM_HERE); | 1002 m_activeIntervalTimer.startOneShot(minimumActiveInterval - activeInterva
l, FROM_HERE); |
| 1894 } | 1003 } |
| 1895 | 1004 |
| 1896 return GestureEventWithHitTestResults(gestureEvent, hitTestResult); | 1005 return GestureEventWithHitTestResults(gestureEvent, hitTestResult); |
| 1897 } | 1006 } |
| 1898 | 1007 |
| 1899 HitTestRequest::HitTestRequestType EventHandler::getHitTypeForGestureType(Platfo
rmEvent::Type type) | 1008 HitTestRequest::HitTestRequestType EventHandler::getHitTypeForGestureType(Platfo
rmEvent::Type type) |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1927 if (!m_hoverTimer.isActive()) | 1036 if (!m_hoverTimer.isActive()) |
| 1928 m_hoverTimer.startOneShot(0, FROM_HERE); | 1037 m_hoverTimer.startOneShot(0, FROM_HERE); |
| 1929 } | 1038 } |
| 1930 | 1039 |
| 1931 void EventHandler::scheduleCursorUpdate() | 1040 void EventHandler::scheduleCursorUpdate() |
| 1932 { | 1041 { |
| 1933 if (!m_cursorUpdateTimer.isActive()) | 1042 if (!m_cursorUpdateTimer.isActive()) |
| 1934 m_cursorUpdateTimer.startOneShot(cursorUpdateInterval, FROM_HERE); | 1043 m_cursorUpdateTimer.startOneShot(cursorUpdateInterval, FROM_HERE); |
| 1935 } | 1044 } |
| 1936 | 1045 |
| 1937 void EventHandler::dispatchFakeMouseMoveEventSoon() | |
| 1938 { | |
| 1939 if (m_mousePressed) | |
| 1940 return; | |
| 1941 | |
| 1942 if (m_mousePositionIsUnknown) | |
| 1943 return; | |
| 1944 | |
| 1945 Settings* settings = m_frame->settings(); | |
| 1946 if (settings && !settings->deviceSupportsMouse()) | |
| 1947 return; | |
| 1948 | |
| 1949 // If the content has ever taken longer than fakeMouseMoveShortInterval we | |
| 1950 // reschedule the timer and use a longer time. This will cause the content | |
| 1951 // to receive these moves only after the user is done scrolling, reducing | |
| 1952 // pauses during the scroll. | |
| 1953 if (m_maxMouseMovedDuration > fakeMouseMoveShortInterval) { | |
| 1954 if (m_fakeMouseMoveEventTimer.isActive()) | |
| 1955 m_fakeMouseMoveEventTimer.stop(); | |
| 1956 m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveLongInterval, FROM_H
ERE); | |
| 1957 } else { | |
| 1958 if (!m_fakeMouseMoveEventTimer.isActive()) | |
| 1959 m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveShortInterval, F
ROM_HERE); | |
| 1960 } | |
| 1961 } | |
| 1962 | |
| 1963 void EventHandler::dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad& quad) | |
| 1964 { | |
| 1965 FrameView* view = m_frame->view(); | |
| 1966 if (!view) | |
| 1967 return; | |
| 1968 | |
| 1969 if (!quad.containsPoint(m_lastKnownMousePosition)) | |
| 1970 return; | |
| 1971 | |
| 1972 dispatchFakeMouseMoveEventSoon(); | |
| 1973 } | |
| 1974 | |
| 1975 void EventHandler::fakeMouseMoveEventTimerFired(Timer<EventHandler>* timer) | |
| 1976 { | |
| 1977 ASSERT_UNUSED(timer, timer == &m_fakeMouseMoveEventTimer); | |
| 1978 ASSERT(!m_mousePressed); | |
| 1979 | |
| 1980 Settings* settings = m_frame->settings(); | |
| 1981 if (settings && !settings->deviceSupportsMouse()) | |
| 1982 return; | |
| 1983 | |
| 1984 FrameView* view = m_frame->view(); | |
| 1985 if (!view) | |
| 1986 return; | |
| 1987 | |
| 1988 if (!m_frame->page() || !m_frame->page()->focusController().isActive()) | |
| 1989 return; | |
| 1990 | |
| 1991 // Don't dispatch a synthetic mouse move event if the mouse cursor is not vi
sible to the user. | |
| 1992 if (!isCursorVisible()) | |
| 1993 return; | |
| 1994 | |
| 1995 bool shiftKey; | |
| 1996 bool ctrlKey; | |
| 1997 bool altKey; | |
| 1998 bool metaKey; | |
| 1999 PlatformKeyboardEvent::getCurrentModifierState(shiftKey, ctrlKey, altKey, me
taKey); | |
| 2000 PlatformMouseEvent fakeMouseMoveEvent(m_lastKnownMousePosition, m_lastKnownM
ouseGlobalPosition, NoButton, PlatformEvent::MouseMoved, 0, shiftKey, ctrlKey, a
ltKey, metaKey, PlatformMouseEvent::RealOrIndistinguishable, currentTime()); | |
| 2001 handleMouseMoveEvent(fakeMouseMoveEvent); | |
| 2002 } | |
| 2003 | |
| 2004 void EventHandler::cancelFakeMouseMoveEvent() | |
| 2005 { | |
| 2006 m_fakeMouseMoveEventTimer.stop(); | |
| 2007 } | |
| 2008 | |
| 2009 bool EventHandler::isCursorVisible() const | 1046 bool EventHandler::isCursorVisible() const |
| 2010 { | 1047 { |
| 2011 return m_frame->page()->isCursorVisible(); | 1048 return m_frame->page()->isCursorVisible(); |
| 2012 } | 1049 } |
| 2013 | 1050 |
| 2014 void EventHandler::hoverTimerFired(Timer<EventHandler>*) | 1051 void EventHandler::hoverTimerFired(Timer<EventHandler>*) |
| 2015 { | 1052 { |
| 2016 m_hoverTimer.stop(); | 1053 m_hoverTimer.stop(); |
| 2017 | 1054 |
| 2018 ASSERT(m_frame); | 1055 ASSERT(m_frame); |
| 2019 ASSERT(m_frame->document()); | 1056 ASSERT(m_frame->document()); |
| 2020 | 1057 |
| 2021 if (RenderView* renderer = m_frame->contentRenderer()) { | 1058 if (RenderView* renderer = m_frame->contentRenderer()) { |
| 2022 HitTestRequest request(HitTestRequest::Move); | 1059 HitTestRequest request(HitTestRequest::Move); |
| 2023 HitTestResult result(m_lastKnownMousePosition); | 1060 HitTestResult result(m_lastKnownMousePosition); |
| 2024 renderer->hitTest(request, result); | 1061 renderer->hitTest(request, result); |
| 2025 m_frame->document()->updateHoverActiveState(request, result.innerElement
()); | |
| 2026 } | 1062 } |
| 2027 } | 1063 } |
| 2028 | 1064 |
| 2029 void EventHandler::activeIntervalTimerFired(Timer<EventHandler>*) | 1065 void EventHandler::activeIntervalTimerFired(Timer<EventHandler>*) |
| 2030 { | 1066 { |
| 2031 m_activeIntervalTimer.stop(); | 1067 m_activeIntervalTimer.stop(); |
| 2032 | |
| 2033 if (m_frame | |
| 2034 && m_frame->document() | |
| 2035 && m_lastDeferredTapElement) { | |
| 2036 // FIXME: Enable condition when http://crbug.com/226842 lands | |
| 2037 // m_lastDeferredTapElement.get() == m_frame->document()->activeElement(
) | |
| 2038 HitTestRequest request(HitTestRequest::TouchEvent | HitTestRequest::Rele
ase); | |
| 2039 m_frame->document()->updateHoverActiveState(request, m_lastDeferredTapEl
ement.get()); | |
| 2040 } | |
| 2041 m_lastDeferredTapElement = nullptr; | 1068 m_lastDeferredTapElement = nullptr; |
| 2042 } | 1069 } |
| 2043 | 1070 |
| 2044 void EventHandler::notifyElementActivated() | 1071 void EventHandler::notifyElementActivated() |
| 2045 { | 1072 { |
| 2046 // Since another element has been set to active, stop current timer and clea
r reference. | 1073 // Since another element has been set to active, stop current timer and clea
r reference. |
| 2047 if (m_activeIntervalTimer.isActive()) | 1074 if (m_activeIntervalTimer.isActive()) |
| 2048 m_activeIntervalTimer.stop(); | 1075 m_activeIntervalTimer.stop(); |
| 2049 m_lastDeferredTapElement = nullptr; | 1076 m_lastDeferredTapElement = nullptr; |
| 2050 } | 1077 } |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2176 } | 1203 } |
| 2177 | 1204 |
| 2178 void EventHandler::defaultTabEventHandler(KeyboardEvent* event) | 1205 void EventHandler::defaultTabEventHandler(KeyboardEvent* event) |
| 2179 { | 1206 { |
| 2180 } | 1207 } |
| 2181 | 1208 |
| 2182 void EventHandler::capsLockStateMayHaveChanged() | 1209 void EventHandler::capsLockStateMayHaveChanged() |
| 2183 { | 1210 { |
| 2184 } | 1211 } |
| 2185 | 1212 |
| 2186 bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults&
mev) | |
| 2187 { | |
| 2188 // FIXME(sky): Remove | |
| 2189 return false; | |
| 2190 } | |
| 2191 | |
| 2192 // If scrollbar (under mouse) is different from last, send a mouse exited. Set | 1213 // If scrollbar (under mouse) is different from last, send a mouse exited. Set |
| 2193 // last to scrollbar if setLast is true; else set last to 0. | 1214 // last to scrollbar if setLast is true; else set last to 0. |
| 2194 void EventHandler::updateLastScrollbarUnderMouse(Scrollbar* scrollbar, bool setL
ast) | 1215 void EventHandler::updateLastScrollbarUnderMouse(Scrollbar* scrollbar, bool setL
ast) |
| 2195 { | 1216 { |
| 2196 if (m_lastScrollbarUnderMouse != scrollbar) { | 1217 if (m_lastScrollbarUnderMouse != scrollbar) { |
| 2197 // Send mouse exited to the old scrollbar. | 1218 // Send mouse exited to the old scrollbar. |
| 2198 if (m_lastScrollbarUnderMouse) | 1219 if (m_lastScrollbarUnderMouse) |
| 2199 m_lastScrollbarUnderMouse->mouseExited(); | 1220 m_lastScrollbarUnderMouse->mouseExited(); |
| 2200 | 1221 |
| 2201 // Send mouse entered if we're setting a new scrollbar. | 1222 // Send mouse entered if we're setting a new scrollbar. |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2489 } | 1510 } |
| 2490 | 1511 |
| 2491 // If we've reached an ancestor that supports a touch action, search
no further. | 1512 // If we've reached an ancestor that supports a touch action, search
no further. |
| 2492 if (renderer->isBox() && toRenderBox(renderer)->scrollsOverflow()) | 1513 if (renderer->isBox() && toRenderBox(renderer)->scrollsOverflow()) |
| 2493 break; | 1514 break; |
| 2494 } | 1515 } |
| 2495 } | 1516 } |
| 2496 return effectiveTouchAction; | 1517 return effectiveTouchAction; |
| 2497 } | 1518 } |
| 2498 | 1519 |
| 2499 void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event) | |
| 2500 { | |
| 2501 m_mousePositionIsUnknown = false; | |
| 2502 m_lastKnownMousePosition = event.position(); | |
| 2503 m_lastKnownMouseGlobalPosition = event.globalPosition(); | |
| 2504 } | |
| 2505 | |
| 2506 bool EventHandler::passWheelEventToWidget(const PlatformWheelEvent& wheelEvent,
Widget* widget) | |
| 2507 { | |
| 2508 // We can sometimes get a null widget! EventHandlerMac handles a null | |
| 2509 // widget by returning false, so we do the same. | |
| 2510 if (!widget) | |
| 2511 return false; | |
| 2512 | |
| 2513 // If not a FrameView, then probably a plugin widget. Those will receive | |
| 2514 // the event via an EventTargetNode dispatch when this returns false. | |
| 2515 if (!widget->isFrameView()) | |
| 2516 return false; | |
| 2517 | |
| 2518 return toFrameView(widget)->frame().eventHandler().handleWheelEvent(wheelEve
nt); | |
| 2519 } | |
| 2520 | |
| 2521 // TODO(esprehn): Remove this. | |
| 2522 bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestR
esults& event) | |
| 2523 { | |
| 2524 return false; | |
| 2525 } | |
| 2526 | |
| 2527 void EventHandler::focusDocumentView() | 1520 void EventHandler::focusDocumentView() |
| 2528 { | 1521 { |
| 2529 Page* page = m_frame->page(); | 1522 Page* page = m_frame->page(); |
| 2530 if (!page) | 1523 if (!page) |
| 2531 return; | 1524 return; |
| 2532 page->focusController().focusDocumentView(m_frame); | 1525 page->focusController().focusDocumentView(m_frame); |
| 2533 } | 1526 } |
| 2534 | 1527 |
| 2535 } // namespace blink | 1528 } // namespace blink |
| OLD | NEW |