예제 #1
0
void EventRetargeter::calculateEventPath(Node* targetNode, Event* event, EventPath& eventPath)
{
    bool inDocument = targetNode->inDocument();
    bool isSVGElement = targetNode->isSVGElement();
    bool isMouseOrFocusEvent = event->isMouseEvent() || event->isFocusEvent();
#if ENABLE(TOUCH_EVENTS)
    bool isTouchEvent = event->isTouchEvent();
#endif
    Vector<EventTarget*, 32> targetStack;

    for (Node* node = nodeOrHostIfPseudoElement(targetNode); node; node = node->parentOrShadowHostNode()) {
        if (targetStack.isEmpty())
            targetStack.append(eventTargetRespectingTargetRules(node));
        if (isMouseOrFocusEvent)
            eventPath.append(adoptPtr(new MouseOrFocusEventContext(node, eventTargetRespectingTargetRules(node), targetStack.last())));
#if ENABLE(TOUCH_EVENTS)
        else if (isTouchEvent)
            eventPath.append(adoptPtr(new TouchEventContext(node, eventTargetRespectingTargetRules(node), targetStack.last())));
#endif
        else
            eventPath.append(adoptPtr(new EventContext(node, eventTargetRespectingTargetRules(node), targetStack.last())));
        if (!inDocument)
            return;
        if (!node->isShadowRoot())
            continue;
        if (determineDispatchBehavior(event, toShadowRoot(node), targetStack.last()) == StayInsideShadowDOM)
            return;
        if (!isSVGElement) {
            ASSERT(!targetStack.isEmpty());
            targetStack.removeLast();
        }
    }
}
예제 #2
0
void EventDispatcher::ensureEventAncestors(Event* event)
{
    if (m_ancestorsInitialized)
        return;
    m_ancestorsInitialized = true;
    bool inDocument = m_node->inDocument();
    bool isSVGElement = m_node->isSVGElement();
    Vector<EventTarget*, 32> targetStack;
    for (AncestorChainWalker walker(m_node.get()); walker.get(); walker.parent()) {
        Node* node = walker.get();
        if (targetStack.isEmpty())
            targetStack.append(eventTargetRespectingTargetRules(node));
        else if (walker.crossingInsertionPoint())
            targetStack.append(targetStack.last());
        m_ancestors.append(EventContext(node, eventTargetRespectingTargetRules(node), targetStack.last()));
        if (!inDocument)
            return;
        if (!node->isShadowRoot())
            continue;
        if (determineDispatchBehavior(event, toShadowRoot(node), targetStack.last()) == StayInsideShadowDOM)
            return;
        if (!isSVGElement) {
            ASSERT(!targetStack.isEmpty());
            targetStack.removeLast();
        }
    }
}
예제 #3
0
void EventRetargeter::calculateEventPath(Node* node, Event* event)
{
    EventPath& eventPath = event->eventPath();
    eventPath.clear();
    bool inDocument = node->inDocument();
    bool isSVGElement = node->isSVGElement();
    bool isMouseOrFocusEvent = event->isMouseEvent() || event->isFocusEvent();
    bool isTouchEvent = event->isTouchEvent();
    Vector<EventTarget*, 32> targetStack;
    for (EventPathWalker walker(node); walker.node(); walker.moveToParent()) {
        Node* node = walker.node();
        if (targetStack.isEmpty())
            targetStack.append(eventTargetRespectingTargetRules(node));
        else if (walker.isVisitingInsertionPointInReprojection())
            targetStack.append(targetStack.last());
        if (isMouseOrFocusEvent)
            eventPath.append(adoptPtr(new MouseOrFocusEventContext(node, eventTargetRespectingTargetRules(node), targetStack.last())));
        else if (isTouchEvent)
            eventPath.append(adoptPtr(new TouchEventContext(node, eventTargetRespectingTargetRules(node), targetStack.last())));
        else
            eventPath.append(adoptPtr(new EventContext(node, eventTargetRespectingTargetRules(node), targetStack.last())));
        if (!inDocument)
            return;
        if (!node->isShadowRoot())
            continue;
        if (determineDispatchBehavior(event, toShadowRoot(node), targetStack.last()) == StayInsideShadowDOM)
            return;
        if (!isSVGElement) {
            ASSERT(!targetStack.isEmpty());
            targetStack.removeLast();
        }
    }
}
예제 #4
0
void EventDispatcher::ensureEventAncestors(Event* event)
{
    if (m_ancestorsInitialized)
        return;
    m_ancestorsInitialized = true;
    bool inDocument = m_node->inDocument();
    bool isSVGElement = m_node->isSVGElement();
    Vector<EventTarget*> targetStack;
    Node* last = 0;
    for (ComposedShadowTreeParentWalker walker(m_node.get()); walker.get(); walker.parentIncludingInsertionPointAndShadowRoot()) {
        Node* node = walker.get();
        if (targetStack.isEmpty())
            targetStack.append(eventTargetRespectingSVGTargetRules(node));
        else if (isInsertionPoint(node) && toInsertionPoint(node)->contains(last))
            targetStack.append(targetStack.last());
        m_ancestors.append(EventContext(node, eventTargetRespectingSVGTargetRules(node), targetStack.last()));
        if (!inDocument)
            return;
        last = node;
        if (!node->isShadowRoot())
            continue;
        if (determineDispatchBehavior(event, toShadowRoot(node), targetStack.last()) == StayInsideShadowDOM)
            return;
        if (!isSVGElement) {
            ASSERT(!targetStack.isEmpty());
            targetStack.removeLast();
        }
    }
}
예제 #5
0
void EventRetargeter::calculateEventPath(Node* node, Event* event)
{
    EventPath& eventPath = event->eventPath();
    eventPath.clear();
    bool inDocument = node->inDocument();
    bool isSVGElement = node->isSVGElement();
    bool isMouseOrFocusEvent = event->isMouseEvent() || event->isFocusEvent();
    bool isTouchEvent = event->isTouchEvent();
    Vector<EventTarget*, 32> targetStack;
    for (EventPathWalker walker(node); walker.node(); walker.moveToParent()) {
        Node* node = walker.node();
        if (targetStack.isEmpty())
            targetStack.append(eventTargetRespectingTargetRules(node));
        else if (walker.isVisitingInsertionPointInReprojection())
            targetStack.append(targetStack.last());
        if (isMouseOrFocusEvent)
            eventPath.append(adoptPtr(new MouseOrFocusEventContext(node, eventTargetRespectingTargetRules(node), targetStack.last())));
        else if (isTouchEvent)
            eventPath.append(adoptPtr(new TouchEventContext(node, eventTargetRespectingTargetRules(node), targetStack.last())));
        else
            eventPath.append(adoptPtr(new EventContext(node, eventTargetRespectingTargetRules(node), targetStack.last())));
        if (!inDocument)
            return;
        if (!node->isShadowRoot())
            continue;
        if (determineDispatchBehavior(event, toShadowRoot(node), targetStack.last()) == StayInsideShadowDOM)
            return;
        if (!isSVGElement) {
            ASSERT(!targetStack.isEmpty());
            targetStack.removeLast();
        }
    }

    // Calculates eventPath for each node for Event.path() API.
    if (!RuntimeEnabledFeatures::experimentalShadowDOMEnabled())
        return;
    TreeScope* lastScope = 0;
    size_t eventPathSize = eventPath.size();
    for (size_t i = 0; i < eventPathSize; ++i) {
        TreeScope* currentScope = eventPath[i]->node()->treeScope();
        if (currentScope == lastScope) {
            // Fast path.
            eventPath[i]->setEventPath(eventPath[i - 1]->eventPath());
            continue;
        }
        lastScope = currentScope;
        Vector<RefPtr<Node> > nodes;
        for (size_t j = 0; j < eventPathSize; ++j) {
            Node* node = eventPath[j]->node();
            if (node->treeScope()->isInclusiveAncestorOf(currentScope))
                nodes.append(node);
        }
        eventPath[i]->adoptEventPath(nodes);
    }
}
void EventDispatcher::ensureEventAncestors(Event* event)
{
    if (!m_node->inDocument())
        return;

    if (m_ancestorsInitialized)
        return;

    m_ancestorsInitialized = true;

    Node* ancestor = m_node.get();
    EventTarget* target = eventTargetRespectingSVGTargetRules(ancestor);
    bool shouldSkipNextAncestor = false;
    while (true) {
        bool isSVGShadowRoot = ancestor->isSVGShadowRoot();
        if (isSVGShadowRoot || ancestor->isShadowRoot()) {
            if (determineDispatchBehavior(event, ancestor) == StayInsideShadowDOM)
                return;
#if ENABLE(SVG)
            ancestor = isSVGShadowRoot ? ancestor->svgShadowHost() : ancestor->shadowHost();
#else
            ancestor = ancestor->shadowHost();
#endif
            if (!shouldSkipNextAncestor)
                target = ancestor;
        } else
            ancestor = ancestor->parentNodeGuaranteedHostFree();

        if (!ancestor)
            return;

#if ENABLE(SVG)
        // Skip SVGShadowTreeRootElement.
        shouldSkipNextAncestor = ancestor->isSVGShadowRoot();
        if (shouldSkipNextAncestor)
            continue;
#endif
        // FIXME: Unroll the extra loop inside eventTargetRespectingSVGTargetRules into this loop.
        m_ancestors.append(EventContext(ancestor, eventTargetRespectingSVGTargetRules(ancestor), target));
    }
}
예제 #7
0
void EventPath::calculatePath()
{
    ASSERT(m_node);
    ASSERT(m_nodeEventContexts.isEmpty());
    m_node->document().updateDistributionForNodeIfNeeded(const_cast<Node*>(m_node));

    Node* current = m_node;
    addNodeEventContext(current);
    if (!m_node->inDocument())
        return;
    while (current) {
        if (current->isShadowRoot() && m_event && determineDispatchBehavior(m_event, toShadowRoot(current), m_node) == StayInsideShadowDOM)
            break;
        Vector<InsertionPoint*, 8> insertionPoints;
        collectDestinationInsertionPoints(*current, insertionPoints);
        if (!insertionPoints.isEmpty()) {
            for (size_t i = 0; i < insertionPoints.size(); ++i) {
                InsertionPoint* insertionPoint = insertionPoints[i];
                if (insertionPoint->isShadowInsertionPoint()) {
                    ShadowRoot* containingShadowRoot = insertionPoint->containingShadowRoot();
                    ASSERT(containingShadowRoot);
                    if (!containingShadowRoot->isOldest())
                        addNodeEventContext(containingShadowRoot->olderShadowRoot());
                }
                addNodeEventContext(insertionPoint);
            }
            current = insertionPoints.last();
            continue;
        }
        if (current->isShadowRoot()) {
            current = current->shadowHost();
            addNodeEventContext(current);
        } else {
            current = current->parentNode();
            if (current)
                addNodeEventContext(current);
        }
    }
}
예제 #8
0
bool EventDispatcher::dispatchEvent(PassRefPtr<Event> event)
{
    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(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();
}