LayoutTests/ChangeLog

 12010-09-17 Dimitri Glazkov <dglazkov@chromium.org>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Implement shadow DOM-aware event targeting and introduce EventContext to track the context of each event dispatch.
 6 https://bugs.webkit.org/show_bug.cgi?id=46015
 7
 8 * fast/events/shadow-boundary-crossing.html:
 9
1102010-09-17 Adam Roben <aroben@apple.com>
211
312 Land new Windows results for fast/forms/file-input-disabled.html

LayoutTests/fast/events/shadow-boundary-crossing.html

22<head>
33 <title></title>
44 <script type="text/javascript">
5  var fired = false;
 5 var success;
66
77 function selectStart(event)
88 {
9  fired = true;
 9 success = event.target.parentNode;
1010 }
1111
1212 function test()

2323 eventSender.mouseDown();
2424 eventSender.mouseUp();
2525
26  document.getElementById("result").innerText = fired ? "FAIL" : "PASS";
 26 document.getElementById("result").innerText = !success ? "FAIL" : "PASS";
2727 }
2828
2929 addEventListener("selectstart", selectStart, true);

WebCore/ChangeLog

 12010-09-17 Dimitri Glazkov <dglazkov@chromium.org>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Implement shadow DOM-aware event targeting and introduce EventContext to track the context of each event dispatch.
 6 https://bugs.webkit.org/show_bug.cgi?id=46015
 7
 8 * WebCore.xcodeproj/project.pbxproj:
 9 * dom/ContainerNode.cpp:
 10 (WebCore::notifyChildInserted):
 11 * dom/EventContext.cpp: Added.
 12 (WebCore::EventContext::EventContext):
 13 (WebCore::EventContext::ancestor):
 14 (WebCore::EventContext::target):
 15 (WebCore::eventTargetRespectingSVGTargetRules):
 16 (WebCore::EventContext::handleLocalEvents):
 17 (WebCore::WindowEventContext::WindowEventContext):
 18 (WebCore::WindowEventContext::window):
 19 (WebCore::WindowEventContext::target):
 20 (WebCore::WindowEventContext::handleLocalEvents):
 21 * dom/EventContext.h: Added.
 22 * dom/Node.cpp:
 23 (WebCore::eventTargetRespectingSVGTargetRules):
 24 (WebCore::Node::markAncestorsWithChildNeedsStyleRecalc):
 25 (WebCore::Node::createRendererIfNeeded):
 26 (WebCore::Node::parentOrHostNode):
 27 (WebCore::Node::enclosingLinkEventParentOrSelf):
 28 (WebCore::Node::eventAncestors):
 29 (WebCore::eventHasListeners):
 30 (WebCore::Node::dispatchGenericEvent):
 31 * dom/Node.h:
 32 * dom/Text.cpp:
 33 (WebCore::Text::createRenderer):
 34 * inspector/InspectorDOMAgent.cpp:
 35 (WebCore::InspectorDOMAgent::getEventListenersForNode):
 36 * page/EventHandler.cpp:
 37 (WebCore::EventHandler::updateMouseEventTargetNode):
 38 * svg/SVGElement.cpp:
 39 * svg/SVGElement.h:
 40
1412010-09-17 Tony Gentilcore <tonyg@chromium.org>
242
343 Reviewed by Adam Barth.

WebCore/WebCore.xcodeproj/project.pbxproj

831831 411046410FA222A600BA436A /* ScriptEventListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 4110463F0FA222A600BA436A /* ScriptEventListener.h */; };
832832 411046420FA222A600BA436A /* ScriptEventListener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 411046400FA222A600BA436A /* ScriptEventListener.cpp */; };
833833 4127D5370F8AAB1D00E424F5 /* ScriptState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4127D5360F8AAB1D00E424F5 /* ScriptState.cpp */; };
 834 4138D3351244054800323D33 /* EventContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 4138D3331244054800323D33 /* EventContext.h */; };
 835 4138D3361244054800323D33 /* EventContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4138D3341244054800323D33 /* EventContext.cpp */; };
