Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(709)

Side by Side Diff: third_party/WebKit/Source/core/input/PointerEventManager.cpp

Issue 2255323004: Create MouseEventManager and EventHandlingUtil (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Applying comments Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/PointerEventManager.h" 5 #include "core/input/PointerEventManager.h"
6 6
7 #include "core/dom/ElementTraversal.h" 7 #include "core/dom/ElementTraversal.h"
8 #include "core/dom/shadow/FlatTreeTraversal.h" 8 #include "core/dom/shadow/FlatTreeTraversal.h"
9 #include "core/events/MouseEvent.h" 9 #include "core/events/MouseEvent.h"
10 #include "core/frame/FrameView.h" 10 #include "core/frame/FrameView.h"
11 #include "core/frame/UseCounter.h" 11 #include "core/frame/UseCounter.h"
12 #include "core/html/HTMLCanvasElement.h" 12 #include "core/html/HTMLCanvasElement.h"
13 #include "core/input/EventHandler.h" 13 #include "core/input/EventHandler.h"
14 #include "core/input/EventHandlingUtil.h"
15 #include "core/input/MouseEventManager.h"
14 #include "core/input/TouchActionUtil.h" 16 #include "core/input/TouchActionUtil.h"
15 #include "core/layout/HitTestCanvasResult.h" 17 #include "core/layout/HitTestCanvasResult.h"
16 #include "core/page/ChromeClient.h" 18 #include "core/page/ChromeClient.h"
17 #include "core/page/Page.h" 19 #include "core/page/Page.h"
18 #include "platform/PlatformTouchEvent.h" 20 #include "platform/PlatformTouchEvent.h"
19 21
20 namespace blink { 22 namespace blink {
21 23
22 namespace { 24 namespace {
23 25
(...skipping 16 matching lines...) Expand all
40 NOTREACHED(); 42 NOTREACHED();
41 return emptyAtom; 43 return emptyAtom;
42 } 44 }
43 } 45 }
44 46
45 bool isInDocument(EventTarget* n) 47 bool isInDocument(EventTarget* n)
46 { 48 {
47 return n && n->toNode() && n->toNode()->isConnected(); 49 return n && n->toNode() && n->toNode()->isConnected();
48 } 50 }
49 51
50 WebInputEventResult dispatchMouseEvent(
51 EventTarget* target,
52 const AtomicString& mouseEventType,
53 const PlatformMouseEvent& mouseEvent,
54 EventTarget* relatedTarget,
55 int detail = 0,
56 bool checkForListener = false)
57 {
58 if (target && target->toNode()
59 && (!checkForListener || target->hasEventListeners(mouseEventType))) {
60 Node* targetNode = target->toNode();
61 MouseEvent* event = MouseEvent::create(mouseEventType,
62 targetNode->document().domWindow(), mouseEvent, detail,
63 relatedTarget ? relatedTarget->toNode() : nullptr);
64 DispatchEventResult dispatchResult = target->dispatchEvent(event);
65 return EventHandler::toWebInputEventResult(dispatchResult);
66 }
67 return WebInputEventResult::NotHandled;
68 }
69
70 PlatformMouseEvent mouseEventWithRegion(Node* node, const PlatformMouseEvent& mo useEvent)
71 {
72 if (!node->isElementNode())
73 return mouseEvent;
74
75 Element* element = toElement(node);
76 if (!element->isInCanvasSubtree())
77 return mouseEvent;
78
79 HTMLCanvasElement* canvas = Traversal<HTMLCanvasElement>::firstAncestorOrSel f(*element);
80 // In this case, the event target is canvas and mouse rerouting doesn't happ en.
81 if (canvas == element)
82 return mouseEvent;
83 String region = canvas->getIdFromControl(element);
84 PlatformMouseEvent newMouseEvent = mouseEvent;
85 newMouseEvent.setRegion(region);
86 return newMouseEvent;
87 }
88
89 void buildAncestorChain(
90 EventTarget* target,
91 HeapVector<Member<Node>, 20>* ancestors)
92 {
93 if (!isInDocument(target))
94 return;
95 Node* targetNode = target->toNode();
96 DCHECK(targetNode);
97 targetNode->updateDistribution();
98 // Index 0 element in the ancestors arrays will be the corresponding
99 // target. So the root of their document will be their last element.
100 for (Node* node = targetNode; node; node = FlatTreeTraversal::parent(*node))
101 ancestors->append(node);
102 }
103
104 void buildAncestorChainsAndFindCommonAncestors(
105 EventTarget* exitedTarget, EventTarget* enteredTarget,
106 HeapVector<Member<Node>, 20>* exitedAncestorsOut,
107 HeapVector<Member<Node>, 20>* enteredAncestorsOut,
108 size_t* exitedAncestorsCommonParentIndexOut,
109 size_t* enteredAncestorsCommonParentIndexOut)
110 {
111 DCHECK(exitedAncestorsOut);
112 DCHECK(enteredAncestorsOut);
113 DCHECK(exitedAncestorsCommonParentIndexOut);
114 DCHECK(enteredAncestorsCommonParentIndexOut);
115
116 buildAncestorChain(exitedTarget, exitedAncestorsOut);
117 buildAncestorChain(enteredTarget, enteredAncestorsOut);
118
119 *exitedAncestorsCommonParentIndexOut = exitedAncestorsOut->size();
120 *enteredAncestorsCommonParentIndexOut = enteredAncestorsOut->size();
121 while (*exitedAncestorsCommonParentIndexOut > 0
122 && *enteredAncestorsCommonParentIndexOut > 0) {
123 if ((*exitedAncestorsOut)[(*exitedAncestorsCommonParentIndexOut)-1]
124 != (*enteredAncestorsOut)[(*enteredAncestorsCommonParentIndexOut)-1] )
125 break;
126 (*exitedAncestorsCommonParentIndexOut)--;
127 (*enteredAncestorsCommonParentIndexOut)--;
128 }
129 }
130
131 } // namespace 52 } // namespace
132 53
54 PointerEventManager::PointerEventBoundaryEventDispatcher::PointerEventBoundaryEv entDispatcher(
55 PointerEventManager* pointerEventManager,
56 PointerEvent* pointerEvent)
57 : m_pointerEventManager(pointerEventManager)
58 , m_pointerEvent(pointerEvent)
59 {
60 }
61
62 void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatchOut(
63 EventTarget* target, EventTarget* relatedTarget)
64 {
65 dispatch(target, relatedTarget, EventTypeNames::pointerout, false);
66 }
67
68 void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatchOver(
69 EventTarget* target, EventTarget* relatedTarget)
70 {
71 dispatch(target, relatedTarget, EventTypeNames::pointerover, false);
72 }
73
74 void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatchLeave(
75 EventTarget* target, EventTarget* relatedTarget, bool checkForListener)
76 {
77 dispatch(target, relatedTarget, EventTypeNames::pointerleave, checkForListen er);
78 }
79
80 void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatchEnter(
81 EventTarget* target, EventTarget* relatedTarget, bool checkForListener)
82 {
83 dispatch(target, relatedTarget, EventTypeNames::pointerenter, checkForListen er);
84 }
85
86 AtomicString PointerEventManager::PointerEventBoundaryEventDispatcher::getLeaveE vent()
87 {
88 return EventTypeNames::pointerleave;
89 }
90
91 AtomicString PointerEventManager::PointerEventBoundaryEventDispatcher::getEnterE vent()
92 {
93 return EventTypeNames::pointerenter;
94 }
95
96 void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatch(
97 EventTarget* target, EventTarget* relatedTarget, const AtomicString& type,
98 bool checkForListener)
99 {
100 m_pointerEventManager->dispatchPointerEvent(target,
101 m_pointerEventManager->m_pointerEventFactory.createPointerBoundaryEvent(
102 m_pointerEvent, type, relatedTarget),
103 checkForListener);
104 }
105
133 WebInputEventResult PointerEventManager::dispatchPointerEvent( 106 WebInputEventResult PointerEventManager::dispatchPointerEvent(
134 EventTarget* target, 107 EventTarget* target,
135 PointerEvent* pointerEvent, 108 PointerEvent* pointerEvent,
136 bool checkForListener) 109 bool checkForListener)
137 { 110 {
138 if (!target) 111 if (!target)
139 return WebInputEventResult::NotHandled; 112 return WebInputEventResult::NotHandled;
140 113
141 // Set whether node under pointer has received pointerover or not. 114 // Set whether node under pointer has received pointerover or not.
142 const int pointerId = pointerEvent->pointerId(); 115 const int pointerId = pointerEvent->pointerId();
(...skipping 11 matching lines...) Expand all
154 } 127 }
155 128
156 if (!RuntimeEnabledFeatures::pointerEventEnabled()) 129 if (!RuntimeEnabledFeatures::pointerEventEnabled())
157 return WebInputEventResult::NotHandled; 130 return WebInputEventResult::NotHandled;
158 if (!checkForListener || target->hasEventListeners(eventType)) { 131 if (!checkForListener || target->hasEventListeners(eventType)) {
159 UseCounter::count(m_frame->document(), UseCounter::PointerEventDispatch) ; 132 UseCounter::count(m_frame->document(), UseCounter::PointerEventDispatch) ;
160 if (eventType == EventTypeNames::pointerdown) 133 if (eventType == EventTypeNames::pointerdown)
161 UseCounter::count(m_frame->document(), UseCounter::PointerEventDispa tchPointerDown); 134 UseCounter::count(m_frame->document(), UseCounter::PointerEventDispa tchPointerDown);
162 135
163 DispatchEventResult dispatchResult = target->dispatchEvent(pointerEvent) ; 136 DispatchEventResult dispatchResult = target->dispatchEvent(pointerEvent) ;
164 return EventHandler::toWebInputEventResult(dispatchResult); 137 return EventHandlingUtil::toWebInputEventResult(dispatchResult);
165 } 138 }
166 return WebInputEventResult::NotHandled; 139 return WebInputEventResult::NotHandled;
167 } 140 }
168 141
169 EventTarget* PointerEventManager::getEffectiveTargetForPointerEvent( 142 EventTarget* PointerEventManager::getEffectiveTargetForPointerEvent(
170 EventTarget* target, int pointerId) 143 EventTarget* target, int pointerId)
171 { 144 {
172 if (EventTarget* capturingTarget = getCapturingNode(pointerId)) 145 if (EventTarget* capturingTarget = getCapturingNode(pointerId))
173 return capturingTarget; 146 return capturingTarget;
174 return target; 147 return target;
(...skipping 23 matching lines...) Expand all
198 mouseEvent.pointerProperties().pointerType)] = false; 171 mouseEvent.pointerProperties().pointerType)] = false;
199 } 172 }
200 173
201 processCaptureAndPositionOfPointerEvent(dummyPointerEvent, enteredNode, 174 processCaptureAndPositionOfPointerEvent(dummyPointerEvent, enteredNode,
202 exitedNode, mouseEvent, true, isFrameBoundaryTransition); 175 exitedNode, mouseEvent, true, isFrameBoundaryTransition);
203 } 176 }
204 177
205 void PointerEventManager::sendBoundaryEvents( 178 void PointerEventManager::sendBoundaryEvents(
206 EventTarget* exitedTarget, 179 EventTarget* exitedTarget,
207 EventTarget* enteredTarget, 180 EventTarget* enteredTarget,
208 PointerEvent* pointerEvent, 181 PointerEvent* pointerEvent)
209 const PlatformMouseEvent& mouseEvent, bool sendMouseEvent)
210 { 182 {
211 if (exitedTarget == enteredTarget) 183 PointerEventBoundaryEventDispatcher boundaryEventDispatcher(this, pointerEve nt);
212 return; 184 boundaryEventDispatcher.sendBoundaryEvents(exitedTarget, enteredTarget);
213
214 // Dispatch pointerout/mouseout events
215 if (isInDocument(exitedTarget)) {
216 if (!sendMouseEvent) {
217 dispatchPointerEvent(exitedTarget, m_pointerEventFactory.createPoint erBoundaryEvent(
218 pointerEvent, EventTypeNames::pointerout, enteredTarget));
219 } else {
220 dispatchMouseEvent(exitedTarget,
221 EventTypeNames::mouseout,
222 mouseEventWithRegion(exitedTarget->toNode(), mouseEvent),
223 enteredTarget);
224 }
225 }
226
227 // Create lists of all exited/entered ancestors, locate the common ancestor
228 // Based on httparchive, in more than 97% cases the depth of DOM is less
229 // than 20.
230 HeapVector<Member<Node>, 20> exitedAncestors;
231 HeapVector<Member<Node>, 20> enteredAncestors;
232 size_t exitedAncestorsCommonParentIndex = 0;
233 size_t enteredAncestorsCommonParentIndex = 0;
234
235 // A note on mouseenter and mouseleave: These are non-bubbling events, and t hey are dispatched if there
236 // is a capturing event handler on an ancestor or a normal event handler on the element itself. This special
237 // handling is necessary to avoid O(n^2) capturing event handler checks.
238 //
239 // Note, however, that this optimization can possibly cause some unanswere d/missing/redundant mouseenter or
240 // mouseleave events in certain contrived eventhandling scenarios, e.g., whe n:
241 // - the mouseleave handler for a node sets the only capturing-mouseleave-li stener in its ancestor, or
242 // - DOM mods in any mouseenter/mouseleave handler changes the common ancest or of exited & entered nodes, etc.
243 // We think the spec specifies a "frozen" state to avoid such corner cases ( check the discussion on "candidate event
244 // listeners" at http://www.w3.org/TR/uievents), but our code below preserve s one such behavior from past only to
245 // match Firefox and IE behavior.
246 //
247 // TODO(mustaq): Confirm spec conformance, double-check with other browsers.
248
249 buildAncestorChainsAndFindCommonAncestors(
250 exitedTarget, enteredTarget,
251 &exitedAncestors, &enteredAncestors,
252 &exitedAncestorsCommonParentIndex, &enteredAncestorsCommonParentIndex);
253
254 bool exitedNodeHasCapturingAncestor = false;
255 for (size_t j = 0; j < exitedAncestors.size(); j++) {
256 if (exitedAncestors[j]->hasCapturingEventListeners(EventTypeNames::mouse leave)
257 || (RuntimeEnabledFeatures::pointerEventEnabled()
258 && exitedAncestors[j]->hasCapturingEventListeners(EventTypeNames::po interleave)))
259 exitedNodeHasCapturingAncestor = true;
260 }
261
262 // Dispatch pointerleave/mouseleave events, in child-to-parent order.
263 for (size_t j = 0; j < exitedAncestorsCommonParentIndex; j++) {
264 if (!sendMouseEvent) {
265 dispatchPointerEvent(exitedAncestors[j].get(),
266 m_pointerEventFactory.createPointerBoundaryEvent(
267 pointerEvent, EventTypeNames::pointerleave, enteredTarget),
268 !exitedNodeHasCapturingAncestor);
269 } else {
270 dispatchMouseEvent(exitedAncestors[j].get(),
271 EventTypeNames::mouseleave,
272 mouseEventWithRegion(exitedTarget->toNode(), mouseEvent),
273 enteredTarget, 0, !exitedNodeHasCapturingAncestor);
274 }
275 }
276
277 // Dispatch pointerover/mouseover.
278 if (isInDocument(enteredTarget)) {
279 if (!sendMouseEvent) {
280 dispatchPointerEvent(enteredTarget, m_pointerEventFactory.createPoin terBoundaryEvent(
281 pointerEvent, EventTypeNames::pointerover, exitedTarget));
282 } else {
283 dispatchMouseEvent(enteredTarget,
284 EventTypeNames::mouseover, mouseEvent, exitedTarget);
285 }
286 }
287
288 // Defer locating capturing pointeenter/mouseenter listener until /after/ di spatching the leave events because
289 // the leave handlers might set a capturing enter handler.
290 bool enteredNodeHasCapturingAncestor = false;
291 for (size_t i = 0; i < enteredAncestors.size(); i++) {
292 if (enteredAncestors[i]->hasCapturingEventListeners(EventTypeNames::mous eenter)
293 || (RuntimeEnabledFeatures::pointerEventEnabled()
294 && enteredAncestors[i]->hasCapturingEventListeners(EventTypeNames::p ointerenter)))
295 enteredNodeHasCapturingAncestor = true;
296 }
297
298 // Dispatch pointerenter/mouseenter events, in parent-to-child order.
299 for (size_t i = enteredAncestorsCommonParentIndex; i > 0; i--) {
300 if (!sendMouseEvent) {
301 dispatchPointerEvent(enteredAncestors[i-1].get(),
302 m_pointerEventFactory.createPointerBoundaryEvent(
303 pointerEvent, EventTypeNames::pointerenter, exitedTarget),
304 !enteredNodeHasCapturingAncestor);
305 } else {
306 dispatchMouseEvent(enteredAncestors[i-1].get(),
307 EventTypeNames::mouseenter, mouseEvent, exitedTarget,
308 0, !enteredNodeHasCapturingAncestor);
309 }
310 }
311 } 185 }
312 186
313 void PointerEventManager::setNodeUnderPointer( 187 void PointerEventManager::setNodeUnderPointer(
314 PointerEvent* pointerEvent, 188 PointerEvent* pointerEvent,
315 EventTarget* target) 189 EventTarget* target)
316 { 190 {
317 if (m_nodeUnderPointer.contains(pointerEvent->pointerId())) { 191 if (m_nodeUnderPointer.contains(pointerEvent->pointerId())) {
318 EventTargetAttributes node = m_nodeUnderPointer.get( 192 EventTargetAttributes node = m_nodeUnderPointer.get(
319 pointerEvent->pointerId()); 193 pointerEvent->pointerId());
320 if (!target) { 194 if (!target) {
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 // Event path could be null if pointer event is not dispatched and 443 // Event path could be null if pointer event is not dispatched and
570 // that happens for example when pointer event feature is not enabled. 444 // that happens for example when pointer event feature is not enabled.
571 if (!isInDocument(mouseTarget) && pointerEvent->hasEventPath()) { 445 if (!isInDocument(mouseTarget) && pointerEvent->hasEventPath()) {
572 for (size_t i = 0; i < pointerEvent->eventPath().size(); i++) { 446 for (size_t i = 0; i < pointerEvent->eventPath().size(); i++) {
573 if (isInDocument(pointerEvent->eventPath()[i].node())) { 447 if (isInDocument(pointerEvent->eventPath()[i].node())) {
574 mouseTarget = pointerEvent->eventPath()[i].node(); 448 mouseTarget = pointerEvent->eventPath()[i].node();
575 break; 449 break;
576 } 450 }
577 } 451 }
578 } 452 }
579 result = EventHandler::mergeEventResult(result, 453 result = EventHandlingUtil::mergeEventResult(result,
580 dispatchMouseEvent(mouseTarget, mouseEventType, mouseEvent, 454 m_mouseEventManager->dispatchMouseEvent(mouseTarget, mouseEventType,
581 nullptr, clickCount)); 455 mouseEvent, nullptr, clickCount));
582 } 456 }
583 457
584 if (pointerEvent->type() == EventTypeNames::pointerup 458 if (pointerEvent->type() == EventTypeNames::pointerup
585 || pointerEvent->type() == EventTypeNames::pointercancel) { 459 || pointerEvent->type() == EventTypeNames::pointercancel) {
586 460
587 releasePointerCapture(pointerEvent->pointerId()); 461 releasePointerCapture(pointerEvent->pointerId());
588 // Send got/lostpointercapture rightaway if necessary. 462 // Send got/lostpointercapture rightaway if necessary.
589 processPendingPointerCapture(pointerEvent); 463 processPendingPointerCapture(pointerEvent);
590 464
591 if (pointerEvent->isPrimary()) { 465 if (pointerEvent->isPrimary()) {
592 m_preventMouseEventForPointerType[toPointerTypeIndex( 466 m_preventMouseEventForPointerType[toPointerTypeIndex(
593 mouseEvent.pointerProperties().pointerType)] = false; 467 mouseEvent.pointerProperties().pointerType)] = false;
594 } 468 }
595 } 469 }
596 470
597 return result; 471 return result;
598 } 472 }
599 473
600 PointerEventManager::PointerEventManager(LocalFrame* frame) 474 PointerEventManager::PointerEventManager(LocalFrame* frame,
601 : m_frame(frame) 475 MouseEventManager* mouseEventManager)
602 , m_touchEventManager(frame) 476 : m_frame(frame)
477 , m_touchEventManager(frame)
478 , m_mouseEventManager(mouseEventManager)
603 { 479 {
604 clear(); 480 clear();
605 } 481 }
606 482
607 PointerEventManager::~PointerEventManager() 483 PointerEventManager::~PointerEventManager()
608 { 484 {
609 } 485 }
610 486
611 void PointerEventManager::clear() 487 void PointerEventManager::clear()
612 { 488 {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 processPendingPointerCapture(pointerEvent); 527 processPendingPointerCapture(pointerEvent);
652 528
653 PointerCapturingMap::const_iterator it = m_pointerCaptureTarget.find(poi nterEvent->pointerId()); 529 PointerCapturingMap::const_iterator it = m_pointerCaptureTarget.find(poi nterEvent->pointerId());
654 if (EventTarget* pointercaptureTarget = (it != m_pointerCaptureTarget.en d()) ? it->value : nullptr) 530 if (EventTarget* pointercaptureTarget = (it != m_pointerCaptureTarget.en d()) ? it->value : nullptr)
655 hitTestTarget = pointercaptureTarget; 531 hitTestTarget = pointercaptureTarget;
656 532
657 setNodeUnderPointer(pointerEvent, hitTestTarget); 533 setNodeUnderPointer(pointerEvent, hitTestTarget);
658 } 534 }
659 if (sendMouseEvent) { 535 if (sendMouseEvent) {
660 // lastNodeUnderMouse is needed here because it is still stored in Event Handler. 536 // lastNodeUnderMouse is needed here because it is still stored in Event Handler.
661 sendBoundaryEvents(lastNodeUnderMouse, hitTestTarget, 537 m_mouseEventManager->sendBoundaryEvents(lastNodeUnderMouse,
662 pointerEvent, mouseEvent, true); 538 hitTestTarget, mouseEvent);
663 } 539 }
664 return hitTestTarget; 540 return hitTestTarget;
665 } 541 }
666 542
667 void PointerEventManager::processPendingPointerCapture( 543 void PointerEventManager::processPendingPointerCapture(
668 PointerEvent* pointerEvent) 544 PointerEvent* pointerEvent)
669 { 545 {
670 EventTarget* pointerCaptureTarget; 546 EventTarget* pointerCaptureTarget;
671 EventTarget* pendingPointerCaptureTarget; 547 EventTarget* pendingPointerCaptureTarget;
672 const int pointerId = pointerEvent->pointerId(); 548 const int pointerId = pointerEvent->pointerId();
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
810 { 686 {
811 visitor->trace(m_frame); 687 visitor->trace(m_frame);
812 visitor->trace(m_nodeUnderPointer); 688 visitor->trace(m_nodeUnderPointer);
813 visitor->trace(m_pointerCaptureTarget); 689 visitor->trace(m_pointerCaptureTarget);
814 visitor->trace(m_pendingPointerCaptureTarget); 690 visitor->trace(m_pendingPointerCaptureTarget);
815 visitor->trace(m_touchEventManager); 691 visitor->trace(m_touchEventManager);
816 } 692 }
817 693
818 694
819 } // namespace blink 695 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698