OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/input/MouseEventManager.h" | 5 #include "core/input/MouseEventManager.h" |
6 | 6 |
7 #include "core/clipboard/DataObject.h" | 7 #include "core/clipboard/DataObject.h" |
8 #include "core/clipboard/DataTransfer.h" | 8 #include "core/clipboard/DataTransfer.h" |
9 #include "core/dom/Element.h" | 9 #include "core/dom/Element.h" |
10 #include "core/dom/ElementTraversal.h" | 10 #include "core/dom/ElementTraversal.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "core/input/InputDeviceCapabilities.h" | 23 #include "core/input/InputDeviceCapabilities.h" |
24 #include "core/input/KeyboardEventManager.h" | 24 #include "core/input/KeyboardEventManager.h" |
25 #include "core/layout/HitTestResult.h" | 25 #include "core/layout/HitTestResult.h" |
26 #include "core/layout/api/LayoutViewItem.h" | 26 #include "core/layout/api/LayoutViewItem.h" |
27 #include "core/page/AutoscrollController.h" | 27 #include "core/page/AutoscrollController.h" |
28 #include "core/page/DragController.h" | 28 #include "core/page/DragController.h" |
29 #include "core/page/DragState.h" | 29 #include "core/page/DragState.h" |
30 #include "core/page/FocusController.h" | 30 #include "core/page/FocusController.h" |
31 #include "core/paint/PaintLayer.h" | 31 #include "core/paint/PaintLayer.h" |
32 #include "core/svg/SVGDocumentExtensions.h" | 32 #include "core/svg/SVGDocumentExtensions.h" |
| 33 #include "platform/Histogram.h" |
33 #include "platform/geometry/FloatQuad.h" | 34 #include "platform/geometry/FloatQuad.h" |
34 | 35 |
35 namespace blink { | 36 namespace blink { |
36 | 37 |
37 namespace { | 38 namespace { |
38 | 39 |
39 String CanvasRegionId(Node* node, const WebMouseEvent& mouse_event) { | 40 String CanvasRegionId(Node* node, const WebMouseEvent& mouse_event) { |
40 if (!node->IsElementNode()) | 41 if (!node->IsElementNode()) |
41 return String(); | 42 return String(); |
42 | 43 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 mouse_press_node_ = nullptr; | 89 mouse_press_node_ = nullptr; |
89 mouse_down_may_start_autoscroll_ = false; | 90 mouse_down_may_start_autoscroll_ = false; |
90 mouse_down_may_start_drag_ = false; | 91 mouse_down_may_start_drag_ = false; |
91 captures_dragging_ = false; | 92 captures_dragging_ = false; |
92 is_mouse_position_unknown_ = true; | 93 is_mouse_position_unknown_ = true; |
93 last_known_mouse_position_ = IntPoint(); | 94 last_known_mouse_position_ = IntPoint(); |
94 last_known_mouse_global_position_ = IntPoint(); | 95 last_known_mouse_global_position_ = IntPoint(); |
95 mouse_pressed_ = false; | 96 mouse_pressed_ = false; |
96 click_count_ = 0; | 97 click_count_ = 0; |
97 click_element_ = nullptr; | 98 click_element_ = nullptr; |
| 99 mouse_down_element_ = nullptr; |
98 mouse_down_pos_ = IntPoint(); | 100 mouse_down_pos_ = IntPoint(); |
99 mouse_down_timestamp_ = TimeTicks(); | 101 mouse_down_timestamp_ = TimeTicks(); |
100 mouse_down_ = WebMouseEvent(); | 102 mouse_down_ = WebMouseEvent(); |
101 svg_pan_ = false; | 103 svg_pan_ = false; |
102 drag_start_pos_ = LayoutPoint(); | 104 drag_start_pos_ = LayoutPoint(); |
103 fake_mouse_move_event_timer_.Stop(); | 105 fake_mouse_move_event_timer_.Stop(); |
104 ResetDragState(); | 106 ResetDragState(); |
105 } | 107 } |
106 | 108 |
107 MouseEventManager::~MouseEventManager() = default; | 109 MouseEventManager::~MouseEventManager() = default; |
108 | 110 |
109 DEFINE_TRACE(MouseEventManager) { | 111 DEFINE_TRACE(MouseEventManager) { |
110 visitor->Trace(frame_); | 112 visitor->Trace(frame_); |
111 visitor->Trace(scroll_manager_); | 113 visitor->Trace(scroll_manager_); |
112 visitor->Trace(node_under_mouse_); | 114 visitor->Trace(node_under_mouse_); |
113 visitor->Trace(mouse_press_node_); | 115 visitor->Trace(mouse_press_node_); |
114 visitor->Trace(click_element_); | 116 visitor->Trace(click_element_); |
| 117 visitor->Trace(mouse_down_element_); |
115 SynchronousMutationObserver::Trace(visitor); | 118 SynchronousMutationObserver::Trace(visitor); |
116 } | 119 } |
117 | 120 |
118 MouseEventManager::MouseEventBoundaryEventDispatcher:: | 121 MouseEventManager::MouseEventBoundaryEventDispatcher:: |
119 MouseEventBoundaryEventDispatcher(MouseEventManager* mouse_event_manager, | 122 MouseEventBoundaryEventDispatcher(MouseEventManager* mouse_event_manager, |
120 const WebMouseEvent* web_mouse_event, | 123 const WebMouseEvent* web_mouse_event, |
121 EventTarget* exited_target, | 124 EventTarget* exited_target, |
122 const String& canvas_region_id) | 125 const String& canvas_region_id) |
123 : mouse_event_manager_(mouse_event_manager), | 126 : mouse_event_manager_(mouse_event_manager), |
124 web_mouse_event_(web_mouse_event), | 127 web_mouse_event_(web_mouse_event), |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 #if OS(MACOSX) | 245 #if OS(MACOSX) |
243 // FIXME: The Mac port achieves the same behavior by checking whether the | 246 // FIXME: The Mac port achieves the same behavior by checking whether the |
244 // context menu is currently open in WebPage::mouseEvent(). Consider merging | 247 // context menu is currently open in WebPage::mouseEvent(). Consider merging |
245 // the implementations. | 248 // the implementations. |
246 if (mev.Event().button == WebPointerProperties::Button::kLeft && | 249 if (mev.Event().button == WebPointerProperties::Button::kLeft && |
247 mev.Event().GetModifiers() & WebInputEvent::Modifiers::kControlKey) | 250 mev.Event().GetModifiers() & WebInputEvent::Modifiers::kControlKey) |
248 context_menu_event = true; | 251 context_menu_event = true; |
249 #endif | 252 #endif |
250 | 253 |
251 const bool should_dispatch_click_event = | 254 const bool should_dispatch_click_event = |
252 click_count_ > 0 && !context_menu_event && click_element_ && | 255 click_count_ > 0 && !context_menu_event && mouse_down_element_ && |
253 mouse_release_target.CanParticipateInFlatTree() && | 256 mouse_release_target.CanParticipateInFlatTree() && |
254 click_element_->CanParticipateInFlatTree() && | 257 mouse_down_element_->CanParticipateInFlatTree() && |
| 258 mouse_down_element_->isConnected() && |
255 !(frame_->GetEventHandler() | 259 !(frame_->GetEventHandler() |
256 .GetSelectionController() | 260 .GetSelectionController() |
257 .HasExtendedSelection() && | 261 .HasExtendedSelection() && |
258 IsLinkSelection(mev)); | 262 IsLinkSelection(mev)); |
259 if (!should_dispatch_click_event) | 263 if (!should_dispatch_click_event) |
260 return WebInputEventResult::kNotHandled; | 264 return WebInputEventResult::kNotHandled; |
261 | 265 |
262 Node* click_target_node = nullptr; | 266 Node* click_target_node = nullptr; |
263 if (click_element_ == mouse_release_target) { | 267 if (mouse_down_element_ == mouse_release_target) { |
264 click_target_node = click_element_; | 268 click_target_node = mouse_down_element_; |
265 } else if (click_element_->GetDocument() == | 269 } else if (mouse_down_element_->GetDocument() == |
266 mouse_release_target.GetDocument()) { | 270 mouse_release_target.GetDocument()) { |
267 // Updates distribution because a 'mouseup' event listener can make the | 271 // Updates distribution because a 'mouseup' event listener can make the |
268 // tree dirty at dispatchMouseEvent() invocation above. | 272 // tree dirty at dispatchMouseEvent() invocation above. |
269 // Unless distribution is updated, commonAncestor would hit ASSERT. | 273 // Unless distribution is updated, commonAncestor would hit ASSERT. |
270 click_element_->UpdateDistribution(); | 274 mouse_down_element_->UpdateDistribution(); |
271 mouse_release_target.UpdateDistribution(); | 275 mouse_release_target.UpdateDistribution(); |
272 click_target_node = mouse_release_target.CommonAncestor( | 276 click_target_node = mouse_release_target.CommonAncestor( |
273 *click_element_, EventHandlingUtil::ParentForClickEvent); | 277 *mouse_down_element_, EventHandlingUtil::ParentForClickEvent); |
274 } | 278 } |
275 if (!click_target_node) | 279 if (!click_target_node) |
276 return WebInputEventResult::kNotHandled; | 280 return WebInputEventResult::kNotHandled; |
277 return DispatchMouseEvent( | 281 |
278 click_target_node, | 282 DEFINE_STATIC_LOCAL(BooleanHistogram, histogram, |
279 !RuntimeEnabledFeatures::auxclickEnabled() || | 283 ("Event.ClickNotFiredDueToDomManipulation")); |
280 (mev.Event().button == WebPointerProperties::Button::kLeft) | 284 |
281 ? EventTypeNames::click | 285 if (click_element_ && click_element_->CanParticipateInFlatTree() && |
282 : EventTypeNames::auxclick, | 286 click_element_->isConnected()) { |
283 mev.Event(), mev.CanvasRegionId(), nullptr); | 287 DCHECK(click_element_ == mouse_down_element_); |
| 288 histogram.Count(false); |
| 289 } else { |
| 290 histogram.Count(true); |
| 291 } |
| 292 |
| 293 if ((click_element_ && click_element_->CanParticipateInFlatTree() && |
| 294 click_element_->isConnected()) || |
| 295 RuntimeEnabledFeatures::clickRetargettingEnabled()) { |
| 296 return DispatchMouseEvent( |
| 297 click_target_node, |
| 298 !RuntimeEnabledFeatures::auxclickEnabled() || |
| 299 (mev.Event().button == WebPointerProperties::Button::kLeft) |
| 300 ? EventTypeNames::click |
| 301 : EventTypeNames::auxclick, |
| 302 mev.Event(), mev.CanvasRegionId(), nullptr); |
| 303 } |
| 304 |
| 305 return WebInputEventResult::kNotHandled; |
284 } | 306 } |
285 | 307 |
286 void MouseEventManager::FakeMouseMoveEventTimerFired(TimerBase* timer) { | 308 void MouseEventManager::FakeMouseMoveEventTimerFired(TimerBase* timer) { |
287 TRACE_EVENT0("input", "MouseEventManager::fakeMouseMoveEventTimerFired"); | 309 TRACE_EVENT0("input", "MouseEventManager::fakeMouseMoveEventTimerFired"); |
288 DCHECK(timer == &fake_mouse_move_event_timer_); | 310 DCHECK(timer == &fake_mouse_move_event_timer_); |
289 DCHECK(!mouse_pressed_); | 311 DCHECK(!mouse_pressed_); |
290 | 312 |
291 if (is_mouse_position_unknown_) | 313 if (is_mouse_position_unknown_) |
292 return; | 314 return; |
293 | 315 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 SendBoundaryEvents(last_node_under_mouse, node_under_mouse_, canvas_region_id, | 401 SendBoundaryEvents(last_node_under_mouse, node_under_mouse_, canvas_region_id, |
380 web_mouse_event); | 402 web_mouse_event); |
381 } | 403 } |
382 | 404 |
383 void MouseEventManager::NodeChildrenWillBeRemoved(ContainerNode& container) { | 405 void MouseEventManager::NodeChildrenWillBeRemoved(ContainerNode& container) { |
384 if (container == click_element_) | 406 if (container == click_element_) |
385 return; | 407 return; |
386 if (!container.IsShadowIncludingInclusiveAncestorOf(click_element_.Get())) | 408 if (!container.IsShadowIncludingInclusiveAncestorOf(click_element_.Get())) |
387 return; | 409 return; |
388 click_element_ = nullptr; | 410 click_element_ = nullptr; |
| 411 |
| 412 // TODO(crbug.com/716694): Do not reset mouse_down_element_ for the purpose of |
| 413 // gathering data. |
389 } | 414 } |
390 | 415 |
391 void MouseEventManager::NodeWillBeRemoved(Node& node_to_be_removed) { | 416 void MouseEventManager::NodeWillBeRemoved(Node& node_to_be_removed) { |
392 if (node_to_be_removed.IsShadowIncludingInclusiveAncestorOf( | 417 if (node_to_be_removed.IsShadowIncludingInclusiveAncestorOf( |
393 click_element_.Get())) { | 418 click_element_.Get())) { |
394 // We don't dispatch click events if the mousedown node is removed | 419 // We don't dispatch click events if the mousedown node is removed |
395 // before a mouseup event. It is compatible with IE and Firefox. | 420 // before a mouseup event. It is compatible with IE and Firefox. |
396 click_element_ = nullptr; | 421 click_element_ = nullptr; |
| 422 |
| 423 // TODO(crbug.com/716694): Do not reset mouse_down_element_ for the purpose |
| 424 // of gathering data. |
397 } | 425 } |
398 } | 426 } |
399 | 427 |
400 Node* MouseEventManager::GetNodeUnderMouse() { | 428 Node* MouseEventManager::GetNodeUnderMouse() { |
401 return node_under_mouse_; | 429 return node_under_mouse_; |
402 } | 430 } |
403 | 431 |
404 WebInputEventResult MouseEventManager::HandleMouseFocus( | 432 WebInputEventResult MouseEventManager::HandleMouseFocus( |
405 const HitTestResult& hit_test_result, | 433 const HitTestResult& hit_test_result, |
406 InputDeviceCapabilities* source_capabilities) { | 434 InputDeviceCapabilities* source_capabilities) { |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
992 return false; | 1020 return false; |
993 svg_pan_ = !is_release_event; | 1021 svg_pan_ = !is_release_event; |
994 frame_->GetDocument()->AccessSVGExtensions().UpdatePan( | 1022 frame_->GetDocument()->AccessSVGExtensions().UpdatePan( |
995 frame_->View()->RootFrameToContents(last_known_mouse_position_)); | 1023 frame_->View()->RootFrameToContents(last_known_mouse_position_)); |
996 return true; | 1024 return true; |
997 } | 1025 } |
998 | 1026 |
999 void MouseEventManager::InvalidateClick() { | 1027 void MouseEventManager::InvalidateClick() { |
1000 click_count_ = 0; | 1028 click_count_ = 0; |
1001 click_element_ = nullptr; | 1029 click_element_ = nullptr; |
| 1030 mouse_down_element_ = nullptr; |
1002 } | 1031 } |
1003 | 1032 |
1004 bool MouseEventManager::MousePressed() { | 1033 bool MouseEventManager::MousePressed() { |
1005 return mouse_pressed_; | 1034 return mouse_pressed_; |
1006 } | 1035 } |
1007 | 1036 |
1008 void MouseEventManager::SetMousePressed(bool mouse_pressed) { | 1037 void MouseEventManager::SetMousePressed(bool mouse_pressed) { |
1009 mouse_pressed_ = mouse_pressed; | 1038 mouse_pressed_ = mouse_pressed; |
1010 } | 1039 } |
1011 | 1040 |
1012 bool MouseEventManager::CapturesDragging() const { | 1041 bool MouseEventManager::CapturesDragging() const { |
1013 return captures_dragging_; | 1042 return captures_dragging_; |
1014 } | 1043 } |
1015 | 1044 |
1016 void MouseEventManager::SetCapturesDragging(bool captures_dragging) { | 1045 void MouseEventManager::SetCapturesDragging(bool captures_dragging) { |
1017 captures_dragging_ = captures_dragging; | 1046 captures_dragging_ = captures_dragging; |
1018 } | 1047 } |
1019 | 1048 |
1020 Node* MouseEventManager::MousePressNode() { | 1049 Node* MouseEventManager::MousePressNode() { |
1021 return mouse_press_node_; | 1050 return mouse_press_node_; |
1022 } | 1051 } |
1023 | 1052 |
1024 void MouseEventManager::SetMousePressNode(Node* node) { | 1053 void MouseEventManager::SetMousePressNode(Node* node) { |
1025 mouse_press_node_ = node; | 1054 mouse_press_node_ = node; |
1026 } | 1055 } |
1027 | 1056 |
1028 void MouseEventManager::SetClickElement(Element* element) { | 1057 void MouseEventManager::SetClickElement(Element* element) { |
1029 SetContext(element ? element->ownerDocument() : nullptr); | 1058 SetContext(element ? element->ownerDocument() : nullptr); |
1030 click_element_ = element; | 1059 click_element_ = element; |
| 1060 mouse_down_element_ = element; |
1031 } | 1061 } |
1032 | 1062 |
1033 void MouseEventManager::SetClickCount(int click_count) { | 1063 void MouseEventManager::SetClickCount(int click_count) { |
1034 click_count_ = click_count; | 1064 click_count_ = click_count; |
1035 } | 1065 } |
1036 | 1066 |
1037 bool MouseEventManager::MouseDownMayStartDrag() { | 1067 bool MouseEventManager::MouseDownMayStartDrag() { |
1038 return mouse_down_may_start_drag_; | 1068 return mouse_down_may_start_drag_; |
1039 } | 1069 } |
1040 | 1070 |
1041 } // namespace blink | 1071 } // namespace blink |
OLD | NEW |