834836 4162A450101145AE00DFF3ED /* DedicatedWorkerContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4162A44D101145AE00DFF3ED /* DedicatedWorkerContext.cpp */; };
835837 4162A451101145AE00DFF3ED /* DedicatedWorkerContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 4162A44E101145AE00DFF3ED /* DedicatedWorkerContext.h */; };
836838 4162A454101145E300DFF3ED /* JSDedicatedWorkerContextCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4162A453101145E300DFF3ED /* JSDedicatedWorkerContextCustom.cpp */; };

67166718 4110463F0FA222A600BA436A /* ScriptEventListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptEventListener.h; sourceTree = "<group>"; };
67176719 411046400FA222A600BA436A /* ScriptEventListener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptEventListener.cpp; sourceTree = "<group>"; };
67186720 4127D5360F8AAB1D00E424F5 /* ScriptState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptState.cpp; sourceTree = "<group>"; };
 6721 4138D3331244054800323D33 /* EventContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventContext.h; sourceTree = "<group>"; };
 6722 4138D3341244054800323D33 /* EventContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventContext.cpp; sourceTree = "<group>"; };
67196723 4162A44D101145AE00DFF3ED /* DedicatedWorkerContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DedicatedWorkerContext.cpp; path = workers/DedicatedWorkerContext.cpp; sourceTree = "<group>"; };
67206724 4162A44E101145AE00DFF3ED /* DedicatedWorkerContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DedicatedWorkerContext.h; path = workers/DedicatedWorkerContext.h; sourceTree = "<group>"; };
67216725 4162A44F101145AE00DFF3ED /* DedicatedWorkerContext.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = DedicatedWorkerContext.idl; path = workers/DedicatedWorkerContext.idl; sourceTree = "<group>"; };

1759517599 85031B2B0A44EFC700F992E0 /* Event.cpp */,
1759617600 85031B2C0A44EFC700F992E0 /* Event.h */,
1759717601 14E836D209F8512000B85AE4 /* Event.idl */,
 17602 4138D3341244054800323D33 /* EventContext.cpp */,
 17603 4138D3331244054800323D33 /* EventContext.h */,
1759817604 BC60D9090D2A17CE00B9918F /* EventException.h */,
1759917605 BC60D90A0D2A17CE00B9918F /* EventException.idl */,
1760017606 935FBC4409BA00B900E230B1 /* EventListener.h */,

1885818864 A8EA7EC00A1945D000A8EF5F /* EntityReference.h in Headers */,
1885918865 2ECF7AE210162B5800427DE7 /* ErrorEvent.h in Headers */,
1886018866 85031B420A44EFC700F992E0 /* Event.h in Headers */,
 18867 4138D3351244054800323D33 /* EventContext.h in Headers */,
1886118868 BC60D90C0D2A17CE00B9918F /* EventException.h in Headers */,
1886218869 93C09A530B064DB3005ABD4D /* EventHandler.h in Headers */,
1886318870 935FBC4509BA00B900E230B1 /* EventListener.h in Headers */,

2139821405 A8EA7EC10A1945D000A8EF5F /* EntityReference.cpp in Sources */,
2139921406 2ECF7AE110162B5800427DE7 /* ErrorEvent.cpp in Sources */,
2140021407 85031B410A44EFC700F992E0 /* Event.cpp in Sources */,
 21408 4138D3361244054800323D33 /* EventContext.cpp in Sources */,
2140121409 93C09A810B064F00005ABD4D /* EventHandler.cpp in Sources */,
2140221410 93C09A7F0B064EEF005ABD4D /* EventHandlerMac.mm in Sources */,
2140321411 1CA19E050DC255950065A994 /* EventLoopMac.mm in Sources */,

WebCore/dom/ContainerNode.cpp

@@static void notifyChildInserted(Node* child)
995995 RefPtr<Node> c = child;
996996 RefPtr<Document> document = child->document();
997997
998  if (c->parentNode() && c->parentNode()->inDocument())
 998 Node* parentOrHostNode = c->parentOrHostNode();
 999 if (parentOrHostNode && parentOrHostNode->inDocument())
