1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_slideshow.hxx"
30 
31 // must be first
32 #include <canvas/debug.hxx>
33 #include <tools/diagnose_ex.h>
34 
35 #include <rtl/ref.hxx>
36 #include <cppuhelper/compbase2.hxx>
37 #include <cppuhelper/basemutex.hxx>
38 
39 #include <com/sun/star/awt/XMouseListener.hpp>
40 #include <com/sun/star/awt/XMouseMotionListener.hpp>
41 #include <com/sun/star/awt/SystemPointer.hpp>
42 #include <com/sun/star/awt/XWindow.hpp>
43 #include <com/sun/star/awt/MouseButton.hpp>
44 #include <com/sun/star/presentation/XSlideShowView.hpp>
45 
46 #include <basegfx/matrix/b2dhommatrix.hxx>
47 #include <basegfx/numeric/ftools.hxx>
48 
49 #include "tools.hxx"
50 #include "eventqueue.hxx"
51 #include "eventmultiplexer.hxx"
52 #include "listenercontainer.hxx"
53 #include "delayevent.hxx"
54 #include "unoview.hxx"
55 #include "unoviewcontainer.hxx"
56 
57 #include <boost/shared_ptr.hpp>
58 #include <boost/weak_ptr.hpp>
59 #include <boost/function.hpp>
60 #include <boost/noncopyable.hpp>
61 #include <boost/bind.hpp>
62 
63 #include <vector>
64 #include <hash_map>
65 #include <algorithm>
66 
67 using namespace ::com::sun::star;
68 
69 namespace boost
70 {
71     // add operator== for weak_ptr
72     template<typename T> bool operator==( weak_ptr<T> const& rLHS,
73                                           weak_ptr<T> const& rRHS )
74     {
75         return !(rLHS<rRHS) && !(rRHS<rLHS);
76     }
77 }
78 
79 namespace slideshow {
80 namespace internal {
81 
82 template <typename HandlerT>
83 class PrioritizedHandlerEntry
84 {
85     typedef boost::shared_ptr<HandlerT> HandlerSharedPtrT;
86     HandlerSharedPtrT mpHandler;
87     double            mnPrio;
88 
89 public:
90     PrioritizedHandlerEntry( HandlerSharedPtrT const& pHandler,
91                              double                   nPrio ) :
92         mpHandler(pHandler),
93         mnPrio(nPrio)
94     {}
95 
96     HandlerSharedPtrT const& getHandler() const { return mpHandler; }
97 
98     /// To sort according to priority
99     bool operator<( PrioritizedHandlerEntry const& rRHS ) const
100     {
101         // reversed order - high prioritized entries
102         // should be at the beginning of the queue
103         return mnPrio > rRHS.mnPrio;
104     }
105 
106     /// To permit std::remove in removeHandler template
107     bool operator==( PrioritizedHandlerEntry const& rRHS ) const
108     {
109         // ignore prio, for removal, only the handler ptr matters
110         return mpHandler == rRHS.mpHandler;
111     }
112 };
113 
114 template<typename T> inline T* get_pointer(PrioritizedHandlerEntry<T> const& handler)
115 {
116     return handler.getHandler().get();
117 }
118 
119 
120 
121 ////////////////////////////////////////////////////////////////////////////
122 
123 
124 typedef cppu::WeakComponentImplHelper2<
125     awt::XMouseListener,
126     awt::XMouseMotionListener > Listener_UnoBase;
127 
128 /** Listener class, to decouple UNO lifetime from EventMultiplexer
129 
130     This class gets registered as the XMouse(Motion)Listener on the
131     XSlideViews, and passes on the events to the EventMultiplexer (via
132     EventQueue indirection, to force the events into the main thread)
133  */
134 class EventMultiplexerListener : private cppu::BaseMutex,
135                                  public Listener_UnoBase,
136                                  private ::boost::noncopyable
137 {
138 public:
139     EventMultiplexerListener( EventQueue&           rEventQueue,
140                               EventMultiplexerImpl& rEventMultiplexer ) :
141         Listener_UnoBase( m_aMutex ),
142         mpEventQueue( &rEventQueue ),
143         mpEventMultiplexer( &rEventMultiplexer )
144     {
145     }
146 
147     // WeakComponentImplHelperBase::disposing
148     virtual void SAL_CALL disposing();
149 
150 private:
151     virtual void SAL_CALL disposing( const lang::EventObject& Source )
152         throw (uno::RuntimeException);
153 
154     // XMouseListener implementation
155     virtual void SAL_CALL mousePressed( const awt::MouseEvent& e )
156         throw (uno::RuntimeException);
157     virtual void SAL_CALL mouseReleased( const awt::MouseEvent& e )
158         throw (uno::RuntimeException);
159     virtual void SAL_CALL mouseEntered( const awt::MouseEvent& e )
160         throw (uno::RuntimeException);
161     virtual void SAL_CALL mouseExited( const awt::MouseEvent& e )
162         throw (uno::RuntimeException);
163 
164     // XMouseMotionListener implementation
165     virtual void SAL_CALL mouseDragged( const awt::MouseEvent& e )
166         throw (uno::RuntimeException);
167     virtual void SAL_CALL mouseMoved( const awt::MouseEvent& e )
168         throw (uno::RuntimeException);
169 
170 
171     EventQueue*           mpEventQueue;
172     EventMultiplexerImpl* mpEventMultiplexer;
173 };
174 
175 
176 ////////////////////////////////////////////////////////////////////////////
177 
178 
179 struct EventMultiplexerImpl
180 {
181     EventMultiplexerImpl( EventQueue&             rEventQueue,
182                           UnoViewContainer const& rViewContainer ) :
183         mrEventQueue(rEventQueue),
184         mrViewContainer(rViewContainer),
185         mxListener( new EventMultiplexerListener(rEventQueue,
186                                                  *this) ),
187         maNextEffectHandlers(),
188         maSlideStartHandlers(),
189         maSlideEndHandlers(),
190         maAnimationStartHandlers(),
191         maAnimationEndHandlers(),
192         maSlideAnimationsEndHandlers(),
193         maAudioStoppedHandlers(),
194         maCommandStopAudioHandlers(),
195         maPauseHandlers(),
196         maViewHandlers(),
197         maViewRepaintHandlers(),
198         maShapeListenerHandlers(),
199         maUserPaintEventHandlers(),
200         maShapeCursorHandlers(),
201         maMouseClickHandlers(),
202         maMouseDoubleClickHandlers(),
203         maMouseMoveHandlers(),
204         maHyperlinkHandlers(),
205         mnTimeout(0.0),
206         mpTickEvent(),
207         mbIsAutoMode(false)
208     {}
209 
210     ~EventMultiplexerImpl()
211     {
212         if( mxListener.is() )
213             mxListener->dispose();
214     }
215 
216     /// Remove all handlers
217     void clear();
218 
219     // actual handler callbacks (get called from the UNO interface
220     // listeners via event queue)
221     void mousePressed( const awt::MouseEvent& e );
222     void mouseReleased( const awt::MouseEvent& e );
223     void mouseDragged( const awt::MouseEvent& e );
224     void mouseMoved( const awt::MouseEvent& e );
225 
226     bool isMouseListenerRegistered() const;
227 
228     typedef ThreadUnsafeListenerContainer<
229         PrioritizedHandlerEntry<EventHandler>,
230         std::vector<
231             PrioritizedHandlerEntry<EventHandler> > >     ImplNextEffectHandlers;
232     typedef PrioritizedHandlerEntry<MouseEventHandler>    ImplMouseHandlerEntry;
233     typedef ThreadUnsafeListenerContainer<
234         ImplMouseHandlerEntry,
235         std::vector<ImplMouseHandlerEntry> >              ImplMouseHandlers;
236     typedef ThreadUnsafeListenerContainer<
237         EventHandlerSharedPtr,
238         std::vector<EventHandlerSharedPtr> >              ImplEventHandlers;
239     typedef ThreadUnsafeListenerContainer<
240         AnimationEventHandlerSharedPtr,
241         std::vector<AnimationEventHandlerSharedPtr> >     ImplAnimationHandlers;
242     typedef ThreadUnsafeListenerContainer<
243         PauseEventHandlerSharedPtr,
244         std::vector<PauseEventHandlerSharedPtr> >         ImplPauseHandlers;
245     typedef ThreadUnsafeListenerContainer<
246         ViewEventHandlerWeakPtr,
247         std::vector<ViewEventHandlerWeakPtr> >            ImplViewHandlers;
248     typedef ThreadUnsafeListenerContainer<
249         ViewRepaintHandlerSharedPtr,
250         std::vector<ViewRepaintHandlerSharedPtr> >        ImplRepaintHandlers;
251     typedef ThreadUnsafeListenerContainer<
252         ShapeListenerEventHandlerSharedPtr,
253         std::vector<ShapeListenerEventHandlerSharedPtr> > ImplShapeListenerHandlers;
254     typedef ThreadUnsafeListenerContainer<
255         UserPaintEventHandlerSharedPtr,
256         std::vector<UserPaintEventHandlerSharedPtr> >     ImplUserPaintEventHandlers;
257     typedef ThreadUnsafeListenerContainer<
258         ShapeCursorEventHandlerSharedPtr,
259         std::vector<ShapeCursorEventHandlerSharedPtr> >   ImplShapeCursorHandlers;
260     typedef ThreadUnsafeListenerContainer<
261         PrioritizedHandlerEntry<HyperlinkHandler>,
262         std::vector<PrioritizedHandlerEntry<HyperlinkHandler> > > ImplHyperLinkHandlers;
263 
264     template <typename XSlideShowViewFunc>
265     void forEachView( XSlideShowViewFunc pViewMethod );
266 
267     UnoViewSharedPtr findUnoView(const uno::Reference<
268                                    presentation::XSlideShowView>& xView) const;
269 
270     template< typename RegisterFunction >
271     void addMouseHandler( ImplMouseHandlers&                rHandlerContainer,
272                           const MouseEventHandlerSharedPtr& rHandler,
273                           double                            nPriority,
274                           RegisterFunction                  pRegisterListener );
275 
276     bool notifyAllAnimationHandlers( ImplAnimationHandlers const& rContainer,
277                                      AnimationNodeSharedPtr const& rNode );
278 
279     bool notifyMouseHandlers(
280         const ImplMouseHandlers& rQueue,
281         bool (MouseEventHandler::*pHandlerMethod)(
282             const awt::MouseEvent& ),
283         const awt::MouseEvent& e );
284 
285     bool notifyNextEffect();
286 
287     /// Called for automatic nextEffect
288     void tick();
289 
290     /// Schedules a tick event
291     void scheduleTick();
292 
293     /// Schedules tick events, if mbIsAutoMode is true
294     void handleTicks();
295 
296 
297     EventQueue&                         mrEventQueue;
298     UnoViewContainer const&             mrViewContainer;
299     ::rtl::Reference<
300         EventMultiplexerListener>       mxListener;
301 
302     ImplNextEffectHandlers              maNextEffectHandlers;
303     ImplEventHandlers                   maSlideStartHandlers;
304     ImplEventHandlers                   maSlideEndHandlers;
305     ImplAnimationHandlers               maAnimationStartHandlers;
306     ImplAnimationHandlers               maAnimationEndHandlers;
307     ImplEventHandlers                   maSlideAnimationsEndHandlers;
308     ImplAnimationHandlers               maAudioStoppedHandlers;
309     ImplAnimationHandlers               maCommandStopAudioHandlers;
310     ImplPauseHandlers                   maPauseHandlers;
311     ImplViewHandlers                    maViewHandlers;
312     ImplRepaintHandlers                 maViewRepaintHandlers;
313     ImplShapeListenerHandlers           maShapeListenerHandlers;
314     ImplUserPaintEventHandlers          maUserPaintEventHandlers;
315     ImplShapeCursorHandlers             maShapeCursorHandlers;
316     ImplMouseHandlers                   maMouseClickHandlers;
317     ImplMouseHandlers                   maMouseDoubleClickHandlers;
318     ImplMouseHandlers                   maMouseMoveHandlers;
319     ImplHyperLinkHandlers               maHyperlinkHandlers;
320 
321     /// automatic next effect mode timeout
322     double                        mnTimeout;
323 
324     /** Holds ptr to optional tick event weakly
325 
326         When event queue is cleansed, the next
327         setAutomaticMode(true) call is then able to
328         regenerate the event.
329     */
330     ::boost::weak_ptr< Event >    mpTickEvent;
331     bool                          mbIsAutoMode;
332 };
333 
334 
335 ///////////////////////////////////////////////////////////////////////////
336 
337 
338 void SAL_CALL EventMultiplexerListener::disposing()
339 {
340     osl::MutexGuard const guard( m_aMutex );
341     mpEventQueue = NULL;
342     mpEventMultiplexer = NULL;
343 }
344 
345 void SAL_CALL EventMultiplexerListener::disposing(
346     const lang::EventObject& /*rSource*/ ) throw (uno::RuntimeException)
347 {
348     // there's no real point in acting on this message - after all,
349     // the event sources are the XSlideShowViews, which must be
350     // explicitely removed from the slideshow via
351     // XSlideShow::removeView(). thus, if a XSlideShowView has
352     // properly removed itself from the slideshow, it will not be
353     // found here. and if it hasn't, there'll be other references at
354     // other places within the slideshow, anyway...
355 }
356 
357 void SAL_CALL EventMultiplexerListener::mousePressed(
358     const awt::MouseEvent& e ) throw (uno::RuntimeException)
359 {
360     osl::MutexGuard const guard( m_aMutex );
361 
362     // notify mouse press. Don't call handlers directly, this
363     // might not be the main thread!
364     if( mpEventQueue )
365         mpEventQueue->addEvent(
366             makeEvent( boost::bind( &EventMultiplexerImpl::mousePressed,
367                                     mpEventMultiplexer,
368                                     e ),
369                        "EventMultiplexerImpl::mousePressed") );
370 }
371 
372 void SAL_CALL EventMultiplexerListener::mouseReleased(
373     const awt::MouseEvent& e ) throw (uno::RuntimeException)
374 {
375     osl::MutexGuard const guard( m_aMutex );
376 
377     // notify mouse release. Don't call handlers directly,
378     // this might not be the main thread!
379     if( mpEventQueue )
380         mpEventQueue->addEvent(
381             makeEvent( boost::bind( &EventMultiplexerImpl::mouseReleased,
382                                     mpEventMultiplexer,
383                                     e ),
384                        "EventMultiplexerImpl::mouseReleased") );
385 }
386 
387 void SAL_CALL EventMultiplexerListener::mouseEntered(
388     const awt::MouseEvent& /*e*/ ) throw (uno::RuntimeException)
389 {
390     // not used here
391 }
392 
393 void SAL_CALL EventMultiplexerListener::mouseExited(
394     const awt::MouseEvent& /*e*/ ) throw (uno::RuntimeException)
395 {
396     // not used here
397 }
398 
399 // XMouseMotionListener implementation
400 void SAL_CALL EventMultiplexerListener::mouseDragged(
401     const awt::MouseEvent& e ) throw (uno::RuntimeException)
402 {
403     osl::MutexGuard const guard( m_aMutex );
404 
405     // notify mouse drag. Don't call handlers directly, this
406     // might not be the main thread!
407     if( mpEventQueue )
408         mpEventQueue->addEvent(
409             makeEvent( boost::bind( &EventMultiplexerImpl::mouseDragged,
410                                     mpEventMultiplexer,
411                                     e ),
412                        "EventMultiplexerImpl::mouseDragged") );
413 }
414 
415 void SAL_CALL EventMultiplexerListener::mouseMoved(
416     const awt::MouseEvent& e ) throw (uno::RuntimeException)
417 {
418     osl::MutexGuard const guard( m_aMutex );
419 
420     // notify mouse move. Don't call handlers directly, this
421     // might not be the main thread!
422     if( mpEventQueue )
423         mpEventQueue->addEvent(
424             makeEvent( boost::bind( &EventMultiplexerImpl::mouseMoved,
425                                     mpEventMultiplexer,
426                                     e ),
427                        "EventMultiplexerImpl::mouseMoved") );
428 }
429 
430 
431 ///////////////////////////////////////////////////////////////////////////
432 
433 
434 bool EventMultiplexerImpl::notifyAllAnimationHandlers( ImplAnimationHandlers const& rContainer,
435                                                        AnimationNodeSharedPtr const& rNode )
436 {
437     return rContainer.applyAll(
438         boost::bind( &AnimationEventHandler::handleAnimationEvent,
439                      _1, boost::cref(rNode) ) );
440 }
441 
442 template <typename XSlideShowViewFunc>
443 void EventMultiplexerImpl::forEachView( XSlideShowViewFunc pViewMethod )
444 {
445     if( pViewMethod )
446     {
447         // (un)register mouse listener on all views
448         for( UnoViewVector::const_iterator aIter( mrViewContainer.begin() ),
449                  aEnd( mrViewContainer.end() ); aIter != aEnd; ++aIter )
450         {
451             uno::Reference<presentation::XSlideShowView> xView ((*aIter)->getUnoView());
452             if (xView.is())
453             {
454                 (xView.get()->*pViewMethod)( mxListener.get() );
455             }
456             else
457             {
458                 OSL_ASSERT(xView.is());
459             }
460         }
461     }
462 }
463 
464 UnoViewSharedPtr EventMultiplexerImpl::findUnoView(
465     const uno::Reference<presentation::XSlideShowView>& xView) const
466 {
467     // find view from which the change originated
468     UnoViewVector::const_iterator       aIter;
469     const UnoViewVector::const_iterator aEnd ( mrViewContainer.end() );
470     if( (aIter=std::find_if( mrViewContainer.begin(),
471                              aEnd,
472                              boost::bind(
473                                  std::equal_to<uno::Reference<presentation::XSlideShowView> >(),
474                                  boost::cref( xView ),
475                                  boost::bind( &UnoView::getUnoView, _1 )))) == aEnd )
476     {
477         OSL_ENSURE(false, "EventMultiplexer::findUnoView(): unexpected message source" );
478         return UnoViewSharedPtr();
479     }
480 
481     return *aIter;
482 }
483 
484 template< typename RegisterFunction >
485 void EventMultiplexerImpl::addMouseHandler(
486     ImplMouseHandlers&                rHandlerContainer,
487     const MouseEventHandlerSharedPtr& rHandler,
488     double                            nPriority,
489     RegisterFunction                  pRegisterListener )
490 {
491     ENSURE_OR_THROW(
492         rHandler,
493         "EventMultiplexer::addMouseHandler(): Invalid handler" );
494 
495     // register mouse listener on all views
496     forEachView( pRegisterListener );
497 
498     // add into sorted container:
499     rHandlerContainer.addSorted(
500         typename ImplMouseHandlers::container_type::value_type(
501             rHandler,
502             nPriority ));
503 }
504 
505 bool EventMultiplexerImpl::isMouseListenerRegistered() const
506 {
507     return !(maMouseClickHandlers.isEmpty() &&
508              maMouseDoubleClickHandlers.isEmpty());
509 }
510 
511 void EventMultiplexerImpl::tick()
512 {
513     if( !mbIsAutoMode )
514         return; // this event is just a left-over, ignore
515 
516     notifyNextEffect();
517 
518     if( !maNextEffectHandlers.isEmpty() )
519     {
520         // still handlers left, schedule next timeout
521         // event. Will also set mbIsTickEventOn back to true
522         scheduleTick();
523     }
524 }
525 
526 void EventMultiplexerImpl::scheduleTick()
527 {
528     EventSharedPtr pEvent(
529         makeDelay( boost::bind( &EventMultiplexerImpl::tick,
530                                 this ),
531                    mnTimeout,
532                    "EventMultiplexerImpl::tick with delay"));
533 
534     // store weak reference to generated event, to notice when
535     // the event queue gets cleansed (we then have to
536     // regenerate the tick event!)
537     mpTickEvent = pEvent;
538 
539     // enabled auto mode: simply schedule a timeout event,
540     // which will eventually call our tick() method
541     mrEventQueue.addEventForNextRound( pEvent );
542 }
543 
544 void EventMultiplexerImpl::handleTicks()
545 {
546     if( !mbIsAutoMode )
547         return; // nothing to do, don't need no ticks
548 
549     EventSharedPtr pTickEvent( mpTickEvent.lock() );
550     if( pTickEvent )
551         return; // nothing to do, there's already a tick
552                 // pending
553 
554     // schedule initial tick (which reschedules itself
555     // after that, all by itself)
556     scheduleTick();
557 }
558 
559 
560 void EventMultiplexerImpl::clear()
561 {
562     // deregister from all views.
563     if( isMouseListenerRegistered() )
564     {
565         for( UnoViewVector::const_iterator aIter=mrViewContainer.begin(),
566                  aEnd=mrViewContainer.end();
567              aIter!=aEnd;
568              ++aIter )
569         {
570 			if( (*aIter)->getUnoView().is() )
571 				(*aIter)->getUnoView()->removeMouseListener( mxListener.get() );
572         }
573     }
574 
575     if( !maMouseMoveHandlers.isEmpty() )
576     {
577         for( UnoViewVector::const_iterator aIter=mrViewContainer.begin(),
578                  aEnd=mrViewContainer.end();
579              aIter!=aEnd;
580              ++aIter )
581         {
582 			if( (*aIter)->getUnoView().is() )
583 	            (*aIter)->getUnoView()->removeMouseMotionListener( mxListener.get() );
584         }
585     }
586 
587     // clear all handlers (releases all references)
588     maNextEffectHandlers.clear();
589     maSlideStartHandlers.clear();
590     maSlideEndHandlers.clear();
591     maAnimationStartHandlers.clear();
592     maAnimationEndHandlers.clear();
593     maSlideAnimationsEndHandlers.clear();
594     maAudioStoppedHandlers.clear();
595     maCommandStopAudioHandlers.clear();
596     maPauseHandlers.clear();
597     maViewHandlers.clear();
598     maViewRepaintHandlers.clear();
599     maMouseClickHandlers.clear();
600     maMouseDoubleClickHandlers.clear();
601     maMouseMoveHandlers.clear();
602     maHyperlinkHandlers.clear();
603     mpTickEvent.reset();
604 }
605 
606 // XMouseListener implementation
607 bool EventMultiplexerImpl::notifyMouseHandlers(
608     const ImplMouseHandlers& rQueue,
609     bool (MouseEventHandler::*pHandlerMethod)( const awt::MouseEvent& ),
610     const awt::MouseEvent& e )
611 {
612     uno::Reference<presentation::XSlideShowView> xView(
613         e.Source, uno::UNO_QUERY );
614 
615     ENSURE_OR_RETURN_FALSE( xView.is(), "EventMultiplexer::notifyHandlers(): "
616                        "event source is not an XSlideShowView" );
617 
618     // find corresponding view (to map mouse position into user
619     // coordinate space)
620     UnoViewVector::const_iterator       aIter;
621     const UnoViewVector::const_iterator aBegin( mrViewContainer.begin() );
622     const UnoViewVector::const_iterator aEnd  ( mrViewContainer.end() );
623     if( (aIter=::std::find_if(
624              aBegin, aEnd,
625              boost::bind( std::equal_to< uno::Reference<
626                           presentation::XSlideShowView > >(),
627                           boost::cref( xView ),
628                           boost::bind( &UnoView::getUnoView, _1 ) ) ) ) == aEnd)
629     {
630         ENSURE_OR_RETURN_FALSE(
631             false, "EventMultiplexer::notifyHandlers(): "
632             "event source not found under registered views" );
633     }
634 
635     // convert mouse position to user coordinate space
636     ::basegfx::B2DPoint     aPosition( e.X, e.Y );
637     ::basegfx::B2DHomMatrix aMatrix( (*aIter)->getTransformation() );
638     if( !aMatrix.invert() )
639         ENSURE_OR_THROW( false, "EventMultiplexer::notifyHandlers():"
640                           " view matrix singular" );
641     aPosition *= aMatrix;
642 
643     awt::MouseEvent aEvent( e );
644     aEvent.X = ::basegfx::fround( aPosition.getX() );
645     aEvent.Y = ::basegfx::fround( aPosition.getY() );
646 
647     // fire event on handlers, try in order of precedence. If
648     // one high-priority handler rejects the event
649     // (i.e. returns false), try next handler.
650     return rQueue.apply(
651         boost::bind(
652             pHandlerMethod,
653             boost::bind(
654                 &ImplMouseHandlers::container_type::value_type::getHandler,
655                 _1 ),
656             aEvent ));
657 }
658 
659 void EventMultiplexerImpl::mousePressed( const awt::MouseEvent& e )
660 {
661     // fire double-click events for every second click
662     sal_Int32 nCurrClickCount = e.ClickCount;
663     while( nCurrClickCount > 1 &&
664            notifyMouseHandlers( maMouseDoubleClickHandlers,
665                                 &MouseEventHandler::handleMousePressed,
666                                 e ))
667     {
668         nCurrClickCount -= 2;
669     }
670 
671     // fire single-click events for all remaining clicks
672     while( nCurrClickCount > 0 &&
673            notifyMouseHandlers( maMouseClickHandlers,
674                                 &MouseEventHandler::handleMousePressed,
675                                 e ))
676     {
677         --nCurrClickCount;
678     }
679 }
680 
681 void EventMultiplexerImpl::mouseReleased( const awt::MouseEvent& e )
682 {
683     // fire double-click events for every second click
684     sal_Int32 nCurrClickCount = e.ClickCount;
685     while( nCurrClickCount > 1 &&
686            notifyMouseHandlers( maMouseDoubleClickHandlers,
687                                 &MouseEventHandler::handleMouseReleased,
688                                 e ))
689     {
690         nCurrClickCount -= 2;
691     }
692 
693     // fire single-click events for all remaining clicks
694     while( nCurrClickCount > 0 &&
695            notifyMouseHandlers( maMouseClickHandlers,
696                                 &MouseEventHandler::handleMouseReleased,
697                                 e ))
698     {
699         --nCurrClickCount;
700     }
701 }
702 
703 void EventMultiplexerImpl::mouseDragged( const awt::MouseEvent& e )
704 {
705     notifyMouseHandlers( maMouseMoveHandlers,
706                          &MouseEventHandler::handleMouseDragged,
707                          e );
708 }
709 
710 void EventMultiplexerImpl::mouseMoved( const awt::MouseEvent& e )
711 {
712     notifyMouseHandlers( maMouseMoveHandlers,
713                          &MouseEventHandler::handleMouseMoved,
714                          e );
715 }
716 
717 bool EventMultiplexerImpl::notifyNextEffect()
718 {
719     // fire event on handlers, try in order of precedence. If one
720     // high-priority handler rejects the event (i.e. returns false),
721     // try next handler.
722     return maNextEffectHandlers.apply(
723         boost::bind(
724             &EventHandler::handleEvent,
725             boost::bind(
726                 &ImplNextEffectHandlers::container_type::value_type::getHandler,
727                 _1 )) );
728 }
729 
730 //////////////////////////////////////////////////////////////////////////
731 
732 
733 EventMultiplexer::EventMultiplexer( EventQueue&             rEventQueue,
734                                     UnoViewContainer const& rViewContainer ) :
735     mpImpl( new EventMultiplexerImpl(rEventQueue, rViewContainer) )
736 {
737 }
738 
739 EventMultiplexer::~EventMultiplexer()
740 {
741     // outline because of EventMultiplexerImpl's incomplete type
742 }
743 
744 void EventMultiplexer::clear()
745 {
746     mpImpl->clear();
747 }
748 
749 void EventMultiplexer::setAutomaticMode( bool bIsAuto )
750 {
751     if( bIsAuto == mpImpl->mbIsAutoMode )
752         return; // no change, nothing to do
753 
754     mpImpl->mbIsAutoMode = bIsAuto;
755 
756     mpImpl->handleTicks();
757 }
758 
759 bool EventMultiplexer::getAutomaticMode() const
760 {
761     return mpImpl->mbIsAutoMode;
762 }
763 
764 void EventMultiplexer::setAutomaticTimeout( double nTimeout )
765 {
766     mpImpl->mnTimeout = nTimeout;
767 }
768 
769 double EventMultiplexer::getAutomaticTimeout() const
770 {
771     return mpImpl->mnTimeout;
772 }
773 
774 void EventMultiplexer::addNextEffectHandler(
775     EventHandlerSharedPtr const& rHandler,
776     double                       nPriority )
777 {
778     mpImpl->maNextEffectHandlers.addSorted(
779         EventMultiplexerImpl::ImplNextEffectHandlers::container_type::value_type(
780             rHandler,
781             nPriority) );
782 
783     // Enable tick events, if not done already
784     mpImpl->handleTicks();
785 }
786 
787 void EventMultiplexer::removeNextEffectHandler(
788     const EventHandlerSharedPtr& rHandler )
789 {
790     mpImpl->maNextEffectHandlers.remove(
791         EventMultiplexerImpl::ImplNextEffectHandlers::container_type::value_type(
792             rHandler,
793             0.0) );
794 }
795 
796 void EventMultiplexer::addSlideStartHandler(
797     const EventHandlerSharedPtr& rHandler )
798 {
799     mpImpl->maSlideStartHandlers.add( rHandler );
800 }
801 
802 void EventMultiplexer::removeSlideStartHandler(
803     const EventHandlerSharedPtr& rHandler )
804 {
805     mpImpl->maSlideStartHandlers.remove( rHandler );
806 }
807 
808 void EventMultiplexer::addSlideEndHandler(
809     const EventHandlerSharedPtr& rHandler )
810 {
811     mpImpl->maSlideEndHandlers.add( rHandler );
812 }
813 
814 void EventMultiplexer::removeSlideEndHandler(
815     const EventHandlerSharedPtr& rHandler )
816 {
817     mpImpl->maSlideEndHandlers.remove( rHandler );
818 }
819 
820 void EventMultiplexer::addAnimationStartHandler(
821     const AnimationEventHandlerSharedPtr& rHandler )
822 {
823     mpImpl->maAnimationStartHandlers.add( rHandler );
824 }
825 
826 void EventMultiplexer::removeAnimationStartHandler(
827     const AnimationEventHandlerSharedPtr& rHandler )
828 {
829     mpImpl->maAnimationStartHandlers.remove( rHandler );
830 }
831 
832 void EventMultiplexer::addAnimationEndHandler(
833     const AnimationEventHandlerSharedPtr& rHandler )
834 {
835     mpImpl->maAnimationEndHandlers.add( rHandler );
836 }
837 
838 void EventMultiplexer::removeAnimationEndHandler(
839     const AnimationEventHandlerSharedPtr& rHandler )
840 {
841     mpImpl->maAnimationEndHandlers.remove( rHandler );
842 }
843 
844 void EventMultiplexer::addSlideAnimationsEndHandler(
845     const EventHandlerSharedPtr& rHandler )
846 {
847     mpImpl->maSlideAnimationsEndHandlers.add( rHandler );
848 }
849 
850 void EventMultiplexer::removeSlideAnimationsEndHandler(
851     const EventHandlerSharedPtr& rHandler )
852 {
853     mpImpl->maSlideAnimationsEndHandlers.remove( rHandler );
854 }
855 
856 void EventMultiplexer::addAudioStoppedHandler(
857     const AnimationEventHandlerSharedPtr& rHandler )
858 {
859     mpImpl->maAudioStoppedHandlers.add( rHandler );
860 }
861 
862 void EventMultiplexer::removeAudioStoppedHandler(
863     const AnimationEventHandlerSharedPtr& rHandler )
864 {
865     mpImpl->maAudioStoppedHandlers.remove( rHandler );
866 }
867 
868 void EventMultiplexer::addCommandStopAudioHandler(
869     const AnimationEventHandlerSharedPtr& rHandler )
870 {
871     mpImpl->maCommandStopAudioHandlers.add( rHandler );
872 }
873 
874 void EventMultiplexer::removeCommandStopAudioHandler(
875     const AnimationEventHandlerSharedPtr& rHandler )
876 {
877     mpImpl->maCommandStopAudioHandlers.remove( rHandler );
878 }
879 
880 void EventMultiplexer::addPauseHandler(
881     const PauseEventHandlerSharedPtr& rHandler )
882 {
883     mpImpl->maPauseHandlers.add( rHandler );
884 }
885 
886 void EventMultiplexer::removePauseHandler(
887     const PauseEventHandlerSharedPtr&  rHandler )
888 {
889     mpImpl->maPauseHandlers.remove( rHandler );
890 }
891 
892 void EventMultiplexer::addViewHandler(
893     const ViewEventHandlerWeakPtr& rHandler )
894 {
895     mpImpl->maViewHandlers.add( rHandler );
896 }
897 
898 void EventMultiplexer::removeViewHandler( const ViewEventHandlerWeakPtr& rHandler )
899 {
900     mpImpl->maViewHandlers.remove( rHandler );
901 }
902 
903 void EventMultiplexer::addViewRepaintHandler( const ViewRepaintHandlerSharedPtr& rHandler )
904 {
905     mpImpl->maViewRepaintHandlers.add( rHandler );
906 }
907 
908 void EventMultiplexer::removeViewRepaintHandler( const ViewRepaintHandlerSharedPtr& rHandler )
909 {
910     mpImpl->maViewRepaintHandlers.remove( rHandler );
911 }
912 
913 void EventMultiplexer::addShapeListenerHandler( const ShapeListenerEventHandlerSharedPtr& rHandler )
914 {
915     mpImpl->maShapeListenerHandlers.add( rHandler );
916 }
917 
918 void EventMultiplexer::removeShapeListenerHandler( const ShapeListenerEventHandlerSharedPtr& rHandler )
919 {
920     mpImpl->maShapeListenerHandlers.remove( rHandler );
921 }
922 
923 void EventMultiplexer::addUserPaintHandler( const UserPaintEventHandlerSharedPtr& rHandler )
924 {
925     mpImpl->maUserPaintEventHandlers.add( rHandler );
926 }
927 
928 void EventMultiplexer::removeUserPaintHandler( const UserPaintEventHandlerSharedPtr& rHandler )
929 {
930     mpImpl->maUserPaintEventHandlers.remove( rHandler );
931 }
932 
933 void EventMultiplexer::addShapeCursorHandler( const ShapeCursorEventHandlerSharedPtr& rHandler )
934 {
935     mpImpl->maShapeCursorHandlers.add( rHandler );
936 }
937 
938 void EventMultiplexer::removeShapeCursorHandler( const ShapeCursorEventHandlerSharedPtr& rHandler )
939 {
940     mpImpl->maShapeCursorHandlers.remove( rHandler );
941 }
942 
943 void EventMultiplexer::addClickHandler(
944     const MouseEventHandlerSharedPtr& rHandler,
945     double                            nPriority )
946 {
947     mpImpl->addMouseHandler(
948         mpImpl->maMouseClickHandlers,
949         rHandler,
950         nPriority,
951         mpImpl->isMouseListenerRegistered()
952         ? NULL
953         : &presentation::XSlideShowView::addMouseListener );
954 }
955 
956 void EventMultiplexer::removeClickHandler(
957     const MouseEventHandlerSharedPtr&  rHandler )
958 {
959     mpImpl->maMouseClickHandlers.remove(
960         EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
961             rHandler,
962             0.0) );
963 
964     if( !mpImpl->isMouseListenerRegistered() )
965         mpImpl->forEachView( &presentation::XSlideShowView::removeMouseListener );
966 }
967 
968 void EventMultiplexer::addDoubleClickHandler(
969     const MouseEventHandlerSharedPtr&   rHandler,
970     double                              nPriority )
971 {
972     mpImpl->addMouseHandler(
973         mpImpl->maMouseDoubleClickHandlers,
974         rHandler,
975         nPriority,
976         mpImpl->isMouseListenerRegistered()
977         ? NULL
978         : &presentation::XSlideShowView::addMouseListener );
979 }
980 
981 void EventMultiplexer::removeDoubleClickHandler(
982     const MouseEventHandlerSharedPtr&    rHandler )
983 {
984     mpImpl->maMouseDoubleClickHandlers.remove(
985         EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
986             rHandler,
987             0.0) );
988 
989     if( !mpImpl->isMouseListenerRegistered() )
990         mpImpl->forEachView( &presentation::XSlideShowView::removeMouseListener );
991 }
992 
993 void EventMultiplexer::addMouseMoveHandler(
994     const MouseEventHandlerSharedPtr& rHandler,
995     double                            nPriority )
996 {
997     mpImpl->addMouseHandler(
998         mpImpl->maMouseMoveHandlers,
999         rHandler,
1000         nPriority,
1001         mpImpl->maMouseMoveHandlers.isEmpty()
1002         ? &presentation::XSlideShowView::addMouseMotionListener
1003         : NULL );
1004 }
1005 
1006 void EventMultiplexer::removeMouseMoveHandler(
1007     const MouseEventHandlerSharedPtr&  rHandler )
1008 {
1009     mpImpl->maMouseMoveHandlers.remove(
1010         EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
1011             rHandler,
1012             0.0) );
1013 
1014     if( mpImpl->maMouseMoveHandlers.isEmpty() )
1015         mpImpl->forEachView(
1016             &presentation::XSlideShowView::removeMouseMotionListener );
1017 }
1018 
1019 void EventMultiplexer::addHyperlinkHandler( const HyperlinkHandlerSharedPtr& rHandler,
1020                                             double                           nPriority )
1021 {
1022     mpImpl->maHyperlinkHandlers.addSorted(
1023         EventMultiplexerImpl::ImplHyperLinkHandlers::container_type::value_type(
1024             rHandler,
1025             nPriority) );
1026 }
1027 
1028 void EventMultiplexer::removeHyperlinkHandler( const HyperlinkHandlerSharedPtr& rHandler )
1029 {
1030     mpImpl->maHyperlinkHandlers.remove(
1031         EventMultiplexerImpl::ImplHyperLinkHandlers::container_type::value_type(
1032             rHandler,
1033             0.0) );
1034 }
1035 
1036 bool EventMultiplexer::notifyShapeListenerAdded(
1037     const uno::Reference<presentation::XShapeEventListener>& xListener,
1038     const uno::Reference<drawing::XShape>&                   xShape )
1039 {
1040     return mpImpl->maShapeListenerHandlers.applyAll(
1041         boost::bind(&ShapeListenerEventHandler::listenerAdded,
1042                     _1,
1043                     boost::cref(xListener),
1044                     boost::cref(xShape)) );
1045 }
1046 
1047 bool EventMultiplexer::notifyShapeListenerRemoved(
1048     const uno::Reference<presentation::XShapeEventListener>& xListener,
1049     const uno::Reference<drawing::XShape>&                   xShape )
1050 {
1051     return mpImpl->maShapeListenerHandlers.applyAll(
1052         boost::bind(&ShapeListenerEventHandler::listenerRemoved,
1053                     _1,
1054                     boost::cref(xListener),
1055                     boost::cref(xShape)) );
1056 }
1057 
1058 bool EventMultiplexer::notifyShapeCursorChange(
1059     const uno::Reference<drawing::XShape>&  xShape,
1060     sal_Int16                               nPointerShape )
1061 {
1062     return mpImpl->maShapeCursorHandlers.applyAll(
1063         boost::bind(&ShapeCursorEventHandler::cursorChanged,
1064                     _1,
1065                     boost::cref(xShape),
1066                     nPointerShape));
1067 }
1068 
1069 bool EventMultiplexer::notifyUserPaintColor( RGBColor const& rUserColor )
1070 {
1071     return mpImpl->maUserPaintEventHandlers.applyAll(
1072         boost::bind(&UserPaintEventHandler::colorChanged,
1073                     _1,
1074                     boost::cref(rUserColor)));
1075 }
1076 
1077 bool EventMultiplexer::notifyUserPaintStrokeWidth( double rUserStrokeWidth )
1078 {
1079     return mpImpl->maUserPaintEventHandlers.applyAll(
1080         boost::bind(&UserPaintEventHandler::widthChanged,
1081 		    _1,
1082                     rUserStrokeWidth));
1083 }
1084 
1085 bool EventMultiplexer::notifyUserPaintDisabled()
1086 {
1087     return mpImpl->maUserPaintEventHandlers.applyAll(
1088         boost::mem_fn(&UserPaintEventHandler::disable));
1089 }
1090 
1091 bool EventMultiplexer::notifySwitchPenMode(){
1092     return mpImpl->maUserPaintEventHandlers.applyAll(
1093 	    boost::mem_fn(&UserPaintEventHandler::switchPenMode));
1094 }
1095 
1096 bool EventMultiplexer::notifySwitchEraserMode(){
1097     return mpImpl->maUserPaintEventHandlers.applyAll(
1098 	    boost::mem_fn(&UserPaintEventHandler::switchEraserMode));
1099 }
1100 
1101 //adding erasing all ink features with UserPaintOverlay
1102 bool EventMultiplexer::notifyEraseAllInk( bool const& rEraseAllInk )
1103 {
1104 	return mpImpl->maUserPaintEventHandlers.applyAll(
1105         boost::bind(&UserPaintEventHandler::eraseAllInkChanged,
1106                     _1,
1107                     boost::cref(rEraseAllInk)));
1108 }
1109 
1110 //adding erasing features with UserPaintOverlay
1111 bool EventMultiplexer::notifyEraseInkWidth( sal_Int32 rEraseInkSize )
1112 {
1113 	return mpImpl->maUserPaintEventHandlers.applyAll(
1114         boost::bind(&UserPaintEventHandler::eraseInkWidthChanged,
1115                     _1,
1116                     boost::cref(rEraseInkSize)));
1117 }
1118 
1119 bool EventMultiplexer::notifyNextEffect()
1120 {
1121     return mpImpl->notifyNextEffect();
1122 }
1123 
1124 bool EventMultiplexer::notifySlideStartEvent()
1125 {
1126     return mpImpl->maSlideStartHandlers.applyAll(
1127         boost::mem_fn(&EventHandler::handleEvent) );
1128 }
1129 
1130 bool EventMultiplexer::notifySlideEndEvent()
1131 {
1132     return mpImpl->maSlideEndHandlers.applyAll(
1133         boost::mem_fn(&EventHandler::handleEvent) );
1134 }
1135 
1136 bool EventMultiplexer::notifyAnimationStart(
1137     const AnimationNodeSharedPtr& rNode )
1138 {
1139     return mpImpl->notifyAllAnimationHandlers( mpImpl->maAnimationStartHandlers,
1140                                                rNode );
1141 }
1142 
1143 bool EventMultiplexer::notifyAnimationEnd(
1144     const AnimationNodeSharedPtr& rNode )
1145 {
1146     return mpImpl->notifyAllAnimationHandlers( mpImpl->maAnimationEndHandlers,
1147                                                rNode );
1148 }
1149 
1150 bool EventMultiplexer::notifySlideAnimationsEnd()
1151 {
1152     return mpImpl->maSlideAnimationsEndHandlers.applyAll(
1153         boost::mem_fn(&EventHandler::handleEvent));
1154 }
1155 
1156 bool EventMultiplexer::notifyAudioStopped(
1157     const AnimationNodeSharedPtr& rNode )
1158 {
1159     return mpImpl->notifyAllAnimationHandlers(
1160         mpImpl->maAudioStoppedHandlers,
1161         rNode );
1162 }
1163 
1164 bool EventMultiplexer::notifyCommandStopAudio(
1165     const AnimationNodeSharedPtr& rNode )
1166 {
1167     return mpImpl->notifyAllAnimationHandlers(
1168         mpImpl->maCommandStopAudioHandlers,
1169         rNode );
1170 }
1171 
1172 bool EventMultiplexer::notifyPauseMode( bool bPauseShow )
1173 {
1174     return mpImpl->maPauseHandlers.applyAll(
1175         boost::bind( &PauseEventHandler::handlePause,
1176                      _1, bPauseShow ));
1177 }
1178 
1179 bool EventMultiplexer::notifyViewAdded( const UnoViewSharedPtr& rView )
1180 {
1181     ENSURE_OR_THROW( rView, "EventMultiplexer::notifyViewAdded(): Invalid view");
1182 
1183     // register event listener
1184     uno::Reference<presentation::XSlideShowView> const rUnoView(
1185         rView->getUnoView() );
1186 
1187     if( mpImpl->isMouseListenerRegistered() )
1188         rUnoView->addMouseListener(
1189             mpImpl->mxListener.get() );
1190 
1191     if( !mpImpl->maMouseMoveHandlers.isEmpty() )
1192         rUnoView->addMouseMotionListener(
1193             mpImpl->mxListener.get() );
1194 
1195     return mpImpl->maViewHandlers.applyAll(
1196         boost::bind( &ViewEventHandler::viewAdded,
1197                      _1,
1198                      boost::cref(rView) ));
1199 }
1200 
1201 bool EventMultiplexer::notifyViewRemoved( const UnoViewSharedPtr& rView )
1202 {
1203     ENSURE_OR_THROW( rView,
1204                       "EventMultiplexer::removeView(): Invalid view" );
1205 
1206     // revoke event listeners
1207     uno::Reference<presentation::XSlideShowView> const rUnoView(
1208         rView->getUnoView() );
1209 
1210     if( mpImpl->isMouseListenerRegistered() )
1211         rUnoView->removeMouseListener(
1212             mpImpl->mxListener.get() );
1213 
1214     if( !mpImpl->maMouseMoveHandlers.isEmpty() )
1215         rUnoView->removeMouseMotionListener(
1216             mpImpl->mxListener.get() );
1217 
1218     return mpImpl->maViewHandlers.applyAll(
1219         boost::bind( &ViewEventHandler::viewRemoved,
1220                      _1,
1221                      boost::cref(rView) ));
1222 }
1223 
1224 bool EventMultiplexer::notifyViewChanged( const UnoViewSharedPtr& rView )
1225 {
1226     return mpImpl->maViewHandlers.applyAll(
1227         boost::bind( &ViewEventHandler::viewChanged,
1228                      _1,
1229                      boost::cref(rView) ));
1230 }
1231 
1232 bool EventMultiplexer::notifyViewChanged( const uno::Reference<presentation::XSlideShowView>& xView )
1233 {
1234     UnoViewSharedPtr pView( mpImpl->findUnoView(xView) );
1235 
1236     if( !pView )
1237         return false; // view not registered here
1238 
1239     return notifyViewChanged( pView );
1240 }
1241 
1242 bool EventMultiplexer::notifyViewsChanged()
1243 {
1244     return mpImpl->maViewHandlers.applyAll(
1245         boost::mem_fn( &ViewEventHandler::viewsChanged ));
1246 }
1247 
1248 bool EventMultiplexer::notifyViewClobbered(
1249     const uno::Reference<presentation::XSlideShowView>& xView )
1250 {
1251     UnoViewSharedPtr pView( mpImpl->findUnoView(xView) );
1252 
1253     if( !pView )
1254         return false; // view not registered here
1255 
1256     return mpImpl->maViewRepaintHandlers.applyAll(
1257         boost::bind( &ViewRepaintHandler::viewClobbered,
1258                      _1,
1259                      boost::cref(pView) ));
1260 }
1261 
1262 bool EventMultiplexer::notifyHyperlinkClicked(
1263     rtl::OUString const& hyperLink )
1264 {
1265     return mpImpl->maHyperlinkHandlers.apply(
1266         boost::bind(&HyperlinkHandler::handleHyperlink,
1267                     _1,
1268                     boost::cref(hyperLink)) );
1269 }
1270 
1271 bool EventMultiplexer::notifySlideTransitionStarted()
1272 {
1273 	return true;
1274 }
1275 
1276 } // namespace internal
1277 } // namespace presentation
1278 
1279