⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dom_nodeimpl.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 5 页
字号:
}

EventListener *NodeImpl::getHTMLEventListener(int id)
{
    if (!m_regdListeners)
        return 0;

    QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
    for (; it.current(); ++it)
        if (it.current()->id == id &&
            it.current()->listener->eventListenerType() == "_khtml_HTMLEventListener") {
            return it.current()->listener;
        }
    return 0;
}


bool NodeImpl::dispatchEvent(EventImpl *evt, int &exceptioncode, bool tempEvent)
{
    evt->ref();

    evt->setTarget(this);

    // We've had at least one report of a crash on a page where document is nil here.
    // Unfortunately that page no longer exists, but we'll make this code robust against
    // that anyway.
    // FIXME: Much code in this class assumes document is non-nil; it would be better to
    // ensure that document can never be nil.
    KHTMLPart *part = 0;
    KHTMLView *view = 0;

    if (document && document->document()) {
        part = document->document()->part();
        view = document->document()->view();
        // Since event handling code could cause this object to be deleted, grab a reference to the view now
        if (view)
            view->ref();
    }

    bool ret = dispatchGenericEvent( evt, exceptioncode );

    // If tempEvent is true, this means that the DOM implementation will not be storing a reference to the event, i.e.
    // there is no way to retrieve it from javascript if a script does not already have a reference to it in a variable.
    // So there is no need for the interpreter to keep the event in it's cache
    if (tempEvent && part && part->jScript())
        part->jScript()->finishedWithEvent(evt);

    if (view)
        view->deref();

    evt->deref();

    return ret;
}

bool NodeImpl::dispatchGenericEvent( EventImpl *evt, int &/*exceptioncode */)
{
    evt->ref();

    // ### check that type specified

    // work out what nodes to send event to
    QPtrList<NodeImpl> nodeChain;
    NodeImpl *n;
    for (n = this; n; n = n->parentNode()) {
        n->ref();
        nodeChain.prepend(n);
    }

    // trigger any capturing event handlers on our way down
    evt->setEventPhase(Event::CAPTURING_PHASE);
    QPtrListIterator<NodeImpl> it(nodeChain);
    for (; it.current() && it.current() != this && !evt->propagationStopped(); ++it) {
        evt->setCurrentTarget(it.current());
        it.current()->handleLocalEvents(evt,true);
    }

    // dispatch to the actual target node
    it.toLast();
    if (!evt->propagationStopped()) {
        evt->setEventPhase(Event::AT_TARGET);
        evt->setCurrentTarget(it.current());

	// Capturing first. -dwh
        it.current()->handleLocalEvents(evt,true);

	// Bubbling second. -dwh
	if (!evt->propagationStopped())
            it.current()->handleLocalEvents(evt,false);
    }
    --it;

    // ok, now bubble up again (only non-capturing event handlers will be called)
    // ### recalculate the node chain here? (e.g. if target node moved in document by previous event handlers)
    // no. the DOM specs says:
    // The chain of EventTargets from the event target to the top of the tree
    // is determined before the initial dispatch of the event.
    // If modifications occur to the tree during event processing,
    // event flow will proceed based on the initial state of the tree.
    //
    // since the initial dispatch is before the capturing phase,
    // there's no need to recalculate the node chain.
    // (tobias)

    if (evt->bubbles()) {
        evt->setEventPhase(Event::BUBBLING_PHASE);
        for (; it.current() && !evt->propagationStopped() && !evt->getCancelBubble(); --it) {
            evt->setCurrentTarget(it.current());
            it.current()->handleLocalEvents(evt,false);
        }
    }

    evt->setCurrentTarget(0);
    evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say
                           // anything about the default event handler phase.


    if (evt->bubbles()) {
	// now we call all default event handlers (this is not part of DOM - it is internal to khtml)

	it.toLast();
	for (; it.current() && !evt->propagationStopped() && !evt->defaultPrevented() && !evt->defaultHandled(); --it)
	    it.current()->defaultEventHandler(evt);
    }

    // deref all nodes in chain
    it.toFirst();
    for (; it.current(); ++it)
        it.current()->deref(); // this may delete us

    DocumentImpl::updateDocumentsRendering();

    bool defaultPrevented = evt->defaultPrevented();

    evt->deref();

    return !defaultPrevented; // ### what if defaultPrevented was called before dispatchEvent?
}

bool NodeImpl::dispatchHTMLEvent(int _id, bool canBubbleArg, bool cancelableArg)
{
    int exceptioncode = 0;
    EventImpl *evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
    return dispatchEvent(evt,exceptioncode,true);
}