9991000 c->insertedIntoDocument();
10001001 else
10011002 c->insertedIntoTree(true);

WebCore/dom/EventContext.cpp

 1/*
 2 * Copyright (C) 2010 Google Inc. All Rights Reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 *
 25 */
 26
 27#include "config.h"
 28#include "EventContext.h"
 29
 30#include "ContainerNode.h"
 31#include "DOMWindow.h"
 32#include "Event.h"
 33
 34#if ENABLE(SVG)
 35#include "SVGElementInstance.h"
 36#include "SVGUseElement.h"
 37#endif
 38
 39namespace WebCore {
 40
 41EventContext::EventContext(ContainerNode* ancestor, EventTarget* target)
 42 : m_ancestor(ancestor)
 43 , m_target(target)
 44{
 45}
 46
 47ContainerNode* EventContext::ancestor() const
 48{
 49 return m_ancestor.get();
 50}
 51
 52EventTarget* EventContext::target() const
 53{
 54 return m_target.get();
 55}
 56
 57static inline EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode)
 58{
 59 ASSERT(referenceNode);
 60
 61#if ENABLE(SVG)
 62 if (!referenceNode->isSVGElement())
 63 return referenceNode;
 64
 65 // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
 66 // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
 67 for (Node* n = referenceNode; n; n = n->parentNode()) {
 68 if (!n->isShadowNode() || !n->isSVGElement())
 69 continue;
 70
 71 ContainerNode* shadowTreeParentElement = n->shadowParentNode();
 72 ASSERT(shadowTreeParentElement->hasTagName(SVGNames::useTag));
 73
 74 if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode))
 75 return instance;
 76 }
 77#endif
 78
 79 return referenceNode;
 80}
 81
 82void EventContext::handleLocalEvents(Event* event) const
 83{
 84 event->setTarget(target());
 85 event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor()));
 86 m_ancestor->handleLocalEvents(event);
 87}
 88
 89WindowEventContext::WindowEventContext(Event* event, Node* node, const Vector<EventContext>& ancestors)
 90{
 91 // We don't dispatch load events to the window. That quirk was originally
 92 // added because Mozilla doesn't propagate load events to the window object.
 93 if (event->type() == eventNames().loadEvent)
 94 return;
 95
 96 EventTarget* targetForWindowEvents = node;
 97 Node* topLevelContainer = node;
 98 if (!ancestors.isEmpty()) {
 99 topLevelContainer = ancestors.last().ancestor();
 100 targetForWindowEvents = ancestors.last().target();
 101 }
 102 if (!topLevelContainer->isDocumentNode())
 103 return;
 104
 105 m_window = static_cast<Document*>(topLevelContainer)->domWindow();
 106 m_target = targetForWindowEvents;
 107}
 108
 109DOMWindow* WindowEventContext::window() const
 110{
 111 return m_window.get();
 112}
 113
 114EventTarget* WindowEventContext::target() const
 115{
 116 return m_target.get();
 117}
 118
 119bool WindowEventContext::handleLocalEvents(Event* event)
 120{
 121 if (!m_window)
 122 return false;
 123
 124 event->setTarget(target());
 125 event->setCurrentTarget(window());
 126 m_window->fireEventListeners(event);
 127 return true;
 128}
 129
 130}

WebCore/dom/EventContext.h

 1/*
 2 * Copyright (C) 2010 Google Inc. All Rights Reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 *
 25 */
 26
 27#ifndef EventContext_h
 28#define EventContext_h
 29
 30#include <wtf/RefPtr.h>
 31#include <wtf/Vector.h>
 32#include <wtf/text/AtomicString.h>
 33
 34namespace WebCore {
 35
 36class ContainerNode;
 37class DOMWindow;
 38class EventTarget;
 39class Event;
 40class Node;
 41
 42class EventContext {
 43public:
 44 EventContext(ContainerNode* ancestor, EventTarget* target);
 45
 46 ContainerNode* ancestor() const;
 47 EventTarget* target() const;
 48 void handleLocalEvents(Event*) const;
 49
 50private:
 51 RefPtr<ContainerNode> m_ancestor;
 52 RefPtr<EventTarget> m_target;
 53};
 54
 55class WindowEventContext {
 56public:
 57 WindowEventContext(Event*, Node*, const Vector<EventContext>& ancestors);
 58
 59 DOMWindow* window() const;
 60 EventTarget* target() const;
 61 bool handleLocalEvents(Event* event);
 62
 63private:
 64 RefPtr<DOMWindow> m_window;
 65 RefPtr<EventTarget> m_target;
 66};
 67
 68}
 69
 70#endif // EventContext_h

