fix disable qrcodegen option
[LibreOffice.git] / unoxml / source / events / eventdispatcher.cxx
blob40a08305bfd0825c597c76946aaac2523e08f60c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <eventdispatcher.hxx>
22 #include <event.hxx>
23 #include <mutationevent.hxx>
24 #include <uievent.hxx>
25 #include <mouseevent.hxx>
27 #include "../dom/document.hxx"
29 #include <osl/mutex.hxx>
31 using namespace css::uno;
32 using namespace css::xml::dom;
33 using namespace css::xml::dom::events;
35 namespace DOM { namespace events {
37 void CEventDispatcher::addListener(xmlNodePtr pNode, const OUString& aType, const Reference<XEventListener>& aListener, bool bCapture)
39 TypeListenerMap *const pTMap = bCapture
40 ? (& m_CaptureListeners) : (& m_TargetListeners);
42 // get the multimap for the specified type
43 ListenerMap *pMap = nullptr;
44 auto tIter = pTMap->find(aType);
45 if (tIter == pTMap->end()) {
46 // the map has to be created
47 auto const pair = pTMap->emplace(aType, ListenerMap());
48 pMap = & pair.first->second;
49 } else {
50 pMap = & tIter->second;
52 assert(pMap != nullptr);
53 pMap->emplace(pNode, aListener);
56 void CEventDispatcher::removeListener(xmlNodePtr pNode, const OUString& aType, const Reference<XEventListener>& aListener, bool bCapture)
58 TypeListenerMap *const pTMap = bCapture
59 ? (& m_CaptureListeners) : (& m_TargetListeners);
61 // get the multimap for the specified type
62 auto tIter = pTMap->find(aType);
63 if (tIter != pTMap->end()) {
64 ListenerMap & rMap = tIter->second;
65 // find listeners of specified type for specified node
66 ListenerMap::iterator iter = rMap.find(pNode);
67 while (iter != rMap.end() && iter->first == pNode)
69 // erase all references to specified listener
70 if (iter->second.is() && iter->second == aListener)
72 iter = rMap.erase(iter);
74 else
75 ++iter;
80 CEventDispatcher::~CEventDispatcher()
84 void CEventDispatcher::callListeners(
85 TypeListenerMap const& rTMap,
86 xmlNodePtr const pNode,
87 const OUString& aType, Reference< XEvent > const& xEvent)
89 // get the multimap for the specified type
90 TypeListenerMap::const_iterator tIter = rTMap.find(aType);
91 if (tIter != rTMap.end()) {
92 ListenerMap const& rMap = tIter->second;
93 auto iterRange = rMap.equal_range(pNode);
94 for( auto iter = iterRange.first; iter != iterRange.second; ++iter )
96 if(iter->second.is())
97 (iter->second)->handleEvent(xEvent);
102 void CEventDispatcher::dispatchEvent(
103 DOM::CDocument & rDocument, ::osl::Mutex & rMutex,
104 xmlNodePtr const pNode, Reference<XNode> const& xNode,
105 Reference< XEvent > const& i_xEvent) const
107 TypeListenerMap captureListeners;
108 TypeListenerMap targetListeners;
110 ::osl::MutexGuard g(rMutex);
112 captureListeners = m_CaptureListeners;
113 targetListeners = m_TargetListeners;
116 if (captureListeners.empty() && targetListeners.empty())
117 return;
119 CEvent *pEvent = nullptr; // pointer to internal event representation
121 OUString const aType = i_xEvent->getType();
122 if (aType == "DOMSubtreeModified" ||
123 aType == "DOMNodeInserted" ||
124 aType == "DOMNodeRemoved" ||
125 aType == "DOMNodeRemovedFromDocument" ||
126 aType == "DOMNodeInsertedIntoDocument" ||
127 aType == "DOMAttrModified" ||
128 aType == "DOMCharacterDataModified" )
130 Reference< XMutationEvent > const aMEvent(i_xEvent,
131 UNO_QUERY_THROW);
132 // dispatch a mutation event
133 // we need to clone the event in order to have complete control
134 // over the implementation
135 CMutationEvent* pMEvent = new CMutationEvent;
136 pMEvent->initMutationEvent(
137 aType, aMEvent->getBubbles(), aMEvent->getCancelable(),
138 aMEvent->getRelatedNode(), aMEvent->getPrevValue(),
139 aMEvent->getNewValue(), aMEvent->getAttrName(),
140 aMEvent->getAttrChange());
141 pEvent = pMEvent;
142 } else if ( // UIEvent
143 aType == "DOMFocusIn" ||
144 aType == "DOMFocusOut" ||
145 aType == "DOMActivate" )
147 Reference< XUIEvent > const aUIEvent(i_xEvent, UNO_QUERY_THROW);
148 CUIEvent* pUIEvent = new CUIEvent;
149 pUIEvent->initUIEvent(aType,
150 aUIEvent->getBubbles(), aUIEvent->getCancelable(),
151 aUIEvent->getView(), aUIEvent->getDetail());
152 pEvent = pUIEvent;
153 } else if ( // MouseEvent
154 aType == "click" ||
155 aType == "mousedown" ||
156 aType == "mouseup" ||
157 aType == "mouseover" ||
158 aType == "mousemove" ||
159 aType == "mouseout" )
161 Reference< XMouseEvent > const aMouseEvent(i_xEvent,
162 UNO_QUERY_THROW);
163 CMouseEvent *pMouseEvent = new CMouseEvent;
164 pMouseEvent->initMouseEvent(aType,
165 aMouseEvent->getBubbles(), aMouseEvent->getCancelable(),
166 aMouseEvent->getView(), aMouseEvent->getDetail(),
167 aMouseEvent->getScreenX(), aMouseEvent->getScreenY(),
168 aMouseEvent->getClientX(), aMouseEvent->getClientY(),
169 aMouseEvent->getCtrlKey(), aMouseEvent->getAltKey(),
170 aMouseEvent->getShiftKey(), aMouseEvent->getMetaKey(),
171 aMouseEvent->getButton(), aMouseEvent->getRelatedTarget());
172 pEvent = pMouseEvent;
174 else // generic event
176 pEvent = new CEvent;
177 pEvent->initEvent(
178 aType, i_xEvent->getBubbles(), i_xEvent->getCancelable());
180 pEvent->m_target.set(xNode, UNO_QUERY_THROW);
181 pEvent->m_currentTarget = i_xEvent->getCurrentTarget();
182 pEvent->m_time = i_xEvent->getTimeStamp();
184 // create the reference to the private event implementation
185 // that will be dispatched to the listeners
186 Reference< XEvent > const xEvent(pEvent);
188 // build the path from target node to the root
189 typedef std::vector< ::std::pair<Reference<XEventTarget>, xmlNodePtr> >
190 NodeVector_t;
191 NodeVector_t captureVector;
193 ::osl::MutexGuard g(rMutex);
195 xmlNodePtr cur = pNode;
196 while (cur != nullptr)
198 Reference< XEventTarget > const xRef(
199 rDocument.GetCNode(cur).get());
200 captureVector.emplace_back(xRef, cur);
201 cur = cur->parent;
205 // the capture vector now holds the node path from target to root
206 // first we must search for capture listeners in order root to
207 // to target. after that, any target listeners have to be called
208 // then bubbeling phase listeners are called in target to root
209 // order
210 // start at the root
211 NodeVector_t::const_reverse_iterator rinode =
212 const_cast<NodeVector_t const&>(captureVector).rbegin();
213 if (rinode != const_cast<NodeVector_t const&>(captureVector).rend())
215 // capturing phase:
216 pEvent->m_phase = PhaseType_CAPTURING_PHASE;
217 while (rinode !=
218 const_cast<NodeVector_t const&>(captureVector).rend())
220 pEvent->m_currentTarget = rinode->first;
221 callListeners(captureListeners, rinode->second, aType, xEvent);
222 if (pEvent->m_canceled) return;
223 ++rinode;
226 NodeVector_t::const_iterator inode = captureVector.begin();
228 // target phase
229 pEvent->m_phase = PhaseType_AT_TARGET;
230 pEvent->m_currentTarget = inode->first;
231 callListeners(targetListeners, inode->second, aType, xEvent);
232 if (pEvent->m_canceled) return;
233 // bubbeling phase
234 ++inode;
235 if (i_xEvent->getBubbles()) {
236 pEvent->m_phase = PhaseType_BUBBLING_PHASE;
237 while (inode != captureVector.end())
239 pEvent->m_currentTarget = inode->first;
240 callListeners(targetListeners,
241 inode->second, aType, xEvent);
242 if (pEvent->m_canceled) return;
243 ++inode;
250 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */