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