changeset 9474:25db4b2e47a1

8145937: Not able to enter text and pop menu disappearing on Mouseover Menu Reviewed-by: azvegint, kcr Contributed-by: murali.billa@oracle.com
author azvegint
date Wed, 23 Dec 2015 21:10:08 +0300
parents f13398be7d13
children 6613c72b99dc
files modules/web/src/main/native/Source/WebCore/dom/EventDispatcher.cpp
diffstat 1 files changed, 67 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/modules/web/src/main/native/Source/WebCore/dom/EventDispatcher.cpp	Wed Dec 23 09:23:32 2015 -0500
+++ b/modules/web/src/main/native/Source/WebCore/dom/EventDispatcher.cpp	Wed Dec 23 21:10:08 2015 +0300
@@ -88,9 +88,9 @@
     EventContext& contextAt(size_t i) { return *m_path[i]; }
 
 #if ENABLE(TOUCH_EVENTS)
-    void updateTouchLists(const TouchEvent&);
+    bool updateTouchLists(const TouchEvent&);
 #endif
-    void setRelatedTarget(EventTarget&);
+    void setRelatedTarget(Node& origin, EventTarget&);
 
     bool hasEventListeners(const AtomicString& eventType) const;
 
@@ -148,18 +148,50 @@
             ASSERT(m_currentTreeScope->parentTreeScope() == &newTreeScope);
         }
 
-        if (m_relatedNodeInCurrentTreeScope) { // relatedNode is under the current tree scope
+        if (&newTreeScope == &m_relatedNodeTreeScope)
+            m_relatedNodeInCurrentTreeScope = &m_relatedNode;
+        else if (m_relatedNodeInCurrentTreeScope) {
             ASSERT(m_currentTreeScope);
             m_relatedNodeInCurrentTreeScope = &newTarget;
-        } else if (&newTreeScope == &m_relatedNodeTreeScope) // relatedNode is in the current tree scope;
-            m_relatedNodeInCurrentTreeScope = &m_relatedNode;
-        // Otherwise, we haven't reached the tree scope that contains relatedNode yet.
+        } else {
+            if (!m_currentTreeScope) {
+                TreeScope* newTreeScopeAncestor = &newTreeScope;
+                do {
+                    m_relatedNodeInCurrentTreeScope = findHostOfTreeScopeInTargetTreeScope(m_relatedNodeTreeScope, *newTreeScopeAncestor);
+                    newTreeScopeAncestor = newTreeScopeAncestor->parentTreeScope();
+                    if (newTreeScopeAncestor == &m_relatedNodeTreeScope) {
+                        m_relatedNodeInCurrentTreeScope = &m_relatedNode;
+                        break;
+                    }
+                } while (newTreeScopeAncestor && !m_relatedNodeInCurrentTreeScope);
+            }
+            ASSERT(m_relatedNodeInCurrentTreeScope || findHostOfTreeScopeInTargetTreeScope(newTreeScope, m_relatedNodeTreeScope)
+                || &newTreeScope.documentScope() != &m_relatedNodeTreeScope.documentScope());
+        }
 
         m_currentTreeScope = &newTreeScope;
 
         return m_relatedNodeInCurrentTreeScope;
     }
 
+    static Node* findHostOfTreeScopeInTargetTreeScope(const TreeScope& startingTreeScope, const TreeScope& targetScope)
+    {
+            ASSERT(&targetScope != &startingTreeScope);
+            Node* previousHost = nullptr;
+            for (const TreeScope* scope = &startingTreeScope; scope; scope = scope->parentTreeScope()) {
+                if (scope == &targetScope) {
+                    ASSERT(previousHost);
+                    ASSERT_WITH_SECURITY_IMPLICATION(&previousHost->treeScope() == &targetScope);
+                    return previousHost;
+                }
+                if (scope->rootNode().isShadowRoot())
+                    previousHost = toShadowRoot(scope->rootNode()).hostElement();
+                else
+                    ASSERT_WITH_SECURITY_IMPLICATION(!scope->parentTreeScope());
+            }
+            return nullptr;
+    }
+
 private:
     Node& m_relatedNode;
     const TreeScope& m_relatedNodeTreeScope;
@@ -230,6 +262,9 @@
 
 static void callDefaultEventHandlersInTheBubblingOrder(Event& event, const EventPath& path)
 {
+    if (path.isEmpty())
+        return;
+
     // Non-bubbling events call only one default event handler, the one for the target.
     path.contextAt(0).node()->defaultEventHandler(&event);
     ASSERT(!event.defaultPrevented());
@@ -305,10 +340,12 @@
     EventPath eventPath(*node, *event);
 
     if (EventTarget* relatedTarget = event->relatedTarget())
-        eventPath.setRelatedTarget(*relatedTarget);
+        eventPath.setRelatedTarget(*node, *relatedTarget);
 #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
-    if (event->isTouchEvent())
-        eventPath.updateTouchLists(*toTouchEvent(event.get()));
+    if (event->isTouchEvent()) {
+        if (!eventPath.updateTouchLists(*toTouchEvent(event.get())))
+            return true;
+    }
 #endif
 
     ChildNodesLazySnapshot::takeChildNodesLazySnapshot();
@@ -427,8 +464,11 @@
         touchTargetResolvers.append(EventRelatedNodeResolver(*touchList->item(i), type));
 }
 
-void EventPath::updateTouchLists(const TouchEvent& touchEvent)
+bool EventPath::updateTouchLists(const TouchEvent& touchEvent)
 {
+    if (!touchEvent.touches() || !touchEvent.targetTouches() || !touchEvent.changedTouches())
+        return false;
+
     Vector<EventRelatedNodeResolver, 16> touchTargetResolvers;
     const size_t touchNodeCount = touchEvent.touches()->length() + touchEvent.targetTouches()->length() + touchEvent.changedTouches()->length();
     touchTargetResolvers.reserveInitialCapacity(touchNodeCount);
@@ -449,10 +489,11 @@
             context.touchList(currentResolver.touchListType())->append(currentResolver.touch()->cloneWithNewTarget(nodeInCurrentTreeScope));
         }
     }
+    return true;
 }
 #endif
 
-void EventPath::setRelatedTarget(EventTarget& relatedTarget)
+void EventPath::setRelatedTarget(Node& origin, EventTarget& relatedTarget)
 {
     Node* relatedNode = relatedTarget.toNode();
     if (!relatedNode)
@@ -460,9 +501,22 @@
 
     EventRelatedNodeResolver resolver(*relatedNode);
 
+    bool originIsRelatedTarget = &origin == relatedNode;
+    Node& rootNodeInOriginTreeScope = origin.treeScope().rootNode();
+
     size_t eventPathSize = m_path.size();
-    for (size_t i = 0; i < eventPathSize; i++)
-        toMouseOrFocusEventContext(*m_path[i]).setRelatedTarget(resolver.moveToParentOrShadowHost(*m_path[i]->node()));
+    size_t i = 0;
+    while (i < eventPathSize) {
+        Node* contextNode = m_path[i]->node();
+        Node* currentRelatedNode = resolver.moveToParentOrShadowHost(*contextNode);
+        if (!originIsRelatedTarget && m_path[i]->target() == currentRelatedNode)
+            break;
+        toMouseOrFocusEventContext(*m_path[i]).setRelatedTarget(currentRelatedNode);
+        i++;
+        if (originIsRelatedTarget && &rootNodeInOriginTreeScope == contextNode)
+            break;
+    }
+    m_path.shrink(i);
 }
 
 bool EventPath::hasEventListeners(const AtomicString& eventType) const