2011-03-26 Dimitri Glazkov <dglazkov@chromium.org>
authordglazkov@chromium.org <dglazkov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 28 Mar 2011 17:01:21 +0000 (17:01 +0000)
committerdglazkov@chromium.org <dglazkov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 28 Mar 2011 17:01:21 +0000 (17:01 +0000)
        Reviewed by Eric Seidel.

        Introduce EventDispatcher, the new common way to fire events.
        https://bugs.webkit.org/show_bug.cgi?id=57168

        The goal here is two-fold:
        1) reduce the need to randomly sprinkle guards around the dispatch code
        by creating a well-scoped abstraction for dispatching events.
        2) create a place where fiddly event-related things like creating event
        contexts for ancestors can be done lazily.

        Additionally, with all the free-standing static functions, this code was
        just begging to come out of Node.cpp.

        The first step is a near-mechanical extraction of mouse-related events
        from Node.cpp to EventDispatcher. For now, the call sites are just
        replaced with invoking EventDispatcher. Later, we can remove these methods
        from Node.

        Refactoring, no functional changes.

        * Android.mk: Added EventDispatcher to build system.
        * CMakeLists.txt: Ditto.
        * GNUmakefile.am: Ditto.
        * WebCore.gypi: Ditto.
        * WebCore.pro: Ditto.
        * WebCore.vcproj/WebCore.vcproj: Ditto.
        * WebCore.xcodeproj/project.pbxproj: Ditto.
        * dom/DOMAllInOne.cpp: Ditto.
        * dom/EventDispatcher.cpp: Added.
        * dom/EventDispatcher.h: Added.
        * dom/Node.cpp:
        (WebCore::Node::dispatchScopedEvent): Replaced to use EventDispatcher.
        (WebCore::Node::dispatchEvent): Ditto.
        (WebCore::Node::dispatchMouseEvent): Ditto.
        (WebCore::Node::dispatchSimulatedClick): Ditto.
        * dom/Node.h: Updated decls.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@82127 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
Source/WebCore/Android.mk
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.am
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.pro
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/dom/DOMAllInOne.cpp
Source/WebCore/dom/EventDispatcher.cpp [new file with mode: 0644]
Source/WebCore/dom/EventDispatcher.h [new file with mode: 0644]
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h

index 1a84190..ed33ace 100644 (file)
@@ -131,6 +131,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
        dom/ErrorEvent.cpp \
        dom/Event.cpp \
        dom/EventContext.cpp \
+       dom/EventDispatcher.cpp \
        dom/EventNames.cpp \
        dom/EventTarget.cpp \
        dom/EventQueue.cpp \
index c50bc27..226572d 100644 (file)
@@ -561,6 +561,7 @@ SET(WebCore_SOURCES
     dom/ErrorEvent.cpp
     dom/Event.cpp
     dom/EventContext.cpp
+    dom/EventDispatcher.cpp
     dom/EventNames.cpp
     dom/EventTarget.cpp
     dom/EventQueue.cpp
index e37c76b..8584194 100644 (file)
@@ -1,3 +1,43 @@
+2011-03-26  Dimitri Glazkov  <dglazkov@chromium.org>
+
+        Reviewed by Eric Seidel.
+
+        Introduce EventDispatcher, the new common way to fire events.
+        https://bugs.webkit.org/show_bug.cgi?id=57168
+
+        The goal here is two-fold:
+        1) reduce the need to randomly sprinkle guards around the dispatch code
+        by creating a well-scoped abstraction for dispatching events.
+        2) create a place where fiddly event-related things like creating event
+        contexts for ancestors can be done lazily.
+
+        Additionally, with all the free-standing static functions, this code was
+        just begging to come out of Node.cpp.
+
+        The first step is a near-mechanical extraction of mouse-related events
+        from Node.cpp to EventDispatcher. For now, the call sites are just
+        replaced with invoking EventDispatcher. Later, we can remove these methods
+        from Node.
+
+        Refactoring, no functional changes.
+
+        * Android.mk: Added EventDispatcher to build system.
+        * CMakeLists.txt: Ditto.
+        * GNUmakefile.am: Ditto.
+        * WebCore.gypi: Ditto.
+        * WebCore.pro: Ditto.
+        * WebCore.vcproj/WebCore.vcproj: Ditto.
+        * WebCore.xcodeproj/project.pbxproj: Ditto.
+        * dom/DOMAllInOne.cpp: Ditto.
+        * dom/EventDispatcher.cpp: Added.
+        * dom/EventDispatcher.h: Added.
+        * dom/Node.cpp:
+        (WebCore::Node::dispatchScopedEvent): Replaced to use EventDispatcher.
+        (WebCore::Node::dispatchEvent): Ditto.
+        (WebCore::Node::dispatchMouseEvent): Ditto.
+        (WebCore::Node::dispatchSimulatedClick): Ditto.
+        * dom/Node.h: Updated decls.
+
 2011-03-28  Dan Bernstein  <mitz@apple.com>
 
         Reviewed by Maciej Stachowiak.
index a4473b4..856db06 100644 (file)
@@ -1220,6 +1220,8 @@ webcore_sources += \
        Source/WebCore/dom/Event.h \
        Source/WebCore/dom/EventContext.cpp \
        Source/WebCore/dom/EventContext.h \