WebCore/dom/Node.cpp

4444#include "DynamicNodeList.h"
4545#include "Element.h"
4646#include "Event.h"
 47#include "EventContext.h"
4748#include "EventException.h"
4849#include "EventHandler.h"
4950#include "EventListener.h"

@@using namespace HTMLNames;
115116
116117static HashSet<Node*>* gNodesDispatchingSimulatedClicks = 0;
117118
 119static inline EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode)
 120{
 121 ASSERT(referenceNode);
 122
 123#if ENABLE(SVG)
 124 if (!referenceNode->isSVGElement())
 125 return referenceNode;
 126
 127 // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
 128 // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
 129 for (Node* n = referenceNode; n; n = n->parentNode()) {
 130 if (!n->isShadowNode() || !n->isSVGElement())
 131 continue;
 132
 133 ContainerNode* shadowTreeParentElement = n->shadowParentNode();
 134 ASSERT(shadowTreeParentElement->hasTagName(SVGNames::useTag));
 135
 136 if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode))
 137 return instance;
 138 }
 139#endif
 140
 141 return referenceNode;
 142}
 143
118144bool Node::isSupported(const String& feature, const String& version)
119145{
120146 return DOMImplementation::hasFeature(feature, version);

@@inline void Node::setStyleChange(StyleChangeType changeType)
720746
721747inline void Node::markAncestorsWithChildNeedsStyleRecalc()
722748{
723  for (Node* p = parentNode(); p && !p->childNeedsStyleRecalc(); p = p->parentNode())
 749 for (Node* p = parentOrHostNode(); p && !p->childNeedsStyleRecalc(); p = p->parentOrHostNode())
724750 p->setChildNeedsStyleRecalc();
725 
 751
726752 if (document()->childNeedsStyleRecalc())
727753 document()->scheduleStyleRecalc();
728754}

@@void Node::createRendererIfNeeded()
13191345
13201346 ASSERT(!renderer());
13211347
1322  Node* parent = parentNode();
 1348 Node* parent = parentOrHostNode();
13231349 ASSERT(parent);
13241350
13251351 RenderObject* parentRenderer = parent->renderer();

@@bool Node::isInShadowTree()
14421468 return false;
14431469}
14441470
 1471ContainerNode* Node::parentOrHostNode()
 1472{
 1473 if (ContainerNode* parent = parentNode())
 1474 return parent;
 1475 return shadowParentNode();
 1476}
 1477