bool NodeImpl::dispatchWindowEvent(int _id, bool canBubbleArg, bool cancelableArg)
{
    int exceptioncode = 0;
    EventImpl *evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
    evt->setTarget( 0 );
    evt->ref();
    DocumentPtr *doc = document;
    doc->ref();
    bool r = dispatchGenericEvent( evt, exceptioncode );
    if (!evt->defaultPrevented() && doc->document())
	doc->document()->defaultEventHandler(evt);

    if (_id == EventImpl::LOAD_EVENT && !evt->propagationStopped() && doc->document()) {
        // For onload events, send them to the enclosing frame only.
        // This is a DOM extension and is independent of bubbling/capturing rules of
        // the DOM.  You send the event only to the enclosing frame.  It does not
        // bubble through the parent document.
        ElementImpl* elt = doc->document()->ownerElement();
        if (elt && (elt->getDocument()->domain().isEmpty() ||
                    elt->getDocument()->domain() == doc->document()->domain())) {
            // We also do a security check, since we don't want to allow the enclosing
            // iframe to see loads of child documents in other domains.
            evt->setCurrentTarget(elt);

            // Capturing first.
            elt->handleLocalEvents(evt,true);

            // Bubbling second.
            if (!evt->propagationStopped())
                elt->handleLocalEvents(evt,false);
            r = !evt->defaultPrevented();
        }
    }

    doc->deref();
    evt->deref();

    return r;
}

bool NodeImpl::dispatchMouseEvent(QMouseEvent *_mouse, int overrideId, int overrideDetail)
{
    bool cancelable = true;
    int detail = overrideDetail; // defaults to 0
    EventImpl::EventId evtId = EventImpl::UNKNOWN_EVENT;
    if (overrideId) {
        evtId = static_cast<EventImpl::EventId>(overrideId);
    }
    else {
        switch (_mouse->type()) {
            case QEvent::MouseButtonPress:
                evtId = EventImpl::MOUSEDOWN_EVENT;
                break;
            case QEvent::MouseButtonRelease:
                evtId = EventImpl::MOUSEUP_EVENT;
                break;
            case QEvent::MouseButtonDblClick:
                evtId = EventImpl::CLICK_EVENT;
#if APPLE_CHANGES
                detail = _mouse->clickCount();
#else
                detail = 1; // ### support for multiple double clicks
#endif
                break;
            case QEvent::MouseMove:
                evtId = EventImpl::MOUSEMOVE_EVENT;
                cancelable = false;
                break;
            default:
                break;
        }
    }
    if (evtId == EventImpl::UNKNOWN_EVENT)
        return false; // shouldn't happen


    int exceptioncode = 0;

#if APPLE_CHANGES
// Careful here - our viewportToContents() converts points from NSEvents, in NSWindow coord system to
// our khtmlview's coord system.  This works for QMouseEvents coming from Cocoa because those events
// hold the location from the NSEvent.  The QMouseEvent param here was made by other khtml code, so it
// will be a "proper" QT event with coords in terms of this widget.  So in WebCore it would never be
// right to pass coords from _mouse to viewportToContents().
#endif
//    int clientX, clientY;
//    viewportToContents(_mouse->x(), _mouse->y(), clientX, clientY);
    int clientX = _mouse->x(); // ### adjust to be relative to view
    int clientY = _mouse->y(); // ### adjust to be relative to view

#if APPLE_CHANGES
    int screenX;
    int screenY;
    KHTMLView *view = document->document()->view();
    if (view) {
        // This gets us as far as NSWindow coords
        QPoint windowLoc = view->contentsToViewport(_mouse->pos());
        // Then from NSWindow coords to screen coords
        QPoint screenLoc = view->viewportToGlobal(windowLoc);
        screenX = screenLoc.x();
        screenY = screenLoc.y();
    } else {
        screenX = _mouse->x();
        screenY = _mouse->y();
    }
#else
    int screenX = _mouse->globalX();
    int screenY = _mouse->globalY();
#endif

    int button = -1;
    switch (_mouse->button()) {
        case Qt::LeftButton:
            button = 0;
            break;
        case Qt::MidButton:
            button = 1;
            break;
        case Qt::RightButton:
            button = 2;
            break;
        default:
            break;
    }
    bool ctrlKey = (_mouse->state() & Qt::ControlButton);
    bool altKey = (_mouse->state() & Qt::AltButton);
    bool shiftKey = (_mouse->state() & Qt::ShiftButton);
    bool metaKey = (_mouse->state() & Qt::MetaButton);

    bool swallowEvent = false;

    EventImpl *me = new MouseEventImpl(evtId,true,cancelable,getDocument()->defaultView(),
                   detail,screenX,screenY,clientX,clientY,ctrlKey,altKey,shiftKey,metaKey,
                   button,0);
    me->ref();
    dispatchEvent(me, exceptioncode, true);
    bool defaultHandled = me->defaultHandled();
    bool defaultPrevented = me->defaultPrevented();
    if (defaultHandled || defaultPrevented)
        swallowEvent = true;
    me->deref();

#if APPLE_CHANGES
    // Special case: If it's a click event, we also send the KHTML_CLICK or KHTML_DBLCLICK event. This is not part
    // of the DOM specs, but is used for compatibility with the traditional onclick="" and ondblclick="" attributes,
    // as there is no way to tell the difference between single & double clicks using DOM (only the click count is
    // stored, which is not necessarily the same)
    if (evtId == EventImpl::CLICK_EVENT) {
        evtId = EventImpl::KHTML_CLICK_EVENT;

        me = new MouseEventImpl(EventImpl::KHTML_CLICK_EVENT,
                                true,cancelable,getDocument()->defaultView(),
                                detail,screenX,screenY,clientX,clientY,
                                ctrlKey,altKey,shiftKey,metaKey,
                                button,0);
        me->ref();
        if (defaultHandled)
            me->setDefaultHandled();
        dispatchEvent(me,exceptioncode,true);
        if (me->defaultHandled())
            defaultHandled = true;
        if (me->defaultPrevented())
            defaultPrevented = true;
        if (me->defaultHandled() || me->defaultPrevented())
            swallowEvent = true;
        me->deref();

        if (_mouse->isDoubleClick()) {
            me = new MouseEventImpl(EventImpl::KHTML_DBLCLICK_EVENT,
                                    true,cancelable,getDocument()->defaultView(),
                                    detail,screenX,screenY,clientX,clientY,
                                    ctrlKey,altKey,shiftKey,metaKey,
                                    button,0);
            me->ref();
            if (defaultHandled)
                me->setDefaultHandled();
            dispatchEvent(me,exceptioncode,true);
            if (me->defaultHandled() || me->defaultPrevented())
                swallowEvent = true;
            me->deref();
        }
    }
#endif

    // Also send a DOMActivate event, which causes things like form submissions to occur.
    if (evtId == EventImpl::KHTML_CLICK_EVENT && !defaultPrevented && !disabled())
        dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, detail);

    return swallowEvent;
}