+       Source/WebCore/dom/EventDispatcher.cpp \
+       Source/WebCore/dom/EventDispatcher.h \
        Source/WebCore/dom/EventException.h \
        Source/WebCore/dom/EventListener.h \
        Source/WebCore/dom/EventNames.cpp \
index 07b3687..921e030 100644 (file)
             'dom/Event.cpp',
             'dom/EventContext.cpp',
             'dom/EventContext.h',
+            'dom/EventDispatcher.cpp',
+            'dom/EventDispatcher.h',
             'dom/EventException.h',
             'dom/EventNames.cpp',
             'dom/EventQueue.cpp',
index d50374e..4251d73 100644 (file)
@@ -488,6 +488,7 @@ SOURCES += \
     dom/ErrorEvent.cpp \
     dom/Event.cpp \
     dom/EventContext.cpp \
+    dom/EventDispatcher.cpp \
     dom/EventNames.cpp \
     dom/EventTarget.cpp \
     dom/EventQueue.cpp \
index 88a489c..f1703d3 100755 (executable)
                                >
                        </File>
                        <File
+                               RelativePath="..\dom\EventDispatcher.cpp"
+                               >
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Release|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug_Cairo_CFLite|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Release_Cairo_CFLite|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug_All|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Release_LTCG|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
+                       <File
+                               RelativePath="..\dom\EventDispatcher.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\dom\EventException.h"
                                >
                        </File>
index d562f6a..3d65533 100644 (file)
                416E75CC0EDF90C700360E1D /* ScriptCallFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 416E75CA0EDF90C700360E1D /* ScriptCallFrame.cpp */; };
                41885B9311B6FDA6003383BB /* FormSubmission.h in Headers */ = {isa = PBXBuildFile; fileRef = 41885B9111B6FDA6003383BB /* FormSubmission.h */; settings = {ATTRIBUTES = (Private, ); }; };
                41885B9411B6FDA6003383BB /* FormSubmission.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41885B9211B6FDA6003383BB /* FormSubmission.cpp */; };
+               418A06D0133C04D500CD379C /* EventDispatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 418A06CE133C04D500CD379C /* EventDispatcher.h */; };
+               418A06D1133C04D500CD379C /* EventDispatcher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 418A06CF133C04D500CD379C /* EventDispatcher.cpp */; };
                418F88040FF957AE0080F045 /* JSAbstractWorker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 418F88020FF957AE0080F045 /* JSAbstractWorker.cpp */; };
                418F88050FF957AF0080F045 /* JSAbstractWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 418F88030FF957AE0080F045 /* JSAbstractWorker.h */; };
                41A3D58E101C152D00316D07 /* DedicatedWorkerThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41A3D58C101C152D00316D07 /* DedicatedWorkerThread.cpp */; };
                416E75CA0EDF90C700360E1D /* ScriptCallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptCallFrame.cpp; sourceTree = "<group>"; };
                41885B9111B6FDA6003383BB /* FormSubmission.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormSubmission.h; sourceTree = "<group>"; };
                41885B9211B6FDA6003383BB /* FormSubmission.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormSubmission.cpp; sourceTree = "<group>"; };
+               418A06CE133C04D500CD379C /* EventDispatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventDispatcher.h; sourceTree = "<group>"; };
+               418A06CF133C04D500CD379C /* EventDispatcher.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventDispatcher.cpp; sourceTree = "<group>"; };
                418F88020FF957AE0080F045 /* JSAbstractWorker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAbstractWorker.cpp; sourceTree = "<group>"; };
                418F88030FF957AE0080F045 /* JSAbstractWorker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAbstractWorker.h; sourceTree = "<group>"; };
                41A3D58C101C152D00316D07 /* DedicatedWorkerThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DedicatedWorkerThread.cpp; path = workers/DedicatedWorkerThread.cpp; sourceTree = "<group>"; };
                                14E836D209F8512000B85AE4 /* Event.idl */,
                                4138D3341244054800323D33 /* EventContext.cpp */,
                                4138D3331244054800323D33 /* EventContext.h */,
+                               418A06CF133C04D500CD379C /* EventDispatcher.cpp */,
+                               418A06CE133C04D500CD379C /* EventDispatcher.h */,
                                BC60D9090D2A17CE00B9918F /* EventException.h */,
                                BC60D90A0D2A17CE00B9918F /* EventException.idl */,
                                935FBC4409BA00B900E230B1 /* EventListener.h */,
                                2ECF7AE210162B5800427DE7 /* ErrorEvent.h in Headers */,
                                85031B420A44EFC700F992E0 /* Event.h in Headers */,
                                4138D3351244054800323D33 /* EventContext.h in Headers */,
+                               418A06D0133C04D500CD379C /* EventDispatcher.h in Headers */,
                                BC60D90C0D2A17CE00B9918F /* EventException.h in Headers */,
                                93C09A530B064DB3005ABD4D /* EventHandler.h in Headers */,
                                935FBC4509BA00B900E230B1 /* EventListener.h in Headers */,
                                2ECF7AE110162B5800427DE7 /* ErrorEvent.cpp in Sources */,
                                85031B410A44EFC700F992E0 /* Event.cpp in Sources */,
                                4138D3361244054800323D33 /* EventContext.cpp in Sources */,
+                               418A06D1133C04D500CD379C /* EventDispatcher.cpp in Sources */,
                                93C09A810B064F00005ABD4D /* EventHandler.cpp in Sources */,
                                93C09A7F0B064EEF005ABD4D /* EventHandlerMac.mm in Sources */,
                                1CA19E050DC255950065A994 /* EventLoopMac.mm in Sources */,
index 08a7680..cc4888f 100644 (file)
@@ -69,6 +69,7 @@
 #include "ErrorEvent.cpp"
 #include "Event.cpp"
 #include "EventContext.cpp"
+#include "EventDispatcher.cpp"
 #include "EventNames.cpp"
 #include "EventQueue.cpp"
 #include "EventTarget.cpp"
diff --git a/Source/WebCore/dom/EventDispatcher.cpp b/Source/WebCore/dom/EventDispatcher.cpp
new file mode 100644 (file)
index 0000000..4461942
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "EventDispatcher.h"
+
+#include "Event.h"
+#include "EventContext.h"
+#include "EventTarget.h"
+#include "FrameView.h"
+#include "InspectorInstrumentation.h"
+#include "MouseEvent.h"
+#include "Node.h"
+
+#if ENABLE(SVG)
+#include "SVGElementInstance.h"
+#include "SVGNames.h"
+#include "SVGUseElement.h"
+#endif
+
+#include "UIEvent.h"
+#include "UIEventWithKeyState.h"
+#include "WindowEventContext.h"
+
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+static HashSet<Node*>* gNodesDispatchingSimulatedClicks = 0;
+
+bool EventDispatcher::dispatchEvent(Node* node, PassRefPtr<Event> event)
+{
+    EventDispatcher dispatcher(node);
+    return dispatcher.dispatchEvent(event);
+}
+
+bool EventDispatcher::dispatchMouseEvent(Node* node, const PlatformMouseEvent& event, const AtomicString& eventType,
+    int detail, Node* relatedTarget)
+{
+    ASSERT(!eventDispatchForbidden());
+    EventDispatcher dispatcher(node);
+
+    IntPoint contentsPos;
+    if (FrameView* view = node->document()->view())
+        contentsPos = view->windowToContents(event.pos());
+
+    short button = event.button();
+
+    ASSERT(event.eventType() == MouseEventMoved || button != NoButton);
+
+    return dispatcher.dispatchMouseEvent(eventType, button, detail,
+        contentsPos.x(), contentsPos.y(), event.globalX(), event.globalY(),
+        event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
+        false, relatedTarget, 0);
+}
+
+void EventDispatcher::dispatchSimulatedClick(Node* node, PassRefPtr<Event> event, bool sendMouseEvents, bool showPressedLook)
+{
+    EventDispatcher dispatcher(node);
+
+    if (!gNodesDispatchingSimulatedClicks)
+        gNodesDispatchingSimulatedClicks = new HashSet<Node*>;
+    else if (gNodesDispatchingSimulatedClicks->contains(node))
+        return;
+
+    gNodesDispatchingSimulatedClicks->add(node);
+
+    // send mousedown and mouseup before the click, if requested
+    if (sendMouseEvents)
+        dispatcher.dispatchSimulatedMouseEvent(eventNames().mousedownEvent, event.get());
+    node->setActive(true, showPressedLook);
+    if (sendMouseEvents)
+        dispatcher.dispatchSimulatedMouseEvent(eventNames().mouseupEvent, event.get());
+    node->setActive(false);
+
+    // always send click
+    dispatcher.dispatchSimulatedMouseEvent(eventNames().clickEvent, event);
+
+    gNodesDispatchingSimulatedClicks->remove(node);
+}
+
+// FIXME: Once https://bugs.webkit.org/show_bug.cgi?id=52963 lands, this should
+// be greatly improved. See https://bugs.webkit.org/show_bug.cgi?id=54025.
+static Node* pullOutOfShadow(Node* node)
+{
+    Node* outermostShadowBoundary = node;
+    for (Node* n = node; n; n = n->parentOrHostNode()) {
+        if (n->isShadowRoot())
+            outermostShadowBoundary = n->parentOrHostNode();
+    }
+    return outermostShadowBoundary;
+}
+
+EventTarget* EventDispatcher::eventTargetRespectingSVGTargetRules(Node* referenceNode)
+{
+    ASSERT(referenceNode);
+
+#if ENABLE(SVG)
+    if (!referenceNode->isSVGElement())
+        return referenceNode;
+
+    // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
+    // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
+    for (Node* n = referenceNode; n; n = n->parentNode()) {
+        if (!n->isShadowRoot() || !n->isSVGElement())
+            continue;
+
+        Element* shadowTreeParentElement = n->shadowHost();
+        ASSERT(shadowTreeParentElement->hasTagName(SVGNames::useTag));
+
+        if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode))
+            return instance;
+    }
+#endif
+
+    return referenceNode;
+}
+
+EventDispatcher::EventDispatcher(Node* node)
+    : m_node(node)
+{
+    ASSERT(node);
+    m_view = node->document()->view();
+}
+
+void EventDispatcher::getEventAncestors(EventTarget* originalTarget, EventDispatchBehavior behavior)
+{
+    if (!m_node->inDocument())
+        return;
+
+    if (ancestorsInitialized())
+        return;
+
+    EventTarget* target = originalTarget;
+    Node* ancestor = m_node.get();
+    bool shouldSkipNextAncestor = false;
+    while (true) {
+        if (ancestor->isShadowRoot()) {
+            if (behavior == StayInsideShadowDOM)
+                return;
+            ancestor = ancestor->shadowHost();
+            if (!shouldSkipNextAncestor)
+                target = ancestor;
+        } else
+            ancestor = ancestor->parentNodeGuaranteedHostFree();
+
+        if (!ancestor)
+            return;
+
+#if ENABLE(SVG)
+        // Skip SVGShadowTreeRootElement.
+        shouldSkipNextAncestor = ancestor->isSVGElement() && ancestor->isShadowRoot();
+        if (shouldSkipNextAncestor)
+            continue;
+#endif
+        // FIXME: Unroll the extra loop inside eventTargetRespectingSVGTargetRules into this loop.
+        m_ancestors.append(EventContext(ancestor, eventTargetRespectingSVGTargetRules(ancestor), target));
+    }
+}
+
+bool EventDispatcher::dispatchEvent(PassRefPtr<Event> prpEvent)
+{
+    RefPtr<Event> event = prpEvent;
+
+    event->setTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
+
+    ASSERT(!eventDispatchForbidden());
+    ASSERT(event->target());
+    ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.
+
+    RefPtr<EventTarget> originalTarget = event->target();
+    getEventAncestors(originalTarget.get(), determineDispatchBehavior(event.get()));
+
+    WindowEventContext windowContext(event.get(), m_node.get(), topEventContext());
+
+    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *event, windowContext.window(), m_node.get(), m_ancestors);
+
+    // Give the target node a chance to do some work before DOM event handlers get a crack.
+    void* data = m_node->preDispatchEventHandler(event.get());
+    if (event->propagationStopped())
+        goto doneDispatching;
+
+    // Trigger capturing event handlers, starting at the top and working our way down.
+    event->setEventPhase(Event::CAPTURING_PHASE);
+
+    if (windowContext.handleLocalEvents(event.get()) && event->propagationStopped())
+        goto doneDispatching;
+
+    for (size_t i = m_ancestors.size(); i; --i) {
+        m_ancestors[i - 1].handleLocalEvents(event.get());
+        if (event->propagationStopped())
+            goto doneDispatching;
+    }
+
+    event->setEventPhase(Event::AT_TARGET);
+    event->setTarget(originalTarget.get());
+    event->setCurrentTarget(EventDispatcher::eventTargetRespectingSVGTargetRules(m_node.get()));
+    m_node->handleLocalEvents(event.get());
+    if (event->propagationStopped())
+        goto doneDispatching;
+
+    if (event->bubbles() && !event->cancelBubble()) {
+        // Trigger bubbling event handlers, starting at the bottom and working our way up.
+        event->setEventPhase(Event::BUBBLING_PHASE);
+
+        size_t size = m_ancestors.size();
+        for (size_t i = 0; i < size; ++i) {
+            m_ancestors[i].handleLocalEvents(event.get());
+            if (event->propagationStopped() || event->cancelBubble())
+                goto doneDispatching;
+        }
+        windowContext.handleLocalEvents(event.get());
+    }
+
+doneDispatching:
+    event->setTarget(originalTarget.get());
+    event->setCurrentTarget(0);
+    event->setEventPhase(0);
+
+    // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
+    m_node->postDispatchEventHandler(event.get(), data);
+
+    // 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()) {
+        // Non-bubbling events call only one default event handler, the one for the target.
+        m_node->defaultEventHandler(event.get());
+        ASSERT(!event->defaultPrevented());
+        if (event->defaultHandled())
+            goto doneWithDefault;
+        // For bubbling events, call default event handlers on the same targets in the
+        // same order as the bubbling phase.
+        if (event->bubbles()) {
+            size_t size = m_ancestors.size();
+            for (size_t i = 0; i < size; ++i) {
+                m_ancestors[i].node()->defaultEventHandler(event.get());
+                ASSERT(!event->defaultPrevented());
+                if (event->defaultHandled())
+                    goto doneWithDefault;
+            }
+        }
+    }
+
+doneWithDefault:
+
+    // Ensure that after event dispatch, the event's target object is the
+    // outermost shadow DOM boundary.
+    event->setTarget(windowContext.target());
+    event->setCurrentTarget(0);
+    InspectorInstrumentation::didDispatchEvent(cookie);
+
+    return !event->defaultPrevented();
+}
+
+bool EventDispatcher::dispatchMouseEvent(const AtomicString& eventType, int button, int detail,
+    int pageX, int pageY, int screenX, int screenY,
+    bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
+    bool isSimulated, Node* relatedTargetArg, PassRefPtr<Event> underlyingEvent)
+{
+    ASSERT(!eventDispatchForbidden());
+    if (m_node->disabled()) // Don't even send DOM events for disabled controls..
+        return true;
+
+    if (eventType.isEmpty())
+        return false; // Shouldn't happen.
+
+    bool cancelable = eventType != eventNames().mousemoveEvent;
+
+    bool swallowEvent = false;
+
+    // Attempting to dispatch with a non-EventTarget relatedTarget causes the relatedTarget to be silently ignored.
+    RefPtr<Node> relatedTarget = pullOutOfShadow(relatedTargetArg);
+
+    int adjustedPageX = pageX;
+    int adjustedPageY = pageY;
+    if (Frame* frame = m_node->document()->frame()) {
+        float pageZoom = frame->pageZoomFactor();
+        if (pageZoom != 1.0f) {
+            // Adjust our pageX and pageY to account for the page zoom.
+            adjustedPageX = lroundf(pageX / pageZoom);
+            adjustedPageY = lroundf(pageY / pageZoom);
+        }
+    }
+
+    RefPtr<MouseEvent> mouseEvent = MouseEvent::create(eventType,
+        true, cancelable, m_node->document()->defaultView(),
+        detail, screenX, screenY, adjustedPageX, adjustedPageY,
+        ctrlKey, altKey, shiftKey, metaKey, button,
+        relatedTarget, 0, isSimulated);
+    mouseEvent->setUnderlyingEvent(underlyingEvent.get());
+    mouseEvent->setAbsoluteLocation(IntPoint(pageX, pageY));
+
+    dispatchEvent(mouseEvent);
+    bool defaultHandled = mouseEvent->defaultHandled();
+    bool defaultPrevented = mouseEvent->defaultPrevented();
+    if (defaultHandled || defaultPrevented)
+        swallowEvent = true;
+
+    // Special case: If it's a double click event, we also send the dblclick event. This is not part
+    // of the DOM specs, but is used for compatibility with the ondblclick="" attribute. This is treated
+    // as a separate event in other DOM-compliant browsers like Firefox, and so we do the same.
+    if (eventType == eventNames().clickEvent && detail == 2) {
+        RefPtr<Event> doubleClickEvent = MouseEvent::create(eventNames().dblclickEvent,
+            true, cancelable, m_node->document()->defaultView(),
+            detail, screenX, screenY, adjustedPageX, adjustedPageY,
+            ctrlKey, altKey, shiftKey, metaKey, button,
+            relatedTarget, 0, isSimulated);
+        doubleClickEvent->setUnderlyingEvent(underlyingEvent.get());
+        if (defaultHandled)
+            doubleClickEvent->setDefaultHandled();
+        dispatchEvent(doubleClickEvent);
+        if (doubleClickEvent->defaultHandled() || doubleClickEvent->defaultPrevented())
+            swallowEvent = true;
+    }
+
+    return swallowEvent;
+}
+
+void EventDispatcher::dispatchSimulatedMouseEvent(const AtomicString& eventType, PassRefPtr<Event> underlyingEvent)
+{
+    ASSERT(!eventDispatchForbidden());
+
+    bool ctrlKey = false;
+    bool altKey = false;
+    bool shiftKey = false;
+    bool metaKey = false;
+    if (UIEventWithKeyState* keyStateEvent = findEventWithKeyState(underlyingEvent.get())) {
+        ctrlKey = keyStateEvent->ctrlKey();
+        altKey = keyStateEvent->altKey();
+        shiftKey = keyStateEvent->shiftKey();
+        metaKey = keyStateEvent->metaKey();
+    }
+
+    // Like Gecko, we just pass 0 for everything when we make a fake mouse event.
+    // Internet Explorer instead gives the current mouse position and state.
+    dispatchMouseEvent(eventType, 0, 0, 0, 0, 0, 0, ctrlKey, altKey, shiftKey, metaKey, true, 0, underlyingEvent);
+}
+
+const EventContext* EventDispatcher::topEventContext()
+{
+    return m_ancestors.isEmpty() ? 0 : &m_ancestors.last();
+}
+
+bool EventDispatcher::ancestorsInitialized() const
+{
+    return m_ancestors.size();
+}
+
+EventDispatchBehavior EventDispatcher::determineDispatchBehavior(Event* event)
+{
+    // Per XBL 2.0 spec, mutation events should never cross shadow DOM boundary:
+    // http://dev.w3.org/2006/xbl2/#event-flow-and-targeting-across-shadow-s
+    if (event->isMutationEvent())
+        return StayInsideShadowDOM;
+
+    // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
+    // Changing this breaks existing sites.
+    // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
+    if (event->type() == eventNames().selectstartEvent)
+        return StayInsideShadowDOM;
+
+    return RetargetEvent;
+}
+
+}
+
diff --git a/Source/WebCore/dom/EventDispatcher.h b/Source/WebCore/dom/EventDispatcher.h
new file mode 100644 (file)
index 0000000..48e4ead
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef EventDispatcher_h
+#define EventDispatcher_h
+
+#include <wtf/Forward.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Event;
+class EventContext;
+class EventTarget;
+class FrameView;
+class Node;
+class PlatformMouseEvent;
+
+enum EventDispatchBehavior {
+    RetargetEvent,
+    StayInsideShadowDOM
+};
+
+
+class EventDispatcher {
+public:
+    static bool dispatchEvent(Node*, PassRefPtr<Event>);
+    static bool dispatchMouseEvent(Node*, const PlatformMouseEvent&, const AtomicString& eventType, int clickCount = 0, Node* relatedTarget = 0);
+    static void dispatchSimulatedClick(Node*, PassRefPtr<Event> underlyingEvent, bool sendMouseEvents = false, bool showPressedLook = true);
+
+    static EventTarget* eventTargetRespectingSVGTargetRules(Node*);
+
+private:
+    EventDispatcher(Node*);
+
+    EventDispatchBehavior determineDispatchBehavior(Event*);
+    void getEventAncestors(EventTarget* originalTarget, EventDispatchBehavior);
+    const EventContext* topEventContext();
+    bool ancestorsInitialized() const;
+
+    bool dispatchEvent(PassRefPtr<Event>);
+    bool dispatchMouseEvent(const AtomicString& eventType, int button, int detail,
+        int pageX, int pageY, int screenX, int screenY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
+        bool isSimulated, Node* relatedTargetArg, PassRefPtr<Event> underlyingEvent);
+    void dispatchSimulatedMouseEvent(const AtomicString& eventType, PassRefPtr<Event> underlyingEvent);
+
+    Vector<EventContext> m_ancestors;
+    RefPtr<Node> m_node;
+    RefPtr<EventTarget> m_originalTarget;
+    RefPtr<FrameView> m_view;
+};
+
+}
+
+#endif
index 1789738..043994a 100644 (file)
@@ -46,6 +46,7 @@
 #include "Element.h"
 #include "Event.h"
 #include "EventContext.h"
