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

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

Powered by Google App Engine
This is Rietveld 408576698