bool EventDispatcher::dispatchEvent(Node* origin, PassRefPtr<Event> prpEvent) { ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden()); if (!prpEvent) return true; ASSERT(origin); RefPtr<Node> node(origin); RefPtr<Event> event(prpEvent); RefPtr<FrameView> view = node->document().view(); EventPath eventPath(*node, *event); if (EventTarget* relatedTarget = event->relatedTarget()) eventPath.setRelatedTarget(*node, *relatedTarget); #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS) if (is<TouchEvent>(*event)) { if (!eventPath.updateTouchLists(downcast<TouchEvent>(*event))) return true; } #endif ChildNodesLazySnapshot::takeChildNodesLazySnapshot(); EventTarget* target = eventTargetRespectingTargetRules(*node); event->setTarget(target); if (!event->target()) return true; ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden()); WindowEventContext windowEventContext(node.get(), eventPath.lastContextIfExists()); InputElementClickState clickHandlingState; if (is<HTMLInputElement>(*node)) downcast<HTMLInputElement>(*node).willDispatchEvent(*event, clickHandlingState); if (!event->propagationStopped() && !eventPath.isEmpty()) dispatchEventInDOM(*event, eventPath, windowEventContext); event->setTarget(eventTargetRespectingTargetRules(*node)); event->setCurrentTarget(nullptr); event->setEventPhase(0); if (clickHandlingState.stateful) downcast<HTMLInputElement>(*node).didDispatchClickEvent(*event, clickHandlingState); // Call default event handlers. While the DOM does have a concept of preventing // default handling, the detail of which handlers are called is an internal // implementation detail and not part of the DOM. if (!event->defaultPrevented() && !event->defaultHandled()) callDefaultEventHandlersInTheBubblingOrder(*event, eventPath); // Ensure that after event dispatch, the event's target object is the // outermost shadow DOM boundary. event->setTarget(windowEventContext.target()); event->setCurrentTarget(0); return !event->defaultPrevented(); }
void EventPath::buildRelatedNodeMap(const Node* relatedNode, RelatedTargetMap& relatedTargetMap) { TreeScope* lastTreeScope = 0; EventPath eventPath(const_cast<Node*>(relatedNode)); for (size_t i = 0; i < eventPath.size(); ++i) { TreeScope* treeScope = &eventPath[i].node()->treeScope(); if (treeScope != lastTreeScope) relatedTargetMap.add(treeScope, eventPath[i].target()); lastTreeScope = treeScope; } }
Element* TreeScope::adjustedFocusedElement() const { Document& document = rootNode().document(); Element* element = document.focusedElement(); if (!element) return 0; EventPath eventPath(element); for (size_t i = 0; i < eventPath.size(); ++i) { if (eventPath[i].node() == rootNode()) { // eventPath.at(i).target() is one of the followings: // - InsertionPoint // - shadow host // - Document::focusedElement() // So, it's safe to do toElement(). return toElement(eventPath[i].target()->toNode()); } } return 0; }
Node* EventPath::parent(Node* node) { EventPath eventPath(node); return eventPath.size() > 1 ? eventPath[1].node() : 0; }