+#include "EventDispatcher.h"
 #include "EventException.h"
 #include "EventHandler.h"
 #include "EventListener.h"
 
 #if ENABLE(SVG)
 #include "SVGElementInstance.h"
-#include "SVGNames.h"
 #include "SVGUseElement.h"
 #endif
 
@@ -125,8 +125,6 @@ namespace WebCore {
 
 using namespace HTMLNames;
 
-static HashSet<Node*>* gNodesDispatchingSimulatedClicks = 0;
-
 bool Node::isSupported(const String& feature, const String& version)
 {
     return DOMImplementation::hasFeature(feature, version);
@@ -2602,195 +2600,17 @@ void Node::handleLocalEvents(Event* event)
     fireEventListeners(event);
 }
 
-static inline EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode)
-{
-    ASSERT(referenceNode);
-
-#if ENABLE(SVG)
-    if (!referenceNode->isSVGElement())
-        return referenceNode;
-
-    // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
-    // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
-    for (Node* n = referenceNode; n; n = n->parentNode()) {
-        if (!n->isShadowRoot() || !n->isSVGElement())
-            continue;
-
-        Element* shadowTreeParentElement = n->shadowHost();
-        ASSERT(shadowTreeParentElement->hasTagName(SVGNames::useTag));
-
-        if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode))
-            return instance;
-    }
-#endif
-
-    return referenceNode;
-}
-
-enum EventDispatchBehavior {
-    RetargetEvent,
-    StayInsideShadowDOM
-};
-
-static void getEventAncestors(Node* node, Vector<EventContext>& ancestors, EventTarget* originalTarget, EventDispatchBehavior behavior)
-{
-    if (!node->inDocument())
-        return;
-
-    EventTarget* target = originalTarget;
-    Node* ancestor = node;
-    bool shouldSkipNextAncestor = false;
-    while (true) {
-        if (ancestor->isShadowRoot()) {
-            if (behavior == StayInsideShadowDOM)
-                return;
-            ancestor = ancestor->shadowHost();
-            if (!shouldSkipNextAncestor)
-                target = ancestor;
-        } else
-            ancestor = ancestor->parentNodeGuaranteedHostFree();
-
-        if (!ancestor)
-            return;
-
-#if ENABLE(SVG)
-        // Skip SVGShadowTreeRootElement.
-        shouldSkipNextAncestor = ancestor->isSVGElement() && ancestor->isShadowRoot();
-        if (shouldSkipNextAncestor)
-            continue;
-#endif
-        // FIXME: Unroll the extra loop inside eventTargetRespectingSVGTargetRules into this loop.
-        ancestors.append(EventContext(ancestor, eventTargetRespectingSVGTargetRules(ancestor), target));
-
-    }
-}
-
 void Node::dispatchScopedEvent(PassRefPtr<Event> event)
 {
     // We need to set the target here because it can go away by the time we actually fire the event.
-    event->setTarget(eventTargetRespectingSVGTargetRules(this));
+    event->setTarget(EventDispatcher::eventTargetRespectingSVGTargetRules(this));
 
     ScopedEventQueue::instance()->enqueueEvent(event);
 }
 
