Beispiel #1
0
EventPath::EventPath(Node& targetNode, Event& event)
{
    bool inDocument = targetNode.inDocument();
    bool isSVGElement = targetNode.isSVGElement();
    bool isMouseOrFocusEvent = event.isMouseEvent() || event.isFocusEvent();
#if ENABLE(TOUCH_EVENTS)
    bool isTouchEvent = event.isTouchEvent();
#endif
    EventTarget* target = 0;

    Node* node = nodeOrHostIfPseudoElement(&targetNode);
    while (node) {
        if (!target || !isSVGElement) // FIXME: This code doesn't make sense once we've climbed out of the SVG subtree in a HTML document.
            target = &eventTargetRespectingTargetRules(*node);
        for (; node; node = node->parentNode()) {
            EventTarget& currentTarget = eventTargetRespectingTargetRules(*node);
            if (isMouseOrFocusEvent)
                m_path.append(std::make_unique<MouseOrFocusEventContext>(node, &currentTarget, target));
#if ENABLE(TOUCH_EVENTS)
            else if (isTouchEvent)
                m_path.append(std::make_unique<TouchEventContext>(node, &currentTarget, target));
#endif
            else
                m_path.append(std::make_unique<EventContext>(node, &currentTarget, target));
            if (!inDocument)
                return;
            if (node->isShadowRoot())
                break;
        }
        if (!node || !shouldEventCrossShadowBoundary(event, *toShadowRoot(node), *target))
            return;
        node = toShadowRoot(node)->hostElement();
    }
}
Beispiel #2
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();
        }
    }
}
Beispiel #3
0
EventPath::EventPath(Node& originalTarget, Event& event)
    : m_event(event)
{
    bool isMouseOrFocusEvent = event.isMouseEvent() || event.isFocusEvent();
#if ENABLE(TOUCH_EVENTS)
    bool isTouchEvent = event.isTouchEvent();
#endif
    Node* node = nodeOrHostIfPseudoElement(&originalTarget);
    Node* target = node ? eventTargetRespectingTargetRules(*node) : nullptr;
    while (node) {
        while (node) {
            EventTarget* currentTarget = eventTargetRespectingTargetRules(*node);

            if (isMouseOrFocusEvent)
                m_path.append(std::make_unique<MouseOrFocusEventContext>(node, currentTarget, target));
#if ENABLE(TOUCH_EVENTS)
            else if (isTouchEvent)
                m_path.append(std::make_unique<TouchEventContext>(node, currentTarget, target));
#endif
            else
                m_path.append(std::make_unique<EventContext>(node, currentTarget, target));

            if (is<ShadowRoot>(*node))
                break;

            ContainerNode* parent = node->parentNode();
            if (!parent)
                return;

#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
            if (ShadowRoot* shadowRootOfParent = parent->shadowRoot()) {
                if (auto* assignedSlot = shadowRootOfParent->findAssignedSlot(*node)) {
                    // node is assigned to a slot. Continue dispatching the event at this slot.
                    parent = assignedSlot;
                }
            }
#endif
            node = parent;
        }

        bool exitingShadowTreeOfTarget = &target->treeScope() == &node->treeScope();
        ShadowRoot& shadowRoot = downcast<ShadowRoot>(*node);
        if (!shouldEventCrossShadowBoundary(event, shadowRoot, originalTarget))
            return;
        node = shadowRoot.host();
        if (exitingShadowTreeOfTarget)
            target = eventTargetRespectingTargetRules(*node);

    }
}
Beispiel #4
0
void EventRetargeter::buildRelatedNodeMap(const Node* relatedNode, RelatedNodeMap& relatedNodeMap)
{
    Vector<Node*, 32> relatedNodeStack;
    TreeScope* lastTreeScope = 0;
    for (Node* node = nodeOrHostIfPseudoElement(const_cast<Node*>(relatedNode)); node; node = node->parentOrShadowHostNode()) {
        if (relatedNodeStack.isEmpty())
            relatedNodeStack.append(node);
        TreeScope* scope = node->treeScope();
        // Skips adding a node to the map if treeScope does not change. Just for the performance optimization.
        if (scope != lastTreeScope)
            relatedNodeMap.add(scope, relatedNodeStack.last());
        lastTreeScope = scope;
        if (node->isShadowRoot()) {
            ASSERT(!relatedNodeStack.isEmpty());
            relatedNodeStack.removeLast();
        }
    }
}
Beispiel #5
0
EventPath::EventPath(Node& originalTarget, Event& event)
    : m_event(event)
{
#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
    Vector<EventTarget*, 16> targetStack;
#endif

    bool isMouseOrFocusEvent = event.isMouseEvent() || event.isFocusEvent();
#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
    bool isTouchEvent = event.isTouchEvent();
#endif
    EventTarget* target = nullptr;

    Node* node = nodeOrHostIfPseudoElement(&originalTarget);
    while (node) {
        if (!target)
            target = eventTargetRespectingTargetRules(*node);
        ContainerNode* parent;
        for (; node; node = parent) {
            EventTarget* currentTarget = eventTargetRespectingTargetRules(*node);
            if (isMouseOrFocusEvent)
                m_path.append(std::make_unique<MouseOrFocusEventContext>(node, currentTarget, target));
#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
            else if (isTouchEvent)
                m_path.append(std::make_unique<TouchEventContext>(node, currentTarget, target));
#endif
            else
                m_path.append(std::make_unique<EventContext>(node, currentTarget, target));
            if (is<ShadowRoot>(*node))
                break;
            parent = node->parentNode();
            if (!parent)
                return;
#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
            if (ShadowRoot* shadowRootOfParent = parent->shadowRoot()) {
                if (auto* assignedSlot = shadowRootOfParent->findAssignedSlot(*node)) {
                    // node is assigned to a slot. Continue dispatching the event at this slot.
                    targetStack.append(target);
                    parent = assignedSlot;
                    target = assignedSlot;
                }
            }
#endif
            node = parent;
        }

        ShadowRoot& shadowRoot = downcast<ShadowRoot>(*node);
        // At a shadow root. Continue dispatching the event at the shadow host.
#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
        if (!targetStack.isEmpty()) {
            // Move target back to a descendant of the shadow host if the event did not originate in this shadow tree or its inner shadow trees.
            target = targetStack.last();
            targetStack.removeLast();
            ASSERT(shadowRoot.host()->contains(target->toNode()));
        } else
#endif
            target = nullptr;

        if (!shouldEventCrossShadowBoundary(event, shadowRoot, originalTarget))
            return;
        node = shadowRoot.host();
    }
}