14451478bool Node::isBlockFlow() const
14461479{
14471480 return renderer() && renderer()->isBlockFlow();

@@void Node::getSubresourceURLs(ListHashSet<KURL>& urls) const
22652298 addSubresourceAttributeURLs(urls);
22662299}
22672300
2268 ContainerNode* Node::eventParentNode()
2269 {
2270  return parentNode();
2271 }
2272 
22732301Node* Node::enclosingLinkEventParentOrSelf()
22742302{
2275  for (Node* node = this; node; node = node->eventParentNode()) {
 2303 for (Node* node = this; node; node = node->parentOrHostNode()) {
22762304 // For imagemaps, the enclosing link node is the associated area element not the image itself.
22772305 // So we don't let images be the enclosingLinkNode, even though isLink sometimes returns true
22782306 // for them.

@@void Node::handleLocalEvents(Event* event)
25102538 fireEventListeners(event);
25112539}
25122540
2513 #if ENABLE(SVG)
2514 static inline SVGElementInstance* eventTargetAsSVGElementInstance(Node* referenceNode)
2515 {
2516  ASSERT(referenceNode);
2517  if (!referenceNode->isSVGElement())
2518  return 0;
2519 
2520  // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
2521  // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
2522  for (Node* n = referenceNode; n; n = n->parentNode()) {
2523  if (!n->isShadowNode() || !n->isSVGElement())
2524  continue;
2525 
2526  ContainerNode* shadowTreeParentElement = n->shadowParentNode();
2527  ASSERT(shadowTreeParentElement->hasTagName(SVGNames::useTag));
2528 
2529  if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode))
2530  return instance;
2531  }
2532 
2533  return 0;
2534 }
2535 #endif
2536 
2537 static inline EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode)
2538 {
2539  ASSERT(referenceNode);
2540 
2541 #if ENABLE(SVG)
2542  if (SVGElementInstance* instance = eventTargetAsSVGElementInstance(referenceNode)) {
2543  ASSERT(instance->shadowTreeElement() == referenceNode);
2544  return instance;
2545  }
2546 #endif
2547 
2548  return referenceNode;
2549 }
2550 
2551 void Node::eventAncestors(Vector<RefPtr<ContainerNode> > &ancestors)
 2541void Node::eventAncestors(Vector<EventContext> &ancestors, EventTarget* originalTarget)
25522542{
25532543 if (inDocument()) {
2554  for (ContainerNode* ancestor = eventParentNode(); ancestor; ancestor = ancestor->eventParentNode()) {
 2544 // FIXME: Integrate better with SVG shadow stuff, which seems very similar.
 2545 EventTarget* target = isShadowNode() ? shadowParentNode() : originalTarget;
 2546 for (ContainerNode* ancestor = parentOrHostNode(); ancestor; ancestor = ancestor->parentOrHostNode()) {
25552547#if ENABLE(SVG)
25562548 // Skip <use> shadow tree elements.
25572549 if (ancestor->isSVGElement() && ancestor->isShadowNode())
25582550 continue;
25592551#endif
2560  ancestors.append(ancestor);
 2552 ancestors.append(EventContext(ancestor, target));
 2553 // FIXME: This is a bit ugly. We should eliminate these multiple calls to shadowParentNode()
 2554 if (ancestor->isShadowNode())
 2555 target = ancestor->shadowParentNode();
25612556 }
25622557 }
25632558}

@@bool Node::dispatchEvent(PassRefPtr<Event> prpEvent)
25732568 return dispatchGenericEvent(event.release());
25742569}
25752570
2576 static bool eventHasListeners(const AtomicString& eventType, DOMWindow* window, Node* node, Vector<RefPtr<ContainerNode> >& ancestors)
 2571static bool eventHasListeners(const AtomicString& eventType, DOMWindow* window, Node* node, const Vector<EventContext>& ancestors)
25772572{
25782573 if (window && window->hasEventListeners(eventType))
25792574 return true;

@@static bool eventHasListeners(const AtomicString& eventType, DOMWindow* window,
25822577 return true;
25832578
25842579 for (size_t i = 0; i < ancestors.size(); i++) {
2585  ContainerNode* ancestor = ancestors[i].get();
 2580 ContainerNode* ancestor = ancestors[i].ancestor();
25862581 if (ancestor->hasEventListeners(eventType))
25872582 return true;
25882583 }

@@bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent)
26022597 // If the node is not in a document just send the event to it.
26032598 // Be sure to ref all of nodes since event handlers could result in the last reference going away.
26042599 RefPtr<Node> thisNode(this);
2605  Vector<RefPtr<ContainerNode> > ancestors;
2606  eventAncestors(ancestors);
 2600 RefPtr<EventTarget> originalTarget(event->target());
 2601 Vector<EventContext> ancestors;
 2602 eventAncestors(ancestors, originalTarget.get());
26072603
2608  // Set up a pointer to indicate whether / where to dispatch window events.
2609  // We don't dispatch load events to the window. That quirk was originally
2610  // added because Mozilla doesn't propagate load events to the window object.
2611  DOMWindow* targetForWindowEvents = 0;
2612  if (event->type() != eventNames().loadEvent) {
2613  Node* topLevelContainer = ancestors.isEmpty() ? this : ancestors.last().get();
2614  if (topLevelContainer->isDocumentNode())
2615  targetForWindowEvents = static_cast<Document*>(topLevelContainer)->domWindow();
2616  }
 2604 WindowEventContext window(event.get(), this, ancestors);
26172605
26182606#if ENABLE(INSPECTOR)
26192607 Page* inspectedPage = InspectorTimelineAgent::instanceCount() ? document()->page() : 0;
26202608 if (inspectedPage) {
2621  if (InspectorTimelineAgent* timelineAgent = eventHasListeners(event->type(), targetForWindowEvents, this, ancestors) ? inspectedPage->inspectorTimelineAgent() : 0)
 2609 if (InspectorTimelineAgent* timelineAgent = eventHasListeners(event->type(), window.window(), this, ancestors) ? inspectedPage->inspectorTimelineAgent() : 0)
26222610 timelineAgent->willDispatchEvent(*event);
26232611 else
26242612 inspectedPage = 0;

@@bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent)
26332621 // Trigger capturing event handlers, starting at the top and working our way down.
26342622 event->setEventPhase(Event::CAPTURING_PHASE);
26352623
2636  if (targetForWindowEvents) {
2637  event->setCurrentTarget(targetForWindowEvents);
2638  targetForWindowEvents->fireEventListeners(event.get());
2639  if (event->propagationStopped())
2640  goto doneDispatching;
2641  }
 2624 if (window.handleLocalEvents(event.get()) && event->propagationStopped())
 2625 goto doneDispatching;
 2626
26422627 for (size_t i = ancestors.size(); i; --i) {
2643  ContainerNode* ancestor = ancestors[i - 1].get();
2644  event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor));
2645  ancestor->handleLocalEvents(event.get());
 2628 ancestors[i - 1].handleLocalEvents(event.get());
26462629 if (event->propagationStopped())
26472630 goto doneDispatching;
26482631 }
26492632
26502633 event->setEventPhase(Event::AT_TARGET);
2651 
 2634 event->setTarget(originalTarget.get());
26522635 event->setCurrentTarget(eventTargetRespectingSVGTargetRules(this));
26532636 handleLocalEvents(event.get());
26542637 if (event->propagationStopped())

@@bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent)
26602643
26612644 size_t size = ancestors.size();
26622645 for (size_t i = 0; i < size; ++i) {
2663  ContainerNode* ancestor = ancestors[i].get();
2664  event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor));
2665  ancestor->handleLocalEvents(event.get());
2666  if (event->propagationStopped() || event->cancelBubble())
2667  goto doneDispatching;
2668  }
2669  if (targetForWindowEvents) {
2670  event->setCurrentTarget(targetForWindowEvents);
2671  targetForWindowEvents->fireEventListeners(event.get());
 2646 ancestors[i].handleLocalEvents(event.get());
26722647 if (event->propagationStopped() || event->cancelBubble())
26732648 goto doneDispatching;
26742649 }
 2650 if (window.handleLocalEvents(event.get()) && (event->propagationStopped() || event->cancelBubble()))
 2651 goto doneDispatching;
26752652 }
26762653
26772654doneDispatching:
 2655 event->setTarget(originalTarget.get());
26782656 event->setCurrentTarget(0);
26792657 event->setEventPhase(0);
26802658