-static const EventContext* topEventContext(const Vector<EventContext>& ancestors)
+bool Node::dispatchEvent(PassRefPtr<Event> event)
 {
-    return ancestors.isEmpty() ? 0 : &ancestors.last();
-}
-
-static EventDispatchBehavior determineDispatchBehavior(Event* event)
-{
-    // Per XBL 2.0 spec, mutation events should never cross shadow DOM boundary:
-    // http://dev.w3.org/2006/xbl2/#event-flow-and-targeting-across-shadow-s
-    if (event->isMutationEvent())
-        return StayInsideShadowDOM;
-
-    // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
-    // Changing this breaks existing sites.
-    // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
-    if (event->type() == eventNames().selectstartEvent)
-        return StayInsideShadowDOM;
-
-    return RetargetEvent;
-}
-
-bool Node::dispatchEvent(PassRefPtr<Event> prpEvent)
-{
-    RefPtr<EventTarget> protect = this;
-    RefPtr<Event> event = prpEvent;
-
-    event->setTarget(eventTargetRespectingSVGTargetRules(this));
-
-    RefPtr<FrameView> view = document()->view();
-
-    ASSERT(!eventDispatchForbidden());
-    ASSERT(event->target());
-    ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.
-
-    RefPtr<EventTarget> originalTarget = event->target();
-    Vector<EventContext> ancestors;
-    getEventAncestors(this, ancestors, originalTarget.get(), determineDispatchBehavior(event.get()));
-
-    WindowEventContext windowContext(event.get(), this, topEventContext(ancestors));
-
-    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(document(), *event, windowContext.window(), this, ancestors);
-
-    // Give the target node a chance to do some work before DOM event handlers get a crack.
-    void* data = preDispatchEventHandler(event.get());
-    if (event->propagationStopped())
-        goto doneDispatching;
-
-    // Trigger capturing event handlers, starting at the top and working our way down.
-    event->setEventPhase(Event::CAPTURING_PHASE);
-
-    if (windowContext.handleLocalEvents(event.get()) && event->propagationStopped())
-        goto doneDispatching;
-
-    for (size_t i = ancestors.size(); i; --i) {
-        ancestors[i - 1].handleLocalEvents(event.get());
-        if (event->propagationStopped())
-            goto doneDispatching;
-    }
-
-    event->setEventPhase(Event::AT_TARGET);
-    event->setTarget(originalTarget.get());
-    event->setCurrentTarget(eventTargetRespectingSVGTargetRules(this));
-    handleLocalEvents(event.get());
-    if (event->propagationStopped())
-        goto doneDispatching;
-
-    if (event->bubbles() && !event->cancelBubble()) {
-        // Trigger bubbling event handlers, starting at the bottom and working our way up.
-        event->setEventPhase(Event::BUBBLING_PHASE);
-
-        size_t size = ancestors.size();
-        for (size_t i = 0; i < size; ++i) {
-            ancestors[i].handleLocalEvents(event.get());
-            if (event->propagationStopped() || event->cancelBubble())
-                goto doneDispatching;
-        }
-        windowContext.handleLocalEvents(event.get());
-    }
-
-doneDispatching:
-    event->setTarget(originalTarget.get());
-    event->setCurrentTarget(0);
-    event->setEventPhase(0);
-
-    // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
-    postDispatchEventHandler(event.get(), data);
-
-    // 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()) {
-        // Non-bubbling events call only one default event handler, the one for the target.
-        defaultEventHandler(event.get());
-        ASSERT(!event->defaultPrevented());
-        if (event->defaultHandled())
-            goto doneWithDefault;
-        // For bubbling events, call default event handlers on the same targets in the
-        // same order as the bubbling phase.
-        if (event->bubbles()) {
-            size_t size = ancestors.size();
-            for (size_t i = 0; i < size; ++i) {
-                ancestors[i].node()->defaultEventHandler(event.get());
-                ASSERT(!event->defaultPrevented());
-                if (event->defaultHandled())
-                    goto doneWithDefault;
-            }
-        }
-    }
-
-doneWithDefault:
-
-    // Ensure that after event dispatch, the event's target object is the
-    // outermost shadow DOM boundary.
-    event->setTarget(windowContext.target());
-    event->setCurrentTarget(0);
-    InspectorInstrumentation::didDispatchEvent(cookie);
-
-    return !event->defaultPrevented();
+    return EventDispatcher::dispatchEvent(this, event);
 }
 
 void Node::dispatchSubtreeModifiedEvent()
@@ -2837,146 +2657,12 @@ bool Node::dispatchKeyEvent(const PlatformKeyboardEvent& key)
 bool Node::dispatchMouseEvent(const PlatformMouseEvent& event, const AtomicString& eventType,
     int detail, Node* relatedTarget)
 {
-    ASSERT(!eventDispatchForbidden());
-    
-    IntPoint contentsPos;
-    if (FrameView* view = document()->view())
-        contentsPos = view->windowToContents(event.pos());
-
-    short button = event.button();
-
-    ASSERT(event.eventType() == MouseEventMoved || button != NoButton);
-    
-    return dispatchMouseEvent(eventType, button, detail,
-        contentsPos.x(), contentsPos.y(), event.globalX(), event.globalY(),
-        event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
-        false, relatedTarget, 0);
-}
-
-void Node::dispatchSimulatedMouseEvent(const AtomicString& eventType,
-    PassRefPtr<Event> underlyingEvent)
-{
-    ASSERT(!eventDispatchForbidden());
-
-    bool ctrlKey = false;
-    bool altKey = false;
-    bool shiftKey = false;
-    bool metaKey = false;
-    if (UIEventWithKeyState* keyStateEvent = findEventWithKeyState(underlyingEvent.get())) {
-        ctrlKey = keyStateEvent->ctrlKey();
-        altKey = keyStateEvent->altKey();
-        shiftKey = keyStateEvent->shiftKey();
-        metaKey = keyStateEvent->metaKey();
-    }
-
-    // Like Gecko, we just pass 0 for everything when we make a fake mouse event.
-    // Internet Explorer instead gives the current mouse position and state.
-    dispatchMouseEvent(eventType, 0, 0, 0, 0, 0, 0,
-        ctrlKey, altKey, shiftKey, metaKey, true, 0, underlyingEvent);
+    return EventDispatcher::dispatchMouseEvent(this, event, eventType, detail, relatedTarget);
 }
 
 void Node::dispatchSimulatedClick(PassRefPtr<Event> event, bool sendMouseEvents, bool showPressedLook)
 {
-    if (!gNodesDispatchingSimulatedClicks)
-        gNodesDispatchingSimulatedClicks = new HashSet<Node*>;
-    else if (gNodesDispatchingSimulatedClicks->contains(this))
-        return;
-    
-    gNodesDispatchingSimulatedClicks->add(this);
-    
-    // send mousedown and mouseup before the click, if requested
-    if (sendMouseEvents)
-        dispatchSimulatedMouseEvent(eventNames().mousedownEvent, event.get());
-    setActive(true, showPressedLook);
-    if (sendMouseEvents)
-        dispatchSimulatedMouseEvent(eventNames().mouseupEvent, event.get());
-    setActive(false);
-
-    // always send click
-    dispatchSimulatedMouseEvent(eventNames().clickEvent, event);
-    
-    gNodesDispatchingSimulatedClicks->remove(this);
-}
-
-// FIXME: Once https://bugs.webkit.org/show_bug.cgi?id=52963 lands, this should
-// be greatly improved. See https://bugs.webkit.org/show_bug.cgi?id=54025.
-static Node* pullOutOfShadow(Node* node)
-{
-    Node* outermostShadowBoundary = node;
-    for (Node* n = node; n; n = n->parentOrHostNode()) {
-        if (n->isShadowRoot())
-            outermostShadowBoundary = n->parentOrHostNode();
-    }
-    return outermostShadowBoundary;
-}
-
-bool Node::dispatchMouseEvent(const AtomicString& eventType, int button, int detail,
-    int pageX, int pageY, int screenX, int screenY,
-    bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, 
-    bool isSimulated, Node* relatedTargetArg, PassRefPtr<Event> underlyingEvent)
-{
-    ASSERT(!eventDispatchForbidden());
-    if (disabled()) // Don't even send DOM events for disabled controls..
-        return true;
-    
-    if (eventType.isEmpty())
-        return false; // Shouldn't happen.
-    
-    // Dispatching the first event can easily result in this node being destroyed.
-    // Since we dispatch up to three events here, we need to make sure we're referenced
-    // so the pointer will be good for the two subsequent ones.
-    RefPtr<Node> protect(this);
-    
-    bool cancelable = eventType != eventNames().mousemoveEvent;
-    
-    bool swallowEvent = false;
-    
-    // Attempting to dispatch with a non-EventTarget relatedTarget causes the relatedTarget to be silently ignored.
-    RefPtr<Node> relatedTarget = pullOutOfShadow(relatedTargetArg);
-
-    int adjustedPageX = pageX;
-    int adjustedPageY = pageY;
-    if (Frame* frame = document()->frame()) {
-        float pageZoom = frame->pageZoomFactor();
-        if (pageZoom != 1.0f) {
-            // Adjust our pageX and pageY to account for the page zoom.
-            adjustedPageX = lroundf(pageX / pageZoom);
-            adjustedPageY = lroundf(pageY / pageZoom);
-        }
-    }
-
-    RefPtr<MouseEvent> mouseEvent = MouseEvent::create(eventType,
-        true, cancelable, document()->defaultView(),
-        detail, screenX, screenY, adjustedPageX, adjustedPageY,
-        ctrlKey, altKey, shiftKey, metaKey, button,
-        relatedTarget, 0, isSimulated);
-    mouseEvent->setUnderlyingEvent(underlyingEvent.get());
-    mouseEvent->setAbsoluteLocation(IntPoint(pageX, pageY));
-    
-    dispatchEvent(mouseEvent);
-    bool defaultHandled = mouseEvent->defaultHandled();
-    bool defaultPrevented = mouseEvent->defaultPrevented();
-    if (defaultHandled || defaultPrevented)
-        swallowEvent = true;
-    
-    // Special case: If it's a double click event, we also send the dblclick event. This is not part
-    // of the DOM specs, but is used for compatibility with the ondblclick="" attribute.  This is treated
-    // as a separate event in other DOM-compliant browsers like Firefox, and so we do the same.
-    if (eventType == eventNames().clickEvent && detail == 2) {
-        RefPtr<Event> doubleClickEvent = MouseEvent::create(eventNames().dblclickEvent,
-            true, cancelable, document()->defaultView(),
-            detail, screenX, screenY, adjustedPageX, adjustedPageY,
-            ctrlKey, altKey, shiftKey, metaKey, button,
-            relatedTarget, 0, isSimulated);
-        doubleClickEvent->setUnderlyingEvent(underlyingEvent.get());
-        if (defaultHandled)
-            doubleClickEvent->setDefaultHandled();
-        dispatchEvent(doubleClickEvent);
-        if (doubleClickEvent->defaultHandled() || doubleClickEvent->defaultPrevented())
-            swallowEvent = true;
-    }
-
-    return swallowEvent;
+    EventDispatcher::dispatchSimulatedClick(this, event, sendMouseEvents, showPressedLook);
 }
 
 void Node::dispatchWheelEvent(PlatformWheelEvent& e)
index 4b52168..129a493 100644 (file)
@@ -537,11 +537,6 @@ public:
     bool dispatchKeyEvent(const PlatformKeyboardEvent&);
     void dispatchWheelEvent(PlatformWheelEvent&);
     bool dispatchMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType, int clickCount = 0, Node* relatedTarget = 0);
-    bool dispatchMouseEvent(const AtomicString& eventType, int button, int clickCount,
-        int pageX, int pageY, int screenX, int screenY,
-        bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
-        bool isSimulated, Node* relatedTarget, PassRefPtr<Event> underlyingEvent);
-    void dispatchSimulatedMouseEvent(const AtomicString& eventType, PassRefPtr<Event> underlyingEvent);
     void dispatchSimulatedClick(PassRefPtr<Event> underlyingEvent, bool sendMouseEvents = false, bool showPressedLook = true);
 
     virtual void dispatchFocusEvent();