1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <multiplexer.hxx>
21
22 #include <osl/diagnose.h>
23 #include <cppuhelper/queryinterface.hxx>
24
25 #include <com/sun/star/awt/XWindow.hpp>
26 #include <com/sun/star/awt/XTopWindow.hpp>
27
28 using namespace ::cppu;
29 using namespace ::osl;
30 using namespace ::com::sun::star::uno;
31 using namespace ::com::sun::star::awt;
32 using namespace ::com::sun::star::lang;
33
34 namespace unocontrols {
35
36 // macros
37
38 #define MULTIPLEX( INTERFACE, METHOD, EVENTTYP, EVENT ) \
39 \
40 /* First get all interfaces from container with right type.*/ \
41 OInterfaceContainerHelper* pContainer = m_aListenerHolder.getContainer( cppu::UnoType<INTERFACE>::get() ); \
42 /* Do the follow only, if elements in container exist.*/ \
43 if( pContainer != nullptr ) \
44 { \
45 OInterfaceIteratorHelper aIterator( *pContainer ); \
46 EVENTTYP aLocalEvent = EVENT; \
47 /* Remark: The control is the event source not the peer.*/ \
48 /* We must change the source of the event. */ \
49 aLocalEvent.Source = m_xControl; \
50 /* Is the control not destroyed? */ \
51 if( aLocalEvent.Source.is() ) \
52 { \
53 if( aIterator.hasMoreElements() ) \
54 { \
55 INTERFACE * pListener = static_cast<INTERFACE *>(aIterator.next()); \
56 try \
57 { \
58 pListener->METHOD( aLocalEvent ); \
59 } \
60 catch(const RuntimeException& ) \
61 { \
62 /* Ignore all system exceptions from the listener! */ \
63 } \
64 } \
65 } \
66 }
67
68 // construct/destruct
69
OMRCListenerMultiplexerHelper(const Reference<XWindow> & xControl,const Reference<XWindow> & xPeer)70 OMRCListenerMultiplexerHelper::OMRCListenerMultiplexerHelper( const Reference< XWindow >& xControl ,
71 const Reference< XWindow >& xPeer )
72 : m_xPeer ( xPeer )
73 , m_xControl ( xControl )
74 , m_aListenerHolder ( m_aMutex )
75 {
76 }
77
OMRCListenerMultiplexerHelper(const OMRCListenerMultiplexerHelper & aCopyInstance)78 OMRCListenerMultiplexerHelper::OMRCListenerMultiplexerHelper( const OMRCListenerMultiplexerHelper& aCopyInstance )
79 : XFocusListener()
80 , XWindowListener()
81 , XKeyListener()
82 , XMouseListener()
83 , XMouseMotionListener()
84 , XPaintListener()
85 , XTopWindowListener()
86 , OWeakObject(aCopyInstance)
87 , m_aListenerHolder ( m_aMutex )
88 {
89 }
90
~OMRCListenerMultiplexerHelper()91 OMRCListenerMultiplexerHelper::~OMRCListenerMultiplexerHelper()
92 {
93 }
94
95 // XInterface
96
queryInterface(const Type & rType)97 Any SAL_CALL OMRCListenerMultiplexerHelper::queryInterface( const Type& rType )
98 {
99 // Attention:
100 // Don't use mutex or guard in this method!!! Is a method of XInterface.
101
102 // Ask for my own supported interfaces ...
103 // Attention: XTypeProvider and XInterface are supported by OComponentHelper!
104 Any aReturn ( ::cppu::queryInterface( rType ,
105 static_cast< XWindowListener* > ( this ) ,
106 static_cast< XKeyListener* > ( this ) ,
107 static_cast< XFocusListener* > ( this ) ,
108 static_cast< XMouseListener* > ( this ) ,
109 static_cast< XMouseMotionListener* > ( this ) ,
110 static_cast< XPaintListener* > ( this ) ,
111 static_cast< XTopWindowListener* > ( this ) ,
112 static_cast< XTopWindowListener* > ( this )
113 )
114 );
115
116 // If searched interface supported by this class ...
117 if ( aReturn.hasValue() )
118 {
119 // ... return this information.
120 return aReturn;
121 }
122 else
123 {
124 // Else; ... ask baseclass for interfaces!
125 return OWeakObject::queryInterface( rType );
126 }
127 }
128
129 // XInterface
130
acquire()131 void SAL_CALL OMRCListenerMultiplexerHelper::acquire() throw()
132 {
133 // Attention:
134 // Don't use mutex or guard in this method!!! Is a method of XInterface.
135
136 // Forward to baseclass
137 OWeakObject::acquire();
138 }
139
140 // XInterface
141
release()142 void SAL_CALL OMRCListenerMultiplexerHelper::release() throw()
143 {
144 // Attention:
145 // Don't use mutex or guard in this method!!! Is a method of XInterface.
146
147 // Forward to baseclass
148 OWeakObject::release();
149 }
150
151 // container method
152
setPeer(const Reference<XWindow> & xPeer)153 void OMRCListenerMultiplexerHelper::setPeer( const Reference< XWindow >& xPeer )
154 {
155 MutexGuard aGuard( m_aMutex );
156 if( m_xPeer != xPeer )
157 {
158 if( m_xPeer.is() )
159 {
160 // get all types from the listener added to the peer
161 const Sequence< Type > aContainedTypes = m_aListenerHolder.getContainedTypes();
162 // loop over all listener types and remove the listeners from the peer
163 for( const auto& rContainedType : aContainedTypes )
164 impl_unadviseFromPeer( m_xPeer, rContainedType );
165 }
166 m_xPeer = xPeer;
167 if( m_xPeer.is() )
168 {
169 // get all types from the listener added to the peer
170 const Sequence< Type > aContainedTypes = m_aListenerHolder.getContainedTypes();
171 // loop over all listener types and add the listeners to the peer
172 for( const auto& rContainedType : aContainedTypes )
173 impl_adviseToPeer( m_xPeer, rContainedType );
174 }
175 }
176 }
177
178 // container method
179
disposeAndClear()180 void OMRCListenerMultiplexerHelper::disposeAndClear()
181 {
182 EventObject aEvent;
183 aEvent.Source = m_xControl;
184 m_aListenerHolder.disposeAndClear( aEvent );
185 }
186
187 // container method
188
advise(const Type & aType,const Reference<XInterface> & xListener)189 void OMRCListenerMultiplexerHelper::advise( const Type& aType ,
190 const Reference< XInterface >& xListener )
191 {
192 MutexGuard aGuard( m_aMutex );
193 if( m_aListenerHolder.addInterface( aType, xListener ) == 1 )
194 {
195 // the first listener is added
196 if( m_xPeer.is() )
197 {
198 impl_adviseToPeer( m_xPeer, aType );
199 }
200 }
201 }
202
203 // container method
204
unadvise(const Type & aType,const Reference<XInterface> & xListener)205 void OMRCListenerMultiplexerHelper::unadvise( const Type& aType ,
206 const Reference< XInterface >& xListener )
207 {
208 MutexGuard aGuard( m_aMutex );
209 if( m_aListenerHolder.removeInterface( aType, xListener ) == 0 )
210 {
211 // the last listener is removed
212 if ( m_xPeer.is() )
213 {
214 impl_unadviseFromPeer( m_xPeer, aType );
215 }
216 }
217 }
218
219 // XEventListener
220
disposing(const EventObject &)221 void SAL_CALL OMRCListenerMultiplexerHelper::disposing( const EventObject& /*aSource*/ )
222 {
223 MutexGuard aGuard( m_aMutex );
224 // peer is disposed, clear the reference
225 m_xPeer.clear();
226 }
227
228 // XFcousListener
229
focusGained(const FocusEvent & aEvent)230 void OMRCListenerMultiplexerHelper::focusGained(const FocusEvent& aEvent )
231 {
232 MULTIPLEX( XFocusListener, focusGained, FocusEvent, aEvent )
233 }
234
235 // XFcousListener
236
focusLost(const FocusEvent & aEvent)237 void OMRCListenerMultiplexerHelper::focusLost(const FocusEvent& aEvent )
238 {
239 MULTIPLEX( XFocusListener, focusLost, FocusEvent, aEvent )
240 }
241
242 // XWindowListener
243
windowResized(const WindowEvent & aEvent)244 void OMRCListenerMultiplexerHelper::windowResized(const WindowEvent& aEvent )
245 {
246 MULTIPLEX( XWindowListener, windowResized, WindowEvent, aEvent )
247 }
248
249 // XWindowListener
250
windowMoved(const WindowEvent & aEvent)251 void OMRCListenerMultiplexerHelper::windowMoved(const WindowEvent& aEvent )
252 {
253 MULTIPLEX( XWindowListener, windowMoved, WindowEvent, aEvent )
254 }
255
256 // XWindowListener
257
windowShown(const EventObject & aEvent)258 void OMRCListenerMultiplexerHelper::windowShown(const EventObject& aEvent )
259 {
260 MULTIPLEX( XWindowListener, windowShown, EventObject, aEvent )
261 }
262
263 // XWindowListener
264
windowHidden(const EventObject & aEvent)265 void OMRCListenerMultiplexerHelper::windowHidden(const EventObject& aEvent )
266 {
267 MULTIPLEX( XWindowListener, windowHidden, EventObject, aEvent )
268 }
269
270 // XKeyListener
271
keyPressed(const KeyEvent & aEvent)272 void OMRCListenerMultiplexerHelper::keyPressed(const KeyEvent& aEvent)
273 {
274 MULTIPLEX( XKeyListener, keyPressed, KeyEvent, aEvent )
275 }
276
277 // XKeyListener
278
keyReleased(const KeyEvent & aEvent)279 void OMRCListenerMultiplexerHelper::keyReleased(const KeyEvent& aEvent)
280 {
281 MULTIPLEX( XKeyListener, keyReleased, KeyEvent, aEvent )
282 }
283
284 // XMouseListener
285
mousePressed(const MouseEvent & aEvent)286 void OMRCListenerMultiplexerHelper::mousePressed(const MouseEvent& aEvent)
287 {
288 MULTIPLEX( XMouseListener, mousePressed, MouseEvent, aEvent )
289 }
290
291 // XMouseListener
292
mouseReleased(const MouseEvent & aEvent)293 void OMRCListenerMultiplexerHelper::mouseReleased(const MouseEvent& aEvent)
294 {
295 MULTIPLEX( XMouseListener, mouseReleased, MouseEvent, aEvent )
296 }
297
298 // XMouseListener
299
mouseEntered(const MouseEvent & aEvent)300 void OMRCListenerMultiplexerHelper::mouseEntered(const MouseEvent& aEvent)
301 {
302 MULTIPLEX( XMouseListener, mouseEntered, MouseEvent, aEvent )
303 }
304
305 // XMouseListener
306
mouseExited(const MouseEvent & aEvent)307 void OMRCListenerMultiplexerHelper::mouseExited(const MouseEvent& aEvent)
308 {
309 MULTIPLEX( XMouseListener, mouseExited, MouseEvent, aEvent )
310 }
311
312 // XMouseMotionListener
313
mouseDragged(const MouseEvent & aEvent)314 void OMRCListenerMultiplexerHelper::mouseDragged(const MouseEvent& aEvent)
315 {
316 MULTIPLEX( XMouseMotionListener, mouseDragged, MouseEvent, aEvent )
317 }
318
319 // XMouseMotionListener
320
mouseMoved(const MouseEvent & aEvent)321 void OMRCListenerMultiplexerHelper::mouseMoved(const MouseEvent& aEvent)
322 {
323 MULTIPLEX( XMouseMotionListener, mouseMoved, MouseEvent, aEvent )
324 }
325
326 // XPaintListener
327
windowPaint(const PaintEvent & aEvent)328 void OMRCListenerMultiplexerHelper::windowPaint(const PaintEvent& aEvent)
329 {
330 MULTIPLEX( XPaintListener, windowPaint, PaintEvent, aEvent )
331 }
332
333 // XTopWindowListener
334
windowOpened(const EventObject & aEvent)335 void OMRCListenerMultiplexerHelper::windowOpened(const EventObject& aEvent)
336 {
337 MULTIPLEX( XTopWindowListener, windowOpened, EventObject, aEvent )
338 }
339
340 // XTopWindowListener
341
windowClosing(const EventObject & aEvent)342 void OMRCListenerMultiplexerHelper::windowClosing( const EventObject& aEvent )
343 {
344 MULTIPLEX( XTopWindowListener, windowClosing, EventObject, aEvent )
345 }
346
347 // XTopWindowListener
348
windowClosed(const EventObject & aEvent)349 void OMRCListenerMultiplexerHelper::windowClosed( const EventObject& aEvent )
350 {
351 MULTIPLEX( XTopWindowListener, windowClosed, EventObject, aEvent )
352 }
353
354 // XTopWindowListener
355
windowMinimized(const EventObject & aEvent)356 void OMRCListenerMultiplexerHelper::windowMinimized( const EventObject& aEvent )
357 {
358 MULTIPLEX( XTopWindowListener, windowMinimized, EventObject, aEvent )
359 }
360
361 // XTopWindowListener
362
windowNormalized(const EventObject & aEvent)363 void OMRCListenerMultiplexerHelper::windowNormalized( const EventObject& aEvent )
364 {
365 MULTIPLEX( XTopWindowListener, windowNormalized, EventObject, aEvent )
366 }
367
368 // XTopWindowListener
369
windowActivated(const EventObject & aEvent)370 void OMRCListenerMultiplexerHelper::windowActivated( const EventObject& aEvent )
371 {
372 MULTIPLEX( XTopWindowListener, windowActivated, EventObject, aEvent )
373 }
374
375 // XTopWindowListener
376
windowDeactivated(const EventObject & aEvent)377 void OMRCListenerMultiplexerHelper::windowDeactivated( const EventObject& aEvent )
378 {
379 MULTIPLEX( XTopWindowListener, windowDeactivated, EventObject, aEvent )
380 }
381
382 // protected method
383
impl_adviseToPeer(const Reference<XWindow> & xPeer,const Type & aType)384 void OMRCListenerMultiplexerHelper::impl_adviseToPeer( const Reference< XWindow >& xPeer ,
385 const Type& aType )
386 {
387 // add a listener to the source (peer)
388 if( aType == cppu::UnoType<XWindowListener>::get())
389 xPeer->addWindowListener( this );
390 else if( aType == cppu::UnoType<XKeyListener>::get())
391 xPeer->addKeyListener( this );
392 else if( aType == cppu::UnoType<XFocusListener>::get())
393 xPeer->addFocusListener( this );
394 else if( aType == cppu::UnoType<XMouseListener>::get())
395 xPeer->addMouseListener( this );
396 else if( aType == cppu::UnoType<XMouseMotionListener>::get())
397 xPeer->addMouseMotionListener( this );
398 else if( aType == cppu::UnoType<XPaintListener>::get())
399 xPeer->addPaintListener( this );
400 else if( aType == cppu::UnoType<XTopWindowListener>::get())
401 {
402 Reference< XTopWindow > xTop( xPeer, UNO_QUERY );
403 if( xTop.is() )
404 xTop->addTopWindowListener( this );
405 }
406 else
407 {
408 OSL_FAIL( "unknown listener" );
409 }
410 }
411
412 // protected method
413
impl_unadviseFromPeer(const Reference<XWindow> & xPeer,const Type & aType)414 void OMRCListenerMultiplexerHelper::impl_unadviseFromPeer( const Reference< XWindow >& xPeer ,
415 const Type& aType )
416 {
417 // the last listener is removed, remove the listener from the source (peer)
418 if( aType == cppu::UnoType<XWindowListener>::get())
419 xPeer->removeWindowListener( this );
420 else if( aType == cppu::UnoType<XKeyListener>::get())
421 xPeer->removeKeyListener( this );
422 else if( aType == cppu::UnoType<XFocusListener>::get())
423 xPeer->removeFocusListener( this );
424 else if( aType == cppu::UnoType<XMouseListener>::get())
425 xPeer->removeMouseListener( this );
426 else if( aType == cppu::UnoType<XMouseMotionListener>::get())
427 xPeer->removeMouseMotionListener( this );
428 else if( aType == cppu::UnoType<XPaintListener>::get())
429 xPeer->removePaintListener( this );
430 else if( aType == cppu::UnoType<XTopWindowListener>::get())
431 {
432 Reference< XTopWindow > xTop( xPeer, UNO_QUERY );
433 if( xTop.is() )
434 xTop->removeTopWindowListener( this );
435 }
436 else
437 {
438 OSL_FAIL( "unknown listener" );
439 }
440 }
441
442 } // namespace unocontrols
443
444 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
445