1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include <eventdispatcher.hxx> 25 26 #include <event.hxx> 27 #include <mutationevent.hxx> 28 #include <uievent.hxx> 29 #include <mouseevent.hxx> 30 31 #include "../dom/document.hxx" 32 33 34 namespace DOM { namespace events { 35 addListener(xmlNodePtr pNode,OUString aType,const Reference<XEventListener> & aListener,sal_Bool bCapture)36 void CEventDispatcher::addListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture) 37 { 38 TypeListenerMap *const pTMap = (bCapture) 39 ? (& m_CaptureListeners) : (& m_TargetListeners); 40 41 // get the multimap for the specified type 42 ListenerMap *pMap = 0; 43 TypeListenerMap::const_iterator tIter = pTMap->find(aType); 44 if (tIter == pTMap->end()) { 45 // the map has to be created 46 pMap = new ListenerMap(); 47 pTMap->insert(TypeListenerMap::value_type(aType, pMap)); 48 } else { 49 pMap = tIter->second; 50 } 51 if (pMap !=0) 52 pMap->insert(ListenerMap::value_type(pNode, aListener)); 53 } 54 removeListener(xmlNodePtr pNode,OUString aType,const Reference<XEventListener> & aListener,sal_Bool bCapture)55 void CEventDispatcher::removeListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture) 56 { 57 TypeListenerMap *const pTMap = (bCapture) 58 ? (& m_CaptureListeners) : (& m_TargetListeners); 59 60 // get the multimap for the specified type 61 TypeListenerMap::const_iterator tIter = pTMap->find(aType); 62 if (tIter != pTMap->end()) { 63 ListenerMap *pMap = tIter->second; 64 // find listeners of specied type for specified node 65 ListenerMap::iterator iter = pMap->find(pNode); 66 while (iter != pMap->end() && iter->first == pNode) 67 { 68 // erase all references to specified listener 69 if ((iter->second).is() && iter->second == aListener) 70 { 71 ListenerMap::iterator tmp_iter = iter; 72 iter++; 73 pMap->erase(tmp_iter); 74 } 75 else 76 iter++; 77 } 78 } 79 } 80 callListeners(TypeListenerMap const & rTMap,xmlNodePtr const pNode,OUString aType,Reference<XEvent> const & xEvent)81 void CEventDispatcher::callListeners( 82 TypeListenerMap const& rTMap, 83 xmlNodePtr const pNode, 84 OUString aType, Reference< XEvent > const& xEvent) 85 { 86 // get the multimap for the specified type 87 TypeListenerMap::const_iterator tIter = rTMap.find(aType); 88 if (tIter != rTMap.end()) { 89 ListenerMap *pMap = tIter->second; 90 ListenerMap::const_iterator iter = pMap->lower_bound(pNode); 91 ListenerMap::const_iterator ibound = pMap->upper_bound(pNode); 92 for( ; iter != ibound; iter++ ) 93 { 94 if((iter->second).is()) 95 (iter->second)->handleEvent(xEvent); 96 } 97 } 98 } 99 dispatchEvent(DOM::CDocument & rDocument,::osl::Mutex & rMutex,xmlNodePtr const pNode,Reference<XNode> const & xNode,Reference<XEvent> const & i_xEvent) const100 bool CEventDispatcher::dispatchEvent( 101 DOM::CDocument & rDocument, ::osl::Mutex & rMutex, 102 xmlNodePtr const pNode, Reference<XNode> const& xNode, 103 Reference< XEvent > const& i_xEvent) const 104 { 105 CEvent *pEvent = 0; // pointer to internal event representation 106 107 OUString const aType = i_xEvent->getType(); 108 if (aType.compareToAscii("DOMSubtreeModified") == 0|| 109 aType.compareToAscii("DOMNodeInserted") == 0|| 110 aType.compareToAscii("DOMNodeRemoved") == 0|| 111 aType.compareToAscii("DOMNodeRemovedFromDocument") == 0|| 112 aType.compareToAscii("DOMNodeInsertedIntoDocument") == 0|| 113 aType.compareToAscii("DOMAttrModified") == 0|| 114 aType.compareToAscii("DOMCharacterDataModified") == 0) 115 { 116 Reference< XMutationEvent > const aMEvent(i_xEvent, 117 UNO_QUERY_THROW); 118 // dispatch a mutation event 119 // we need to clone the event in order to have complete control 120 // over the implementation 121 CMutationEvent* pMEvent = new CMutationEvent; 122 pMEvent->initMutationEvent( 123 aType, aMEvent->getBubbles(), aMEvent->getCancelable(), 124 aMEvent->getRelatedNode(), aMEvent->getPrevValue(), 125 aMEvent->getNewValue(), aMEvent->getAttrName(), 126 aMEvent->getAttrChange()); 127 pEvent = pMEvent; 128 } else if ( // UIEvent 129 aType.compareToAscii("DOMFocusIn") == 0|| 130 aType.compareToAscii("DOMFocusOut") == 0|| 131 aType.compareToAscii("DOMActivate") == 0) 132 { 133 Reference< XUIEvent > const aUIEvent(i_xEvent, UNO_QUERY_THROW); 134 CUIEvent* pUIEvent = new CUIEvent; 135 pUIEvent->initUIEvent(aType, 136 aUIEvent->getBubbles(), aUIEvent->getCancelable(), 137 aUIEvent->getView(), aUIEvent->getDetail()); 138 pEvent = pUIEvent; 139 } else if ( // MouseEvent 140 aType.compareToAscii("click") == 0|| 141 aType.compareToAscii("mousedown") == 0|| 142 aType.compareToAscii("mouseup") == 0|| 143 aType.compareToAscii("mouseover") == 0|| 144 aType.compareToAscii("mousemove") == 0|| 145 aType.compareToAscii("mouseout") == 0) 146 { 147 Reference< XMouseEvent > const aMouseEvent(i_xEvent, 148 UNO_QUERY_THROW); 149 CMouseEvent *pMouseEvent = new CMouseEvent; 150 pMouseEvent->initMouseEvent(aType, 151 aMouseEvent->getBubbles(), aMouseEvent->getCancelable(), 152 aMouseEvent->getView(), aMouseEvent->getDetail(), 153 aMouseEvent->getScreenX(), aMouseEvent->getScreenY(), 154 aMouseEvent->getClientX(), aMouseEvent->getClientY(), 155 aMouseEvent->getCtrlKey(), aMouseEvent->getAltKey(), 156 aMouseEvent->getShiftKey(), aMouseEvent->getMetaKey(), 157 aMouseEvent->getButton(), aMouseEvent->getRelatedTarget()); 158 pEvent = pMouseEvent; 159 } 160 else // generic event 161 { 162 pEvent = new CEvent; 163 pEvent->initEvent( 164 aType, i_xEvent->getBubbles(), i_xEvent->getCancelable()); 165 } 166 pEvent->m_target.set(xNode, UNO_QUERY_THROW); 167 pEvent->m_currentTarget = i_xEvent->getCurrentTarget(); 168 pEvent->m_time = i_xEvent->getTimeStamp(); 169 170 // create the reference to the provate event implementation 171 // that will be dispatched to the listeners 172 Reference< XEvent > const xEvent(pEvent); 173 174 // build the path from target node to the root 175 typedef std::vector< ::std::pair<Reference<XEventTarget>, xmlNodePtr> > 176 NodeVector_t; 177 NodeVector_t captureVector; 178 TypeListenerMap captureListeners; 179 TypeListenerMap targetListeners; 180 { 181 ::osl::MutexGuard g(rMutex); 182 183 xmlNodePtr cur = pNode; 184 while (cur != NULL) 185 { 186 Reference< XEventTarget > const xRef( 187 rDocument.GetCNode(cur).get()); 188 captureVector.push_back(::std::make_pair(xRef, cur)); 189 cur = cur->parent; 190 } 191 captureListeners = m_CaptureListeners; 192 targetListeners = m_TargetListeners; 193 } 194 195 // the caputre vector now holds the node path from target to root 196 // first we must search for capture listernes in order root to 197 // to target. after that, any target listeners have to be called 198 // then bubbeling phase listeners are called in target to root 199 // order 200 // start at the root 201 NodeVector_t::const_reverse_iterator rinode = 202 const_cast<NodeVector_t const&>(captureVector).rbegin(); 203 if (rinode != const_cast<NodeVector_t const&>(captureVector).rend()) 204 { 205 // capturing phase: 206 pEvent->m_phase = PhaseType_CAPTURING_PHASE; 207 while (rinode != 208 const_cast<NodeVector_t const&>(captureVector).rend()) 209 { 210 pEvent->m_currentTarget = rinode->first; 211 callListeners(captureListeners, rinode->second, aType, xEvent); 212 if (pEvent->m_canceled) return sal_True; 213 rinode++; 214 } 215 216 NodeVector_t::const_iterator inode = captureVector.begin(); 217 218 // target phase 219 pEvent->m_phase = PhaseType_AT_TARGET; 220 pEvent->m_currentTarget = inode->first; 221 callListeners(targetListeners, inode->second, aType, xEvent); 222 if (pEvent->m_canceled) return sal_True; 223 // bubbeling phase 224 inode++; 225 if (i_xEvent->getBubbles()) { 226 pEvent->m_phase = PhaseType_BUBBLING_PHASE; 227 while (inode != captureVector.end()) 228 { 229 pEvent->m_currentTarget = inode->first; 230 callListeners(targetListeners, 231 inode->second, aType, xEvent); 232 if (pEvent->m_canceled) return sal_True; 233 inode++; 234 } 235 } 236 } 237 return sal_True; 238 } 239 }} 240