bool NodeImpl::dispatchUIEvent(int _id, int detail)
{
    assert (!( (_id != EventImpl::DOMFOCUSIN_EVENT &&
        _id != EventImpl::DOMFOCUSOUT_EVENT &&
                _id != EventImpl::DOMACTIVATE_EVENT)));

    bool cancelable = false;
    if (_id == EventImpl::DOMACTIVATE_EVENT)
        cancelable = true;

    int exceptioncode = 0;
    if (getDocument()) {
        UIEventImpl *evt = new UIEventImpl(static_cast<EventImpl::EventId>(_id),true,
                                           cancelable,getDocument()->defaultView(),detail);
        return dispatchEvent(evt,exceptioncode,true);
    }
    return false;
}

void NodeImpl::registerNodeList(NodeListImpl *list)
{
    if (!m_nodeLists) {
        m_nodeLists = new QPtrDict<NodeListImpl>;
    }

    m_nodeLists->insert(list, list);
}

void NodeImpl::unregisterNodeList(NodeListImpl *list)
{
    if (!m_nodeLists)
        return;

    m_nodeLists->remove(list);
}

void NodeImpl::notifyLocalNodeListsSubtreeModified()
{
    if (!m_nodeLists)
        return;

    QPtrDictIterator<NodeListImpl> i(*m_nodeLists);

    while (NodeListImpl *list = i.current()) {
        list->rootNodeSubtreeModified();
        ++i;
    }
}

void NodeImpl::notifyNodeListsSubtreeModified()
{
    for (NodeImpl *n = this; n; n = n->parentNode()) {
        n->notifyLocalNodeListsSubtreeModified();
    }
}

bool NodeImpl::dispatchSubtreeModifiedEvent(bool sendChildrenChanged)
{
    notifyNodeListsSubtreeModified();
    if (sendChildrenChanged)
        childrenChanged();
    if (!getDocument()->hasListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER))
	return false;
    int exceptioncode = 0;
    return dispatchEvent(new MutationEventImpl(EventImpl::DOMSUBTREEMODIFIED_EVENT,
			 true,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
}

bool NodeImpl::dispatchKeyEvent(QKeyEvent *key)
{
    int exceptioncode = 0;
    //kdDebug(6010) << "DOM::NodeImpl: dispatching keyboard event" << endl;
    KeyboardEventImpl *keyboardEventImpl = new KeyboardEventImpl(key, getDocument()->defaultView());
    keyboardEventImpl->ref();
    bool r = dispatchEvent(keyboardEventImpl,exceptioncode,true);

#if APPLE_CHANGES
    // we want to return false if default is prevented (already taken care of)
    // or if the element is default-handled by the DOM. Otherwise we let it just
    // let it get handled by AppKit
    if (keyboardEventImpl->defaultHandled())
#else
    // the default event handler should accept() the internal QKeyEvent
    // to prevent the view from further evaluating it.
    if (!keyboardEventImpl->defaultPrevented() && !keyboardEventImpl->qKeyEvent->isAccepted())
#endif
      r = false;

    keyboardEventImpl->deref();
    return r;
}

void NodeImpl::handleLocalEvents(EventImpl *evt, bool useCapture)
{
    if (!m_regdListeners)
        return;

    if (disabled() && evt->isMouseEvent())
        return;

    QPtrList<RegisteredEventListener> listenersCopy = *m_regdListeners;
    QPtrListIterator<RegisteredEventListener> it(listenersCopy);
    Event ev = evt;
    for (; it.current(); ++it) {
        if (it.current()->id == evt->id() && it.current()->useCapture == useCapture)
            it.current()->listener->handleEvent(ev, false);
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -