📄 dom_nodeimpl.cpp
字号:
return count;}void NodeImpl::addEventListener(int id, EventListener *listener, const bool useCapture){ switch (id) { case EventImpl::DOMSUBTREEMODIFIED_EVENT: getDocument()->addListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER); break; case EventImpl::DOMNODEINSERTED_EVENT: getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER); break; case EventImpl::DOMNODEREMOVED_EVENT: getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER); break; case EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT: getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER); break; case EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT: getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER); break; case EventImpl::DOMATTRMODIFIED_EVENT: getDocument()->addListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER); break; case EventImpl::DOMCHARACTERDATAMODIFIED_EVENT: getDocument()->addListenerType(DocumentImpl::DOMCHARACTERDATAMODIFIED_LISTENER); break; default: break; } RegisteredEventListener *rl = new RegisteredEventListener(static_cast<EventImpl::EventId>(id),listener,useCapture); if (!m_regdListeners) { m_regdListeners = new QPtrList<RegisteredEventListener>; m_regdListeners->setAutoDelete(true); } listener->ref(); // remove existing identical listener set with identical arguments - the DOM2 // spec says that "duplicate instances are discarded" in this case. removeEventListener(id,listener,useCapture); m_regdListeners->append(rl); listener->deref();}void NodeImpl::removeEventListener(int id, EventListener *listener, bool useCapture){ if (!m_regdListeners) // nothing to remove return; RegisteredEventListener rl(static_cast<EventImpl::EventId>(id),listener,useCapture); QPtrListIterator<RegisteredEventListener> it(*m_regdListeners); for (; it.current(); ++it) if (*(it.current()) == rl) { m_regdListeners->removeRef(it.current()); return; }}void NodeImpl::removeHTMLEventListener(int id){ if (!m_regdListeners) // nothing to remove return; QPtrListIterator<RegisteredEventListener> it(*m_regdListeners); for (; it.current(); ++it) if (it.current()->id == id && it.current()->listener->eventListenerType() == "_khtml_HTMLEventListener") { m_regdListeners->removeRef(it.current()); return; }}void NodeImpl::setHTMLEventListener(int id, EventListener *listener){ // in case we already have it, we don't want removeHTMLEventListener to destroy it if (listener) listener->ref(); removeHTMLEventListener(id); if (listener) { addEventListener(id,listener,false); listener->deref(); }}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->setTarget(this); KHTMLPart *part = document->document()->part(); // Since event handling code could cause this object to be deleted, grab a reference to the view now KHTMLView *view = document->document()->view(); 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(); return ret;}bool NodeImpl::dispatchGenericEvent( EventImpl *evt, int &/*exceptioncode */){ // ### 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); } // In the case of a mouse click, also send a DOMActivate event, which causes things like form submissions // to occur. Note that this only happens for _real_ mouse clicks (for which we get a KHTML_CLICK_EVENT or // KHTML_DBLCLICK_EVENT), not the standard DOM "click" event that could be sent from js code. if (!evt->defaultPrevented() && !disabled()) if (evt->id() == EventImpl::KHTML_CLICK_EVENT) dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, 1); else if (evt->id() == EventImpl::KHTML_DBLCLICK_EVENT) dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, 2); // deref all nodes in chain it.toFirst(); for (; it.current(); ++it) it.current()->deref(); // this may delete us DocumentImpl::updateDocumentsRendering(); return !evt->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); evt->ref(); bool r = dispatchEvent(evt,exceptioncode,true); evt->deref(); return r;}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. DOM::ElementImpl* elt = doc->document()->ownerElement(); if (elt && (elt->getDocument()->domain().isNull() || 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; detail = 1; // ### support for multiple double clicks 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;// 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 int screenX = _mouse->globalX(); int screenY = _mouse->globalY(); 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 = false; // ### qt support? EventImpl *evt = new MouseEventImpl(evtId,true,cancelable,getDocument()->defaultView(), detail,screenX,screenY,clientX,clientY,ctrlKey,altKey,shiftKey,metaKey, button,0); evt->ref(); bool r = dispatchEvent(evt,exceptioncode,true); evt->deref(); return r;}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; UIEventImpl *evt = new UIEventImpl(static_cast<EventImpl::EventId>(_id),true, cancelable,getDocument()->defaultView(),detail); evt->ref(); bool r = dispatchEvent(evt,exceptioncode,true); evt->deref(); return r;}bool NodeImpl::dispatchSubtreeModifiedEvent(){ 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); }}void NodeImpl::defaultEventHandler(EventImpl *evt){}unsigned long NodeImpl::childNodeCount(){ return 0;}NodeImpl *NodeImpl::childNode(unsigned long /*index*/){ return 0;}NodeImpl *NodeImpl::traverseNextNode(NodeImpl *stayWithin) const{ if (firstChild()) return firstChild(); if (nextSibling()) return nextSibling(); const NodeImpl *n = this; while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin)) n = n->parentNode(); if (n && (!stayWithin || n->parentNode() != stayWithin)) return n->nextSibling(); return 0;}NodeImpl *NodeImpl::traverseNextSibling(NodeImpl *stayWithin) const{ if (nextSibling()) return nextSibling(); const NodeImpl *n = this; while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin)) n = n->parentNode(); if (n && (!stayWithin || n->parentNode() != stayWithin)) return n->nextSibling(); return 0;}NodeImpl *NodeImpl::traversePreviousNode() const{ if (previousSibling()) { NodeImpl *n = previousSibling(); while (n->lastChild()) n = n->lastChild(); return n; } else if (parentNode()) { return parentNode(); } else { return 0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -