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