Ejemplo n.º 1
0
void HTMLStyleElementImp::handleMutation(EventListenerImp* listener, events::Event event)
{
    // TODO: update type, media, and scoped. Then check type.

    events::MutationEvent mutation(interface_cast<events::MutationEvent>(event));

    DocumentImp* document = getOwnerDocumentImp();
    if (!document)
        return;

    if (mutation.getType() == u"DOMNodeRemoved" && event.getTarget().self() == this)
        styleSheet = 0;
    else {
        std::u16string content;
        for (Node node = getFirstChild(); node; node = node.getNextSibling()) {
            if (TextImp* text = dynamic_cast<TextImp*>(node.self()))  // TODO better to avoid imp call?
                content += text->getData();
        }
        CSSParser parser;
        styleSheet = parser.parse(document, content);
        if (auto imp = dynamic_cast<CSSStyleSheetImp*>(styleSheet.self())) {
            imp->setOwnerNode(this);
            if (4 <= getLogLevel())
                dumpStyleSheet(std::cerr, imp);
        }
    }
    if (WindowImp* view = document->getDefaultWindow())
        view->setFlags(Box::NEED_SELECTOR_REMATCHING);
    document->resetStyleSheets();
}
Ejemplo n.º 2
0
bool EventTargetImp::dispatchEvent(events::Event evt)
{
    EventImp* event = dynamic_cast<EventImp*>(evt.self());
    if (!event)
        return false;

    event->setDispatchFlag(true);
    if (auto documentWindow = dynamic_cast<DocumentWindow*>(this))
        event->setTarget(documentWindow->getWindowImp());
    else
        event->setTarget(this);

    if (NodeImp* node = dynamic_cast<NodeImp*>(this)) {
        DocumentImp* document = dynamic_cast<DocumentImp*>(node);
        if (!document)
            document = node->getOwnerDocumentImp();
        assert(document);

        document->enter();

        std::list<EventTargetImp*> eventPath;
        for (NodeImp* ancestor = node->parentNode; ancestor; ancestor = ancestor->parentNode) {
            if (auto shadowTree = dynamic_cast<HTMLTemplateElementImp*>(ancestor)) {
                if (NodeImp* host = dynamic_cast<NodeImp*>(shadowTree->getHost().self())) {
                    // TODO: Fix 'target' of the event as well.
                    // TODO: Check the mouseover and mouseout events.
                    ancestor = host;
                    if (!dynamic_cast<UIEventImp*>(event)) {
                        // To repaint the window, we still need to notify the bound document
                        // of the event.
                        // TODO: Support nesting of bound elements.
                        eventPath.push_front(ancestor->getOwnerDocumentImp());
                        break;
                    }
                }
            }
            eventPath.push_front(ancestor);
        }

        // cf. http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#events-and-the-window-object
        if (document && event->getType() != u"load") {
            if (WindowImp* view = document->getDefaultWindow())
                eventPath.push_front(view->getDocumentWindow().get());
        }

        event->setEventPhase(events::Event::CAPTURING_PHASE);
        for (auto i = eventPath.begin(); i != eventPath.end(); ++i) {
            if (event->getStopPropagationFlag())
                break;
            event->setCurrentTarget(*i);
            (*i)->invoke(event);
        }

        event->setEventPhase(events::Event::AT_TARGET);
        if (!event->getStopPropagationFlag()) {
            event->setCurrentTarget(node);
            node->invoke(event);
        }

        if (event->getBubbles()) {
            event->setEventPhase(events::Event::BUBBLING_PHASE);
            for (auto i = eventPath.rbegin(); i != eventPath.rend(); ++i) {
                if (event->getStopPropagationFlag())
                    break;
                event->setCurrentTarget(*i);
                (*i)->invoke(event);
            }
        }

        if (!event->getDefaultPrevented()) {
            // TODO: Call default actions;
            // cf. http://www.w3.org/TR/DOM-Level-3-Events/#event-flow-default-cancel
            // cf. http://www.w3.org/TR/xbl/#the-default-phase0
            event->setEventPhase(EventImp::DEFAULT_PHASE);
            event->setCurrentTarget(node);
            node->invoke(event);
            if (event->getBubbles()) {
                for (auto i = eventPath.rbegin(); i != eventPath.rend(); ++i) {
                    if (event->getDefaultPrevented())
                        break;
                    event->setCurrentTarget(*i);
                    (*i)->invoke(event);
                }
            }
        }

        document->exit();

    } else if (DocumentWindow* window = dynamic_cast<DocumentWindow*>(this)) {
        auto proxy = dynamic_cast<WindowImp*>(window->getDocument().getDefaultView().self());
        window->enter(proxy);
        event->setEventPhase(events::Event::AT_TARGET);
        event->setCurrentTarget(this);
        invoke(event);
        window->exit(proxy);
    }
    event->setDispatchFlag(false);
    event->setEventPhase(events::Event::AT_TARGET);
    event->setCurrentTarget(0);

    return !event->getDefaultPrevented();
}