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