@@doneDispatching:
26952673 if (event->bubbles()) {
26962674 size_t size = ancestors.size();
26972675 for (size_t i = 0; i < size; ++i) {
2698  ContainerNode* ancestor = ancestors[i].get();
2699  ancestor->defaultEventHandler(event.get());
 2676 ancestors[i].ancestor()->defaultEventHandler(event.get());
27002677 ASSERT(!event->defaultPrevented());
27012678 if (event->defaultHandled())
27022679 goto doneWithDefault;

WebCore/dom/Node.h

@@class Document;
4949class DynamicNodeList;
5050class Element;
5151class Event;
 52class EventContext;
5253class EventListener;
5354class FloatPoint;
5455class Frame;

@@public:
212213 Node* shadowAncestorNode();
213214 Node* shadowTreeRootNode();
214215 bool isInShadowTree();
215 
216  // The node's parent for the purpose of event capture and bubbling.
217  virtual ContainerNode* eventParentNode();
 216 // Node's parent or shadow tree host.
 217 ContainerNode* parentOrHostNode();
218218
219219 // Returns the enclosing event parent node (or self) that, when clicked, would trigger a navigation.
220220 Node* enclosingLinkEventParentOrSelf();
221221
222  // Node ancestors when concerned about event flow
223  void eventAncestors(Vector<RefPtr<ContainerNode> > &ancestors);
 222 // Node ancestors when concerned about event flow.
 223 void eventAncestors(Vector<EventContext> &ancestors, EventTarget*);
224224
225225 bool isBlockFlow() const;
226226 bool isBlockFlowOrBlockTable() const;

WebCore/dom/Text.cpp

@@bool Text::rendererIsNeeded(RenderStyle *style)
237237
238238RenderObject* Text::createRenderer(RenderArena* arena, RenderStyle*)
239239{
 240 Node* parentOrHost = parentOrHostNode();
240241#if ENABLE(SVG)
241  if (parentNode()->isSVGElement()
 242 if (parentOrHost->isSVGElement()
242243#if ENABLE(SVG_FOREIGN_OBJECT)
243  && !parentNode()->hasTagName(SVGNames::foreignObjectTag)
 244 && !parentOrHost->hasTagName(SVGNames::foreignObjectTag)
244245#endif
245246 )
246247 return new (arena) RenderSVGInlineText(this, dataImpl());

WebCore/inspector/InspectorDOMAgent.cpp

5050#include "Document.h"
5151#include "DocumentType.h"
5252#include "Event.h"
 53#include "EventContext.h"
5354#include "EventListener.h"
5455#include "EventNames.h"
5556#include "EventTarget.h"

@@void InspectorDOMAgent::getEventListenersForNode(long nodeId, long* outNodeId, R
594595 return;
595596
596597 // The Node's Event Ancestors (not including self)
597  Vector<RefPtr<ContainerNode> > ancestors;
598  node->eventAncestors(ancestors);
 598 Vector<EventContext> ancestors;
 599 node->eventAncestors(ancestors, node);
599600
600601 // Nodes and their Listeners for the concerned event types (order is top to bottom)
601602 Vector<EventListenerInfo> eventInformation;
602603 for (size_t i = ancestors.size(); i; --i) {
603  ContainerNode* ancestor = ancestors[i - 1].get();
 604 ContainerNode* ancestor = ancestors[i - 1].ancestor();
604605 for (size_t j = 0; j < eventTypesLength; ++j) {
605606 AtomicString& type = eventTypes[j];
606607 if (ancestor->hasEventListeners(type))

WebCore/page/EventHandler.cpp

@@void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo
17631763 // If the target node is a text node, dispatch on the parent node - rdar://4196646
17641764 if (result && result->isTextNode())
17651765 result = result->parentNode();
 1766 // FIXME: Implement proper re-targeting of events inside of the shadow tree.
17661767 if (result)
17671768 result = result->shadowAncestorNode();
17681769 }

WebCore/svg/SVGElement.cpp

@@void SVGElement::updateAnimatedSVGAttribute(const QualifiedName& name) const
332332 clearIsSynchronizingSVGAttributes();
333333}
334334
335 ContainerNode* SVGElement::eventParentNode()
336 {
337  if (ContainerNode* shadowParent = shadowParentNode())
338  return shadowParent;
339  return StyledElement::eventParentNode();
340 }
341 
342335}
343336
344337#endif // ENABLE(SVG)

WebCore/svg/SVGElement.h

@@namespace WebCore {
9696
9797 virtual bool isSupported(StringImpl* feature, StringImpl* version) const;
9898
99  virtual ContainerNode* eventParentNode();
100 
10199 virtual bool needsPendingResourceHandling() const { return true; }
102100 virtual void buildPendingResource() { }
103101